Skip to content

Commit e2a090b

Browse files
devsnektargos
authored andcommitted
build: enable loading internal modules from disk
PR-URL: #31321 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 5ec9295 commit e2a090b

File tree

5 files changed

+85
-9
lines changed

5 files changed

+85
-9
lines changed

configure.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,12 @@
630630
default=False,
631631
help='compile V8 with minimal optimizations and with runtime checks')
632632

633+
parser.add_option('--node-builtin-modules-path',
634+
action='store',
635+
dest='node_builtin_modules_path',
636+
default=False,
637+
help='node will load builtin modules from disk instead of from binary')
638+
633639
# Create compile_commands.json in out/Debug and out/Release.
634640
parser.add_option('-C',
635641
action='store_true',
@@ -1023,18 +1029,18 @@ def configure_node(o):
10231029
o['variables']['want_separate_host_toolset'] = int(
10241030
cross_compiling and want_snapshots)
10251031

1026-
if not options.without_node_snapshot:
1032+
if options.without_node_snapshot or options.node_builtin_modules_path:
1033+
o['variables']['node_use_node_snapshot'] = 'false'
1034+
else:
10271035
o['variables']['node_use_node_snapshot'] = b(
10281036
not cross_compiling and want_snapshots and not options.shared)
1029-
else:
1030-
o['variables']['node_use_node_snapshot'] = 'false'
10311037

1032-
if not options.without_node_code_cache:
1038+
if options.without_node_code_cache or options.node_builtin_modules_path:
1039+
o['variables']['node_use_node_code_cache'] = 'false'
1040+
else:
10331041
# TODO(refack): fix this when implementing embedded code-cache when cross-compiling.
10341042
o['variables']['node_use_node_code_cache'] = b(
10351043
not cross_compiling and not options.shared)
1036-
else:
1037-
o['variables']['node_use_node_code_cache'] = 'false'
10381044

10391045
if target_arch == 'arm':
10401046
configure_arm(o)
@@ -1191,6 +1197,10 @@ def configure_node(o):
11911197
else:
11921198
o['variables']['node_target_type'] = 'executable'
11931199

1200+
if options.node_builtin_modules_path:
1201+
print('Warning! Loading builtin modules from disk is for development')
1202+
o['variables']['node_builtin_modules_path'] = options.node_builtin_modules_path
1203+
11941204
def configure_napi(output):
11951205
version = getnapibuildversion.get_napi_version()
11961206
output['variables']['napi_build_version'] = version

node.gyp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
'node_core_target_name%': 'node',
2525
'node_lib_target_name%': 'libnode',
2626
'node_intermediate_lib_type%': 'static_library',
27+
'node_builtin_modules_path%': '',
2728
'library_files': [
2829
'lib/internal/bootstrap/environment.js',
2930
'lib/internal/bootstrap/loaders.js',
@@ -716,6 +717,9 @@
716717
'msvs_disabled_warnings!': [4244],
717718

718719
'conditions': [
720+
[ 'node_builtin_modules_path!=""', {
721+
'defines': [ 'NODE_BUILTIN_MODULES_PATH="<(node_builtin_modules_path)"' ]
722+
}],
719723
[ 'node_shared=="true"', {
720724
'sources': [
721725
'src/node_snapshot_stub.cc',

src/node.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "env-inl.h"
2828
#include "memory_tracker-inl.h"
2929
#include "node_binding.h"
30+
#include "node_errors.h"
3031
#include "node_internals.h"
3132
#include "node_main_instance.h"
3233
#include "node_metadata.h"

src/node_native_module.cc

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,64 @@ MaybeLocal<Function> NativeModuleLoader::CompileAsModule(
174174
return LookupAndCompile(context, id, &parameters, result);
175175
}
176176

177+
#ifdef NODE_BUILTIN_MODULES_PATH
178+
static std::string OnDiskFileName(const char* id) {
179+
std::string filename = NODE_BUILTIN_MODULES_PATH;
180+
filename += "/";
181+
182+
if (strncmp(id, "internal/deps", strlen("internal/deps")) == 0) {
183+
id += strlen("internal/");
184+
} else {
185+
filename += "lib/";
186+
}
187+
filename += id;
188+
filename += ".js";
189+
190+
return filename;
191+
}
192+
#endif // NODE_BUILTIN_MODULES_PATH
193+
194+
MaybeLocal<String> NativeModuleLoader::LoadBuiltinModuleSource(Isolate* isolate,
195+
const char* id) {
196+
#ifdef NODE_BUILTIN_MODULES_PATH
197+
std::string filename = OnDiskFileName(id);
198+
199+
uv_fs_t req;
200+
uv_file file =
201+
uv_fs_open(nullptr, &req, filename.c_str(), O_RDONLY, 0, nullptr);
202+
CHECK_GE(req.result, 0);
203+
uv_fs_req_cleanup(&req);
204+
205+
std::shared_ptr<void> defer_close(nullptr, [file](...) {
206+
uv_fs_t close_req;
207+
CHECK_EQ(0, uv_fs_close(nullptr, &close_req, file, nullptr));
208+
uv_fs_req_cleanup(&close_req);
209+
});
210+
211+
std::string contents;
212+
char buffer[4096];
213+
uv_buf_t buf = uv_buf_init(buffer, sizeof(buffer));
214+
215+
while (true) {
216+
const int r =
217+
uv_fs_read(nullptr, &req, file, &buf, 1, contents.length(), nullptr);
218+
CHECK_GE(req.result, 0);
219+
uv_fs_req_cleanup(&req);
220+
if (r <= 0) {
221+
break;
222+
}
223+
contents.append(buf.base, r);
224+
}
225+
226+
return String::NewFromUtf8(
227+
isolate, contents.c_str(), v8::NewStringType::kNormal, contents.length());
228+
#else
229+
const auto source_it = source_.find(id);
230+
CHECK_NE(source_it, source_.end());
231+
return source_it->second.ToStringChecked(isolate);
232+
#endif // NODE_BUILTIN_MODULES_PATH
233+
}
234+
177235
// Returns Local<Function> of the compiled module if return_code_cache
178236
// is false (we are only compiling the function).
179237
// Otherwise return a Local<Object> containing the cache.
@@ -185,9 +243,10 @@ MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
185243
Isolate* isolate = context->GetIsolate();
186244
EscapableHandleScope scope(isolate);
187245

188-
const auto source_it = source_.find(id);
189-
CHECK_NE(source_it, source_.end());
190-
Local<String> source = source_it->second.ToStringChecked(isolate);
246+
Local<String> source;
247+
if (!LoadBuiltinModuleSource(isolate, id).ToLocal(&source)) {
248+
return {};
249+
}
191250

192251
std::string filename_s = id + std::string(".js");
193252
Local<String> filename =

src/node_native_module.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ class NativeModuleLoader {
6666
NativeModuleCacheMap* code_cache();
6767
v8::ScriptCompiler::CachedData* GetCodeCache(const char* id) const;
6868
enum class Result { kWithCache, kWithoutCache };
69+
v8::MaybeLocal<v8::String> LoadBuiltinModuleSource(v8::Isolate* isolate,
70+
const char* id);
6971
// If an exception is encountered (e.g. source code contains
7072
// syntax error), the returned value is empty.
7173
v8::MaybeLocal<v8::Function> LookupAndCompile(

0 commit comments

Comments
 (0)