Skip to content

Commit 5e28660

Browse files
codebytereaddaleax
authored andcommitted
src: allow embedders to disable esm loader
PR-URL: #34060 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: David Carlier <[email protected]> Reviewed-By: Gus Caplan <[email protected]>
1 parent 4cd7f5f commit 5e28660

File tree

7 files changed

+76
-4
lines changed

7 files changed

+76
-4
lines changed

lib/internal/bootstrap/pre_execution.js

+8-2
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');
@@ -64,7 +67,10 @@ function prepareMainThreadExecution(expandArgv1 = false) {
6467
initializeDeprecations();
6568
initializeWASI();
6669
initializeCJSLoader();
67-
initializeESMLoader();
70+
71+
if (!shouldNotRegisterESMLoader) {
72+
initializeESMLoader();
73+
}
6874

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

lib/internal/options.js

+2-1
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

+4
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,10 @@ inline bool Environment::is_main_thread() const {
859859
return worker_context() == nullptr;
860860
}
861861

862+
inline bool Environment::should_not_register_esm_loader() const {
863+
return flags_ & EnvironmentFlags::kNoRegisterESMLoader;
864+
}
865+
862866
inline bool Environment::owns_process_state() const {
863867
return flags_ & EnvironmentFlags::kOwnsProcessState;
864868
}

src/env.h

+1
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,7 @@ class Environment : public MemoryRetainer {
10631063
inline void set_has_serialized_options(bool has_serialized_options);
10641064

10651065
inline bool is_main_thread() const;
1066+
inline bool should_not_register_esm_loader() const;
10661067
inline bool owns_process_state() const;
10671068
inline bool owns_inspector() const;
10681069
inline uint64_t thread_id() const;

src/node.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,11 @@ enum Flags : uint64_t {
396396
// Set if this Environment instance is associated with the global inspector
397397
// handling code (i.e. listening on SIGUSR1).
398398
// This is set when using kDefaultFlags.
399-
kOwnsInspector = 1 << 2
399+
kOwnsInspector = 1 << 2,
400+
// Set if Node.js should not run its own esm loader. This is needed by some
401+
// embedders, because it's possible for the Node.js esm loader to conflict
402+
// with another one in an embedder environment, e.g. Blink's in Chromium.
403+
kNoRegisterESMLoader = 1 << 3
400404
};
401405
} // namespace EnvironmentFlags
402406

src/node_options.cc

+6
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,12 @@ void Initialize(Local<Object> target,
994994
context, FIXED_ONE_BYTE_STRING(isolate, "envSettings"), env_settings)
995995
.Check();
996996

997+
target
998+
->Set(context,
999+
FIXED_ONE_BYTE_STRING(env->isolate(), "shouldNotRegisterESMLoader"),
1000+
Boolean::New(isolate, env->should_not_register_esm_loader()))
1001+
.Check();
1002+
9971003
Local<Object> types = Object::New(isolate);
9981004
NODE_DEFINE_CONSTANT(types, kNoOp);
9991005
NODE_DEFINE_CONSTANT(types, kV8Option);

test/cctest/test_environment.cc

+50
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)