mirror of
https://github.com/swc-project/swc.git
synced 2024-09-20 05:07:40 +03:00
feat(es/compat): Implement loose mode for class_properties
(#3722)
This commit is contained in:
parent
d23e19abe9
commit
14155eb0e7
@ -184,7 +184,14 @@ impl<'a, 'b, P: swc_ecma_visit::Fold> PassBuilder<'a, 'b, P> {
|
||||
} else {
|
||||
Either::Right(chain!(
|
||||
Optional::new(
|
||||
compat::es2022::es2022(compat::es2022::Config { loose: self.loose }),
|
||||
compat::es2022::es2022(compat::es2022::Config {
|
||||
class_properties: compat::es2022::class_properties::Config {
|
||||
private_as_properties: self.loose,
|
||||
constant_super: self.loose,
|
||||
set_public_fields: self.loose,
|
||||
no_document_all: self.loose
|
||||
}
|
||||
}),
|
||||
should_enable(self.target, EsVersion::Es2022)
|
||||
),
|
||||
Optional::new(
|
||||
|
@ -1,16 +1,3 @@
|
||||
function _defineProperty(obj, key, value) {
|
||||
if (key in obj) {
|
||||
Object.defineProperty(obj, key, {
|
||||
value: value,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true
|
||||
});
|
||||
} else {
|
||||
obj[key] = value;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
var ClassA = function ClassA() {
|
||||
"use strict";
|
||||
};
|
||||
@ -24,6 +11,6 @@ module.exports = (function() {
|
||||
};
|
||||
return ClassB;
|
||||
}();
|
||||
_defineProperty(ClassB, "MyA", ClassA);
|
||||
ClassB.MyA = ClassA;
|
||||
return ClassB;
|
||||
})();
|
||||
|
@ -1,16 +1,11 @@
|
||||
var a = function() {};
|
||||
module.exports = (function() {
|
||||
var b, c, d, e = function() {
|
||||
var b = function() {
|
||||
"use strict";
|
||||
function e() {}
|
||||
return e.prototype.it = function() {
|
||||
this.bb = new e.MyA();
|
||||
}, e;
|
||||
function b() {}
|
||||
return b.prototype.it = function() {
|
||||
this.bb = new b.MyA();
|
||||
}, b;
|
||||
}();
|
||||
return b = e, c = "MyA", d = a, c in b ? Object.defineProperty(b, c, {
|
||||
value: d,
|
||||
enumerable: !0,
|
||||
configurable: !0,
|
||||
writable: !0
|
||||
}) : b[c] = d, e;
|
||||
return b.MyA = a, b;
|
||||
})();
|
||||
|
@ -69,26 +69,26 @@ function _createSuper(Derived) {
|
||||
return _possibleConstructorReturn(this, result);
|
||||
};
|
||||
}
|
||||
var C = /*#__PURE__*/ function(_super) {
|
||||
var C = /*#__PURE__*/ function(__class) {
|
||||
"use strict";
|
||||
_inherits(_class, _super);
|
||||
var _super1 = _createSuper(_class);
|
||||
_inherits(_class, __class);
|
||||
var _super = _createSuper(_class);
|
||||
function _class() {
|
||||
_classCallCheck(this, _class);
|
||||
var _this;
|
||||
_this = _super1.apply(this, arguments);
|
||||
_this = _super.apply(this, arguments);
|
||||
_this.c = 3;
|
||||
return _this;
|
||||
}
|
||||
return _class;
|
||||
}(/*#__PURE__*/ function(_super) {
|
||||
}(/*#__PURE__*/ function(__class) {
|
||||
"use strict";
|
||||
_inherits(_class, _super);
|
||||
var _super2 = _createSuper(_class);
|
||||
_inherits(_class, __class);
|
||||
var _super = _createSuper(_class);
|
||||
function _class() {
|
||||
_classCallCheck(this, _class);
|
||||
var _this;
|
||||
_this = _super2.apply(this, arguments);
|
||||
_this = _super.apply(this, arguments);
|
||||
_this.b = 2;
|
||||
return _this;
|
||||
}
|
||||
|
@ -44,22 +44,22 @@ function _createSuper(Derived) {
|
||||
})(self);
|
||||
};
|
||||
}
|
||||
var c = new (function(_super) {
|
||||
var c = new (function(__class) {
|
||||
"use strict";
|
||||
_inherits(_class, _super);
|
||||
var _super1 = _createSuper(_class);
|
||||
_inherits(_class, __class);
|
||||
var _super = _createSuper(_class);
|
||||
function _class() {
|
||||
var _this;
|
||||
return _classCallCheck(this, _class), _this = _super1.apply(this, arguments), _this.c = 3, _this;
|
||||
return _classCallCheck(this, _class), _this = _super.apply(this, arguments), _this.c = 3, _this;
|
||||
}
|
||||
return _class;
|
||||
}(function(_super) {
|
||||
}(function(__class) {
|
||||
"use strict";
|
||||
_inherits(_class, _super);
|
||||
var _super2 = _createSuper(_class);
|
||||
_inherits(_class, __class);
|
||||
var _super = _createSuper(_class);
|
||||
function _class() {
|
||||
var _this;
|
||||
return _classCallCheck(this, _class), _this = _super2.apply(this, arguments), _this.b = 2, _this;
|
||||
return _classCallCheck(this, _class), _this = _super.apply(this, arguments), _this.b = 2, _this;
|
||||
}
|
||||
return _class;
|
||||
}(function _class() {
|
||||
|
@ -70,26 +70,26 @@ function _createSuper(Derived) {
|
||||
};
|
||||
}
|
||||
// @target: es6
|
||||
var C = /*#__PURE__*/ function(_super) {
|
||||
var C = /*#__PURE__*/ function(__class) {
|
||||
"use strict";
|
||||
_inherits(_class, _super);
|
||||
var _super1 = _createSuper(_class);
|
||||
_inherits(_class, __class);
|
||||
var _super = _createSuper(_class);
|
||||
function _class() {
|
||||
_classCallCheck(this, _class);
|
||||
var _this;
|
||||
_this = _super1.apply(this, arguments);
|
||||
_this = _super.apply(this, arguments);
|
||||
_this.c = 3;
|
||||
return _this;
|
||||
}
|
||||
return _class;
|
||||
}(/*#__PURE__*/ function(_super) {
|
||||
}(/*#__PURE__*/ function(__class) {
|
||||
"use strict";
|
||||
_inherits(_class, _super);
|
||||
var _super2 = _createSuper(_class);
|
||||
_inherits(_class, __class);
|
||||
var _super = _createSuper(_class);
|
||||
function _class() {
|
||||
_classCallCheck(this, _class);
|
||||
var _this;
|
||||
_this = _super2.apply(this, arguments);
|
||||
_this = _super.apply(this, arguments);
|
||||
_this.b = 2;
|
||||
return _this;
|
||||
}
|
||||
|
@ -44,22 +44,22 @@ function _createSuper(Derived) {
|
||||
})(self);
|
||||
};
|
||||
}
|
||||
var c = new (function(_super) {
|
||||
var c = new (function(__class) {
|
||||
"use strict";
|
||||
_inherits(_class, _super);
|
||||
var _super1 = _createSuper(_class);
|
||||
_inherits(_class, __class);
|
||||
var _super = _createSuper(_class);
|
||||
function _class() {
|
||||
var _this;
|
||||
return _classCallCheck(this, _class), _this = _super1.apply(this, arguments), _this.c = 3, _this;
|
||||
return _classCallCheck(this, _class), _this = _super.apply(this, arguments), _this.c = 3, _this;
|
||||
}
|
||||
return _class;
|
||||
}(function(_super) {
|
||||
}(function(__class) {
|
||||
"use strict";
|
||||
_inherits(_class, _super);
|
||||
var _super2 = _createSuper(_class);
|
||||
_inherits(_class, __class);
|
||||
var _super = _createSuper(_class);
|
||||
function _class() {
|
||||
var _this;
|
||||
return _classCallCheck(this, _class), _this = _super2.apply(this, arguments), _this.b = 2, _this;
|
||||
return _classCallCheck(this, _class), _this = _super.apply(this, arguments), _this.b = 2, _this;
|
||||
}
|
||||
return _class;
|
||||
}(function _class() {
|
||||
|
@ -41,7 +41,7 @@ class A {
|
||||
var _foo = {
|
||||
writable: true,
|
||||
value: true
|
||||
} // error (duplicate)
|
||||
}// error (duplicate)
|
||||
;
|
||||
class B {
|
||||
test(x) {
|
||||
|
@ -59,7 +59,7 @@ var A = function A() {
|
||||
var _foo = {
|
||||
writable: true,
|
||||
value: true
|
||||
} // error (duplicate)
|
||||
}// error (duplicate)
|
||||
;
|
||||
var B = /*#__PURE__*/ function() {
|
||||
"use strict";
|
||||
|
@ -92,7 +92,12 @@ where
|
||||
let pass = add!(
|
||||
pass,
|
||||
ClassProperties,
|
||||
es2022::class_properties(es2022::class_properties::Config { loose })
|
||||
es2022::class_properties(es2022::class_properties::Config {
|
||||
private_as_properties: loose,
|
||||
set_public_fields: loose,
|
||||
constant_super: loose,
|
||||
no_document_all: loose
|
||||
})
|
||||
);
|
||||
let pass = add!(pass, PrivatePropertyInObject, es2022::private_in_object());
|
||||
|
||||
|
@ -1 +1,5 @@
|
||||
[1, 2, 3][flatMap];
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3
|
||||
][flatMap];
|
||||
|
@ -1,8 +1,9 @@
|
||||
var __ = _classPrivateFieldLooseKey("__");
|
||||
class A {
|
||||
}
|
||||
var __ = {
|
||||
Object.defineProperty(A, __, {
|
||||
writable: true,
|
||||
value: (()=>{
|
||||
A.abc = 123;
|
||||
})()
|
||||
};
|
||||
});
|
||||
|
@ -20,8 +20,8 @@ use swc_ecma_ast::*;
|
||||
use swc_ecma_codegen::Emitter;
|
||||
use swc_ecma_parser::{EsConfig, Parser, Syntax};
|
||||
use swc_ecma_preset_env::{preset_env, Config, FeatureOrModule, Mode, Targets, Version};
|
||||
use swc_ecma_transforms::fixer;
|
||||
use swc_ecma_utils::drop_span;
|
||||
use swc_ecma_transforms::{fixer, helpers};
|
||||
use swc_ecma_utils::{drop_span, HANDLER};
|
||||
use swc_ecma_visit::{as_folder, FoldWith, VisitMut};
|
||||
use testing::{NormalizedOutput, Tester};
|
||||
|
||||
@ -134,7 +134,6 @@ fn exec(c: PresetConfig, dir: PathBuf) -> Result<(), Error> {
|
||||
v => unreachable!("invalid: {:?}", v),
|
||||
},
|
||||
skip: vec![],
|
||||
// TODO
|
||||
loose: true,
|
||||
// TODO
|
||||
dynamic_import: true,
|
||||
@ -194,7 +193,9 @@ fn exec(c: PresetConfig, dir: PathBuf) -> Result<(), Error> {
|
||||
e.into_diagnostic(&handler).emit()
|
||||
}
|
||||
|
||||
let actual = module.fold_with(&mut pass);
|
||||
let actual = helpers::HELPERS.set(&Default::default(), || {
|
||||
HANDLER.set(&handler, || module.fold_with(&mut pass))
|
||||
});
|
||||
|
||||
// debug mode?
|
||||
if dir.join("stdout.txt").exists() {
|
||||
|
@ -40,7 +40,7 @@ fn syntax(decorators_before_export: bool) -> Syntax {
|
||||
fn tr() -> impl Fold {
|
||||
chain!(
|
||||
decorators(Default::default()),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
)
|
||||
}
|
||||
|
||||
@ -2023,7 +2023,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_constructors_return_new_constructor_exec,
|
||||
r#"
|
||||
@ -2181,7 +2181,7 @@ export { _class1 as default }
|
||||
// "presets": ["env"],
|
||||
// "plugins": [
|
||||
// ["proposal-decorators", { "legacy": true }],
|
||||
// [class_properties(class_properties::Config { loose: false }), { "loose":
|
||||
// [class_properties(Default::default()), { "loose":
|
||||
// true }] ]
|
||||
//}
|
||||
//"#),
|
||||
@ -2208,7 +2208,7 @@ export { _class1 as default }
|
||||
// "presets": ["env"],
|
||||
// "plugins": [
|
||||
// ["proposal-decorators", { "legacy": true }],
|
||||
// [class_properties(class_properties::Config { loose: false }), { "loose":
|
||||
// [class_properties(Default::default()), { "loose":
|
||||
// true }] ]
|
||||
//}
|
||||
//"#),
|
||||
@ -2343,7 +2343,7 @@ export { _class1 as default }
|
||||
// "presets": ["env"],
|
||||
// "plugins": [
|
||||
// ["proposal-decorators", { "legacy": true }],
|
||||
// [class_properties(class_properties::Config { loose: false }), { "loose":
|
||||
// [class_properties(Default::default()), { "loose":
|
||||
// true }] ]
|
||||
//}
|
||||
//"#),
|
||||
@ -2480,7 +2480,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_prototype_methods_numeric_props_exec,
|
||||
r#"
|
||||
@ -2506,7 +2506,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_static_properties_mutate_descriptor_exec,
|
||||
r#"
|
||||
@ -2621,7 +2621,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_static_methods_string_props_exec,
|
||||
r#"
|
||||
@ -2647,7 +2647,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_prototype_properties_string_literal_properties_exec,
|
||||
r#"
|
||||
@ -2692,7 +2692,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_prototype_methods_mutate_descriptor_exec,
|
||||
r#"
|
||||
@ -2825,7 +2825,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_object_properties_numeric_props_exec,
|
||||
r#"
|
||||
@ -2882,7 +2882,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_prototype_properties_return_descriptor_exec,
|
||||
r#"
|
||||
@ -2999,7 +2999,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_object_properties_string_props_exec,
|
||||
r#"
|
||||
@ -3027,7 +3027,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_object_properties_return_descriptor_exec,
|
||||
r#"
|
||||
@ -3140,7 +3140,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_prototype_methods_string_props_exec,
|
||||
r#"
|
||||
@ -3166,7 +3166,7 @@ test!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_regression_8041,
|
||||
r#"
|
||||
@ -3196,7 +3196,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_prototype_methods_return_descriptor_exec,
|
||||
r#"
|
||||
@ -3331,7 +3331,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_object_ordering_reverse_order_exec,
|
||||
r#"
|
||||
@ -3375,7 +3375,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_object_methods_numeric_props_exec,
|
||||
r#"
|
||||
@ -3402,7 +3402,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_static_properties_return_descriptor_exec,
|
||||
r#"
|
||||
@ -3522,7 +3522,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_export_default_exec,
|
||||
r#"
|
||||
@ -3552,7 +3552,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_ordering_reverse_order_exec,
|
||||
r#"
|
||||
@ -3599,7 +3599,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_object_methods_mutate_descriptor_exec,
|
||||
r#"
|
||||
@ -3728,7 +3728,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_static_methods_return_descriptor_exec,
|
||||
r#"
|
||||
@ -3860,7 +3860,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_object_methods_return_descriptor_exec,
|
||||
r#"
|
||||
@ -3991,7 +3991,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_object_methods_string_props_exec,
|
||||
r#"
|
||||
@ -4019,7 +4019,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_prototype_properties_child_classes_properties_exec,
|
||||
r#"
|
||||
@ -4062,7 +4062,7 @@ test_exec!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
),
|
||||
legacy_class_static_methods_mutate_descriptor_exec,
|
||||
r#"
|
||||
@ -5144,7 +5144,7 @@ test!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
classes(Some(t.comments.clone()), Default::default())
|
||||
),
|
||||
decorators_legacy_interop_local_define_property,
|
||||
|
@ -694,7 +694,7 @@ test!(
|
||||
legacy: true,
|
||||
..Default::default()
|
||||
}),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
classes(Some(t.comments.clone()), Default::default()),
|
||||
),
|
||||
decorators_legacy_interop_strict,
|
||||
|
@ -3,5 +3,5 @@ function _classPrivateFieldBase(receiver, privateKey) {
|
||||
throw new TypeError("attempted to use private field on non-instance");
|
||||
}
|
||||
|
||||
return receiver;
|
||||
return receiver[privateKey];
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
var id = 0;
|
||||
|
||||
function _classPrivateFieldLooseKey(name) {
|
||||
return "__private_" + id++ + "_" + name;
|
||||
}
|
@ -186,7 +186,7 @@ define_helpers!(Helpers {
|
||||
class_private_field_get: (class_extract_field_descriptor, class_apply_descriptor_get),
|
||||
class_private_field_init: (check_private_redeclaration),
|
||||
class_private_field_loose_base: (),
|
||||
// class_private_field_loose_key: (),
|
||||
class_private_field_loose_key: (),
|
||||
class_private_field_set: (class_extract_field_descriptor, class_apply_descriptor_set),
|
||||
class_private_method_get: (),
|
||||
class_private_method_init: (check_private_redeclaration),
|
||||
|
@ -756,8 +756,8 @@ where
|
||||
key: PropName::Ident(quote_ident!(key.span(), "key")),
|
||||
value: match key {
|
||||
PropName::Ident(i) => Box::new(Expr::Lit(Lit::Str(quote_str!(i.span, i.sym)))),
|
||||
PropName::Str(s) => Box::new(Expr::Lit(Lit::Str(s))),
|
||||
PropName::Num(n) => Box::new(Expr::Lit(Lit::Num(n))),
|
||||
PropName::Str(s) => Box::new(Expr::from(s)),
|
||||
PropName::Num(n) => Box::new(Expr::from(n)),
|
||||
PropName::BigInt(b) => Box::new(Expr::Lit(
|
||||
Str {
|
||||
span: b.span,
|
||||
|
@ -7,7 +7,8 @@ use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Check;
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_utils::{
|
||||
alias_if_required, prepend, private_ident, undefined, ExprFactory, IntoIndirectCall, StmtLike,
|
||||
alias_if_required, opt_chain_test, prepend, private_ident, undefined, ExprFactory,
|
||||
IntoIndirectCall, StmtLike,
|
||||
};
|
||||
use swc_ecma_visit::{
|
||||
as_folder, noop_visit_mut_type, noop_visit_type, Fold, Visit, VisitMut, VisitMutWith,
|
||||
@ -447,31 +448,7 @@ impl OptChaining {
|
||||
}
|
||||
};
|
||||
|
||||
let test = Box::new(Expr::Bin(if self.c.no_document_all {
|
||||
BinExpr {
|
||||
span: obj_span,
|
||||
left,
|
||||
op: op!("=="),
|
||||
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
|
||||
}
|
||||
} else {
|
||||
BinExpr {
|
||||
span,
|
||||
left: Box::new(Expr::Bin(BinExpr {
|
||||
span: obj_span,
|
||||
left,
|
||||
op: op!("==="),
|
||||
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
|
||||
})),
|
||||
op: op!("||"),
|
||||
right: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: right,
|
||||
op: op!("==="),
|
||||
right: undefined(span),
|
||||
})),
|
||||
}
|
||||
}));
|
||||
let test = Box::new(opt_chain_test(left, right, span, self.c.no_document_all));
|
||||
|
||||
CondExpr {
|
||||
span,
|
||||
@ -595,31 +572,7 @@ impl OptChaining {
|
||||
}
|
||||
};
|
||||
|
||||
let test = Box::new(Expr::Bin(if self.c.no_document_all {
|
||||
BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left,
|
||||
op: op!("=="),
|
||||
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
|
||||
}
|
||||
} else {
|
||||
BinExpr {
|
||||
span,
|
||||
left: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left,
|
||||
op: op!("==="),
|
||||
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
|
||||
})),
|
||||
op: op!("||"),
|
||||
right: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: right,
|
||||
op: op!("==="),
|
||||
right: undefined(span),
|
||||
})),
|
||||
}
|
||||
}));
|
||||
let test = Box::new(opt_chain_test(left, right, span, self.c.no_document_all));
|
||||
|
||||
CondExpr {
|
||||
span: DUMMY_SP,
|
||||
|
@ -0,0 +1,356 @@
|
||||
use swc_common::{Span, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::helper;
|
||||
use swc_ecma_utils::{
|
||||
prop_name_to_expr, prop_name_to_expr_value, quote_ident, undefined, ExprFactory,
|
||||
};
|
||||
|
||||
use super::Config;
|
||||
|
||||
pub(super) enum MemberInit {
|
||||
PubProp(PubProp),
|
||||
PrivProp(PrivProp),
|
||||
PrivMethod(PrivMethod),
|
||||
PrivAccessor(PrivAccessor),
|
||||
}
|
||||
|
||||
pub(super) struct PubProp {
|
||||
pub span: Span,
|
||||
pub name: PropName,
|
||||
pub value: Box<Expr>,
|
||||
}
|
||||
|
||||
pub(super) struct PrivProp {
|
||||
pub span: Span,
|
||||
pub name: Ident,
|
||||
pub value: Box<Expr>,
|
||||
}
|
||||
|
||||
pub(super) struct PrivMethod {
|
||||
pub span: Span,
|
||||
pub name: Ident,
|
||||
// only used in loose mode
|
||||
pub fn_name: Ident,
|
||||
}
|
||||
|
||||
pub(super) struct PrivAccessor {
|
||||
pub span: Span,
|
||||
pub name: Ident,
|
||||
pub getter: Option<Ident>,
|
||||
pub setter: Option<Ident>,
|
||||
}
|
||||
|
||||
pub(super) struct MemberInitRecord {
|
||||
c: Config,
|
||||
pub record: Vec<MemberInit>,
|
||||
}
|
||||
|
||||
impl MemberInitRecord {
|
||||
pub fn new(c: Config) -> Self {
|
||||
Self {
|
||||
c,
|
||||
record: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, member: MemberInit) -> bool {
|
||||
// there shouldn't be many class field, so n^2 should be fine
|
||||
if let MemberInit::PrivAccessor(accessor) = member {
|
||||
if let Some(MemberInit::PrivAccessor(previous)) =
|
||||
self.record.iter_mut().find(|item| match item {
|
||||
MemberInit::PrivAccessor(PrivAccessor { name, .. })
|
||||
if name.sym == accessor.name.sym =>
|
||||
{
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
{
|
||||
previous.getter = previous.getter.take().or(accessor.getter);
|
||||
previous.setter = previous.setter.take().or(accessor.setter);
|
||||
false
|
||||
} else {
|
||||
self.record.push(MemberInit::PrivAccessor(accessor));
|
||||
true
|
||||
}
|
||||
} else {
|
||||
self.record.push(member);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_init(self) -> Vec<Box<Expr>> {
|
||||
self.record
|
||||
.into_iter()
|
||||
.map(|init| {
|
||||
match init {
|
||||
MemberInit::PrivMethod(PrivMethod {
|
||||
span,
|
||||
name,
|
||||
fn_name,
|
||||
}) => {
|
||||
let (callee, args) = if self.c.private_as_properties {
|
||||
(
|
||||
obj_def_prop(),
|
||||
vec![
|
||||
ThisExpr { span: DUMMY_SP }.as_arg(),
|
||||
name.as_arg(),
|
||||
get_method_desc(Box::new(fn_name.into())).as_arg(),
|
||||
],
|
||||
)
|
||||
} else {
|
||||
(
|
||||
helper!(class_private_method_init, "classPrivateMethodInit"),
|
||||
vec![ThisExpr { span: DUMMY_SP }.as_arg(), name.as_arg()],
|
||||
)
|
||||
};
|
||||
Expr::Call(CallExpr {
|
||||
span,
|
||||
callee,
|
||||
args,
|
||||
type_args: Default::default(),
|
||||
})
|
||||
}
|
||||
MemberInit::PrivProp(PrivProp { span, name, value }) => Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: if self.c.private_as_properties {
|
||||
obj_def_prop()
|
||||
} else {
|
||||
helper!(class_private_field_init, "classPrivateFieldInit")
|
||||
},
|
||||
args: vec![
|
||||
ThisExpr { span: DUMMY_SP }.as_arg(),
|
||||
name.as_arg(),
|
||||
get_value_desc(value).as_arg(),
|
||||
],
|
||||
type_args: Default::default(),
|
||||
}),
|
||||
MemberInit::PrivAccessor(PrivAccessor {
|
||||
span,
|
||||
name,
|
||||
getter,
|
||||
setter,
|
||||
}) => Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: if self.c.private_as_properties {
|
||||
obj_def_prop()
|
||||
} else {
|
||||
helper!(class_private_field_init, "classPrivateFieldInit")
|
||||
},
|
||||
args: vec![
|
||||
ThisExpr { span: DUMMY_SP }.as_arg(),
|
||||
name.as_arg(),
|
||||
get_accessor_desc(getter, setter).as_arg(),
|
||||
],
|
||||
type_args: Default::default(),
|
||||
}),
|
||||
MemberInit::PubProp(PubProp { span, name, value }) => {
|
||||
if self.c.set_public_fields {
|
||||
let this = ThisExpr { span: DUMMY_SP };
|
||||
Expr::Assign(AssignExpr {
|
||||
span,
|
||||
left: PatOrExpr::Expr(Box::new(match name {
|
||||
PropName::Ident(id) => this.make_member(id),
|
||||
_ => this.computed_member(prop_name_to_expr(name)),
|
||||
})),
|
||||
op: op!("="),
|
||||
right: value,
|
||||
})
|
||||
} else {
|
||||
Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: helper!(define_property, "defineProperty"),
|
||||
args: vec![
|
||||
ThisExpr { span: DUMMY_SP }.as_arg(),
|
||||
prop_name_to_expr_value(name).as_arg(),
|
||||
value.as_arg(),
|
||||
],
|
||||
type_args: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn into_init_static(self, class_ident: Ident) -> Vec<Stmt> {
|
||||
self.record
|
||||
.into_iter()
|
||||
.map(|value| match value {
|
||||
MemberInit::PubProp(PubProp { span, name, value }) => Stmt::Expr(ExprStmt {
|
||||
span,
|
||||
expr: (if self.c.set_public_fields {
|
||||
let class = class_ident.clone();
|
||||
Expr::Assign(AssignExpr {
|
||||
span,
|
||||
left: PatOrExpr::Expr(Box::new(match name {
|
||||
PropName::Ident(id) => class.make_member(id),
|
||||
_ => class.computed_member(prop_name_to_expr(name)),
|
||||
})),
|
||||
op: op!("="),
|
||||
right: value,
|
||||
})
|
||||
} else {
|
||||
Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: helper!(define_property, "defineProperty"),
|
||||
args: vec![
|
||||
class_ident.clone().as_arg(),
|
||||
prop_name_to_expr_value(name).as_arg(),
|
||||
value.as_arg(),
|
||||
],
|
||||
type_args: Default::default(),
|
||||
})
|
||||
})
|
||||
.into(),
|
||||
}),
|
||||
MemberInit::PrivProp(PrivProp { span, name, value }) => {
|
||||
if self.c.private_as_properties {
|
||||
Stmt::Expr(ExprStmt {
|
||||
span,
|
||||
expr: Box::new(Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: obj_def_prop(),
|
||||
args: vec![
|
||||
class_ident.clone().as_arg(),
|
||||
name.as_arg(),
|
||||
get_value_desc(value).as_arg(),
|
||||
],
|
||||
type_args: None,
|
||||
})),
|
||||
})
|
||||
} else {
|
||||
Stmt::Decl(Decl::Var(VarDecl {
|
||||
span,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span,
|
||||
name: name.into(),
|
||||
init: Some(Expr::Object(get_value_desc(value)).into()),
|
||||
definite: false,
|
||||
}],
|
||||
declare: false,
|
||||
}))
|
||||
}
|
||||
}
|
||||
MemberInit::PrivAccessor(PrivAccessor {
|
||||
span,
|
||||
name,
|
||||
getter,
|
||||
setter,
|
||||
}) => {
|
||||
if self.c.private_as_properties {
|
||||
Stmt::Expr(ExprStmt {
|
||||
span,
|
||||
expr: Box::new(Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: obj_def_prop(),
|
||||
args: vec![
|
||||
class_ident.clone().as_arg(),
|
||||
name.as_arg(),
|
||||
get_accessor_desc(getter, setter).as_arg(),
|
||||
],
|
||||
type_args: None,
|
||||
})),
|
||||
})
|
||||
} else {
|
||||
Stmt::Decl(Decl::Var(VarDecl {
|
||||
span,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span,
|
||||
name: name.into(),
|
||||
init: Some(Expr::Object(get_accessor_desc(getter, setter)).into()),
|
||||
definite: false,
|
||||
}],
|
||||
declare: false,
|
||||
}))
|
||||
}
|
||||
}
|
||||
MemberInit::PrivMethod(PrivMethod {
|
||||
span,
|
||||
name,
|
||||
fn_name,
|
||||
}) => {
|
||||
if self.c.private_as_properties {
|
||||
Stmt::Expr(ExprStmt {
|
||||
span,
|
||||
expr: Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: obj_def_prop(),
|
||||
args: vec![
|
||||
class_ident.clone().as_arg(),
|
||||
name.as_arg(),
|
||||
get_method_desc(Box::new(fn_name.into())).as_arg(),
|
||||
],
|
||||
type_args: None,
|
||||
})
|
||||
.into(),
|
||||
})
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_value_desc(value: Box<Expr>) -> ObjectLit {
|
||||
ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
// writeable: true
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("writable")),
|
||||
value: true.into(),
|
||||
}))),
|
||||
// value: value,
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("value")),
|
||||
value,
|
||||
}))),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn get_accessor_desc(getter: Option<Ident>, setter: Option<Ident>) -> ObjectLit {
|
||||
ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("get")),
|
||||
value: getter
|
||||
.map(|id| Box::new(id.into()))
|
||||
.unwrap_or_else(|| undefined(DUMMY_SP)),
|
||||
}))),
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("set")),
|
||||
value: setter
|
||||
.map(|id| Box::new(id.into()))
|
||||
.unwrap_or_else(|| undefined(DUMMY_SP)),
|
||||
}))),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn get_method_desc(value: Box<Expr>) -> ObjectLit {
|
||||
ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
// value: value,
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("value")),
|
||||
value,
|
||||
}))),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn obj_def_prop() -> Callee {
|
||||
quote_ident!("Object")
|
||||
.make_member(quote_ident!("defineProperty"))
|
||||
.as_callee()
|
||||
}
|
@ -1,10 +1,9 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use swc_common::{
|
||||
collections::{AHashMap, AHashSet},
|
||||
util::take::Take,
|
||||
Mark, Span, Spanned, SyntaxContext, DUMMY_SP,
|
||||
Mark, Spanned, SyntaxContext, DUMMY_SP,
|
||||
};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{helper, perf::Check};
|
||||
@ -20,6 +19,7 @@ use swc_ecma_visit::{
|
||||
|
||||
use self::{
|
||||
class_name_tdz::ClassNameTdzFolder,
|
||||
member_init::{MemberInit, MemberInitRecord, PrivAccessor, PrivMethod, PrivProp, PubProp},
|
||||
private_field::{
|
||||
dup_private_method, visit_private_in_expr, BrandCheckHandler, Private,
|
||||
PrivateAccessVisitor, PrivateKind, PrivateRecord,
|
||||
@ -29,6 +29,7 @@ use self::{
|
||||
};
|
||||
|
||||
mod class_name_tdz;
|
||||
mod member_init;
|
||||
mod private_field;
|
||||
mod this_in_static;
|
||||
mod used_name;
|
||||
@ -42,30 +43,24 @@ mod used_name;
|
||||
/// We use custom helper to handle export default class
|
||||
pub fn class_properties(config: Config) -> impl Fold + VisitMut {
|
||||
as_folder(ClassProperties {
|
||||
config,
|
||||
c: config,
|
||||
private: PrivateRecord::new(),
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct Config {
|
||||
pub loose: bool,
|
||||
pub private_as_properties: bool,
|
||||
pub set_public_fields: bool,
|
||||
pub constant_super: bool,
|
||||
pub no_document_all: bool,
|
||||
}
|
||||
|
||||
struct ClassProperties {
|
||||
config: Config,
|
||||
c: Config,
|
||||
private: PrivateRecord,
|
||||
}
|
||||
|
||||
enum MemberInit {
|
||||
Prop(Span, Box<Expr>),
|
||||
Private(Span, Box<Expr>),
|
||||
PrivMethod(Span),
|
||||
PrivAccessor(Span, Option<Ident>, Option<Ident>),
|
||||
}
|
||||
|
||||
type MemberInitMap = IndexMap<Expr, MemberInit, ahash::RandomState>;
|
||||
|
||||
#[fast_path(ShouldWork)]
|
||||
impl VisitMut for ClassProperties {
|
||||
noop_visit_mut_type!();
|
||||
@ -394,16 +389,15 @@ impl ClassProperties {
|
||||
|
||||
let has_super = class.super_class.is_some();
|
||||
|
||||
// we need a hash map to avoid generate two init for corresponding getter/setter
|
||||
let mut constructor_inits = MemberInitMap::default();
|
||||
let mut constructor_inits = MemberInitRecord::new(self.c);
|
||||
let mut vars = vec![];
|
||||
let mut extra_inits = MemberInitMap::default();
|
||||
// same here
|
||||
let mut extra_inits = MemberInitRecord::new(self.c);
|
||||
let mut private_method_fn_decls = vec![];
|
||||
let mut members = vec![];
|
||||
let mut constructor = None;
|
||||
let mut used_names = vec![];
|
||||
let mut used_key_names = vec![];
|
||||
let mut super_ident = None;
|
||||
|
||||
class.body.visit_mut_with(&mut BrandCheckHandler {
|
||||
names: &mut AHashSet::default(),
|
||||
@ -421,7 +415,7 @@ impl ClassProperties {
|
||||
span: c_span,
|
||||
mut expr,
|
||||
}) => {
|
||||
vars.extend(visit_private_in_expr(&mut expr, &self.private));
|
||||
vars.extend(visit_private_in_expr(&mut expr, &self.private, self.c));
|
||||
|
||||
expr.visit_mut_with(&mut ClassNameTdzFolder {
|
||||
class_name: &class_ident,
|
||||
@ -462,21 +456,8 @@ impl ClassProperties {
|
||||
});
|
||||
}
|
||||
|
||||
let key = match prop.key {
|
||||
PropName::Ident(i) => Expr::from(Lit::Str(Str {
|
||||
span: i.span,
|
||||
value: i.sym,
|
||||
has_escape: false,
|
||||
kind: StrKind::Normal {
|
||||
contains_quote: false,
|
||||
},
|
||||
})),
|
||||
PropName::Num(num) => Expr::from(num),
|
||||
PropName::Str(s) => Expr::from(s),
|
||||
PropName::BigInt(big_int) => Expr::from(big_int),
|
||||
|
||||
PropName::Computed(mut key) => {
|
||||
vars.extend(visit_private_in_expr(&mut key.expr, &self.private));
|
||||
if let PropName::Computed(key) = &mut prop.key {
|
||||
vars.extend(visit_private_in_expr(&mut key.expr, &self.private, self.c));
|
||||
let (ident, aliased) = if let Expr::Ident(i) = &*key.expr {
|
||||
if used_key_names.contains(&i.sym) {
|
||||
(alias_ident_for(&key.expr, "_ref"), true)
|
||||
@ -492,21 +473,41 @@ impl ClassProperties {
|
||||
vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.clone().into(),
|
||||
init: Some(key.expr),
|
||||
init: Some(key.expr.take()),
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
Expr::from(ident)
|
||||
}
|
||||
*key.expr = Expr::from(ident);
|
||||
};
|
||||
|
||||
let mut value = prop.value.unwrap_or_else(|| undefined(prop_span));
|
||||
|
||||
value.visit_mut_with(&mut NewTargetInProp);
|
||||
|
||||
vars.extend(visit_private_in_expr(&mut value, &self.private));
|
||||
vars.extend(visit_private_in_expr(&mut value, &self.private, self.c));
|
||||
|
||||
if prop.is_static {
|
||||
if let (Some(super_class), None) = (&mut class.super_class, &super_ident) {
|
||||
let (ident, aliased) = alias_if_required(&*super_class, "_ref");
|
||||
super_ident = Some(ident.clone());
|
||||
|
||||
if aliased {
|
||||
vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.clone().into(),
|
||||
init: None,
|
||||
definite: false,
|
||||
});
|
||||
let span = super_class.span();
|
||||
**super_class = Expr::Assign(AssignExpr {
|
||||
span,
|
||||
op: op!("="),
|
||||
left: PatOrExpr::Pat(Box::new(ident.into())),
|
||||
right: super_class.take(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
value.visit_mut_with(&mut SuperFieldAccessFolder {
|
||||
class_name: &class_ident,
|
||||
vars: &mut vars,
|
||||
@ -516,19 +517,23 @@ impl ClassProperties {
|
||||
in_injected_define_property_call: false,
|
||||
in_nested_scope: false,
|
||||
this_alias_mark: None,
|
||||
// TODO: add loose mode
|
||||
constant_super: false,
|
||||
super_class: &None,
|
||||
constant_super: self.c.constant_super,
|
||||
super_class: &super_ident,
|
||||
});
|
||||
value.visit_mut_with(&mut ThisInStaticFolder {
|
||||
ident: class_ident.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
let init = MemberInit::PubProp(PubProp {
|
||||
span: prop_span,
|
||||
name: prop.key,
|
||||
value,
|
||||
});
|
||||
if prop.is_static {
|
||||
extra_inits.insert(key, MemberInit::Prop(prop_span, value));
|
||||
extra_inits.push(init);
|
||||
} else {
|
||||
constructor_inits.insert(key, MemberInit::Prop(prop_span, value));
|
||||
constructor_inits.push(init);
|
||||
}
|
||||
}
|
||||
ClassMember::PrivateProp(mut prop) => {
|
||||
@ -542,7 +547,7 @@ impl ClassProperties {
|
||||
|
||||
if let Some(value) = &mut prop.value {
|
||||
value.visit_mut_with(&mut NewTargetInProp);
|
||||
vars.extend(visit_private_in_expr(&mut *value, &self.private));
|
||||
vars.extend(visit_private_in_expr(&mut *value, &self.private, self.c));
|
||||
}
|
||||
|
||||
prop.value.visit_with(&mut UsedNameCollector {
|
||||
@ -556,12 +561,27 @@ impl ClassProperties {
|
||||
|
||||
let value = prop.value.unwrap_or_else(|| undefined(prop_span));
|
||||
|
||||
if prop.is_static {
|
||||
extra_inits.insert(ident.into(), MemberInit::Private(prop_span, value));
|
||||
} else {
|
||||
constructor_inits
|
||||
.insert(ident.clone().into(), MemberInit::Private(prop_span, value));
|
||||
|
||||
let init = MemberInit::PrivProp(PrivProp {
|
||||
span: prop_span,
|
||||
name: ident.clone(),
|
||||
value,
|
||||
});
|
||||
if self.c.private_as_properties {
|
||||
vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
definite: false,
|
||||
name: ident.clone().into(),
|
||||
init: Some(Box::new(Expr::from(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: helper!(
|
||||
class_private_field_loose_key,
|
||||
"classPrivateFieldLooseKey"
|
||||
),
|
||||
args: vec![ident.sym.as_arg()],
|
||||
type_args: Default::default(),
|
||||
}))),
|
||||
});
|
||||
} else if !prop.is_static {
|
||||
vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
definite: false,
|
||||
@ -574,6 +594,11 @@ impl ClassProperties {
|
||||
}))),
|
||||
});
|
||||
};
|
||||
if prop.is_static {
|
||||
extra_inits.push(init);
|
||||
} else {
|
||||
constructor_inits.push(init);
|
||||
};
|
||||
}
|
||||
|
||||
ClassMember::Constructor(c) => {
|
||||
@ -607,21 +632,22 @@ impl ClassProperties {
|
||||
|
||||
let extra_collect = match (method.kind, is_static) {
|
||||
(MethodKind::Getter | MethodKind::Setter, false) => {
|
||||
let mut inserted = false;
|
||||
let mut key = weak_coll_var.clone();
|
||||
key.span = DUMMY_SP.with_ctxt(key.span.ctxt);
|
||||
let mut entry =
|
||||
constructor_inits.entry(key.into()).or_insert_with(|| {
|
||||
inserted = true;
|
||||
MemberInit::PrivAccessor(prop_span, None, None)
|
||||
});
|
||||
if let MemberInit::PrivAccessor(_, getter, setter) = &mut entry {
|
||||
if method.kind == MethodKind::Getter {
|
||||
*getter = Some(fn_name.clone())
|
||||
let is_getter = method.kind == MethodKind::Getter;
|
||||
let inserted =
|
||||
constructor_inits.push(MemberInit::PrivAccessor(PrivAccessor {
|
||||
span: prop_span,
|
||||
name: weak_coll_var.clone(),
|
||||
getter: if is_getter {
|
||||
Some(fn_name.clone())
|
||||
} else {
|
||||
*setter = Some(fn_name.clone())
|
||||
}
|
||||
};
|
||||
None
|
||||
},
|
||||
setter: if !is_getter {
|
||||
Some(fn_name.clone())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}));
|
||||
|
||||
if inserted {
|
||||
Some(quote_ident!("WeakMap"))
|
||||
@ -630,29 +656,53 @@ impl ClassProperties {
|
||||
}
|
||||
}
|
||||
(MethodKind::Getter | MethodKind::Setter, true) => {
|
||||
let mut key = weak_coll_var.clone();
|
||||
key.span = DUMMY_SP.with_ctxt(key.span.ctxt);
|
||||
let mut entry = extra_inits
|
||||
.entry(key.into())
|
||||
.or_insert(MemberInit::PrivAccessor(prop_span, None, None));
|
||||
if let MemberInit::PrivAccessor(_, getter, setter) = &mut entry {
|
||||
if method.kind == MethodKind::Getter {
|
||||
*getter = Some(fn_name.clone())
|
||||
let is_getter = method.kind == MethodKind::Getter;
|
||||
let inserted =
|
||||
extra_inits.push(MemberInit::PrivAccessor(PrivAccessor {
|
||||
span: prop_span,
|
||||
name: weak_coll_var.clone(),
|
||||
getter: if is_getter {
|
||||
Some(fn_name.clone())
|
||||
} else {
|
||||
*setter = Some(fn_name.clone())
|
||||
}
|
||||
}
|
||||
None
|
||||
},
|
||||
setter: if !is_getter {
|
||||
Some(fn_name.clone())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}));
|
||||
if inserted && self.c.private_as_properties {
|
||||
Some(Ident::dummy())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
(MethodKind::Method, false) => {
|
||||
constructor_inits.insert(
|
||||
weak_coll_var.clone().into(),
|
||||
MemberInit::PrivMethod(prop_span),
|
||||
);
|
||||
constructor_inits.push(MemberInit::PrivMethod(PrivMethod {
|
||||
span: prop_span,
|
||||
name: weak_coll_var.clone(),
|
||||
fn_name: if self.c.private_as_properties {
|
||||
fn_name.clone()
|
||||
} else {
|
||||
Ident::dummy()
|
||||
},
|
||||
}));
|
||||
Some(quote_ident!("WeakSet"))
|
||||
}
|
||||
(MethodKind::Method, true) => None,
|
||||
(MethodKind::Method, true) => {
|
||||
if self.c.private_as_properties {
|
||||
extra_inits.push(MemberInit::PrivMethod(PrivMethod {
|
||||
span: prop_span,
|
||||
name: weak_coll_var.clone(),
|
||||
fn_name: fn_name.clone(),
|
||||
}));
|
||||
Some(Ident::dummy())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(extra) = extra_collect {
|
||||
@ -660,12 +710,24 @@ impl ClassProperties {
|
||||
span: DUMMY_SP,
|
||||
definite: false,
|
||||
name: weak_coll_var.clone().into(),
|
||||
init: Some(Box::new(Expr::from(NewExpr {
|
||||
init: Some(Box::new(if self.c.private_as_properties {
|
||||
Expr::from(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: helper!(
|
||||
class_private_field_loose_key,
|
||||
"classPrivateFieldLooseKey"
|
||||
),
|
||||
args: vec![weak_coll_var.sym.as_arg()],
|
||||
type_args: Default::default(),
|
||||
})
|
||||
} else {
|
||||
Expr::New(NewExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: Box::new(Expr::Ident(extra)),
|
||||
args: Some(Default::default()),
|
||||
type_args: Default::default(),
|
||||
}))),
|
||||
})
|
||||
})),
|
||||
})
|
||||
};
|
||||
|
||||
@ -691,86 +753,18 @@ impl ClassProperties {
|
||||
private: &self.private,
|
||||
vars: vec![],
|
||||
in_assign_pat: false,
|
||||
c: self.c,
|
||||
});
|
||||
|
||||
let extra_stmts = extra_inits
|
||||
.into_iter()
|
||||
.map(|(key, value)| match value {
|
||||
MemberInit::Prop(span, value) => Stmt::Expr(ExprStmt {
|
||||
span,
|
||||
expr: Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: helper!(define_property, "defineProperty"),
|
||||
args: vec![class_ident.clone().as_arg(), key.as_arg(), value.as_arg()],
|
||||
type_args: Default::default(),
|
||||
})
|
||||
.into(),
|
||||
}),
|
||||
MemberInit::Private(span, value) => Stmt::Decl(Decl::Var(VarDecl {
|
||||
span,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span,
|
||||
name: key.expect_ident().into(),
|
||||
init: Some(
|
||||
Expr::Object(ObjectLit {
|
||||
span,
|
||||
props: vec![
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("writable")),
|
||||
value: true.into(),
|
||||
}))),
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("value")),
|
||||
value,
|
||||
}))),
|
||||
],
|
||||
})
|
||||
.into(),
|
||||
),
|
||||
definite: false,
|
||||
}],
|
||||
declare: false,
|
||||
})),
|
||||
MemberInit::PrivAccessor(span, getter, setter) => Stmt::Decl(Decl::Var(VarDecl {
|
||||
span,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span,
|
||||
name: key.expect_ident().into(),
|
||||
init: Some(
|
||||
Expr::Object(ObjectLit {
|
||||
span,
|
||||
props: vec![
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("get")),
|
||||
value: getter
|
||||
.map(|id| Box::new(id.into()))
|
||||
.unwrap_or_else(|| undefined(DUMMY_SP)),
|
||||
}))),
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("set")),
|
||||
value: setter
|
||||
.map(|id| Box::new(id.into()))
|
||||
.unwrap_or_else(|| undefined(DUMMY_SP)),
|
||||
}))),
|
||||
],
|
||||
})
|
||||
.into(),
|
||||
),
|
||||
definite: false,
|
||||
}],
|
||||
declare: false,
|
||||
})),
|
||||
MemberInit::PrivMethod(_) => unreachable!(),
|
||||
})
|
||||
.chain(private_method_fn_decls)
|
||||
.collect();
|
||||
let mut extra_stmts = extra_inits.into_init_static(class_ident.clone());
|
||||
|
||||
extra_stmts.extend(private_method_fn_decls);
|
||||
|
||||
members.visit_mut_with(&mut PrivateAccessVisitor {
|
||||
private: &self.private,
|
||||
vars: vec![],
|
||||
in_assign_pat: false,
|
||||
c: self.c,
|
||||
});
|
||||
|
||||
self.private.pop();
|
||||
@ -823,10 +817,10 @@ impl ClassProperties {
|
||||
&mut self,
|
||||
constructor: Option<Constructor>,
|
||||
has_super: bool,
|
||||
constructor_exprs: MemberInitMap,
|
||||
constructor_exprs: MemberInitRecord,
|
||||
) -> Option<Constructor> {
|
||||
let constructor = constructor.or_else(|| {
|
||||
if constructor_exprs.is_empty() {
|
||||
if constructor_exprs.record.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(default_constructor(has_super))
|
||||
@ -834,91 +828,7 @@ impl ClassProperties {
|
||||
});
|
||||
|
||||
if let Some(mut c) = constructor {
|
||||
let constructor_exprs = constructor_exprs
|
||||
.into_iter()
|
||||
.map(|(key, value)| {
|
||||
let (span, callee, args) = match value {
|
||||
MemberInit::PrivMethod(span) => (
|
||||
span,
|
||||
helper!(class_private_method_init, "classPrivateMethodInit"),
|
||||
vec![ThisExpr { span: DUMMY_SP }.as_arg(), key.as_arg()],
|
||||
),
|
||||
MemberInit::Private(span, value) => (
|
||||
span,
|
||||
helper!(class_private_field_init, "classPrivateFieldInit"),
|
||||
vec![
|
||||
ThisExpr { span: DUMMY_SP }.as_arg(),
|
||||
key.as_arg(),
|
||||
ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
// writeable: true
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("writable")),
|
||||
value: true.into(),
|
||||
},
|
||||
))),
|
||||
// value: value,
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("value")),
|
||||
value,
|
||||
},
|
||||
))),
|
||||
],
|
||||
}
|
||||
.as_arg(),
|
||||
],
|
||||
),
|
||||
MemberInit::PrivAccessor(span, getter, setter) => (
|
||||
span,
|
||||
helper!(class_private_field_init, "classPrivateFieldInit"),
|
||||
vec![
|
||||
ThisExpr { span: DUMMY_SP }.as_arg(),
|
||||
key.as_arg(),
|
||||
ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("get")),
|
||||
value: getter
|
||||
.map(|id| Box::new(id.into()))
|
||||
.unwrap_or_else(|| undefined(DUMMY_SP)),
|
||||
},
|
||||
))),
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("set")),
|
||||
value: setter
|
||||
.map(|id| Box::new(id.into()))
|
||||
.unwrap_or_else(|| undefined(DUMMY_SP)),
|
||||
},
|
||||
))),
|
||||
],
|
||||
}
|
||||
.as_arg(),
|
||||
],
|
||||
),
|
||||
MemberInit::Prop(span, value) => (
|
||||
span,
|
||||
helper!(define_property, "defineProperty"),
|
||||
vec![
|
||||
ThisExpr { span: DUMMY_SP }.as_arg(),
|
||||
key.as_arg(),
|
||||
value.as_arg(),
|
||||
],
|
||||
),
|
||||
};
|
||||
Box::new(Expr::Call(CallExpr {
|
||||
span,
|
||||
callee,
|
||||
args,
|
||||
type_args: Default::default(),
|
||||
}))
|
||||
})
|
||||
.collect();
|
||||
let constructor_exprs = constructor_exprs.into_init();
|
||||
// Prepend properties
|
||||
inject_after_super(&mut c, constructor_exprs);
|
||||
Some(c)
|
||||
|
@ -9,10 +9,13 @@ use swc_common::{
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::helper;
|
||||
use swc_ecma_utils::{
|
||||
alias_ident_for, alias_if_required, prepend, quote_ident, undefined, ExprFactory, HANDLER,
|
||||
alias_ident_for, alias_if_required, opt_chain_test, prepend, quote_ident, undefined,
|
||||
ExprFactory, HANDLER,
|
||||
};
|
||||
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
|
||||
|
||||
use super::Config;
|
||||
|
||||
pub(super) struct Private {
|
||||
pub mark: Mark,
|
||||
pub class_name: Ident,
|
||||
@ -135,6 +138,7 @@ pub(super) struct PrivateAccessVisitor<'a> {
|
||||
pub vars: Vec<VarDeclarator>,
|
||||
pub private: &'a PrivateRecord,
|
||||
pub in_assign_pat: bool,
|
||||
pub c: Config,
|
||||
}
|
||||
|
||||
macro_rules! take_vars {
|
||||
@ -175,6 +179,30 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
|
||||
take_vars!(visit_mut_constructor, Constructor);
|
||||
|
||||
fn visit_mut_expr(&mut self, e: &mut Expr) {
|
||||
if self.c.private_as_properties {
|
||||
if let Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj,
|
||||
prop: MemberProp::PrivateName(n),
|
||||
}) = e
|
||||
{
|
||||
obj.visit_mut_children_with(self);
|
||||
let (mark, _, _) = self.private.get(&n.id);
|
||||
let ident = Ident::new(format!("_{}", n.id.sym).into(), n.id.span.apply_mark(mark));
|
||||
|
||||
*e = Expr::Call(CallExpr {
|
||||
callee: helper!(class_private_field_loose_base, "classPrivateFieldLooseBase"),
|
||||
span: *span,
|
||||
args: vec![obj.take().as_arg(), ident.clone().as_arg()],
|
||||
type_args: None,
|
||||
})
|
||||
.computed_member(ident);
|
||||
} else {
|
||||
e.visit_mut_children_with(self)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
match e {
|
||||
Expr::Update(UpdateExpr {
|
||||
span,
|
||||
@ -539,22 +567,12 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
|
||||
|
||||
*e = Expr::Cond(CondExpr {
|
||||
span: *span,
|
||||
test: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: Box::new(ident.clone().into()),
|
||||
op: op!("==="),
|
||||
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
|
||||
})),
|
||||
op: op!("||"),
|
||||
right: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: Box::new(ident.into()),
|
||||
op: op!("==="),
|
||||
right: undefined(DUMMY_SP),
|
||||
})),
|
||||
})),
|
||||
test: Box::new(opt_chain_test(
|
||||
Box::new(ident.clone().into()),
|
||||
Box::new(ident.into()),
|
||||
*span,
|
||||
self.c.no_document_all,
|
||||
)),
|
||||
cons: undefined(DUMMY_SP),
|
||||
alt: Box::new(expr),
|
||||
})
|
||||
@ -584,11 +602,13 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
|
||||
pub(super) fn visit_private_in_expr(
|
||||
expr: &mut Expr,
|
||||
private: &PrivateRecord,
|
||||
config: Config,
|
||||
) -> Vec<VarDeclarator> {
|
||||
let mut priv_visitor = PrivateAccessVisitor {
|
||||
private,
|
||||
vars: vec![],
|
||||
in_assign_pat: false,
|
||||
c: config,
|
||||
};
|
||||
|
||||
expr.visit_mut_with(&mut priv_visitor);
|
||||
@ -701,7 +721,9 @@ impl<'a> PrivateAccessVisitor<'a> {
|
||||
);
|
||||
}
|
||||
|
||||
let get = if kind.is_method {
|
||||
let get = if self.c.private_as_properties {
|
||||
helper!(class_private_field_loose_base, "classPrivateFieldLooseBase")
|
||||
} else if kind.is_method {
|
||||
helper!(class_private_method_get, "classPrivateMethodGet")
|
||||
} else {
|
||||
helper!(class_private_field_get, "classPrivateFieldGet")
|
||||
@ -709,7 +731,7 @@ impl<'a> PrivateAccessVisitor<'a> {
|
||||
|
||||
match &*obj {
|
||||
Expr::This(this) => (
|
||||
if kind.is_method {
|
||||
if kind.is_method && !self.c.private_as_properties {
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: get,
|
||||
|
@ -13,14 +13,12 @@ pub mod static_blocks;
|
||||
pub fn es2022(config: Config) -> impl Fold {
|
||||
chain!(
|
||||
static_blocks(),
|
||||
class_properties(class_properties::Config {
|
||||
loose: config.loose,
|
||||
}),
|
||||
class_properties(config.class_properties),
|
||||
private_in_object(),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Config {
|
||||
pub loose: bool,
|
||||
pub class_properties: class_properties::Config,
|
||||
}
|
||||
|
@ -6549,7 +6549,7 @@ test!(
|
||||
let global_mark = Mark::fresh(Mark::root());
|
||||
|
||||
chain!(
|
||||
es2022::es2022(es2022::Config { loose: false }),
|
||||
es2022::es2022(Default::default()),
|
||||
es2018::es2018(Default::default()),
|
||||
es2017::es2017(),
|
||||
es2016::es2016(),
|
||||
@ -6590,7 +6590,7 @@ test!(
|
||||
let global_mark = Mark::fresh(Mark::root());
|
||||
|
||||
chain!(
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
es2015::es2015(
|
||||
global_mark,
|
||||
Some(t.comments.clone()),
|
||||
@ -6673,7 +6673,7 @@ test!(
|
||||
let global_mark = Mark::fresh(Mark::root());
|
||||
|
||||
chain!(
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
es2015::es2015(
|
||||
global_mark,
|
||||
Some(t.comments.clone()),
|
||||
@ -6720,7 +6720,7 @@ test!(
|
||||
let global_mark = Mark::fresh(Mark::root());
|
||||
|
||||
chain!(
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
es2015::es2015(
|
||||
global_mark,
|
||||
Some(t.comments.clone()),
|
||||
@ -6768,7 +6768,7 @@ fn exec(input: PathBuf) {
|
||||
Default::default(),
|
||||
|t| {
|
||||
chain!(
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
classes(Some(t.comments.clone()), Default::default())
|
||||
)
|
||||
},
|
||||
@ -6784,7 +6784,7 @@ fn fixture(input: PathBuf) {
|
||||
Default::default(),
|
||||
&|t| {
|
||||
chain!(
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
classes(Some(t.comments.clone()), Default::default())
|
||||
)
|
||||
},
|
||||
|
@ -44,18 +44,35 @@ fn fixture(input: PathBuf) {
|
||||
let mut pass: Box<dyn Fold> = Box::new(noop());
|
||||
|
||||
for plugin in &options.plugins {
|
||||
let (name, _option) = match plugin {
|
||||
let (name, option) = match plugin {
|
||||
PluginConfig::WithOption(name, config) => (name, config.clone()),
|
||||
PluginConfig::Name(name) => (name, serde_json::Value::Null),
|
||||
};
|
||||
|
||||
let loose = option
|
||||
.as_object()
|
||||
.and_then(|opt| opt.get("loose"))
|
||||
.and_then(|loose| {
|
||||
if let Some(true) = loose.as_bool() {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.is_some();
|
||||
|
||||
match &**name {
|
||||
"transform-new-target" => {}
|
||||
|
||||
"proposal-class-properties" => {
|
||||
pass = Box::new(chain!(
|
||||
pass,
|
||||
class_properties(class_properties::Config { loose: false })
|
||||
class_properties(class_properties::Config {
|
||||
constant_super: loose,
|
||||
set_public_fields: loose,
|
||||
private_as_properties: loose,
|
||||
no_document_all: loose
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -1824,7 +1824,7 @@ test!(
|
||||
|_| {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
chain!(
|
||||
es2022(es2022::Config { loose: false }),
|
||||
es2022(Default::default()),
|
||||
es2021(),
|
||||
es2018(Default::default()),
|
||||
es2017(),
|
||||
|
@ -2291,10 +2291,7 @@ test!(
|
||||
|
||||
test_exec!(
|
||||
Syntax::default(),
|
||||
|_| chain!(
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
async_to_generator()
|
||||
),
|
||||
|_| chain!(class_properties(Default::default()), async_to_generator()),
|
||||
issue_1341_1_exec,
|
||||
"
|
||||
class A {
|
||||
@ -2347,10 +2344,7 @@ test!(
|
||||
|
||||
test_exec!(
|
||||
Syntax::default(),
|
||||
|_| chain!(
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
async_to_generator()
|
||||
),
|
||||
|_| chain!(class_properties(Default::default()), async_to_generator()),
|
||||
issue_1341_2_exec,
|
||||
"
|
||||
class A {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -47,6 +47,8 @@ fn fixture(input: PathBuf) {
|
||||
PluginConfig::Name(name) => (name, serde_json::Value::Null),
|
||||
};
|
||||
|
||||
let loose = input.to_string_lossy().contains("private-loose");
|
||||
|
||||
match &**name {
|
||||
"proposal-private-property-in-object" => {}
|
||||
|
||||
@ -56,7 +58,10 @@ fn fixture(input: PathBuf) {
|
||||
pass = Box::new(chain!(
|
||||
pass,
|
||||
class_properties(class_properties::Config {
|
||||
loose: input.to_string_lossy().contains("private-loose")
|
||||
set_public_fields: loose,
|
||||
constant_super: loose,
|
||||
no_document_all: loose,
|
||||
private_as_properties: loose
|
||||
})
|
||||
));
|
||||
}
|
||||
@ -68,7 +73,10 @@ fn fixture(input: PathBuf) {
|
||||
pass = Box::new(chain!(
|
||||
pass,
|
||||
class_properties(class_properties::Config {
|
||||
loose: input.to_string_lossy().contains("private-loose")
|
||||
set_public_fields: loose,
|
||||
constant_super: loose,
|
||||
no_document_all: loose,
|
||||
private_as_properties: loose
|
||||
})
|
||||
));
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"transform-new-target",
|
||||
"transform-arrow-functions",
|
||||
["proposal-class-properties", { "loose": true }]
|
||||
]
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"plugins": [
|
||||
["proposal-class-properties", { "loose": true }],
|
||||
"transform-new-target",
|
||||
"transform-arrow-functions"
|
||||
]
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
class Foo {
|
||||
constructor(){
|
||||
this.test = function _target() {
|
||||
this.constructor;
|
||||
};
|
||||
this.test2 = function() {
|
||||
void 0;
|
||||
};
|
||||
this.Bar = (function _target() {
|
||||
class _class {
|
||||
constructor(){
|
||||
this.q = void 0;
|
||||
}
|
||||
}
|
||||
_class.p = void 0;
|
||||
_class.p1 = class _class {
|
||||
constructor(){
|
||||
this.constructor;
|
||||
}
|
||||
};
|
||||
_class.p2 = new function _target() {
|
||||
this.constructor;
|
||||
};
|
||||
_class.p3 = function() {
|
||||
void 0;
|
||||
};
|
||||
_class.p4 = function _target() {
|
||||
this.constructor;
|
||||
};
|
||||
return _class;
|
||||
})();
|
||||
}
|
||||
}
|
@ -548,7 +548,7 @@ test!(
|
||||
decorators(Default::default()),
|
||||
resolver_with_mark(mark),
|
||||
strip(mark),
|
||||
class_properties(class_properties::Config { loose: false }),
|
||||
class_properties(Default::default()),
|
||||
simplifier(Default::default()),
|
||||
es2018(Default::default()),
|
||||
es2017(),
|
||||
|
@ -96,11 +96,7 @@ fn common_reserved_word(b: &mut Bencher) {
|
||||
|
||||
#[bench]
|
||||
fn es2020(b: &mut Bencher) {
|
||||
run(b, || {
|
||||
swc_ecma_transforms_compat::es2022(swc_ecma_transforms_compat::es2022::Config {
|
||||
loose: false,
|
||||
})
|
||||
});
|
||||
run(b, || swc_ecma_transforms_compat::es2022(Default::default()));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
@ -1617,6 +1617,9 @@ pub fn alias_ident_for(expr: &Expr, default: &str) -> Ident {
|
||||
| Expr::Member(MemberExpr {
|
||||
prop: MemberProp::Ident(ident),
|
||||
..
|
||||
})
|
||||
| Expr::Class(ClassExpr {
|
||||
ident: Some(ident), ..
|
||||
}) => format!("_{}", ident.sym).into(),
|
||||
Expr::Member(MemberExpr {
|
||||
prop: MemberProp::Computed(computed),
|
||||
@ -1736,6 +1739,39 @@ pub fn undefined(span: Span) -> Box<Expr> {
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn opt_chain_test(
|
||||
left: Box<Expr>,
|
||||
right: Box<Expr>,
|
||||
span: Span,
|
||||
no_document_all: bool,
|
||||
) -> Expr {
|
||||
if no_document_all {
|
||||
Expr::Bin(BinExpr {
|
||||
span,
|
||||
left,
|
||||
op: op!("=="),
|
||||
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
|
||||
})
|
||||
} else {
|
||||
Expr::Bin(BinExpr {
|
||||
span,
|
||||
left: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left,
|
||||
op: op!("==="),
|
||||
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
|
||||
})),
|
||||
op: op!("||"),
|
||||
right: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: right,
|
||||
op: op!("==="),
|
||||
right: undefined(DUMMY_SP),
|
||||
})),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// inject `branch` after directives
|
||||
#[inline(never)]
|
||||
pub fn prepend<T: StmtLike>(stmts: &mut Vec<T>, stmt: T) {
|
||||
|
@ -0,0 +1,5 @@
|
||||
var id = 0;
|
||||
|
||||
export function _classPrivateFieldLooseKey(name) {
|
||||
return "__private_" + id++ + "_" + name;
|
||||
}
|
Loading…
Reference in New Issue
Block a user