fix: ensure (a?.b)() has proper this (#11623)
* fix: ensure (a?.b)() has proper this * let test be more restrictive * fix: transformed member call should preserve computed * chore: revamp test files * refactor: simplify * fix: unwrap parthenthesizedExpression * add loose test cases * add `(a?.#b)()` support * add with-transform test cases * Update packages/babel-plugin-proposal-optional-chaining/src/index.js Co-authored-by: Justin Ridgewell <justin@ridgewell.name> * address review comments * update test fixtures Co-authored-by: Justin Ridgewell <justin@ridgewell.name>
This commit is contained in:
parent
3a3457d808
commit
1e115aed33
@ -241,6 +241,15 @@ const privateNameHandlerSpec = {
|
|||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
boundGet(member) {
|
||||||
|
this.memoise(member, 1);
|
||||||
|
|
||||||
|
return t.callExpression(
|
||||||
|
t.memberExpression(this.get(member), t.identifier("bind")),
|
||||||
|
[this.receiver(member)],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
set(member, value) {
|
set(member, value) {
|
||||||
const { classRef, privateNamesMap, file } = this;
|
const { classRef, privateNamesMap, file } = this;
|
||||||
const { name } = member.node.property.id;
|
const { name } = member.node.property.id;
|
||||||
@ -323,6 +332,13 @@ const privateNameHandlerLoose = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
boundGet(member) {
|
||||||
|
return t.callExpression(
|
||||||
|
t.memberExpression(this.get(member), t.identifier("bind")),
|
||||||
|
[t.cloneNode(member.node.object)],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
simpleSet(member) {
|
simpleSet(member) {
|
||||||
return this.get(member);
|
return this.get(member);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -167,6 +167,9 @@ const handle = {
|
|||||||
const parentIsOptionalCall = parentPath.isOptionalCallExpression({
|
const parentIsOptionalCall = parentPath.isOptionalCallExpression({
|
||||||
callee: node,
|
callee: node,
|
||||||
});
|
});
|
||||||
|
const isParenthesizedMemberCall =
|
||||||
|
parentPath.isCallExpression({ callee: node }) &&
|
||||||
|
node.extra?.parenthesized;
|
||||||
startingOptional.replaceWith(toNonOptional(startingOptional, baseRef));
|
startingOptional.replaceWith(toNonOptional(startingOptional, baseRef));
|
||||||
if (parentIsOptionalCall) {
|
if (parentIsOptionalCall) {
|
||||||
if (parent.optional) {
|
if (parent.optional) {
|
||||||
@ -174,6 +177,9 @@ const handle = {
|
|||||||
} else {
|
} else {
|
||||||
parentPath.replaceWith(this.call(member, parent.arguments));
|
parentPath.replaceWith(this.call(member, parent.arguments));
|
||||||
}
|
}
|
||||||
|
} else if (isParenthesizedMemberCall) {
|
||||||
|
// `(a?.#b)()` to `(a == null ? void 0 : a.#b.bind(a))()`
|
||||||
|
member.replaceWith(this.boundGet(member));
|
||||||
} else {
|
} else {
|
||||||
member.replaceWith(this.get(member));
|
member.replaceWith(this.get(member));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
class Foo {
|
||||||
|
static #x = 1;
|
||||||
|
|
||||||
|
static self = Foo;
|
||||||
|
static #m = function() { return this.#x; };
|
||||||
|
static getSelf() { return Foo }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect((Foo?.#m)()).toEqual(1);
|
||||||
|
expect((Foo?.#m)().toString).toEqual(1..toString);
|
||||||
|
expect((Foo?.#m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((o?.Foo.#m)()).toEqual(1);
|
||||||
|
expect((o?.Foo.#m)().toString).toEqual(1..toString);
|
||||||
|
expect((o?.Foo.#m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((((o.Foo?.self.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
expect((((o.Foo.self?.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
|
||||||
|
expect((((fn()?.Foo?.self.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
expect((((fn?.().Foo.self?.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
testNull() {
|
||||||
|
const o = null;
|
||||||
|
const fn = function () {
|
||||||
|
return { o };
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(() => { (o?.Foo.#m)() }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.#m)().toString }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.#m)().toString() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => { (((o.Foo?.self.getSelf)())?.#m)() }).toThrow();
|
||||||
|
expect(() => { (((o.Foo.self?.getSelf)())?.#m)() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => (((fn()?.Foo?.self.getSelf)())?.#m)()).toThrow();
|
||||||
|
expect(() => (((fn?.().Foo.self?.getSelf)())?.#m)()).toThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
|
(new Foo).testNull();
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
class Foo {
|
||||||
|
static #x = 1;
|
||||||
|
|
||||||
|
static self = Foo;
|
||||||
|
static #m = function() { return this.#x; };
|
||||||
|
static getSelf() { return Foo }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo?.#m)();
|
||||||
|
(Foo?.#m)().toString;
|
||||||
|
(Foo?.#m)().toString();
|
||||||
|
|
||||||
|
(o?.Foo.#m)();
|
||||||
|
(o?.Foo.#m)().toString;
|
||||||
|
(o?.Foo.#m)().toString();
|
||||||
|
|
||||||
|
(((o.Foo?.self.getSelf)())?.#m)();
|
||||||
|
(((o.Foo.self?.getSelf)())?.#m)();
|
||||||
|
|
||||||
|
(((fn()?.Foo?.self.getSelf)())?.#m)();
|
||||||
|
(((fn?.().Foo.self?.getSelf)())?.#m)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["external-helpers", { "helperVersion": "7.100.0" }],
|
||||||
|
["proposal-class-properties", { "loose": true }],
|
||||||
|
["proposal-optional-chaining", { "loose": true }]
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
class Foo {
|
||||||
|
static getSelf() {
|
||||||
|
return Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
var _o$Foo$self$getSelf, _o$Foo$self$getSelf2, _fn$Foo$self$getSelf, _fn$Foo$self$getSelf2, _o$Foo, _o$Foo$self, _fn, _fn$Foo, _fn$Foo$self, _fn$Foo$self2;
|
||||||
|
|
||||||
|
const o = {
|
||||||
|
Foo: Foo
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(Foo, _m)[_m].bind(Foo))();
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(Foo, _m)[_m].bind(Foo))().toString;
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(Foo, _m)[_m].bind(Foo))().toString();
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(o.Foo, _m)[_m].bind(o.Foo))();
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(o.Foo, _m)[_m].bind(o.Foo))().toString;
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(o.Foo, _m)[_m].bind(o.Foo))().toString();
|
||||||
|
((_o$Foo$self$getSelf = ((_o$Foo = o.Foo) == null ? void 0 : _o$Foo.self.getSelf.bind(_o$Foo.self))()) === null || _o$Foo$self$getSelf === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(_o$Foo$self$getSelf, _m)[_m].bind(_o$Foo$self$getSelf))();
|
||||||
|
((_o$Foo$self$getSelf2 = ((_o$Foo$self = o.Foo.self) == null ? void 0 : _o$Foo$self.getSelf.bind(_o$Foo$self))()) === null || _o$Foo$self$getSelf2 === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(_o$Foo$self$getSelf2, _m)[_m].bind(_o$Foo$self$getSelf2))();
|
||||||
|
((_fn$Foo$self$getSelf = ((_fn = fn()) == null ? void 0 : (_fn$Foo = _fn.Foo) == null ? void 0 : _fn$Foo.self.getSelf.bind(_fn.Foo.self))()) === null || _fn$Foo$self$getSelf === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(_fn$Foo$self$getSelf, _m)[_m].bind(_fn$Foo$self$getSelf))();
|
||||||
|
((_fn$Foo$self$getSelf2 = (fn == null ? void 0 : (_fn$Foo$self2 = _fn$Foo$self = fn().Foo.self) == null ? void 0 : _fn$Foo$self2.getSelf.bind(_fn$Foo$self))()) === null || _fn$Foo$self$getSelf2 === void 0 ? void 0 : babelHelpers.classPrivateFieldLooseBase(_fn$Foo$self$getSelf2, _m)[_m].bind(_fn$Foo$self$getSelf2))();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var _x = babelHelpers.classPrivateFieldLooseKey("x");
|
||||||
|
|
||||||
|
var _m = babelHelpers.classPrivateFieldLooseKey("m");
|
||||||
|
|
||||||
|
Object.defineProperty(Foo, _x, {
|
||||||
|
writable: true,
|
||||||
|
value: 1
|
||||||
|
});
|
||||||
|
Foo.self = Foo;
|
||||||
|
Object.defineProperty(Foo, _m, {
|
||||||
|
writable: true,
|
||||||
|
value: function () {
|
||||||
|
return babelHelpers.classPrivateFieldLooseBase(this, _x)[_x];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
new Foo().test();
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
class Foo {
|
||||||
|
static #x = 1;
|
||||||
|
|
||||||
|
static self = Foo;
|
||||||
|
static #m = function() { return this.#x; };
|
||||||
|
static getSelf() { return Foo }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect((Foo?.#m)()).toEqual(1);
|
||||||
|
expect((Foo?.#m)().toString).toEqual(1..toString);
|
||||||
|
expect((Foo?.#m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((o?.Foo.#m)()).toEqual(1);
|
||||||
|
expect((o?.Foo.#m)().toString).toEqual(1..toString);
|
||||||
|
expect((o?.Foo.#m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((((o.Foo?.self.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
expect((((o.Foo.self?.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
|
||||||
|
expect((((fn()?.Foo?.self.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
expect((((fn?.().Foo.self?.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
testNull() {
|
||||||
|
const o = null;
|
||||||
|
const fn = function () {
|
||||||
|
return { o };
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(() => { (o?.Foo.#m)() }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.#m)().toString }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.#m)().toString() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => { (((o.Foo?.self.getSelf)())?.#m)() }).toThrow();
|
||||||
|
expect(() => { (((o.Foo.self?.getSelf)())?.#m)() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => (((fn()?.Foo?.self.getSelf)())?.#m)()).toThrow();
|
||||||
|
expect(() => (((fn?.().Foo.self?.getSelf)())?.#m)()).toThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
|
(new Foo).testNull();
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
class Foo {
|
||||||
|
static #x = 1;
|
||||||
|
|
||||||
|
static self = Foo;
|
||||||
|
static #m = function() { return this.#x; };
|
||||||
|
static getSelf() { return Foo }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo?.#m)();
|
||||||
|
(Foo?.#m)().toString;
|
||||||
|
(Foo?.#m)().toString();
|
||||||
|
|
||||||
|
(o?.Foo.#m)();
|
||||||
|
(o?.Foo.#m)().toString;
|
||||||
|
(o?.Foo.#m)().toString();
|
||||||
|
|
||||||
|
(((o.Foo?.self.getSelf)())?.#m)();
|
||||||
|
(((o.Foo.self?.getSelf)())?.#m)();
|
||||||
|
|
||||||
|
(((fn()?.Foo?.self.getSelf)())?.#m)();
|
||||||
|
(((fn?.().Foo.self?.getSelf)())?.#m)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["external-helpers", { "helperVersion": "7.100.0" }],
|
||||||
|
"proposal-class-properties"
|
||||||
|
],
|
||||||
|
"minNodeVersion": "14.0.0"
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
class Foo {
|
||||||
|
static getSelf() {
|
||||||
|
return Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
var _o$Foo, _o$Foo2, _o$Foo3, _o$Foo$self$getSelf, _o$Foo$self$getSelf2, _fn$Foo$self$getSelf, _fn$Foo$self$getSelf2;
|
||||||
|
|
||||||
|
const o = {
|
||||||
|
Foo: Foo
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _m).bind(Foo))();
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _m).bind(Foo))().toString;
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _m).bind(Foo))().toString();
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo = o.Foo, Foo, _m).bind(_o$Foo))();
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo2 = o.Foo, Foo, _m).bind(_o$Foo2))().toString;
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo3 = o.Foo, Foo, _m).bind(_o$Foo3))().toString();
|
||||||
|
((_o$Foo$self$getSelf = (o.Foo?.self.getSelf)()) === null || _o$Foo$self$getSelf === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo$self$getSelf, Foo, _m).bind(_o$Foo$self$getSelf))();
|
||||||
|
((_o$Foo$self$getSelf2 = (o.Foo.self?.getSelf)()) === null || _o$Foo$self$getSelf2 === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo$self$getSelf2, Foo, _m).bind(_o$Foo$self$getSelf2))();
|
||||||
|
((_fn$Foo$self$getSelf = (fn()?.Foo?.self.getSelf)()) === null || _fn$Foo$self$getSelf === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_fn$Foo$self$getSelf, Foo, _m).bind(_fn$Foo$self$getSelf))();
|
||||||
|
((_fn$Foo$self$getSelf2 = (fn?.().Foo.self?.getSelf)()) === null || _fn$Foo$self$getSelf2 === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_fn$Foo$self$getSelf2, Foo, _m).bind(_fn$Foo$self$getSelf2))();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var _x = {
|
||||||
|
writable: true,
|
||||||
|
value: 1
|
||||||
|
};
|
||||||
|
babelHelpers.defineProperty(Foo, "self", Foo);
|
||||||
|
var _m = {
|
||||||
|
writable: true,
|
||||||
|
value: function () {
|
||||||
|
return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new Foo().test();
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
class Foo {
|
||||||
|
static #x = 1;
|
||||||
|
|
||||||
|
static self = Foo;
|
||||||
|
static #m = function() { return this.#x; };
|
||||||
|
static getSelf() { return Foo }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect((Foo?.#m)()).toEqual(1);
|
||||||
|
expect((Foo?.#m)().toString).toEqual(1..toString);
|
||||||
|
expect((Foo?.#m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((o?.Foo.#m)()).toEqual(1);
|
||||||
|
expect((o?.Foo.#m)().toString).toEqual(1..toString);
|
||||||
|
expect((o?.Foo.#m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((((o.Foo?.self.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
expect((((o.Foo.self?.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
|
||||||
|
expect((((fn()?.Foo?.self.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
expect((((fn?.().Foo.self?.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
testNull() {
|
||||||
|
const o = null;
|
||||||
|
const fn = function () {
|
||||||
|
return { o };
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(() => { (o?.Foo.#m)() }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.#m)().toString }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.#m)().toString() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => { (((o.Foo?.self.getSelf)())?.#m)() }).toThrow();
|
||||||
|
expect(() => { (((o.Foo.self?.getSelf)())?.#m)() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => (((fn()?.Foo?.self.getSelf)())?.#m)()).toThrow();
|
||||||
|
expect(() => (((fn?.().Foo.self?.getSelf)())?.#m)()).toThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
|
(new Foo).testNull();
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
class Foo {
|
||||||
|
static #x = 1;
|
||||||
|
|
||||||
|
static self = Foo;
|
||||||
|
static #m = function() { return this.#x; };
|
||||||
|
static getSelf() { return Foo }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo?.#m)();
|
||||||
|
(Foo?.#m)().toString;
|
||||||
|
(Foo?.#m)().toString();
|
||||||
|
|
||||||
|
(o?.Foo.#m)();
|
||||||
|
(o?.Foo.#m)().toString;
|
||||||
|
(o?.Foo.#m)().toString();
|
||||||
|
|
||||||
|
(((o.Foo?.self.getSelf)())?.#m)();
|
||||||
|
(((o.Foo.self?.getSelf)())?.#m)();
|
||||||
|
|
||||||
|
(((fn()?.Foo?.self.getSelf)())?.#m)();
|
||||||
|
(((fn?.().Foo.self?.getSelf)())?.#m)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["external-helpers", { "helperVersion": "7.100.0" }],
|
||||||
|
"proposal-class-properties",
|
||||||
|
"proposal-optional-chaining"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
class Foo {
|
||||||
|
static getSelf() {
|
||||||
|
return Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
var _o$Foo, _o$Foo2, _o$Foo3, _o$Foo$self$getSelf, _o$Foo$self$getSelf2, _fn$Foo$self$getSelf, _fn$Foo$self$getSelf2, _o$Foo4, _o$Foo4$self, _o$Foo$self, _fn, _fn$Foo$self, _fn$Foo, _fn$Foo$self2, _fn$Foo$self3;
|
||||||
|
|
||||||
|
const o = {
|
||||||
|
Foo: Foo
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _m).bind(Foo))();
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _m).bind(Foo))().toString;
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _m).bind(Foo))().toString();
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo = o.Foo, Foo, _m).bind(_o$Foo))();
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo2 = o.Foo, Foo, _m).bind(_o$Foo2))().toString;
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo3 = o.Foo, Foo, _m).bind(_o$Foo3))().toString();
|
||||||
|
((_o$Foo$self$getSelf = ((_o$Foo4 = o.Foo) === null || _o$Foo4 === void 0 ? void 0 : (_o$Foo4$self = _o$Foo4.self).getSelf.bind(_o$Foo4$self))()) === null || _o$Foo$self$getSelf === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo$self$getSelf, Foo, _m).bind(_o$Foo$self$getSelf))();
|
||||||
|
((_o$Foo$self$getSelf2 = ((_o$Foo$self = o.Foo.self) === null || _o$Foo$self === void 0 ? void 0 : _o$Foo$self.getSelf.bind(_o$Foo$self))()) === null || _o$Foo$self$getSelf2 === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo$self$getSelf2, Foo, _m).bind(_o$Foo$self$getSelf2))();
|
||||||
|
((_fn$Foo$self$getSelf = ((_fn = fn()) === null || _fn === void 0 ? void 0 : (_fn$Foo = _fn.Foo) === null || _fn$Foo === void 0 ? void 0 : (_fn$Foo$self = _fn$Foo.self).getSelf.bind(_fn$Foo$self))()) === null || _fn$Foo$self$getSelf === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_fn$Foo$self$getSelf, Foo, _m).bind(_fn$Foo$self$getSelf))();
|
||||||
|
((_fn$Foo$self$getSelf2 = (fn === null || fn === void 0 ? void 0 : (_fn$Foo$self3 = _fn$Foo$self2 = fn().Foo.self) === null || _fn$Foo$self3 === void 0 ? void 0 : _fn$Foo$self3.getSelf.bind(_fn$Foo$self2))()) === null || _fn$Foo$self$getSelf2 === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_fn$Foo$self$getSelf2, Foo, _m).bind(_fn$Foo$self$getSelf2))();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var _x = {
|
||||||
|
writable: true,
|
||||||
|
value: 1
|
||||||
|
};
|
||||||
|
babelHelpers.defineProperty(Foo, "self", Foo);
|
||||||
|
var _m = {
|
||||||
|
writable: true,
|
||||||
|
value: function () {
|
||||||
|
return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new Foo().test();
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
class Foo {
|
||||||
|
static #x = 1;
|
||||||
|
|
||||||
|
static self = Foo;
|
||||||
|
static #m = function() { return this.#x; };
|
||||||
|
static getSelf() { return Foo }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect((Foo?.#m)()).toEqual(1);
|
||||||
|
expect((Foo?.#m)().toString).toEqual(1..toString);
|
||||||
|
expect((Foo?.#m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((o?.Foo.#m)()).toEqual(1);
|
||||||
|
expect((o?.Foo.#m)().toString).toEqual(1..toString);
|
||||||
|
expect((o?.Foo.#m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((((o.Foo?.self.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
expect((((o.Foo.self?.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
|
||||||
|
expect((((fn()?.Foo?.self.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
expect((((fn?.().Foo.self?.getSelf)())?.#m)()).toEqual(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
testNull() {
|
||||||
|
const o = null;
|
||||||
|
const fn = function () {
|
||||||
|
return { o };
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(() => { (o?.Foo.#m)() }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.#m)().toString }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.#m)().toString() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => { (((o.Foo?.self.getSelf)())?.#m)() }).toThrow();
|
||||||
|
expect(() => { (((o.Foo.self?.getSelf)())?.#m)() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => (((fn()?.Foo?.self.getSelf)())?.#m)()).toThrow();
|
||||||
|
expect(() => (((fn?.().Foo.self?.getSelf)())?.#m)()).toThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
|
(new Foo).testNull();
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
class Foo {
|
||||||
|
static #x = 1;
|
||||||
|
|
||||||
|
static self = Foo;
|
||||||
|
static #m = function() { return this.#x; };
|
||||||
|
static getSelf() { return Foo }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo?.#m)();
|
||||||
|
(Foo?.#m)().toString;
|
||||||
|
(Foo?.#m)().toString();
|
||||||
|
|
||||||
|
(o?.Foo.#m)();
|
||||||
|
(o?.Foo.#m)().toString;
|
||||||
|
(o?.Foo.#m)().toString();
|
||||||
|
|
||||||
|
(((o.Foo?.self.getSelf)())?.#m)();
|
||||||
|
(((o.Foo.self?.getSelf)())?.#m)();
|
||||||
|
|
||||||
|
(((fn()?.Foo?.self.getSelf)())?.#m)();
|
||||||
|
(((fn?.().Foo.self?.getSelf)())?.#m)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["external-helpers", { "helperVersion": "7.100.0" }],
|
||||||
|
"proposal-class-properties"
|
||||||
|
],
|
||||||
|
"minNodeVersion": "14.0.0"
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
class Foo {
|
||||||
|
static getSelf() {
|
||||||
|
return Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
var _o$Foo, _o$Foo2, _o$Foo3, _o$Foo$self$getSelf, _o$Foo$self$getSelf2, _fn$Foo$self$getSelf, _fn$Foo$self$getSelf2;
|
||||||
|
|
||||||
|
const o = {
|
||||||
|
Foo: Foo
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _m).bind(Foo))();
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _m).bind(Foo))().toString;
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _m).bind(Foo))().toString();
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo = o.Foo, Foo, _m).bind(_o$Foo))();
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo2 = o.Foo, Foo, _m).bind(_o$Foo2))().toString;
|
||||||
|
(o === null || o === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo3 = o.Foo, Foo, _m).bind(_o$Foo3))().toString();
|
||||||
|
((_o$Foo$self$getSelf = (o.Foo?.self.getSelf)()) === null || _o$Foo$self$getSelf === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo$self$getSelf, Foo, _m).bind(_o$Foo$self$getSelf))();
|
||||||
|
((_o$Foo$self$getSelf2 = (o.Foo.self?.getSelf)()) === null || _o$Foo$self$getSelf2 === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_o$Foo$self$getSelf2, Foo, _m).bind(_o$Foo$self$getSelf2))();
|
||||||
|
((_fn$Foo$self$getSelf = (fn()?.Foo?.self.getSelf)()) === null || _fn$Foo$self$getSelf === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_fn$Foo$self$getSelf, Foo, _m).bind(_fn$Foo$self$getSelf))();
|
||||||
|
((_fn$Foo$self$getSelf2 = (fn?.().Foo.self?.getSelf)()) === null || _fn$Foo$self$getSelf2 === void 0 ? void 0 : babelHelpers.classStaticPrivateFieldSpecGet(_fn$Foo$self$getSelf2, Foo, _m).bind(_fn$Foo$self$getSelf2))();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var _x = {
|
||||||
|
writable: true,
|
||||||
|
value: 1
|
||||||
|
};
|
||||||
|
babelHelpers.defineProperty(Foo, "self", Foo);
|
||||||
|
var _m = {
|
||||||
|
writable: true,
|
||||||
|
value: function () {
|
||||||
|
return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new Foo().test();
|
||||||
@ -23,14 +23,17 @@ export default declare((api, options) => {
|
|||||||
|
|
||||||
visitor: {
|
visitor: {
|
||||||
"OptionalCallExpression|OptionalMemberExpression"(path) {
|
"OptionalCallExpression|OptionalMemberExpression"(path) {
|
||||||
const { parentPath, scope } = path;
|
const { scope } = path;
|
||||||
|
const parentPath = path.findParent(p => !p.isParenthesizedExpression());
|
||||||
let isDeleteOperation = false;
|
let isDeleteOperation = false;
|
||||||
const optionals = [];
|
const optionals = [];
|
||||||
|
|
||||||
let optionalPath = path;
|
let optionalPath = path;
|
||||||
while (
|
while (
|
||||||
optionalPath.isOptionalMemberExpression() ||
|
optionalPath.isOptionalMemberExpression() ||
|
||||||
optionalPath.isOptionalCallExpression()
|
optionalPath.isOptionalCallExpression() ||
|
||||||
|
optionalPath.isParenthesizedExpression() ||
|
||||||
|
optionalPath.isTSNonNullExpression()
|
||||||
) {
|
) {
|
||||||
const { node } = optionalPath;
|
const { node } = optionalPath;
|
||||||
if (node.optional) {
|
if (node.optional) {
|
||||||
@ -43,10 +46,8 @@ export default declare((api, options) => {
|
|||||||
} else if (optionalPath.isOptionalCallExpression()) {
|
} else if (optionalPath.isOptionalCallExpression()) {
|
||||||
optionalPath.node.type = "CallExpression";
|
optionalPath.node.type = "CallExpression";
|
||||||
optionalPath = optionalPath.get("callee");
|
optionalPath = optionalPath.get("callee");
|
||||||
}
|
} else {
|
||||||
|
// unwrap TSNonNullExpression/ParenthesizedExpression if needed
|
||||||
// unwrap a TSNonNullExpression if need
|
|
||||||
if (optionalPath.isTSNonNullExpression()) {
|
|
||||||
optionalPath = optionalPath.get("expression");
|
optionalPath = optionalPath.get("expression");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +114,36 @@ export default declare((api, options) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let replacement = replacementPath.node;
|
||||||
|
// Ensure (a?.b)() has proper `this`
|
||||||
|
if (
|
||||||
|
t.isMemberExpression(replacement) &&
|
||||||
|
(replacement.extra?.parenthesized ||
|
||||||
|
// if replacementPath.parentPath does not equal parentPath,
|
||||||
|
// it must be unwrapped from parenthesized expression.
|
||||||
|
replacementPath.parentPath !== parentPath) &&
|
||||||
|
parentPath.isCallExpression()
|
||||||
|
) {
|
||||||
|
// `(a?.b)()` to `(a == null ? undefined : a.b.bind(a))()`
|
||||||
|
const { object } = replacement;
|
||||||
|
let baseRef;
|
||||||
|
if (!loose || !isSimpleMemberExpression(object)) {
|
||||||
|
// memoize the context object in non-loose mode
|
||||||
|
// `(a?.b.c)()` to `(a == null ? undefined : (_a$b = a.b).c.bind(_a$b))()`
|
||||||
|
baseRef = scope.maybeGenerateMemoised(object);
|
||||||
|
if (baseRef) {
|
||||||
|
replacement.object = t.assignmentExpression(
|
||||||
|
"=",
|
||||||
|
baseRef,
|
||||||
|
object,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
replacement = t.callExpression(
|
||||||
|
t.memberExpression(replacement, t.identifier("bind")),
|
||||||
|
[t.cloneNode(baseRef ?? object)],
|
||||||
|
);
|
||||||
|
}
|
||||||
replacementPath.replaceWith(
|
replacementPath.replaceWith(
|
||||||
t.conditionalExpression(
|
t.conditionalExpression(
|
||||||
loose
|
loose
|
||||||
@ -134,7 +164,7 @@ export default declare((api, options) => {
|
|||||||
isDeleteOperation
|
isDeleteOperation
|
||||||
? t.booleanLiteral(true)
|
? t.booleanLiteral(true)
|
||||||
: scope.buildUndefinedNode(),
|
: scope.buildUndefinedNode(),
|
||||||
replacementPath.node,
|
replacement,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,51 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.x = 1;
|
||||||
|
this.self = this;
|
||||||
|
}
|
||||||
|
m() { return this.x; };
|
||||||
|
getSelf() { return this }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const Foo = this;
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect((Foo?.["m"])()).toEqual(1);
|
||||||
|
expect((Foo?.["m"])().toString).toEqual(1..toString);
|
||||||
|
expect((Foo?.["m"])().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect(((Foo?.["m"]))()).toEqual(1);
|
||||||
|
expect(((Foo?.["m"]))().toString).toEqual(1..toString);
|
||||||
|
expect(((Foo?.["m"]))().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((o?.Foo.m)()).toEqual(1);
|
||||||
|
expect((o?.Foo.m)().toString).toEqual(1..toString);
|
||||||
|
expect((o?.Foo.m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((((o.Foo?.self.getSelf)())?.m)()).toEqual(1);
|
||||||
|
expect((((o.Foo.self?.getSelf)())?.m)()).toEqual(1);
|
||||||
|
|
||||||
|
expect((((fn()?.Foo?.self.getSelf)())?.m)()).toEqual(1);
|
||||||
|
expect((((fn?.().Foo.self?.getSelf)())?.m)()).toEqual(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
testNull() {
|
||||||
|
const o = null;
|
||||||
|
|
||||||
|
expect(() => { (o?.Foo.m)() }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.m)().toString }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.m)().toString() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => { (((o.Foo?.self.getSelf)())?.m)() }).toThrow();
|
||||||
|
expect(() => { (((o.Foo.self?.getSelf)())?.m)() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => (((fn()?.Foo?.self.getSelf)())?.m)()).toThrow();
|
||||||
|
expect(() => (((fn?.().Foo.self?.getSelf)())?.m)()).toThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
|
(new Foo).testNull();
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"plugins": [["proposal-optional-chaining", { "loose": true }]],
|
||||||
|
"parserOpts": {
|
||||||
|
"createParenthesizedExpressions": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.x = 1;
|
||||||
|
this.self = this;
|
||||||
|
}
|
||||||
|
m() { return this.x; };
|
||||||
|
getSelf() { return this }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const Foo = this;
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect((Foo?.["m"])()).toEqual(1);
|
||||||
|
expect((Foo?.["m"])().toString).toEqual(1..toString);
|
||||||
|
expect((Foo?.["m"])().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect(((Foo?.["m"]))()).toEqual(1);
|
||||||
|
expect(((Foo?.["m"]))().toString).toEqual(1..toString);
|
||||||
|
expect(((Foo?.["m"]))().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((o?.Foo.m)()).toEqual(1);
|
||||||
|
expect((o?.Foo.m)().toString).toEqual(1..toString);
|
||||||
|
expect((o?.Foo.m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((((o.Foo?.self.getSelf)())?.m)()).toEqual(1);
|
||||||
|
expect((((o.Foo.self?.getSelf)())?.m)()).toEqual(1);
|
||||||
|
|
||||||
|
expect((((fn()?.Foo?.self.getSelf)())?.m)()).toEqual(1);
|
||||||
|
expect((((fn?.().Foo.self?.getSelf)())?.m)()).toEqual(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
testNull() {
|
||||||
|
const o = null;
|
||||||
|
|
||||||
|
expect(() => { (o?.Foo.m)() }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.m)().toString }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.m)().toString() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => { (((o.Foo?.self.getSelf)())?.m)() }).toThrow();
|
||||||
|
expect(() => { (((o.Foo.self?.getSelf)())?.m)() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => (((fn()?.Foo?.self.getSelf)())?.m)()).toThrow();
|
||||||
|
expect(() => (((fn?.().Foo.self?.getSelf)())?.m)()).toThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
|
(new Foo).testNull();
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["proposal-optional-chaining"],
|
||||||
|
"parserOpts": {
|
||||||
|
"createParenthesizedExpressions": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.x = 1;
|
||||||
|
this.self = this;
|
||||||
|
}
|
||||||
|
m() { return this.x; };
|
||||||
|
getSelf() { return this }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const Foo = this;
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect((Foo?.["m"])()).toEqual(1);
|
||||||
|
expect((Foo?.["m"])().toString).toEqual(1..toString);
|
||||||
|
expect((Foo?.["m"])().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((o?.Foo.m)()).toEqual(1);
|
||||||
|
expect((o?.Foo.m)().toString).toEqual(1..toString);
|
||||||
|
expect((o?.Foo.m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((((o.Foo?.self.getSelf)())?.m)()).toEqual(1);
|
||||||
|
expect((((o.Foo.self?.getSelf)())?.m)()).toEqual(1);
|
||||||
|
|
||||||
|
expect((((fn()?.Foo?.self.getSelf)())?.m)()).toEqual(1);
|
||||||
|
expect((((fn?.().Foo.self?.getSelf)())?.m)()).toEqual(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
testNull() {
|
||||||
|
const o = null;
|
||||||
|
|
||||||
|
expect(() => { (o?.Foo.m)() }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.m)().toString }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.m)().toString() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => { (((o.Foo?.self.getSelf)())?.m)() }).toThrow();
|
||||||
|
expect(() => { (((o.Foo.self?.getSelf)())?.m)() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => (((fn()?.Foo?.self.getSelf)())?.m)()).toThrow();
|
||||||
|
expect(() => (((fn?.().Foo.self?.getSelf)())?.m)()).toThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
|
(new Foo).testNull();
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.x = 1;
|
||||||
|
this.self = this;
|
||||||
|
}
|
||||||
|
m() { return this.x; };
|
||||||
|
getSelf() { return this }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const Foo = this;
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo?.["m"])();
|
||||||
|
(Foo?.["m"])().toString;
|
||||||
|
(Foo?.["m"])().toString();
|
||||||
|
|
||||||
|
(o?.Foo.m)();
|
||||||
|
(o?.Foo.m)().toString;
|
||||||
|
(o?.Foo.m)().toString();
|
||||||
|
|
||||||
|
(((o.Foo?.self.getSelf)())?.m)();
|
||||||
|
(((o.Foo.self?.getSelf)())?.m)();
|
||||||
|
|
||||||
|
(((fn()?.Foo?.self.getSelf)())?.m)();
|
||||||
|
(((fn?.().Foo.self?.getSelf)())?.m)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": [["proposal-optional-chaining", { "loose": true }]]
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.x = 1;
|
||||||
|
this.self = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
m() {
|
||||||
|
return this.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelf() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
var _o$Foo$self$getSelf, _o$Foo, _o$Foo$self$getSelf2, _o$Foo$self, _fn$Foo$self$getSelf, _fn, _fn$Foo, _fn$Foo$self$getSelf2, _fn$Foo$self, _fn$Foo$self2;
|
||||||
|
|
||||||
|
const Foo = this;
|
||||||
|
const o = {
|
||||||
|
Foo: Foo
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo == null ? void 0 : Foo["m"].bind(Foo))();
|
||||||
|
(Foo == null ? void 0 : Foo["m"].bind(Foo))().toString;
|
||||||
|
(Foo == null ? void 0 : Foo["m"].bind(Foo))().toString();
|
||||||
|
(o == null ? void 0 : o.Foo.m.bind(o.Foo))();
|
||||||
|
(o == null ? void 0 : o.Foo.m.bind(o.Foo))().toString;
|
||||||
|
(o == null ? void 0 : o.Foo.m.bind(o.Foo))().toString();
|
||||||
|
((_o$Foo$self$getSelf = ((_o$Foo = o.Foo) == null ? void 0 : _o$Foo.self.getSelf.bind(_o$Foo.self))()) == null ? void 0 : _o$Foo$self$getSelf.m.bind(_o$Foo$self$getSelf))();
|
||||||
|
((_o$Foo$self$getSelf2 = ((_o$Foo$self = o.Foo.self) == null ? void 0 : _o$Foo$self.getSelf.bind(_o$Foo$self))()) == null ? void 0 : _o$Foo$self$getSelf2.m.bind(_o$Foo$self$getSelf2))();
|
||||||
|
((_fn$Foo$self$getSelf = ((_fn = fn()) == null ? void 0 : (_fn$Foo = _fn.Foo) == null ? void 0 : _fn$Foo.self.getSelf.bind(_fn.Foo.self))()) == null ? void 0 : _fn$Foo$self$getSelf.m.bind(_fn$Foo$self$getSelf))();
|
||||||
|
((_fn$Foo$self$getSelf2 = (fn == null ? void 0 : (_fn$Foo$self2 = _fn$Foo$self = fn().Foo.self) == null ? void 0 : _fn$Foo$self2.getSelf.bind(_fn$Foo$self))()) == null ? void 0 : _fn$Foo$self$getSelf2.m.bind(_fn$Foo$self$getSelf2))();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
new Foo().test();
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.x = 1;
|
||||||
|
this.self = this;
|
||||||
|
}
|
||||||
|
m() { return this.x; };
|
||||||
|
getSelf() { return this }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const Foo = this;
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect((Foo?.["m"])()).toEqual(1);
|
||||||
|
expect((Foo?.["m"])().toString).toEqual(1..toString);
|
||||||
|
expect((Foo?.["m"])().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((o?.Foo.m)()).toEqual(1);
|
||||||
|
expect((o?.Foo.m)().toString).toEqual(1..toString);
|
||||||
|
expect((o?.Foo.m)().toString()).toEqual('1');
|
||||||
|
|
||||||
|
expect((((o.Foo?.self.getSelf)())?.m)()).toEqual(1);
|
||||||
|
expect((((o.Foo.self?.getSelf)())?.m)()).toEqual(1);
|
||||||
|
|
||||||
|
expect((((fn()?.Foo?.self.getSelf)())?.m)()).toEqual(1);
|
||||||
|
expect((((fn?.().Foo.self?.getSelf)())?.m)()).toEqual(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
testNull() {
|
||||||
|
const o = null;
|
||||||
|
|
||||||
|
expect(() => { (o?.Foo.m)() }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.m)().toString }).toThrow();
|
||||||
|
expect(() => { (o?.Foo.m)().toString() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => { (((o.Foo?.self.getSelf)())?.m)() }).toThrow();
|
||||||
|
expect(() => { (((o.Foo.self?.getSelf)())?.m)() }).toThrow();
|
||||||
|
|
||||||
|
expect(() => (((fn()?.Foo?.self.getSelf)())?.m)()).toThrow();
|
||||||
|
expect(() => (((fn?.().Foo.self?.getSelf)())?.m)()).toThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
|
(new Foo).testNull();
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.x = 1;
|
||||||
|
this.self = this;
|
||||||
|
}
|
||||||
|
m() { return this.x; };
|
||||||
|
getSelf() { return this }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
const Foo = this;
|
||||||
|
const o = { Foo: Foo };
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo?.["m"])();
|
||||||
|
(Foo?.["m"])().toString;
|
||||||
|
(Foo?.["m"])().toString();
|
||||||
|
|
||||||
|
(o?.Foo.m)();
|
||||||
|
(o?.Foo.m)().toString;
|
||||||
|
(o?.Foo.m)().toString();
|
||||||
|
|
||||||
|
(((o.Foo?.self.getSelf)())?.m)();
|
||||||
|
(((o.Foo.self?.getSelf)())?.m)();
|
||||||
|
|
||||||
|
(((fn()?.Foo?.self.getSelf)())?.m)();
|
||||||
|
(((fn?.().Foo.self?.getSelf)())?.m)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(new Foo).test();
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.x = 1;
|
||||||
|
this.self = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
m() {
|
||||||
|
return this.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelf() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
var _o$Foo, _o$Foo2, _o$Foo3, _o$Foo$self$getSelf, _o$Foo4, _o$Foo4$self, _o$Foo$self$getSelf2, _o$Foo$self, _fn$Foo$self$getSelf, _fn, _fn$Foo$self, _fn$Foo, _fn$Foo$self$getSelf2, _fn$Foo$self2, _fn$Foo$self3;
|
||||||
|
|
||||||
|
const Foo = this;
|
||||||
|
const o = {
|
||||||
|
Foo: Foo
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn = function () {
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : Foo["m"].bind(Foo))();
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : Foo["m"].bind(Foo))().toString;
|
||||||
|
(Foo === null || Foo === void 0 ? void 0 : Foo["m"].bind(Foo))().toString();
|
||||||
|
(o === null || o === void 0 ? void 0 : (_o$Foo = o.Foo).m.bind(_o$Foo))();
|
||||||
|
(o === null || o === void 0 ? void 0 : (_o$Foo2 = o.Foo).m.bind(_o$Foo2))().toString;
|
||||||
|
(o === null || o === void 0 ? void 0 : (_o$Foo3 = o.Foo).m.bind(_o$Foo3))().toString();
|
||||||
|
((_o$Foo$self$getSelf = ((_o$Foo4 = o.Foo) === null || _o$Foo4 === void 0 ? void 0 : (_o$Foo4$self = _o$Foo4.self).getSelf.bind(_o$Foo4$self))()) === null || _o$Foo$self$getSelf === void 0 ? void 0 : _o$Foo$self$getSelf.m.bind(_o$Foo$self$getSelf))();
|
||||||
|
((_o$Foo$self$getSelf2 = ((_o$Foo$self = o.Foo.self) === null || _o$Foo$self === void 0 ? void 0 : _o$Foo$self.getSelf.bind(_o$Foo$self))()) === null || _o$Foo$self$getSelf2 === void 0 ? void 0 : _o$Foo$self$getSelf2.m.bind(_o$Foo$self$getSelf2))();
|
||||||
|
((_fn$Foo$self$getSelf = ((_fn = fn()) === null || _fn === void 0 ? void 0 : (_fn$Foo = _fn.Foo) === null || _fn$Foo === void 0 ? void 0 : (_fn$Foo$self = _fn$Foo.self).getSelf.bind(_fn$Foo$self))()) === null || _fn$Foo$self$getSelf === void 0 ? void 0 : _fn$Foo$self$getSelf.m.bind(_fn$Foo$self$getSelf))();
|
||||||
|
((_fn$Foo$self$getSelf2 = (fn === null || fn === void 0 ? void 0 : (_fn$Foo$self3 = _fn$Foo$self2 = fn().Foo.self) === null || _fn$Foo$self3 === void 0 ? void 0 : _fn$Foo$self3.getSelf.bind(_fn$Foo$self2))()) === null || _fn$Foo$self$getSelf2 === void 0 ? void 0 : _fn$Foo$self$getSelf2.m.bind(_fn$Foo$self$getSelf2))();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
new Foo().test();
|
||||||
Loading…
x
Reference in New Issue
Block a user