@@ -24368,6 +24368,122 @@ TEST(ImportFromSyntheticModuleThrow) {
2436824368 CHECK(try_catch.HasCaught());
2436924369}
2437024370
24371+ namespace {
24372+
24373+ v8::MaybeLocal<Module> ModuleEvaluateTerminateExecutionResolveCallback(
24374+ Local<Context> context, Local<String> specifier,
24375+ Local<FixedArray> import_assertions, Local<Module> referrer) {
24376+ v8::Isolate* isolate = context->GetIsolate();
24377+
24378+ Local<String> url = v8_str("www.test.com");
24379+ Local<String> source_text = v8_str("await Promise.resolve();");
24380+ v8::ScriptOrigin origin(isolate, url, 0, 0, false, -1, Local<v8::Value>(),
24381+ false, false, true);
24382+ v8::ScriptCompiler::Source source(source_text, origin);
24383+ Local<Module> module =
24384+ v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
24385+ module
24386+ ->InstantiateModule(context,
24387+ ModuleEvaluateTerminateExecutionResolveCallback)
24388+ .ToChecked();
24389+
24390+ CHECK_EQ(module->GetStatus(), Module::kInstantiated);
24391+ return module;
24392+ }
24393+
24394+ void ModuleEvaluateTerminateExecution(
24395+ const v8::FunctionCallbackInfo<v8::Value>& args) {
24396+ v8::Isolate::GetCurrent()->TerminateExecution();
24397+ }
24398+ } // namespace
24399+
24400+ TEST(ModuleEvaluateTerminateExecution) {
24401+ LocalContext env;
24402+ v8::Isolate* isolate = env->GetIsolate();
24403+ v8::Isolate::Scope iscope(isolate);
24404+ v8::HandleScope scope(isolate);
24405+ v8::Local<v8::Context> context = v8::Context::New(isolate);
24406+ v8::Context::Scope cscope(context);
24407+
24408+ v8::Local<v8::Function> terminate_execution =
24409+ v8::Function::New(context, ModuleEvaluateTerminateExecution,
24410+ v8_str("terminate_execution"))
24411+ .ToLocalChecked();
24412+ context->Global()
24413+ ->Set(context, v8_str("terminate_execution"), terminate_execution)
24414+ .FromJust();
24415+
24416+ Local<String> url = v8_str("www.test.com");
24417+ Local<String> source_text = v8_str(
24418+ "terminate_execution();"
24419+ "await Promise.resolve();");
24420+ v8::ScriptOrigin origin(isolate, url, 0, 0, false, -1, Local<v8::Value>(),
24421+ false, false, true);
24422+ v8::ScriptCompiler::Source source(source_text, origin);
24423+ Local<Module> module =
24424+ v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
24425+ module
24426+ ->InstantiateModule(context,
24427+ ModuleEvaluateTerminateExecutionResolveCallback)
24428+ .ToChecked();
24429+
24430+ CHECK_EQ(module->GetStatus(), Module::kInstantiated);
24431+ TryCatch try_catch(isolate);
24432+ v8::MaybeLocal<Value> completion_value = module->Evaluate(context);
24433+ CHECK(completion_value.IsEmpty());
24434+
24435+ CHECK_EQ(module->GetStatus(), Module::kErrored);
24436+ CHECK(try_catch.HasCaught());
24437+ CHECK(try_catch.HasTerminated());
24438+ }
24439+
24440+ TEST(ModuleEvaluateImportTerminateExecution) {
24441+ LocalContext env;
24442+ v8::Isolate* isolate = env->GetIsolate();
24443+ v8::Isolate::Scope iscope(isolate);
24444+ v8::HandleScope scope(isolate);
24445+ v8::Local<v8::Context> context = v8::Context::New(isolate);
24446+ v8::Context::Scope cscope(context);
24447+
24448+ v8::Local<v8::Function> terminate_execution =
24449+ v8::Function::New(context, ModuleEvaluateTerminateExecution,
24450+ v8_str("terminate_execution"))
24451+ .ToLocalChecked();
24452+ context->Global()
24453+ ->Set(context, v8_str("terminate_execution"), terminate_execution)
24454+ .FromJust();
24455+
24456+ Local<String> url = v8_str("www.test.com");
24457+ Local<String> source_text = v8_str(
24458+ "import './synthetic.module';"
24459+ "terminate_execution();"
24460+ "await Promise.resolve();");
24461+ v8::ScriptOrigin origin(isolate, url, 0, 0, false, -1, Local<v8::Value>(),
24462+ false, false, true);
24463+ v8::ScriptCompiler::Source source(source_text, origin);
24464+ Local<Module> module =
24465+ v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
24466+ module
24467+ ->InstantiateModule(context,
24468+ ModuleEvaluateTerminateExecutionResolveCallback)
24469+ .ToChecked();
24470+
24471+ CHECK_EQ(module->GetStatus(), Module::kInstantiated);
24472+ TryCatch try_catch(isolate);
24473+ v8::MaybeLocal<Value> completion_value = module->Evaluate(context);
24474+ Local<v8::Promise> promise(
24475+ Local<v8::Promise>::Cast(completion_value.ToLocalChecked()));
24476+ CHECK_EQ(promise->State(), v8::Promise::kPending);
24477+ isolate->PerformMicrotaskCheckpoint();
24478+
24479+ // The exception thrown by terminate execution is not catchable by JavaScript
24480+ // so the promise can not be settled.
24481+ CHECK_EQ(promise->State(), v8::Promise::kPending);
24482+ CHECK_EQ(module->GetStatus(), Module::kEvaluated);
24483+ CHECK(try_catch.HasCaught());
24484+ CHECK(try_catch.HasTerminated());
24485+ }
24486+
2437124487// Tests that the code cache does not confuse the same source code compiled as a
2437224488// script and as a module.
2437324489TEST(CodeCacheModuleScriptMismatch) {
0 commit comments