| 514 | } |
| 515 | |
| 516 | Local<Value> ModuleInternal::LoadESModule(Isolate* isolate, const std::string& path) { |
| 517 | auto context = isolate->GetCurrentContext(); |
| 518 | |
| 519 | // 1) Prepare URL & source |
| 520 | string url = "file://" + path; |
| 521 | string content = Runtime::GetRuntime(isolate)->ReadFileText(path); |
| 522 | |
| 523 | Local<String> sourceText = ArgConverter::ConvertToV8String(isolate, content); |
| 524 | ScriptCompiler::CachedData* cacheData = nullptr; // TODO: Implement cache support for ES modules |
| 525 | |
| 526 | Local<String> urlString; |
| 527 | if (!String::NewFromUtf8(isolate, url.c_str(), NewStringType::kNormal).ToLocal(&urlString)) { |
| 528 | throw NativeScriptException(string("Failed to create URL string for ES module ") + path); |
| 529 | } |
| 530 | |
| 531 | ScriptOrigin origin(isolate, urlString, 0, 0, false, -1, Local<Value>(), false, false, |
| 532 | true // ← is_module |
| 533 | ); |
| 534 | ScriptCompiler::Source source(sourceText, origin, cacheData); |
| 535 | |
| 536 | // 2) Compile with its own TryCatch |
| 537 | Local<Module> module; |
| 538 | { |
| 539 | TryCatch tcCompile(isolate); |
| 540 | MaybeLocal<Module> maybeMod = ScriptCompiler::CompileModule( |
| 541 | isolate, &source, |
| 542 | cacheData ? ScriptCompiler::kConsumeCodeCache : ScriptCompiler::kNoCompileOptions); |
| 543 | |
| 544 | if (!maybeMod.ToLocal(&module)) { |
| 545 | if (tcCompile.HasCaught()) { |
| 546 | throw NativeScriptException(tcCompile, "Cannot compile ES module " + path); |
| 547 | } else { |
| 548 | throw NativeScriptException(string("Cannot compile ES module ") + path); |
| 549 | } |
| 550 | } |
| 551 | } |
| 552 | |
| 553 | // 3) Register for resolution callback |
| 554 | // Safe Global handle management: Clear any existing entry first |
| 555 | auto it = g_moduleRegistry.find(path); |
| 556 | if (it != g_moduleRegistry.end()) { |
| 557 | // Clear the existing Global handle before replacing it |
| 558 | it->second.Reset(); |
| 559 | } |
| 560 | |
| 561 | // Now safely set the new module handle |
| 562 | g_moduleRegistry[path].Reset(isolate, module); |
| 563 | |
| 564 | // 4) Instantiate (link) with ResolveModuleCallback |
| 565 | { |
| 566 | TryCatch tcLink(isolate); |
| 567 | bool linked = module->InstantiateModule(context, &ResolveModuleCallback).FromMaybe(false); |
| 568 | |
| 569 | if (!linked) { |
| 570 | if (tcLink.HasCaught()) { |
| 571 | throw NativeScriptException(tcLink, "Cannot instantiate module " + path); |
| 572 | } else { |
| 573 | throw NativeScriptException(string("Cannot instantiate module ") + path); |
nothing calls this directly
no test coverage detected