Skip to content

Commit 84742d8

Browse files
committed
fix(transformer/module_runner): fix export default live binding (#10560)
Aligning with vitejs/vite#19842 (Hopefully this is the last one 🙂)
1 parent 6c115c7 commit 84742d8

File tree

1 file changed

+136
-49
lines changed

1 file changed

+136
-49
lines changed

crates/oxc_transformer/src/plugins/module_runner_transform.rs

Lines changed: 136 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ impl<'a> ModuleRunnerTransform<'a> {
9999
}
100100

101101
const SSR_MODULE_EXPORTS_KEY: Atom<'static> = Atom::new_const("__vite_ssr_exports__");
102+
const SSR_EXPORT_DEFAULT_KEY: Atom<'static> = Atom::new_const("__vite_ssr_export_default__");
102103
const SSR_IMPORT_KEY: Atom<'static> = Atom::new_const("__vite_ssr_import__");
103104
const SSR_DYNAMIC_IMPORT_KEY: Atom<'static> = Atom::new_const("__vite_ssr_dynamic_import__");
104105
const SSR_EXPORT_ALL_KEY: Atom<'static> = Atom::new_const("__vite_ssr_exportAll__");
@@ -166,7 +167,12 @@ impl<'a> ModuleRunnerTransform<'a> {
166167
);
167168
}
168169
Statement::ExportDefaultDeclaration(export) => {
169-
Self::transform_export_default_declaration(&mut new_stmts, export, ctx);
170+
Self::transform_export_default_declaration(
171+
&mut new_stmts,
172+
&mut hoist_exports,
173+
export,
174+
ctx,
175+
);
170176
}
171177
_ => {
172178
new_stmts.push(stmt);
@@ -536,11 +542,13 @@ impl<'a> ModuleRunnerTransform<'a> {
536542
/// export default function () {}
537543
/// export default {}
538544
/// // to
539-
/// __vite_ssr_exports__.default = function () {}
540-
/// __vite_ssr_exports__.default = {}
545+
/// Object.defineProperty(__vite_ssr_exports__, 'default', { enumerable: true, configurable: true, get(){ return __vite_ssr_export_default__ } });
546+
/// const __vite_ssr_export_default__ = function () {}
547+
/// const __vite_ssr_export_default__ = {}
541548
/// ```
542549
fn transform_export_default_declaration(
543550
new_stmts: &mut ArenaVec<'a, Statement<'a>>,
551+
hoist_exports: &mut Vec<Statement<'a>>,
544552
export: ArenaBox<'a, ExportDefaultDeclaration<'a>>,
545553
ctx: &mut TraverseCtx<'a>,
546554
) {
@@ -549,28 +557,26 @@ impl<'a> ModuleRunnerTransform<'a> {
549557
ExportDefaultDeclarationKind::FunctionDeclaration(mut func) => {
550558
if let Some(id) = &func.id {
551559
let ident = BoundIdentifier::from_binding_ident(id).create_read_expression(ctx);
552-
new_stmts.extend([
553-
Statement::FunctionDeclaration(func),
554-
Self::create_export(span, ident, DEFAULT, ctx),
555-
]);
560+
new_stmts.push(Statement::FunctionDeclaration(func));
561+
hoist_exports.push(Self::create_export(span, ident, DEFAULT, ctx));
556562
} else {
557563
func.r#type = FunctionType::FunctionExpression;
558564
let right = Expression::FunctionExpression(func);
559565
new_stmts.push(Self::create_export_default_assignment(span, right, ctx));
566+
hoist_exports.push(Self::create_export_default(span, ctx));
560567
}
561568
return;
562569
}
563570
ExportDefaultDeclarationKind::ClassDeclaration(mut class) => {
564571
if let Some(id) = &class.id {
565572
let ident = BoundIdentifier::from_binding_ident(id).create_read_expression(ctx);
566-
new_stmts.extend([
567-
Statement::ClassDeclaration(class),
568-
Self::create_export(span, ident, DEFAULT, ctx),
569-
]);
573+
new_stmts.push(Statement::ClassDeclaration(class));
574+
hoist_exports.push(Self::create_export(span, ident, DEFAULT, ctx));
570575
} else {
571576
class.r#type = ClassType::ClassExpression;
572577
let right = Expression::ClassExpression(class);
573578
new_stmts.push(Self::create_export_default_assignment(span, right, ctx));
579+
hoist_exports.push(Self::create_export_default(span, ctx));
574580
}
575581
return;
576582
}
@@ -582,6 +588,7 @@ impl<'a> ModuleRunnerTransform<'a> {
582588
};
583589

584590
new_stmts.push(Self::create_export_default_assignment(span, expr, ctx));
591+
hoist_exports.push(Self::create_export_default(span, ctx));
585592
}
586593

587594
/// Transform import specifiers, and return an imported names object.
@@ -780,20 +787,30 @@ impl<'a> ModuleRunnerTransform<'a> {
780787
ctx.ast.statement_expression(span, Self::create_define_property(arguments, ctx))
781788
}
782789

783-
// __vite_ssr_exports__.default = right;
790+
fn create_export_default(span: Span, ctx: &mut TraverseCtx<'a>) -> Statement<'a> {
791+
Self::create_export(
792+
span,
793+
ctx.create_unbound_ident_expr(SPAN, SSR_EXPORT_DEFAULT_KEY, ReferenceFlags::Read),
794+
DEFAULT,
795+
ctx,
796+
)
797+
}
798+
799+
// const __vite_ssr_export_default__ = right;
784800
fn create_export_default_assignment(
785801
span: Span,
786802
right: Expression<'a>,
787803
ctx: &mut TraverseCtx<'a>,
788804
) -> Statement<'a> {
789-
let object =
790-
ctx.create_unbound_ident_expr(SPAN, SSR_MODULE_EXPORTS_KEY, ReferenceFlags::Read);
791-
let property = ctx.ast.identifier_name(SPAN, DEFAULT);
792-
let member = ctx.ast.member_expression_static(SPAN, object, property, false);
793-
let target = AssignmentTarget::from(member);
794-
let operator = AssignmentOperator::Assign;
795-
let assignment = ctx.ast.expression_assignment(SPAN, operator, target, right);
796-
ctx.ast.statement_expression(span, assignment)
805+
let binding = ctx.generate_binding_in_current_scope(
806+
SSR_EXPORT_DEFAULT_KEY,
807+
SymbolFlags::BlockScopedVariable,
808+
);
809+
let pattern = binding.create_binding_pattern(ctx);
810+
let kind = VariableDeclarationKind::Const;
811+
let declarator = ctx.ast.variable_declarator(SPAN, kind, pattern, Some(right), false);
812+
let declaration = ctx.ast.declaration_variable(span, kind, ctx.ast.vec1(declarator), false);
813+
Statement::from(declaration)
797814
}
798815
}
799816

@@ -1187,7 +1204,19 @@ const __vite_ssr_import_0__ = await __vite_ssr_import__('vue', { importedNames:
11871204

11881205
#[test]
11891206
fn export_default() {
1190-
test_same("export default {}", "__vite_ssr_exports__.default = {};");
1207+
test_same(
1208+
"export default {}",
1209+
"
1210+
Object.defineProperty(__vite_ssr_exports__, 'default', {
1211+
enumerable: true,
1212+
configurable: true,
1213+
get() {
1214+
return __vite_ssr_export_default__;
1215+
}
1216+
});
1217+
const __vite_ssr_export_default__ = {};
1218+
",
1219+
);
11911220
}
11921221

11931222
#[test]
@@ -1436,22 +1465,22 @@ class A extends __vite_ssr_import_0__.Foo {}",
14361465
export class B extends Foo {}
14371466
",
14381467
"
1439-
Object.defineProperty(__vite_ssr_exports__, 'B', {
1468+
Object.defineProperty(__vite_ssr_exports__, 'default', {
14401469
enumerable: true,
14411470
configurable: true,
14421471
get() {
1443-
return B;
1472+
return A;
14441473
}
14451474
});
1446-
const __vite_ssr_import_0__ = await __vite_ssr_import__('./dependency', { importedNames: ['Foo'] });
1447-
class A extends __vite_ssr_import_0__.Foo {}
1448-
Object.defineProperty(__vite_ssr_exports__, 'default', {
1475+
Object.defineProperty(__vite_ssr_exports__, 'B', {
14491476
enumerable: true,
14501477
configurable: true,
14511478
get() {
1452-
return A;
1479+
return B;
14531480
}
14541481
});
1482+
const __vite_ssr_import_0__ = await __vite_ssr_import__('./dependency', { importedNames: ['Foo'] });
1483+
class A extends __vite_ssr_import_0__.Foo {}
14551484
class B extends __vite_ssr_import_0__.Foo {}
14561485
",
14571486
);
@@ -1461,44 +1490,73 @@ class A extends __vite_ssr_import_0__.Foo {}",
14611490
#[test]
14621491
fn should_handle_default_export_variants() {
14631492
// default anonymous functions
1464-
test_same("export default function() {}", "__vite_ssr_exports__.default = function() {};");
1493+
test_same(
1494+
"export default function() {}",
1495+
"
1496+
Object.defineProperty(__vite_ssr_exports__, 'default', {
1497+
enumerable: true,
1498+
configurable: true,
1499+
get() {
1500+
return __vite_ssr_export_default__;
1501+
}
1502+
});
1503+
const __vite_ssr_export_default__ = function() {};
1504+
",
1505+
);
14651506

14661507
// default anonymous class
1467-
test_same("export default class {}", "__vite_ssr_exports__.default = class {};");
1508+
test_same(
1509+
"export default class {}",
1510+
"
1511+
Object.defineProperty(__vite_ssr_exports__, 'default', {
1512+
enumerable: true,
1513+
configurable: true,
1514+
get() {
1515+
return __vite_ssr_export_default__;
1516+
}
1517+
});
1518+
const __vite_ssr_export_default__ = class {};
1519+
",
1520+
);
14681521

14691522
// default named functions
14701523
test_same(
1471-
"export default function foo() {}\nfoo.prototype = Object.prototype;",
1472-
"function foo() {}
1524+
"
1525+
export default function foo() {}
1526+
foo.prototype = Object.prototype;
1527+
",
1528+
"
14731529
Object.defineProperty(__vite_ssr_exports__, 'default', {
1474-
enumerable: true,
1475-
configurable: true,
1476-
get() {
1477-
return foo;
1478-
}
1530+
enumerable: true,
1531+
configurable: true,
1532+
get() {
1533+
return foo;
1534+
}
14791535
});
1480-
foo.prototype = Object.prototype;",
1536+
function foo() {}
1537+
foo.prototype = Object.prototype;
1538+
",
14811539
);
14821540

14831541
// default named classes
14841542
test_same(
14851543
"export default class A {}\nexport class B extends A {}",
14861544
"
1487-
Object.defineProperty(__vite_ssr_exports__, 'B', {
1545+
Object.defineProperty(__vite_ssr_exports__, 'default', {
14881546
enumerable: true,
14891547
configurable: true,
14901548
get() {
1491-
return B;
1549+
return A;
14921550
}
14931551
});
1494-
class A {}
1495-
Object.defineProperty(__vite_ssr_exports__, 'default', {
1552+
Object.defineProperty(__vite_ssr_exports__, 'B', {
14961553
enumerable: true,
14971554
configurable: true,
14981555
get() {
1499-
return A;
1556+
return B;
15001557
}
15011558
});
1559+
class A {}
15021560
class B extends A {}
15031561
",
15041562
);
@@ -1830,15 +1888,37 @@ function fn2() {}
18301888
// return Math.random()
18311889
// }
18321890
test_same(
1833-
"export default (function getRandom() {
1834-
return Math.random();
1835-
});",
1836-
"__vite_ssr_exports__.default = function getRandom() {
1891+
"
1892+
export default (function getRandom() {
18371893
return Math.random();
1838-
};",
1894+
});
1895+
",
1896+
"
1897+
Object.defineProperty(__vite_ssr_exports__, 'default', {
1898+
enumerable: true,
1899+
configurable: true,
1900+
get() {
1901+
return __vite_ssr_export_default__;
1902+
}
1903+
});
1904+
const __vite_ssr_export_default__ = function getRandom() {
1905+
return Math.random();
1906+
};
1907+
",
18391908
);
18401909

1841-
test_same("export default (class A {});", "__vite_ssr_exports__.default = class A {};");
1910+
test_same(
1911+
"export default (class A {});",
1912+
"
1913+
Object.defineProperty(__vite_ssr_exports__, 'default', {
1914+
enumerable: true,
1915+
configurable: true,
1916+
get() {
1917+
return __vite_ssr_export_default__;
1918+
}
1919+
});
1920+
const __vite_ssr_export_default__ = class A {};",
1921+
);
18421922
}
18431923

18441924
// https://github.com/vitejs/vite/issues/8002
@@ -2085,6 +2165,13 @@ console.log(__vite_ssr_import_1__.foo + 2);",
20852165
console.log(bar)
20862166
",
20872167
"
2168+
Object.defineProperty(__vite_ssr_exports__, 'default', {
2169+
enumerable: true,
2170+
configurable: true,
2171+
get() {
2172+
return __vite_ssr_export_default__;
2173+
}
2174+
});
20882175
Object.defineProperty(__vite_ssr_exports__, 'bar', {
20892176
enumerable: true,
20902177
configurable: true,
@@ -2094,7 +2181,7 @@ Object.defineProperty(__vite_ssr_exports__, 'bar', {
20942181
});
20952182
const __vite_ssr_import_0__ = await __vite_ssr_import__('./foo', { importedNames: ['foo'] });
20962183
const __vite_ssr_import_1__ = await __vite_ssr_import__('./bar');
2097-
__vite_ssr_exports__.default = (0, __vite_ssr_import_0__.foo)();
2184+
const __vite_ssr_export_default__ = (0, __vite_ssr_import_0__.foo)();
20982185
console.log(bar);
20992186
",
21002187
);

0 commit comments

Comments
 (0)