Skip to content

Commit e4c7b59

Browse files
codebytereMylesBorins
authored andcommitted
src: allow embedders to disable esm loader
PR-URL: #34060 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Gus Caplan <me@gus.host>
1 parent 9c12e53 commit e4c7b59

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');
@@ -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

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
@@ -805,6 +805,10 @@ inline bool Environment::is_main_thread() const {
805805
return worker_context() == nullptr;
806806
}
807807

808+
inline bool Environment::should_not_register_esm_loader() const {
809+
return flags_ & EnvironmentFlags::kNoRegisterESMLoader;
810+
}
811+
808812
inline bool Environment::owns_process_state() const {
809813
return flags_ & EnvironmentFlags::kOwnsProcessState;
810814
}

src/env.h

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

10141014
inline bool is_main_thread() const;
1015+
inline bool should_not_register_esm_loader() const;
10151016
inline bool owns_process_state() const;
10161017
inline bool owns_inspector() const;
10171018
inline uint64_t thread_id() const;

src/node.h

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

src/node_options.cc

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

980+
target
981+
->Set(context,
982+
FIXED_ONE_BYTE_STRING(env->isolate(), "shouldNotRegisterESMLoader"),
983+
Boolean::New(isolate, env->should_not_register_esm_loader()))
984+
.Check();
985+
980986
Local<Object> types = Object::New(isolate);
981987
NODE_DEFINE_CONSTANT(types, kNoOp);
982988
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)