@@ -1441,35 +1441,18 @@ void ContextifyContext::ContainsModuleSyntax(
14411441 env, " containsModuleSyntax needs at least 1 argument" );
14421442 }
14431443
1444+ // Argument 1: source code
1445+ Local<String> code;
1446+ CHECK (args[0 ]->IsString ());
1447+ code = args[0 ].As <String>();
1448+
14441449 // Argument 2: filename; if undefined, use empty string
14451450 Local<String> filename = String::Empty (isolate);
14461451 if (!args[1 ]->IsUndefined ()) {
14471452 CHECK (args[1 ]->IsString ());
14481453 filename = args[1 ].As <String>();
14491454 }
14501455
1451- // Argument 1: source code; if undefined, read from filename in argument 2
1452- Local<String> code;
1453- if (args[0 ]->IsUndefined ()) {
1454- CHECK (!filename.IsEmpty ());
1455- const char * filename_str = Utf8Value (isolate, filename).out ();
1456- std::string contents;
1457- int result = ReadFileSync (&contents, filename_str);
1458- if (result != 0 ) {
1459- isolate->ThrowException (
1460- ERR_MODULE_NOT_FOUND (isolate, " Cannot read file %s" , filename_str));
1461- return ;
1462- }
1463- code = String::NewFromUtf8 (isolate,
1464- contents.c_str (),
1465- v8::NewStringType::kNormal ,
1466- contents.length ())
1467- .ToLocalChecked ();
1468- } else {
1469- CHECK (args[0 ]->IsString ());
1470- code = args[0 ].As <String>();
1471- }
1472-
14731456 // TODO(geoffreybooth): Centralize this rather than matching the logic in
14741457 // cjs/loader.js and translators.js
14751458 Local<String> script_id = String::Concat (
@@ -1499,91 +1482,32 @@ void ContextifyContext::ContainsModuleSyntax(
14991482
15001483 bool should_retry_as_esm = false ;
15011484 if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
1502- Utf8Value message_value (env->isolate (), try_catch.Message ()->Get ());
1503- auto message = message_value.ToStringView ();
1504-
1505- for (const auto & error_message : esm_syntax_error_messages) {
1506- if (message.find (error_message) != std::string_view::npos) {
1507- should_retry_as_esm = true ;
1508- break ;
1509- }
1510- }
1511-
1512- if (!should_retry_as_esm) {
1513- for (const auto & error_message : throws_only_in_cjs_error_messages) {
1514- if (message.find (error_message) != std::string_view::npos) {
1515- // Try parsing again where the CommonJS wrapper is replaced by an
1516- // async function wrapper. If the new parse succeeds, then the error
1517- // was caused by either a top-level declaration of one of the CommonJS
1518- // module variables, or a top-level `await`.
1519- TryCatchScope second_parse_try_catch (env);
1520- code =
1521- String::Concat (isolate,
1522- String::NewFromUtf8 (isolate, " (async function() {" )
1523- .ToLocalChecked (),
1524- code);
1525- code = String::Concat (
1526- isolate,
1527- code,
1528- String::NewFromUtf8 (isolate, " })();" ).ToLocalChecked ());
1529- ScriptCompiler::Source wrapped_source = GetCommonJSSourceInstance (
1530- isolate, code, filename, 0 , 0 , host_defined_options, nullptr );
1531- std::ignore = ScriptCompiler::CompileFunction (
1532- context,
1533- &wrapped_source,
1534- params.size (),
1535- params.data (),
1536- 0 ,
1537- nullptr ,
1538- options,
1539- v8::ScriptCompiler::NoCacheReason::kNoCacheNoReason );
1540- if (!second_parse_try_catch.HasTerminated ()) {
1541- if (second_parse_try_catch.HasCaught ()) {
1542- // If on the second parse an error is thrown by ESM syntax, then
1543- // what happened was that the user had top-level `await` or a
1544- // top-level declaration of one of the CommonJS module variables
1545- // above the first `import` or `export`.
1546- Utf8Value second_message_value (
1547- env->isolate (), second_parse_try_catch.Message ()->Get ());
1548- auto second_message = second_message_value.ToStringView ();
1549- for (const auto & error_message : esm_syntax_error_messages) {
1550- if (second_message.find (error_message) !=
1551- std::string_view::npos) {
1552- should_retry_as_esm = true ;
1553- break ;
1554- }
1555- }
1556- } else {
1557- // No errors thrown in the second parse, so most likely the error
1558- // was caused by a top-level `await` or a top-level declaration of
1559- // one of the CommonJS module variables.
1560- should_retry_as_esm = true ;
1561- }
1562- }
1563- break ;
1564- }
1565- }
1566- }
1485+ should_retry_as_esm = ContextifyContext::ShouldRetryAsESMInternal (env, code);
15671486 }
15681487 args.GetReturnValue ().Set (should_retry_as_esm);
15691488}
15701489
15711490void ContextifyContext::ShouldRetryAsESM (
15721491 const FunctionCallbackInfo<Value>& args) {
15731492 Environment* env = Environment::GetCurrent (args);
1574- Isolate* isolate = env->isolate ();
1575- Local<Context> context = env->context ();
15761493
1577- if (args.Length () != 1 ) {
1578- return THROW_ERR_MISSING_ARGS (env, " shouldRetryAsESM needs 1 argument" );
1579- }
1494+ CHECK_EQ (args.Length (), 1 );
1495+
15801496 // Argument 1: source code
15811497 Local<String> code;
15821498 CHECK (args[0 ]->IsString ());
15831499 code = args[0 ].As <String>();
15841500
1585- Local<String> script_id =
1586- String::NewFromUtf8 (isolate, " throwaway" ).ToLocalChecked ();
1501+ bool should_retry_as_esm = ContextifyContext::ShouldRetryAsESMInternal (env, code);
1502+
1503+ args.GetReturnValue ().Set (should_retry_as_esm);
1504+ }
1505+
1506+ bool ContextifyContext::ShouldRetryAsESMInternal (
1507+ Environment* env, Local<String> code) {
1508+ Isolate* isolate = env->isolate ();
1509+
1510+ Local<String> script_id = FIXED_ONE_BYTE_STRING (isolate, " throwaway" );
15871511 Local<Symbol> id_symbol = Symbol::New (isolate, script_id);
15881512
15891513 Local<PrimitiveArray> host_defined_options =
@@ -1609,6 +1533,7 @@ void ContextifyContext::ShouldRetryAsESM(
16091533 ScriptCompiler::Source wrapped_source = GetCommonJSSourceInstance (
16101534 isolate, code, script_id, 0 , 0 , host_defined_options, nullptr );
16111535
1536+ Local<Context> context = env->context ();
16121537 std::vector<Local<String>> params = GetCJSParameters (env->isolate_data ());
16131538 std::ignore = ScriptCompiler::CompileFunction (
16141539 context,
@@ -1620,7 +1545,6 @@ void ContextifyContext::ShouldRetryAsESM(
16201545 options,
16211546 v8::ScriptCompiler::NoCacheReason::kNoCacheNoReason );
16221547
1623- bool should_retry_as_esm = false ;
16241548 if (!try_catch.HasTerminated ()) {
16251549 if (try_catch.HasCaught ()) {
16261550 // If on the second parse an error is thrown by ESM syntax, then
@@ -1631,18 +1555,17 @@ void ContextifyContext::ShouldRetryAsESM(
16311555 auto message_view = message_value.ToStringView ();
16321556 for (const auto & error_message : esm_syntax_error_messages) {
16331557 if (message_view.find (error_message) != std::string_view::npos) {
1634- should_retry_as_esm = true ;
1635- break ;
1558+ return true ;
16361559 }
16371560 }
16381561 } else {
16391562 // No errors thrown in the second parse, so most likely the error
16401563 // was caused by a top-level `await` or a top-level declaration of
16411564 // one of the CommonJS module variables.
1642- should_retry_as_esm = true ;
1565+ return true ;
16431566 }
16441567 }
1645- args. GetReturnValue (). Set (should_retry_as_esm) ;
1568+ return false ;
16461569}
16471570
16481571static void CompileFunctionForCJSLoader (
0 commit comments