diff --git a/packages/babel-helper-create-class-features-plugin/src/decorators.ts b/packages/babel-helper-create-class-features-plugin/src/decorators.ts index d4175e68a395..432439aed912 100644 --- a/packages/babel-helper-create-class-features-plugin/src/decorators.ts +++ b/packages/babel-helper-create-class-features-plugin/src/decorators.ts @@ -80,7 +80,10 @@ function extractElementDescriptor( const properties: t.ObjectExpression["properties"] = [ prop("kind", t.stringLiteral(t.isClassMethod(node) ? node.kind : "field")), prop("decorators", takeDecorators(node as Decorable)), - prop("static", node.static && t.booleanLiteral(true)), + prop( + "static", + !t.isStaticBlock(node) && node.static && t.booleanLiteral(true), + ), prop("key", getKey(node)), ].filter(Boolean); 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 cbaee3f1ca2d..bebb6a107cc9 100644 --- a/packages/babel-helper-create-class-features-plugin/src/fields.ts +++ b/packages/babel-helper-create-class-features-plugin/src/fields.ts @@ -911,7 +911,7 @@ function replaceThisContext( getSuperRef, getObjectRef() { state.needsClassRef = true; - return isStaticBlock || path.node.static + return t.isStaticBlock(path.node) || path.node.static ? ref : t.memberExpression(ref, t.identifier("prototype")); }, @@ -931,7 +931,8 @@ function replaceThisContext( export type PropNode = | t.ClassProperty | t.ClassPrivateMethod - | t.ClassPrivateProperty; + | t.ClassPrivateProperty + | t.StaticBlock; export type PropPath = NodePath; export function buildFieldsInitNodes( @@ -963,7 +964,7 @@ export function buildFieldsInitNodes( for (const prop of props) { prop.isClassProperty() && ts.assertFieldTransformed(prop); - const isStatic = prop.node.static; + const isStatic = !t.isStaticBlock(prop.node) && prop.node.static; const isInstance = !isStatic; const isPrivate = prop.isPrivate(); const isPublic = !isPrivate; diff --git a/packages/babel-helper-create-class-features-plugin/src/index.ts b/packages/babel-helper-create-class-features-plugin/src/index.ts index 6e242a58c7c4..70da4597d09b 100644 --- a/packages/babel-helper-create-class-features-plugin/src/index.ts +++ b/packages/babel-helper-create-class-features-plugin/src/index.ts @@ -170,7 +170,7 @@ export function createClassFeaturePlugin({ path.isPrivate() || path.isStaticBlock?.() ) { - props.push(path); + props.push(path as PropPath); } } } @@ -246,7 +246,7 @@ export function createClassFeaturePlugin({ (referenceVisitor, state) => { if (isDecorated) return; for (const prop of props) { - if (prop.node.static) continue; + if (t.isStaticBlock(prop.node) || prop.node.static) continue; prop.traverse(referenceVisitor, state); } }, diff --git a/packages/babel-helpers/src/helpers-generated.ts b/packages/babel-helpers/src/helpers-generated.ts index 1f148f411cae..ae41ece213ea 100644 --- a/packages/babel-helpers/src/helpers-generated.ts +++ b/packages/babel-helpers/src/helpers-generated.ts @@ -13,6 +13,10 @@ function helper(minVersion, source) { } export default Object.freeze({ + applyDecs: helper( + "7.16.6", + 'function createMetadataMethodsForProperty(metadataMap,kind,property){return{getMetadata(key){if("symbol"!=typeof key)throw new TypeError("Metadata keys must be symbols, received: "+key);var metadataForKey=metadataMap[key];if(void 0!==metadataForKey)if(1===kind){var pub=metadataForKey.public;if(void 0!==pub)return pub[property]}else if(2===kind){var priv=metadataForKey.private;if(void 0!==priv)return priv.get(property)}else if(Object.hasOwnProperty.call(metadataForKey,"constructor"))return metadataForKey.constructor},setMetadata(key,value){if("symbol"!=typeof key)throw new TypeError("Metadata keys must be symbols, received: "+key);var metadataForKey=metadataMap[key];if(void 0===metadataForKey&&(metadataForKey=metadataMap[key]={}),1===kind){var pub=metadataForKey.public;void 0===pub&&(pub=metadataForKey.public=Object.create(null)),pub[property]=value}else if(2===kind){var priv=metadataForKey.priv;void 0===priv&&(priv=metadataForKey.private=new Map),priv.set(property,value)}else metadataForKey.constructor=value}}}function convertMetadataMapToFinal(obj,metadataMap){var parentMetadataMap=obj[Symbol.metadata],metadataKeys=Object.getOwnPropertySymbols(metadataMap);if(0!==metadataKeys.length){for(var i=0;i3,isStatic=kind>=5;if(isStatic?(base=Class,metadataMap=staticMetadataMap,kind-=5,staticInitializers||(staticInitializers=[]),initializers=staticInitializers):(base=Class.prototype,metadataMap=protoMetadataMap,protoInitializers||(protoInitializers=[]),initializers=protoInitializers),0!==kind&&!isPrivate){var existingNonFields=isStatic?existingStaticNonFields:existingProtoNonFields,existingKind=existingNonFields.get(name)||0;if(!0===existingKind||3===existingKind&&4!==kind||4===existingKind&&3!==kind)throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+name);!existingKind&&kind>2?existingNonFields.set(name,kind):existingNonFields.set(name,!0)}applyMemberDec(ret,base,decInfo,name,kind,isStatic,isPrivate,metadataMap,initializers)}}protoInitializers&&pushInitializers(ret,protoInitializers),staticInitializers&&pushInitializers(ret,staticInitializers)}function pushInitializers(ret,initializers){initializers.length>0?(initializers=initializers.slice(),ret.push((function(instance){for(var i=0;i0?ret.push((function(){for(var i=0;i 3; + + var isStatic = kind >= 5; /* STATIC */ + var base; + var metadataMap; + var initializers; + + if (isStatic) { + base = Class; + metadataMap = staticMetadataMap; + kind = kind - 5 /* STATIC */; + + if (!staticInitializers) { + staticInitializers = []; + } + + initializers = staticInitializers; + } else { + base = Class.prototype; + metadataMap = protoMetadataMap; + + if (!protoInitializers) { + protoInitializers = []; + } + + initializers = protoInitializers; + } + + if (kind !== 0 /* FIELD */ && !isPrivate) { + var existingNonFields = isStatic + ? existingStaticNonFields + : existingProtoNonFields; + + var existingKind = existingNonFields.get(name) || 0; + + if ( + existingKind === true || + (existingKind === 3 /* GETTER */ && kind !== 4) /* SETTER */ || + (existingKind === 4 /* SETTER */ && kind !== 3) /* GETTER */ + ) { + throw new Error( + "Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + + name + ); + } else if (!existingKind && kind > 2 /* METHOD */) { + existingNonFields.set(name, kind); + } else { + existingNonFields.set(name, true); + } + } + + applyMemberDec( + ret, + base, + decInfo, + name, + kind, + isStatic, + isPrivate, + metadataMap, + initializers + ); + } + + if (protoInitializers) { + pushInitializers(ret, protoInitializers); + } + + if (staticInitializers) { + pushInitializers(ret, staticInitializers); + } +} + +function pushInitializers(ret, initializers) { + if (initializers.length > 0) { + // Slice the array, which means that `addInitializer` can no longer add + // additional initializers to the array + initializers = initializers.slice(); + + ret.push(function (instance) { + for (var i = 0; i < initializers.length; i++) { + initializers[i].call(instance, instance); + } + }); + } else { + ret.push(function () {}); + } +} + +function applyClassDecs(ret, targetClass, metadataMap, classDecs) { + var initializers = []; + var newClass = targetClass; + + var name = targetClass.name; + var ctx = Object.assign( + { + kind: "class", + name: name, + addInitializer: createAddInitializerMethod(initializers), + }, + createMetadataMethodsForProperty(metadataMap, 0 /* CONSTRUCTOR */, name) + ); + + for (var i = 0; i < classDecs.length; i++) { + newClass = classDecs[i](newClass, ctx) || newClass; + } + + ret.push(newClass); + + if (initializers.length > 0) { + ret.push(function () { + for (var i = 0; i < initializers.length; i++) { + initializers[i].call(newClass, newClass); + } + }); + } else { + ret.push(function () {}); + } +} + +/** + Basic usage: + + applyDecs( + Class, + [ + // member decorators + [ + dec, // dec or array of decs + 0, // kind of value being decorated + 'prop', // name of public prop on class containing the value being decorated, + '#p', // the name of the private property (if is private, undefined otherwise), + ] + ], + [ + // class decorators + dec1, dec2 + ] + ) + ``` + + Fully transpiled example: + + ```js + @dec + class Class { + @dec + a = 123; + + @dec + #a = 123; + + @dec + @dec2 + accessor b = 123; + + @dec + accessor #b = 123; + + @dec + c() { console.log('c'); } + + @dec + #c() { console.log('privC'); } + + @dec + get d() { console.log('d'); } + + @dec + get #d() { console.log('privD'); } + + @dec + set e(v) { console.log('e'); } + + @dec + set #e(v) { console.log('privE'); } + } + + + // becomes + let initializeInstance; + let initializeClass; + + let initA; + let initPrivA; + + let initB; + let initPrivB, getPrivB, setPrivB; + + let privC; + let privD; + let privE; + + let Class; + class _Class { + static { + let ret = applyDecs( + this, + [ + [dec, 0, 'a'], + [dec, 0, 'a', (i) => i.#a, (i, v) => i.#a = v], + [[dec, dec2], 1, 'b'], + [dec, 1, 'b', (i) => i.#privBData, (i, v) => i.#privBData = v], + [dec, 2, 'c'], + [dec, 2, 'c', () => console.log('privC')], + [dec, 3, 'd'], + [dec, 3, 'd', () => console.log('privD')], + [dec, 4, 'e'], + [dec, 4, 'e', () => console.log('privE')], + ], + [ + dec + ] + ) + + initA = ret[0]; + + initPrivA = ret[1]; + + initB = ret[2]; + + initPrivB = ret[3]; + getPrivB = ret[4]; + setPrivB = ret[5]; + + privC = ret[6]; + + privD = ret[7]; + + privE = ret[8]; + + initializeInstance = ret[9]; + + Class = ret[10] + + initializeClass = ret[11]; + } + + a = (initializeInstance(this), initA(this, 123)); + + #a = initPrivA(this, 123); + + #bData = initB(this, 123); + get b() { return this.#bData } + set b(v) { this.#bData = v } + + #privBData = initPrivB(this, 123); + get #b() { return getPrivB(this); } + set #b(v) { setPrivB(this, v); } + + c() { console.log('c'); } + + #c(...args) { return privC(this, ...args) } + + get d() { console.log('d'); } + + get #d() { return privD(this); } + + set e(v) { console.log('e'); } + + set #e(v) { privE(this, v); } + } + + initializeClass(Class); + */ +export default function applyDecs(targetClass, memberDecs, classDecs) { + var ret = []; + var staticMetadataMap = {}; + + if (memberDecs) { + var protoMetadataMap = {}; + + applyMemberDecs( + ret, + targetClass, + protoMetadataMap, + staticMetadataMap, + memberDecs + ); + + convertMetadataMapToFinal(targetClass.prototype, protoMetadataMap); + } + + if (classDecs) { + applyClassDecs(ret, targetClass, staticMetadataMap, classDecs); + } + + convertMetadataMapToFinal(targetClass, staticMetadataMap); + + return ret; +} diff --git a/packages/babel-plugin-proposal-decorators/CONTRIB.md b/packages/babel-plugin-proposal-decorators/CONTRIB.md new file mode 100644 index 000000000000..30c36983e1ce --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/CONTRIB.md @@ -0,0 +1,374 @@ +These are notes about the implementation of the 2021-12 decorators transform. +The implementation's goals are (in descending order): + +1. Being accurate to the actual proposal (e.g. not defining additional + properties unless required, matching semantics exactly, etc.). This includes + being able to work properly with private fields and methods. +2. Transpiling to a very minimal and minifiable output. This transform will + affect each and every decorated class, so ensuring that the output is not 10x + the size of the original is important. +3. Having good runtime performance. Decoration output has the potential to + drastically impact startup performance, since it runs whenever a decorated + class is defined. In addition, every instance of a decorated class may be + impacted for certain types of decorators. + +All of these goals come somewhat at the expense of readability and can make the +implementation difficult to understand, so these notes are meant to document the +motivations behind the design. + +## Overview + +Given a simple decorated class like this one: + +```js +@dec +class Class { + @dec a = 123; + + @dec static #b() { + console.log('foo'); + } + + [someVal]() {} + + @dec + @dec2 + accessor #c = 456; +} +``` + +It's output would be something like the following: + +```js +import { applyDecs } from '@babel/helpers'; + +let initInstance, initClass, initA, callB, computedKey, initC, getC, setC; + +const elementDecs = [ + [dec, 0, 'a'], + [dec, 7, 'x', '#b'] + (computedKey = someVal, null) + [[dec, dec2], 1, 'y', '#c'] +]; + +const classDecs = [dec]; + +let Class; +class _Class { + static { + let ret = applyDecs( + this, + elementDecs, + [dec] + ); + + initA = ret[0]; + callB = ret[1]; + initC = ret[2]; + getC = ret[3]; + setC = ret[4]; + initInstance = ret[5]; + Class = ret[6]; + initClass = ret[7]; + } + + a = (initInstance(this), initA(this, 123)); + + static #b(...args) { + callB(this, args); + } + static x() { + console.log('foo'); + } + + [computedKey]() {} + + #y = initC(this, 123); + get y() { + return this.#y; + } + set y(v) { + this.#y = v; + } + get #c() { + return getC(this); + } + set #c(v) { + setC(this, v); + } + + static { + initClass(C); + } +} +``` + +Let's break this output down a bit: + +```js +let initInstance, initClass, initA, callB, initC, getC, setC; +``` + +First, we need to setup some local variables outside of the class. These are +for: + +- Decorated class field/accessor initializers +- Extra initializer functions added by `addInitializers` +- Private class methods + +These are essentially all values that cannot be defined on the class itself via +`Object.defineProperty`, so we have to insert them into the class manually, +ahead of time and populate them when we run our decorators. + +```js +const elementDecs = [ + [dec, 0, 'a'], + [dec, 7, 'x', '#b'] + (computedKey = someVal, null) + [[dec, dec2], 1, 'y', '#c'] +]; + +const classDecs = [dec]; +``` + +Next up, we define and evaluate the decorator member expressions. The reason we +do this _before_ defining the class is because we must interleave decorator +expressions with computed property key expressions, since computed properties +and decorators can run arbitrary code which can modify the runtime of subsequent +decorators or computed property keys. + +```js +let Class; +class _Class { +``` + +This class is being decorated directly, which means that the decorator may +replace the class itself. Class bindings are not mutable, so we need to create a +new `let` variable for the decorated class. + + +```js + static { + let ret = applyDecs( + this, + elementDecs, + classDecs + ); + + initA = ret[0]; + callB = ret[1]; + initC = ret[2]; + getC = ret[3]; + setC = ret[4]; + initInstance = ret[5]; + Class = ret[6]; + initClass = ret[7]; + } +``` + +Next, we immediately define a `static` block which actually applies the +decorators. This is important because we must apply the decorators _after_ the +class prototype has been fully setup, but _before_ static fields are run, since +static fields should only see the decorated version of the class. + +We apply the decorators to class elements and the class itself, and the +application returns an array of values that are used to populate all of the +local variables we defined earlier. The array's order is fully deterministic, so +we can assign the values based on an index we can calculate ahead of time. + +We'll come back to `applyDecs` in a bit to dig into what its format is exactly, +but now let's dig into the new definitions of our class elements. + +```js + a = (initInstance(this), initA(this, 123)); +``` + +Alright, so previously this was a simple class field. Since it's the first field +on the class, we've updated it to immediately call `initInstance` in its +initializer. This calls any initializers added with `addInitializer` for all of +the per-class values (methods and accessors), which should all be setup on the +instance before class fields are assigned. Then, it calls `initA` to get the +initial value of the field, which allows initializers returned from the +decorator to intercept and decorate it. It's important that the initial value +is used/defined _within_ the class body, because initializers can now refer to +private class fields, e.g. `a = this.#b` is a valid field initializer and would +become `a = initA(this, this.#b)`, which would also be valid. We cannot +extract initializer code, or any other code, from the class body because of +this. + +Overall, this decoration is pretty straightforward other than the fact that we +have to reference `initA` externally. + +```js + static #b(...args) { + callB(this, args); + } + static x() { + console.log('foo'); + } +``` + +Next up, we have a private static class method `#b`. This one is a bit more +complex, as our definition has been broken out into 2 parts: + +1. `static #b`: This is the method itself, which being a private method we + cannot overwrite with `defineProperty`. We also can't convert it into a + private field because that would change its semantics (would make it + writable). So, we instead have it proxy to the locally scoped `callB` + variable, which will be populated with the fully decorated method. +2. `static x`: This contains the _code_ of the original method. Once again, this + code cannot be removed from the class body because it may reference private + identifiers. However, we have moved the code to a _public_ method, which means + we can now read its value using `Object.getOwnPropertyDescriptor`. Decorators + use this to get the initial implementation of the method, which can then be + wrapped with decorator code/logic. They then `delete` this temporary property, + which is necessary because no additional elements should be added to a class + definition. + + The name for this method is unimportant, but because public method names + cannot be minified and we also need to pass the name into `applyDecs`, we + generate as small of a unique identifier as possible here, starting with 1 + char names which are not taken and growing until we find one that is free. + +```js + [computedKey]() {} +``` + +Next is the undecorated method with a computed key. This uses the previously +calculated and stored computed key. + +```js + #y = initC(this, 123); + get y() { + return this.#y; + } + set y(v) { + this.#y = v; + } + get #c() { + return getC(this); + } + set #c(v) { + setC(this, v); + } +``` + +Next up, we have the output for `accessor #c`. This is the most complicated +case, since we have to transpile the decorators, the `accessor` keyword, and +target a private field. Breaking it down piece by piece: + +```js + #y = initC(this, 123); +``` + +`accessor #c` desugars to a getter and setter which are backed by a new private +field, `#y`. Like before, the name of this field doesn't really matter, we'll +just generate a short, unique name. We call the decorated initializer for `#c` +and return that value to assign to the field. + +```js + get y() { + return this.#y; + } + set y(v) { + this.#y = v; + } +``` + +Next we have a getter and setter named `y` which provide access to the backing +storage for the accessor. These are the base getter/setter for the accessor, +which the decorator will get via `Object.getOwnPropertyDescriptor`. They will be +deleted from the class fully, so again the name is not important here, just +needs to be short. + +```js + get #c() { + return getC(this); + } + set #c(v) { + setC(this, v); + } +``` + +Next, we have the getter and setter for `#c` itself. These methods defer to +the `getC` and `setC` local variables, which will be the decorated versions of +the `get y` and `set y` methods from the previous step. + +```js + static { + initClass(C); + } +``` + +Finally, we call `initClass` in another static block, running any class and +static method initializers on the final class. This is done in a static block +for convenience with class expressions, but it could run immediately after the +class is defined. + +Ok, so now that we understand the general output, let's go back to `applyDecs`: + +```js +const elementDecs = [ + [dec, 0, 'a'], + [dec, 7, 'x', '#b'] + (computedKey = someVal, null) + [[dec, dec2], 1, 'y', '#c'] +]; + +const classDecs = [dec]; + +// ... + +let ret = applyDecs( + this, + elementDecs, + classDecs +); +``` + +`applyDecs` takes all of the decorators for the class and applies them. It +receives the following arguments: + +1. The class itself +2. Decorators to apply to class elements +3. Decorators to apply to the class itself + +The format of the data is designed to be as minimal as possible. Here's an +annotated version of the member descriptors: + +```js +[ + // List of decorators to apply to the field. Array if multiple decorators, + // otherwise just the single decorator itself. + dec, + + // The type of the decorator, represented as an enum. Static-ness is also + // encoded by adding 5 to the values + // 0 === FIELD + // 1 === ACCESSOR + // 2 === METHOD + // 3 === GETTER + // 4 === SETTER + // 5 === FIELD + STATIC + // 6 === ACCESSOR + STATIC + // 7 === METHOD + STATIC + // 8 === GETTER + STATIC + // 9 === SETTER + STATIC + 1, + + // The name of the public property that can be used to access the value. + // For public members this is the actual name, for private members this is + // the name of the public property which can be used to access the value + // (see descriptions of #b and #c above) + 'y', + + // Optional fourth value, this is the spelling of the private element's name, + // which signals that the element is private to `applyDecs` and is used in the + // decorator's context object + '#c' +], +``` + +Static and prototype decorators are all described like this. For class +decorators, it's just the list of decorators since no other context +is necessary. diff --git a/packages/babel-plugin-proposal-decorators/src/index.ts b/packages/babel-plugin-proposal-decorators/src/index.ts index a7e142769038..ddf98ea99e76 100644 --- a/packages/babel-plugin-proposal-decorators/src/index.ts +++ b/packages/babel-plugin-proposal-decorators/src/index.ts @@ -7,6 +7,7 @@ import { FEATURES, } from "@babel/helper-create-class-features-plugin"; import legacyVisitor from "./transformer-legacy"; +import transformer2021_12 from "./transformer-2021-12"; export default declare((api, options) => { api.assertVersion(7); @@ -16,7 +17,7 @@ export default declare((api, options) => { throw new Error("'legacy' must be a boolean."); } - const { decoratorsBeforeExport } = options; + const { decoratorsBeforeExport, version } = options; if (decoratorsBeforeExport === undefined) { if (!legacy) { throw new Error( @@ -37,6 +38,10 @@ export default declare((api, options) => { } if (legacy) { + if (version !== undefined) { + throw new Error("'version' can't be used with legacy decorators"); + } + return { name: "proposal-decorators", inherits: syntaxDecorators, @@ -47,6 +52,12 @@ export default declare((api, options) => { }; } + if (version === "2021-12") { + return transformer2021_12(api, options); + } else if (!(version === "2018-09" || version === undefined)) { + throw new Error("Unsupported decorators version: " + version); + } + return createClassFeaturePlugin({ name: "proposal-decorators", diff --git a/packages/babel-plugin-proposal-decorators/src/transformer-2021-12.ts b/packages/babel-plugin-proposal-decorators/src/transformer-2021-12.ts new file mode 100644 index 000000000000..f05391ef28ac --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/src/transformer-2021-12.ts @@ -0,0 +1,919 @@ +import type { NodePath } from "@babel/traverse"; +import { types as t } from "@babel/core"; +import syntaxDecorators from "@babel/plugin-syntax-decorators"; + +type ClassDecoratableElement = + | t.ClassMethod + | t.ClassPrivateMethod + | t.ClassProperty + | t.ClassPrivateProperty + | t.ClassAccessorProperty; + +type ClassElement = + | ClassDecoratableElement + | t.TSDeclareMethod + | t.TSIndexSignature + | t.StaticBlock; + +type classUidGenerator = ( + isPrivate: B, +) => B extends true ? t.PrivateName : t.Identifier; + +function incrementId(id: number[], idx = id.length - 1): void { + // If index is -1, id needs an additional character, unshift A + if (idx === -1) { + id.unshift(65); + return; + } + + const current = id[idx]; + + if (current === 90) { + // if current is Z, skip to a + id[idx] = 97; + } else if (current === 122) { + // if current is z, reset to A and carry the 1 + id[idx] = 65; + incrementId(id, idx - 1); + } else { + // else, increment by one + id[idx] = current + 1; + } +} + +/** + * Generates a new element name that is unique to the given class. This can be + * used to create extra class fields and methods for the implementation, while + * keeping the length of those names as small as possible. This is important for + * minification purposes, since public names cannot be safely renamed/minified. + * + * Names are split into two namespaces, public and private. Static and non-static + * names are shared in the same namespace, because this is true for private names + * (you cannot have #x and static #x in the same class) and it's not worth the + * extra complexity for public names. + */ +function createUidGeneratorForClass( + body: NodePath[], +): (isPrivate: boolean) => t.Identifier | t.PrivateName { + let currentPublicId: number[], currentPrivateId: number[]; + + const publicNames = new Set(); + const privateNames = new Set(); + + for (const element of body) { + if ( + element.node.type === "TSIndexSignature" || + element.node.type === "StaticBlock" + ) { + continue; + } + + const { key } = element.node; + + if (key.type === "PrivateName") { + privateNames.add(key.id.name); + } else if (key.type === "Identifier") { + publicNames.add(key.name); + } + } + + return (isPrivate: boolean): t.Identifier | t.PrivateName => { + let currentId: number[], names: Set; + + if (isPrivate) { + if (!currentPrivateId) { + currentPrivateId = [65]; + } + + currentId = currentPrivateId; + names = privateNames; + } else { + if (!currentPublicId) { + currentPublicId = [65]; + } + + currentId = currentPublicId; + names = publicNames; + } + + let reifiedId = String.fromCharCode(...currentId); + + while (names.has(reifiedId)) { + incrementId(currentId); + reifiedId = String.fromCharCode(...currentId); + } + + incrementId(currentId); + + if (isPrivate) { + return t.privateName(t.identifier(reifiedId)); + } else { + return t.identifier(reifiedId); + } + }; +} + +/** + * Wraps the above generator function so that it's run lazily the first time + * it's actually required. Several types of decoration do not require this, so it + * saves iterating the class elements an additional time and allocating the space + * for the Sets of element names. + */ +function createLazyUidGeneratorForClass( + body: NodePath[], +): classUidGenerator { + let generator: (isPrivate: boolean) => t.Identifier | t.PrivateName; + + const lazyGenerator = (isPrivate: boolean): t.Identifier | t.PrivateName => { + if (!generator) { + generator = createUidGeneratorForClass(body); + } + + return generator(isPrivate); + }; + + return lazyGenerator as unknown as classUidGenerator; +} + +/** + * Takes a class definition and replaces it with an equivalent class declaration + * which is then assigned to a local variable. This allows us to reassign the + * local variable with the decorated version of the class. The class definition + * retains its original name so that `toString` is not affected, other + * references to the class are renamed instead. + */ +function replaceClassWithVar( + path: NodePath, +): [t.Identifier, NodePath] { + if (path.type === "ClassDeclaration") { + const varId = path.scope.generateUidIdentifierBasedOnNode(path.node.id); + const classId = t.identifier(path.node.id.name); + + path.scope.rename(classId.name, varId.name); + + path.insertBefore( + t.variableDeclaration("let", [t.variableDeclarator(varId)]), + ); + path.get("id").replaceWith(classId); + + return [t.cloneNode(varId), path]; + } else { + let className: string; + let varId: t.Identifier; + + if (path.node.id) { + className = path.node.id.name; + varId = generateLocalVarId(path, className); + path.scope.rename(className, varId.name); + } else if ( + path.parentPath.node.type === "VariableDeclarator" && + path.parentPath.node.id.type === "Identifier" + ) { + className = path.parentPath.node.id.name; + varId = generateLocalVarId(path, className); + } else { + varId = generateLocalVarId(path, "decorated_class"); + } + + const newClassExpr = t.classExpression( + className && t.identifier(className), + path.node.superClass, + path.node.body, + ); + + const [newPath] = path.replaceWith( + t.sequenceExpression([newClassExpr, varId]), + ); + + return [t.cloneNode(varId), newPath.get("expressions.0")]; + } +} + +function generateClassProperty( + key: t.PrivateName | t.Identifier, + value: t.Expression | undefined, + isStatic: boolean, +): t.ClassPrivateProperty | t.ClassProperty { + if (key.type === "PrivateName") { + return t.classPrivateProperty(key, value, undefined, isStatic); + } else { + return t.classProperty(key, value, undefined, undefined, isStatic); + } +} + +function addProxyAccessorsFor( + element: NodePath, + originalKey: t.PrivateName | t.Expression, + targetKey: t.PrivateName, + isComputed = false, +): void { + const { static: isStatic } = element.node; + + const getterBody = t.blockStatement([ + t.returnStatement( + t.memberExpression(t.thisExpression(), t.cloneNode(targetKey)), + ), + ]); + + const setterBody = t.blockStatement([ + t.expressionStatement( + t.assignmentExpression( + "=", + t.memberExpression(t.thisExpression(), t.cloneNode(targetKey)), + t.identifier("v"), + ), + ), + ]); + + let getter: t.ClassMethod | t.ClassPrivateMethod, + setter: t.ClassMethod | t.ClassPrivateMethod; + + if (originalKey.type === "PrivateName") { + getter = t.classPrivateMethod( + "get", + t.cloneNode(originalKey), + [], + getterBody, + isStatic, + ); + setter = t.classPrivateMethod( + "set", + t.cloneNode(originalKey), + [t.identifier("v")], + setterBody, + isStatic, + ); + } else { + getter = t.classMethod( + "get", + t.cloneNode(originalKey), + [], + getterBody, + isComputed, + isStatic, + ); + setter = t.classMethod( + "set", + t.cloneNode(originalKey), + [t.identifier("v")], + setterBody, + isComputed, + isStatic, + ); + } + + element.insertAfter(setter); + element.insertAfter(getter); +} + +function extractProxyAccessorsFor( + targetKey: t.PrivateName, +): t.FunctionExpression[] { + return [ + t.functionExpression( + undefined, + [], + t.blockStatement([ + t.returnStatement( + t.memberExpression(t.thisExpression(), t.cloneNode(targetKey)), + ), + ]), + ), + t.functionExpression( + undefined, + [t.identifier("value")], + t.blockStatement([ + t.expressionStatement( + t.assignmentExpression( + "=", + t.memberExpression(t.thisExpression(), t.cloneNode(targetKey)), + t.identifier("value"), + ), + ), + ]), + ), + ]; +} + +const FIELD = 0; +const ACCESSOR = 1; +const METHOD = 2; +const GETTER = 3; +const SETTER = 4; + +const STATIC = 5; + +function getElementKind(element: NodePath): number { + switch (element.node.type) { + case "ClassProperty": + case "ClassPrivateProperty": + return FIELD; + case "ClassAccessorProperty": + return ACCESSOR; + case "ClassMethod": + case "ClassPrivateMethod": + if (element.node.kind === "get") { + return GETTER; + } else if (element.node.kind === "set") { + return SETTER; + } else { + return METHOD; + } + } +} + +function generateLocalVarId(path: NodePath, name: string): t.Identifier { + const varId = path.scope.generateUidIdentifier(name); + path.scope.parent.push({ id: varId }); + return t.cloneNode(varId); +} + +// Information about the decorators applied to an element +interface DecoratorInfo { + // The expressions of the decorators themselves + decorators: t.Expression[]; + + // The kind of the decorated value, matches the kind value passed to applyDecs + kind: number; + + // whether or not the field is static + isStatic: boolean; + + // The name of the decorator + name: t.StringLiteral | t.Expression; + + privateMethods: t.FunctionExpression | t.FunctionExpression[] | undefined; + + // The names of local variables that will be used/returned from the decoration + locals: t.Identifier | t.Identifier[] | undefined; +} + +// Information about a computed property key. These must be evaluated +// interspersed with decorator expressions, which is why they get added to the +// array of DecoratorInfos later on. +interface ComputedPropInfo { + localComputedNameId: t.Identifier; + keyNode: t.Expression; +} + +function isDecoratorInfo( + info: DecoratorInfo | ComputedPropInfo, +): info is DecoratorInfo { + return "decorators" in info; +} + +function generateDecorationExprs( + info: (DecoratorInfo | ComputedPropInfo)[], +): t.ArrayExpression { + return t.arrayExpression( + info.filter(isDecoratorInfo).map(el => { + const decs = + el.decorators.length > 1 + ? t.arrayExpression(el.decorators) + : el.decorators[0]; + + const kind = el.isStatic ? el.kind + STATIC : el.kind; + + const decInfo = [decs, t.numericLiteral(kind), el.name]; + + const { privateMethods } = el; + + if (Array.isArray(privateMethods)) { + decInfo.push(...privateMethods); + } else if (privateMethods) { + decInfo.push(privateMethods); + } + + return t.arrayExpression(decInfo); + }), + ); +} + +function extractElementLocalAssignments( + decorationInfo: (DecoratorInfo | ComputedPropInfo)[], +) { + const locals: t.Identifier[] = []; + + for (const el of decorationInfo) { + if ("locals" in el && el.locals) { + if (Array.isArray(el.locals)) { + locals.push(...el.locals); + } else { + locals.push(el.locals); + } + } + } + + return locals; +} + +function addCallAccessorsFor( + element: NodePath, + key: t.PrivateName, + getId: t.Identifier, + setId: t.Identifier, +) { + element.insertAfter( + t.classPrivateMethod( + "get", + t.cloneNode(key), + [], + t.blockStatement([ + t.expressionStatement( + t.callExpression(t.cloneNode(getId), [t.thisExpression()]), + ), + ]), + ), + ); + + element.insertAfter( + t.classPrivateMethod( + "set", + t.cloneNode(key), + [t.identifier("v")], + t.blockStatement([ + t.expressionStatement( + t.callExpression(t.cloneNode(setId), [ + t.thisExpression(), + t.identifier("v"), + ]), + ), + ]), + ), + ); +} + +function isNotTsParameter( + node: t.Identifier | t.Pattern | t.RestElement | t.TSParameterProperty, +): node is t.Identifier | t.Pattern | t.RestElement { + return node.type !== "TSParameterProperty"; +} + +function movePrivateMethod( + element: NodePath, + key: t.PrivateName, + methodLocalVar: t.Identifier, + isStatic: boolean, +) { + let params: (t.Identifier | t.RestElement)[]; + let block: t.Statement[]; + + const methodExpression = t.functionExpression( + undefined, + element.node.params.filter(isNotTsParameter), + element.node.body, + element.node.async, + ); + + if (element.node.kind === "method") { + params = [t.restElement(t.identifier("args"))]; + block = [ + t.returnStatement( + t.callExpression(methodLocalVar, [ + t.thisExpression(), + t.spreadElement(t.identifier("args")), + ]), + ), + ]; + } else if (element.node.kind === "set") { + params = [t.identifier("v")]; + block = [ + t.expressionStatement( + t.callExpression(methodLocalVar, [ + t.thisExpression(), + t.identifier("v"), + ]), + ), + ]; + } else { + params = []; + block = [ + t.returnStatement(t.callExpression(methodLocalVar, [t.thisExpression()])), + ]; + } + + element.replaceWith( + t.classPrivateMethod( + element.node.kind, + t.cloneNode(key), + params, + t.blockStatement(block), + isStatic, + ), + ); + + return methodExpression; +} + +function isClassDecoratableElementPath( + path: NodePath, +): path is NodePath { + const { type } = path; + + return ( + type !== "TSDeclareMethod" && + type !== "TSIndexSignature" && + type !== "StaticBlock" + ); +} + +function transformClass( + path: NodePath, + state: any, +): NodePath { + const body = path.get("body.body"); + + const classDecorators = path.node.decorators; + let hasElementDecorators = false; + + const generateClassUid = createLazyUidGeneratorForClass(body); + + // Iterate over the class to see if we need to decorate it, and also to + // transform simple auto accessors which are not decorated + for (const element of body) { + if (!isClassDecoratableElementPath(element)) { + continue; + } + + if (element.node.decorators) { + hasElementDecorators = true; + } else if (element.node.type === "ClassAccessorProperty") { + const { key, value, static: isStatic } = element.node; + + const newId = generateClassUid(true); + + const valueNode = value ? t.cloneNode(value) : undefined; + + const newField = generateClassProperty(newId, valueNode, isStatic); + + const [newPath] = element.replaceWith(newField); + addProxyAccessorsFor(newPath, key, newId, element.node.computed); + } + } + + // If nothing is decorated, return + if (!classDecorators && !hasElementDecorators) return; + + const elementDecoratorInfo: (DecoratorInfo | ComputedPropInfo)[] = []; + + let firstFieldPath: + | NodePath + | undefined; + let constructorPath: NodePath | undefined; + let requiresProtoInit = false; + let requiresStaticInit = false; + let hasComputedProps = false; + + if (hasElementDecorators) { + for (const element of body) { + if (!isClassDecoratableElementPath(element)) { + continue; + } + + let { key } = element.node; + const kind = getElementKind(element); + const decorators = element.get("decorators"); + + const isPrivate = key.type === "PrivateName"; + const isComputed = + "computed" in element.node && element.node.computed === true; + const isStatic = !!element.node.static; + + let name = "computedKey"; + + if (isPrivate) { + name = (key as t.PrivateName).id.name; + } else if (key.type === "Identifier") { + name = key.name; + } + + if ( + element.node.type === "ClassMethod" && + element.node.kind === "constructor" + ) { + constructorPath = element as NodePath; + } + + if (isComputed) { + const keyPath = element.get("key"); + const localComputedNameId = generateLocalVarId(keyPath, name); + keyPath.replaceWith(localComputedNameId); + + elementDecoratorInfo.push({ + localComputedNameId: t.cloneNode(localComputedNameId), + keyNode: t.cloneNode(key as t.Expression), + }); + + key = localComputedNameId; + hasComputedProps = true; + } + + if (Array.isArray(decorators)) { + let locals: t.Identifier | t.Identifier[]; + let privateMethods: t.FunctionExpression | t.FunctionExpression[]; + + if (kind === ACCESSOR) { + const { value } = element.node as t.ClassAccessorProperty; + + const params: t.Expression[] = [t.thisExpression()]; + + if (value) { + params.push(t.cloneNode(value)); + } + + const newId = generateClassUid(true); + const newFieldInitId = generateLocalVarId(element, `init_${name}`); + const newValue = t.callExpression( + t.cloneNode(newFieldInitId), + params, + ); + + const newField = generateClassProperty(newId, newValue, isStatic); + const [newPath] = element.replaceWith(newField); + + if (isPrivate) { + privateMethods = extractProxyAccessorsFor(newId); + + const getId = generateLocalVarId(newPath, `get_${name}`); + const setId = generateLocalVarId(newPath, `set_${name}`); + + addCallAccessorsFor(newPath, key as t.PrivateName, getId, setId); + + locals = [newFieldInitId, getId, setId]; + } else { + addProxyAccessorsFor(newPath, key, newId, isComputed); + locals = newFieldInitId; + } + } else if (kind === FIELD) { + const initId = generateLocalVarId(element, `init_${name}`); + const valuePath = ( + element as NodePath + ).get("value"); + + valuePath.replaceWith( + t.callExpression( + t.cloneNode(initId), + [t.thisExpression(), valuePath.node].filter(v => v), + ), + ); + + locals = initId; + + if (isPrivate) { + privateMethods = extractProxyAccessorsFor(key as t.PrivateName); + } + } else if (isPrivate) { + const methodLocalVar = generateLocalVarId(element, `call_${name}`); + + privateMethods = movePrivateMethod( + element as NodePath, + t.cloneNode(key as t.PrivateName), + t.cloneNode(methodLocalVar), + isStatic, + ); + + locals = methodLocalVar; + } + + let nameExpr: t.Expression; + + if (isComputed) { + nameExpr = t.cloneNode(key as t.Expression); + } else if (key.type === "PrivateName") { + nameExpr = t.stringLiteral(key.id.name); + } else if (key.type === "Identifier") { + nameExpr = t.stringLiteral(key.name); + } + + elementDecoratorInfo.push({ + kind, + decorators: decorators.map(d => d.node.expression), + name: nameExpr, + isStatic, + privateMethods, + locals, + }); + + if (kind !== FIELD) { + if (isStatic) { + requiresStaticInit = true; + } else { + requiresProtoInit = true; + } + } + + element.node.decorators = null; + + if (!firstFieldPath && (kind === FIELD || kind === ACCESSOR)) { + firstFieldPath = element as NodePath< + t.ClassProperty | t.ClassPrivateProperty + >; + } + } + } + } + + if (hasComputedProps) { + const assignments: t.AssignmentExpression[] = []; + + for (const info of elementDecoratorInfo) { + if (isDecoratorInfo(info)) { + const { decorators } = info; + const newDecorators: t.Identifier[] = []; + + for (const decorator of decorators) { + const localComputedNameId = generateLocalVarId(path, "dec"); + assignments.push( + t.assignmentExpression("=", localComputedNameId, decorator), + ); + newDecorators.push(t.cloneNode(localComputedNameId)); + } + + info.decorators = newDecorators; + } else { + assignments.push( + t.assignmentExpression("=", info.localComputedNameId, info.keyNode), + ); + } + } + + path.insertBefore(assignments); + } + + const elementDecorations = generateDecorationExprs(elementDecoratorInfo); + const classDecorations = t.arrayExpression( + (classDecorators || []).map(d => d.expression), + ); + + const locals: t.Identifier[] = + extractElementLocalAssignments(elementDecoratorInfo); + let protoInitLocal: t.Identifier, + staticInitLocal: t.Identifier, + classInitLocal: t.Identifier; + + if (requiresProtoInit) { + protoInitLocal = generateLocalVarId(path, "initProto"); + locals.push(protoInitLocal); + + const protoInitCall = t.callExpression(t.cloneNode(protoInitLocal), [ + t.thisExpression(), + ]); + + if (firstFieldPath) { + const value = firstFieldPath.get("value"); + const body: t.Expression[] = [protoInitCall]; + + if (value.node) { + body.push(value.node); + } + + value.replaceWith(t.sequenceExpression(body)); + } else if (constructorPath) { + if (path.node.superClass) { + const superPath = constructorPath + .get("body.body") + .find( + path => + path.node.type === "ExpressionStatement" && + path.node.expression.type === "CallExpression" && + path.node.expression.callee.type === "Super", + ); + + if (!superPath) { + throw new Error( + `No super found inside class constructor for ${ + path.node.id ? path.node.id.name : "an anonymous class" + }, but the class extends from another class`, + ); + } + + superPath.insertAfter(t.expressionStatement(protoInitCall)); + } else { + constructorPath.node.body.body.unshift( + t.expressionStatement(protoInitCall), + ); + } + } else { + const body: t.Statement[] = [t.expressionStatement(protoInitCall)]; + + if (path.node.superClass) { + body.unshift( + t.expressionStatement( + t.callExpression(t.super(), [ + t.spreadElement(t.identifier("args")), + ]), + ), + ); + } + + path.node.body.body.unshift( + t.classMethod( + "constructor", + t.identifier("constructor"), + [t.restElement(t.identifier("args"))], + t.blockStatement(body), + ), + ); + } + } + + if (requiresStaticInit) { + staticInitLocal = generateLocalVarId(path, "initStatic"); + locals.push(staticInitLocal); + } + + if (classDecorators) { + classInitLocal = generateLocalVarId(path, "initClass"); + + const [localId, classPath] = replaceClassWithVar(path); + path = classPath; + + locals.push(localId, classInitLocal); + path.node.decorators = null; + } + + const staticBlock = t.staticBlock( + [ + t.variableDeclaration("let", [ + t.variableDeclarator( + t.identifier("ret"), + t.callExpression(state.addHelper("applyDecs"), [ + t.thisExpression(), + elementDecorations, + classDecorations, + ]), + ), + ]), + ...locals.map((local, idx) => { + return t.expressionStatement( + t.assignmentExpression( + "=", + local, + t.memberExpression( + t.identifier("ret"), + t.numericLiteral(idx), + true, + ), + ), + ); + }), + requiresStaticInit && + t.expressionStatement( + t.callExpression(t.cloneNode(staticInitLocal), [t.thisExpression()]), + ), + ].filter(v => v), + ); + + path.node.body.body.unshift(staticBlock as unknown as ClassElement); + + if (classInitLocal) { + path.node.body.body.push( + t.staticBlock([ + t.expressionStatement( + t.callExpression(t.cloneNode(classInitLocal), []), + ), + ]), + ); + } + + // Recrawl the scope to make sure new identifiers are properly synced + path.scope.crawl(); + + return path; +} + +export default function ({ assertVersion }, { decoratorsBeforeExport }) { + assertVersion("^7.16.0"); + + const VISITED = new WeakSet(); + + return { + name: "proposal-decorators", + inherits: syntaxDecorators, + manipulateOptions({ generatorOpts }) { + generatorOpts.decoratorsBeforeExport = decoratorsBeforeExport; + }, + + visitor: { + ClassDeclaration(path: NodePath, state: any) { + if (VISITED.has(path)) return; + + const newPath = transformClass(path, state); + + if (newPath) { + VISITED.add(newPath); + } + }, + + ClassExpression(path: NodePath, state: any) { + if (VISITED.has(path)) return; + + const newPath = transformClass(path, state); + + if (newPath) { + VISITED.add(newPath); + } + }, + }, + }; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/private/exec.js new file mode 100644 index 000000000000..d3161fa6ab3d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/private/exec.js @@ -0,0 +1,54 @@ +function dec({ get, set }, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return { + get() { + return get.call(this) + 1; + }, + + set(v) { + set.call(this, v + 1); + }, + + initializer(v) { + return v ? v : 1; + } + } +} + +class Foo { + @dec + accessor #a; + + @dec + accessor #b = 123; +} + +let foo = new Foo(); + +const aContext = foo['#aContext']; +const bContext = foo['#bContext']; + +expect(aContext.access.get.call(foo)).toBe(2); +aContext.access.set.call(foo, 123); +expect(aContext.access.get.call(foo)).toBe(125); +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('accessor'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.access.get.call(foo)).toBe(124); +bContext.access.set.call(foo, 123); +expect(bContext.access.get.call(foo)).toBe(125); +expect(bContext.name).toBe('#b'); +expect(bContext.kind).toBe('accessor'); +expect(bContext.isStatic).toBe(false); +expect(bContext.isPrivate).toBe(true); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/private/input.js new file mode 100644 index 000000000000..be4f348923bc --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/private/input.js @@ -0,0 +1,7 @@ +class Foo { + @dec + accessor #a; + + @dec + accessor #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/private/output.js new file mode 100644 index 000000000000..24483d69c6f6 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/private/output.js @@ -0,0 +1,66 @@ +var _init_a, _get_a, _set_a, _init_b, _get_b, _set_b, _initProto; + +var _A = /*#__PURE__*/new WeakMap(); + +var _a = /*#__PURE__*/new WeakMap(); + +var _B = /*#__PURE__*/new WeakMap(); + +var _b = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor() { + babelHelpers.classPrivateFieldInitSpec(this, _b, { + get: _get_b2, + set: _set_b2 + }); + babelHelpers.classPrivateFieldInitSpec(this, _a, { + get: _get_a2, + set: _set_a2 + }); + babelHelpers.classPrivateFieldInitSpec(this, _A, { + writable: true, + value: (_initProto(this), _init_a(this)) + }); + babelHelpers.classPrivateFieldInitSpec(this, _B, { + writable: true, + value: _init_b(this, 123) + }); + } + +} + +function _set_a2(v) { + _set_a(this, v); +} + +function _get_a2() { + _get_a(this); +} + +function _set_b2(v) { + _set_b(this, v); +} + +function _get_b2() { + _get_b(this); +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 1, "a", function () { + return babelHelpers.classPrivateFieldGet(this, _A); + }, function (value) { + babelHelpers.classPrivateFieldSet(this, _A, value); + }], [dec, 1, "b", function () { + return babelHelpers.classPrivateFieldGet(this, _B); + }, function (value) { + babelHelpers.classPrivateFieldSet(this, _B, value); + }]], []); + _init_a = ret[0]; + _get_a = ret[1]; + _set_a = ret[2]; + _init_b = ret[3]; + _get_b = ret[4]; + _set_b = ret[5]; + _initProto = ret[6]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/public/exec.js new file mode 100644 index 000000000000..7951130866a2 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/public/exec.js @@ -0,0 +1,75 @@ +function dec({ get, set }, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return { + get() { + return get.call(this) + 1; + }, + + set(v) { + set.call(this, v + 1); + }, + + initializer(v) { + return v ? v : 1; + } + } +} + +class Foo { + @dec + accessor a; + + @dec + accessor b = 123; + + @dec + accessor ['c'] = 456; +} + +let foo = new Foo(); + +const aContext = foo['aContext']; +const bContext = foo['bContext']; +const cContext = foo['cContext']; + +expect(foo.a).toBe(2); +foo.a = 123; +expect(foo.a).toBe(125); +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('accessor'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); +expect(foo.hasOwnProperty('a')).toBe(false); +expect(Foo.prototype.hasOwnProperty('a')).toBe(true); + +expect(foo.b).toBe(124); +foo.b = 123; +expect(foo.b).toBe(125); +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('accessor'); +expect(bContext.isStatic).toBe(false); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); +expect(foo.hasOwnProperty('b')).toBe(false); +expect(Foo.prototype.hasOwnProperty('b')).toBe(true); + +expect(foo.c).toBe(457); +foo.c = 456; +expect(foo.c).toBe(458); +expect(cContext.name).toBe('c'); +expect(cContext.kind).toBe('accessor'); +expect(cContext.isStatic).toBe(false); +expect(cContext.isPrivate).toBe(false); +expect(typeof cContext.addInitializer).toBe('function'); +expect(typeof cContext.setMetadata).toBe('function'); +expect(typeof cContext.getMetadata).toBe('function'); +expect(foo.hasOwnProperty('c')).toBe(false); +expect(Foo.prototype.hasOwnProperty('c')).toBe(true); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/public/input.js new file mode 100644 index 000000000000..5945d3196f1d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/public/input.js @@ -0,0 +1,10 @@ +class Foo { + @dec + accessor a; + + @dec + accessor b = 123; + + @dec + accessor ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/public/output.js new file mode 100644 index 000000000000..0f5860f1f22a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/public/output.js @@ -0,0 +1,62 @@ +var _init_a, _init_b, _computedKey, _init_computedKey, _dec, _dec2, _dec3, _initProto; + +_dec = dec +_dec2 = dec +_computedKey = 'c' +_dec3 = dec + +var _A = /*#__PURE__*/new WeakMap(); + +var _B = /*#__PURE__*/new WeakMap(); + +var _C = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor() { + babelHelpers.classPrivateFieldInitSpec(this, _A, { + writable: true, + value: (_initProto(this), _init_a(this)) + }); + babelHelpers.classPrivateFieldInitSpec(this, _B, { + writable: true, + value: _init_b(this, 123) + }); + babelHelpers.classPrivateFieldInitSpec(this, _C, { + writable: true, + value: _init_computedKey(this, 456) + }); + } + + get a() { + return babelHelpers.classPrivateFieldGet(this, _A); + } + + set a(v) { + babelHelpers.classPrivateFieldSet(this, _A, v); + } + + get b() { + return babelHelpers.classPrivateFieldGet(this, _B); + } + + set b(v) { + babelHelpers.classPrivateFieldSet(this, _B, v); + } + + get [_computedKey]() { + return babelHelpers.classPrivateFieldGet(this, _C); + } + + set [_computedKey](v) { + babelHelpers.classPrivateFieldSet(this, _C, v); + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 1, "a"], [_dec2, 1, "b"], [_dec3, 1, _computedKey]], []); + _init_a = ret[0]; + _init_b = ret[1]; + _init_computedKey = ret[2]; + _initProto = ret[3]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-private/exec.js new file mode 100644 index 000000000000..06946cc2f26d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-private/exec.js @@ -0,0 +1,52 @@ +function dec({ get, set }, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return { + get() { + return get.call(this) + 1; + }, + + set(v) { + set.call(this, v + 1); + }, + + initializer(v) { + return v ? v : 1; + } + } +} + +class Foo { + @dec + static accessor #a; + + @dec + static accessor #b = 123; +} + +const aContext = Foo['#aContext']; +const bContext = Foo['#bContext']; + +expect(aContext.access.get.call(Foo)).toBe(2); +aContext.access.set.call(Foo, 123); +expect(aContext.access.get.call(Foo)).toBe(125); +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('accessor'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.access.get.call(Foo)).toBe(124); +bContext.access.set.call(Foo, 123); +expect(bContext.access.get.call(Foo)).toBe(125); +expect(bContext.name).toBe('#b'); +expect(bContext.kind).toBe('accessor'); +expect(bContext.isStatic).toBe(true); +expect(bContext.isPrivate).toBe(true); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-private/input.js new file mode 100644 index 000000000000..ebb88a741572 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-private/input.js @@ -0,0 +1,7 @@ +class Foo { + @dec + static accessor #a; + + @dec + static accessor #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-private/output.js new file mode 100644 index 000000000000..0c7dc01a1ff7 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-private/output.js @@ -0,0 +1,65 @@ +var _init_a, _get_a, _set_a, _init_b, _get_b, _set_b, _initStatic; + +var _a = /*#__PURE__*/new WeakMap(); + +var _b = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor() { + babelHelpers.classPrivateFieldInitSpec(this, _b, { + get: _get_b2, + set: _set_b2 + }); + babelHelpers.classPrivateFieldInitSpec(this, _a, { + get: _get_a2, + set: _set_a2 + }); + } + +} + +function _set_a2(v) { + _set_a(this, v); +} + +function _get_a2() { + _get_a(this); +} + +function _set_b2(v) { + _set_b(this, v); +} + +function _get_b2() { + _get_b(this); +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 6, "a", function () { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _A); + }, function (value) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _A, value); + }], [dec, 6, "b", function () { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _B); + }, function (value) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _B, value); + }]], []); + _init_a = ret[0]; + _get_a = ret[1]; + _set_a = ret[2]; + _init_b = ret[3]; + _get_b = ret[4]; + _set_b = ret[5]; + _initStatic = ret[6]; + + _initStatic(Foo); +})(); + +var _A = { + writable: true, + value: _init_a(Foo) +}; +var _B = { + writable: true, + value: _init_b(Foo, 123) +}; diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-public/exec.js new file mode 100644 index 000000000000..21973ce25629 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-public/exec.js @@ -0,0 +1,70 @@ +function dec({ get, set }, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return { + get() { + return get.call(this) + 1; + }, + + set(v) { + set.call(this, v + 1); + }, + + initializer(v) { + return v ? v : 1; + } + } +} + +class Foo { + @dec + static accessor a; + + @dec + static accessor b = 123; + + @dec + static accessor ['c'] = 456; +} + +const aContext = Foo['aContext']; +const bContext = Foo['bContext']; +const cContext = Foo['cContext']; + +expect(Foo.a).toBe(2); +Foo.a = 123; +expect(Foo.a).toBe(125); +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('accessor'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); +expect(Foo.hasOwnProperty('a')).toBe(true); + +expect(Foo.b).toBe(124); +Foo.b = 123; +expect(Foo.b).toBe(125); +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('accessor'); +expect(bContext.isStatic).toBe(true); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); +expect(Foo.hasOwnProperty('b')).toBe(true); + +expect(Foo.c).toBe(457); +Foo.c = 456; +expect(Foo.c).toBe(458); +expect(cContext.name).toBe('c'); +expect(cContext.kind).toBe('accessor'); +expect(cContext.isStatic).toBe(true); +expect(cContext.isPrivate).toBe(false); +expect(typeof cContext.addInitializer).toBe('function'); +expect(typeof cContext.setMetadata).toBe('function'); +expect(typeof cContext.getMetadata).toBe('function'); +expect(Foo.hasOwnProperty('c')).toBe(true); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-public/input.js new file mode 100644 index 000000000000..edf06478601f --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-public/input.js @@ -0,0 +1,10 @@ +class Foo { + @dec + static accessor a; + + @dec + static accessor b = 123; + + @dec + static accessor ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-public/output.js new file mode 100644 index 000000000000..3a06d2421c32 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/static-public/output.js @@ -0,0 +1,56 @@ +var _init_a, _init_b, _computedKey, _init_computedKey, _dec, _dec2, _dec3, _initStatic; + +_dec = dec +_dec2 = dec +_computedKey = 'c' +_dec3 = dec + +class Foo { + static get a() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _A); + } + + static set a(v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _A, v); + } + + static get b() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _B); + } + + static set b(v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _B, v); + } + + static get [_computedKey]() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _C); + } + + static set [_computedKey](v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _C, v); + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 6, "a"], [_dec2, 6, "b"], [_dec3, 6, _computedKey]], []); + _init_a = ret[0]; + _init_b = ret[1]; + _init_computedKey = ret[2]; + _initStatic = ret[3]; + + _initStatic(Foo); +})(); + +var _A = { + writable: true, + value: _init_a(Foo) +}; +var _B = { + writable: true, + value: _init_b(Foo, 123) +}; +var _C = { + writable: true, + value: _init_computedKey(Foo, 456) +}; diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-private/exec.js new file mode 100644 index 000000000000..51715be9f173 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-private/exec.js @@ -0,0 +1,31 @@ +class Foo { + accessor #a; + + accessor #b = 123; + + getA() { + return this.#a; + } + + setA(v) { + this.#a = v; + } + + getB() { + return this.#b; + } + + setB(v) { + this.#b = v; + } +} + +let foo = new Foo(); + +expect(foo.getA()).toBe(undefined); +foo.setA(123) +expect(foo.getA()).toBe(123); + +expect(foo.getB()).toBe(123); +foo.setB(456) +expect(foo.getB()).toBe(456); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-private/input.js new file mode 100644 index 000000000000..4afc45261337 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-private/input.js @@ -0,0 +1,5 @@ +class Foo { + accessor #a; + + accessor #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-private/output.js new file mode 100644 index 000000000000..29d3fbd66965 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-private/output.js @@ -0,0 +1,45 @@ +var _A = /*#__PURE__*/new WeakMap(); + +var _a = /*#__PURE__*/new WeakMap(); + +var _B = /*#__PURE__*/new WeakMap(); + +var _b = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor() { + babelHelpers.classPrivateFieldInitSpec(this, _b, { + get: _get_b, + set: _set_b + }); + babelHelpers.classPrivateFieldInitSpec(this, _a, { + get: _get_a, + set: _set_a + }); + babelHelpers.classPrivateFieldInitSpec(this, _A, { + writable: true, + value: void 0 + }); + babelHelpers.classPrivateFieldInitSpec(this, _B, { + writable: true, + value: 123 + }); + } + +} + +function _get_a() { + return babelHelpers.classPrivateFieldGet(this, _A); +} + +function _set_a(v) { + babelHelpers.classPrivateFieldSet(this, _A, v); +} + +function _get_b() { + return babelHelpers.classPrivateFieldGet(this, _B); +} + +function _set_b(v) { + babelHelpers.classPrivateFieldSet(this, _B, v); +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-public/exec.js new file mode 100644 index 000000000000..5ccd5dcce44d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-public/exec.js @@ -0,0 +1,27 @@ +class Foo { + accessor a; + + accessor b = 123; + + accessor ['c'] = 456; +} + +let foo = new Foo(); + +expect(foo.a).toBe(undefined); +foo.a = 123; +expect(foo.a).toBe(123); +expect(foo.hasOwnProperty('a')).toBe(false); +expect(Foo.prototype.hasOwnProperty('a')).toBe(true); + +expect(foo.b).toBe(123); +foo.b = 456 +expect(foo.b).toBe(456); +expect(foo.hasOwnProperty('b')).toBe(false); +expect(Foo.prototype.hasOwnProperty('b')).toBe(true); + +expect(foo.c).toBe(456); +foo.c = 789 +expect(foo.c).toBe(789); +expect(foo.hasOwnProperty('c')).toBe(false); +expect(Foo.prototype.hasOwnProperty('c')).toBe(true); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-public/input.js new file mode 100644 index 000000000000..ad27f18d5ed3 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-public/input.js @@ -0,0 +1,7 @@ +class Foo { + accessor a; + + accessor b = 123; + + accessor ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-public/output.js new file mode 100644 index 000000000000..6ec6f9255a06 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-public/output.js @@ -0,0 +1,47 @@ +var _A = /*#__PURE__*/new WeakMap(); + +var _B = /*#__PURE__*/new WeakMap(); + +var _C = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor() { + babelHelpers.classPrivateFieldInitSpec(this, _A, { + writable: true, + value: void 0 + }); + babelHelpers.classPrivateFieldInitSpec(this, _B, { + writable: true, + value: 123 + }); + babelHelpers.classPrivateFieldInitSpec(this, _C, { + writable: true, + value: 456 + }); + } + + get a() { + return babelHelpers.classPrivateFieldGet(this, _A); + } + + set a(v) { + babelHelpers.classPrivateFieldSet(this, _A, v); + } + + get b() { + return babelHelpers.classPrivateFieldGet(this, _B); + } + + set b(v) { + babelHelpers.classPrivateFieldSet(this, _B, v); + } + + get 'c'() { + return babelHelpers.classPrivateFieldGet(this, _C); + } + + set 'c'(v) { + babelHelpers.classPrivateFieldSet(this, _C, v); + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-private/exec.js new file mode 100644 index 000000000000..21defb3f24d8 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-private/exec.js @@ -0,0 +1,29 @@ +class Foo { + static accessor #a; + + static accessor #b = 123; + + static getA() { + return this.#a; + } + + static setA(v) { + this.#a = v; + } + + static getB() { + return this.#b; + } + + static setB(v) { + this.#b = v; + } +} + +expect(Foo.getA()).toBe(undefined); +Foo.setA(123) +expect(Foo.getA()).toBe(123); + +expect(Foo.getB()).toBe(123); +Foo.setB(456) +expect(Foo.getB()).toBe(456); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-private/input.js new file mode 100644 index 000000000000..2e516a961de9 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-private/input.js @@ -0,0 +1,5 @@ +class Foo { + static accessor #a; + + static accessor #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-private/output.js new file mode 100644 index 000000000000..51de21b149b2 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-private/output.js @@ -0,0 +1,34 @@ +class Foo {} + +function _get_a() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _A); +} + +function _set_a(v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _A, v); +} + +function _get_b() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _B); +} + +function _set_b(v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _B, v); +} + +var _b = { + get: _get_b, + set: _set_b +}; +var _a = { + get: _get_a, + set: _set_a +}; +var _A = { + writable: true, + value: void 0 +}; +var _B = { + writable: true, + value: 123 +}; diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-public/exec.js new file mode 100644 index 000000000000..d22a4e710dd8 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-public/exec.js @@ -0,0 +1,22 @@ +class Foo { + static accessor a; + + static accessor b = 123; + + static accessor ['c'] = 456; +} + +expect(Foo.a).toBe(undefined); +Foo.a = 123; +expect(Foo.a).toBe(123); +expect(Foo.hasOwnProperty('a')).toBe(true); + +expect(Foo.b).toBe(123); +Foo.b = 456 +expect(Foo.b).toBe(456); +expect(Foo.hasOwnProperty('b')).toBe(true); + +expect(Foo.c).toBe(456); +Foo.c = 789 +expect(Foo.c).toBe(789); +expect(Foo.hasOwnProperty('c')).toBe(true); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-public/input.js new file mode 100644 index 000000000000..160e72cd531c --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-public/input.js @@ -0,0 +1,7 @@ +class Foo { + static accessor a; + + static accessor b = 123; + + static accessor ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-public/output.js new file mode 100644 index 000000000000..4fe37de40ebf --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-accessors/undecorated-static-public/output.js @@ -0,0 +1,39 @@ +class Foo { + static get a() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _A); + } + + static set a(v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _A, v); + } + + static get b() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _B); + } + + static set b(v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _B, v); + } + + static get 'c'() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _C); + } + + static set 'c'(v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _C, v); + } + +} + +var _A = { + writable: true, + value: void 0 +}; +var _B = { + writable: true, + value: 123 +}; +var _C = { + writable: true, + value: 456 +}; diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions/input.js new file mode 100644 index 000000000000..542bf870c079 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions/input.js @@ -0,0 +1,11 @@ +const A = @dec class A {} +const B = @dec class C {} +const D = @dec class {} +const E = (@dec class {}, 123); +const F = [@dec class G {}, @dec class {}]; +const H = @dec class extends I {}; +const J = @dec class K extends L {}; + +function classFactory() { + return @dec class {} +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions/output.js new file mode 100644 index 000000000000..105c8eb31f6d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/expressions/output.js @@ -0,0 +1,69 @@ +var _initClass, _A, _class, _temp, _initClass2, _C, _class2, _temp2, _initClass3, _D, _class3, _temp3, _initClass4, _decorated_class, _class4, _temp4, _initClass5, _G, _class5, _temp5, _initClass6, _decorated_class2, _class6, _temp6, _initClass7, _H, _class7, _temp7, _initClass8, _K, _class8, _temp8; + +const A = ((_temp = _class = class A {}, (() => { + let ret = babelHelpers.applyDecs(_class, [], [dec]); + _A = ret[0]; + _initClass = ret[1]; +})(), (() => { + _initClass(); +})(), _temp), _A); +const B = ((_temp2 = _class2 = class C {}, (() => { + let ret = babelHelpers.applyDecs(_class2, [], [dec]); + _C = ret[0]; + _initClass2 = ret[1]; +})(), (() => { + _initClass2(); +})(), _temp2), _C); +const D = ((_temp3 = _class3 = class D {}, (() => { + let ret = babelHelpers.applyDecs(_class3, [], [dec]); + _D = ret[0]; + _initClass3 = ret[1]; +})(), (() => { + _initClass3(); +})(), _temp3), _D); +const E = (((_temp4 = _class4 = class {}, (() => { + let ret = babelHelpers.applyDecs(_class4, [], [dec]); + _decorated_class = ret[0]; + _initClass4 = ret[1]; +})(), (() => { + _initClass4(); +})(), _temp4), _decorated_class), 123); +const F = [((_temp5 = _class5 = class G {}, (() => { + let ret = babelHelpers.applyDecs(_class5, [], [dec]); + _G = ret[0]; + _initClass5 = ret[1]; +})(), (() => { + _initClass5(); +})(), _temp5), _G), ((_temp6 = _class6 = class {}, (() => { + let ret = babelHelpers.applyDecs(_class6, [], [dec]); + _decorated_class2 = ret[0]; + _initClass6 = ret[1]; +})(), (() => { + _initClass6(); +})(), _temp6), _decorated_class2)]; +const H = ((_temp7 = _class7 = class H extends I {}, (() => { + let ret = babelHelpers.applyDecs(_class7, [], [dec]); + _H = ret[0]; + _initClass7 = ret[1]; +})(), (() => { + _initClass7(); +})(), _temp7), _H); +const J = ((_temp8 = _class8 = class K extends L {}, (() => { + let ret = babelHelpers.applyDecs(_class8, [], [dec]); + _K = ret[0]; + _initClass8 = ret[1]; +})(), (() => { + _initClass8(); +})(), _temp8), _K); + +function classFactory() { + var _initClass9, _decorated_class3, _class9, _temp9; + + return (_temp9 = _class9 = class {}, (() => { + let ret = babelHelpers.applyDecs(_class9, [], [dec]); + _decorated_class3 = ret[0]; + _initClass9 = ret[1]; + })(), (() => { + _initClass9(); + })(), _temp9), _decorated_class3; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/inheritance/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/inheritance/exec.js new file mode 100644 index 000000000000..889e8c102cf4 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/inheritance/exec.js @@ -0,0 +1,18 @@ +let count = 0; + +function dec1(Klass) { + expect(++count).toBe(1); + expect(Klass.name).toBe('Bar'); +} + +@dec1 +class Bar {} + +function dec2(Klass) { + expect(++count).toBe(2); + expect(Klass.name).toBe('Foo'); + expect(Object.getPrototypeOf(Klass)).toBe(Bar); +} + +@dec2 +class Foo extends Bar {} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/inheritance/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/inheritance/input.js new file mode 100644 index 000000000000..7a4a6684555a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/inheritance/input.js @@ -0,0 +1,5 @@ +@dec1 +class Bar {} + +@dec2 +class Foo extends Bar {} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/inheritance/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/inheritance/output.js new file mode 100644 index 000000000000..c8312963ba87 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/inheritance/output.js @@ -0,0 +1,29 @@ +var _initClass, _initClass2; + +let _Bar; + +class Bar {} + +(() => { + let ret = babelHelpers.applyDecs(Bar, [], [dec1]); + _Bar = ret[0]; + _initClass = ret[1]; +})(); + +(() => { + _initClass(); +})(); + +let _Foo; + +class Foo extends _Bar {} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [], [dec2]); + _Foo = ret[0]; + _initClass2 = ret[1]; +})(); + +(() => { + _initClass2(); +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/initializers/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/initializers/exec.js new file mode 100644 index 000000000000..aefc3ba5b88c --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/initializers/exec.js @@ -0,0 +1,41 @@ +function dec1(Foo, { addInitializer }) { + expect(Foo.field).toBe(undefined); + addInitializer(() => { + Foo.initField = 123; + }); +} + +@dec1 +class Foo { + static { + expect(this.initField).toBe(undefined); + } + + static field = 123; +} + +expect(Foo.initField).toBe(123); +expect(Foo.field).toBe(123); + +function dec2(Bar, { addInitializer }) { + expect(Bar.field).toBe(123); + expect(Bar.otherField).toBe(undefined); + expect(Bar.initField).toBe(123); + addInitializer(() => { + Bar.initField = 456; + }); +} + +@dec2 +class Bar extends Foo { + static { + expect(this.initField).toBe(123); + this.otherField = 456; + } + + static field = 456; +} + +expect(Bar.initField).toBe(456); +expect(Bar.field).toBe(456); +expect(Bar.otherField).toBe(456); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/initializers/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/initializers/input.js new file mode 100644 index 000000000000..deeb483448f7 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/initializers/input.js @@ -0,0 +1,13 @@ +@dec +class Foo { + static field = 123; +} + +@dec +class Bar extends Foo { + static { + this.otherField = 456; + } + + static field = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/initializers/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/initializers/output.js new file mode 100644 index 000000000000..60ba8b6da39f --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/initializers/output.js @@ -0,0 +1,37 @@ +var _initClass, _initClass2; + +let _Foo; + +class Foo {} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [], [dec]); + _Foo = ret[0]; + _initClass = ret[1]; +})(); + +babelHelpers.defineProperty(Foo, "field", 123); + +(() => { + _initClass(); +})(); + +let _Bar; + +class Bar extends _Foo {} + +(() => { + let ret = babelHelpers.applyDecs(Bar, [], [dec]); + _Bar = ret[0]; + _initClass2 = ret[1]; +})(); + +(() => { + Bar.otherField = 456; +})(); + +babelHelpers.defineProperty(Bar, "field", 123); + +(() => { + _initClass2(); +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement-with-expr/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement-with-expr/exec.js new file mode 100644 index 000000000000..739e33a05be5 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement-with-expr/exec.js @@ -0,0 +1,17 @@ +let replaced; + +function dec(Klass) { + replaced = class extends Klass {}; + + return replaced; +} + +const Foo = @dec class Bar { + static bar = new Bar(); +}; + +const foo = new Foo(); + +expect(Foo).toBe(replaced); +expect(Foo.bar).toBeInstanceOf(replaced); +expect(foo).toBeInstanceOf(replaced); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement-with-expr/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement-with-expr/input.js new file mode 100644 index 000000000000..fde7feb1abd7 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement-with-expr/input.js @@ -0,0 +1,6 @@ +const Foo = @dec class Bar { + bar = new Bar(); +}; + +const foo = new Foo(); + diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement-with-expr/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement-with-expr/output.js new file mode 100644 index 000000000000..d79f9124aabc --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement-with-expr/output.js @@ -0,0 +1,15 @@ +var _initClass, _Bar, _class, _temp; + +const Foo = ((_temp = _class = class Bar { + constructor() { + babelHelpers.defineProperty(this, "bar", new _Bar()); + } + +}, (() => { + let ret = babelHelpers.applyDecs(_class, [], [dec]); + _Bar = ret[0]; + _initClass = ret[1]; +})(), (() => { + _initClass(); +})(), _temp), _Bar); +const foo = new Foo(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement/exec.js new file mode 100644 index 000000000000..c8dc49c0d85e --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement/exec.js @@ -0,0 +1,19 @@ + +let replaced; + +function dec(Klass) { + replaced = class extends Klass {}; + + return replaced; +} + +@dec +class Foo { + static foo = new Foo(); +} + +const foo = new Foo(); + +expect(Foo).toBe(replaced); +expect(Foo.foo).toBeInstanceOf(replaced); +expect(foo).toBeInstanceOf(replaced); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement/input.js new file mode 100644 index 000000000000..e6da5000db62 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement/input.js @@ -0,0 +1,6 @@ +@dec +class Foo { + static foo = new Foo(); +} + +const foo = new Foo(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement/output.js new file mode 100644 index 000000000000..dc651115550e --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-classes/replacement/output.js @@ -0,0 +1,19 @@ +var _initClass; + +let _Foo; + +class Foo {} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [], [dec]); + _Foo = ret[0]; + _initClass = ret[1]; +})(); + +babelHelpers.defineProperty(Foo, "foo", new _Foo()); + +(() => { + _initClass(); +})(); + +const foo = new _Foo(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-ast/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-ast/exec.js new file mode 100644 index 000000000000..49fad189f4e2 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-ast/exec.js @@ -0,0 +1,33 @@ +var i = 0; + +function getKey() { + return (i++).toString(); +} + +let elements = []; + +function dec(fn, context) { + elements.push({ fn, context }); +} + +class Foo { + @dec + [getKey()]() { + return 1; + } + + @dec + [getKey()]() { + return 2; + } +} + +expect(elements).toHaveLength(2); + +expect(elements[0].context.name).toBe("0"); +expect(elements[0].fn()).toBe(1); + +expect(elements[1].context.name).toBe("1"); +expect(elements[1].fn()).toBe(2); + +expect(i).toBe(2); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-ast/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-ast/input.js new file mode 100644 index 000000000000..2ca438188867 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-ast/input.js @@ -0,0 +1,11 @@ +class Foo { + @dec + [getKey()]() { + return 1; + } + + @dec + [getKey()]() { + return 2; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-ast/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-ast/output.js new file mode 100644 index 000000000000..ad38e1347441 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-ast/output.js @@ -0,0 +1,26 @@ +var _computedKey, _computedKey2, _dec, _dec2, _initProto; + +_computedKey = getKey() +_dec = dec +_computedKey2 = getKey() +_dec2 = dec + +class Foo { + constructor(...args) { + _initProto(this); + } + + [_computedKey]() { + return 1; + } + + [_computedKey2]() { + return 2; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 2, _computedKey], [_dec2, 2, _computedKey2]], []); + _initProto = ret[0]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-value/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-value/exec.js new file mode 100644 index 000000000000..c97e2293ac96 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-value/exec.js @@ -0,0 +1,29 @@ +expect(() => { + var i = 0; + var j = 0; + + function getKeyI() { + return (i++).toString(); + } + function getKeyJ() { + return (j++).toString(); + } + + let elements = []; + + function dec(fn, context) { + elements.push({ fn, context }); + } + + class Foo { + @dec + [getKeyI()]() { + return 1; + } + + @dec + [getKeyJ()]() { + return 2; + } + } +}).toThrow("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: 0") diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-value/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-value/input.js new file mode 100644 index 000000000000..8aeb57759b76 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-value/input.js @@ -0,0 +1,11 @@ +class Foo { + @dec + [getKeyI()]() { + return 1; + } + + @dec + [getKeyJ()]() { + return 2; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-value/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-value/output.js new file mode 100644 index 000000000000..6785c74c5407 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/computed-keys-same-value/output.js @@ -0,0 +1,26 @@ +var _computedKey, _computedKey2, _dec, _dec2, _initProto; + +_computedKey = getKeyI() +_dec = dec +_computedKey2 = getKeyJ() +_dec2 = dec + +class Foo { + constructor(...args) { + _initProto(this); + } + + [_computedKey]() { + return 1; + } + + [_computedKey2]() { + return 2; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 2, _computedKey], [_dec2, 2, _computedKey2]], []); + _initProto = ret[0]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/method-and-field/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/method-and-field/exec.js new file mode 100644 index 000000000000..8ac906f1823a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/method-and-field/exec.js @@ -0,0 +1,23 @@ +let elements = []; + +function dec(val, context) { + elements.push({ val, context }); +} + +class Foo { + @dec + a = 123; + + @dec + a() { + return 1; + } +} + +expect(elements).toHaveLength(2); + +expect(elements[0].context.name).toBe("a"); +expect(elements[0].val).toBe(undefined); + +expect(elements[1].context.name).toBe("a"); +expect(elements[1].val()).toBe(1); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/method-and-field/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/method-and-field/input.js new file mode 100644 index 000000000000..522da0061204 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/method-and-field/input.js @@ -0,0 +1,9 @@ +class Foo { + @dec + a = 123; + + @dec + a() { + return 1; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/method-and-field/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/method-and-field/output.js new file mode 100644 index 000000000000..3e6340ae06ca --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/method-and-field/output.js @@ -0,0 +1,18 @@ +var _init_a, _initProto; + +class Foo { + constructor() { + babelHelpers.defineProperty(this, "a", (_initProto(this), _init_a(this, 123))); + } + + a() { + return 1; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 0, "a"], [dec, 2, "a"]], []); + _init_a = ret[0]; + _initProto = ret[1]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/methods-with-same-key/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/methods-with-same-key/exec.js new file mode 100644 index 000000000000..9e270b2a7488 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/methods-with-same-key/exec.js @@ -0,0 +1,19 @@ +expect(() => { + let elements = []; + + function dec(val, context) { + elements.push({ val, context }); + } + + class Foo { + @dec + a() { + return 1; + } + + @dec + a() { + return 2; + } + } +}).toThrow("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: a") diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/methods-with-same-key/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/methods-with-same-key/input.js new file mode 100644 index 000000000000..db90a40aa67b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/methods-with-same-key/input.js @@ -0,0 +1,11 @@ +class Foo { + @dec + a() { + return 1; + } + + @dec + a() { + return 2; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/methods-with-same-key/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/methods-with-same-key/output.js new file mode 100644 index 000000000000..4321ac7a3e96 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/methods-with-same-key/output.js @@ -0,0 +1,21 @@ +var _initProto; + +class Foo { + constructor(...args) { + _initProto(this); + } + + a() { + return 1; + } + + a() { + return 2; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 2, "a"], [dec, 2, "a"]], []); + _initProto = ret[0]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-duplicated-keys/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/private/exec.js new file mode 100644 index 000000000000..9d368edd0f8b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/private/exec.js @@ -0,0 +1,41 @@ +function dec(_v, context) { + return function (v) { + this[context.name + 'Context'] = context; + return (v || 1) + 1; + } +} + +class Foo { + @dec + #a; + + @dec + #b = 123; +} + +let foo = new Foo(); + +const aContext = foo['#aContext']; +const bContext = foo['#bContext']; + +expect(aContext.access.get.call(foo)).toBe(2); +aContext.access.set.call(foo, 123); +expect(aContext.access.get.call(foo)).toBe(123); +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('field'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('undefined'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.access.get.call(foo)).toBe(124); +bContext.access.set.call(foo, 123); +expect(bContext.access.get.call(foo)).toBe(123); +expect(bContext.name).toBe('#b'); +expect(bContext.kind).toBe('field'); +expect(bContext.isStatic).toBe(false); +expect(bContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('undefined'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/private/input.js new file mode 100644 index 000000000000..222ec09fc95e --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/private/input.js @@ -0,0 +1,7 @@ +class Foo { + @dec + #a; + + @dec + #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/private/output.js new file mode 100644 index 000000000000..26a92fd7388a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/private/output.js @@ -0,0 +1,33 @@ +var _init_a, _init_b; + +var _a = /*#__PURE__*/new WeakMap(); + +var _b = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor() { + babelHelpers.classPrivateFieldInitSpec(this, _a, { + writable: true, + value: _init_a(this) + }); + babelHelpers.classPrivateFieldInitSpec(this, _b, { + writable: true, + value: _init_b(this, 123) + }); + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 0, "a", function () { + return babelHelpers.classPrivateFieldGet(this, _a); + }, function (value) { + babelHelpers.classPrivateFieldSet(this, _a, value); + }], [dec, 0, "b", function () { + return babelHelpers.classPrivateFieldGet(this, _b); + }, function (value) { + babelHelpers.classPrivateFieldSet(this, _b, value); + }]], []); + _init_a = ret[0]; + _init_b = ret[1]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/public/exec.js new file mode 100644 index 000000000000..0d5ed78cf745 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/public/exec.js @@ -0,0 +1,62 @@ +function dec(_v, context) { + return function (v) { + this[context.name + 'Context'] = context; + return (v || 1) + 1; + } +} + +class Foo { + @dec + a; + + @dec + b = 123; + + @dec + ['c'] = 456; +} + +let foo = new Foo(); + +const aContext = foo['aContext']; +const bContext = foo['bContext']; +const cContext = foo['cContext']; + +expect(foo.a).toBe(2); +foo.a = 123; +expect(foo.a).toBe(123); +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('field'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('undefined'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); +expect(foo.hasOwnProperty('a')).toBe(true); +expect(Foo.prototype.hasOwnProperty('a')).toBe(false); + +expect(foo.b).toBe(124); +foo.b = 123; +expect(foo.b).toBe(123); +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('field'); +expect(bContext.isStatic).toBe(false); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('undefined'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); +expect(foo.hasOwnProperty('b')).toBe(true); +expect(Foo.prototype.hasOwnProperty('b')).toBe(false); + +expect(foo.c).toBe(457); +foo.c = 456; +expect(foo.c).toBe(456); +expect(cContext.name).toBe('c'); +expect(cContext.kind).toBe('field'); +expect(cContext.isStatic).toBe(false); +expect(cContext.isPrivate).toBe(false); +expect(typeof cContext.addInitializer).toBe('undefined'); +expect(typeof cContext.setMetadata).toBe('function'); +expect(typeof cContext.getMetadata).toBe('function'); +expect(foo.hasOwnProperty('c')).toBe(true); +expect(Foo.prototype.hasOwnProperty('c')).toBe(false); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/public/input.js new file mode 100644 index 000000000000..8dff95c99a3a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/public/input.js @@ -0,0 +1,10 @@ +class Foo { + @dec + a; + + @dec + b = 123; + + @dec + ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/public/output.js new file mode 100644 index 000000000000..946e639dc76e --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/public/output.js @@ -0,0 +1,22 @@ +var _init_a, _init_b, _computedKey, _init_computedKey, _dec, _dec2, _dec3; + +_dec = dec +_dec2 = dec +_computedKey = 'c' +_dec3 = dec + +class Foo { + constructor() { + babelHelpers.defineProperty(this, "a", _init_a(this)); + babelHelpers.defineProperty(this, "b", _init_b(this, 123)); + babelHelpers.defineProperty(this, _computedKey, _init_computedKey(this, 456)); + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 0, "a"], [_dec2, 0, "b"], [_dec3, 0, _computedKey]], []); + _init_a = ret[0]; + _init_b = ret[1]; + _init_computedKey = ret[2]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-private/exec.js new file mode 100644 index 000000000000..51fba146164c --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-private/exec.js @@ -0,0 +1,39 @@ +function dec(_v, context) { + return function (v) { + this[context.name + 'Context'] = context; + return (v || 1) + 1; + } +} + +class Foo { + @dec + static #a; + + @dec + static #b = 123; +} + +const aContext = Foo['#aContext']; +const bContext = Foo['#bContext']; + +expect(aContext.access.get.call(Foo)).toBe(2); +aContext.access.set.call(Foo, 123); +expect(aContext.access.get.call(Foo)).toBe(123); +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('field'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('undefined'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.access.get.call(Foo)).toBe(124); +bContext.access.set.call(Foo, 123); +expect(bContext.access.get.call(Foo)).toBe(123); +expect(bContext.name).toBe('#b'); +expect(bContext.kind).toBe('field'); +expect(bContext.isStatic).toBe(true); +expect(bContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('undefined'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-private/input.js new file mode 100644 index 000000000000..830d82321863 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-private/input.js @@ -0,0 +1,7 @@ +class Foo { + @dec + static #a; + + @dec + static #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-private/output.js new file mode 100644 index 000000000000..39e124e65684 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-private/output.js @@ -0,0 +1,26 @@ +var _init_a, _init_b; + +class Foo {} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 5, "a", function () { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _a); + }, function (value) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _a, value); + }], [dec, 5, "b", function () { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _b); + }, function (value) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _b, value); + }]], []); + _init_a = ret[0]; + _init_b = ret[1]; +})(); + +var _a = { + writable: true, + value: _init_a(Foo) +}; +var _b = { + writable: true, + value: _init_b(Foo, 123) +}; diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-public/exec.js new file mode 100644 index 000000000000..48af3023539c --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-public/exec.js @@ -0,0 +1,57 @@ +function dec(_v, context) { + return function (v) { + this[context.name + 'Context'] = context; + return (v || 1) + 1; + } +} + +class Foo { + @dec + static a; + + @dec + static b = 123; + + @dec + static ['c'] = 456; +} + +const aContext = Foo['aContext']; +const bContext = Foo['bContext']; +const cContext = Foo['cContext']; + +expect(Foo.a).toBe(2); +Foo.a = 123; +expect(Foo.a).toBe(123); +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('field'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('undefined'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); +expect(Foo.hasOwnProperty('a')).toBe(true); + +expect(Foo.b).toBe(124); +Foo.b = 123; +expect(Foo.b).toBe(123); +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('field'); +expect(bContext.isStatic).toBe(true); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('undefined'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); +expect(Foo.hasOwnProperty('b')).toBe(true); + +expect(Foo.c).toBe(457); +Foo.c = 456; +expect(Foo.c).toBe(456); +expect(cContext.name).toBe('c'); +expect(cContext.kind).toBe('field'); +expect(cContext.isStatic).toBe(true); +expect(cContext.isPrivate).toBe(false); +expect(typeof cContext.addInitializer).toBe('undefined'); +expect(typeof cContext.setMetadata).toBe('function'); +expect(typeof cContext.getMetadata).toBe('function'); +expect(Foo.hasOwnProperty('c')).toBe(true); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-public/input.js new file mode 100644 index 000000000000..9b9dae98314a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-public/input.js @@ -0,0 +1,10 @@ +class Foo { + @dec + static a; + + @dec + static b = 123; + + @dec + static ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-public/output.js new file mode 100644 index 000000000000..259a78679fed --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-fields/static-public/output.js @@ -0,0 +1,19 @@ +var _init_a, _init_b, _computedKey, _init_computedKey, _dec, _dec2, _dec3; + +_dec = dec +_dec2 = dec +_computedKey = 'c' +_dec3 = dec + +class Foo {} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 5, "a"], [_dec2, 5, "b"], [_dec3, 5, _computedKey]], []); + _init_a = ret[0]; + _init_b = ret[1]; + _init_computedKey = ret[2]; +})(); + +babelHelpers.defineProperty(Foo, "a", _init_a(Foo)); +babelHelpers.defineProperty(Foo, "b", _init_b(Foo, 123)); +babelHelpers.defineProperty(Foo, _computedKey, _init_computedKey(Foo, 456)); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/private/exec.js new file mode 100644 index 000000000000..a4f9a31d2589 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/private/exec.js @@ -0,0 +1,67 @@ +function dec(value, context) { + context.addInitializer((instance) => { + instance[context.name + '_' + context.kind + 'Context'] = context; + }); + + if (context.kind === 'getter') { + return function () { + return value.call(this) + 1; + } + } else { + return function (v) { + return value.call(this, v + 1); + } + } +} + +class Foo { + value = 1; + + @dec + get #a() { + return this.value; + } + + @dec + set #a(v) { + this.value = v; + } + + getA() { + return this.#a; + } + + setA(v) { + this.#a = v; + } +} + +let foo = new Foo(); + +const a_getterContext = foo['#a_getterContext']; +const a_setterContext = foo['#a_setterContext']; + +expect(a_getterContext.access.get.call(foo)).toBe(2); +expect(foo.getA()).toBe(2); +a_setterContext.access.set.call(foo, 123); +expect(a_getterContext.access.get.call(foo)).toBe(125); +expect(foo.getA()).toBe(125); +foo.setA(456); +expect(a_getterContext.access.get.call(foo)).toBe(458); +expect(foo.getA()).toBe(458); + +expect(a_getterContext.name).toBe('#a'); +expect(a_getterContext.kind).toBe('getter'); +expect(a_getterContext.isStatic).toBe(false); +expect(a_getterContext.isPrivate).toBe(true); +expect(typeof a_getterContext.addInitializer).toBe('function'); +expect(typeof a_getterContext.setMetadata).toBe('function'); +expect(typeof a_getterContext.getMetadata).toBe('function'); + +expect(a_setterContext.name).toBe('#a'); +expect(a_setterContext.kind).toBe('setter'); +expect(a_setterContext.isStatic).toBe(false); +expect(a_setterContext.isPrivate).toBe(true); +expect(typeof a_setterContext.addInitializer).toBe('function'); +expect(typeof a_setterContext.setMetadata).toBe('function'); +expect(typeof a_setterContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/private/input.js new file mode 100644 index 000000000000..060ae225a21e --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/private/input.js @@ -0,0 +1,21 @@ +class Foo { + value = 1; + + @dec + get #a() { + return this.value; + } + + @dec + set #a(v) { + this.value = v; + } + + getA() { + return this.#a; + } + + setA(v) { + this.#a = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/private/output.js new file mode 100644 index 000000000000..357fba3f5191 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/private/output.js @@ -0,0 +1,43 @@ +var _call_a, _call_a2, _initProto; + +var _a = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor(...args) { + babelHelpers.classPrivateFieldInitSpec(this, _a, { + get: _get_a, + set: _set_a + }); + babelHelpers.defineProperty(this, "value", 1); + + _initProto(this); + } + + getA() { + return babelHelpers.classPrivateFieldGet(this, _a); + } + + setA(v) { + babelHelpers.classPrivateFieldSet(this, _a, v); + } + +} + +function _get_a() { + return _call_a(this); +} + +function _set_a(v) { + _call_a2(this, v); +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 3, "a", function () { + return this.value; + }], [dec, 4, "a", function (v) { + this.value = v; + }]], []); + _call_a = ret[0]; + _call_a2 = ret[1]; + _initProto = ret[2]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/public/exec.js new file mode 100644 index 000000000000..0420e538875b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/public/exec.js @@ -0,0 +1,88 @@ +function dec(value, context) { + context.addInitializer((instance) => { + instance[context.name + '_' + context.kind + 'Context'] = context; + }); + + if (context.kind === 'getter') { + return function () { + return value.call(this) + 1; + } + } else { + return function (v) { + return value.call(this, v + 1); + } + } +} + +class Foo { + value = 1; + + @dec + get a() { + return this.value; + } + + @dec + set a(v) { + this.value = v; + } + + @dec + get ['b']() { + return this.value; + } + + @dec + set ['b'](v) { + this.value = v; + } +} + +let foo = new Foo(); + +const a_getterContext = foo['a_getterContext']; +const a_setterContext = foo['a_setterContext']; + +const b_getterContext = foo['b_getterContext']; +const b_setterContext = foo['b_setterContext']; + +expect(foo.a).toBe(2); +expect(foo.b).toBe(2); +foo.a = 123; +expect(foo.a).toBe(125); +expect(foo.b).toBe(125); +foo.b = 456; +expect(foo.a).toBe(458); +expect(foo.b).toBe(458); + +expect(a_getterContext.name).toBe('a'); +expect(a_getterContext.kind).toBe('getter'); +expect(a_getterContext.isStatic).toBe(false); +expect(a_getterContext.isPrivate).toBe(false); +expect(typeof a_getterContext.addInitializer).toBe('function'); +expect(typeof a_getterContext.setMetadata).toBe('function'); +expect(typeof a_getterContext.getMetadata).toBe('function'); + +expect(a_setterContext.name).toBe('a'); +expect(a_setterContext.kind).toBe('setter'); +expect(a_setterContext.isStatic).toBe(false); +expect(a_setterContext.isPrivate).toBe(false); +expect(typeof a_setterContext.addInitializer).toBe('function'); +expect(typeof a_setterContext.setMetadata).toBe('function'); +expect(typeof a_setterContext.getMetadata).toBe('function'); + +expect(b_getterContext.name).toBe('b'); +expect(b_getterContext.kind).toBe('getter'); +expect(b_getterContext.isStatic).toBe(false); +expect(b_getterContext.isPrivate).toBe(false); +expect(typeof b_getterContext.addInitializer).toBe('function'); +expect(typeof b_getterContext.setMetadata).toBe('function'); +expect(typeof b_getterContext.getMetadata).toBe('function'); + +expect(b_setterContext.name).toBe('b'); +expect(b_setterContext.kind).toBe('setter'); +expect(b_setterContext.isStatic).toBe(false); +expect(b_setterContext.isPrivate).toBe(false); +expect(typeof b_setterContext.addInitializer).toBe('function'); +expect(typeof b_setterContext.setMetadata).toBe('function'); +expect(typeof b_setterContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/public/input.js new file mode 100644 index 000000000000..ef384166d689 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/public/input.js @@ -0,0 +1,23 @@ +class Foo { + value = 1; + + @dec + get a() { + return this.value; + } + + @dec + set a(v) { + this.value = v; + } + + @dec + get ['b']() { + return this.value; + } + + @dec + set ['b'](v) { + this.value = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/public/output.js new file mode 100644 index 000000000000..c9c4d665adac --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/public/output.js @@ -0,0 +1,38 @@ +var _computedKey, _computedKey2, _dec, _dec2, _dec3, _dec4, _initProto; + +_dec = dec +_dec2 = dec +_computedKey = 'b' +_dec3 = dec +_computedKey2 = 'b' +_dec4 = dec + +class Foo { + constructor(...args) { + babelHelpers.defineProperty(this, "value", 1); + + _initProto(this); + } + + get a() { + return this.value; + } + + set a(v) { + this.value = v; + } + + get [_computedKey]() { + return this.value; + } + + set [_computedKey2](v) { + this.value = v; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 3, "a"], [_dec2, 4, "a"], [_dec3, 3, _computedKey], [_dec4, 4, _computedKey2]], []); + _initProto = ret[0]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-private/exec.js new file mode 100644 index 000000000000..90bdd12c47ec --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-private/exec.js @@ -0,0 +1,65 @@ +function dec(value, context) { + context.addInitializer((instance) => { + instance[context.name + '_' + context.kind + 'Context'] = context; + }); + + if (context.kind === 'getter') { + return function () { + return value.call(this) + 1; + } + } else { + return function (v) { + return value.call(this, v + 1); + } + } +} + +class Foo { + static value = 1; + + @dec + static get #a() { + return this.value; + } + + @dec + static set #a(v) { + this.value = v; + } + + static getA() { + return this.#a; + } + + static setA(v) { + this.#a = v; + } +} + +const a_getterContext = Foo['#a_getterContext']; +const a_setterContext = Foo['#a_setterContext']; + +expect(a_getterContext.access.get.call(Foo)).toBe(2); +expect(Foo.getA()).toBe(2); +a_setterContext.access.set.call(Foo, 123); +expect(a_getterContext.access.get.call(Foo)).toBe(125); +expect(Foo.getA()).toBe(125); +Foo.setA(456); +expect(a_getterContext.access.get.call(Foo)).toBe(458); +expect(Foo.getA()).toBe(458); + +expect(a_getterContext.name).toBe('#a'); +expect(a_getterContext.kind).toBe('getter'); +expect(a_getterContext.isStatic).toBe(true); +expect(a_getterContext.isPrivate).toBe(true); +expect(typeof a_getterContext.addInitializer).toBe('function'); +expect(typeof a_getterContext.setMetadata).toBe('function'); +expect(typeof a_getterContext.getMetadata).toBe('function'); + +expect(a_setterContext.name).toBe('#a'); +expect(a_setterContext.kind).toBe('setter'); +expect(a_setterContext.isStatic).toBe(true); +expect(a_setterContext.isPrivate).toBe(true); +expect(typeof a_setterContext.addInitializer).toBe('function'); +expect(typeof a_setterContext.setMetadata).toBe('function'); +expect(typeof a_setterContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-private/input.js new file mode 100644 index 000000000000..f439a9152528 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-private/input.js @@ -0,0 +1,21 @@ +class Foo { + static value = 1; + + @dec + static get #a() { + return this.value; + } + + @dec + static set #a(v) { + this.value = v; + } + + static getA() { + return this.#a; + } + + static setA(v) { + this.#a = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-private/output.js new file mode 100644 index 000000000000..1cb263635eff --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-private/output.js @@ -0,0 +1,40 @@ +var _call_a, _call_a2, _initStatic; + +class Foo { + static getA() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _a); + } + + static setA(v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _a, v); + } + +} + +function _get_a() { + return _call_a(this); +} + +function _set_a(v) { + _call_a2(this, v); +} + +var _a = { + get: _get_a, + set: _set_a +}; + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 8, "a", function () { + return this.value; + }], [dec, 9, "a", function (v) { + this.value = v; + }]], []); + _call_a = ret[0]; + _call_a2 = ret[1]; + _initStatic = ret[2]; + + _initStatic(Foo); +})(); + +babelHelpers.defineProperty(Foo, "value", 1); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-public/exec.js new file mode 100644 index 000000000000..23ea7b2f54cd --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-public/exec.js @@ -0,0 +1,87 @@ +function dec(value, context) { + context.addInitializer((instance) => { + instance[context.name + '_' + context.kind + 'Context'] = context; + }); + + if (context.kind === 'getter') { + return function () { + return value.call(this) + 1; + } + } else { + return function (v) { + return value.call(this, v + 1); + } + } +} + +class Foo { + static value = 1; + + @dec + static get a() { + return this.value; + } + + @dec + static set a(v) { + this.value = v; + } + + @dec + static get ['b']() { + return this.value; + } + + @dec + static set ['b'](v) { + this.value = v; + } +} + +const a_getterContext = Foo['a_getterContext']; +const a_setterContext = Foo['a_setterContext']; + +const b_getterContext = Foo['b_getterContext']; +const b_setterContext = Foo['b_setterContext']; + +expect(Foo.a).toBe(2); +expect(Foo.b).toBe(2); +Foo.a = 123; +expect(Foo.a).toBe(125); +expect(Foo.b).toBe(125); +Foo.b = 456; +expect(Foo.a).toBe(458); +expect(Foo.b).toBe(458); + +expect(a_getterContext.name).toBe('a'); +expect(a_getterContext.kind).toBe('getter'); +expect(a_getterContext.isStatic).toBe(true); +expect(a_getterContext.isPrivate).toBe(false); +expect(typeof a_getterContext.addInitializer).toBe('function'); +expect(typeof a_getterContext.setMetadata).toBe('function'); +expect(typeof a_getterContext.getMetadata).toBe('function'); + +expect(a_setterContext.name).toBe('a'); +expect(a_setterContext.kind).toBe('setter'); +expect(a_setterContext.isStatic).toBe(true); +expect(a_setterContext.isPrivate).toBe(false); +expect(typeof a_setterContext.addInitializer).toBe('function'); +expect(typeof a_setterContext.setMetadata).toBe('function'); +expect(typeof a_setterContext.getMetadata).toBe('function'); + +expect(b_getterContext.name).toBe('b'); +expect(b_getterContext.kind).toBe('getter'); +expect(b_getterContext.isStatic).toBe(true); +expect(b_getterContext.isPrivate).toBe(false); +expect(typeof b_getterContext.addInitializer).toBe('function'); +expect(typeof b_getterContext.setMetadata).toBe('function'); +expect(typeof b_getterContext.getMetadata).toBe('function'); + +expect(b_setterContext.name).toBe('b'); +expect(b_setterContext.kind).toBe('setter'); +expect(b_setterContext.isStatic).toBe(true); +expect(b_setterContext.isPrivate).toBe(false); +expect(typeof b_setterContext.addInitializer).toBe('function'); +expect(typeof b_setterContext.setMetadata).toBe('function'); +expect(typeof b_setterContext.getMetadata).toBe('function'); + diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-public/input.js new file mode 100644 index 000000000000..193bf7b836a2 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-public/input.js @@ -0,0 +1,23 @@ +class Foo { + static value = 1; + + @dec + static get a() { + return this.value; + } + + @dec + static set a(v) { + this.value = v; + } + + @dec + static get ['b']() { + return this.value; + } + + @dec + static set ['b'](v) { + this.value = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-public/output.js new file mode 100644 index 000000000000..81ec1ebd1de3 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters-and-setters/static-public/output.js @@ -0,0 +1,36 @@ +var _computedKey, _computedKey2, _dec, _dec2, _dec3, _dec4, _initStatic; + +_dec = dec +_dec2 = dec +_computedKey = 'b' +_dec3 = dec +_computedKey2 = 'b' +_dec4 = dec + +class Foo { + static get a() { + return this.value; + } + + static set a(v) { + this.value = v; + } + + static get [_computedKey]() { + return this.value; + } + + static set [_computedKey2](v) { + this.value = v; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 8, "a"], [_dec2, 9, "a"], [_dec3, 8, _computedKey], [_dec4, 9, _computedKey2]], []); + _initStatic = ret[0]; + + _initStatic(Foo); +})(); + +babelHelpers.defineProperty(Foo, "value", 1); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/private/exec.js new file mode 100644 index 000000000000..70c0965c67e9 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/private/exec.js @@ -0,0 +1,39 @@ +function dec(get, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function () { + return get.call(this) + 1; + } +} + +class Foo { + value = 1; + + @dec + get #a() { + return this.value; + } + + getA() { + return this.#a; + } +} + +let foo = new Foo(); + +const aContext = foo['#aContext']; + +expect(aContext.access.get.call(foo)).toBe(2); +expect(foo.getA()).toBe(2); +foo.value = 123; +expect(aContext.access.get.call(foo)).toBe(124); +expect(foo.getA()).toBe(124); +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('getter'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/private/input.js new file mode 100644 index 000000000000..49c601a1dd5b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/private/input.js @@ -0,0 +1,12 @@ +class Foo { + value = 1; + + @dec + get #a() { + return this.value; + } + + getA() { + return this.#a; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/private/output.js new file mode 100644 index 000000000000..80abff25c450 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/private/output.js @@ -0,0 +1,32 @@ +var _call_a, _initProto; + +var _a = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor(...args) { + babelHelpers.classPrivateFieldInitSpec(this, _a, { + get: _get_a, + set: void 0 + }); + babelHelpers.defineProperty(this, "value", 1); + + _initProto(this); + } + + getA() { + return babelHelpers.classPrivateFieldGet(this, _a); + } + +} + +function _get_a() { + return _call_a(this); +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 3, "a", function () { + return this.value; + }]], []); + _call_a = ret[0]; + _initProto = ret[1]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/public/exec.js new file mode 100644 index 000000000000..22f52e96d4f2 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/public/exec.js @@ -0,0 +1,50 @@ +function dec(get, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function () { + return get.call(this) + 1; + } +} + +class Foo { + value = 1; + + @dec + get a() { + return this.value; + } + + @dec + get ['b']() { + return this.value; + } +} + +let foo = new Foo(); + +const aContext = foo['aContext']; +const bContext = foo['bContext']; + +expect(foo.a).toBe(2); +expect(foo.b).toBe(2); +foo.value = 123; +expect(foo.a).toBe(124); +expect(foo.b).toBe(124); + +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('getter'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('getter'); +expect(bContext.isStatic).toBe(false); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/public/input.js new file mode 100644 index 000000000000..9d1cbae52f1d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/public/input.js @@ -0,0 +1,13 @@ +class Foo { + value = 1; + + @dec + get a() { + return this.value; + } + + @dec + get ['b']() { + return this.value; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/public/output.js new file mode 100644 index 000000000000..0eaa0ea08bc5 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/public/output.js @@ -0,0 +1,27 @@ +var _computedKey, _dec, _dec2, _initProto; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + constructor(...args) { + babelHelpers.defineProperty(this, "value", 1); + + _initProto(this); + } + + get a() { + return this.value; + } + + get [_computedKey]() { + return this.value; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 3, "a"], [_dec2, 3, _computedKey]], []); + _initProto = ret[0]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-private/exec.js new file mode 100644 index 000000000000..7d1c8027d545 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-private/exec.js @@ -0,0 +1,38 @@ +function dec(get, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function () { + return get.call(this) + 1; + } +} + +class Foo { + static value = 1; + + @dec + static get #a() { + return this.value; + } + + static getA() { + return this.#a; + } +} + +const aContext = Foo['#aContext']; + +expect(aContext.access.get.call(Foo)).toBe(2); +expect(Foo.getA()).toBe(2); +Foo.value = 123; +expect(aContext.access.get.call(Foo)).toBe(124); +expect(Foo.getA()).toBe(124); + +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('getter'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-private/input.js new file mode 100644 index 000000000000..90edd26364d8 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-private/input.js @@ -0,0 +1,12 @@ +class Foo { + static value = 1; + + @dec + static get #a() { + return this.value; + } + + static getA() { + return this.#a; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-private/output.js new file mode 100644 index 000000000000..d042cefae18f --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-private/output.js @@ -0,0 +1,29 @@ +var _call_a, _initStatic; + +class Foo { + static getA() { + return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _a); + } + +} + +function _get_a() { + return _call_a(this); +} + +var _a = { + get: _get_a, + set: void 0 +}; + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 8, "a", function () { + return this.value; + }]], []); + _call_a = ret[0]; + _initStatic = ret[1]; + + _initStatic(Foo); +})(); + +babelHelpers.defineProperty(Foo, "value", 1); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-public/exec.js new file mode 100644 index 000000000000..94c7b9d5dab5 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-public/exec.js @@ -0,0 +1,48 @@ +function dec(get, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function () { + return get.call(this) + 1; + } +} + +class Foo { + static value = 1; + + @dec + static get a() { + return this.value; + } + + @dec + static get ['b']() { + return this.value; + } +} + +const aContext = Foo['aContext']; +const bContext = Foo['bContext']; + +expect(Foo.a).toBe(2); +expect(Foo.b).toBe(2); +Foo.value = 123; +expect(Foo.a).toBe(124); +expect(Foo.b).toBe(124); + +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('getter'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('getter'); +expect(bContext.isStatic).toBe(true); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-public/input.js new file mode 100644 index 000000000000..1383fa58abf4 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-public/input.js @@ -0,0 +1,13 @@ +class Foo { + static value = 1; + + @dec + static get a() { + return this.value; + } + + @dec + static get ['b']() { + return this.value; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-public/output.js new file mode 100644 index 000000000000..f0cb604d640e --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters/static-public/output.js @@ -0,0 +1,25 @@ +var _computedKey, _dec, _dec2, _initStatic; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + static get a() { + return this.value; + } + + static get [_computedKey]() { + return this.value; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 8, "a"], [_dec2, 8, _computedKey]], []); + _initStatic = ret[0]; + + _initStatic(Foo); +})(); + +babelHelpers.defineProperty(Foo, "value", 1); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/class/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/class/exec.js new file mode 100644 index 000000000000..2eaa3d1263b0 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/class/exec.js @@ -0,0 +1,10 @@ +const key = Symbol(); + +function dec(_, { setMetadata }) { + setMetadata(key, 123); +} + +@dec +class Foo {} + +expect(Foo[Symbol.metadata][key].constructor).toBe(123); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/getting-previously-set-metadata/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/getting-previously-set-metadata/exec.js new file mode 100644 index 000000000000..73eeed66ac57 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/getting-previously-set-metadata/exec.js @@ -0,0 +1,30 @@ +const key = Symbol(); + +function dec1(_, { setMetadata, getMetadata }) { + expect(getMetadata(key)).toBe(undefined); + setMetadata(key, 123); + expect(getMetadata(key)).toBe(123); +} + +function dec2(_, { setMetadata, getMetadata }) { + expect(getMetadata(key)).toBe(123); + setMetadata(key, 456); + expect(getMetadata(key)).toBe(456); +} + +class Foo { + @dec1 @dec2 a; +} + +function dec3(_, { setMetadata, getMetadata }) { + expect(getMetadata(key)).toBe(undefined); + setMetadata(key, 789); + expect(getMetadata(key)).toBe(789); +} + +class Bar extends Foo { + @dec3 a; +} + +expect(Foo.prototype[Symbol.metadata][key].public.a).toBe(456); +expect(Bar.prototype[Symbol.metadata][key].public.a).toBe(789); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/inheritance-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/inheritance-private/exec.js new file mode 100644 index 000000000000..d36a857a1e77 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/inheritance-private/exec.js @@ -0,0 +1,16 @@ +const key = Symbol(); + +function dec(_, { setMetadata }) { + setMetadata(key, 123); +} + +class Foo { + @dec #a; +} + +class Bar extends Foo { + @dec #b; +} + +expect(Foo.prototype[Symbol.metadata][key].private).toEqual([123]); +expect(Bar.prototype[Symbol.metadata][key].private).toEqual([123, 123]); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/inheritance-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/inheritance-public/exec.js new file mode 100644 index 000000000000..666bc9601116 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/inheritance-public/exec.js @@ -0,0 +1,18 @@ +const key = Symbol(); + +function dec(_, { setMetadata }) { + setMetadata(key, 123); +} + +class Foo { + @dec a; +} + +class Bar extends Foo { + @dec b; +} + +expect(Foo.prototype[Symbol.metadata][key].public.a).toEqual(123); +expect(Foo.prototype[Symbol.metadata][key].public.b).toEqual(undefined); +expect(Bar.prototype[Symbol.metadata][key].public.a).toEqual(123); +expect(Bar.prototype[Symbol.metadata][key].public.b).toEqual(123); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/non-symbol-keys/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/non-symbol-keys/exec.js new file mode 100644 index 000000000000..a6c8ae1af6f8 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/non-symbol-keys/exec.js @@ -0,0 +1,10 @@ +expect(() => { + const key = 'test'; + + function dec(_, { setMetadata }) { + setMetadata(key, 123); + } + + @dec + class Foo {} +}).toThrow('Metadata keys must be symbols, received: test') diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/proto-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/proto-private/exec.js new file mode 100644 index 000000000000..a10baeb36f72 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/proto-private/exec.js @@ -0,0 +1,11 @@ +const key = Symbol(); + +function dec(_, { setMetadata }) { + setMetadata(key, 123); +} + +class Foo { + @dec #a; +} + +expect(Foo.prototype[Symbol.metadata][key].private[0]).toBe(123); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/proto-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/proto-public/exec.js new file mode 100644 index 000000000000..021bdaf9a5e0 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/proto-public/exec.js @@ -0,0 +1,11 @@ +const key = Symbol(); + +function dec(_, { setMetadata }) { + setMetadata(key, 123); +} + +class Foo { + @dec a; +} + +expect(Foo.prototype[Symbol.metadata][key].public.a).toBe(123); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/static-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/static-private/exec.js new file mode 100644 index 000000000000..c8453c1559ce --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/static-private/exec.js @@ -0,0 +1,11 @@ +const key = Symbol(); + +function dec(_, { setMetadata }) { + setMetadata(key, 123); +} + +class Foo { + @dec static #a; +} + +expect(Foo[Symbol.metadata][key].private[0]).toBe(123); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/static-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/static-public/exec.js new file mode 100644 index 000000000000..1635eab50b54 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-metadata/static-public/exec.js @@ -0,0 +1,11 @@ +const key = Symbol(); + +function dec(_, { setMetadata }) { + setMetadata(key, 123); +} + +class Foo { + @dec static a; +} + +expect(Foo[Symbol.metadata][key].public.a).toBe(123); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/private/exec.js new file mode 100644 index 000000000000..5a3ce1785ff0 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/private/exec.js @@ -0,0 +1,41 @@ +function dec(fn, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function () { + return fn.call(this) + 1; + } +} + +class Foo { + value = 1; + + @dec + #a() { + return this.value; + } + + callA() { + return this.#a(); + } +} + +let foo = new Foo(); + +const aContext = foo['#aContext']; + +// First call gets the method, second call calls the method with correct `this` +expect(aContext.access.get.call(foo).call(foo)).toBe(2); +expect(foo.callA()).toBe(2); +foo.value = 123; +expect(aContext.access.get.call(foo).call(foo)).toBe(124); +expect(foo.callA()).toBe(124); + +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('method'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/private/input.js new file mode 100644 index 000000000000..fc7ace8128ee --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/private/input.js @@ -0,0 +1,12 @@ +class Foo { + value = 1; + + @dec + #a() { + return this.value; + } + + callA() { + return this.#a(); + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/private/output.js new file mode 100644 index 000000000000..fe401b31bcaa --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/private/output.js @@ -0,0 +1,29 @@ +var _call_a, _initProto; + +var _a = /*#__PURE__*/new WeakSet(); + +class Foo { + constructor(..._args) { + babelHelpers.classPrivateMethodInitSpec(this, _a); + babelHelpers.defineProperty(this, "value", 1); + + _initProto(this); + } + + callA() { + return babelHelpers.classPrivateMethodGet(this, _a, _a2).call(this); + } + +} + +function _a2(...args) { + return _call_a(this, ...args); +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 2, "a", function () { + return this.value; + }]], []); + _call_a = ret[0]; + _initProto = ret[1]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/public/exec.js new file mode 100644 index 000000000000..0f27b61caa4d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/public/exec.js @@ -0,0 +1,50 @@ +function dec(fn, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function () { + return fn.call(this) + 1; + } +} + +class Foo { + value = 1; + + @dec + a() { + return this.value; + } + + @dec + ['b']() { + return this.value; + } +} + +let foo = new Foo(); + +const aContext = foo['aContext']; +const bContext = foo['bContext']; + +expect(foo.a()).toBe(2); +expect(foo.b()).toBe(2); +foo.value = 123; +expect(foo.a()).toBe(124); +expect(foo.b()).toBe(124); + +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('method'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('method'); +expect(bContext.isStatic).toBe(false); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/public/input.js new file mode 100644 index 000000000000..f364442146ea --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/public/input.js @@ -0,0 +1,13 @@ +class Foo { + value = 1; + + @dec + a() { + return this.value; + } + + @dec + ['b']() { + return this.value; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/public/output.js new file mode 100644 index 000000000000..8e37ce0d2b78 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/public/output.js @@ -0,0 +1,27 @@ +var _computedKey, _dec, _dec2, _initProto; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + constructor(...args) { + babelHelpers.defineProperty(this, "value", 1); + + _initProto(this); + } + + a() { + return this.value; + } + + [_computedKey]() { + return this.value; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 2, "a"], [_dec2, 2, _computedKey]], []); + _initProto = ret[0]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-private/exec.js new file mode 100644 index 000000000000..bab58275b48a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-private/exec.js @@ -0,0 +1,39 @@ +function dec(fn, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function () { + return fn.call(this) + 1; + } +} + +class Foo { + static value = 1; + + @dec + static #a() { + return this.value; + } + + static callA() { + return this.#a(); + } +} + +const aContext = Foo['#aContext']; + +// First call gets the method, second call calls the method with correct `this` +expect(aContext.access.get.call(Foo).call(Foo)).toBe(2); +expect(Foo.callA()).toBe(2); +Foo.value = 123; +expect(aContext.access.get.call(Foo).call(Foo)).toBe(124); +expect(Foo.callA()).toBe(124); + +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('method'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-private/input.js new file mode 100644 index 000000000000..e68191455f14 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-private/input.js @@ -0,0 +1,12 @@ +class Foo { + static value = 1; + + @dec + static #a() { + return this.value; + } + + static callA() { + return this.#a(); + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-private/output.js new file mode 100644 index 000000000000..066d49a1812b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-private/output.js @@ -0,0 +1,24 @@ +var _call_a, _initStatic; + +class Foo { + static callA() { + return babelHelpers.classStaticPrivateMethodGet(this, Foo, _a).call(this); + } + +} + +function _a(...args) { + return _call_a(this, ...args); +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 7, "a", function () { + return this.value; + }]], []); + _call_a = ret[0]; + _initStatic = ret[1]; + + _initStatic(Foo); +})(); + +babelHelpers.defineProperty(Foo, "value", 1); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-public/exec.js new file mode 100644 index 000000000000..e68458db59d9 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-public/exec.js @@ -0,0 +1,48 @@ +function dec(fn, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function () { + return fn.call(this) + 1; + } +} + +class Foo { + static value = 1; + + @dec + static a() { + return this.value; + } + + @dec + static ['b']() { + return this.value; + } +} + +const aContext = Foo['aContext']; +const bContext = Foo['bContext']; + +expect(Foo.a()).toBe(2); +expect(Foo.b()).toBe(2); +Foo.value = 123; +expect(Foo.a()).toBe(124); +expect(Foo.b()).toBe(124); + +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('method'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('method'); +expect(bContext.isStatic).toBe(true); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-public/input.js new file mode 100644 index 000000000000..77dae8711cd3 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-public/input.js @@ -0,0 +1,13 @@ +class Foo { + static value = 1; + + @dec + static a() { + return this.value; + } + + @dec + static ['b']() { + return this.value; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-public/output.js new file mode 100644 index 000000000000..7b210ccadb01 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-methods/static-public/output.js @@ -0,0 +1,25 @@ +var _computedKey, _dec, _dec2, _initStatic; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + static a() { + return this.value; + } + + static [_computedKey]() { + return this.value; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 7, "a"], [_dec2, 7, _computedKey]], []); + _initStatic = ret[0]; + + _initStatic(Foo); +})(); + +babelHelpers.defineProperty(Foo, "value", 1); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/initializer-timing/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/initializer-timing/exec.js new file mode 100644 index 000000000000..ac5920dcd16a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/initializer-timing/exec.js @@ -0,0 +1,34 @@ +function dec1(fn, context) { + context.addInitializer((instance) => { + expect(instance.value).toBe(undefined); + }); + + return fn; +} + +class Foo { + value = 1; + + @dec1 + foo() {} +} + +function dec2(fn, context) { + context.addInitializer((instance) => { + expect(instance.value).toBe(1); + }); + + return fn; +} + + +class Bar extends Foo { + constructor() { + super(); + + this.value = 2; + } + + @dec2 + bar() {} +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/valid-expression-formats/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/valid-expression-formats/input.js new file mode 100644 index 000000000000..844a924e3e80 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/valid-expression-formats/input.js @@ -0,0 +1,22 @@ +@dec +@call() +@chain.expr() +@(arbitrary + expr) +@(array[expr]) +class Foo { + #a; + + @dec + @call() + @chain.expr() + @(arbitrary + expr) + @(array[expr]) + method() {} + + makeClass() { + return class Nested { + @(this.#a) + bar; + } + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/valid-expression-formats/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/valid-expression-formats/output.js new file mode 100644 index 000000000000..c7e843e7728f --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-misc/valid-expression-formats/output.js @@ -0,0 +1,44 @@ +var _initProto, _initClass; + +let _Foo; + +var _a = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor(...args) { + babelHelpers.classPrivateFieldInitSpec(this, _a, { + writable: true, + value: void 0 + }); + + _initProto(this); + } + + method() {} + + makeClass() { + var _init_bar, _class, _temp; + + return _temp = _class = class Nested { + constructor() { + babelHelpers.defineProperty(this, "bar", _init_bar(this)); + } + + }, (() => { + let ret = babelHelpers.applyDecs(_class, [[babelHelpers.classPrivateFieldGet(_class, _a), 0, "bar"]], []); + _init_bar = ret[0]; + })(), _temp; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[[dec, call(), chain.expr(), arbitrary + expr, array[expr]], 2, "method"]], [dec, call(), chain.expr(), arbitrary + expr, array[expr]]); + _initProto = ret[0]; + _Foo = ret[1]; + _initClass = ret[2]; +})(); + +(() => { + _initClass(); +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/options.json new file mode 100644 index 000000000000..69f3e599cf2d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ], + "proposal-class-properties", + "proposal-private-methods", + "proposal-class-static-block" + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/private/exec.js new file mode 100644 index 000000000000..c2768a0a2c67 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/private/exec.js @@ -0,0 +1,40 @@ +function dec(set, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function (v) { + return set.call(this, v + 1); + } +} + +class Foo { + value = 1; + + @dec + set #a(v) { + return this.value = v; + } + + setA(v) { + this.#a = v; + } +} + +let foo = new Foo(); + +const aContext = foo['#aContext']; + +expect(foo.value).toBe(1); +aContext.access.set.call(foo, 123); +expect(foo.value).toBe(124); +foo.setA(456); +expect(foo.value).toBe(457); + +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('setter'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/private/input.js new file mode 100644 index 000000000000..254f2f102f9a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/private/input.js @@ -0,0 +1,12 @@ +class Foo { + value = 1; + + @dec + set #a(v) { + return this.value = v; + } + + setA(v) { + this.#a = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/private/output.js new file mode 100644 index 000000000000..695c7be68cf4 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/private/output.js @@ -0,0 +1,32 @@ +var _call_a, _initProto; + +var _a = /*#__PURE__*/new WeakMap(); + +class Foo { + constructor(...args) { + babelHelpers.classPrivateFieldInitSpec(this, _a, { + get: void 0, + set: _set_a + }); + babelHelpers.defineProperty(this, "value", 1); + + _initProto(this); + } + + setA(v) { + babelHelpers.classPrivateFieldSet(this, _a, v); + } + +} + +function _set_a(v) { + _call_a(this, v); +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 4, "a", function (v) { + return this.value = v; + }]], []); + _call_a = ret[0]; + _initProto = ret[1]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/public/exec.js new file mode 100644 index 000000000000..ab2f98534b95 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/public/exec.js @@ -0,0 +1,50 @@ +function dec(set, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function (v) { + return set.call(this, v + 1); + } +} + +class Foo { + value = 1; + + @dec + set a(v) { + return this.value = v; + } + + @dec + set ['b'](v) { + return this.value = v; + } +} + +let foo = new Foo(); + +const aContext = foo['aContext']; +const bContext = foo['bContext']; + +expect(foo.value).toBe(1); +foo.a = 123; +expect(foo.value).toBe(124); +foo.a = 456; +expect(foo.value).toBe(457); + +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('setter'); +expect(aContext.isStatic).toBe(false); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('setter'); +expect(bContext.isStatic).toBe(false); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/public/input.js new file mode 100644 index 000000000000..b8b837257ff0 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/public/input.js @@ -0,0 +1,13 @@ +class Foo { + value = 1; + + @dec + set a(v) { + return this.value = v; + } + + @dec + set ['b'](v) { + return this.value = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/public/output.js new file mode 100644 index 000000000000..8bad20b4287d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/public/output.js @@ -0,0 +1,27 @@ +var _computedKey, _dec, _dec2, _initProto; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + constructor(...args) { + babelHelpers.defineProperty(this, "value", 1); + + _initProto(this); + } + + set a(v) { + return this.value = v; + } + + set [_computedKey](v) { + return this.value = v; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 4, "a"], [_dec2, 4, _computedKey]], []); + _initProto = ret[0]; +})(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-private/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-private/exec.js new file mode 100644 index 000000000000..55ecade3ac96 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-private/exec.js @@ -0,0 +1,38 @@ +function dec(set, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function (v) { + return set.call(this, v + 1); + } +} + +class Foo { + static value = 1; + + @dec + static set #a(v) { + return this.value = v; + } + + static setA(v) { + this.#a = v; + } +} + +const aContext = Foo['#aContext']; + +expect(Foo.value).toBe(1); +aContext.access.set.call(Foo, 123); +expect(Foo.value).toBe(124); +Foo.setA(456); +expect(Foo.value).toBe(457); + +expect(aContext.name).toBe('#a'); +expect(aContext.kind).toBe('setter'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(true); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-private/input.js new file mode 100644 index 000000000000..0038d6b6bd30 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-private/input.js @@ -0,0 +1,12 @@ +class Foo { + static value = 1; + + @dec + static set #a(v) { + return this.value = v; + } + + static setA(v) { + this.#a = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-private/output.js new file mode 100644 index 000000000000..85131b4f3bb3 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-private/output.js @@ -0,0 +1,29 @@ +var _call_a, _initStatic; + +class Foo { + static setA(v) { + babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _a, v); + } + +} + +function _set_a(v) { + _call_a(this, v); +} + +var _a = { + get: void 0, + set: _set_a +}; + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[dec, 9, "a", function (v) { + return this.value = v; + }]], []); + _call_a = ret[0]; + _initStatic = ret[1]; + + _initStatic(Foo); +})(); + +babelHelpers.defineProperty(Foo, "value", 1); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-public/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-public/exec.js new file mode 100644 index 000000000000..2e7eb639048c --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-public/exec.js @@ -0,0 +1,49 @@ +function dec(set, context) { + context.addInitializer((instance) => { + instance[context.name + 'Context'] = context; + }); + + return function (v) { + return set.call(this, v + 1); + } +} + +class Foo { + static value = 1; + + @dec + static set a(v) { + return this.value = v; + } + + @dec + static set ['b'](v) { + return this.value = v; + } +} + +const aContext = Foo['aContext']; +const bContext = Foo['bContext']; + + +expect(Foo.value).toBe(1); +Foo.a = 123; +expect(Foo.value).toBe(124); +Foo.a = 456; +expect(Foo.value).toBe(457); + +expect(aContext.name).toBe('a'); +expect(aContext.kind).toBe('setter'); +expect(aContext.isStatic).toBe(true); +expect(aContext.isPrivate).toBe(false); +expect(typeof aContext.addInitializer).toBe('function'); +expect(typeof aContext.setMetadata).toBe('function'); +expect(typeof aContext.getMetadata).toBe('function'); + +expect(bContext.name).toBe('b'); +expect(bContext.kind).toBe('setter'); +expect(bContext.isStatic).toBe(true); +expect(bContext.isPrivate).toBe(false); +expect(typeof bContext.addInitializer).toBe('function'); +expect(typeof bContext.setMetadata).toBe('function'); +expect(typeof bContext.getMetadata).toBe('function'); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-public/input.js new file mode 100644 index 000000000000..0cca65be7fa3 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-public/input.js @@ -0,0 +1,13 @@ +class Foo { + static value = 1; + + @dec + static set a(v) { + return this.value = v; + } + + @dec + static set ['b'](v) { + return this.value = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-public/output.js new file mode 100644 index 000000000000..ffa0e29f537e --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-setters/static-public/output.js @@ -0,0 +1,25 @@ +var _computedKey, _dec, _dec2, _initStatic; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + static set a(v) { + return this.value = v; + } + + static set [_computedKey](v) { + return this.value = v; + } + +} + +(() => { + let ret = babelHelpers.applyDecs(Foo, [[_dec, 9, "a"], [_dec2, 9, _computedKey]], []); + _initStatic = ret[0]; + + _initStatic(Foo); +})(); + +babelHelpers.defineProperty(Foo, "value", 1); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/options.json new file mode 100644 index 000000000000..18aa205580db --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ] + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/private/input.js new file mode 100644 index 000000000000..be4f348923bc --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/private/input.js @@ -0,0 +1,7 @@ +class Foo { + @dec + accessor #a; + + @dec + accessor #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/private/output.js new file mode 100644 index 000000000000..7b60ca77fcf4 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/private/output.js @@ -0,0 +1,42 @@ +var _init_a, _get_a, _set_a, _init_b, _get_b, _set_b, _initProto; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 1, "a", function () { + return this.#A; + }, function (value) { + this.#A = value; + }], [dec, 1, "b", function () { + return this.#B; + }, function (value) { + this.#B = value; + }]], []); + _init_a = ret[0]; + _get_a = ret[1]; + _set_a = ret[2]; + _init_b = ret[3]; + _get_b = ret[4]; + _set_b = ret[5]; + _initProto = ret[6]; + } + #A = (_initProto(this), _init_a(this)); + + set #a(v) { + _set_a(this, v); + } + + get #a() { + _get_a(this); + } + + #B = _init_b(this, 123); + + set #b(v) { + _set_b(this, v); + } + + get #b() { + _get_b(this); + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/public/input.js new file mode 100644 index 000000000000..5945d3196f1d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/public/input.js @@ -0,0 +1,10 @@ +class Foo { + @dec + accessor a; + + @dec + accessor b = 123; + + @dec + accessor ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/public/output.js new file mode 100644 index 000000000000..2c3c5093a868 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/public/output.js @@ -0,0 +1,46 @@ +var _init_a, _init_b, _computedKey, _init_computedKey, _dec, _dec2, _dec3, _initProto; + +_dec = dec +_dec2 = dec +_computedKey = 'c' +_dec3 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 1, "a"], [_dec2, 1, "b"], [_dec3, 1, _computedKey]], []); + _init_a = ret[0]; + _init_b = ret[1]; + _init_computedKey = ret[2]; + _initProto = ret[3]; + } + #A = (_initProto(this), _init_a(this)); + + get a() { + return this.#A; + } + + set a(v) { + this.#A = v; + } + + #B = _init_b(this, 123); + + get b() { + return this.#B; + } + + set b(v) { + this.#B = v; + } + + #C = _init_computedKey(this, 456); + + get [_computedKey]() { + return this.#C; + } + + set [_computedKey](v) { + this.#C = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-private/input.js new file mode 100644 index 000000000000..ebb88a741572 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-private/input.js @@ -0,0 +1,7 @@ +class Foo { + @dec + static accessor #a; + + @dec + static accessor #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-private/output.js new file mode 100644 index 000000000000..8e64fa883507 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-private/output.js @@ -0,0 +1,45 @@ +var _init_a, _get_a, _set_a, _init_b, _get_b, _set_b, _initStatic; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 6, "a", function () { + return this.#A; + }, function (value) { + this.#A = value; + }], [dec, 6, "b", function () { + return this.#B; + }, function (value) { + this.#B = value; + }]], []); + _init_a = ret[0]; + _get_a = ret[1]; + _set_a = ret[2]; + _init_b = ret[3]; + _get_b = ret[4]; + _set_b = ret[5]; + _initStatic = ret[6]; + + _initStatic(this); + + } + static #A = _init_a(this); + + set #a(v) { + _set_a(this, v); + } + + get #a() { + _get_a(this); + } + + static #B = _init_b(this, 123); + + set #b(v) { + _set_b(this, v); + } + + get #b() { + _get_b(this); + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-public/input.js new file mode 100644 index 000000000000..edf06478601f --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-public/input.js @@ -0,0 +1,10 @@ +class Foo { + @dec + static accessor a; + + @dec + static accessor b = 123; + + @dec + static accessor ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-public/output.js new file mode 100644 index 000000000000..27738b418076 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/static-public/output.js @@ -0,0 +1,49 @@ +var _init_a, _init_b, _computedKey, _init_computedKey, _dec, _dec2, _dec3, _initStatic; + +_dec = dec +_dec2 = dec +_computedKey = 'c' +_dec3 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 6, "a"], [_dec2, 6, "b"], [_dec3, 6, _computedKey]], []); + _init_a = ret[0]; + _init_b = ret[1]; + _init_computedKey = ret[2]; + _initStatic = ret[3]; + + _initStatic(this); + + } + static #A = _init_a(this); + + static get a() { + return this.#A; + } + + static set a(v) { + this.#A = v; + } + + static #B = _init_b(this, 123); + + static get b() { + return this.#B; + } + + static set b(v) { + this.#B = v; + } + + static #C = _init_computedKey(this, 456); + + static get [_computedKey]() { + return this.#C; + } + + static set [_computedKey](v) { + this.#C = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-private/input.js new file mode 100644 index 000000000000..4afc45261337 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-private/input.js @@ -0,0 +1,5 @@ +class Foo { + accessor #a; + + accessor #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-private/output.js new file mode 100644 index 000000000000..9eb7268e4131 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-private/output.js @@ -0,0 +1,22 @@ +class Foo { + #A; + + get #a() { + return this.#A; + } + + set #a(v) { + this.#A = v; + } + + #B = 123; + + get #b() { + return this.#B; + } + + set #b(v) { + this.#B = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-public/input.js new file mode 100644 index 000000000000..ad27f18d5ed3 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-public/input.js @@ -0,0 +1,7 @@ +class Foo { + accessor a; + + accessor b = 123; + + accessor ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-public/output.js new file mode 100644 index 000000000000..f6269be736f1 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-public/output.js @@ -0,0 +1,32 @@ +class Foo { + #A; + + get a() { + return this.#A; + } + + set a(v) { + this.#A = v; + } + + #B = 123; + + get b() { + return this.#B; + } + + set b(v) { + this.#B = v; + } + + #C = 456; + + get 'c'() { + return this.#C; + } + + set 'c'(v) { + this.#C = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-private/input.js new file mode 100644 index 000000000000..2e516a961de9 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-private/input.js @@ -0,0 +1,5 @@ +class Foo { + static accessor #a; + + static accessor #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-private/output.js new file mode 100644 index 000000000000..04cc0ef030d0 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-private/output.js @@ -0,0 +1,22 @@ +class Foo { + static #A; + + static get #a() { + return this.#A; + } + + static set #a(v) { + this.#A = v; + } + + static #B = 123; + + static get #b() { + return this.#B; + } + + static set #b(v) { + this.#B = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-public/input.js new file mode 100644 index 000000000000..160e72cd531c --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-public/input.js @@ -0,0 +1,7 @@ +class Foo { + static accessor a; + + static accessor b = 123; + + static accessor ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-public/output.js new file mode 100644 index 000000000000..187ad5214a67 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-accessors/undecorated-static-public/output.js @@ -0,0 +1,32 @@ +class Foo { + static #A; + + static get a() { + return this.#A; + } + + static set a(v) { + this.#A = v; + } + + static #B = 123; + + static get b() { + return this.#B; + } + + static set b(v) { + this.#B = v; + } + + static #C = 456; + + static get 'c'() { + return this.#C; + } + + static set 'c'(v) { + this.#C = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/expressions/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/expressions/input.js new file mode 100644 index 000000000000..542bf870c079 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/expressions/input.js @@ -0,0 +1,11 @@ +const A = @dec class A {} +const B = @dec class C {} +const D = @dec class {} +const E = (@dec class {}, 123); +const F = [@dec class G {}, @dec class {}]; +const H = @dec class extends I {}; +const J = @dec class K extends L {}; + +function classFactory() { + return @dec class {} +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/expressions/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/expressions/output.js new file mode 100644 index 000000000000..1ee87380900b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/expressions/output.js @@ -0,0 +1,105 @@ +var _initClass, _A, _initClass2, _C, _initClass3, _D, _initClass4, _decorated_class, _initClass5, _G, _initClass6, _decorated_class2, _initClass7, _H, _initClass8, _K; + +const A = (class A { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _A = ret[0]; + _initClass = ret[1]; + } + static { + _initClass(); + + } +}, _A); +const B = (class C { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _C = ret[0]; + _initClass2 = ret[1]; + } + static { + _initClass2(); + + } +}, _C); +const D = (class D { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _D = ret[0]; + _initClass3 = ret[1]; + } + static { + _initClass3(); + + } +}, _D); +const E = ((class { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _decorated_class = ret[0]; + _initClass4 = ret[1]; + } + static { + _initClass4(); + + } +}, _decorated_class), 123); +const F = [(class G { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _G = ret[0]; + _initClass5 = ret[1]; + } + static { + _initClass5(); + + } +}, _G), (class { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _decorated_class2 = ret[0]; + _initClass6 = ret[1]; + } + static { + _initClass6(); + + } +}, _decorated_class2)]; +const H = (class H extends I { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _H = ret[0]; + _initClass7 = ret[1]; + } + static { + _initClass7(); + + } +}, _H); +const J = (class K extends L { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _K = ret[0]; + _initClass8 = ret[1]; + } + static { + _initClass8(); + + } +}, _K); + +function classFactory() { + var _initClass9, _decorated_class3; + + return class { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _decorated_class3 = ret[0]; + _initClass9 = ret[1]; + } + static { + _initClass9(); + + } + }, _decorated_class3; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/inheritance/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/inheritance/input.js new file mode 100644 index 000000000000..7a4a6684555a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/inheritance/input.js @@ -0,0 +1,5 @@ +@dec1 +class Bar {} + +@dec2 +class Foo extends Bar {} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/inheritance/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/inheritance/output.js new file mode 100644 index 000000000000..6217a56fe9d5 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/inheritance/output.js @@ -0,0 +1,29 @@ +var _initClass, _initClass2; + +let _Bar; + +class Bar { + static { + let ret = babelHelpers.applyDecs(this, [], [dec1]); + _Bar = ret[0]; + _initClass = ret[1]; + } + static { + _initClass(); + + } +} + +let _Foo; + +class Foo extends _Bar { + static { + let ret = babelHelpers.applyDecs(this, [], [dec2]); + _Foo = ret[0]; + _initClass2 = ret[1]; + } + static { + _initClass2(); + + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/initializers/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/initializers/input.js new file mode 100644 index 000000000000..deeb483448f7 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/initializers/input.js @@ -0,0 +1,13 @@ +@dec +class Foo { + static field = 123; +} + +@dec +class Bar extends Foo { + static { + this.otherField = 456; + } + + static field = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/initializers/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/initializers/output.js new file mode 100644 index 000000000000..18c2186d6823 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/initializers/output.js @@ -0,0 +1,34 @@ +var _initClass, _initClass2; + +let _Foo; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _Foo = ret[0]; + _initClass = ret[1]; + } + static field = 123; + static { + _initClass(); + + } +} + +let _Bar; + +class Bar extends _Foo { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _Bar = ret[0]; + _initClass2 = ret[1]; + } + static { + this.otherField = 456; + } + static field = 123; + static { + _initClass2(); + + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/options.json new file mode 100644 index 000000000000..18aa205580db --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ] + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement-with-expr/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement-with-expr/input.js new file mode 100644 index 000000000000..fde7feb1abd7 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement-with-expr/input.js @@ -0,0 +1,6 @@ +const Foo = @dec class Bar { + bar = new Bar(); +}; + +const foo = new Foo(); + diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement-with-expr/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement-with-expr/output.js new file mode 100644 index 000000000000..c4bf6c7a951a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement-with-expr/output.js @@ -0,0 +1,15 @@ +var _initClass, _Bar; + +const Foo = (class Bar { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _Bar = ret[0]; + _initClass = ret[1]; + } + bar = new _Bar(); + static { + _initClass(); + + } +}, _Bar); +const foo = new Foo(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement/input.js new file mode 100644 index 000000000000..e6da5000db62 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement/input.js @@ -0,0 +1,6 @@ +@dec +class Foo { + static foo = new Foo(); +} + +const foo = new Foo(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement/output.js new file mode 100644 index 000000000000..ade4fc8b1fc8 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-classes/replacement/output.js @@ -0,0 +1,18 @@ +var _initClass; + +let _Foo; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [], [dec]); + _Foo = ret[0]; + _initClass = ret[1]; + } + static foo = new _Foo(); + static { + _initClass(); + + } +} + +const foo = new _Foo(); diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-ast/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-ast/input.js new file mode 100644 index 000000000000..2ca438188867 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-ast/input.js @@ -0,0 +1,11 @@ +class Foo { + @dec + [getKey()]() { + return 1; + } + + @dec + [getKey()]() { + return 2; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-ast/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-ast/output.js new file mode 100644 index 000000000000..e6fec9cb1913 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-ast/output.js @@ -0,0 +1,26 @@ +var _computedKey, _computedKey2, _dec, _dec2, _initProto; + +_computedKey = getKey() +_dec = dec +_computedKey2 = getKey() +_dec2 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 2, _computedKey], [_dec2, 2, _computedKey2]], []); + _initProto = ret[0]; + } + + constructor(...args) { + _initProto(this); + } + + [_computedKey]() { + return 1; + } + + [_computedKey2]() { + return 2; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-value/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-value/input.js new file mode 100644 index 000000000000..8aeb57759b76 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-value/input.js @@ -0,0 +1,11 @@ +class Foo { + @dec + [getKeyI()]() { + return 1; + } + + @dec + [getKeyJ()]() { + return 2; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-value/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-value/output.js new file mode 100644 index 000000000000..eff8d4e46495 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/computed-keys-same-value/output.js @@ -0,0 +1,26 @@ +var _computedKey, _computedKey2, _dec, _dec2, _initProto; + +_computedKey = getKeyI() +_dec = dec +_computedKey2 = getKeyJ() +_dec2 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 2, _computedKey], [_dec2, 2, _computedKey2]], []); + _initProto = ret[0]; + } + + constructor(...args) { + _initProto(this); + } + + [_computedKey]() { + return 1; + } + + [_computedKey2]() { + return 2; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/method-and-field/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/method-and-field/input.js new file mode 100644 index 000000000000..522da0061204 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/method-and-field/input.js @@ -0,0 +1,9 @@ +class Foo { + @dec + a = 123; + + @dec + a() { + return 1; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/method-and-field/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/method-and-field/output.js new file mode 100644 index 000000000000..7496a3ed5593 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/method-and-field/output.js @@ -0,0 +1,15 @@ +var _init_a, _initProto; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 0, "a"], [dec, 2, "a"]], []); + _init_a = ret[0]; + _initProto = ret[1]; + } + a = (_initProto(this), _init_a(this, 123)); + + a() { + return 1; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/methods-with-same-key/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/methods-with-same-key/input.js new file mode 100644 index 000000000000..db90a40aa67b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/methods-with-same-key/input.js @@ -0,0 +1,11 @@ +class Foo { + @dec + a() { + return 1; + } + + @dec + a() { + return 2; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/methods-with-same-key/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/methods-with-same-key/output.js new file mode 100644 index 000000000000..5bdf7d033a97 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/methods-with-same-key/output.js @@ -0,0 +1,21 @@ +var _initProto; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 2, "a"], [dec, 2, "a"]], []); + _initProto = ret[0]; + } + + constructor(...args) { + _initProto(this); + } + + a() { + return 1; + } + + a() { + return 2; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/options.json new file mode 100644 index 000000000000..18aa205580db --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-duplicated-keys/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ] + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/options.json new file mode 100644 index 000000000000..18aa205580db --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ] + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/private/input.js new file mode 100644 index 000000000000..222ec09fc95e --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/private/input.js @@ -0,0 +1,7 @@ +class Foo { + @dec + #a; + + @dec + #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/private/output.js new file mode 100644 index 000000000000..07e4a6ebdd53 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/private/output.js @@ -0,0 +1,19 @@ +var _init_a, _init_b; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 0, "a", function () { + return this.#a; + }, function (value) { + this.#a = value; + }], [dec, 0, "b", function () { + return this.#b; + }, function (value) { + this.#b = value; + }]], []); + _init_a = ret[0]; + _init_b = ret[1]; + } + #a = _init_a(this); + #b = _init_b(this, 123); +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/public/input.js new file mode 100644 index 000000000000..8dff95c99a3a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/public/input.js @@ -0,0 +1,10 @@ +class Foo { + @dec + a; + + @dec + b = 123; + + @dec + ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/public/output.js new file mode 100644 index 000000000000..2c7b73d3df0b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/public/output.js @@ -0,0 +1,18 @@ +var _init_a, _init_b, _computedKey, _init_computedKey, _dec, _dec2, _dec3; + +_dec = dec +_dec2 = dec +_computedKey = 'c' +_dec3 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 0, "a"], [_dec2, 0, "b"], [_dec3, 0, _computedKey]], []); + _init_a = ret[0]; + _init_b = ret[1]; + _init_computedKey = ret[2]; + } + a = _init_a(this); + b = _init_b(this, 123); + [_computedKey] = _init_computedKey(this, 456); +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-private/input.js new file mode 100644 index 000000000000..830d82321863 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-private/input.js @@ -0,0 +1,7 @@ +class Foo { + @dec + static #a; + + @dec + static #b = 123; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-private/output.js new file mode 100644 index 000000000000..10ea3f8f997c --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-private/output.js @@ -0,0 +1,19 @@ +var _init_a, _init_b; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 5, "a", function () { + return this.#a; + }, function (value) { + this.#a = value; + }], [dec, 5, "b", function () { + return this.#b; + }, function (value) { + this.#b = value; + }]], []); + _init_a = ret[0]; + _init_b = ret[1]; + } + static #a = _init_a(this); + static #b = _init_b(this, 123); +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-public/input.js new file mode 100644 index 000000000000..9b9dae98314a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-public/input.js @@ -0,0 +1,10 @@ +class Foo { + @dec + static a; + + @dec + static b = 123; + + @dec + static ['c'] = 456; +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-public/output.js new file mode 100644 index 000000000000..9acf131a0e7f --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-fields/static-public/output.js @@ -0,0 +1,18 @@ +var _init_a, _init_b, _computedKey, _init_computedKey, _dec, _dec2, _dec3; + +_dec = dec +_dec2 = dec +_computedKey = 'c' +_dec3 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 5, "a"], [_dec2, 5, "b"], [_dec3, 5, _computedKey]], []); + _init_a = ret[0]; + _init_b = ret[1]; + _init_computedKey = ret[2]; + } + static a = _init_a(this); + static b = _init_b(this, 123); + static [_computedKey] = _init_computedKey(this, 456); +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/options.json new file mode 100644 index 000000000000..18aa205580db --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ] + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/private/input.js new file mode 100644 index 000000000000..060ae225a21e --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/private/input.js @@ -0,0 +1,21 @@ +class Foo { + value = 1; + + @dec + get #a() { + return this.value; + } + + @dec + set #a(v) { + this.value = v; + } + + getA() { + return this.#a; + } + + setA(v) { + this.#a = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/private/output.js new file mode 100644 index 000000000000..d7d5b6d6f492 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/private/output.js @@ -0,0 +1,37 @@ +var _call_a, _call_a2, _initProto; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 3, "a", function () { + return this.value; + }], [dec, 4, "a", function (v) { + this.value = v; + }]], []); + _call_a = ret[0]; + _call_a2 = ret[1]; + _initProto = ret[2]; + } + + constructor(...args) { + _initProto(this); + } + + value = 1; + + get #a() { + return _call_a(this); + } + + set #a(v) { + _call_a2(this, v); + } + + getA() { + return this.#a; + } + + setA(v) { + this.#a = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/public/input.js new file mode 100644 index 000000000000..ef384166d689 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/public/input.js @@ -0,0 +1,23 @@ +class Foo { + value = 1; + + @dec + get a() { + return this.value; + } + + @dec + set a(v) { + this.value = v; + } + + @dec + get ['b']() { + return this.value; + } + + @dec + set ['b'](v) { + this.value = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/public/output.js new file mode 100644 index 000000000000..528ceb3e2f30 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/public/output.js @@ -0,0 +1,38 @@ +var _computedKey, _computedKey2, _dec, _dec2, _dec3, _dec4, _initProto; + +_dec = dec +_dec2 = dec +_computedKey = 'b' +_dec3 = dec +_computedKey2 = 'b' +_dec4 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 3, "a"], [_dec2, 4, "a"], [_dec3, 3, _computedKey], [_dec4, 4, _computedKey2]], []); + _initProto = ret[0]; + } + + constructor(...args) { + _initProto(this); + } + + value = 1; + + get a() { + return this.value; + } + + set a(v) { + this.value = v; + } + + get [_computedKey]() { + return this.value; + } + + set [_computedKey2](v) { + this.value = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-private/input.js new file mode 100644 index 000000000000..f439a9152528 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-private/input.js @@ -0,0 +1,21 @@ +class Foo { + static value = 1; + + @dec + static get #a() { + return this.value; + } + + @dec + static set #a(v) { + this.value = v; + } + + static getA() { + return this.#a; + } + + static setA(v) { + this.#a = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-private/output.js new file mode 100644 index 000000000000..8b263b5a8743 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-private/output.js @@ -0,0 +1,35 @@ +var _call_a, _call_a2, _initStatic; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 8, "a", function () { + return this.value; + }], [dec, 9, "a", function (v) { + this.value = v; + }]], []); + _call_a = ret[0]; + _call_a2 = ret[1]; + _initStatic = ret[2]; + + _initStatic(this); + + } + static value = 1; + + static get #a() { + return _call_a(this); + } + + static set #a(v) { + _call_a2(this, v); + } + + static getA() { + return this.#a; + } + + static setA(v) { + this.#a = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-public/input.js new file mode 100644 index 000000000000..193bf7b836a2 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-public/input.js @@ -0,0 +1,23 @@ +class Foo { + static value = 1; + + @dec + static get a() { + return this.value; + } + + @dec + static set a(v) { + this.value = v; + } + + @dec + static get ['b']() { + return this.value; + } + + @dec + static set ['b'](v) { + this.value = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-public/output.js new file mode 100644 index 000000000000..25d9304d4cd6 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters-and-setters/static-public/output.js @@ -0,0 +1,36 @@ +var _computedKey, _computedKey2, _dec, _dec2, _dec3, _dec4, _initStatic; + +_dec = dec +_dec2 = dec +_computedKey = 'b' +_dec3 = dec +_computedKey2 = 'b' +_dec4 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 8, "a"], [_dec2, 9, "a"], [_dec3, 8, _computedKey], [_dec4, 9, _computedKey2]], []); + _initStatic = ret[0]; + + _initStatic(this); + + } + static value = 1; + + static get a() { + return this.value; + } + + static set a(v) { + this.value = v; + } + + static get [_computedKey]() { + return this.value; + } + + static set [_computedKey2](v) { + this.value = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/options.json new file mode 100644 index 000000000000..18aa205580db --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ] + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/private/input.js new file mode 100644 index 000000000000..49c601a1dd5b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/private/input.js @@ -0,0 +1,12 @@ +class Foo { + value = 1; + + @dec + get #a() { + return this.value; + } + + getA() { + return this.#a; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/private/output.js new file mode 100644 index 000000000000..df97177ba9ee --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/private/output.js @@ -0,0 +1,26 @@ +var _call_a, _initProto; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 3, "a", function () { + return this.value; + }]], []); + _call_a = ret[0]; + _initProto = ret[1]; + } + + constructor(...args) { + _initProto(this); + } + + value = 1; + + get #a() { + return _call_a(this); + } + + getA() { + return this.#a; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/public/input.js new file mode 100644 index 000000000000..9d1cbae52f1d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/public/input.js @@ -0,0 +1,13 @@ +class Foo { + value = 1; + + @dec + get a() { + return this.value; + } + + @dec + get ['b']() { + return this.value; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/public/output.js new file mode 100644 index 000000000000..1563a92ec037 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/public/output.js @@ -0,0 +1,27 @@ +var _computedKey, _dec, _dec2, _initProto; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 3, "a"], [_dec2, 3, _computedKey]], []); + _initProto = ret[0]; + } + + constructor(...args) { + _initProto(this); + } + + value = 1; + + get a() { + return this.value; + } + + get [_computedKey]() { + return this.value; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-private/input.js new file mode 100644 index 000000000000..90edd26364d8 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-private/input.js @@ -0,0 +1,12 @@ +class Foo { + static value = 1; + + @dec + static get #a() { + return this.value; + } + + static getA() { + return this.#a; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-private/output.js new file mode 100644 index 000000000000..10759040b63d --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-private/output.js @@ -0,0 +1,24 @@ +var _call_a, _initStatic; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 8, "a", function () { + return this.value; + }]], []); + _call_a = ret[0]; + _initStatic = ret[1]; + + _initStatic(this); + + } + static value = 1; + + static get #a() { + return _call_a(this); + } + + static getA() { + return this.#a; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-public/input.js new file mode 100644 index 000000000000..1383fa58abf4 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-public/input.js @@ -0,0 +1,13 @@ +class Foo { + static value = 1; + + @dec + static get a() { + return this.value; + } + + @dec + static get ['b']() { + return this.value; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-public/output.js new file mode 100644 index 000000000000..9d5a6446c106 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-getters/static-public/output.js @@ -0,0 +1,25 @@ +var _computedKey, _dec, _dec2, _initStatic; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 8, "a"], [_dec2, 8, _computedKey]], []); + _initStatic = ret[0]; + + _initStatic(this); + + } + static value = 1; + + static get a() { + return this.value; + } + + static get [_computedKey]() { + return this.value; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/options.json new file mode 100644 index 000000000000..18aa205580db --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ] + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/private/input.js new file mode 100644 index 000000000000..fc7ace8128ee --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/private/input.js @@ -0,0 +1,12 @@ +class Foo { + value = 1; + + @dec + #a() { + return this.value; + } + + callA() { + return this.#a(); + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/private/output.js new file mode 100644 index 000000000000..51c994adc67f --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/private/output.js @@ -0,0 +1,26 @@ +var _call_a, _initProto; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 2, "a", function () { + return this.value; + }]], []); + _call_a = ret[0]; + _initProto = ret[1]; + } + + constructor(...args) { + _initProto(this); + } + + value = 1; + + #a(...args) { + return _call_a(this, ...args); + } + + callA() { + return this.#a(); + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/public/input.js new file mode 100644 index 000000000000..f364442146ea --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/public/input.js @@ -0,0 +1,13 @@ +class Foo { + value = 1; + + @dec + a() { + return this.value; + } + + @dec + ['b']() { + return this.value; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/public/output.js new file mode 100644 index 000000000000..c48bdc911c40 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/public/output.js @@ -0,0 +1,27 @@ +var _computedKey, _dec, _dec2, _initProto; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 2, "a"], [_dec2, 2, _computedKey]], []); + _initProto = ret[0]; + } + + constructor(...args) { + _initProto(this); + } + + value = 1; + + a() { + return this.value; + } + + [_computedKey]() { + return this.value; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-private/input.js new file mode 100644 index 000000000000..e68191455f14 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-private/input.js @@ -0,0 +1,12 @@ +class Foo { + static value = 1; + + @dec + static #a() { + return this.value; + } + + static callA() { + return this.#a(); + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-private/output.js new file mode 100644 index 000000000000..ab6dbba2b7cd --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-private/output.js @@ -0,0 +1,24 @@ +var _call_a, _initStatic; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 7, "a", function () { + return this.value; + }]], []); + _call_a = ret[0]; + _initStatic = ret[1]; + + _initStatic(this); + + } + static value = 1; + + static #a(...args) { + return _call_a(this, ...args); + } + + static callA() { + return this.#a(); + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-public/input.js new file mode 100644 index 000000000000..77dae8711cd3 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-public/input.js @@ -0,0 +1,13 @@ +class Foo { + static value = 1; + + @dec + static a() { + return this.value; + } + + @dec + static ['b']() { + return this.value; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-public/output.js new file mode 100644 index 000000000000..45d345e5e902 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-methods/static-public/output.js @@ -0,0 +1,25 @@ +var _computedKey, _dec, _dec2, _initStatic; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 7, "a"], [_dec2, 7, _computedKey]], []); + _initStatic = ret[0]; + + _initStatic(this); + + } + static value = 1; + + static a() { + return this.value; + } + + static [_computedKey]() { + return this.value; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-misc/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-misc/options.json new file mode 100644 index 000000000000..18aa205580db --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-misc/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ] + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-misc/valid-expression-formats/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-misc/valid-expression-formats/input.js new file mode 100644 index 000000000000..844a924e3e80 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-misc/valid-expression-formats/input.js @@ -0,0 +1,22 @@ +@dec +@call() +@chain.expr() +@(arbitrary + expr) +@(array[expr]) +class Foo { + #a; + + @dec + @call() + @chain.expr() + @(arbitrary + expr) + @(array[expr]) + method() {} + + makeClass() { + return class Nested { + @(this.#a) + bar; + } + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-misc/valid-expression-formats/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-misc/valid-expression-formats/output.js new file mode 100644 index 000000000000..826f3587b019 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-misc/valid-expression-formats/output.js @@ -0,0 +1,37 @@ +var _initProto, _initClass; + +let _Foo; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[[dec, call(), chain.expr(), arbitrary + expr, array[expr]], 2, "method"]], [dec, call(), chain.expr(), arbitrary + expr, array[expr]]); + _initProto = ret[0]; + _Foo = ret[1]; + _initClass = ret[2]; + } + + constructor(...args) { + _initProto(this); + } + + #a; + + method() {} + + makeClass() { + var _init_bar; + + return class Nested { + static { + let ret = babelHelpers.applyDecs(this, [[this.#a, 0, "bar"]], []); + _init_bar = ret[0]; + } + bar = _init_bar(this); + }; + } + + static { + _initClass(); + + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/options.json new file mode 100644 index 000000000000..18aa205580db --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + [ + "proposal-decorators", + { "version": "2021-12", "decoratorsBeforeExport": false } + ] + ] +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/private/input.js new file mode 100644 index 000000000000..254f2f102f9a --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/private/input.js @@ -0,0 +1,12 @@ +class Foo { + value = 1; + + @dec + set #a(v) { + return this.value = v; + } + + setA(v) { + this.#a = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/private/output.js new file mode 100644 index 000000000000..3d481a84f51b --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/private/output.js @@ -0,0 +1,26 @@ +var _call_a, _initProto; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 4, "a", function (v) { + return this.value = v; + }]], []); + _call_a = ret[0]; + _initProto = ret[1]; + } + + constructor(...args) { + _initProto(this); + } + + value = 1; + + set #a(v) { + _call_a(this, v); + } + + setA(v) { + this.#a = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/public/input.js new file mode 100644 index 000000000000..b8b837257ff0 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/public/input.js @@ -0,0 +1,13 @@ +class Foo { + value = 1; + + @dec + set a(v) { + return this.value = v; + } + + @dec + set ['b'](v) { + return this.value = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/public/output.js new file mode 100644 index 000000000000..bec9149a24ae --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/public/output.js @@ -0,0 +1,27 @@ +var _computedKey, _dec, _dec2, _initProto; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 4, "a"], [_dec2, 4, _computedKey]], []); + _initProto = ret[0]; + } + + constructor(...args) { + _initProto(this); + } + + value = 1; + + set a(v) { + return this.value = v; + } + + set [_computedKey](v) { + return this.value = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-private/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-private/input.js new file mode 100644 index 000000000000..0038d6b6bd30 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-private/input.js @@ -0,0 +1,12 @@ +class Foo { + static value = 1; + + @dec + static set #a(v) { + return this.value = v; + } + + static setA(v) { + this.#a = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-private/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-private/output.js new file mode 100644 index 000000000000..0363ea081a38 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-private/output.js @@ -0,0 +1,24 @@ +var _call_a, _initStatic; + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[dec, 9, "a", function (v) { + return this.value = v; + }]], []); + _call_a = ret[0]; + _initStatic = ret[1]; + + _initStatic(this); + + } + static value = 1; + + static set #a(v) { + _call_a(this, v); + } + + static setA(v) { + this.#a = v; + } + +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-public/input.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-public/input.js new file mode 100644 index 000000000000..0cca65be7fa3 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-public/input.js @@ -0,0 +1,13 @@ +class Foo { + static value = 1; + + @dec + static set a(v) { + return this.value = v; + } + + @dec + static set ['b'](v) { + return this.value = v; + } +} diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-public/output.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-public/output.js new file mode 100644 index 000000000000..2ae733cdf792 --- /dev/null +++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-transform-only-setters/static-public/output.js @@ -0,0 +1,25 @@ +var _computedKey, _dec, _dec2, _initStatic; + +_dec = dec +_computedKey = 'b' +_dec2 = dec + +class Foo { + static { + let ret = babelHelpers.applyDecs(this, [[_dec, 9, "a"], [_dec2, 9, _computedKey]], []); + _initStatic = ret[0]; + + _initStatic(this); + + } + static value = 1; + + static set a(v) { + return this.value = v; + } + + static set [_computedKey](v) { + return this.value = v; + } + +} diff --git a/packages/babel-plugin-syntax-decorators/src/index.ts b/packages/babel-plugin-syntax-decorators/src/index.ts index a825adfd77a5..5f43d029b7af 100644 --- a/packages/babel-plugin-syntax-decorators/src/index.ts +++ b/packages/babel-plugin-syntax-decorators/src/index.ts @@ -3,7 +3,7 @@ import { declare } from "@babel/helper-plugin-utils"; export default declare((api, options) => { api.assertVersion(7); - const { legacy = false } = options; + const { legacy = false, version } = options; if (typeof legacy !== "boolean") { throw new Error("'legacy' must be a boolean."); } @@ -29,6 +29,12 @@ export default declare((api, options) => { } } + if ( + !(version === "2021-12" || version === "2018-09" || version === undefined) + ) { + throw new Error("Unsupported decorators version: " + version); + } + return { name: "syntax-decorators", @@ -38,6 +44,11 @@ export default declare((api, options) => { ? "decorators-legacy" : ["decorators", { decoratorsBeforeExport }], ); + + if (version === "2021-12") { + parserOpts.plugins.push("decoratorAutoAccessors"); + parserOpts.plugins.push("classStaticBlock"); + } }, }; }); diff --git a/packages/babel-runtime-corejs2/package.json b/packages/babel-runtime-corejs2/package.json index b2f4ef3f086a..acea1aaaaf0a 100644 --- a/packages/babel-runtime-corejs2/package.json +++ b/packages/babel-runtime-corejs2/package.json @@ -18,6 +18,15 @@ "regenerator-runtime": "^0.13.4" }, "exports": { + "./helpers/applyDecs": [ + { + "node": "./helpers/applyDecs.js", + "import": "./helpers/esm/applyDecs.js", + "default": "./helpers/applyDecs.js" + }, + "./helpers/applyDecs.js" + ], + "./helpers/esm/applyDecs": "./helpers/esm/applyDecs.js", "./helpers/asyncIterator": [ { "node": "./helpers/asyncIterator.js", diff --git a/packages/babel-runtime-corejs3/package.json b/packages/babel-runtime-corejs3/package.json index 57485d0a5e33..56286b17066f 100644 --- a/packages/babel-runtime-corejs3/package.json +++ b/packages/babel-runtime-corejs3/package.json @@ -17,6 +17,15 @@ "regenerator-runtime": "^0.13.4" }, "exports": { + "./helpers/applyDecs": [ + { + "node": "./helpers/applyDecs.js", + "import": "./helpers/esm/applyDecs.js", + "default": "./helpers/applyDecs.js" + }, + "./helpers/applyDecs.js" + ], + "./helpers/esm/applyDecs": "./helpers/esm/applyDecs.js", "./helpers/asyncIterator": [ { "node": "./helpers/asyncIterator.js", diff --git a/packages/babel-runtime/package.json b/packages/babel-runtime/package.json index c1bba2a1a855..f74ff2f5f127 100644 --- a/packages/babel-runtime/package.json +++ b/packages/babel-runtime/package.json @@ -17,6 +17,15 @@ "regenerator-runtime": "^0.13.4" }, "exports": { + "./helpers/applyDecs": [ + { + "node": "./helpers/applyDecs.js", + "import": "./helpers/esm/applyDecs.js", + "default": "./helpers/applyDecs.js" + }, + "./helpers/applyDecs.js" + ], + "./helpers/esm/applyDecs": "./helpers/esm/applyDecs.js", "./helpers/asyncIterator": [ { "node": "./helpers/asyncIterator.js", diff --git a/packages/babel-types/src/ast-types/generated/index.ts b/packages/babel-types/src/ast-types/generated/index.ts index 5e6547f5e991..f750429c735d 100644 --- a/packages/babel-types/src/ast-types/generated/index.ts +++ b/packages/babel-types/src/ast-types/generated/index.ts @@ -736,8 +736,10 @@ export interface ClassBody extends BaseNode { | ClassPrivateMethod | ClassProperty | ClassPrivateProperty + | ClassAccessorProperty | TSDeclareMethod | TSIndexSignature + | StaticBlock >; } diff --git a/packages/babel-types/src/builders/generated/index.ts b/packages/babel-types/src/builders/generated/index.ts index 5ba1190e4145..130814020c40 100644 --- a/packages/babel-types/src/builders/generated/index.ts +++ b/packages/babel-types/src/builders/generated/index.ts @@ -344,8 +344,10 @@ export function classBody( | t.ClassPrivateMethod | t.ClassProperty | t.ClassPrivateProperty + | t.ClassAccessorProperty | t.TSDeclareMethod | t.TSIndexSignature + | t.StaticBlock >, ): t.ClassBody { return builder.apply("ClassBody", arguments); diff --git a/packages/babel-types/src/definitions/core.ts b/packages/babel-types/src/definitions/core.ts index 5c38150c6a46..df9783987d60 100644 --- a/packages/babel-types/src/definitions/core.ts +++ b/packages/babel-types/src/definitions/core.ts @@ -1262,8 +1262,10 @@ defineType("ClassBody", { "ClassPrivateMethod", "ClassProperty", "ClassPrivateProperty", + "ClassAccessorProperty", "TSDeclareMethod", "TSIndexSignature", + "StaticBlock", ), ), ), diff --git a/yarn.lock b/yarn.lock index 64d2507c1e46..da2049cc3e95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -768,6 +768,7 @@ __metadata: resolution: "@babel/helper-module-transforms@condition:BABEL_8_BREAKING?:workspace:^7.16.5#a9f1b1" dependencies: "@babel/helper-module-transforms-BABEL_8_BREAKING-false": "npm:@babel/helper-module-transforms@workspace:^7.16.5" + checksum: 3f28946c026120f97d7ad2ce86b6413d1d15f64d251db3269fedf1e85216d04981aeacf83c1ae2d1e761df5004765d4bad4d2c4198c0b744efb0201740e630a7 languageName: node linkType: hard