destructuring private fields with array pattern / object patte… (#10017)

* destructuring private fields with array pattern / object pattern

* wip: new test cases

* destrucuring and rest for private properties

* test case for loose private-loose

* add transform-desturcturing for exec

* update test case

* remove getPrototypeOf imports from get and set

* wip: destructure super assignment

* throw "Destructuring to a super field is not supported yet."

* fix tests and fix assignment pattern

* remove CallExpression from AssignmentPattern
This commit is contained in:
Tan Li Hau 2019-07-15 07:00:20 +08:00 committed by Nicolò Ribaudo
parent 7f47cb65d0
commit d3fe22f0e1
88 changed files with 970 additions and 4 deletions

View File

@ -211,6 +211,19 @@ const privateNameHandlerSpec = {
]);
},
destructureSet(member) {
const { privateNamesMap, file } = this;
const { name } = member.node.property.id;
const { id } = privateNamesMap.get(name);
return t.memberExpression(
t.callExpression(file.addHelper("classPrivateFieldDestructureSet"), [
this.receiver(member),
t.cloneNode(id),
]),
t.identifier("value"),
);
},
call(member, args) {
// The first access (the get) should do the memo assignment.
this.memoise(member, 1);

View File

@ -100,6 +100,34 @@ const handle = {
return;
}
// { KEY: MEMBER } = OBJ -> { KEY: _destructureSet(MEMBER) } = OBJ
// { KEY: MEMBER = _VALUE } = OBJ -> { KEY: _destructureSet(MEMBER) = _VALUE } = OBJ
// {...MEMBER} -> {..._destructureSet(MEMBER)}
//
// [MEMBER] = ARR -> [_destructureSet(MEMBER)] = ARR
// [MEMBER = _VALUE] = ARR -> [_destructureSet(MEMBER) = _VALUE] = ARR
// [...MEMBER] -> [..._destructureSet(MEMBER)]
if (
// { KEY: MEMBER } = OBJ
(parentPath.isObjectProperty({ value: node }) &&
parentPath.parentPath.isObjectPattern()) ||
// { KEY: MEMBER = _VALUE } = OBJ
(parentPath.isAssignmentPattern({ left: node }) &&
parentPath.parentPath.isObjectProperty({ value: parent }) &&
parentPath.parentPath.parentPath.isObjectPattern()) ||
// [MEMBER] = ARR
parentPath.isArrayPattern() ||
// [MEMBER = _VALUE] = ARR
(parentPath.isAssignmentPattern({ left: node }) &&
parentPath.parentPath.isArrayPattern()) ||
// {...MEMBER}
// [...MEMBER]
parentPath.isRestElement()
) {
member.replaceWith(this.destructureSet(member));
return;
}
// MEMBER -> _get(MEMBER)
member.replaceWith(this.get(member));
},

View File

