diff --git a/ecmascript/transforms/compat/Cargo.toml b/ecmascript/transforms/compat/Cargo.toml index da098fbe6b6..8cc452f378f 100644 --- a/ecmascript/transforms/compat/Cargo.toml +++ b/ecmascript/transforms/compat/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "Apache-2.0/MIT" name = "swc_ecma_transforms_compat" repository = "https://github.com/swc-project/swc.git" -version = "0.17.4" +version = "0.17.5" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/ecmascript/transforms/compat/src/es2015/block_scoping.rs b/ecmascript/transforms/compat/src/es2015/block_scoping.rs index 43982c97f1e..e80b4f30507 100644 --- a/ecmascript/transforms/compat/src/es2015/block_scoping.rs +++ b/ecmascript/transforms/compat/src/es2015/block_scoping.rs @@ -998,846 +998,3 @@ impl Visit for FunctionFinder { self.found = true } } - -#[cfg(test)] -mod tests { - use super::block_scoping; - use crate::{es2015, es2015::for_of::for_of, es2017::async_to_generator}; - use swc_common::{chain, Mark}; - use swc_ecma_parser::Syntax; - use swc_ecma_transforms_testing::{test, test_exec, Tester}; - - test!( - ::swc_ecma_parser::Syntax::default(), - |_| block_scoping(), - for_loop, - "for (const key in obj) { - const bar = obj[key]; - - let qux; - let fog; - - if (Array.isArray(bar)) { - qux = bar[0]; - fog = bar[1]; - } else { - qux = bar; - } - - baz(key, qux, fog); - }", - "for (var key in obj) { - var bar = obj[key]; - - var qux = void 0; - var fog = void 0; - - if (Array.isArray(bar)) { - qux = bar[0]; - fog = bar[1]; - } else { - qux = bar; - } - - baz(key, qux, fog); - }" - ); - - test!( - ::swc_ecma_parser::Syntax::default(), - |_| block_scoping(), - for_let_loop, - "let functions = []; -for (let i = 0; i < 10; i++) { - functions.push(function() { - console.log(i); - }); -} -functions[0](); -functions[7]();", - " -var _loop = function(i) { - functions.push(function() { - console.log(i); - }); -}; -var functions = []; -for(var i = 0; i < 10; i++)_loop(i); -functions[0](); -functions[7](); -" - ); - - test_exec!( - ::swc_ecma_parser::Syntax::default(), - |_| block_scoping(), - for_let_loop_exec, - "let functions = []; -for (let i = 0; i < 10; i++) { - functions.push(function() { - return i; - }); -} -expect(functions[0]()).toBe(0); -expect(functions[7]()).toBe(7); -" - ); - - test_exec!( - ::swc_ecma_parser::Syntax::default(), - |_| block_scoping(), - for_let_of_exec, - "let functions = []; -for (let i of [1, 3, 5, 7, 9]) { - functions.push(function() { - return i; - }); -} -expect(functions[0]()).toBe(1); -expect(functions[1]()).toBe(3); -" - ); - - test_exec!( - ::swc_ecma_parser::Syntax::default(), - |_| chain!(for_of(Default::default()), block_scoping()), - issue_609_1, - "let functions = []; -for (let i of [1, 3, 5, 7, 9]) { - functions.push(function() { - return i; - }); -} -expect(functions[0]()).toBe(1); -expect(functions[1]()).toBe(3); -" - ); - - test!( - ::swc_ecma_parser::Syntax::default(), - |_| block_scoping(), - issue_662, - "function foo(parts) { - let match = null; - - for (let i = 1; i >= 0; i--) { - for (let j = 0; j >= 0; j--) { - match = parts[i][j]; - - if (match) { - break; - } - } - - if (match) { - break; - } - } - - return match; -} - -foo();", - "function foo(parts) { - var match = null; - - for (var i = 1; i >= 0; i--) { - for (var j = 0; j >= 0; j--) { - match = parts[i][j]; - - if (match) { - break; - } - } - - if (match) { - break; - } - } - - return match; -} - -foo();" - ); - - test!( - ::swc_ecma_parser::Syntax::default(), - |_| block_scoping(), - issue_686, - "module.exports = function(values) { - var vars = []; - var elem = null, name, val; - for (var i = 0; i < this.elements.length; i++) { - elem = this.elements[i]; - name = elem.name; - if (!name) continue; - val = values[name]; - if (val == null) val = ''; - switch (elem.type) { - case 'submit': - break; - case 'radio': - case 'checkbox': - elem.checked = val.some(function(str) { - return str.toString() == elem.value; - }); - break; - case 'select-multiple': - elem.fill(val); - break; - case 'textarea': - elem.innerText = val; - break; - case 'hidden': - break; - default: - if (elem.fill) { - elem.fill(val); - } else { - elem.value = val; - } - break; - } - } - return vars; - };", - " - module.exports = function(values) { - var _this = this, _loop = function(i) { - elem = _this.elements[i]; - name = elem.name; - if (!name) return 'continue'; - val = values[name]; - if (val == null) val = ''; - switch(elem.type){ - case 'submit': - break; - case 'radio': - case 'checkbox': - elem.checked = val.some(function(str) { - return str.toString() == elem.value; - }); - break; - case 'select-multiple': - elem.fill(val); - break; - case 'textarea': - elem.innerText = val; - break; - case 'hidden': - break; - default: - if (elem.fill) { - elem.fill(val); - } else { - elem.value = val; - } - break; - } - }; - var vars = []; - var elem = null, name, val; - for(var i = 0; i < this.elements.length; i++){ - var _ret = _loop(i); - if (_ret === 'continue') continue; - } - return vars; - }; - " - ); - - test_exec!( - ::swc_ecma_parser::Syntax::default(), - |_| block_scoping(), - issue_723_1, - "function foo() { - const lod = { 0: { mig: 'bana' }}; - - for (let i = 0; i < 1; i++) { - const { mig } = lod[i]; - - return false; - - (zap) => zap === mig; - } - - return true; -} -expect(foo()).toBe(false); -" - ); - - test_exec!( - ::swc_ecma_parser::Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - issue_723_2, - "function foo() { - const lod = { 0: { mig: 'bana' }}; - - for (let i = 0; i < 1; i++) { - const { mig } = lod[i]; - - return false; - - (zap) => zap === mig; - } - - return true; -} -expect(foo()).toBe(false); -" - ); - - test!( - Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - issue_1022_1, - " - for (let i = 0; i < 5; i++) { - console.log(i++, [2].every(x => x != i)) - } - ", - r#" - var _loop = function(i1) { - console.log(i1++, [ - 2 - ].every(function(x) { - return x != i1; - })); - i = i1, void 0; - }; - for(var i = 0; i < 5; i++)_loop(i); - "# - ); - - test!( - Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - issue_1022_2, - " - for (let i = 0; i < 5; i++) { - console.log(i++, [2].every(x => x != i)) - if (i % 2 === 0) continue - } - ", - r#" - var _loop = function(i1) { - console.log(i1++, [ - 2 - ].every(function(x) { - return x != i1; - })); - if (i1 % 2 === 0) return i = i1, "continue"; - i = i1, void 0; - }; - for(var i = 0; i < 5; i++){ - var _ret = _loop(i); - if (_ret === "continue") continue; - } - "# - ); - - test!( - Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - issue_1022_3, - " - for (let i = 0; i < 5; i++) { - console.log(i++, [2].every(x => x != i)) - if (i % 2 === 0) break - } - ", - r#" - var _loop = function(i1) { - console.log(i1++, [ - 2 - ].every(function(x) { - return x != i1; - })); - if (i1 % 2 === 0) return i = i1, "break"; - i = i1, void 0; - }; - for(var i = 0; i < 5; i++){ - var _ret = _loop(i); - if (_ret === "break") break; - } - "# - ); - - test!( - Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - issue_1021_1, - " - class C { - m() { - for (let x = 0; x < 10; x++) console.log(this, y => y != x) - } - } - ", - r#" - var C = function() { - "use strict"; - function C() { - _classCallCheck(this, C); - } - _createClass(C, [ - { - key: "m", - value: function m() { - var _this = this, _loop = function(x) { - console.log(_this, function(y) { - return y != x; - }); - }; - for(var x = 0; x < 10; x++)_loop(x); - } - } - ]); - return C; - }(); - "# - ); - - test!( - Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - issue_1036_1, - " - async function foo() { - await Promise.all([[1], [2], [3]].map( - async ([a]) => Promise.resolve().then(() => a * 2)) - ) - } - ", - " - async function foo() { - await Promise.all([ - [ - 1 - ], - [ - 2 - ], - [ - 3 - ] - ].map(async function(param) { - var _param = _slicedToArray(param, 1), a = _param[0]; - return Promise.resolve().then(function() { - return a * 2; - }); - })); - } - " - ); - - test!( - Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - chain!( - async_to_generator(), - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - ) - }, - issue_1036_2, - " - async function foo() { - await Promise.all([[1], [2], [3]].map( - async ([a]) => Promise.resolve().then(() => a * 2)) - ) - } - ", - r#" - var regeneratorRuntime = require("regenerator-runtime"); - var _marked = regeneratorRuntime.mark(_foo); - function _foo() { - _foo = _asyncToGenerator(regeneratorRuntime.mark(function _callee() { - return regeneratorRuntime.wrap(function _callee$(_ctx) { - while(1)switch(_ctx.prev = _ctx.next){ - case 0: - _ctx.next = 2; - return Promise.all([ - [ - 1 - ], - [ - 2 - ], - [ - 3 - ] - ].map(_asyncToGenerator(regeneratorRuntime.mark(function _callee1(param) { - var _param = _slicedToArray(param, 1), a = _param[0]; - return regeneratorRuntime.wrap(function _callee$1(_ctx1) { - while(1)switch(_ctx1.prev = _ctx1.next){ - case 0: - return _ctx1.abrupt("return", Promise.resolve().then(function() { - return a * 2; - })); - case 1: - case "end": - return _ctx1.stop(); - } - }, _callee1); - })))); - case 2: - case "end": - return _ctx.stop(); - } - }, _callee); - })); - return _foo.apply(this, arguments); - } - function foo() { - return _foo.apply(this, arguments); - } - - "# - ); - - test_exec!( - Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - chain!( - async_to_generator(), - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - ) - }, - issue_1036_3, - " - const x = async function() { - return await Promise.all([[1], [2], [3]].map( - async ([a]) => Promise.resolve().then(() => a * 2)) - ) - }; - return x().then(x => { - expect(x).toEqual([2, 4, 6]) - }) - " - ); - - test!( - ::swc_ecma_parser::Syntax::default(), - |_| block_scoping(), - issue_1231_1, - " - function combineOverlappingMatches(matches) { - let hasOverlaps = false - - for (let i = matches.length - 1; i >= 0; i--) { - let currentMatch = matches[i] - let overlap = matches.find(match => { - return match !== currentMatch && match.itemsType === currentMatch.itemsType - }) - - if (overlap) { - hasOverlaps = true - matches.splice(i, 1) - } - } - - if (hasOverlaps) { - combineOverlappingMatches(matches) - } - } - - combineOverlappingMatches([1]) - ", - " - function combineOverlappingMatches(matches) { - var hasOverlaps = false; - for(var i = matches.length - 1; i >= 0; i--){ - var currentMatch = matches[i]; - var overlap = matches.find((match)=>{ - return match !== currentMatch && match.itemsType === currentMatch.itemsType; - }); - if (overlap) { - hasOverlaps = true; - matches.splice(i, 1); - } - } - if (hasOverlaps) { - combineOverlappingMatches(matches); - } - } - combineOverlappingMatches([ - 1 - ]); - " - ); - - test!( - ::swc_ecma_parser::Syntax::default(), - |_| block_scoping(), - issue_1415_1, - " - export function test(items) { - const infoMap = new WeakMap(); - for (let i = 0; i < items.length; i += 1) { - const item = items[i]; - let info; - switch (item.type) { - case 'branch1': - info = item.method1(); - break; - case 'branch2': - info = item.method2(); - break; - case 'branch3': - info = item.method3( - Object.fromEntries( - item.subItems.map((t) => [item.alias ?? t.name, getInfo(t)]) - ) - ); - break; - default: - throw new Error('boom'); - } - infoMap.set(item, info); // important - } - - function getInfo(item) { - if (!infoMap.has(item)) { - throw new Error('no info yet'); - } - return infoMap.get(item); - } - } - ", - " - export function test(items) { - var infoMap = new WeakMap(); - for(var i = 0; i < items.length; i += 1){ - var item = items[i]; - var info = void 0; - switch(item.type){ - case 'branch1': - info = item.method1(); - break; - case 'branch2': - info = item.method2(); - break; - case 'branch3': - info = item.method3(Object.fromEntries(item.subItems.map((t)=>[ - item.alias ?? t.name, - getInfo(t) - ] - ))); - break; - default: - throw new Error('boom'); - } - infoMap.set(item, info); - } - function getInfo(item) { - if (!infoMap.has(item)) { - throw new Error('no info yet'); - } - return infoMap.get(item); - } - } - " - ); - - test!( - ::swc_ecma_parser::Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - arguments_loop, - " - function test() { - for (var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - console.log((() => arg)()); - } - } - ", - " - function test() { - var _arguments = arguments, _loop = function(i) { - var arg = _arguments[i]; - console.log(function() { - return arg; - }()); - }; - for(var i = 0; i < arguments.length; i++)_loop(i); - } - " - ); - - test!( - ::swc_ecma_parser::Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - arguments_loop_member, - " - function test(a) { - for (var i = 0; i < a.arguments.length; i++) { - var arg = a.arguments[i]; - console.log((() => arg)()); - } - } - ", - " - function test(a) { - var _loop = function(i) { - var arg = a.arguments[i]; - console.log(function() { - return arg; - }()); - }; - for(var i = 0; i < a.arguments.length; i++)_loop(i); - } - " - ); - - test!( - ::swc_ecma_parser::Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - arguments_arrow, - " - function test() { - for (var i = 0; i < arguments.length; i++) { - console.log((() => arguments[i])()); - } - } - ", - " - function test() { - var _this = this, _arguments = arguments, _loop = function(i) { - console.log((function(_arguments1) { - return _arguments1[i]; - }).bind(_this, _arguments)()); - }; - for(var i = 0; i < arguments.length; i++)_loop(i); - } - " - ); - - test!( - ::swc_ecma_parser::Syntax::default(), - |Tester { comments, .. }| { - let mark = Mark::fresh(Mark::root()); - es2015::es2015( - mark, - Some(comments.clone()), - es2015::Config { - ..Default::default() - }, - ) - }, - arguments_function, - " - function test() { - for (var i = 0; i < arguments.length; i++) { - console.log((function () { return arguments[i] })()); - } - } - ", - " - function test() { - var _loop = function(i) { - console.log(function() { - return arguments[i]; - }()); - }; - for(var i = 0; i < arguments.length; i++)_loop(i); - } - " - ); -} diff --git a/ecmascript/transforms/compat/src/es2015/regenerator/hoist.rs b/ecmascript/transforms/compat/src/es2015/regenerator/hoist.rs index a805b5d8dc0..633a4f63696 100644 --- a/ecmascript/transforms/compat/src/es2015/regenerator/hoist.rs +++ b/ecmascript/transforms/compat/src/es2015/regenerator/hoist.rs @@ -60,6 +60,11 @@ impl Hoister { impl Fold for Hoister { noop_fold_type!(); + /// Noop + fn fold_function(&mut self, n: Function) -> Function { + n + } + fn fold_expr(&mut self, e: Expr) -> Expr { let e = e.fold_children_with(self); diff --git a/ecmascript/transforms/compat/src/es2015/regenerator/mod.rs b/ecmascript/transforms/compat/src/es2015/regenerator/mod.rs index d135273892f..a57490f0ad4 100644 --- a/ecmascript/transforms/compat/src/es2015/regenerator/mod.rs +++ b/ecmascript/transforms/compat/src/es2015/regenerator/mod.rs @@ -1,5 +1,5 @@ use self::{case::CaseHandler, hoist::hoist}; -use std::mem::replace; +use std::mem::take; use swc_atoms::js_word; use swc_common::{Mark, Spanned, DUMMY_SP}; use swc_ecma_ast::*; @@ -78,7 +78,7 @@ impl Regenerator { span: DUMMY_SP, kind: VarDeclKind::Var, declare: false, - decls: replace(&mut self.top_level_vars, Default::default()), + decls: take(&mut self.top_level_vars), }))), ); } @@ -411,7 +411,7 @@ impl Regenerator { buf.push(Stmt::Decl(Decl::Var(VarDecl { span: DUMMY_SP, kind: VarDeclKind::Var, - decls: replace(&mut self.outer_fn_vars, Default::default()), + decls: take(&mut self.outer_fn_vars), declare: false, }))); } diff --git a/ecmascript/transforms/compat/tests/es2015_block_scoping.rs b/ecmascript/transforms/compat/tests/es2015_block_scoping.rs new file mode 100644 index 00000000000..960c6c8d5ef --- /dev/null +++ b/ecmascript/transforms/compat/tests/es2015_block_scoping.rs @@ -0,0 +1,885 @@ +use swc_common::{chain, Mark}; +use swc_ecma_parser::Syntax; +use swc_ecma_transforms_compat::es2015::block_scoping; +use swc_ecma_transforms_compat::{es2015, es2015::for_of::for_of, es2017::async_to_generator}; +use swc_ecma_transforms_testing::{test, test_exec, Tester}; + +test!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + for_loop, + "for (const key in obj) { + const bar = obj[key]; + + let qux; + let fog; + + if (Array.isArray(bar)) { + qux = bar[0]; + fog = bar[1]; + } else { + qux = bar; + } + + baz(key, qux, fog); + }", + "for (var key in obj) { + var bar = obj[key]; + + var qux = void 0; + var fog = void 0; + + if (Array.isArray(bar)) { + qux = bar[0]; + fog = bar[1]; + } else { + qux = bar; + } + + baz(key, qux, fog); + }" +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + for_let_loop, + "let functions = []; +for (let i = 0; i < 10; i++) { + functions.push(function() { + console.log(i); + }); +} +functions[0](); +functions[7]();", + " +var _loop = function(i) { + functions.push(function() { + console.log(i); + }); +}; +var functions = []; +for(var i = 0; i < 10; i++)_loop(i); +functions[0](); +functions[7](); +" +); + +test_exec!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + for_let_loop_exec, + "let functions = []; +for (let i = 0; i < 10; i++) { + functions.push(function() { + return i; + }); +} +expect(functions[0]()).toBe(0); +expect(functions[7]()).toBe(7); +" +); + +test_exec!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + for_let_of_exec, + "let functions = []; +for (let i of [1, 3, 5, 7, 9]) { + functions.push(function() { + return i; + }); +} +expect(functions[0]()).toBe(1); +expect(functions[1]()).toBe(3); +" +); + +test_exec!( + ::swc_ecma_parser::Syntax::default(), + |_| chain!(for_of(Default::default()), block_scoping()), + issue_609_1, + "let functions = []; +for (let i of [1, 3, 5, 7, 9]) { + functions.push(function() { + return i; + }); +} +expect(functions[0]()).toBe(1); +expect(functions[1]()).toBe(3); +" +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + issue_662, + "function foo(parts) { + let match = null; + + for (let i = 1; i >= 0; i--) { + for (let j = 0; j >= 0; j--) { + match = parts[i][j]; + + if (match) { + break; + } + } + + if (match) { + break; + } + } + + return match; +} + +foo();", + "function foo(parts) { + var match = null; + + for (var i = 1; i >= 0; i--) { + for (var j = 0; j >= 0; j--) { + match = parts[i][j]; + + if (match) { + break; + } + } + + if (match) { + break; + } + } + + return match; +} + +foo();" +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + issue_686, + "module.exports = function(values) { + var vars = []; + var elem = null, name, val; + for (var i = 0; i < this.elements.length; i++) { + elem = this.elements[i]; + name = elem.name; + if (!name) continue; + val = values[name]; + if (val == null) val = ''; + switch (elem.type) { + case 'submit': + break; + case 'radio': + case 'checkbox': + elem.checked = val.some(function(str) { + return str.toString() == elem.value; + }); + break; + case 'select-multiple': + elem.fill(val); + break; + case 'textarea': + elem.innerText = val; + break; + case 'hidden': + break; + default: + if (elem.fill) { + elem.fill(val); + } else { + elem.value = val; + } + break; + } + } + return vars; + };", + " + module.exports = function(values) { + var _this = this, _loop = function(i) { + elem = _this.elements[i]; + name = elem.name; + if (!name) return 'continue'; + val = values[name]; + if (val == null) val = ''; + switch(elem.type){ + case 'submit': + break; + case 'radio': + case 'checkbox': + elem.checked = val.some(function(str) { + return str.toString() == elem.value; + }); + break; + case 'select-multiple': + elem.fill(val); + break; + case 'textarea': + elem.innerText = val; + break; + case 'hidden': + break; + default: + if (elem.fill) { + elem.fill(val); + } else { + elem.value = val; + } + break; + } + }; + var vars = []; + var elem = null, name, val; + for(var i = 0; i < this.elements.length; i++){ + var _ret = _loop(i); + if (_ret === 'continue') continue; + } + return vars; + }; + " +); + +test_exec!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + issue_723_1, + "function foo() { + const lod = { 0: { mig: 'bana' }}; + + for (let i = 0; i < 1; i++) { + const { mig } = lod[i]; + + return false; + + (zap) => zap === mig; + } + + return true; +} +expect(foo()).toBe(false); +" +); + +test_exec!( + ::swc_ecma_parser::Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + issue_723_2, + "function foo() { + const lod = { 0: { mig: 'bana' }}; + + for (let i = 0; i < 1; i++) { + const { mig } = lod[i]; + + return false; + + (zap) => zap === mig; + } + + return true; +} +expect(foo()).toBe(false); +" +); + +test!( + Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + issue_1022_1, + " + for (let i = 0; i < 5; i++) { + console.log(i++, [2].every(x => x != i)) + } + ", + r#" + var _loop = function(i1) { + console.log(i1++, [ + 2 + ].every(function(x) { + return x != i1; + })); + i = i1, void 0; + }; + for(var i = 0; i < 5; i++)_loop(i); + "# +); + +test!( + Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + issue_1022_2, + " + for (let i = 0; i < 5; i++) { + console.log(i++, [2].every(x => x != i)) + if (i % 2 === 0) continue + } + ", + r#" + var _loop = function(i1) { + console.log(i1++, [ + 2 + ].every(function(x) { + return x != i1; + })); + if (i1 % 2 === 0) return i = i1, "continue"; + i = i1, void 0; + }; + for(var i = 0; i < 5; i++){ + var _ret = _loop(i); + if (_ret === "continue") continue; + } + "# +); + +test!( + Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + issue_1022_3, + " + for (let i = 0; i < 5; i++) { + console.log(i++, [2].every(x => x != i)) + if (i % 2 === 0) break + } + ", + r#" + var _loop = function(i1) { + console.log(i1++, [ + 2 + ].every(function(x) { + return x != i1; + })); + if (i1 % 2 === 0) return i = i1, "break"; + i = i1, void 0; + }; + for(var i = 0; i < 5; i++){ + var _ret = _loop(i); + if (_ret === "break") break; + } + "# +); + +test!( + Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + issue_1021_1, + " + class C { + m() { + for (let x = 0; x < 10; x++) console.log(this, y => y != x) + } + } + ", + r#" + var C = function() { + "use strict"; + function C() { + _classCallCheck(this, C); + } + _createClass(C, [ + { + key: "m", + value: function m() { + var _this = this, _loop = function(x) { + console.log(_this, function(y) { + return y != x; + }); + }; + for(var x = 0; x < 10; x++)_loop(x); + } + } + ]); + return C; + }(); + "# +); + +test!( + Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + issue_1036_1, + " + async function foo() { + await Promise.all([[1], [2], [3]].map( + async ([a]) => Promise.resolve().then(() => a * 2)) + ) + } + ", + " + async function foo() { + await Promise.all([ + [ + 1 + ], + [ + 2 + ], + [ + 3 + ] + ].map(async function(param) { + var _param = _slicedToArray(param, 1), a = _param[0]; + return Promise.resolve().then(function() { + return a * 2; + }); + })); + } + " +); + +test!( + Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + chain!( + async_to_generator(), + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + ) + }, + issue_1036_2, + " + async function foo() { + await Promise.all([[1], [2], [3]].map( + async ([a]) => Promise.resolve().then(() => a * 2)) + ) + } + ", + r#" + var regeneratorRuntime = require("regenerator-runtime"); + var _marked = regeneratorRuntime.mark(_foo); + function _foo() { + _foo = _asyncToGenerator(regeneratorRuntime.mark(function _callee() { + return regeneratorRuntime.wrap(function _callee$(_ctx) { + while(1)switch(_ctx.prev = _ctx.next){ + case 0: + _ctx.next = 2; + return Promise.all([ + [ + 1 + ], + [ + 2 + ], + [ + 3 + ] + ].map(_asyncToGenerator(regeneratorRuntime.mark(function _callee1(param) { + var _param = _slicedToArray(param, 1), a = _param[0]; + return regeneratorRuntime.wrap(function _callee$1(_ctx1) { + while(1)switch(_ctx1.prev = _ctx1.next){ + case 0: + return _ctx1.abrupt("return", Promise.resolve().then(function() { + return a * 2; + })); + case 1: + case "end": + return _ctx1.stop(); + } + }, _callee1); + })))); + case 2: + case "end": + return _ctx.stop(); + } + }, _callee); + })); + return _foo.apply(this, arguments); + } + function foo() { + return _foo.apply(this, arguments); + } + + "# +); + +test_exec!( + Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + chain!( + async_to_generator(), + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + ) + }, + issue_1036_3, + " + const x = async function() { + return await Promise.all([[1], [2], [3]].map( + async ([a]) => Promise.resolve().then(() => a * 2)) + ) + }; + return x().then(x => { + expect(x).toEqual([2, 4, 6]) + }) + " +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + issue_1231_1, + " + function combineOverlappingMatches(matches) { + let hasOverlaps = false + + for (let i = matches.length - 1; i >= 0; i--) { + let currentMatch = matches[i] + let overlap = matches.find(match => { + return match !== currentMatch && match.itemsType === currentMatch.itemsType + }) + + if (overlap) { + hasOverlaps = true + matches.splice(i, 1) + } + } + + if (hasOverlaps) { + combineOverlappingMatches(matches) + } + } + + combineOverlappingMatches([1]) + ", + " + function combineOverlappingMatches(matches) { + var hasOverlaps = false; + for(var i = matches.length - 1; i >= 0; i--){ + var currentMatch = matches[i]; + var overlap = matches.find((match)=>{ + return match !== currentMatch && match.itemsType === currentMatch.itemsType; + }); + if (overlap) { + hasOverlaps = true; + matches.splice(i, 1); + } + } + if (hasOverlaps) { + combineOverlappingMatches(matches); + } + } + combineOverlappingMatches([ + 1 + ]); + " +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + issue_1415_1, + " + export function test(items) { + const infoMap = new WeakMap(); + for (let i = 0; i < items.length; i += 1) { + const item = items[i]; + let info; + switch (item.type) { + case 'branch1': + info = item.method1(); + break; + case 'branch2': + info = item.method2(); + break; + case 'branch3': + info = item.method3( + Object.fromEntries( + item.subItems.map((t) => [item.alias ?? t.name, getInfo(t)]) + ) + ); + break; + default: + throw new Error('boom'); + } + infoMap.set(item, info); // important + } + + function getInfo(item) { + if (!infoMap.has(item)) { + throw new Error('no info yet'); + } + return infoMap.get(item); + } + } + ", + " + export function test(items) { + var infoMap = new WeakMap(); + for(var i = 0; i < items.length; i += 1){ + var item = items[i]; + var info = void 0; + switch(item.type){ + case 'branch1': + info = item.method1(); + break; + case 'branch2': + info = item.method2(); + break; + case 'branch3': + info = item.method3(Object.fromEntries(item.subItems.map((t)=>[ + item.alias ?? t.name, + getInfo(t) + ] + ))); + break; + default: + throw new Error('boom'); + } + infoMap.set(item, info); + } + function getInfo(item) { + if (!infoMap.has(item)) { + throw new Error('no info yet'); + } + return infoMap.get(item); + } + } + " +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + arguments_loop, + " + function test() { + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + console.log((() => arg)()); + } + } + ", + " + function test() { + var _arguments = arguments, _loop = function(i) { + var arg = _arguments[i]; + console.log(function() { + return arg; + }()); + }; + for(var i = 0; i < arguments.length; i++)_loop(i); + } + " +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + arguments_loop_member, + " + function test(a) { + for (var i = 0; i < a.arguments.length; i++) { + var arg = a.arguments[i]; + console.log((() => arg)()); + } + } + ", + " + function test(a) { + var _loop = function(i) { + var arg = a.arguments[i]; + console.log(function() { + return arg; + }()); + }; + for(var i = 0; i < a.arguments.length; i++)_loop(i); + } + " +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + arguments_arrow, + " + function test() { + for (var i = 0; i < arguments.length; i++) { + console.log((() => arguments[i])()); + } + } + ", + " + function test() { + var _this = this, _arguments = arguments, _loop = function(i) { + console.log((function(_arguments1) { + return _arguments1[i]; + }).bind(_this, _arguments)()); + }; + for(var i = 0; i < arguments.length; i++)_loop(i); + } + " +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |Tester { comments, .. }| { + let mark = Mark::fresh(Mark::root()); + es2015::es2015( + mark, + Some(comments.clone()), + es2015::Config { + ..Default::default() + }, + ) + }, + arguments_function, + " + function test() { + for (var i = 0; i < arguments.length; i++) { + console.log((function () { return arguments[i] })()); + } + } + ", + " + function test() { + var _loop = function(i) { + console.log(function() { + return arguments[i]; + }()); + }; + for(var i = 0; i < arguments.length; i++)_loop(i); + } + " +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + issue_1462_1, + " + export default function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + + ownKeys.forEach(function (key) { + defineProperty(target, key, source[key]); + }); + } + + return target; + } + ", + " + export default function _objectSpread(target) { + var _arguments = arguments, _loop = function(i) { + var source = _arguments[i] != null ? _arguments[i] : { + }; + var ownKeys = Object.keys(source); + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) \ + { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + ownKeys.forEach(function(key) { + defineProperty(target, key, source[key]); + }); + }; + for(var i = 1; i < arguments.length; i++)_loop(i); + return target; + } + " +); diff --git a/ecmascript/transforms/typescript/Cargo.toml b/ecmascript/transforms/typescript/Cargo.toml index 730326e3a33..63a354549d3 100644 --- a/ecmascript/transforms/typescript/Cargo.toml +++ b/ecmascript/transforms/typescript/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "Apache-2.0/MIT" name = "swc_ecma_transforms_typescript" repository = "https://github.com/swc-project/swc.git" -version = "0.19.1" +version = "0.19.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/ecmascript/transforms/typescript/src/strip.rs b/ecmascript/transforms/typescript/src/strip.rs index 13e93b3ccfc..7540b368e99 100644 --- a/ecmascript/transforms/typescript/src/strip.rs +++ b/ecmascript/transforms/typescript/src/strip.rs @@ -1271,9 +1271,11 @@ impl VisitMut for Strip { fn visit_mut_block_stmt_or_expr(&mut self, n: &mut BlockStmtOrExpr) { match n { BlockStmtOrExpr::Expr(expr) if expr.is_class() => { + let span = expr.span(); + let ClassExpr { ident, class } = expr.take().class().unwrap(); let ident = ident.unwrap_or_else(|| private_ident!("_class")); - let (decl, extra_exprs) = self.fold_class_as_decl(ident, class); + let (decl, extra_exprs) = self.fold_class_as_decl(ident.clone(), class); let mut stmts = vec![]; stmts.push(Stmt::Decl(decl)); stmts.extend( @@ -1282,6 +1284,10 @@ impl VisitMut for Strip { .map(|e| e.into_stmt()) .collect::>(), ); + stmts.push(Stmt::Return(ReturnStmt { + span, + arg: Some(Box::new(Expr::Ident(ident))), + })); *n = BlockStmtOrExpr::BlockStmt(BlockStmt { span: n.span(), stmts, diff --git a/tests/fixture/issue-1505/case1/output/index.ts b/tests/fixture/issue-1505/case1/output/index.ts index badaf0cc18f..becbb7a134d 100644 --- a/tests/fixture/issue-1505/case1/output/index.ts +++ b/tests/fixture/issue-1505/case1/output/index.ts @@ -59,4 +59,5 @@ export var fn = function() { return _class; }(MyClass); _class.x = 5; + return _class; }; diff --git a/tests/fixture/issue-1505/case2/output/index.ts b/tests/fixture/issue-1505/case2/output/index.ts index 79e91f1836a..6c5566d7d21 100644 --- a/tests/fixture/issue-1505/case2/output/index.ts +++ b/tests/fixture/issue-1505/case2/output/index.ts @@ -58,4 +58,5 @@ export var fn = function() { } return _class; }(MyClass); + return _class; }; diff --git a/tests/fixture/issue-1505/case3/output/index.tsx b/tests/fixture/issue-1505/case3/output/index.tsx index 3992197879b..21f81f78258 100644 --- a/tests/fixture/issue-1505/case3/output/index.tsx +++ b/tests/fixture/issue-1505/case3/output/index.tsx @@ -63,4 +63,5 @@ var withTeamsForUser = function(_WrappedComponent) { return _class; }(Component); _class.displayName = "x"; + return _class; }; diff --git a/tests/fixture/issue-1505/case5/output/index.tsx b/tests/fixture/issue-1505/case5/output/index.tsx index 890ef1e1ed6..f457c667914 100644 --- a/tests/fixture/issue-1505/case5/output/index.tsx +++ b/tests/fixture/issue-1505/case5/output/index.tsx @@ -55,4 +55,5 @@ var withTeamsForUser = function() { return _class; }(Component); _class.displayName = "x"; + return _class; }; diff --git a/tests/fixture/issue-1505/tsx-default/output/index.ts b/tests/fixture/issue-1505/tsx-default/output/index.ts index 79e91f1836a..6c5566d7d21 100644 --- a/tests/fixture/issue-1505/tsx-default/output/index.ts +++ b/tests/fixture/issue-1505/tsx-default/output/index.ts @@ -58,4 +58,5 @@ export var fn = function() { } return _class; }(MyClass); + return _class; }; diff --git a/tests/fixture/issue-1718/case1/input/.swcrc b/tests/fixture/issue-1718/case1/input/.swcrc new file mode 100644 index 00000000000..097ae6ef11e --- /dev/null +++ b/tests/fixture/issue-1718/case1/input/.swcrc @@ -0,0 +1,7 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript" + } + } +} diff --git a/tests/fixture/issue-1718/case1/input/index.ts b/tests/fixture/issue-1718/case1/input/index.ts new file mode 100644 index 00000000000..64d0dd20007 --- /dev/null +++ b/tests/fixture/issue-1718/case1/input/index.ts @@ -0,0 +1,13 @@ +async function scanUser(groups: { users: number[] }[]) { + await Promise.all(groups.map(async ({ users }) => { + for (const user of users) { + console.log('user', user) + await new Promise(resolve => setTimeout(resolve, 30)) + } + })) +} + +scanUser([ + { users: [1, 2, 3, 4, 5] }, + { users: [11, 12, 13, 14, 15] }, +]) \ No newline at end of file diff --git a/tests/fixture/issue-1718/case1/output/index.ts b/tests/fixture/issue-1718/case1/output/index.ts new file mode 100644 index 00000000000..6889443a913 --- /dev/null +++ b/tests/fixture/issue-1718/case1/output/index.ts @@ -0,0 +1,136 @@ +function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + if (info.done) { + resolve(value); + } else { + Promise.resolve(value).then(_next, _throw); + } +} +function _asyncToGenerator(fn) { + return function() { + var self = this, args = arguments; + return new Promise(function(resolve, reject) { + var gen = fn.apply(self, args); + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); + } + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); + } + _next(undefined); + }); + }; +} +var regeneratorRuntime = require("regenerator-runtime"); +var _marked = regeneratorRuntime.mark(_scanUser); +function _scanUser() { + _scanUser = _asyncToGenerator(regeneratorRuntime.mark(function _callee(groups) { + return regeneratorRuntime.wrap(function _callee$(_ctx) { + while(1)switch(_ctx.prev = _ctx.next){ + case 0: + _ctx.next = 2; + return Promise.all(groups.map(_asyncToGenerator(regeneratorRuntime.mark(function _callee1(param) { + var users = param.users; + var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, user; + return regeneratorRuntime.wrap(function _callee$1(_ctx1) { + while(1)switch(_ctx1.prev = _ctx1.next){ + case 0: + _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined; + _ctx1.prev = 1; + _iterator = users[Symbol.iterator](); + case 3: + if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { + _ctx1.next = 11; + break; + } + user = _step.value; + console.log('user', user); + _ctx1.next = 8; + return new Promise(function(resolve) { + return setTimeout(resolve, 30); + }); + case 8: + _iteratorNormalCompletion = true; + _ctx1.next = 3; + break; + case 11: + _ctx1.next = 17; + break; + case 13: + _ctx1.prev = 13; + _ctx1.t0 = _ctx1["catch"](1); + _didIteratorError = true; + _iteratorError = _ctx1.t0; + case 17: + _ctx1.prev = 17; + _ctx1.prev = 18; + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + case 20: + _ctx1.prev = 20; + if (!_didIteratorError) { + _ctx1.next = 23; + break; + } + throw _iteratorError; + case 23: + return _ctx1.finish(20); + case 24: + return _ctx1.finish(17); + case 25: + case "end": + return _ctx1.stop(); + } + }, _callee1, null, [ + [ + 18, + , + 20, + 24 + ], + [ + 1, + 13, + 17, + 25 + ] + ]); + })))); + case 2: + case "end": + return _ctx.stop(); + } + }, _callee); + })); + return _scanUser.apply(this, arguments); +} +function scanUser(groups) { + return _scanUser.apply(this, arguments); +} +scanUser([ + { + users: [ + 1, + 2, + 3, + 4, + 5 + ] + }, + { + users: [ + 11, + 12, + 13, + 14, + 15 + ] + }, +]); diff --git a/tests/fixture/issue-1718/case2/input/.swcrc b/tests/fixture/issue-1718/case2/input/.swcrc new file mode 100644 index 00000000000..7ab90c3cb5d --- /dev/null +++ b/tests/fixture/issue-1718/case2/input/.swcrc @@ -0,0 +1,8 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript" + }, + "target": "es2016" + } +} diff --git a/tests/fixture/issue-1718/case2/input/index.ts b/tests/fixture/issue-1718/case2/input/index.ts new file mode 100644 index 00000000000..64d0dd20007 --- /dev/null +++ b/tests/fixture/issue-1718/case2/input/index.ts @@ -0,0 +1,13 @@ +async function scanUser(groups: { users: number[] }[]) { + await Promise.all(groups.map(async ({ users }) => { + for (const user of users) { + console.log('user', user) + await new Promise(resolve => setTimeout(resolve, 30)) + } + })) +} + +scanUser([ + { users: [1, 2, 3, 4, 5] }, + { users: [11, 12, 13, 14, 15] }, +]) \ No newline at end of file diff --git a/tests/fixture/issue-1718/case2/output/index.ts b/tests/fixture/issue-1718/case2/output/index.ts new file mode 100644 index 00000000000..f4c2a5ec396 --- /dev/null +++ b/tests/fixture/issue-1718/case2/output/index.ts @@ -0,0 +1,64 @@ +function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + if (info.done) { + resolve(value); + } else { + Promise.resolve(value).then(_next, _throw); + } +} +function _asyncToGenerator(fn) { + return function() { + var self = this, args = arguments; + return new Promise(function(resolve, reject) { + var gen = fn.apply(self, args); + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); + } + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); + } + _next(undefined); + }); + }; +} +function _scanUser() { + _scanUser = _asyncToGenerator(function*(groups) { + yield Promise.all(groups.map(_asyncToGenerator(function*({ users }) { + for (const user of users){ + console.log('user', user); + yield new Promise((resolve)=>setTimeout(resolve, 30) + ); + } + }))); + }); + return _scanUser.apply(this, arguments); +} +function scanUser(groups) { + return _scanUser.apply(this, arguments); +} +scanUser([ + { + users: [ + 1, + 2, + 3, + 4, + 5 + ] + }, + { + users: [ + 11, + 12, + 13, + 14, + 15 + ] + }, +]); diff --git a/tests/fixture/issue-1729/case1/input/index.ts b/tests/fixture/issue-1729/case1/input/index.ts new file mode 100644 index 00000000000..aac8db7d64e --- /dev/null +++ b/tests/fixture/issue-1729/case1/input/index.ts @@ -0,0 +1,14 @@ +function createConstructor(callback) { + let klass + return (...args) => { + if (klass === undefined) { + klass = callback() + } + return new klass(...args) + } +} + +const constructor = createConstructor(() => class { +}) + +console.log(constructor()) \ No newline at end of file diff --git a/tests/fixture/issue-1729/case1/output/index.ts b/tests/fixture/issue-1729/case1/output/index.ts new file mode 100644 index 00000000000..08fb2500559 --- /dev/null +++ b/tests/fixture/issue-1729/case1/output/index.ts @@ -0,0 +1,78 @@ +function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for(var i = 0, arr2 = new Array(arr.length); i < arr.length; i++){ + arr2[i] = arr[i]; + } + return arr2; + } +} +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} +function isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + try { + Date.prototype.toString.call(Reflect.construct(Date, [], function() { + })); + return true; + } catch (e) { + return false; + } +} +function _construct(Parent, args, Class) { + if (isNativeReflectConstruct()) { + _construct = Reflect.construct; + } else { + _construct = function _construct(Parent, args, Class) { + var a = [ + null + ]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + return _construct.apply(null, arguments); +} +function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); +} +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); +} +function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + return _setPrototypeOf(o, p); +} +function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); +} +function createConstructor(callback) { + var klass; + return function() { + for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){ + args[_key] = arguments[_key]; + } + if (klass === undefined) { + klass = callback(); + } + return _construct(klass, _toConsumableArray(args)); + }; +} +var constructor = createConstructor(function() { + var _class = function _class() { + "use strict"; + _classCallCheck(this, _class); + }; + return _class; +}); +console.log(constructor()); diff --git a/tests/fixture/issue-1729/case2/input/.swcrc b/tests/fixture/issue-1729/case2/input/.swcrc new file mode 100644 index 00000000000..a6bc67beede --- /dev/null +++ b/tests/fixture/issue-1729/case2/input/.swcrc @@ -0,0 +1,5 @@ +{ + "jsc": { + "target": "es2016" + } +} diff --git a/tests/fixture/issue-1729/case2/input/index.ts b/tests/fixture/issue-1729/case2/input/index.ts new file mode 100644 index 00000000000..aac8db7d64e --- /dev/null +++ b/tests/fixture/issue-1729/case2/input/index.ts @@ -0,0 +1,14 @@ +function createConstructor(callback) { + let klass + return (...args) => { + if (klass === undefined) { + klass = callback() + } + return new klass(...args) + } +} + +const constructor = createConstructor(() => class { +}) + +console.log(constructor()) \ No newline at end of file diff --git a/tests/fixture/issue-1729/case2/output/index.ts b/tests/fixture/issue-1729/case2/output/index.ts new file mode 100644 index 00000000000..f9ad4d6b99c --- /dev/null +++ b/tests/fixture/issue-1729/case2/output/index.ts @@ -0,0 +1,13 @@ +function createConstructor(callback) { + let klass; + return (...args)=>{ + if (klass === undefined) { + klass = callback(); + } + return new klass(...args); + }; +} +const constructor = createConstructor(()=>class { + } +); +console.log(constructor()); diff --git a/tests/fixture/issue-1729/case3/input/.swcrc b/tests/fixture/issue-1729/case3/input/.swcrc new file mode 100644 index 00000000000..2b745723f27 --- /dev/null +++ b/tests/fixture/issue-1729/case3/input/.swcrc @@ -0,0 +1,5 @@ +{ + "jsc": { + "target": "es2020" + } +} diff --git a/tests/fixture/issue-1729/case3/input/index.ts b/tests/fixture/issue-1729/case3/input/index.ts new file mode 100644 index 00000000000..aac8db7d64e --- /dev/null +++ b/tests/fixture/issue-1729/case3/input/index.ts @@ -0,0 +1,14 @@ +function createConstructor(callback) { + let klass + return (...args) => { + if (klass === undefined) { + klass = callback() + } + return new klass(...args) + } +} + +const constructor = createConstructor(() => class { +}) + +console.log(constructor()) \ No newline at end of file diff --git a/tests/fixture/issue-1729/case3/output/index.ts b/tests/fixture/issue-1729/case3/output/index.ts new file mode 100644 index 00000000000..f9ad4d6b99c --- /dev/null +++ b/tests/fixture/issue-1729/case3/output/index.ts @@ -0,0 +1,13 @@ +function createConstructor(callback) { + let klass; + return (...args)=>{ + if (klass === undefined) { + klass = callback(); + } + return new klass(...args); + }; +} +const constructor = createConstructor(()=>class { + } +); +console.log(constructor()); diff --git a/tests/fixture/issue-1729/case4/input/.swcrc b/tests/fixture/issue-1729/case4/input/.swcrc new file mode 100644 index 00000000000..982f2795781 --- /dev/null +++ b/tests/fixture/issue-1729/case4/input/.swcrc @@ -0,0 +1,8 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript" + }, + "target": "es2020" + } +} diff --git a/tests/fixture/issue-1729/case4/input/index.ts b/tests/fixture/issue-1729/case4/input/index.ts new file mode 100644 index 00000000000..aac8db7d64e --- /dev/null +++ b/tests/fixture/issue-1729/case4/input/index.ts @@ -0,0 +1,14 @@ +function createConstructor(callback) { + let klass + return (...args) => { + if (klass === undefined) { + klass = callback() + } + return new klass(...args) + } +} + +const constructor = createConstructor(() => class { +}) + +console.log(constructor()) \ No newline at end of file diff --git a/tests/fixture/issue-1729/case4/output/index.ts b/tests/fixture/issue-1729/case4/output/index.ts new file mode 100644 index 00000000000..27235c024c2 --- /dev/null +++ b/tests/fixture/issue-1729/case4/output/index.ts @@ -0,0 +1,15 @@ +function createConstructor(callback) { + let klass; + return (...args)=>{ + if (klass === undefined) { + klass = callback(); + } + return new klass(...args); + }; +} +const constructor = createConstructor(()=>{ + class _class { + } + return _class; +}); +console.log(constructor());