Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add delete obj?.#x.a support #11669

Merged
merged 1 commit into from Jun 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 24 additions & 4 deletions packages/babel-helper-member-expression-to-functions/src/index.js
Expand Up @@ -125,8 +125,19 @@ const handle = {
) {
throw member.buildCodeFrameError(`can't handle assignment`);
}
if (rootParentPath.isUnaryExpression({ operator: "delete" })) {
throw member.buildCodeFrameError(`can't handle delete`);
const isDeleteOperation = rootParentPath.isUnaryExpression({
operator: "delete",
});
if (
isDeleteOperation &&
endPath.isOptionalMemberExpression() &&
endPath.get("property").isPrivateName()
) {
// @babel/parser will throw error on `delete obj?.#x`.
// This error serves as fallback when `delete obj?.#x` is constructed from babel types
throw member.buildCodeFrameError(
`can't delete a private class element`,
);
}

// Now, we're looking for the start of this optional chain, which is
Expand Down Expand Up @@ -211,7 +222,13 @@ const handle = {
}
}

endPath.replaceWith(
let replacementPath = endPath;
if (isDeleteOperation) {
replacementPath = endParentPath;
regular = endParentPath.node;
}

replacementPath.replaceWith(
t.conditionalExpression(
t.logicalExpression(
"||",
Expand All @@ -228,11 +245,14 @@ const handle = {
scope.buildUndefinedNode(),
),
),
scope.buildUndefinedNode(),
isDeleteOperation
? t.booleanLiteral(true)
: scope.buildUndefinedNode(),
regular,
),
);

// context and isDeleteOperation can not be both truthy
if (context) {
const endParent = endParentPath.node;
endParentPath.replaceWith(
Expand Down
@@ -0,0 +1,102 @@
class Foo {
static #x = 1;
static #self = Foo;
static self = Foo;
static getSelf() { return this }

static test() {
const o = { Foo: Foo };
const deep = { very: { o } };
function fn() {
return o;
}
function fnDeep() {
return deep;
}
expect(() => delete Foo?.#self.unicorn).toThrow(TypeError);
expect(() => delete deep?.very.o?.Foo.#self.unicorn).toThrow(TypeError);

expect(() => delete o?.Foo.#self.unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self.self.unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self?.self.unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self.self?.self.unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self?.self?.self.unicorn).toThrow(TypeError);

expect(() => delete o?.Foo.#self.getSelf().unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self.getSelf?.().unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self?.getSelf().unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self?.getSelf?.().unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self.getSelf()?.self.unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self.getSelf?.()?.self.unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self?.getSelf()?.self.unicorn).toThrow(TypeError);
expect(() => delete o?.Foo.#self?.getSelf?.()?.self.unicorn).toThrow(TypeError);

expect(() => delete fn?.().Foo.#self.unicorn).toThrow(TypeError);
expect(() => delete fnDeep?.().very.o?.Foo.#self.unicorn).toThrow(TypeError);

expect(() => delete fn?.().Foo.#self.unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self.self.unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self?.self.unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self.self?.self.unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self?.self?.self.unicorn).toThrow(TypeError);

expect(() => delete fn?.().Foo.#self.getSelf().unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self.getSelf?.().unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self?.getSelf().unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self?.getSelf?.().unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self.getSelf()?.self.unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self.getSelf?.()?.self.unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self?.getSelf()?.self.unicorn).toThrow(TypeError);
expect(() => delete fn?.().Foo.#self?.getSelf?.()?.self.unicorn).toThrow(TypeError);


}

static testNull() {
const o = null;
const deep = { very: { o } };
const fn = null;
function fnDeep() {
return deep;
}

expect(delete deep?.very.o?.Foo.#self.unicorn).toBe(true);

expect(delete o?.Foo.#self.unicorn).toBe(true);
expect(delete o?.Foo.#self.self.unicorn).toBe(true);
expect(delete o?.Foo.#self?.self.unicorn).toBe(true);
expect(delete o?.Foo.#self.self?.self.unicorn).toBe(true);
expect(delete o?.Foo.#self?.self?.self.unicorn).toBe(true);

expect(delete o?.Foo.#self.getSelf().unicorn).toBe(true);
expect(delete o?.Foo.#self.getSelf?.().unicorn).toBe(true);
expect(delete o?.Foo.#self?.getSelf().unicorn).toBe(true);
expect(delete o?.Foo.#self?.getSelf?.().unicorn).toBe(true);
expect(delete o?.Foo.#self.getSelf()?.self.unicorn).toBe(true);
expect(delete o?.Foo.#self.getSelf?.()?.self.unicorn).toBe(true);
expect(delete o?.Foo.#self?.getSelf()?.self.unicorn).toBe(true);
expect(delete o?.Foo.#self?.getSelf?.()?.self.unicorn).toBe(true);

expect(delete fn?.().Foo.#self.unicorn).toBe(true);
expect(delete fnDeep?.().very.o?.Foo.#self.unicorn).toBe(true);

expect(delete fn?.().Foo.#self.unicorn).toBe(true);
expect(delete fn?.().Foo.#self.self.unicorn).toBe(true);
expect(delete fn?.().Foo.#self?.self.unicorn).toBe(true);
expect(delete fn?.().Foo.#self.self?.self.unicorn).toBe(true);
expect(delete fn?.().Foo.#self?.self?.self.unicorn).toBe(true);

expect(delete fn?.().Foo.#self.getSelf().unicorn).toBe(true);
expect(delete fn?.().Foo.#self.getSelf?.().unicorn).toBe(true);
expect(delete fn?.().Foo.#self?.getSelf().unicorn).toBe(true);
expect(delete fn?.().Foo.#self?.getSelf?.().unicorn).toBe(true);
expect(delete fn?.().Foo.#self.getSelf()?.self.unicorn).toBe(true);
expect(delete fn?.().Foo.#self.getSelf?.()?.self.unicorn).toBe(true);
expect(delete fn?.().Foo.#self?.getSelf()?.self.unicorn).toBe(true);
expect(delete fn?.().Foo.#self?.getSelf?.()?.self.unicorn).toBe(true);
}
}

Object.defineProperty(Foo, "unicorn", { configurable: false });
Foo.test();
Foo.testNull();
@@ -0,0 +1,56 @@
class Foo {
static #x = 1;
static #self = Foo;
static self = Foo;
static getSelf() { return this }

static test() {
const o = { Foo: Foo };
const deep = { very: { o } };
function fn() {
return o;
}
function fnDeep() {
return deep;
}

delete Foo?.#self.unicorn;
delete deep?.very.o?.Foo.#self.unicorn;

delete o?.Foo.#self.unicorn;
delete o?.Foo.#self.self.unicorn;
delete o?.Foo.#self?.self.unicorn;
delete o?.Foo.#self.self?.self.unicorn;
delete o?.Foo.#self?.self?.self.unicorn;

delete o?.Foo.#self.getSelf().unicorn;
delete o?.Foo.#self.getSelf?.().unicorn;
delete o?.Foo.#self?.getSelf().unicorn;
delete o?.Foo.#self?.getSelf?.().unicorn;
delete o?.Foo.#self.getSelf()?.self.unicorn;
delete o?.Foo.#self.getSelf?.()?.self.unicorn;
delete o?.Foo.#self?.getSelf()?.self.unicorn;
delete o?.Foo.#self?.getSelf?.()?.self.unicorn;

delete fn?.().Foo.#self.unicorn;
delete fnDeep?.().very.o?.Foo.#self.unicorn;

delete fn?.().Foo.#self.unicorn;
delete fn?.().Foo.#self.self.unicorn;
delete fn?.().Foo.#self?.self.unicorn;
delete fn?.().Foo.#self.self?.self.unicorn;
delete fn?.().Foo.#self?.self?.self.unicorn;

delete fn?.().Foo.#self.getSelf().unicorn;
delete fn?.().Foo.#self.getSelf?.().unicorn;
delete fn?.().Foo.#self?.getSelf().unicorn;
delete fn?.().Foo.#self?.getSelf?.().unicorn;
delete fn?.().Foo.#self.getSelf()?.self.unicorn;
delete fn?.().Foo.#self.getSelf?.()?.self.unicorn;
delete fn?.().Foo.#self?.getSelf()?.self.unicorn;
delete fn?.().Foo.#self?.getSelf?.()?.self.unicorn;

}
}

Foo.test();
@@ -0,0 +1,6 @@
{
"plugins": [
["proposal-optional-chaining", { "loose": true }],
["proposal-class-properties", { "loose": true }]
]
}
@@ -0,0 +1,79 @@
function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }

var id = 0;

function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }

var _x = _classPrivateFieldLooseKey("x");

var _self = _classPrivateFieldLooseKey("self");

class Foo {
static getSelf() {
return this;
}

static test() {
var _deep$very$o, _classPrivateFieldLoo, _classPrivateFieldLoo2, _fnDeep$very$o, _classPrivateFieldLoo3, _classPrivateFieldLoo4, _ref, _ref2, _ref3, _ref3$self, _ref4, _ref5, _ref6, _ref7, _ref8, _ref8$call, _ref9, _ref9$getSelf, _ref10, _ref10$getSelf, _ref11, _ref12, _ref13, _ref13$self, _ref14, _ref15, _ref16, _ref17, _ref18, _ref18$call, _ref19, _ref19$getSelf, _ref20, _ref20$getSelf;

const o = {
Foo: Foo
};
const deep = {
very: {
o
}
};

function fn() {
return o;
}

function fnDeep() {
return deep;
}

Foo === null || Foo === void 0 ? true : delete _classPrivateFieldLooseBase(Foo, _self)[_self].unicorn;
(_deep$very$o = deep == null ? void 0 : deep.very.o) === null || _deep$very$o === void 0 ? true : delete _classPrivateFieldLooseBase(_deep$very$o.Foo, _self)[_self].unicorn;
o === null || o === void 0 ? true : delete _classPrivateFieldLooseBase(o.Foo, _self)[_self].unicorn;
o === null || o === void 0 ? true : delete _classPrivateFieldLooseBase(o.Foo, _self)[_self].self.unicorn;
(_ref = o === null || o === void 0 ? void 0 : _classPrivateFieldLooseBase(o.Foo, _self)[_self]) == null ? true : delete _ref.self.unicorn;
(_ref2 = o === null || o === void 0 ? void 0 : _classPrivateFieldLooseBase(o.Foo, _self)[_self].self) == null ? true : delete _ref2.self.unicorn;
(_ref3 = o === null || o === void 0 ? void 0 : _classPrivateFieldLooseBase(o.Foo, _self)[_self]) == null ? true : (_ref3$self = _ref3.self) == null ? true : delete _ref3$self.self.unicorn;
o === null || o === void 0 ? true : delete _classPrivateFieldLooseBase(o.Foo, _self)[_self].getSelf().unicorn;
(_ref4 = o === null || o === void 0 ? void 0 : (_classPrivateFieldLoo = _classPrivateFieldLooseBase(o.Foo, _self)[_self]).getSelf) == null ? true : delete _ref4.call(_classPrivateFieldLoo).unicorn;
(_ref5 = o === null || o === void 0 ? void 0 : _classPrivateFieldLooseBase(o.Foo, _self)[_self]) == null ? true : delete _ref5.getSelf().unicorn;
(_ref6 = o === null || o === void 0 ? void 0 : _classPrivateFieldLooseBase(o.Foo, _self)[_self]) == null ? true : _ref6.getSelf == null ? true : delete _ref6.getSelf().unicorn;
(_ref7 = o === null || o === void 0 ? void 0 : _classPrivateFieldLooseBase(o.Foo, _self)[_self].getSelf()) == null ? true : delete _ref7.self.unicorn;
(_ref8 = o === null || o === void 0 ? void 0 : (_classPrivateFieldLoo2 = _classPrivateFieldLooseBase(o.Foo, _self)[_self]).getSelf) == null ? true : (_ref8$call = _ref8.call(_classPrivateFieldLoo2)) == null ? true : delete _ref8$call.self.unicorn;
(_ref9 = o === null || o === void 0 ? void 0 : _classPrivateFieldLooseBase(o.Foo, _self)[_self]) == null ? true : (_ref9$getSelf = _ref9.getSelf()) == null ? true : delete _ref9$getSelf.self.unicorn;
(_ref10 = o === null || o === void 0 ? void 0 : _classPrivateFieldLooseBase(o.Foo, _self)[_self]) == null ? true : _ref10.getSelf == null ? true : (_ref10$getSelf = _ref10.getSelf()) == null ? true : delete _ref10$getSelf.self.unicorn;
fn === null || fn === void 0 ? true : delete _classPrivateFieldLooseBase(fn().Foo, _self)[_self].unicorn;
(_fnDeep$very$o = fnDeep == null ? void 0 : fnDeep().very.o) === null || _fnDeep$very$o === void 0 ? true : delete _classPrivateFieldLooseBase(_fnDeep$very$o.Foo, _self)[_self].unicorn;
fn === null || fn === void 0 ? true : delete _classPrivateFieldLooseBase(fn().Foo, _self)[_self].unicorn;
fn === null || fn === void 0 ? true : delete _classPrivateFieldLooseBase(fn().Foo, _self)[_self].self.unicorn;
(_ref11 = fn === null || fn === void 0 ? void 0 : _classPrivateFieldLooseBase(fn().Foo, _self)[_self]) == null ? true : delete _ref11.self.unicorn;
(_ref12 = fn === null || fn === void 0 ? void 0 : _classPrivateFieldLooseBase(fn().Foo, _self)[_self].self) == null ? true : delete _ref12.self.unicorn;
(_ref13 = fn === null || fn === void 0 ? void 0 : _classPrivateFieldLooseBase(fn().Foo, _self)[_self]) == null ? true : (_ref13$self = _ref13.self) == null ? true : delete _ref13$self.self.unicorn;
fn === null || fn === void 0 ? true : delete _classPrivateFieldLooseBase(fn().Foo, _self)[_self].getSelf().unicorn;
(_ref14 = fn === null || fn === void 0 ? void 0 : (_classPrivateFieldLoo3 = _classPrivateFieldLooseBase(fn().Foo, _self)[_self]).getSelf) == null ? true : delete _ref14.call(_classPrivateFieldLoo3).unicorn;
(_ref15 = fn === null || fn === void 0 ? void 0 : _classPrivateFieldLooseBase(fn().Foo, _self)[_self]) == null ? true : delete _ref15.getSelf().unicorn;
(_ref16 = fn === null || fn === void 0 ? void 0 : _classPrivateFieldLooseBase(fn().Foo, _self)[_self]) == null ? true : _ref16.getSelf == null ? true : delete _ref16.getSelf().unicorn;
(_ref17 = fn === null || fn === void 0 ? void 0 : _classPrivateFieldLooseBase(fn().Foo, _self)[_self].getSelf()) == null ? true : delete _ref17.self.unicorn;
(_ref18 = fn === null || fn === void 0 ? void 0 : (_classPrivateFieldLoo4 = _classPrivateFieldLooseBase(fn().Foo, _self)[_self]).getSelf) == null ? true : (_ref18$call = _ref18.call(_classPrivateFieldLoo4)) == null ? true : delete _ref18$call.self.unicorn;
(_ref19 = fn === null || fn === void 0 ? void 0 : _classPrivateFieldLooseBase(fn().Foo, _self)[_self]) == null ? true : (_ref19$getSelf = _ref19.getSelf()) == null ? true : delete _ref19$getSelf.self.unicorn;
(_ref20 = fn === null || fn === void 0 ? void 0 : _classPrivateFieldLooseBase(fn().Foo, _self)[_self]) == null ? true : _ref20.getSelf == null ? true : (_ref20$getSelf = _ref20.getSelf()) == null ? true : delete _ref20$getSelf.self.unicorn;
}

}

Object.defineProperty(Foo, _x, {
writable: true,
value: 1
});
Object.defineProperty(Foo, _self, {
writable: true,
value: Foo
});
Foo.self = Foo;
Foo.test();