Skip to content

Commit

Permalink
fix(es/transforms): Fix bugs (#2249)
Browse files Browse the repository at this point in the history
swc_ecma_transforms_compat:
 - Fix `this` in class properties. (#2228)

swc_ecma_transforms_typescript:
 - Handle `import =` correctly. (#2234)
 - Ensure that #1653 is not the case anymore. (#1653)

swc:
 - Ensure that #2232 is not the case. (#2232)
  • Loading branch information
kdy1 authored Sep 15, 2021
1 parent cab37f8 commit 6f33c32
Show file tree
Hide file tree
Showing 28 changed files with 430 additions and 24 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ecmascript/transforms/compat/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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.34.2"
version = "0.34.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
Expand Down
67 changes: 63 additions & 4 deletions ecmascript/transforms/compat/src/es2015/classes/constructor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::iter;
use swc_atoms::JsWord;
use swc_atoms::{js_word, JsWord};
use swc_common::{Mark, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::helper;
Expand Down Expand Up @@ -44,6 +44,10 @@ impl SuperCallFinder {
macro_rules! ignore_return {
($name:ident, $T:ty) => {
fn $name(&mut self, n: $T) -> $T {
if self.in_injected_define_property_call {
return n;
}

let old = self.ignore_return;
self.ignore_return = true;
let n = n.fold_children_with(self);
Expand Down Expand Up @@ -164,6 +168,7 @@ pub(super) struct ConstructorFolder<'a> {
pub is_constructor_default: bool,
/// True when recursing into other function or class.
pub ignore_return: bool,
pub in_injected_define_property_call: bool,
}

/// `None`: `return _possibleConstructorReturn`
Expand All @@ -190,6 +195,28 @@ impl Fold for ConstructorFolder<'_> {
_ => return expr,
}

// We pretend method folding mode for while folding injected `_defineProperty`
// calls.
match expr {
Expr::Call(CallExpr {
callee: ExprOrSuper::Expr(ref callee),
..
}) => match &**callee {
Expr::Ident(Ident {
sym: js_word!("_defineProperty"),
..
}) => {
let old = self.in_injected_define_property_call;
self.in_injected_define_property_call = true;
let n = expr.fold_children_with(self);
self.in_injected_define_property_call = old;
return n;
}
_ => {}
},
_ => {}
}

let expr = expr.fold_children_with(self);

match expr {
Expand Down Expand Up @@ -395,6 +422,7 @@ pub(super) fn replace_this_in_constructor(mark: Mark, c: Constructor) -> (Constr
mark: Mark,
found: bool,
wrap_with_assertion: bool,
in_injected_define_property_call: bool,
}

impl Fold for Replacer {
Expand All @@ -404,8 +432,30 @@ pub(super) fn replace_this_in_constructor(mark: Mark, c: Constructor) -> (Constr
n
}

fn fold_expr(&mut self, expr: Expr) -> Expr {
match expr {
fn fold_expr(&mut self, n: Expr) -> Expr {
// We pretend method folding mode for while folding injected `_defineProperty`
// calls.
match n {
Expr::Call(CallExpr {
callee: ExprOrSuper::Expr(ref callee),
..
}) => match &**callee {
Expr::Ident(Ident {
sym: js_word!("_defineProperty"),
..
}) => {
let old = self.in_injected_define_property_call;
self.in_injected_define_property_call = true;
let n = n.fold_children_with(self);
self.in_injected_define_property_call = old;
return n;
}
_ => {}
},
_ => {}
}

match n {
Expr::This(..) => {
self.found = true;
let this = quote_ident!(DUMMY_SP.apply_mark(self.mark), "_this");
Expand All @@ -421,8 +471,16 @@ pub(super) fn replace_this_in_constructor(mark: Mark, c: Constructor) -> (Constr
Expr::Ident(this)
}
}
_ => expr.fold_children_with(self),

_ => n.fold_children_with(self),
}
}

fn fold_function(&mut self, n: Function) -> Function {
if self.in_injected_define_property_call {
return n;
}
n.fold_children_with(self)
}

fn fold_member_expr(
Expand Down Expand Up @@ -454,6 +512,7 @@ pub(super) fn replace_this_in_constructor(mark: Mark, c: Constructor) -> (Constr
found: false,
mark,
wrap_with_assertion: true,
in_injected_define_property_call: false,
};
let c = c.fold_with(&mut v);

Expand Down
1 change: 1 addition & 0 deletions ecmascript/transforms/compat/src/es2015/classes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ where
},
mark: this_mark,
ignore_return: false,
in_injected_define_property_call: false,
});

insert_this |= (mode == None && !is_always_initialized)
Expand Down
4 changes: 2 additions & 2 deletions ecmascript/transforms/compat/src/es2015/regenerator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ mod case;
mod hoist;
mod leap;

pub fn regenerator(global_mark: Mark) -> impl Fold {
pub fn regenerator(top_level_mark: Mark) -> impl Fold {
Regenerator {
global_mark,
global_mark: top_level_mark,
regenerator_runtime: Default::default(),
top_level_vars: Default::default(),
}
Expand Down
2 changes: 1 addition & 1 deletion ecmascript/transforms/compat/tests/es2015_classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6539,7 +6539,7 @@ fn exec(input: PathBuf) {
let src = read_to_string(&input).unwrap();
compare_stdout(
Default::default(),
|t| classes(Some(t.comments.clone())),
|t| chain!(class_properties(), classes(Some(t.comments.clone()))),
&src,
);
}
23 changes: 22 additions & 1 deletion ecmascript/transforms/compat/tests/es2017_async_to_generator.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::es2015::regenerator;
use std::{fs::read_to_string, path::PathBuf};
use swc_common::{chain, Mark, Spanned};
use swc_ecma_ast::*;
use swc_ecma_parser::Syntax;
Expand All @@ -9,7 +10,7 @@ use swc_ecma_transforms_compat::{
es2017::async_to_generator,
es2020::class_properties,
};
use swc_ecma_transforms_testing::{test, test_exec};
use swc_ecma_transforms_testing::{compare_stdout, test, test_exec};
use swc_ecma_visit::{Fold, FoldWith};

struct ParenRemover;
Expand Down Expand Up @@ -2684,3 +2685,23 @@ test_exec!(
await res;
"
);

#[testing::fixture("tests/fixture/async-to-generator/**/exec.js")]
fn exec(input: PathBuf) {
let input = read_to_string(&input).unwrap();
compare_stdout(Default::default(), |_| async_to_generator(), &input);
}

#[testing::fixture("tests/fixture/async-to-generator/**/exec.js")]
fn exec_regenerator(input: PathBuf) {
let input = read_to_string(&input).unwrap();
compare_stdout(
Default::default(),
|_| {
let top_level_mark = Mark::fresh(Mark::root());

chain!(async_to_generator(), regenerator(top_level_mark))
},
&input,
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![allow(deprecated)]

use std::{fs::read_to_string, path::PathBuf};
use swc_common::chain;
use swc_ecma_parser::{EsConfig, Syntax, TsConfig};
use swc_ecma_transforms_base::resolver::resolver;
Expand All @@ -10,7 +11,7 @@ use swc_ecma_transforms_compat::{
es2020::{class_properties, typescript_class_properties},
es3::reserved_words,
};
use swc_ecma_transforms_testing::{test, test_exec, Tester};
use swc_ecma_transforms_testing::{compare_stdout, test, test_exec, Tester};
use swc_ecma_visit::Fold;

fn ts() -> Syntax {
Expand Down Expand Up @@ -5568,3 +5569,9 @@ test!(
}
"
);

#[testing::fixture("tests/fixture/classes/**/exec.js")]
fn exec(input: PathBuf) {
let src = read_to_string(&input).unwrap();
compare_stdout(Default::default(), |_| class_properties(), &src);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const foo = async () => {
try {
console.log(1)
} catch (err) {
console.log(err.message)
}
}

foo()
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Foo { }

class Bar extends Foo {
events = {
"abc: click": function abcClick() {
this.data = 123;
console.log(this);
}
}

setData() {
this.data = 456
}
}

const bar = new Bar();
console.log(bar.data);
console.log(bar.events)
console.log(bar.events["abc: click"]());
console.log(bar.data);
bar.setData();
console.log(bar.data);
2 changes: 1 addition & 1 deletion ecmascript/transforms/typescript/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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.40.2"
version = "0.40.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
Expand Down
23 changes: 14 additions & 9 deletions ecmascript/transforms/typescript/src/strip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1887,13 +1887,8 @@ impl VisitMut for Strip {
}

ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(import)) => {
if !import.is_export {
continue;
}

stmts.push(ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
span: DUMMY_SP,
decl: Decl::Var(VarDecl {
if !import.is_type_only {
let var = Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
decls: vec![VarDeclarator {
Expand All @@ -1903,8 +1898,18 @@ impl VisitMut for Strip {
definite: false,
}],
declare: false,
}),
})));
});
if import.is_export {
stmts.push(ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(
ExportDecl {
span: DUMMY_SP,
decl: var,
},
)));
} else {
stmts.push(ModuleItem::Stmt(Stmt::Decl(var)));
}
}
}

ModuleItem::ModuleDecl(ModuleDecl::TsExportAssignment(export)) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export function Colors(member: Colors.KeyType): Colors {
return Colors.ValueFor(member);
}

export module Colors {
export type KeyType = keyof typeof ValueMap;

export const ValueMap = {
Red: { value: 0.0, label: 'Red' },
Blue: { value: 1.0, label: 'Blue' },
Green: { value: 2.0, label: 'Green' },
} as const;

export const Values: Colors[] = [0.0, 1.0, 2.0];

export function ValueFor(member: KeyType): Colors {
return ValueMap[member]?.value;
}

export function LabelFor(
member: KeyType
): Promise<string | undefined> {
return ValueMap[member]?.label;
}
}
11 changes: 11 additions & 0 deletions ecmascript/transforms/typescript/tests/fixture/issue-1653/input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace X {
export namespace Z {
export const foo = 0
}
}

namespace Y {
export namespace Z {
export const bar = 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var X;
(function(X) {
var Z;
(function(Z) {
Z.foo = 0;
})(Z || (Z = {
}));
X.Z = Z;
})(X || (X = {
}));
var Y;
(function(Y) {
(function(Z) {
Z.bar = 1;
})(Z || (Z = {
}));
})(Y || (Y = {
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Shapes {
export namespace Polygons {
export class Triangle { }
export class Square { }
}
}
import polygons = Shapes.Polygons;
let sq = new polygons.Square();
Loading

0 comments on commit 6f33c32

Please sign in to comment.