@babel/plugin-proposal-decorators
Advanced tools
Comparing version 8.0.0-alpha.4 to 8.0.0-alpha.5
305
lib/index.js
@@ -7,2 +7,3 @@ import { declare } from '@babel/helper-plugin-utils'; | ||
import splitExportDeclaration from '@babel/helper-split-export-declaration'; | ||
import { skipTransparentExprWrappers } from '@babel/helper-skip-transparent-expression-wrappers'; | ||
@@ -202,12 +203,15 @@ const buildClassDecorator = template.statement(` | ||
} | ||
function replaceClassWithVar(path) { | ||
function replaceClassWithVar(path, className) { | ||
if (path.type === "ClassDeclaration") { | ||
const varId = path.scope.generateUidIdentifierBasedOnNode(path.node.id); | ||
const classId = types.identifier(path.node.id.name); | ||
path.scope.rename(classId.name, varId.name); | ||
path.insertBefore(types.variableDeclaration("let", [types.variableDeclarator(varId)])); | ||
const id = path.node.id; | ||
const className = id.name; | ||
const varId = path.scope.generateUidIdentifierBasedOnNode(id); | ||
const classId = types.identifier(className); | ||
path.scope.rename(className, varId.name); | ||
path.get("id").replaceWith(classId); | ||
return [types.cloneNode(varId), path]; | ||
return { | ||
id: types.cloneNode(varId), | ||
path | ||
}; | ||
} else { | ||
let className; | ||
let varId; | ||
@@ -218,11 +222,11 @@ if (path.node.id) { | ||
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 = path.scope.parent.generateDeclaredUidIdentifier(className); | ||
} else { | ||
varId = path.scope.parent.generateDeclaredUidIdentifier("decorated_class"); | ||
varId = path.scope.parent.generateDeclaredUidIdentifier(typeof className === "string" ? className : "decorated_class"); | ||
} | ||
const newClassExpr = types.classExpression(className && types.identifier(className), path.node.superClass, path.node.body); | ||
const newClassExpr = types.classExpression(typeof className === "string" ? types.identifier(className) : null, path.node.superClass, path.node.body); | ||
const [newPath] = path.replaceWith(types.sequenceExpression([newClassExpr, varId])); | ||
return [types.cloneNode(varId), newPath.get("expressions.0")]; | ||
return { | ||
id: types.cloneNode(varId), | ||
path: newPath.get("expressions.0") | ||
}; | ||
} | ||
@@ -382,3 +386,9 @@ } | ||
} | ||
function transformClass(path, state, constantSuper, version) { | ||
function createSetFunctionNameCall(state, className) { | ||
return types.callExpression(state.addHelper("setFunctionName"), [types.thisExpression(), className]); | ||
} | ||
function createToPropertyKeyCall(state, propertyKey) { | ||
return types.callExpression(state.addHelper("toPropertyKey"), [propertyKey]); | ||
} | ||
function transformClass(path, state, constantSuper, version, className, propertyVisitor) { | ||
const body = path.get("body.body"); | ||
@@ -388,2 +398,9 @@ const classDecorators = path.node.decorators; | ||
const generateClassPrivateUid = createLazyPrivateUidGeneratorForClass(path); | ||
const assignments = []; | ||
const scopeParent = path.scope.parent; | ||
const memoiseExpression = (expression, hint) => { | ||
const localEvaluatedId = scopeParent.generateDeclaredUidIdentifier(hint); | ||
assignments.push(types.assignmentExpression("=", localEvaluatedId, expression)); | ||
return types.cloneNode(localEvaluatedId); | ||
}; | ||
for (const element of body) { | ||
@@ -394,4 +411,16 @@ if (!isClassDecoratableElementPath(element)) { | ||
if (element.node.decorators && element.node.decorators.length > 0) { | ||
switch (element.node.type) { | ||
case "ClassProperty": | ||
propertyVisitor.ClassProperty(element, state); | ||
break; | ||
case "ClassPrivateProperty": | ||
propertyVisitor.ClassPrivateProperty(element, state); | ||
break; | ||
case "ClassAccessorProperty": | ||
propertyVisitor.ClassAccessorProperty(element, state); | ||
break; | ||
} | ||
hasElementDecorators = true; | ||
} else if (element.node.type === "ClassAccessorProperty") { | ||
propertyVisitor.ClassAccessorProperty(element, state); | ||
const { | ||
@@ -404,9 +433,15 @@ key, | ||
const newId = generateClassPrivateUid(); | ||
const valueNode = value ? types.cloneNode(value) : undefined; | ||
const newField = generateClassProperty(newId, valueNode, isStatic); | ||
const newField = generateClassProperty(newId, value, isStatic); | ||
const keyPath = element.get("key"); | ||
const [newPath] = element.replaceWith(newField); | ||
addProxyAccessorsFor(path.node.id, newPath, key, newId, version, computed); | ||
addProxyAccessorsFor(path.node.id, newPath, computed && !keyPath.isConstantExpression() ? memoiseExpression(createToPropertyKeyCall(state, key), "computedKey") : key, newId, version, computed); | ||
} | ||
} | ||
if (!classDecorators && !hasElementDecorators) return; | ||
if (!classDecorators && !hasElementDecorators) { | ||
if (assignments.length > 0) { | ||
path.insertBefore(assignments.map(expr => types.expressionStatement(expr))); | ||
path.scope.crawl(); | ||
} | ||
return; | ||
} | ||
const elementDecoratorInfo = []; | ||
@@ -419,9 +454,2 @@ let firstFieldPath; | ||
let protoInitLocal, staticInitLocal, classInitLocal, classIdLocal; | ||
const assignments = []; | ||
const scopeParent = path.scope.parent; | ||
const memoiseExpression = (expression, hint) => { | ||
const localEvaluatedId = scopeParent.generateDeclaredUidIdentifier(hint); | ||
assignments.push(types.assignmentExpression("=", localEvaluatedId, expression)); | ||
return types.cloneNode(localEvaluatedId); | ||
}; | ||
const decoratorsThis = new Map(); | ||
@@ -448,7 +476,10 @@ const maybeExtractDecorator = decorator => { | ||
}; | ||
let needsDeclaraionForClassBinding = false; | ||
if (classDecorators) { | ||
classInitLocal = scopeParent.generateDeclaredUidIdentifier("initClass"); | ||
const [classId, classPath] = replaceClassWithVar(path); | ||
path = classPath; | ||
classIdLocal = classId; | ||
needsDeclaraionForClassBinding = path.isClassDeclaration(); | ||
({ | ||
id: classIdLocal, | ||
path | ||
} = replaceClassWithVar(path, className)); | ||
path.node.decorators = null; | ||
@@ -483,4 +514,4 @@ for (const classDecorator of classDecorators) { | ||
if (isComputed) { | ||
if (!scopeParent.isStatic(node.key)) { | ||
node.key = memoiseExpression(node.key, "computedKey"); | ||
if (!element.get("key").isConstantExpression()) { | ||
node.key = memoiseExpression(createToPropertyKeyCall(state, node.key), "computedKey"); | ||
} | ||
@@ -732,10 +763,13 @@ } | ||
} | ||
originalClass.body.body.unshift(types.staticBlock([types.expressionStatement(createLocalsAssignment(elementLocals, classLocals, elementDecorations, types.arrayExpression(classDecorations), types.numericLiteral(classDecorationsFlag), needsInstancePrivateBrandCheck ? lastInstancePrivateName : null, types.cloneNode(superClass), state)), requiresStaticInit && types.expressionStatement(types.callExpression(types.cloneNode(staticInitLocal), [types.thisExpression()]))].filter(Boolean))); | ||
originalClass.body.body.unshift(types.staticBlock([types.expressionStatement(createLocalsAssignment(elementLocals, classLocals, elementDecorations, types.arrayExpression(classDecorations), types.numericLiteral(classDecorationsFlag), needsInstancePrivateBrandCheck ? lastInstancePrivateName : null, typeof className === "object" ? className : undefined, types.cloneNode(superClass), state)), requiresStaticInit && types.expressionStatement(types.callExpression(types.cloneNode(staticInitLocal), [types.thisExpression()]))].filter(Boolean))); | ||
path.insertBefore(assignments.map(expr => types.expressionStatement(expr))); | ||
if (needsDeclaraionForClassBinding) { | ||
path.insertBefore(types.variableDeclaration("let", [types.variableDeclarator(types.cloneNode(classIdLocal))])); | ||
} | ||
path.scope.crawl(); | ||
return path; | ||
} | ||
function createLocalsAssignment(elementLocals, classLocals, elementDecorations, classDecorations, classDecorationsFlag, maybePrivateBranName, superClass, state, version) { | ||
function createLocalsAssignment(elementLocals, classLocals, elementDecorations, classDecorations, classDecorationsFlag, maybePrivateBranName, setClassName, superClass, state, version) { | ||
let lhs, rhs; | ||
const args = [types.thisExpression(), elementDecorations, classDecorations]; | ||
const args = [setClassName ? createSetFunctionNameCall(state, setClassName) : types.thisExpression(), elementDecorations, classDecorations]; | ||
{ | ||
@@ -768,2 +802,165 @@ if (maybePrivateBranName || superClass || classDecorationsFlag.value !== 0) { | ||
} | ||
function isProtoKey(node) { | ||
return node.type === "Identifier" ? node.name === "__proto__" : node.value === "__proto__"; | ||
} | ||
function isDecorated(node) { | ||
return node.decorators && node.decorators.length > 0; | ||
} | ||
function shouldTransformElement(node) { | ||
switch (node.type) { | ||
case "ClassAccessorProperty": | ||
return true; | ||
case "ClassMethod": | ||
case "ClassProperty": | ||
case "ClassPrivateMethod": | ||
case "ClassPrivateProperty": | ||
return isDecorated(node); | ||
default: | ||
return false; | ||
} | ||
} | ||
function shouldTransformClass(node) { | ||
return isDecorated(node) || node.body.body.some(shouldTransformElement); | ||
} | ||
function NamedEvaluationVisitoryFactory(isAnonymous, visitor) { | ||
function handleComputedProperty(propertyPath, key, state) { | ||
switch (key.type) { | ||
case "StringLiteral": | ||
return types.stringLiteral(key.value); | ||
case "NumericLiteral": | ||
case "BigIntLiteral": | ||
{ | ||
const keyValue = key.value + ""; | ||
propertyPath.get("key").replaceWith(types.stringLiteral(keyValue)); | ||
return types.stringLiteral(keyValue); | ||
} | ||
default: | ||
{ | ||
const ref = propertyPath.scope.maybeGenerateMemoised(key); | ||
propertyPath.get("key").replaceWith(types.assignmentExpression("=", ref, types.callExpression(state.addHelper("toPropertyKey"), [key]))); | ||
return types.cloneNode(ref); | ||
} | ||
} | ||
} | ||
return { | ||
VariableDeclarator(path, state) { | ||
const id = path.node.id; | ||
if (id.type === "Identifier") { | ||
const initializer = skipTransparentExprWrappers(path.get("init")); | ||
if (isAnonymous(initializer)) { | ||
const name = id.name; | ||
visitor(initializer, state, name); | ||
} | ||
} | ||
}, | ||
AssignmentExpression(path, state) { | ||
const id = path.node.left; | ||
if (id.type === "Identifier") { | ||
const initializer = skipTransparentExprWrappers(path.get("right")); | ||
if (isAnonymous(initializer)) { | ||
switch (path.node.operator) { | ||
case "=": | ||
case "&&=": | ||
case "||=": | ||
case "??=": | ||
visitor(initializer, state, id.name); | ||
} | ||
} | ||
} | ||
}, | ||
AssignmentPattern(path, state) { | ||
const id = path.node.left; | ||
if (id.type === "Identifier") { | ||
const initializer = skipTransparentExprWrappers(path.get("right")); | ||
if (isAnonymous(initializer)) { | ||
const name = id.name; | ||
visitor(initializer, state, name); | ||
} | ||
} | ||
}, | ||
ObjectExpression(path, state) { | ||
for (const propertyPath of path.get("properties")) { | ||
const { | ||
node | ||
} = propertyPath; | ||
if (node.type !== "ObjectProperty") continue; | ||
const id = node.key; | ||
const initializer = skipTransparentExprWrappers(propertyPath.get("value")); | ||
if (isAnonymous(initializer)) { | ||
if (!node.computed) { | ||
if (!isProtoKey(id)) { | ||
if (id.type === "Identifier") { | ||
visitor(initializer, state, id.name); | ||
} else { | ||
const className = types.stringLiteral(id.value + ""); | ||
visitor(initializer, state, className); | ||
} | ||
} | ||
} else { | ||
const ref = handleComputedProperty(propertyPath, id, state); | ||
visitor(initializer, state, ref); | ||
} | ||
} | ||
} | ||
}, | ||
ClassPrivateProperty(path, state) { | ||
const { | ||
node | ||
} = path; | ||
const initializer = skipTransparentExprWrappers(path.get("value")); | ||
if (isAnonymous(initializer)) { | ||
const className = types.stringLiteral("#" + node.key.id.name); | ||
visitor(initializer, state, className); | ||
} | ||
}, | ||
ClassAccessorProperty(path, state) { | ||
const { | ||
node | ||
} = path; | ||
const id = node.key; | ||
const initializer = skipTransparentExprWrappers(path.get("value")); | ||
if (isAnonymous(initializer)) { | ||
if (!node.computed) { | ||
if (id.type === "Identifier") { | ||
visitor(initializer, state, id.name); | ||
} else if (id.type === "PrivateName") { | ||
const className = types.stringLiteral("#" + id.id.name); | ||
visitor(initializer, state, className); | ||
} else { | ||
const className = types.stringLiteral(id.value + ""); | ||
visitor(initializer, state, className); | ||
} | ||
} else { | ||
const ref = handleComputedProperty(path, id, state); | ||
visitor(initializer, state, ref); | ||
} | ||
} | ||
}, | ||
ClassProperty(path, state) { | ||
const { | ||
node | ||
} = path; | ||
const id = node.key; | ||
const initializer = skipTransparentExprWrappers(path.get("value")); | ||
if (isAnonymous(initializer)) { | ||
if (!node.computed) { | ||
if (id.type === "Identifier") { | ||
visitor(initializer, state, id.name); | ||
} else { | ||
const className = types.stringLiteral(id.value + ""); | ||
visitor(initializer, state, className); | ||
} | ||
} else { | ||
const ref = handleComputedProperty(path, id, state); | ||
visitor(initializer, state, ref); | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
function isDecoratedAnonymousClassExpression(path) { | ||
return path.isClassExpression({ | ||
id: null | ||
}) && shouldTransformClass(path.node); | ||
} | ||
function transformer2023_05 ({ | ||
@@ -776,15 +973,41 @@ assertVersion, | ||
{ | ||
assertVersion("^7.21.0"); | ||
assertVersion("8.0.0-alpha.5"); | ||
} | ||
const VISITED = new WeakSet(); | ||
const constantSuper = assumption("constantSuper") ?? loose; | ||
const namedEvaluationVisitor = NamedEvaluationVisitoryFactory(isDecoratedAnonymousClassExpression, visitClass); | ||
function visitClass(path, state, className) { | ||
if (VISITED.has(path)) return; | ||
const { | ||
node | ||
} = path; | ||
className ??= node.id?.name; | ||
const newPath = transformClass(path, state, constantSuper, version, className, namedEvaluationVisitor); | ||
if (newPath) { | ||
VISITED.add(newPath); | ||
return; | ||
} | ||
VISITED.add(path); | ||
} | ||
return { | ||
name: "proposal-decorators", | ||
inherits: syntaxDecorators, | ||
visitor: { | ||
"ExportNamedDeclaration|ExportDefaultDeclaration"(path) { | ||
visitor: Object.assign({ | ||
ExportDefaultDeclaration(path, state) { | ||
const { | ||
declaration | ||
} = path.node; | ||
if (declaration?.type === "ClassDeclaration" && declaration.decorators?.length > 0) { | ||
if (declaration?.type === "ClassDeclaration" && isDecorated(declaration)) { | ||
const isAnonymous = !declaration.id; | ||
const updatedVarDeclarationPath = splitExportDeclaration(path); | ||
if (isAnonymous) { | ||
visitClass(updatedVarDeclarationPath, state, types.stringLiteral("default")); | ||
} | ||
} | ||
}, | ||
ExportNamedDeclaration(path) { | ||
const { | ||
declaration | ||
} = path.node; | ||
if (declaration?.type === "ClassDeclaration" && isDecorated(declaration)) { | ||
splitExportDeclaration(path); | ||
@@ -794,7 +1017,5 @@ } | ||
Class(path, state) { | ||
if (VISITED.has(path)) return; | ||
const newPath = transformClass(path, state, constantSuper, version); | ||
if (newPath) VISITED.add(newPath); | ||
visitClass(path, state, undefined); | ||
} | ||
} | ||
}, namedEvaluationVisitor) | ||
}; | ||
@@ -804,3 +1025,3 @@ } | ||
var index = declare((api, options) => { | ||
api.assertVersion(7); | ||
api.assertVersion("8.0.0-alpha.5"); | ||
const { | ||
@@ -807,0 +1028,0 @@ version |
{ | ||
"name": "@babel/plugin-proposal-decorators", | ||
"version": "8.0.0-alpha.4", | ||
"version": "8.0.0-alpha.5", | ||
"author": "The Babel Team (https://babel.dev/team)", | ||
@@ -23,18 +23,19 @@ "license": "MIT", | ||
"dependencies": { | ||
"@babel/helper-create-class-features-plugin": "^8.0.0-alpha.4", | ||
"@babel/helper-plugin-utils": "^8.0.0-alpha.4", | ||
"@babel/helper-replace-supers": "^8.0.0-alpha.4", | ||
"@babel/helper-split-export-declaration": "^8.0.0-alpha.4", | ||
"@babel/plugin-syntax-decorators": "^8.0.0-alpha.4" | ||
"@babel/helper-create-class-features-plugin": "^8.0.0-alpha.5", | ||
"@babel/helper-plugin-utils": "^8.0.0-alpha.5", | ||
"@babel/helper-replace-supers": "^8.0.0-alpha.5", | ||
"@babel/helper-skip-transparent-expression-wrappers": "^8.0.0-alpha.5", | ||
"@babel/helper-split-export-declaration": "^8.0.0-alpha.5", | ||
"@babel/plugin-syntax-decorators": "^8.0.0-alpha.5" | ||
}, | ||
"peerDependencies": { | ||
"@babel/core": "^8.0.0-alpha.4" | ||
"@babel/core": "^8.0.0-alpha.5" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^8.0.0-alpha.4", | ||
"@babel/helper-plugin-test-runner": "^8.0.0-alpha.4", | ||
"@babel/traverse": "^8.0.0-alpha.4", | ||
"@babel/core": "^8.0.0-alpha.5", | ||
"@babel/helper-plugin-test-runner": "^8.0.0-alpha.5", | ||
"@babel/traverse": "^8.0.0-alpha.5", | ||
"@types/charcodes": "^0.2.0", | ||
"array.prototype.concat": "^1.0.2", | ||
"babel-plugin-polyfill-es-shims": "^0.10.0", | ||
"babel-plugin-polyfill-es-shims": "^0.10.1", | ||
"charcodes": "^0.2.0", | ||
@@ -41,0 +42,0 @@ "object.getownpropertydescriptors": "^2.1.1" |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
164714
1034
7