From 3bb2a6ccca4e78412f80aea4fe6c22d04d345a00 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Fri, 4 Feb 2022 11:33:19 +0800 Subject: [PATCH] fix(es/compat): Handle initializer hole in array patterns (#3442) --- .../src/es2015/destructuring.rs | 46 ++++---- .../tests/es2015_destructuring.rs | 111 ++++++++++++++++++ 2 files changed, 132 insertions(+), 25 deletions(-) diff --git a/crates/swc_ecma_transforms_compat/src/es2015/destructuring.rs b/crates/swc_ecma_transforms_compat/src/es2015/destructuring.rs index 06b59bc8750..9aaab697c3b 100644 --- a/crates/swc_ecma_transforms_compat/src/es2015/destructuring.rs +++ b/crates/swc_ecma_transforms_compat/src/es2015/destructuring.rs @@ -434,40 +434,36 @@ impl AssignFolder { right: def_value, .. }) => { - assert!( - decl.init.is_some(), - "destructuring pattern binding requires initializer" - ); + let init = if let Some(init) = decl.init { + let tmp_ident = match &*init { + Expr::Ident(ref i) if i.span.ctxt() != SyntaxContext::empty() => i.clone(), - let init = decl.init; - let tmp_ident: Ident = (|| { - if let Some(ref e) = init { - match &**e { - Expr::Ident(ref i) if i.span.ctxt() != SyntaxContext::empty() => { - return i.clone(); - } - _ => {} + _ => { + let tmp_ident = private_ident!(span, "tmp"); + decls.push(VarDeclarator { + span: DUMMY_SP, + name: tmp_ident.clone().into(), + init: Some(init), + definite: false, + }); + + tmp_ident } - } + }; - let tmp_ident = private_ident!(span, "tmp"); - decls.push(VarDeclarator { - span: DUMMY_SP, - name: tmp_ident.clone().into(), - init, - definite: false, - }); - - tmp_ident - })(); + // tmp === void 0 ? def_value : tmp + Some(Box::new(make_cond_expr(tmp_ident, def_value))) + } else { + Some(def_value) + }; let var_decl = VarDeclarator { span, name: *left, - // tmp === void 0 ? def_value : tmp - init: Some(Box::new(make_cond_expr(tmp_ident, def_value))), + init, definite: false, }; + let mut var_decls = vec![var_decl]; var_decls.visit_mut_with(self); decls.extend(var_decls); diff --git a/crates/swc_ecma_transforms_compat/tests/es2015_destructuring.rs b/crates/swc_ecma_transforms_compat/tests/es2015_destructuring.rs index d82e517cd1b..5830616710f 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2015_destructuring.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2015_destructuring.rs @@ -1992,3 +1992,114 @@ test!( ref = [], ref1 = ref[0], bar = ref1 === void 0 ? baz : ref1, ref; " ); + +test!( + syntax(), + |_| tr(), + statements_let_dstr_ary_ptrn_elem_id_init_hole, + "\ + let [x = 23] = [,]; + + assert.sameValue(x, 23); + ", + "\ + let x = 23; + assert.sameValue(x, 23); + " +); + +test!( + syntax(), + |_| tr(), + statements_let_dstr_ary_ptrn_elem_id_init_hole_2, + "\ + let y = [x = 23] = [,]; + ", + "\ + var ref, ref1; + let y = (ref = [,], ref1 = ref[0], x = ref1 === void 0 ? 23 : ref1, ref); + " +); + +test!( + syntax(), + |_| tr(), + statements_const_dstr_ary_ptrn_elem_id_init_hole, + "\ + const [x = 23] = [,]; + + assert.sameValue(x, 23); + ", + "\ + const x = 23; + assert.sameValue(x, 23); + " +); + +test!( + syntax(), + |_| tr(), + statements_const_dstr_ary_ptrn_elem_id_init_hole_2, + "const [x = 23, y = 42] = [,,];", + "const x = 23, y = 42;" +); + +test!( + syntax(), + |_| tr(), + statements_const_dstr_ary_ptrn_elem_id_init_hole_3, + "const [x = 23, y] = [, 42];", + "const x = 23, y = 42;" +); + +test!( + syntax(), + |_| tr(), + statements_const_dstr_ary_ptrn_elem_id_init_hole_4, + "\ + function* foo() { + yield 1; + yield 2; + } + + let bar = foo(); + + const [x = bar.next().value, y] = [, bar.next().value]; + console.log(x, y); + ", + "\ + function* foo() { + yield 1; + yield 2; + } + let bar = foo(); + const ref = [,bar.next().value], tmp = ref[0], + x = tmp === void 0 ? bar.next().value : tmp, y = ref[1]; + console.log(x, y);" +); + +test!( + syntax(), + |_| tr(), + for_const_dstr_ary_ptrn_elem_id_init_hole, + "\ + var iterCount = 0; + + for (const [x = 23] = [,]; iterCount < 1; ) { + assert.sameValue(x, 23); + // another statement + + iterCount += 1; + } + + assert.sameValue(iterCount, 1, 'Iteration occurred as expected'); + ", + "\ + var iterCount = 0; + for(const x = 23; iterCount < 1;){ + assert.sameValue(x, 23); + iterCount += 1; + } + assert.sameValue(iterCount, 1, 'Iteration occurred as expected'); + " +);