Skip to content

Commit 40acad0

Browse files
committed
src: allow embedders to disable esm loader
1 parent fe6e468 commit 40acad0

File tree

7 files changed

+76
-4
lines changed

7 files changed

+76
-4
lines changed

lib/internal/bootstrap/pre_execution.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ const {
66
SafeWeakMap,
77
} = primordials;
88

9-
const { getOptionValue } = require('internal/options');
9+
const {
10+
getOptionValue,
11+
shouldNotRegisterESMLoader
12+
} = require('internal/options');
1013
const { Buffer } = require('buffer');
1114
const { ERR_MANIFEST_ASSERT_INTEGRITY } = require('internal/errors').codes;
1215
const assert = require('internal/assert');
@@ -56,7 +59,10 @@ function prepareMainThreadExecution(expandArgv1 = false) {
5659
initializeDeprecations();
5760
initializeWASI();
5861
initializeCJSLoader();
59-
initializeESMLoader();
62+
63+
if (!shouldNotRegisterESMLoader) {
64+
initializeESMLoader();
65+
}
6066

6167
const CJSLoader = require('internal/modules/cjs/loader');
6268
assert(!CJSLoader.hasLoadedAnyUserCJSModule);

lib/internal/options.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
const { getOptions } = internalBinding('options');
3+
const { getOptions, shouldNotRegisterESMLoader } = internalBinding('options');
44
const { options, aliases } = getOptions();
55

66
let warnOnAllowUnauthorized = true;
@@ -32,4 +32,5 @@ module.exports = {
3232
aliases,
3333
getOptionValue,
3434
getAllowUnauthorized,
35+
shouldNotRegisterESMLoader
3536
};

src/env-inl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,10 @@ inline bool Environment::is_main_thread() const {
771771
return worker_context() == nullptr;
772772
}
773773

774+
inline bool Environment::should_not_register_esm_loader() const {
775+
return flags_ & EnvironmentFlags::kNoRegisterESMLoader;
776+
}
777+
774778
inline bool Environment::owns_process_state() const {
775779
return flags_ & EnvironmentFlags::kOwnsProcessState;
776780
}

src/env.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,7 @@ class Environment : public MemoryRetainer {
10571057
inline void set_has_serialized_options(bool has_serialized_options);
10581058

10591059
inline bool is_main_thread() const;
1060+
inline bool should_not_register_esm_loader() const;
10601061
inline bool owns_process_state() const;
10611062
inline bool owns_inspector() const;
10621063
inline uint64_t thread_id() const;

src/node.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,11 @@ enum Flags : uint64_t {
408408
// Set if this Environment instance is associated with the global inspector
409409
// handling code (i.e. listening on SIGUSR1).
410410
// This is set when using kDefaultFlags.
411-
kOwnsInspector = 1 << 2
411+
kOwnsInspector = 1 << 2,
412+
// Set if Node.js should not run its own esm loader. This is needed by some
413+
// embedders, because it's possible for the Node.js esm loader to conflict
414+
// with another one in an embedder environment, e.g. Blink's in Chromium.
415+
kNoRegisterESMLoader = 1 << 3
412416
};
413417
} // namespace EnvironmentFlags
414418

src/node_options.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,12 @@ void Initialize(Local<Object> target,
979979
context, FIXED_ONE_BYTE_STRING(isolate, "envSettings"), env_settings)
980980
.Check();
981981

982+
target
983+
->Set(context,
984+
FIXED_ONE_BYTE_STRING(env->isolate(), "shouldNotRegisterESMLoader"),
985+
Boolean::New(isolate, env->should_not_register_esm_loader()))
986+
.Check();
987+
982988
Local<Object> types = Object::New(isolate);
983989
NODE_DEFINE_CONSTANT(types, kNoOp);
984990
NODE_DEFINE_CONSTANT(types, kV8Option);

test/cctest/test_environment.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,56 @@ class EnvironmentTest : public EnvironmentTestFixture {
3232
}
3333
};
3434

35+
TEST_F(EnvironmentTest, EnvironmentWithESMLoader) {
36+
const v8::HandleScope handle_scope(isolate_);
37+
Argv argv;
38+
Env env {handle_scope, argv};
39+
40+
node::Environment* envi = *env;
41+
envi->options()->experimental_vm_modules = true;
42+
43+
SetProcessExitHandler(*env, [&](node::Environment* env_, int exit_code) {
44+
EXPECT_EQ(*env, env_);
45+
EXPECT_EQ(exit_code, 0);
46+
node::Stop(*env);
47+
});
48+
49+
node::LoadEnvironment(
50+
*env,
51+
"const { SourceTextModule } = require('vm');"
52+
"try {"
53+
"new SourceTextModule('export const a = 1;');"
54+
"process.exit(0);"
55+
"} catch {"
56+
"process.exit(42);"
57+
"}");
58+
}
59+
60+
TEST_F(EnvironmentTest, EnvironmentWithNoESMLoader) {
61+
const v8::HandleScope handle_scope(isolate_);
62+
Argv argv;
63+
Env env {handle_scope, argv, node::EnvironmentFlags::kNoRegisterESMLoader};
64+
65+
node::Environment* envi = *env;
66+
envi->options()->experimental_vm_modules = true;
67+
68+
SetProcessExitHandler(*env, [&](node::Environment* env_, int exit_code) {
69+
EXPECT_EQ(*env, env_);
70+
EXPECT_EQ(exit_code, 42);
71+
node::Stop(*env);
72+
});
73+
74+
node::LoadEnvironment(
75+
*env,
76+
"const { SourceTextModule } = require('vm');"
77+
"try {"
78+
"new SourceTextModule('export const a = 1;');"
79+
"process.exit(0);"
80+
"} catch {"
81+
"process.exit(42);"
82+
"}");
83+
}
84+
3585
TEST_F(EnvironmentTest, PreExecutionPreparation) {
3686
const v8::HandleScope handle_scope(isolate_);
3787
const Argv argv;

0 commit comments

Comments
 (0)