@ -125,6 +125,12 @@ const specHandlers = {
]);
},
destructureSet(superMember) {
throw superMember.buildCodeFrameError(
`Destructuring to a super field is not supported yet.`,
);
},
call(superMember, args) {
return optimiseCall(this.get(superMember), t.thisExpression(), args);
},
@ -174,6 +180,13 @@ const looseHandlers = {
value,
);
},
destructureSet(superMember) {
const { computed } = superMember.node;
const prop = this.prop(superMember);
return t.memberExpression(t.thisExpression(), prop, computed);
},
};
export default class ReplaceSupers {

View File

@ -720,7 +720,6 @@ helpers.superPropBase = helper("7.0.0-beta.0")`
`;
helpers.get = helper("7.0.0-beta.0")`
import getPrototypeOf from "getPrototypeOf";
import superPropBase from "superPropBase";
export default function _get(target, property, receiver) {
@ -745,7 +744,6 @@ helpers.get = helper("7.0.0-beta.0")`
`;
helpers.set = helper("7.0.0-beta.0")`
import getPrototypeOf from "getPrototypeOf";
import superPropBase from "superPropBase";
import defineProperty from "defineProperty";
@ -1123,6 +1121,34 @@ helpers.classPrivateFieldSet = helper("7.0.0-beta.0")`
}
`;
helpers.classPrivateFieldDestructureSet = helper("7.4.4")`
export default function _classPrivateFieldDestructureSet(receiver, privateMap) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance");
}
var descriptor = privateMap.get(receiver);
if (descriptor.set) {
if (!("__destrObj" in descriptor)) {
descriptor.__destrObj = {
set value(v) {
descriptor.set.call(receiver, v)
},
};
}
return descriptor.__destrObj;
} else {
if (!descriptor.writable) {
// This should only throw in strict mode, but class bodies are
// always strict and private fields can only be used inside
// class bodies.
throw new TypeError("attempted to set read only private field");
}
return descriptor;
}
}
`;
helpers.classStaticPrivateFieldSpecGet = helper("7.0.2")`
export default function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) {
if (receiver !== classConstructor) {

View File

@ -0,0 +1,17 @@
class Foo {
#client
constructor(props) {
this.#client = 1;
;([this.x = this.#client, this.#client, this.y = this.#client] = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo([undefined, 'bar']);
expect(foo.getClient()).toBe('bar');
expect(foo.x).toBe(1);
expect(foo.y).toBe('bar');

View File

@ -0,0 +1,8 @@
class Foo {
#client
constructor(props) {
this.#client = 1;
([this.x = this.#client, this.#client, this.y = this.#client] = props);
}
}

View File

@ -0,0 +1,13 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _client, {
writable: true,
value: void 0
});
babelHelpers.classPrivateFieldLooseBase(this, _client)[_client] = 1;
[this.x = babelHelpers.classPrivateFieldLooseBase(this, _client)[_client], babelHelpers.classPrivateFieldLooseBase(this, _client)[_client], this.y = babelHelpers.classPrivateFieldLooseBase(this, _client)[_client]] = props;
};
var _client = babelHelpers.classPrivateFieldLooseKey("client");

View File

@ -0,0 +1,15 @@
class Foo {
#client
constructor(props) {
let x;
;([x, ...this.#client] = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo(['foo', 'bar', 'baz', 'quu']);
expect(foo.getClient()).toEqual(['bar', 'baz', 'quu']);

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
([x, ...this.#client] = props);
}
}

View File

@ -0,0 +1,12 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _client, {
writable: true,
value: void 0
});
[x, ...babelHelpers.classPrivateFieldLooseBase(this, _client)[_client]] = props;
};
var _client = babelHelpers.classPrivateFieldLooseKey("client");

View File

@ -0,0 +1,14 @@
class Foo {
#client
constructor(props) {
([this.#client = 5] = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo([]);
expect(foo.getClient()).toEqual(5);

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
([this.#client = 5] = props);
}
}

View File

@ -0,0 +1,12 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _client, {
writable: true,
value: void 0
});
[babelHelpers.classPrivateFieldLooseBase(this, _client)[_client] = 5] = props;
};
var _client = babelHelpers.classPrivateFieldLooseKey("client");

View File

@ -0,0 +1,14 @@
class Foo {
#client
constructor(props) {
;([this.#client] = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo(['bar']);
expect(foo.getClient()).toBe('bar');

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
([this.#client] = props);
}
}

View File

@ -0,0 +1,12 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _client, {
writable: true,
value: void 0
});
[babelHelpers.classPrivateFieldLooseBase(this, _client)[_client]] = props;
};
var _client = babelHelpers.classPrivateFieldLooseKey("client");

View File

@ -0,0 +1,17 @@
class Foo {
#client
constructor(props) {
this.#client = 'foo';
;({ x: this.x = this.#client, y: this.#client, z: this.z = this.#client } = props)
}
getClient() {
return this.#client;
}
}
const foo = new Foo({ y: 'bar' });
expect(foo.getClient()).toBe('bar');
expect(foo.x).toBe('foo');
expect(foo.z).toBe('bar');

View File

@ -0,0 +1,8 @@
class Foo {
#client
constructor(props) {
this.#client = 'foo';
({ x: this.x = this.#client, y: this.#client, z: this.z = this.#client } = props)
}
}

View File

@ -0,0 +1,17 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _client, {
writable: true,
value: void 0
});
babelHelpers.classPrivateFieldLooseBase(this, _client)[_client] = 'foo';
({
x: this.x = babelHelpers.classPrivateFieldLooseBase(this, _client)[_client],
y: babelHelpers.classPrivateFieldLooseBase(this, _client)[_client],
z: this.z = babelHelpers.classPrivateFieldLooseBase(this, _client)[_client]
} = props);
};
var _client = babelHelpers.classPrivateFieldLooseKey("client");

View File

@ -0,0 +1,15 @@
class Foo {
#client
constructor(props) {
let x;
;({ x, ...this.#client } = props)
}
getClient() {
return this.#client;
}
}
const foo = new Foo({ x: 'foo', y: 'bar', z: 'baz' });
expect(foo.getClient()).toEqual({ y: 'bar', z: 'baz' });

View File

@ -0,0 +1,15 @@
{
"plugins": [
"transform-destructuring",
[
"external-helpers",
{
"helperVersion": "7.4.4"
}
],
"proposal-class-properties",
"transform-classes",
"transform-block-scoping",
"syntax-class-properties"
]
}

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
({ x, ...this.#client } = props)
}
}

View File

@ -0,0 +1,15 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _client, {
writable: true,
value: void 0
});
({
x,
...babelHelpers.classPrivateFieldLooseBase(this, _client)[_client]
} = props);
};
var _client = babelHelpers.classPrivateFieldLooseKey("client");

View File

@ -0,0 +1,14 @@
class Foo {
#client
constructor(props) {
({ client: this.#client = 5 } = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo({});
expect(foo.getClient()).toEqual(5);

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
({ client: this.#client = 5 } = props);
}
}

View File

@ -0,0 +1,14 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _client, {
writable: true,
value: void 0
});
({
client: babelHelpers.classPrivateFieldLooseBase(this, _client)[_client] = 5
} = props);
};
var _client = babelHelpers.classPrivateFieldLooseKey("client");

View File

@ -0,0 +1,14 @@
class Foo {
#client
constructor(props) {
;({ client: this.#client } = props)
}
getClient() {
return this.#client;
}
}
const foo = new Foo({ client: 'bar' });
expect(foo.getClient()).toBe('bar');

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
({ client: this.#client } = props)
}
}

View File

@ -0,0 +1,14 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _client, {
writable: true,
value: void 0
});
({
client: babelHelpers.classPrivateFieldLooseBase(this, _client)[_client]
} = props);
};
var _client = babelHelpers.classPrivateFieldLooseKey("client");

View File

@ -0,0 +1,17 @@
class Foo {
#client
constructor(props) {
this.#client = 1;
;([this.x = this.#client, this.#client, this.y = this.#client] = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo([undefined, 'bar']);
expect(foo.getClient()).toBe('bar');
expect(foo.x).toBe(1);
expect(foo.y).toBe('bar');

View File

@ -0,0 +1,8 @@
class Foo {
#client
constructor(props) {
this.#client = 1;
([this.x = this.#client, this.#client, this.y = this.#client] = props);
}
}

View File

@ -0,0 +1,15 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
_client.set(this, {
writable: true,
value: void 0
});
babelHelpers.classPrivateFieldSet(this, _client, 1);
[this.x = babelHelpers.classPrivateFieldGet(this, _client), babelHelpers.classPrivateFieldDestructureSet(this, _client).value, this.y = babelHelpers.classPrivateFieldGet(this, _client)] = props;
};
var _client = new WeakMap();

View File

@ -0,0 +1,15 @@
class Foo {
#client
constructor(props) {
let x;
;([x, ...this.#client] = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo(['foo', 'bar', 'baz', 'quu']);
expect(foo.getClient()).toEqual(['bar', 'baz', 'quu']);

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
([x, ...this.#client] = props);
}
}

View File

@ -0,0 +1,14 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
_client.set(this, {
writable: true,
value: void 0
});
[x, ...babelHelpers.classPrivateFieldDestructureSet(this, _client).value] = props;
};
var _client = new WeakMap();

View File

@ -0,0 +1,14 @@
class Foo {
#client
constructor(props) {
([this.#client = 5] = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo([]);
expect(foo.getClient()).toEqual(5);

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
([this.#client = 5] = props);
}
}

View File

@ -0,0 +1,14 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
_client.set(this, {
writable: true,
value: void 0
});
[babelHelpers.classPrivateFieldDestructureSet(this, _client).value = 5] = props;
};
var _client = new WeakMap();

View File

@ -0,0 +1,14 @@
class Foo {
#client
constructor(props) {
;([this.#client] = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo(['bar']);
expect(foo.getClient()).toBe('bar');

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
([this.#client] = props);
}
}

View File

@ -0,0 +1,14 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
_client.set(this, {
writable: true,
value: void 0
});
[babelHelpers.classPrivateFieldDestructureSet(this, _client).value] = props;
};
var _client = new WeakMap();

View File

@ -0,0 +1,17 @@
class Foo {
#client
constructor(props) {
this.#client = 'foo';
;({ x: this.x = this.#client, y: this.#client, z: this.z = this.#client } = props)
}
getClient() {
return this.#client;
}
}
const foo = new Foo({ y: 'bar' });
expect(foo.getClient()).toBe('bar');
expect(foo.x).toBe('foo');
expect(foo.z).toBe('bar');

View File

@ -0,0 +1,8 @@
class Foo {
#client
constructor(props) {
this.#client = 'foo';
({ x: this.x = this.#client, y: this.#client, z: this.z = this.#client } = props)
}
}

View File

@ -0,0 +1,19 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
_client.set(this, {
writable: true,
value: void 0
});
babelHelpers.classPrivateFieldSet(this, _client, 'foo');
({
x: this.x = babelHelpers.classPrivateFieldGet(this, _client),
y: babelHelpers.classPrivateFieldDestructureSet(this, _client).value,
z: this.z = babelHelpers.classPrivateFieldGet(this, _client)
} = props);
};
var _client = new WeakMap();

View File

@ -0,0 +1,15 @@
class Foo {
#client
constructor(props) {
let x;
;({ x, ...this.#client } = props)
}
getClient() {
return this.#client;
}
}
const foo = new Foo({ x: 'foo', y: 'bar', z: 'baz' });
expect(foo.getClient()).toEqual({ y: 'bar', z: 'baz' });

View File

@ -0,0 +1,15 @@
{
"plugins": [
"transform-destructuring",
[
"external-helpers",
{
"helperVersion": "7.4.4"
}
],
"proposal-class-properties",
"transform-classes",
"transform-block-scoping",
"syntax-class-properties"
]
}

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
({ x, ...this.#client } = props)
}
}

View File

@ -0,0 +1,17 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
_client.set(this, {
writable: true,
value: void 0
});
({
x,
...babelHelpers.classPrivateFieldDestructureSet(this, _client).value
} = props);
};
var _client = new WeakMap();

View File

@ -0,0 +1,14 @@
class Foo {
#client
constructor(props) {
({x: this.#client = 5} = props);
}
getClient() {
return this.#client;
}
}
const foo = new Foo({});
expect(foo.getClient()).toEqual(5);

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
({x: this.#client = 5} = props);
}
}

View File

@ -0,0 +1,16 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
_client.set(this, {
writable: true,
value: void 0
});
({
x: babelHelpers.classPrivateFieldDestructureSet(this, _client).value = 5
} = props);
};
var _client = new WeakMap();

View File

@ -0,0 +1,14 @@
class Foo {
#client
constructor(props) {
;({ client: this.#client } = props)
}
getClient() {
return this.#client;
}
}
const foo = new Foo({ client: 'bar' });
expect(foo.getClient()).toBe('bar');

View File

@ -0,0 +1,7 @@
class Foo {
#client
constructor(props) {
({ client: this.#client } = props)
}
}

View File

@ -0,0 +1,16 @@
var Foo = function Foo(props) {
"use strict";
babelHelpers.classCallCheck(this, Foo);
_client.set(this, {
writable: true,
value: void 0
});
({
client: babelHelpers.classPrivateFieldDestructureSet(this, _client).value
} = props);
};
var _client = new WeakMap();

View File

@ -3,7 +3,7 @@
[
"external-helpers",
{
"helperVersion": "7.0.2"
"helperVersion": "7.4.4"
}
],
"proposal-class-properties",

View File

@ -0,0 +1,5 @@
class Foo {
constructor(props) {
;([x, ...super.client] = props);
}
}

View File

@ -0,0 +1,10 @@
{
"plugins": [
"external-helpers",
"proposal-class-properties",
"transform-classes",
"transform-block-scoping",
"syntax-class-properties"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
class Foo {
constructor(props) {
;([super.client] = props);
}
}

View File

@ -0,0 +1,10 @@
{
"plugins": [
"external-helpers",
"proposal-class-properties",
"transform-classes",
"transform-block-scoping",
"syntax-class-properties"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
class Foo {
constructor(props) {
;({ x, ...super.client } = props)
}
}

View File

@ -0,0 +1,10 @@
{
"plugins": [
"external-helpers",
"proposal-class-properties",
"transform-classes",
"transform-block-scoping",
"syntax-class-properties"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
class Foo {
constructor(props) {
;({ client: super.client } = props)
}
}

View File

@ -0,0 +1,10 @@
{
"plugins": [
"external-helpers",
"proposal-class-properties",
"transform-classes",
"transform-block-scoping",
"syntax-class-properties"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
class Foo {
foo(props) {
;([x, ...super.client] = props);
}
}

View File

@ -0,0 +1,16 @@
var Foo =
/*#__PURE__*/
function () {
"use strict";
function Foo() {}
var _proto = Foo.prototype;
_proto.foo = function foo(props) {
;
[x, ...this.client] = props;
};
return Foo;
}();

View File

@ -0,0 +1,5 @@
class Foo {
foo(props) {
;([super.client] = props);
}
}

View File

@ -0,0 +1,16 @@
var Foo =
/*#__PURE__*/
function () {
"use strict";
function Foo() {}
var _proto = Foo.prototype;
_proto.foo = function foo(props) {
;
[this.client] = props;
};
return Foo;
}();

View File

@ -0,0 +1,5 @@
class Foo {
foo(props) {
;({ x, ...super.client } = props)
}
}

View File

@ -0,0 +1,19 @@
var Foo =
/*#__PURE__*/
function () {
"use strict";
function Foo() {}
var _proto = Foo.prototype;
_proto.foo = function foo(props) {
;
({
x,
...this.client
} = props);
};
return Foo;
}();

View File

@ -0,0 +1,5 @@
class Foo {
foo(props) {
;({ client: super.client } = props)
}
}

View File

@ -0,0 +1,18 @@
var Foo =
/*#__PURE__*/
function () {
"use strict";
function Foo() {}
var _proto = Foo.prototype;
_proto.foo = function foo(props) {
;
({
client: this.client
} = props);
};
return Foo;
}();

View File

@ -0,0 +1,5 @@
class Foo {
constructor(props) {
;([x, ...super.client] = props);
}
}

View File

@ -0,0 +1,10 @@
{
"plugins": [
"external-helpers",
"transform-function-name",
"transform-classes",
"transform-spread",
"transform-block-scoping"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
class Foo {
constructor(props) {
;([super.client] = props);
}
}

View File

@ -0,0 +1,10 @@
{
"plugins": [
"external-helpers",
"transform-function-name",
"transform-classes",
"transform-spread",
"transform-block-scoping"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
class Foo {
constructor(props) {
;({ x, ...super.client } = props)
}
}

View File

@ -0,0 +1,10 @@
{
"plugins": [
"external-helpers",
"transform-function-name",
"transform-classes",
"transform-spread",
"transform-block-scoping"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
class Foo {
constructor(props) {
;({ client: super.client } = props)
}
}

View File

@ -0,0 +1,10 @@
{
"plugins": [
"external-helpers",
"transform-function-name",
"transform-classes",
"transform-spread",
"transform-block-scoping"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
const foo = {
bar(props) {
;([x, ...super.client] = props);
}
}

View File

@ -0,0 +1,8 @@
{
"plugins": [
"external-helpers",
"transform-object-super",
"transform-shorthand-properties"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
const foo = {
bar(props) {
;([super.client] = props);
}
}

View File

@ -0,0 +1,8 @@
{
"plugins": [
"external-helpers",
"transform-object-super",
"transform-shorthand-properties"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
const foo = {
bar(props) {
;({ x, ...super.client } = props)
}
}

View File

@ -0,0 +1,8 @@
{
"plugins": [
"external-helpers",
"transform-object-super",
"transform-shorthand-properties"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -0,0 +1,5 @@
const foo = {
bar(props) {
;({ client: super.client } = props)
}
}

View File

@ -0,0 +1,8 @@
{
"plugins": [
"external-helpers",
"transform-object-super",
"transform-shorthand-properties"
],
"throws": "Destructuring to a super field is not supported yet."
}

View File

@ -20,7 +20,12 @@ defineType("AssignmentPattern", {
fields: {
...patternLikeCommon,
left: {
validate: assertNodeType("Identifier", "ObjectPattern", "ArrayPattern"),
validate: assertNodeType(
"Identifier",
"ObjectPattern",
"ArrayPattern",
"MemberExpression",
),
},
right: {
validate: assertNodeType("Expression"),