Skip to content

Commit 59861ba

Browse files
joyeecheungtargos
authored andcommitted
bootstrap: include fs module into the builtin snapshot
PR-URL: #36943 Fixes: #35930 Refs: #35711 Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent e400f8c commit 59861ba

11 files changed

+165
-26
lines changed

lib/fs.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ const {
6767

6868
const pathModule = require('path');
6969
const { isArrayBufferView } = require('internal/util/types');
70+
71+
// We need to get the statValues from the binding at the callsite since
72+
// it's re-initialized after deserialization.
73+
7074
const binding = internalBinding('fs');
7175
const { Buffer } = require('buffer');
7276
const {
@@ -81,7 +85,7 @@ const {
8185
uvException
8286
} = require('internal/errors');
8387

84-
const { FSReqCallback, statValues } = binding;
88+
const { FSReqCallback } = binding;
8589
const { toPathIfFileURL } = require('internal/url');
8690
const internalUtil = require('internal/util');
8791
const {
@@ -1772,8 +1776,8 @@ function realpathSync(p, options) {
17721776

17731777
// Continue if not a symlink, break if a pipe/socket
17741778
if (knownHard[base] || cache?.get(base) === base) {
1775-
if (isFileType(statValues, S_IFIFO) ||
1776-
isFileType(statValues, S_IFSOCK)) {
1779+
if (isFileType(binding.statValues, S_IFIFO) ||
1780+
isFileType(binding.statValues, S_IFSOCK)) {
17771781
break;
17781782
}
17791783
continue;
@@ -1915,8 +1919,8 @@ function realpath(p, options, callback) {
19151919

19161920
// Continue if not a symlink, break if a pipe/socket
19171921
if (knownHard[base]) {
1918-
if (isFileType(statValues, S_IFIFO) ||
1919-
isFileType(statValues, S_IFSOCK)) {
1922+
if (isFileType(binding.statValues, S_IFIFO) ||
1923+
isFileType(binding.statValues, S_IFSOCK)) {
19201924
return callback(null, encodeRealpathResult(p, options));
19211925
}
19221926
return process.nextTick(LOOP);

lib/internal/bootstrap/node.js

+3
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ process.emitWarning = emitWarning;
277277
// Note: only after this point are the timers effective
278278
}
279279

280+
// Preload modules so that they are included in the builtin snapshot.
281+
require('fs');
282+
280283
function setupPrepareStackTrace() {
281284
const {
282285
setEnhanceStackForFatalException,

src/node_dir.cc

+9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "node_dir.h"
2+
#include "node_external_reference.h"
23
#include "node_file-inl.h"
34
#include "node_process.h"
45
#include "memory_tracker-inl.h"
@@ -364,8 +365,16 @@ void Initialize(Local<Object> target,
364365
env->set_dir_instance_template(dirt);
365366
}
366367

368+
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
369+
registry->Register(OpenDir);
370+
registry->Register(DirHandle::New);
371+
registry->Register(DirHandle::Read);
372+
registry->Register(DirHandle::Close);
373+
}
374+
367375
} // namespace fs_dir
368376

369377
} // end namespace node
370378

371379
NODE_MODULE_CONTEXT_AWARE_INTERNAL(fs_dir, node::fs_dir::Initialize)
380+
NODE_MODULE_EXTERNAL_REFERENCE(fs_dir, node::fs_dir::RegisterExternalReferences)

src/node_external_reference.h

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class ExternalReferenceRegistry {
5353
V(credentials) \
5454
V(env_var) \
5555
V(errors) \
56+
V(fs) \
57+
V(fs_dir) \
5658
V(handle_wrap) \
5759
V(messaging) \
5860
V(native_module) \

src/node_file.cc

+96-8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "aliased_buffer.h"
2424
#include "memory_tracker-inl.h"
2525
#include "node_buffer.h"
26+
#include "node_external_reference.h"
2627
#include "node_process.h"
2728
#include "node_stat_watcher.h"
2829
#include "util-inl.h"
@@ -2398,6 +2399,47 @@ void BindingData::MemoryInfo(MemoryTracker* tracker) const {
23982399
file_handle_read_wrap_freelist);
23992400
}
24002401

2402+
BindingData::BindingData(Environment* env, v8::Local<v8::Object> wrap)
2403+
: SnapshotableObject(env, wrap, type_int),
2404+
stats_field_array(env->isolate(), kFsStatsBufferLength),
2405+
stats_field_bigint_array(env->isolate(), kFsStatsBufferLength) {
2406+
wrap->Set(env->context(),
2407+
FIXED_ONE_BYTE_STRING(env->isolate(), "statValues"),
2408+
stats_field_array.GetJSArray())
2409+
.Check();
2410+
2411+
wrap->Set(env->context(),
2412+
FIXED_ONE_BYTE_STRING(env->isolate(), "bigintStatValues"),
2413+
stats_field_bigint_array.GetJSArray())
2414+
.Check();
2415+
}
2416+
2417+
void BindingData::Deserialize(Local<Context> context,
2418+
Local<Object> holder,
2419+
int index,
2420+
InternalFieldInfo* info) {
2421+
DCHECK_EQ(index, BaseObject::kSlot);
2422+
HandleScope scope(context->GetIsolate());
2423+
Environment* env = Environment::GetCurrent(context);
2424+
BindingData* binding = env->AddBindingData<BindingData>(context, holder);
2425+
CHECK_NOT_NULL(binding);
2426+
}
2427+
2428+
void BindingData::PrepareForSerialization(Local<Context> context,
2429+
v8::SnapshotCreator* creator) {
2430+
CHECK(file_handle_read_wrap_freelist.empty());
2431+
// We'll just re-initialize the buffers in the constructor since their
2432+
// contents can be thrown away once consumed in the previous call.
2433+
stats_field_array.Release();
2434+
stats_field_bigint_array.Release();
2435+
}
2436+
2437+
InternalFieldInfo* BindingData::Serialize(int index) {
2438+
DCHECK_EQ(index, BaseObject::kSlot);
2439+
InternalFieldInfo* info = InternalFieldInfo::New(type());
2440+
return info;
2441+
}
2442+
24012443
// TODO(addaleax): Remove once we're on C++17.
24022444
constexpr FastStringKey BindingData::type_name;
24032445

@@ -2461,14 +2503,6 @@ void Initialize(Local<Object> target,
24612503
static_cast<int32_t>(FsStatsOffset::kFsStatsFieldsNumber)))
24622504
.Check();
24632505

2464-
target->Set(context,
2465-
FIXED_ONE_BYTE_STRING(isolate, "statValues"),
2466-
binding_data->stats_field_array.GetJSArray()).Check();
2467-
2468-
target->Set(context,
2469-
FIXED_ONE_BYTE_STRING(isolate, "bigintStatValues"),
2470-
binding_data->stats_field_bigint_array.GetJSArray()).Check();
2471-
24722506
StatWatcher::Initialize(env, target);
24732507

24742508
// Create FunctionTemplate for FSReqCallback
@@ -2532,8 +2566,62 @@ void Initialize(Local<Object> target,
25322566
BindingData* FSReqBase::binding_data() {
25332567
return binding_data_.get();
25342568
}
2569+
2570+
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
2571+
registry->Register(Access);
2572+
StatWatcher::RegisterExternalReferences(registry);
2573+
2574+
registry->Register(Close);
2575+
registry->Register(Open);
2576+
registry->Register(OpenFileHandle);
2577+
registry->Register(Read);
2578+
registry->Register(ReadBuffers);
2579+
registry->Register(Fdatasync);
2580+
registry->Register(Fsync);
2581+
registry->Register(Rename);
2582+
registry->Register(FTruncate);
2583+
registry->Register(RMDir);
2584+
registry->Register(MKDir);
2585+
registry->Register(ReadDir);
2586+
registry->Register(InternalModuleReadJSON);
2587+
registry->Register(InternalModuleStat);
2588+
registry->Register(Stat);
2589+
registry->Register(LStat);
2590+
registry->Register(FStat);
2591+
registry->Register(Link);
2592+
registry->Register(Symlink);
2593+
registry->Register(ReadLink);
2594+
registry->Register(Unlink);
2595+
registry->Register(WriteBuffer);
2596+
registry->Register(WriteBuffers);
2597+
registry->Register(WriteString);
2598+
registry->Register(RealPath);
2599+
registry->Register(CopyFile);
2600+
2601+
registry->Register(Chmod);
2602+
registry->Register(FChmod);
2603+
// registry->Register(LChmod);
2604+
2605+
registry->Register(Chown);
2606+
registry->Register(FChown);
2607+
registry->Register(LChown);
2608+
2609+
registry->Register(UTimes);
2610+
registry->Register(FUTimes);
2611+
registry->Register(LUTimes);
2612+
2613+
registry->Register(Mkdtemp);
2614+
registry->Register(NewFSReqCallback);
2615+
2616+
registry->Register(FileHandle::New);
2617+
registry->Register(FileHandle::Close);
2618+
registry->Register(FileHandle::ReleaseFD);
2619+
StreamBase::RegisterExternalReferences(registry);
2620+
}
2621+
25352622
} // namespace fs
25362623

25372624
} // end namespace node
25382625

25392626
NODE_MODULE_CONTEXT_AWARE_INTERNAL(fs, node::fs::Initialize)
2627+
NODE_MODULE_EXTERNAL_REFERENCE(fs, node::fs::RegisterExternalReferences)

src/node_file.h

+7-8
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,30 @@
33

44
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
55

6-
#include "node.h"
76
#include "aliased_buffer.h"
87
#include "node_messaging.h"
8+
#include "node_snapshotable.h"
99
#include "stream_base.h"
10-
#include <iostream>
1110

1211
namespace node {
1312
namespace fs {
1413

1514
class FileHandleReadWrap;
1615

17-
class BindingData : public BaseObject {
16+
class BindingData : public SnapshotableObject {
1817
public:
19-
explicit BindingData(Environment* env, v8::Local<v8::Object> wrap)
20-
: BaseObject(env, wrap),
21-
stats_field_array(env->isolate(), kFsStatsBufferLength),
22-
stats_field_bigint_array(env->isolate(), kFsStatsBufferLength) {}
18+
explicit BindingData(Environment* env, v8::Local<v8::Object> wrap);
2319

2420
AliasedFloat64Array stats_field_array;
2521
AliasedBigUint64Array stats_field_bigint_array;
2622

2723
std::vector<BaseObjectPtr<FileHandleReadWrap>>
2824
file_handle_read_wrap_freelist;
2925

30-
static constexpr FastStringKey type_name { "fs" };
26+
SERIALIZABLE_OBJECT_METHODS()
27+
static constexpr FastStringKey type_name{"node::fs::BindingData"};
28+
static constexpr EmbedderObjectType type_int =
29+
EmbedderObjectType::k_fs_binding_data;
3130

3231
void MemoryInfo(MemoryTracker* tracker) const override;
3332
SET_SELF_SIZE(BindingData)

src/node_snapshotable.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ namespace node {
1212
class Environment;
1313
struct EnvSerializeInfo;
1414

15-
#define SERIALIZABLE_OBJECT_TYPES(V)
15+
#define SERIALIZABLE_OBJECT_TYPES(V) \
16+
V(fs_binding_data, fs::BindingData)
1617

1718
enum class EmbedderObjectType : uint8_t {
1819
k_default = 0,

src/node_stat_watcher.cc

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2020
// USE OR OTHER DEALINGS IN THE SOFTWARE.
2121

22-
#include "memory_tracker-inl.h"
2322
#include "node_stat_watcher.h"
2423
#include "async_wrap-inl.h"
2524
#include "env-inl.h"
25+
#include "memory_tracker-inl.h"
26+
#include "node_external_reference.h"
2627
#include "node_file-inl.h"
2728
#include "util-inl.h"
2829

@@ -55,6 +56,11 @@ void StatWatcher::Initialize(Environment* env, Local<Object> target) {
5556
env->SetConstructorFunction(target, "StatWatcher", t);
5657
}
5758

59+
void StatWatcher::RegisterExternalReferences(
60+
ExternalReferenceRegistry* registry) {
61+
registry->Register(StatWatcher::New);
62+
registry->Register(StatWatcher::Start);
63+
}
5864

5965
StatWatcher::StatWatcher(fs::BindingData* binding_data,
6066
Local<Object> wrap,

src/node_stat_watcher.h

+2
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ class BindingData;
3535
}
3636

3737
class Environment;
38+
class ExternalReferenceRegistry;
3839

3940
class StatWatcher : public HandleWrap {
4041
public:
4142
static void Initialize(Environment* env, v8::Local<v8::Object> target);
43+
static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
4244

4345
protected:
4446
StatWatcher(fs::BindingData* binding_data,

src/stream_base.cc

+26-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
#include "stream_wrap.h"
44
#include "allocated_buffer-inl.h"
55

6+
#include "env-inl.h"
7+
#include "js_stream.h"
68
#include "node.h"
79
#include "node_buffer.h"
810
#include "node_errors.h"
9-
#include "env-inl.h"
10-
#include "js_stream.h"
11+
#include "node_external_reference.h"
1112
#include "string_bytes.h"
1213
#include "util-inl.h"
1314
#include "v8.h"
@@ -423,6 +424,29 @@ void StreamBase::AddMethods(Environment* env, Local<FunctionTemplate> t) {
423424
&Value::IsFunction>);
424425
}
425426

427+
void StreamBase::RegisterExternalReferences(
428+
ExternalReferenceRegistry* registry) {
429+
registry->Register(GetFD);
430+
registry->Register(GetExternal);
431+
registry->Register(GetBytesRead);
432+
registry->Register(GetBytesWritten);
433+
registry->Register(JSMethod<&StreamBase::ReadStartJS>);
434+
registry->Register(JSMethod<&StreamBase::ReadStopJS>);
435+
registry->Register(JSMethod<&StreamBase::Shutdown>);
436+
registry->Register(JSMethod<&StreamBase::UseUserBuffer>);
437+
registry->Register(JSMethod<&StreamBase::Writev>);
438+
registry->Register(JSMethod<&StreamBase::WriteBuffer>);
439+
registry->Register(JSMethod<&StreamBase::WriteString<ASCII>>);
440+
registry->Register(JSMethod<&StreamBase::WriteString<UTF8>>);
441+
registry->Register(JSMethod<&StreamBase::WriteString<UCS2>>);
442+
registry->Register(JSMethod<&StreamBase::WriteString<LATIN1>>);
443+
registry->Register(
444+
BaseObject::InternalFieldGet<StreamBase::kOnReadFunctionField>);
445+
registry->Register(
446+
BaseObject::InternalFieldSet<StreamBase::kOnReadFunctionField,
447+
&Value::IsFunction>);
448+
}
449+
426450
void StreamBase::GetFD(const FunctionCallbackInfo<Value>& args) {
427451
// Mimic implementation of StreamBase::GetFD() and UDPWrap::GetFD().
428452
StreamBase* wrap = StreamBase::FromObject(args.This().As<Object>());

src/stream_base.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class ShutdownWrap;
1919
class WriteWrap;
2020
class StreamBase;
2121
class StreamResource;
22+
class ExternalReferenceRegistry;
2223

2324
struct StreamWriteResult {
2425
bool async;
@@ -308,7 +309,7 @@ class StreamBase : public StreamResource {
308309

309310
static void AddMethods(Environment* env,
310311
v8::Local<v8::FunctionTemplate> target);
311-
312+
static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
312313
virtual bool IsAlive() = 0;
313314
virtual bool IsClosing() = 0;
314315
virtual bool IsIPCPipe();

0 commit comments

Comments
 (0)