fix(javascript): preserve lexical binding and default export capture semantics

Resolve CommonJS wrapper bindings from the parser-owned source type. Capture default identifier export values at the export statement while preserving live named bindings.

Refs: #3261, #3297

Co-authored-by: hhang <169027046+xu91102@users.noreply.github.com>
This commit is contained in:
morluto
2026-10-14 17:49:13 +08:00
parent 322506d0c0
commit dae1e55381
6 changed files with 111 additions and 16 deletions
@@ -94,6 +94,11 @@ export interface JavaScriptSemanticAnalysisState {
JavaScriptSemanticModuleLink,
JavaScriptSemanticBindingState
>;
/** Default expressions capture their value at the export statement. */
readonly defaultExportExpressions: WeakMap<
JavaScriptSemanticModuleLink,
t.Node
>;
/** Initializer expressions whose write can be skipped by enclosing control flow. */
readonly conditionallySkippedExpressions: WeakSet<t.Node>;
/** Unbound identifier writes retain their source sites for capture ordering. */
@@ -263,8 +268,10 @@ export const isUnmodifiedCommonJsWrapperBinding = (
name: string,
state: JavaScriptSemanticAnalysisState,
): boolean => {
// Parser sourceType separates explicit modules from script/CommonJS source;
// specifier resolution mode does not establish that distinction.
if (
state.staticImportResolutionMode !== "require" ||
state.program.sourceType !== "script" ||
!["module", "exports", "require"].includes(name) ||
!t.isIdentifier(node, { name })
)