Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 27 additions & 34 deletions crates/oxc_transformer/src/es2022/class_properties/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@
//! ```js
//! class C extends S {
//! constructor(yes) {
//! var _super = (..._args) => {
//! super(..._args);
//! this.prop = foo();
//! return this;
//! };
//! var _super = (..._args) => (
//! super(..._args),
//! this.prop = foo(),
//! this
//! );
//! if (yes) {
//! _super(2);
//! } else {
Expand Down Expand Up @@ -145,7 +145,7 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
);
params_rest =
Some(ctx.ast.alloc_binding_rest_element(SPAN, binding.create_binding_pattern(ctx)));
stmts.push(create_super_call_stmt(&binding, ctx));
stmts.push(ctx.ast.statement_expression(SPAN, create_super_call(&binding, ctx)));
}
// TODO: Should these have the span of the original `PropertyDefinition`s?
stmts.extend(exprs_into_stmts(inits, ctx));
Expand Down Expand Up @@ -512,13 +512,8 @@ impl<'a, 'c> ConstructorBodyInitsInserter<'a, 'c> {
}

/// Insert `_super` function at top of constructor.
/// ```js
/// var _super = (..._args) => {
/// super(..._args);
/// <inits>
/// return this;
/// };
/// ```
///
/// `var _super = (..._args) => (super(..._args), <inits>, this);`
fn insert_super_func(
&mut self,
stmts: &mut ArenaVec<'a, Statement<'a>>,
Expand All @@ -534,22 +529,24 @@ impl<'a, 'c> ConstructorBodyInitsInserter<'a, 'c> {
let args_binding =
ctx.generate_uid("args", super_func_scope_id, SymbolFlags::FunctionScopedVariable);

// `super(..._args); <inits>; return this;`
// `(super(..._args), <inits>, this)`
//
// TODO(improve-on-babel): When not in loose mode, inits are `_defineProperty(this, propName, value)`.
// `_defineProperty` returns `this`, so last statement could be `return _defineProperty(this, propName, value)`,
// rather than an additional `return this` statement.
let super_call = create_super_call_stmt(&args_binding, ctx);
let return_stmt = ctx.ast.statement_return(SPAN, Some(ctx.ast.expression_this(SPAN)));
let body_stmts = ctx.ast.vec_from_iter(
[super_call].into_iter().chain(exprs_into_stmts(inits, ctx)).chain([return_stmt]),
let super_call = create_super_call(&args_binding, ctx);
let this_expr = ctx.ast.expression_this(SPAN);
let body_exprs = ctx.ast.expression_sequence(
SPAN,
ctx.ast.vec_from_iter([super_call].into_iter().chain(inits).chain([this_expr])),
);
let body = ctx.ast.vec1(ctx.ast.statement_expression(SPAN, body_exprs));

// `(...args) => { super(..._args); <inits>; return this; }`
// `(..._args) => (super(..._args), <inits>, this)`
let super_func = Expression::ArrowFunctionExpression(
ctx.ast.alloc_arrow_function_expression_with_scope_id(
SPAN,
false,
true,
false,
NONE,
ctx.ast.alloc_formal_parameters(
Expand All @@ -562,12 +559,12 @@ impl<'a, 'c> ConstructorBodyInitsInserter<'a, 'c> {
)),
),
NONE,
ctx.ast.alloc_function_body(SPAN, ctx.ast.vec(), body_stmts),
ctx.ast.alloc_function_body(SPAN, ctx.ast.vec(), body),
super_func_scope_id,
),
);

// `var _super = (...args) => { ... }`
// `var _super = (..._args) => ( ... );`
// Note: `super_binding` can be `None` at this point if no `super()` found in constructor
// (see comment above in `insert`).
let super_binding = self
Expand Down Expand Up @@ -664,20 +661,16 @@ impl<'a, 'c> ConstructorBodyInitsInserter<'a, 'c> {
}

/// `super(...args);`
fn create_super_call_stmt<'a>(
fn create_super_call<'a>(
args_binding: &BoundIdentifier<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Statement<'a> {
ctx.ast.statement_expression(
) -> Expression<'a> {
ctx.ast.expression_call(
SPAN,
ctx.ast.expression_call(
SPAN,
ctx.ast.expression_super(SPAN),
NONE,
ctx.ast.vec1(
ctx.ast.argument_spread_element(SPAN, args_binding.create_read_expression(ctx)),
),
false,
),
ctx.ast.expression_super(SPAN),
NONE,
ctx.ast
.vec1(ctx.ast.argument_spread_element(SPAN, args_binding.create_read_expression(ctx))),
false,
)
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
var _bar = /*#__PURE__*/new WeakMap();
class Foo extends Bar {
constructor() {
var _super = (..._args) => {
super(..._args);
babelHelpers.classPrivateFieldInitSpec(this, _bar, "foo");
return this;
};
var _super = (..._args) => (
super(..._args),
babelHelpers.classPrivateFieldInitSpec(this, _bar, "foo"),
this
);

if (condition) {
_super();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
class Foo extends Bar {
constructor() {
var _super = (..._args) => {
super(..._args);
this.bar = "foo";
return this;
};
var _super = (..._args) => (
super(..._args),
this.bar = "foo",
this
);
foo(_super());
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
class Foo extends Bar {
constructor() {
var _super = (..._args) => {
super(..._args);
babelHelpers.defineProperty(this, "bar", "foo");
return this;
};
var _super = (..._args) => (
super(..._args),
babelHelpers.defineProperty(this, "bar", "foo"),
this
);

if (condition) {
_super();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
class Foo extends Bar {
constructor() {
var _super = (..._args) => {
super(..._args);
babelHelpers.defineProperty(this, "bar", "foo");
return this;
};
var _super = (..._args) => (
super(..._args),
babelHelpers.defineProperty(this, "bar", "foo"),
this
);
foo(_super());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ class Obj {
// ensure superClass is still transformed
class SuperClass extends Obj {
constructor() {
var _super = (..._args) => {
super(..._args);
babelHelpers.defineProperty(this, "field", 1);
return this;
};
var _super = (..._args) => (
super(..._args),
babelHelpers.defineProperty(this, "field", 1),
this
);
class B extends (_super(), Obj) {
constructor() {
super();
Expand All @@ -47,11 +47,11 @@ new SuperClass();
// ensure ComputedKey Method is still transformed
class ComputedMethod extends Obj {
constructor() {
var _super2 = (..._args2) => {
super(..._args2);
babelHelpers.defineProperty(this, "field", 1);
return this;
};
var _super2 = (..._args2) => (
super(..._args2),
babelHelpers.defineProperty(this, "field", 1),
this
);
class B extends Obj {
constructor() {
super();
Expand All @@ -69,11 +69,11 @@ new ComputedMethod();
class ComputedField extends Obj {
constructor() {
let _super4;
var _super3 = (..._args3) => {
super(..._args3);
babelHelpers.defineProperty(this, "field", 1);
return this;
};
var _super3 = (..._args3) => (
super(..._args3),
babelHelpers.defineProperty(this, "field", 1),
this
);
_super4 = _super3();
class B extends Obj {
constructor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
class A extends B {
constructor() {
var _super = (..._args) => {
super(..._args);
babelHelpers.defineProperty(this, "x", 2);
return this;
};
var _super = (..._args) => (
super(..._args),
babelHelpers.defineProperty(this, "x", 2),
this
);
x ? _super(a) : _super(b);
}
}