Skip to content

Commit

Permalink
Class static private field destructure set (#12917)
Browse files Browse the repository at this point in the history
* fix: support static private field destructure set ([C.#p] = [0])

* 馃毀

* fix: add compatibility warning for older @babel/helper versions

* refactor: extract common routines among classPrivateFiled helpers

* More 馃毀
  • Loading branch information
JLHwung committed Mar 3, 2021
1 parent 70c77e5 commit bdb207c
Show file tree
Hide file tree
Showing 49 changed files with 515 additions and 129 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/release.yml
Expand Up @@ -49,7 +49,9 @@ jobs:
git config user.email "babel-bot@users.noreply.github.com"
- name: Create new version
run: yarn release-tool version -f @babel/standalone --yes patch
run: |
make new-version-checklist
yarn release-tool version -f @babel/standalone --yes patch
- name: Push to GitHub
id: push
Expand Down Expand Up @@ -167,5 +169,4 @@ jobs:
- name: Delete temporary branch from GitHub
if: needs.git-version.result == 'success'
run:
git push "https://babel-bot:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git" :${{ needs.git-version.outputs.branch }}
run: git push "https://babel-bot:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git" :${{ needs.git-version.outputs.branch }}
14 changes: 14 additions & 0 deletions Makefile
Expand Up @@ -195,7 +195,21 @@ prepublish:
$(MAKE) prepublish-build
IS_PUBLISH=true $(MAKE) test

new-version-checklist:
@echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
@echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
@echo "!!!!!! !!!!!!"
@echo "!!!!!! Update classStaticPrivateFieldDestructureSet !!!!!!"
@echo "!!!!!! helper version in !!!!!!"
@echo "!!!!!! packages/babel-helpers/src/helpers.js !!!!!!"
@echo "!!!!!! packages/babel-helper-create-class-features-plugin/src/fields.js"
@echo "!!!!!! !!!!!!"
@echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
@echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
@exit 1

new-version:
$(MAKE) new-version-checklist
git pull --rebase
$(YARN) release-tool version -f @babel/standalone

Expand Down
25 changes: 23 additions & 2 deletions packages/babel-helper-create-class-features-plugin/src/fields.js
Expand Up @@ -318,9 +318,30 @@ const privateNameHandlerSpec = {
},

destructureSet(member) {
const { privateNamesMap, file } = this;
const { classRef, privateNamesMap, file } = this;
const { name } = member.node.property.id;
const { id } = privateNamesMap.get(name);
const { id, static: isStatic } = privateNamesMap.get(name);
if (isStatic) {
try {
// classStaticPrivateFieldDestructureSet was introduced in 7.99.0
// eslint-disable-next-line no-var
var helper = file.addHelper("classStaticPrivateFieldDestructureSet");
} catch {
throw new Error(
"Babel can not transpile `[C.#p] = [0]` with @babel/helpers < 7.99.0, \n" +
"please update @babel/helpers to the latest version.",
);
}
return t.memberExpression(
t.callExpression(helper, [
this.receiver(member),
t.cloneNode(classRef),
t.cloneNode(id),
]),
t.identifier("value"),
);
}

return t.memberExpression(
t.callExpression(file.addHelper("classPrivateFieldDestructureSet"), [
this.receiver(member),
Expand Down
153 changes: 91 additions & 62 deletions packages/babel-helpers/src/helpers.js
Expand Up @@ -1299,24 +1299,90 @@ helpers.classPrivateFieldLooseBase = helper("7.0.0-beta.0")`
`;

helpers.classPrivateFieldGet = helper("7.0.0-beta.0")`
import classApplyDescriptorGet from "classApplyDescriptorGet";
import classExtractFieldDescriptor from "classExtractFieldDescriptor";
export default function _classPrivateFieldGet(receiver, privateMap) {
var descriptor = privateMap.get(receiver);
if (!descriptor) {
throw new TypeError("attempted to get private field on non-instance");
var descriptor = classExtractFieldDescriptor(receiver, privateMap, "get");
return classApplyDescriptorGet(receiver, descriptor);
}
`;

helpers.classPrivateFieldSet = helper("7.0.0-beta.0")`
import classApplyDescriptorSet from "classApplyDescriptorSet";
import classExtractFieldDescriptor from "classExtractFieldDescriptor";
export default function _classPrivateFieldSet(receiver, privateMap, value) {
var descriptor = classExtractFieldDescriptor(receiver, privateMap, "set");
classApplyDescriptorSet(receiver, descriptor, value);
return value;
}
`;

helpers.classPrivateFieldDestructureSet = helper("7.4.4")`
import classApplyDescriptorDestructureSet from "classApplyDescriptorDestructureSet";
import classExtractFieldDescriptor from "classExtractFieldDescriptor";
export default function _classPrivateFieldDestructureSet(receiver, privateMap) {
var descriptor = classExtractFieldDescriptor(receiver, privateMap, "set");
return classApplyDescriptorDestructureSet(receiver, descriptor);
}
`;

helpers.classExtractFieldDescriptor = helper("7.99.0")`
export default function _classExtractFieldDescriptor(receiver, privateMap, action) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to " + action + " private field on non-instance");
}
return privateMap.get(receiver);
}
`;

helpers.classStaticPrivateFieldSpecGet = helper("7.0.2")`
import classApplyDescriptorGet from "classApplyDescriptorGet";
import classCheckPrivateStaticAccess from "classCheckPrivateStaticAccess";
import classCheckPrivateStaticFieldDescriptor from "classCheckPrivateStaticFieldDescriptor";
export default function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) {
classCheckPrivateStaticAccess(receiver, classConstructor);
classCheckPrivateStaticFieldDescriptor(descriptor, "get");
return classApplyDescriptorGet(receiver, descriptor);
}
`;

helpers.classStaticPrivateFieldSpecSet = helper("7.0.2")`
import classApplyDescriptorSet from "classApplyDescriptorSet";
import classCheckPrivateStaticAccess from "classCheckPrivateStaticAccess";
import classCheckPrivateStaticFieldDescriptor from "classCheckPrivateStaticFieldDescriptor";
export default function _classStaticPrivateFieldSpecSet(receiver, classConstructor, descriptor, value) {
classCheckPrivateStaticAccess(receiver, classConstructor);
classCheckPrivateStaticFieldDescriptor(descriptor, "set");
classApplyDescriptorSet(receiver, descriptor, value);
return value;
}
`;

helpers.classStaticPrivateMethodGet = helper("7.3.2")`
import classCheckPrivateStaticAccess from "classCheckPrivateStaticAccess";
export default function _classStaticPrivateMethodGet(receiver, classConstructor, method) {
classCheckPrivateStaticAccess(receiver, classConstructor);
return method;
}
`;

helpers.classStaticPrivateMethodSet = helper("7.3.2")`
export default function _classStaticPrivateMethodSet() {
throw new TypeError("attempted to set read only static private field");
}
`;

helpers.classApplyDescriptorGet = helper("7.99.0")`
export default function _classApplyDescriptorGet(receiver, descriptor) {
if (descriptor.get) {
return descriptor.get.call(receiver);
}
return descriptor.value;
}
`;

helpers.classPrivateFieldSet = helper("7.0.0-beta.0")`
export default function _classPrivateFieldSet(receiver, privateMap, value) {
var descriptor = privateMap.get(receiver);
if (!descriptor) {
throw new TypeError("attempted to set private field on non-instance");
}
helpers.classApplyDescriptorSet = helper("7.99.0")`
export default function _classApplyDescriptorSet(receiver, descriptor, value) {
if (descriptor.set) {
descriptor.set.call(receiver, value);
} else {
Expand All @@ -1326,23 +1392,13 @@ helpers.classPrivateFieldSet = helper("7.0.0-beta.0")`
// class bodies.
throw new TypeError("attempted to set read only private field");
}
descriptor.value = value;
}
return value;
}
`;

helpers.classPrivateFieldDestructureSet = helper("7.4.4")`
export default function _classPrivateFieldDestructureSet(receiver, privateMap) {
if (privateMap === undefined) {
throw new TypeError("attempted to set private static field before its declaration");
}
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance");
}
var descriptor = privateMap.get(receiver);
helpers.classApplyDescriptorDestructureSet = helper("7.99.0")`
export default function _classApplyDescriptorDestructureSet(receiver, descriptor) {
if (descriptor.set) {
if (!("__destrObj" in descriptor)) {
descriptor.__destrObj = {
Expand All @@ -1365,57 +1421,30 @@ helpers.classPrivateFieldDestructureSet = helper("7.4.4")`
}
`;

helpers.classStaticPrivateFieldSpecGet = helper("7.0.2")`
export default function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) {
if (receiver !== classConstructor) {
throw new TypeError("Private static access of wrong provenance");
}
if (descriptor === undefined) {
throw new TypeError("attempted to get private static field before its declaration");
}
if (descriptor.get) {
return descriptor.get.call(receiver);
}
return descriptor.value;
helpers.classStaticPrivateFieldDestructureSet = helper("7.99.0")`
import classApplyDescriptorDestructureSet from "classApplyDescriptorDestructureSet";
import classCheckPrivateStaticAccess from "classCheckPrivateStaticAccess";
import classCheckPrivateStaticFieldDescriptor from "classCheckPrivateStaticFieldDescriptor";
export default function _classStaticPrivateFieldDestructureSet(receiver, classConstructor, descriptor) {
classCheckPrivateStaticAccess(receiver, classConstructor);
classCheckPrivateStaticFieldDescriptor(descriptor, "set");
return classApplyDescriptorDestructureSet(receiver, descriptor);
}
`;

helpers.classStaticPrivateFieldSpecSet = helper("7.0.2")`
export default function _classStaticPrivateFieldSpecSet(receiver, classConstructor, descriptor, value) {
helpers.classCheckPrivateStaticAccess = helper("7.99.0")`
export default function _classCheckPrivateStaticAccess(receiver, classConstructor) {
if (receiver !== classConstructor) {
throw new TypeError("Private static access of wrong provenance");
}
if (descriptor === undefined) {
throw new TypeError("attempted to set private static field before its declaration");
}
if (descriptor.set) {
descriptor.set.call(receiver, value);
} 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");
}
descriptor.value = value;
}
return value;
}
`;

helpers.classStaticPrivateMethodGet = helper("7.3.2")`
export default function _classStaticPrivateMethodGet(receiver, classConstructor, method) {
if (receiver !== classConstructor) {
throw new TypeError("Private static access of wrong provenance");
helpers.classCheckPrivateStaticFieldDescriptor = helper("7.99.0")`
export default function _classCheckPrivateStaticFieldDescriptor(descriptor, action) {
if (descriptor === undefined) {
throw new TypeError("attempted to " + action + " private static field before its declaration");
}
return method;
}
`;

helpers.classStaticPrivateMethodSet = helper("7.3.2")`
export default function _classStaticPrivateMethodSet() {
throw new TypeError("attempted to set read only static private field");
}
`;

Expand Down
@@ -0,0 +1,14 @@
class Foo {
static #client

constructor(props) {
;([Foo.#client] = props);
}

getClient() {
return Foo.#client;
}
}

const foo = new Foo(['bar']);
expect(foo.getClient()).toBe('bar');
@@ -0,0 +1,7 @@
class Foo {
static #client

constructor(props) {
([Foo.#client] = props);
}
}
@@ -0,0 +1,13 @@
var _client = babelHelpers.classPrivateFieldLooseKey("client");

var Foo = function Foo(props) {
"use strict";

babelHelpers.classCallCheck(this, Foo);
[babelHelpers.classPrivateFieldLooseBase(Foo, _client)[_client]] = props;
};

Object.defineProperty(Foo, _client, {
writable: true,
value: void 0
});
@@ -0,0 +1,14 @@
class Foo {
static #client

constructor(props) {
;({ client: Foo.#client } = props)
}

getClient() {
return Foo.#client;
}
}

const foo = new Foo({ client: 'bar' });
expect(foo.getClient()).toBe('bar');
@@ -0,0 +1,7 @@
class Foo {
static #client

constructor(props) {
({ client: Foo.#client } = props)
}
}
@@ -0,0 +1,15 @@
var _client = babelHelpers.classPrivateFieldLooseKey("client");

var Foo = function Foo(props) {
"use strict";

babelHelpers.classCallCheck(this, Foo);
({
client: babelHelpers.classPrivateFieldLooseBase(Foo, _client)[_client]
} = props);
};

Object.defineProperty(Foo, _client, {
writable: true,
value: void 0
});
@@ -0,0 +1,14 @@
class Foo {
static #client

constructor(props) {
;([Foo.#client] = props);
}

getClient() {
return Foo.#client;
}
}

const foo = new Foo(['bar']);
expect(foo.getClient()).toBe('bar');
@@ -0,0 +1,7 @@
class Foo {
static #client

constructor(props) {
([Foo.#client] = props);
}
}
@@ -0,0 +1,11 @@
var Foo = function Foo(props) {
"use strict";

babelHelpers.classCallCheck(this, Foo);
[babelHelpers.classStaticPrivateFieldDestructureSet(Foo, Foo, _client).value] = props;
};

var _client = {
writable: true,
value: void 0
};
@@ -0,0 +1,14 @@
class Foo {
static #client

constructor(props) {
;({ client: Foo.#client } = props)
}

getClient() {
return Foo.#client;
}
}

const foo = new Foo({ client: 'bar' });
expect(foo.getClient()).toBe('bar');

0 comments on commit bdb207c

Please sign in to comment.