From c78baef2ccecaca76ca973f57c834e00a25154bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Sun, 22 Aug 2021 15:56:49 +0900 Subject: [PATCH] fix(es/transforms/compat): Implement `new.tartet` (#2129) swc_ecma_transforms_compat: - Handle `new.target`. (#1179) --- Cargo.lock | 4 +- ecmascript/parser/Cargo.toml | 2 +- ecmascript/transforms/compat/Cargo.toml | 2 +- .../transforms/compat/src/es2015/mod.rs | 1 + .../compat/src/es2015/new_target.rs | 257 ++++++++++++++++++ .../compat/tests/es2015_new_target.rs | 16 ++ .../new-target/exec/class-extended/exec.js | 22 ++ .../fixture/new-target/exec/class/exec.js | 12 + .../exec/function-class-extended/exec.js | 16 ++ .../new-target/exec/function-class/exec.js | 10 + .../fixture/new-target/exec/function/exec.js | 12 + .../new-target/exec/reflect-class/exec.js | 27 ++ .../new-target/exec/reflect-function/exec.js | 40 +++ .../general/.class-properties-loose/exec.js | 9 + .../general/.class-properties-loose/input.js | 20 ++ .../.class-properties-loose/options.json | 7 + .../general/.class-properties-loose/output.js | 35 +++ .../general/.class-properties/exec.js | 9 + .../general/.class-properties/input.js | 20 ++ .../general/.class-properties/options.json | 7 + .../general/.class-properties/output.js | 33 +++ .../fixture/new-target/general/arrow/input.js | 13 + .../new-target/general/arrow/options.json | 3 + .../new-target/general/arrow/output.js | 14 + .../fixture/new-target/general/class/input.js | 9 + .../new-target/general/class/output.js | 8 + .../general/extended-class/input.js | 20 ++ .../general/extended-class/output.js | 17 ++ .../new-target/general/function/input.js | 11 + .../new-target/general/function/output.js | 9 + .../new-target/general/object/input.js | 11 + .../new-target/general/object/output.js | 9 + ecmascript/transforms/testing/src/lib.rs | 5 +- node/bundler/src/loaders/swc.rs | 2 +- 34 files changed, 683 insertions(+), 9 deletions(-) create mode 100644 ecmascript/transforms/compat/src/es2015/new_target.rs create mode 100644 ecmascript/transforms/compat/tests/es2015_new_target.rs create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/exec/class-extended/exec.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/exec/class/exec.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/exec/function-class-extended/exec.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/exec/function-class/exec.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/exec/function/exec.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/exec/reflect-class/exec.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/exec/reflect-function/exec.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/exec.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/input.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/options.json create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/output.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/exec.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/input.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/options.json create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/output.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/input.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/options.json create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/output.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/class/input.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/class/output.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/extended-class/input.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/extended-class/output.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/function/input.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/function/output.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/object/input.js create mode 100644 ecmascript/transforms/compat/tests/fixture/new-target/general/object/output.js diff --git a/Cargo.lock b/Cargo.lock index 5644378faab..473e26c4bc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2491,7 +2491,7 @@ dependencies = [ [[package]] name = "swc_ecma_parser" -version = "0.67.0" +version = "0.67.1" dependencies = [ "either", "enum_kind", @@ -2599,7 +2599,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_compat" -version = "0.30.0" +version = "0.30.1" dependencies = [ "arrayvec", "fxhash", diff --git a/ecmascript/parser/Cargo.toml b/ecmascript/parser/Cargo.toml index 309148a21b1..b2f02410091 100644 --- a/ecmascript/parser/Cargo.toml +++ b/ecmascript/parser/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "examples/**/*.rs"] license = "Apache-2.0/MIT" name = "swc_ecma_parser" repository = "https://github.com/swc-project/swc.git" -version = "0.67.0" +version = "0.67.1" [package.metadata.docs.rs] all-features = true diff --git a/ecmascript/transforms/compat/Cargo.toml b/ecmascript/transforms/compat/Cargo.toml index f34b897c68f..57c9fa31fd4 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.30.0" +version = "0.30.1" # 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/mod.rs b/ecmascript/transforms/compat/src/es2015/mod.rs index 7e0418022ae..dde2c74c5c2 100644 --- a/ecmascript/transforms/compat/src/es2015/mod.rs +++ b/ecmascript/transforms/compat/src/es2015/mod.rs @@ -20,6 +20,7 @@ mod duplicate_keys; pub mod for_of; mod function_name; mod instanceof; +pub mod new_target; mod parameters; mod regenerator; mod shorthand_property; diff --git a/ecmascript/transforms/compat/src/es2015/new_target.rs b/ecmascript/transforms/compat/src/es2015/new_target.rs new file mode 100644 index 00000000000..5dd404ea779 --- /dev/null +++ b/ecmascript/transforms/compat/src/es2015/new_target.rs @@ -0,0 +1,257 @@ +use std::borrow::Cow; +use swc_atoms::js_word; +use swc_common::{pass::CompilerPass, DUMMY_SP}; +use swc_ecma_ast::*; +use swc_ecma_transforms_base::perf::Check; +use swc_ecma_transforms_macros::fast_path; +use swc_ecma_utils::{prepend, private_ident, quote_ident, undefined, ExprFactory}; +use swc_ecma_visit::{ + as_folder, noop_visit_mut_type, noop_visit_type, Fold, Node, Visit, VisitMut, VisitMutWith, +}; + +pub fn new_target() -> impl Fold + VisitMut + CompilerPass { + as_folder(NewTarget::default()) +} + +#[derive(Default)] + +struct NewTarget { + cur: Option, + + in_constructor: bool, + in_method: bool, + in_arrow_expr: bool, + + var: Option, +} + +#[fast_path(ShouldWork)] +impl VisitMut for NewTarget { + noop_visit_mut_type!(); + + fn visit_mut_arrow_expr(&mut self, e: &mut ArrowExpr) { + // #[fast_path] ensures that `e` contains new.target + + let old = self.in_arrow_expr; + if self.var.is_none() { + let mut v = Expr::MetaProp(MetaPropExpr { + meta: Ident::new("new".into(), DUMMY_SP), + prop: Ident::new("target".into(), DUMMY_SP), + }); + v.visit_mut_with(self); + self.var.get_or_insert_with(|| VarDeclarator { + span: DUMMY_SP, + name: Pat::Ident(private_ident!("_newtarget").into()), + init: Some(Box::new(v)), + definite: Default::default(), + }); + } + self.in_arrow_expr = true; + e.visit_mut_children_with(self); + + self.in_arrow_expr = old; + } + + fn visit_mut_class_decl(&mut self, class: &mut ClassDecl) { + let old = self.cur.take(); + self.cur = Some(class.ident.clone()); + + class.visit_mut_children_with(self); + + self.cur = old; + } + + fn visit_mut_class_expr(&mut self, class: &mut ClassExpr) { + let old = self.cur.take(); + self.cur = class.ident.clone(); + + class.visit_mut_children_with(self); + + self.cur = old; + } + + fn visit_mut_class_method(&mut self, c: &mut ClassMethod) { + let old = self.in_method; + + self.in_method = true; + + c.visit_mut_children_with(self); + + self.in_method = old; + } + + fn visit_mut_constructor(&mut self, c: &mut Constructor) { + let old = self.in_constructor; + + self.in_constructor = true; + + c.visit_mut_children_with(self); + + self.in_constructor = old; + } + + fn visit_mut_expr(&mut self, e: &mut Expr) { + e.visit_mut_children_with(self); + + match e { + Expr::MetaProp(MetaPropExpr { + meta: + Ident { + sym: js_word!("new"), + .. + }, + prop: + Ident { + sym: js_word!("target"), + .. + }, + }) => { + if self.in_arrow_expr { + *e = Expr::Ident(self.var.as_ref().unwrap().name.clone().ident().unwrap().id); + } else if self.in_method { + *e = *undefined(DUMMY_SP) + } else { + if let Some(cur) = self.cur.clone() { + let c = + ThisExpr { span: DUMMY_SP }.make_member(quote_ident!("constructor")); + + if self.in_constructor { + *e = c; + } else { + // (this instanceof Foo ? this.constructor : void 0) + *e = Expr::Cond(CondExpr { + span: DUMMY_SP, + // this instanceof Foo + test: Box::new(Expr::Bin(BinExpr { + span: DUMMY_SP, + op: op!("instanceof"), + left: Box::new(Expr::This(ThisExpr { span: DUMMY_SP })), + right: Box::new(Expr::Ident(cur)), + })), + // this.constructor + cons: Box::new(c), + // void 0 + alt: undefined(DUMMY_SP), + }); + } + } + } + } + + _ => {} + } + } + + fn visit_mut_fn_decl(&mut self, f: &mut FnDecl) { + // #[fast_path] ensures that `f` contains `new.target`. + + let old = self.cur.take(); + self.cur = Some(f.ident.clone()); + + f.visit_mut_children_with(self); + + self.cur = old; + } + + fn visit_mut_fn_expr(&mut self, f: &mut FnExpr) { + // #[fast_path] ensures that `f` contains `new.target`. + + let i = f + .ident + .get_or_insert_with(|| private_ident!("_target")) + .clone(); + + let old = self.cur.take(); + self.cur = Some(i.clone()); + + f.visit_mut_children_with(self); + + self.cur = old; + } + + fn visit_mut_method_prop(&mut self, m: &mut MethodProp) { + let old = self.in_method; + + self.in_method = true; + + m.visit_mut_children_with(self); + + self.in_method = old; + } + + fn visit_mut_module_items(&mut self, stmts: &mut Vec) { + stmts.visit_mut_children_with(self); + + if let Some(var) = self.var.take() { + prepend( + stmts, + ModuleItem::Stmt(Stmt::Decl(Decl::Var(VarDecl { + span: DUMMY_SP, + kind: VarDeclKind::Var, + declare: false, + decls: vec![var], + }))), + ) + } + } + + fn visit_mut_stmts(&mut self, stmts: &mut Vec) { + stmts.visit_mut_children_with(self); + + if !self.in_arrow_expr { + if let Some(var) = self.var.take() { + prepend( + stmts, + Stmt::Decl(Decl::Var(VarDecl { + span: DUMMY_SP, + kind: VarDeclKind::Var, + declare: false, + decls: vec![var], + })), + ) + } + } + } +} + +impl CompilerPass for NewTarget { + fn name() -> Cow<'static, str> { + Cow::Borrowed("new-target") + } +} + +#[derive(Default)] +struct ShouldWork { + found: bool, +} + +impl Visit for ShouldWork { + noop_visit_type!(); + + fn visit_meta_prop_expr(&mut self, n: &MetaPropExpr, _: &dyn Node) { + match n { + MetaPropExpr { + meta: + Ident { + sym: js_word!("new"), + .. + }, + prop: + Ident { + sym: js_word!("target"), + .. + }, + } => { + self.found = true; + } + + _ => {} + } + } +} + +impl Check for ShouldWork { + fn should_handle(&self) -> bool { + self.found + } +} diff --git a/ecmascript/transforms/compat/tests/es2015_new_target.rs b/ecmascript/transforms/compat/tests/es2015_new_target.rs new file mode 100644 index 00000000000..2bbdc9f4700 --- /dev/null +++ b/ecmascript/transforms/compat/tests/es2015_new_target.rs @@ -0,0 +1,16 @@ +use std::{fs::read_to_string, path::PathBuf}; +use swc_ecma_transforms_compat::es2015::new_target::new_target; +use swc_ecma_transforms_testing::{exec_tr, test_fixture}; + +#[testing::fixture("tests/fixture/new-target/**/exec.js")] +fn exec(input: PathBuf) { + let input = read_to_string(&input).unwrap(); + exec_tr("new-target", Default::default(), |_| new_target(), &input); +} + +#[testing::fixture("tests/fixture/new-target/**/input.js")] +fn fixture(input: PathBuf) { + let dir = input.parent().unwrap(); + let output = dir.join("output.js"); + test_fixture(Default::default(), &|_| new_target(), &input, &output); +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/exec/class-extended/exec.js b/ecmascript/transforms/compat/tests/fixture/new-target/exec/class-extended/exec.js new file mode 100644 index 00000000000..78eb0c33d51 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/exec/class-extended/exec.js @@ -0,0 +1,22 @@ +"use strict"; + +const targets = []; +class Foo { + constructor() { + targets.push(new.target); + } +} + +class Bar extends Foo { + constructor() { + super(); + targets.push(new.target); + } +} + +new Foo; +new Bar; + +expect(targets[0]).toBe(Foo); +expect(targets[1]).toBe(Bar); +expect(targets[2]).toBe(Bar); diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/exec/class/exec.js b/ecmascript/transforms/compat/tests/fixture/new-target/exec/class/exec.js new file mode 100644 index 00000000000..4651c76237f --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/exec/class/exec.js @@ -0,0 +1,12 @@ +"use strict"; + +const targets = []; +class Foo { + constructor() { + targets.push(new.target); + } +} + +new Foo; + +expect(targets[0]).toBe(Foo); diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/exec/function-class-extended/exec.js b/ecmascript/transforms/compat/tests/fixture/new-target/exec/function-class-extended/exec.js new file mode 100644 index 00000000000..87071962cf7 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/exec/function-class-extended/exec.js @@ -0,0 +1,16 @@ +"use strict"; + +const targets = []; +function Foo() { + targets.push(new.target); +} + +function Bar() { + Foo.call(this); +} + +new Foo; +new Bar(); + +expect(targets[0]).toBe(Foo); +expect(targets[1]).toBeUndefined(); diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/exec/function-class/exec.js b/ecmascript/transforms/compat/tests/fixture/new-target/exec/function-class/exec.js new file mode 100644 index 00000000000..f3d6f3066a8 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/exec/function-class/exec.js @@ -0,0 +1,10 @@ +"use strict"; + +const targets = []; +function Foo() { + targets.push(new.target); +} + +new Foo; + +expect(targets[0]).toBe(Foo); diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/exec/function/exec.js b/ecmascript/transforms/compat/tests/fixture/new-target/exec/function/exec.js new file mode 100644 index 00000000000..082aa855052 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/exec/function/exec.js @@ -0,0 +1,12 @@ +"use strict"; + +const targets = []; +function foo() { + targets.push(new.target); +} + +foo(); +foo.call({}); + +expect(targets[0]).toBeUndefined(); +expect(targets[1]).toBeUndefined(); diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/exec/reflect-class/exec.js b/ecmascript/transforms/compat/tests/fixture/new-target/exec/reflect-class/exec.js new file mode 100644 index 00000000000..f7fc3cf03f8 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/exec/reflect-class/exec.js @@ -0,0 +1,27 @@ +const targets = []; +class Foo { + constructor() { + targets.push(new.target); + } +} + +class Bar extends Foo { +} +class Baz { +} + +Reflect.construct(Foo, []); +Reflect.construct(Foo, [], Bar); +Reflect.construct(Bar, []); +Reflect.construct(Bar, [], Baz); +Reflect.construct(Foo, [], Baz); + +expect(targets[0]).toBe(Foo); + +expect(targets[1]).toBe(Bar); + +expect(targets[2]).toBe(Bar); + +expect(targets[3]).toBe(Baz); + +expect(targets[4]).toBe(Baz); diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/exec/reflect-function/exec.js b/ecmascript/transforms/compat/tests/fixture/new-target/exec/reflect-function/exec.js new file mode 100644 index 00000000000..1ed060abd08 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/exec/reflect-function/exec.js @@ -0,0 +1,40 @@ +const targets = []; +function Foo() { + targets.push(new.target); +} + +function Bar() { + Foo.call(this); +} +Bar.prototype = Object.create(Foo.prototype, { + constructor: { + value: Bar, + writable: true, + configurable: true, + } +}); + +function Baz() {} + +Reflect.construct(Foo, []); +Reflect.construct(Foo, [], Bar); +Reflect.construct(Bar, []); +Reflect.construct(Bar, [], Baz); +Reflect.construct(Foo, [], Baz); + +expect(targets[0]).toBe(Foo); + +expect(targets[1]).toBe(Bar); + +expect(() => { + // Wish we could support this... + // Then again, this is what a transformed class does. + expect(targets[2]).toBeUndefined(); +}).toThrow(); + +expect(targets[3]).toBeUndefined(); + +expect(() => { + // Wish we could support this... + expect(targets[4]).toBe(Baz); +}).toThrow(); diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/exec.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/exec.js new file mode 100644 index 00000000000..396babafae9 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/exec.js @@ -0,0 +1,9 @@ +class Foo { + constructor() { + this.Bar = class { + static p = new.target + } + } +} + +expect((new Foo).Bar.p).toBeUndefined() diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/input.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/input.js new file mode 100644 index 00000000000..0045e3f3d0a --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/input.js @@ -0,0 +1,20 @@ +class Foo { + constructor() { + this.Bar = class { + static p = new.target + static p1 = class { constructor() { new.target } } // should not replace + static p2 = new function () { new.target } // should not replace + static p3 = () => { new.target } // should replace + static p4 = function () { new.target } // should not replace + q = new.target // should not replace + } + } + + test = function() { + new.target; + }; + + test2 = () => { + new.target; + } +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/options.json b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/options.json new file mode 100644 index 00000000000..fafe51d4fbf --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + "transform-new-target", + "transform-arrow-functions", + ["proposal-class-properties", { "loose": true }] + ] +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/output.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/output.js new file mode 100644 index 00000000000..a64af0349e5 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties-loose/output.js @@ -0,0 +1,35 @@ +class Foo { + constructor() { + var _newtarget = this.constructor, + _class, + _temp; + + this.test = function _target() { + this instanceof _target ? this.constructor : void 0; + }; + + this.test2 = function () { + _newtarget; + }; + + this.Bar = (_temp = _class = class _target2 { + constructor() { + this.q = this.constructor; + } // should not replace + + + }, _class.p = void 0, _class.p1 = class _target3 { + constructor() { + this.constructor; + } + + }, _class.p2 = new function _target4() { + this instanceof _target4 ? this.constructor : void 0; + }(), _class.p3 = function () { + void 0; + }, _class.p4 = function _target5() { + this instanceof _target5 ? this.constructor : void 0; + }, _temp); + } + +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/exec.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/exec.js new file mode 100644 index 00000000000..396babafae9 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/exec.js @@ -0,0 +1,9 @@ +class Foo { + constructor() { + this.Bar = class { + static p = new.target + } + } +} + +expect((new Foo).Bar.p).toBeUndefined() diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/input.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/input.js new file mode 100644 index 00000000000..0045e3f3d0a --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/input.js @@ -0,0 +1,20 @@ +class Foo { + constructor() { + this.Bar = class { + static p = new.target + static p1 = class { constructor() { new.target } } // should not replace + static p2 = new function () { new.target } // should not replace + static p3 = () => { new.target } // should replace + static p4 = function () { new.target } // should not replace + q = new.target // should not replace + } + } + + test = function() { + new.target; + }; + + test2 = () => { + new.target; + } +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/options.json b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/options.json new file mode 100644 index 00000000000..e82809c9418 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + "transform-new-target", + "transform-arrow-functions", + ["proposal-class-properties", { "loose": false }] + ] +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/output.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/output.js new file mode 100644 index 00000000000..50c1d35350a --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/.class-properties/output.js @@ -0,0 +1,33 @@ +class Foo { + constructor() { + var _newtarget = this.constructor, + _class, + _temp; + + babelHelpers.defineProperty(this, "test", function _target() { + this instanceof _target ? this.constructor : void 0; + }); + babelHelpers.defineProperty(this, "test2", function () { + _newtarget; + }); + this.Bar = (_temp = _class = class _target2 { + constructor() { + babelHelpers.defineProperty(this, "q", this.constructor); + } // should not replace + + + }, babelHelpers.defineProperty(_class, "p", void 0), babelHelpers.defineProperty(_class, "p1", class _target3 { + constructor() { + this.constructor; + } + + }), babelHelpers.defineProperty(_class, "p2", new function _target4() { + this instanceof _target4 ? this.constructor : void 0; + }()), babelHelpers.defineProperty(_class, "p3", function () { + void 0; + }), babelHelpers.defineProperty(_class, "p4", function _target5() { + this instanceof _target5 ? this.constructor : void 0; + }), _temp); + } + +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/input.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/input.js new file mode 100644 index 00000000000..902735c13a4 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/input.js @@ -0,0 +1,13 @@ +function Foo() { + const a = () => { + new.target; + }; +} + +class Bar { + constructor() { + const a = () => { + new.target; + }; + } +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/options.json b/ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/options.json new file mode 100644 index 00000000000..a48be298047 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["transform-new-target", "transform-arrow-functions"] +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/output.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/output.js new file mode 100644 index 00000000000..d8fb911a7c4 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/arrow/output.js @@ -0,0 +1,14 @@ +function Foo() { + var _newtarget = this instanceof Foo ? this.constructor : void 0; + const a = ()=>{ + _newtarget; + }; +} +class Bar { + constructor(){ + var _newtarget = this.constructor; + const a = ()=>{ + _newtarget; + }; + } +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/class/input.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/class/input.js new file mode 100644 index 00000000000..eb27600e912 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/class/input.js @@ -0,0 +1,9 @@ +class Foo { + constructor() { + new.target; + } + + test() { + new.target; + } +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/class/output.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/class/output.js new file mode 100644 index 00000000000..c95b4a17852 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/class/output.js @@ -0,0 +1,8 @@ +class Foo { + constructor(){ + this.constructor; + } + test() { + void 0; + } +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/extended-class/input.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/extended-class/input.js new file mode 100644 index 00000000000..420f160b66f --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/extended-class/input.js @@ -0,0 +1,20 @@ +class Foo { + constructor() { + new.target; + } +} + +class Bar extends Foo { + constructor() { + // This is probably bad... + new.target; + super(); + } +} + +class Baz extends Foo { + constructor() { + super(); + new.target; + } +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/extended-class/output.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/extended-class/output.js new file mode 100644 index 00000000000..423422c676c --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/extended-class/output.js @@ -0,0 +1,17 @@ +class Foo { + constructor(){ + this.constructor; + } +} +class Bar extends Foo { + constructor(){ + this.constructor; + super(); + } +} +class Baz extends Foo { + constructor(){ + super(); + this.constructor; + } +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/function/input.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/function/input.js new file mode 100644 index 00000000000..67fd631d5ac --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/function/input.js @@ -0,0 +1,11 @@ +function Foo() { + new.target; +} + +Foo.prototype.test = function() { + new.target; +}; + +var Bar = function() { + new.target; +}; diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/function/output.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/function/output.js new file mode 100644 index 00000000000..477f063b1a2 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/function/output.js @@ -0,0 +1,9 @@ +function Foo() { + this instanceof Foo ? this.constructor : void 0; +} +Foo.prototype.test = function _target() { + this instanceof _target ? this.constructor : void 0; +}; +var Bar = function _target1() { + this instanceof _target1 ? this.constructor : void 0; +}; diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/object/input.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/object/input.js new file mode 100644 index 00000000000..c231a30a581 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/object/input.js @@ -0,0 +1,11 @@ +"use strict"; + +const object = { + test() { + new.target; + }, + + test2: function() { + new.target; + }, +} diff --git a/ecmascript/transforms/compat/tests/fixture/new-target/general/object/output.js b/ecmascript/transforms/compat/tests/fixture/new-target/general/object/output.js new file mode 100644 index 00000000000..a4310482509 --- /dev/null +++ b/ecmascript/transforms/compat/tests/fixture/new-target/general/object/output.js @@ -0,0 +1,9 @@ +"use strict"; +const object = { + test () { + void 0; + }, + test2: function _target() { + this instanceof _target ? this.constructor : void 0; + } +}; diff --git a/ecmascript/transforms/testing/src/lib.rs b/ecmascript/transforms/testing/src/lib.rs index c5cfdbcb9c3..553a4eadf28 100644 --- a/ecmascript/transforms/testing/src/lib.rs +++ b/ecmascript/transforms/testing/src/lib.rs @@ -3,7 +3,7 @@ use anyhow::{bail, Context, Error}; use serde::de::DeserializeOwned; use std::{ env, - fs::{create_dir_all, read_to_string, remove_dir_all, OpenOptions}, + fs::{create_dir_all, read_to_string, OpenOptions}, io::{self, Write}, mem::{replace, take}, path::Path, @@ -428,9 +428,6 @@ where .join("testing") .join(test_name); - // Remove outputs from previous tests - let _ = remove_dir_all(&root); - create_dir_all(&root).expect("failed to create parent directory for temp directory"); let tmp_dir = tempdir_in(&root).expect("failed to create a temp directory"); diff --git a/node/bundler/src/loaders/swc.rs b/node/bundler/src/loaders/swc.rs index 658c2ce5c26..02639eb299f 100644 --- a/node/bundler/src/loaders/swc.rs +++ b/node/bundler/src/loaders/swc.rs @@ -45,7 +45,7 @@ impl SwcLoader { .and_then(|g| Some(g.envs.clone())) .unwrap_or_default(); - let mut envs_map: HashMap = envs + let envs_map: HashMap = envs .into_iter() .map(|name| { let value = env::var(&name).ok();