Skip to content

Commit e97880f

Browse files
feat(es/transformer): Add edge_default_param bugfix hook
This adds the `edge_default_param` bugfix to `swc_ecma_transformer` using the hook-based visitor pattern. This transform converts destructured parameters with default values to non-shorthand syntax, fixing an arguments-related bug in Edge 16 & 17. Changes: - Add `edge_default_param.rs` hook in `bugfix/` module - Add `enter_object_pat`/`exit_object_pat` hooks to `OrderedChain` - Update `BugfixOptions` with `edge_default_param` option Closes #10470 Co-authored-by: Donny/강동윤 <[email protected]>
1 parent 5efcac9 commit e97880f

File tree

3 files changed

+94
-10
lines changed

3 files changed

+94
-10
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//! Bugfix: Edge Default Param
2+
//!
3+
//! Converts destructured parameters with default values to non-shorthand
4+
//! syntax. This fixes the only arguments-related bug in ES Modules-supporting
5+
//! browsers (Edge 16 & 17). Use this plugin instead of
6+
//! @babel/plugin-transform-parameters when targeting ES Modules.
7+
//!
8+
//! ## Example
9+
//!
10+
//! Input:
11+
//! ```js
12+
//! const f = ({ a = 1 }) => a;
13+
//! ```
14+
//!
15+
//! Output:
16+
//! ```js
17+
//! const f = ({ a: a = 1 }) => a;
18+
//! ```
19+
20+
use swc_ecma_ast::*;
21+
use swc_ecma_hooks::VisitMutHook;
22+
23+
use crate::TraverseCtx;
24+
25+
pub fn hook() -> impl VisitMutHook<TraverseCtx> {
26+
EdgeDefaultParamPass { in_arrow: false }
27+
}
28+
29+
struct EdgeDefaultParamPass {
30+
in_arrow: bool,
31+
}
32+
33+
impl VisitMutHook<TraverseCtx> for EdgeDefaultParamPass {
34+
fn enter_arrow_expr(&mut self, _node: &mut ArrowExpr, _ctx: &mut TraverseCtx) {
35+
self.in_arrow = true;
36+
}
37+
38+
fn exit_arrow_expr(&mut self, _node: &mut ArrowExpr, _ctx: &mut TraverseCtx) {
39+
self.in_arrow = false;
40+
}
41+
42+
fn exit_object_pat(&mut self, n: &mut ObjectPat, _ctx: &mut TraverseCtx) {
43+
if !self.in_arrow {
44+
return;
45+
}
46+
47+
for prop in n.props.iter_mut() {
48+
if let ObjectPatProp::Assign(AssignPatProp {
49+
value: Some(value),
50+
key,
51+
span,
52+
..
53+
}) = prop
54+
{
55+
*prop = ObjectPatProp::KeyValue(KeyValuePatProp {
56+
key: PropName::Ident(key.clone().into()),
57+
value: AssignPat {
58+
span: *span,
59+
left: key.clone().into(),
60+
right: value.clone(),
61+
}
62+
.into(),
63+
});
64+
}
65+
}
66+
}
67+
}
Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
11
use swc_ecma_hooks::VisitMutHook;
22

3-
use crate::TraverseCtx;
3+
use crate::{
4+
hook_utils::{HookBuilder, NoopHook},
5+
TraverseCtx,
6+
};
7+
8+
mod edge_default_param;
49

510
#[derive(Debug, Default)]
611
#[non_exhaustive]
7-
pub struct BugfixOptions {}
12+
pub struct BugfixOptions {
13+
/// Enable edge default param bugfix.
14+
///
15+
/// Converts destructured parameters with default values to non-shorthand
16+
/// syntax. This fixes the only arguments-related bug in ES
17+
/// Modules-supporting browsers (Edge 16 & 17).
18+
pub edge_default_param: bool,
19+
}
820

921
impl BugfixOptions {
1022
/// Returns true if any transform is enabled.
11-
/// Currently no bugfixes are available.
1223
pub fn is_enabled(&self) -> bool {
13-
false
24+
self.edge_default_param
1425
}
1526
}
1627

1728
pub fn hook(options: BugfixOptions) -> impl VisitMutHook<TraverseCtx> {
18-
BugfixPass { options }
19-
}
29+
let hook = HookBuilder::new(NoopHook);
2030

21-
struct BugfixPass {
22-
options: BugfixOptions,
23-
}
31+
// Edge default param: { a = 1 } -> { a: a = 1 }
32+
let hook = hook.chain(if options.edge_default_param {
33+
Some(self::edge_default_param::hook())
34+
} else {
35+
None
36+
});
2437

25-
impl VisitMutHook<TraverseCtx> for BugfixPass {}
38+
hook.build()
39+
}

crates/swc_ecma_transformer/src/hook_utils.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ where
124124
exit_module_export_name,
125125
ModuleExportName
126126
);
127+
128+
// Bugfix hooks: object pattern handling
129+
chained_method!(enter_object_pat, exit_object_pat, ObjectPat);
127130
}
128131

129132
pub(crate) struct NoopHook;

0 commit comments

Comments
 (0)