diff --git a/lib/internal/process/execution.js b/lib/internal/process/execution.js index 4f72aa41251836..09b18b8f2c37db 100644 --- a/lib/internal/process/execution.js +++ b/lib/internal/process/execution.js @@ -83,7 +83,7 @@ function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) { if (getOptionValue('--experimental-detect-module') && getOptionValue('--input-type') === '' && getOptionValue('--experimental-default-type') === '' && - containsModuleSyntax(body, name)) { + containsModuleSyntax(body, name, null, 'no CJS variables')) { return evalModuleEntryPoint(body, print); } diff --git a/src/node_contextify.cc b/src/node_contextify.cc index f65edc9893b075..65e45309221a06 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -1451,7 +1451,8 @@ static MaybeLocal CompileFunctionForCJSLoader(Environment* env, Local context, Local code, Local filename, - bool* cache_rejected) { + bool* cache_rejected, + bool is_cjs_scope) { Isolate* isolate = context->GetIsolate(); EscapableHandleScope scope(isolate); @@ -1504,7 +1505,10 @@ static MaybeLocal CompileFunctionForCJSLoader(Environment* env, options = ScriptCompiler::kConsumeCodeCache; } - std::vector> params = GetCJSParameters(env->isolate_data()); + std::vector> params; + if (is_cjs_scope) { + params = GetCJSParameters(env->isolate_data()); + } MaybeLocal maybe_fn = ScriptCompiler::CompileFunction( context, &source, @@ -1566,7 +1570,7 @@ static void CompileFunctionForCJSLoader( ShouldNotAbortOnUncaughtScope no_abort_scope(realm->env()); TryCatchScope try_catch(env); if (!CompileFunctionForCJSLoader( - env, context, code, filename, &cache_rejected) + env, context, code, filename, &cache_rejected, true) .ToLocal(&fn)) { CHECK(try_catch.HasCaught()); CHECK(!try_catch.HasTerminated()); @@ -1704,11 +1708,15 @@ static void ContainsModuleSyntax(const FunctionCallbackInfo& args) { CHECK(args[1]->IsString()); Local filename = args[1].As(); - // Argument 2: resource name (URL for ES module). + // Argument 3: resource name (URL for ES module). Local resource_name = filename; if (args[2]->IsString()) { resource_name = args[2].As(); } + // Argument 4: flag to indicate if CJS variables should not be in scope + // (they should be for normal CommonJS modules, but not for the + // CommonJS eval scope). + bool cjs_var = !args[3]->IsString(); bool cache_rejected = false; Local message; @@ -1717,7 +1725,7 @@ static void ContainsModuleSyntax(const FunctionCallbackInfo& args) { TryCatchScope try_catch(env); ShouldNotAbortOnUncaughtScope no_abort_scope(env); if (CompileFunctionForCJSLoader( - env, context, code, filename, &cache_rejected) + env, context, code, filename, &cache_rejected, cjs_var) .ToLocal(&fn)) { args.GetReturnValue().Set(false); return; diff --git a/test/es-module/test-esm-detect-ambiguous.mjs b/test/es-module/test-esm-detect-ambiguous.mjs index c027f46328acee..8c70542b2ead72 100644 --- a/test/es-module/test-esm-detect-ambiguous.mjs +++ b/test/es-module/test-esm-detect-ambiguous.mjs @@ -44,6 +44,19 @@ describe('--experimental-detect-module', { concurrency: true }, () => { strictEqual(signal, null); }); + it('should not switch to module if code is parsable as script', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-detect-module', + '--eval', + 'let __filename,__dirname,require,module,exports;this.a', + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, ''); + strictEqual(code, 0); + strictEqual(signal, null); + }); + it('should be overridden by --experimental-default-type', async () => { const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ '--experimental-detect-module', @@ -393,3 +406,18 @@ describe('Wrapping a `require` of an ES module while using `--abort-on-uncaught- strictEqual(signal, null); }); }); + +describe('when working with Worker threads', () => { + it('should support sloppy scripts that declare CJS "global-like" variables', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-detect-module', + '--eval', + 'new worker_threads.Worker("let __filename,__dirname,require,module,exports;this.a",{eval:true})', + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, ''); + strictEqual(code, 0); + strictEqual(signal, null); + }); +});