From fcfaa05e5c3fdc8284780199fb810245a42cfdd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sat, 12 Mar 2022 18:31:40 +0100 Subject: [PATCH] [setPublicClassFields] Use define for static `name`/`length` --- .../src/fields.ts | 27 ++++++++++++++++--- .../length-name-use-define/input.js | 11 ++++++++ .../length-name-use-define/output.js | 19 +++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/length-name-use-define/input.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/length-name-use-define/output.js diff --git a/packages/babel-helper-create-class-features-plugin/src/fields.ts b/packages/babel-helper-create-class-features-plugin/src/fields.ts index f4083d199f20..16842401fbfb 100644 --- a/packages/babel-helper-create-class-features-plugin/src/fields.ts +++ b/packages/babel-helper-create-class-features-plugin/src/fields.ts @@ -936,6 +936,18 @@ export type PropNode = | t.StaticBlock; export type PropPath = NodePath; +function isNameOrLength(node: t.ClassProperty) { + if (node.key.type === "Identifier") { + return ( + !node.computed && (node.key.name === "name" || node.key.name === "length") + ); + } + if (node.key.type === "StringLiteral") { + return node.key.value === "name" || node.key.value === "length"; + } + return false; +} + export function buildFieldsInitNodes( ref: t.Identifier, superRef: t.Expression | undefined, @@ -1019,10 +1031,19 @@ export function buildFieldsInitNodes( ); break; case isStatic && isPublic && isField && setPublicClassFields: - needsClassRef = true; + // Functions always have non-writable .name and .length properties, + // so we must always use [[Define]] for them. + // It might still be possible to a computed static fields whose resulting + // key is "name" or "length", but the assumption is telling us that it's + // not going to happen. // @ts-expect-error checked in switch - staticNodes.push(buildPublicFieldInitLoose(t.cloneNode(ref), prop)); - break; + if (!isNameOrLength(prop.node)) { + needsClassRef = true; + // @ts-expect-error checked in switch + staticNodes.push(buildPublicFieldInitLoose(t.cloneNode(ref), prop)); + break; + } + // falls through case isStatic && isPublic && isField && !setPublicClassFields: needsClassRef = true; staticNodes.push( diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/length-name-use-define/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/length-name-use-define/input.js new file mode 100644 index 000000000000..ba1775f8fd16 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/length-name-use-define/input.js @@ -0,0 +1,11 @@ +class A { + static name = 1; + static length = 2; + static foo = 3; + static [bar] = 4; + static ["name"] = 5; + static [name] = 6; + + name = 7; + length = 8; +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/length-name-use-define/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/length-name-use-define/output.js new file mode 100644 index 000000000000..27c9b8adfba9 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/length-name-use-define/output.js @@ -0,0 +1,19 @@ +let _bar, _name; + +_bar = bar; +_name = name; + +class A { + constructor() { + this.name = 7; + this.length = 8; + } + +} + +babelHelpers.defineProperty(A, "name", 1); +babelHelpers.defineProperty(A, "length", 2); +A.foo = 3; +A[_bar] = 4; +babelHelpers.defineProperty(A, "name", 5); +A[_name] = 6;