Skip to content
Merged
Prev Previous commit
Next Next commit
register HasTopLevelAwait method in cpp api
  • Loading branch information
mertcanaltin committed Jun 3, 2025
commit 32247d10c9be251a17bdeddeb658e10f7cf361d1
23 changes: 23 additions & 0 deletions src/module_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,27 @@ void ModuleWrap::IsGraphAsync(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(module->IsGraphAsync());
}

void ModuleWrap::HasTopLevelAwait(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
ModuleWrap* obj;
ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());

Local<Module> module = obj->module_.Get(isolate);

// Check if module is valid
if (module.IsEmpty()) {
args.GetReturnValue().Set(false);
return;
}

// For source text modules, check if the graph is async
// For synthetic modules, it's always false
bool has_top_level_await = module->IsSourceTextModule() &&
module->IsGraphAsync();

args.GetReturnValue().Set(has_top_level_await);
}

void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
ModuleWrap* obj;
Expand Down Expand Up @@ -1305,6 +1326,7 @@ void ModuleWrap::CreatePerIsolateProperties(IsolateData* isolate_data,
SetProtoMethodNoSideEffect(isolate, tpl, "getNamespace", GetNamespace);
SetProtoMethodNoSideEffect(isolate, tpl, "getStatus", GetStatus);
SetProtoMethodNoSideEffect(isolate, tpl, "isGraphAsync", IsGraphAsync);
SetProtoMethodNoSideEffect(isolate, tpl, "hasTopLevelAwait", HasTopLevelAwait);
SetProtoMethodNoSideEffect(isolate, tpl, "getError", GetError);
SetConstructorFunction(isolate, target, "ModuleWrap", tpl);
isolate_data->set_module_wrap_constructor_template(tpl);
Expand Down Expand Up @@ -1367,6 +1389,7 @@ void ModuleWrap::RegisterExternalReferences(
registry->Register(GetStatus);
registry->Register(GetError);
registry->Register(IsGraphAsync);
registry->Register(HasTopLevelAwait);

registry->Register(CreateRequiredModuleFacade);

Expand Down
1 change: 1 addition & 0 deletions src/module_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class ModuleWrap : public BaseObject {
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackField("resolve_cache", resolve_cache_);
}
static void HasTopLevelAwait(const v8::FunctionCallbackInfo<v8::Value>& args);

v8::Local<v8::Context> context() const;
v8::Maybe<bool> CheckUnsettledTopLevelAwait();
Expand Down
17 changes: 9 additions & 8 deletions test/es-module/test-esm-detect-ambiguous.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,10 @@ describe('Module syntax detection', { concurrency: !process.env.TEST_PARALLEL },
'const fs = require("node:fs"); await Promise.resolve();',
]);

match(stderr, /ReferenceError: require is not defined in ES module scope/);
match(
stderr,
/ERR_AMBIGUOUS_MODULE_SYNTAX: This file cannot be parsed as either CommonJS or ES Module\. CommonJS error: await is only valid in async functions\. ES Module error: require is not defined in ES module scope\. If you meant to use CommonJS, wrap top-level await in async function\. If you meant to use ESM, do not use require\(\)\./
);
Comment thread
mertcanaltin marked this conversation as resolved.
strictEqual(stdout, '');
strictEqual(code, 1);
strictEqual(signal, null);
Expand Down Expand Up @@ -431,16 +434,14 @@ describe('cjs & esm ambiguous syntax case', () => {
[
'--input-type=module',
'--eval',
`await 1; const fs = require('fs');`,
`await 1;\nconst fs = require('fs');`,
]
);

match(stderr, /ERR_AMBIGUOUS_MODULE_SYNTAX/);
match(stderr, /This file cannot be parsed as either CommonJS or ES Module/);
match(stderr, /await is only valid in async functions/);
match(stderr, /require is not defined in ES module scope/);
match(stderr, /If you meant to use CommonJS/);
match(stderr, /If you meant to use ESM/);
match(
stderr,
/ERR_AMBIGUOUS_MODULE_SYNTAX: This file cannot be parsed as either CommonJS or ES Module\. CommonJS error: await is only valid in async functions\. ES Module error: require is not defined in ES module scope\. If you meant to use CommonJS, wrap top-level await in async function\. If you meant to use ESM, do not use require\(\)\./
);

strictEqual(code, 1);
strictEqual(signal, null);
Expand Down