Skip to content

Commit d202890

Browse files
Align import * as ns; export { ns } with export * as ns
https://bugs.webkit.org/show_bug.cgi?id=303141 Reviewed by NOBODY (OOPS!). This patch changes JSC's handling of `import * as ns; export { ns }` to align with tc39/ecma262#3715, which reached consensus in the Nov 2025 TC39 meeting. This will be tested by tc39/test262#4606, for now I manually verified that the relevant tests in that PR are failing before this patch and passing after it. * Source/JavaScriptCore/parser/ModuleAnalyzer.cpp: (JSC::ModuleAnalyzer::exportVariable):
1 parent 293a1a5 commit d202890

File tree

2 files changed

+5
-9
lines changed

2 files changed

+5
-9
lines changed

JSTests/test262/expectations.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -713,10 +713,6 @@ test/language/identifiers/start-unicode-17.0.0-escaped.js:
713713
test/language/identifiers/start-unicode-17.0.0.js:
714714
default: "SyntaxError: Invalid character '\\u088f'"
715715
strict mode: "SyntaxError: Invalid character '\\u088f'"
716-
test/language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-export-star-as-from-and-import-star-as-and-export.js:
717-
module: "SyntaxError: Importing binding name 'foo' cannot be resolved due to ambiguous multiple bindings."
718-
test/language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-import-star-as-and-export.js:
719-
module: "SyntaxError: Importing binding name 'foo' cannot be resolved due to ambiguous multiple bindings."
720716
test/language/module-code/top-level-await/async-module-does-not-block-sibling-modules.js:
721717
module: 'Test262Error: Expected SameValue(«true», «false») to be true'
722718
test/language/module-code/top-level-await/dynamic-import-of-waiting-module.js:

Source/JavaScriptCore/parser/ModuleAnalyzer.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,24 +73,24 @@ void ModuleAnalyzer::exportVariable(ModuleProgramNode& moduleProgramNode, const
7373
return;
7474
}
7575

76+
std::optional<JSModuleRecord::ImportEntry> optionalImportEntry = moduleRecord()->tryGetImportEntry(localName.get());
77+
ASSERT(optionalImportEntry);
78+
const JSModuleRecord::ImportEntry& importEntry = *optionalImportEntry;
79+
7680
if (variable.isImportedNamespace()) {
7781
// Exported namespace binding.
7882
// import * as namespace from "mod"
7983
// export { namespace }
8084
//
8185
// Sec 15.2.1.16.1 step 11-a-ii-2-b https://tc39.github.io/ecma262/#sec-parsemodule
82-
// Namespace export is handled as local export since a namespace object binding itself is implemented as a local binding.
8386
for (auto& exportName : moduleProgramNode.moduleScopeData().exportedBindings().get(localName.get()))
84-
moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createLocal(Identifier::fromUid(m_vm, exportName.get()), Identifier::fromUid(m_vm, localName.get())));
87+
moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createNamespace(Identifier::fromUid(m_vm, exportName.get()), importEntry.moduleRequest));
8588
return;
8689
}
8790

8891
// Indirectly exported binding.
8992
// import a from "mod"
9093
// export { a }
91-
std::optional<JSModuleRecord::ImportEntry> optionalImportEntry = moduleRecord()->tryGetImportEntry(localName.get());
92-
ASSERT(optionalImportEntry);
93-
const JSModuleRecord::ImportEntry& importEntry = *optionalImportEntry;
9494
for (auto& exportName : moduleProgramNode.moduleScopeData().exportedBindings().get(localName.get()))
9595
moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createIndirect(Identifier::fromUid(m_vm, exportName.get()), importEntry.importName, importEntry.moduleRequest));
9696
}

0 commit comments

Comments
 (0)