-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat(es/transformer): Add edge_default_param bugfix hook #11504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| //! Bugfix: Edge Default Param | ||
| //! | ||
| //! Converts destructured parameters with default values to non-shorthand | ||
| //! syntax. This fixes the only arguments-related bug in ES Modules-supporting | ||
| //! browsers (Edge 16 & 17). Use this plugin instead of | ||
| //! @babel/plugin-transform-parameters when targeting ES Modules. | ||
| //! | ||
| //! ## Example | ||
| //! | ||
| //! Input: | ||
| //! ```js | ||
| //! const f = ({ a = 1 }) => a; | ||
| //! ``` | ||
| //! | ||
| //! Output: | ||
| //! ```js | ||
| //! const f = ({ a: a = 1 }) => a; | ||
| //! ``` | ||
|
|
||
| use swc_ecma_ast::*; | ||
| use swc_ecma_hooks::VisitMutHook; | ||
|
|
||
| use crate::TraverseCtx; | ||
|
|
||
| pub fn hook() -> impl VisitMutHook<TraverseCtx> { | ||
| EdgeDefaultParamPass { in_arrow: false } | ||
| } | ||
|
|
||
| struct EdgeDefaultParamPass { | ||
| in_arrow: bool, | ||
| } | ||
|
|
||
| impl VisitMutHook<TraverseCtx> for EdgeDefaultParamPass { | ||
| fn enter_arrow_expr(&mut self, _node: &mut ArrowExpr, _ctx: &mut TraverseCtx) { | ||
| self.in_arrow = true; | ||
| } | ||
|
|
||
| fn exit_arrow_expr(&mut self, _node: &mut ArrowExpr, _ctx: &mut TraverseCtx) { | ||
| self.in_arrow = false; | ||
| } | ||
|
|
||
| fn exit_object_pat(&mut self, n: &mut ObjectPat, _ctx: &mut TraverseCtx) { | ||
| if !self.in_arrow { | ||
| return; | ||
| } | ||
|
|
||
| for prop in n.props.iter_mut() { | ||
| if let ObjectPatProp::Assign(AssignPatProp { | ||
| value: Some(value), | ||
| key, | ||
| span, | ||
| .. | ||
| }) = prop | ||
| { | ||
| *prop = ObjectPatProp::KeyValue(KeyValuePatProp { | ||
| key: PropName::Ident(key.clone().into()), | ||
| value: AssignPat { | ||
| span: *span, | ||
| left: key.clone().into(), | ||
| right: value.clone(), | ||
| } | ||
| .into(), | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,39 @@ | ||
| use swc_ecma_hooks::VisitMutHook; | ||
|
|
||
| use crate::TraverseCtx; | ||
| use crate::{ | ||
| hook_utils::{HookBuilder, NoopHook}, | ||
| TraverseCtx, | ||
| }; | ||
|
|
||
| mod edge_default_param; | ||
|
|
||
| #[derive(Debug, Default)] | ||
| #[non_exhaustive] | ||
| pub struct BugfixOptions {} | ||
| pub struct BugfixOptions { | ||
| /// Enable edge default param bugfix. | ||
| /// | ||
| /// Converts destructured parameters with default values to non-shorthand | ||
| /// syntax. This fixes the only arguments-related bug in ES | ||
| /// Modules-supporting browsers (Edge 16 & 17). | ||
| pub edge_default_param: bool, | ||
| } | ||
|
|
||
| impl BugfixOptions { | ||
| /// Returns true if any transform is enabled. | ||
| /// Currently no bugfixes are available. | ||
| pub fn is_enabled(&self) -> bool { | ||
| false | ||
| self.edge_default_param | ||
| } | ||
| } | ||
|
|
||
| pub fn hook(options: BugfixOptions) -> impl VisitMutHook<TraverseCtx> { | ||
| BugfixPass { options } | ||
| } | ||
| let hook = HookBuilder::new(NoopHook); | ||
|
|
||
| struct BugfixPass { | ||
| options: BugfixOptions, | ||
| } | ||
| // Edge default param: { a = 1 } -> { a: a = 1 } | ||
| let hook = hook.chain(if options.edge_default_param { | ||
| Some(self::edge_default_param::hook()) | ||
|
Comment on lines
28
to
+33
|
||
| } else { | ||
| None | ||
| }); | ||
|
|
||
| impl VisitMutHook<TraverseCtx> for BugfixPass {} | ||
| hook.build() | ||
| } | ||
|
Comment on lines
10
to
+39
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EdgeDefaultParamPasscurrently uses a singlein_arrowboolean that is set for the entireArrowExprtraversal. This makes the rewrite run for allObjectPats anywhere inside an arrow (including in the body), even though the bugfix is documented as targeting destructured parameters only. It also becomes incorrect for nested arrows because exiting an inner arrow setsin_arrow = falsewhile still inside the outer arrow.To match the intended behavior (and the existing implementation in
crates/swc_ecma_compat_bugfixes/src/edge_default_param.rs), restrict the rewrite toArrowExpr.paramsonly (e.g., perform the transformation directly inenter_arrow_exprby walkingnode.params), or alternatively track nesting with a counter/stack and only enable the rewrite while visiting the parameter list.