@babel/plugin-transform-object-rest-spread
Advanced tools
Comparing version
161
lib/index.js
@@ -9,2 +9,3 @@ 'use strict'; | ||
var helperCompilationTargets = require('@babel/helper-compilation-targets'); | ||
var pluginTransformDestructuring = require('@babel/plugin-transform-destructuring'); | ||
@@ -54,6 +55,2 @@ function shouldStoreRHSInTemporaryVariable(node) { | ||
const { | ||
isAssignmentPattern, | ||
isObjectProperty | ||
} = core.types; | ||
{ | ||
@@ -86,33 +83,35 @@ const node = core.types.identifier("a"); | ||
} | ||
function hasRestElement(path) { | ||
let foundRestElement = false; | ||
visitRestElements(path, restElement => { | ||
foundRestElement = true; | ||
restElement.stop(); | ||
}); | ||
return foundRestElement; | ||
function* iterateObjectRestElement(path) { | ||
switch (path.type) { | ||
case "ArrayPattern": | ||
for (const elementPath of path.get("elements")) { | ||
if (elementPath.isRestElement()) { | ||
yield* iterateObjectRestElement(elementPath.get("argument")); | ||
} else { | ||
yield* iterateObjectRestElement(elementPath); | ||
} | ||
} | ||
break; | ||
case "ObjectPattern": | ||
for (const propertyPath of path.get("properties")) { | ||
if (propertyPath.isRestElement()) { | ||
yield propertyPath; | ||
} else { | ||
yield* iterateObjectRestElement(propertyPath.get("value")); | ||
} | ||
} | ||
break; | ||
case "AssignmentPattern": | ||
yield* iterateObjectRestElement(path.get("left")); | ||
break; | ||
} | ||
} | ||
function hasObjectPatternRestElement(path) { | ||
let foundRestElement = false; | ||
visitRestElements(path, restElement => { | ||
if (restElement.parentPath.isObjectPattern()) { | ||
foundRestElement = true; | ||
restElement.stop(); | ||
} | ||
}); | ||
return foundRestElement; | ||
function hasObjectRestElement(path) { | ||
const objectRestPatternIterator = iterateObjectRestElement(path); | ||
return !objectRestPatternIterator.next().done; | ||
} | ||
function visitRestElements(path, visitor) { | ||
path.traverse({ | ||
Expression(path) { | ||
const { | ||
parent, | ||
key | ||
} = path; | ||
if (isAssignmentPattern(parent) && key === "right" || isObjectProperty(parent) && parent.computed && key === "key") { | ||
path.skip(); | ||
} | ||
}, | ||
RestElement: visitor | ||
}); | ||
function visitObjectRestElements(path, visitor) { | ||
for (const restElementPath of iterateObjectRestElement(path)) { | ||
visitor(restElementPath); | ||
} | ||
} | ||
@@ -221,3 +220,3 @@ function hasSpread(node) { | ||
} | ||
if (paramPath.isArrayPattern() && hasRestElement(paramPath)) { | ||
if (paramPath.isArrayPattern() && hasObjectRestElement(paramPath)) { | ||
const elements = paramPath.get("elements"); | ||
@@ -228,3 +227,3 @@ for (let i = 0; i < elements.length; i++) { | ||
} | ||
if (paramPath.isObjectPattern() && hasRestElement(paramPath)) { | ||
if (paramPath.isObjectPattern() && hasObjectRestElement(paramPath)) { | ||
const uid = parentPath.scope.generateUidIdentifier("ref"); | ||
@@ -251,3 +250,3 @@ const declar = core.types.variableDeclaration("let", [core.types.variableDeclarator(paramPath.node, uid)]); | ||
const param = params[i]; | ||
if (hasRestElement(param)) { | ||
if (hasObjectRestElement(param)) { | ||
paramsWithRestElement.add(i); | ||
@@ -299,6 +298,3 @@ for (const name of Object.keys(param.getBindingIdentifiers())) { | ||
const originalPath = path; | ||
visitRestElements(path.get("id"), path => { | ||
if (!path.parentPath.isObjectPattern()) { | ||
return; | ||
} | ||
visitObjectRestElements(path.get("id"), path => { | ||
if (shouldStoreRHSInTemporaryVariable(originalPath.node.id) && !core.types.isIdentifier(originalPath.node.init)) { | ||
@@ -328,3 +324,3 @@ const initRef = path.scope.generateUidIdentifierBasedOnNode(originalPath.node.init, "ref"); | ||
}); | ||
const objectPatternPath = path.findParent(path => path.isObjectPattern()); | ||
const objectPatternPath = path.parentPath; | ||
const [impureComputedPropertyDeclarators, argument, callExpression] = createObjectRest(objectPatternPath, file, ref); | ||
@@ -347,3 +343,3 @@ if (pureGetters) { | ||
if (!declaration.isVariableDeclaration()) return; | ||
const hasRest = declaration.get("declarations").some(path => hasObjectPatternRestElement(path.get("id"))); | ||
const hasRest = declaration.get("declarations").some(path => hasObjectRestElement(path.get("id"))); | ||
if (!hasRest) return; | ||
@@ -363,3 +359,3 @@ const specifiers = []; | ||
const leftPath = path.get("left"); | ||
if (leftPath.isObjectPattern() && hasRestElement(leftPath)) { | ||
if (leftPath.isObjectPattern() && hasObjectRestElement(leftPath)) { | ||
const nodes = []; | ||
@@ -386,22 +382,31 @@ const refName = path.scope.generateUidBasedOnNode(path.node.right, "ref"); | ||
const leftPath = path.get("left"); | ||
const left = node.left; | ||
if (!hasObjectPatternRestElement(leftPath)) { | ||
return; | ||
} | ||
if (!core.types.isVariableDeclaration(left)) { | ||
if (!leftPath.isVariableDeclaration()) { | ||
if (!hasObjectRestElement(leftPath)) { | ||
return; | ||
} | ||
const temp = scope.generateUidIdentifier("ref"); | ||
node.left = core.types.variableDeclaration("var", [core.types.variableDeclarator(temp)]); | ||
path.ensureBlock(); | ||
const body = path.node.body; | ||
if (body.body.length === 0 && path.isCompletionRecord()) { | ||
body.body.unshift(core.types.expressionStatement(scope.buildUndefinedNode())); | ||
const statementBody = path.node.body.body; | ||
const nodes = []; | ||
if (statementBody.length === 0 && path.isCompletionRecord()) { | ||
nodes.unshift(core.types.expressionStatement(scope.buildUndefinedNode())); | ||
} | ||
body.body.unshift(core.types.expressionStatement(core.types.assignmentExpression("=", left, core.types.cloneNode(temp)))); | ||
nodes.unshift(core.types.expressionStatement(core.types.assignmentExpression("=", leftPath.node, core.types.cloneNode(temp)))); | ||
pluginTransformDestructuring.unshiftForXStatementBody(path, nodes); | ||
scope.crawl(); | ||
return; | ||
} else { | ||
const pattern = left.declarations[0].id; | ||
const patternPath = leftPath.get("declarations")[0].get("id"); | ||
if (!hasObjectRestElement(patternPath)) { | ||
return; | ||
} | ||
const left = leftPath.node; | ||
const pattern = patternPath.node; | ||
const key = scope.generateUidIdentifier("ref"); | ||
node.left = core.types.variableDeclaration(left.kind, [core.types.variableDeclarator(key, null)]); | ||
path.ensureBlock(); | ||
const body = node.body; | ||
body.body.unshift(core.types.variableDeclaration(node.left.kind, [core.types.variableDeclarator(pattern, core.types.cloneNode(key))])); | ||
pluginTransformDestructuring.unshiftForXStatementBody(path, [core.types.variableDeclaration(node.left.kind, [core.types.variableDeclarator(pattern, core.types.cloneNode(key))])]); | ||
scope.crawl(); | ||
return; | ||
} | ||
@@ -411,9 +416,14 @@ }, | ||
const objectPatterns = []; | ||
visitRestElements(path, path => { | ||
if (!path.parentPath.isObjectPattern()) { | ||
return; | ||
} | ||
const { | ||
scope | ||
} = path; | ||
const uidIdentifiers = []; | ||
visitObjectRestElements(path, path => { | ||
const objectPattern = path.parentPath; | ||
const uid = path.scope.generateUidIdentifier("ref"); | ||
objectPatterns.push(core.types.variableDeclarator(objectPattern.node, uid)); | ||
const uid = scope.generateUidIdentifier("ref"); | ||
objectPatterns.push({ | ||
left: objectPattern.node, | ||
right: uid | ||
}); | ||
uidIdentifiers.push(uid); | ||
objectPattern.replaceWith(core.types.cloneNode(uid)); | ||
@@ -423,6 +433,27 @@ path.skip(); | ||
if (objectPatterns.length > 0) { | ||
const statementPath = path.getStatementParent(); | ||
const statementNode = statementPath.node; | ||
const kind = statementNode.type === "VariableDeclaration" ? statementNode.kind : "var"; | ||
statementPath.insertAfter(core.types.variableDeclaration(kind, objectPatterns)); | ||
const patternParentPath = path.findParent(path => !(path.isPattern() || path.isObjectProperty())); | ||
const patternParent = patternParentPath.node; | ||
switch (patternParent.type) { | ||
case "VariableDeclarator": | ||
patternParentPath.insertAfter(objectPatterns.map(({ | ||
left, | ||
right | ||
}) => core.types.variableDeclarator(left, right))); | ||
break; | ||
case "AssignmentExpression": | ||
{ | ||
for (const uidIdentifier of uidIdentifiers) { | ||
scope.push({ | ||
id: core.types.cloneNode(uidIdentifier) | ||
}); | ||
} | ||
patternParentPath.insertAfter(objectPatterns.map(({ | ||
left, | ||
right | ||
}) => core.types.assignmentExpression("=", left, right))); | ||
} | ||
break; | ||
default: | ||
throw new Error(`Unexpected pattern parent type: ${patternParent.type}`); | ||
} | ||
} | ||
@@ -429,0 +460,0 @@ }, |
{ | ||
"name": "@babel/plugin-transform-object-rest-spread", | ||
"version": "7.27.1", | ||
"version": "7.27.2", | ||
"description": "Compile object rest and spread to ES5", | ||
@@ -20,4 +20,5 @@ "repository": { | ||
"dependencies": { | ||
"@babel/helper-compilation-targets": "^7.27.1", | ||
"@babel/helper-compilation-targets": "^7.27.2", | ||
"@babel/helper-plugin-utils": "^7.27.1", | ||
"@babel/plugin-transform-destructuring": "^7.27.1", | ||
"@babel/plugin-transform-parameters": "^7.27.1" | ||
@@ -31,3 +32,3 @@ }, | ||
"@babel/helper-plugin-test-runner": "^7.27.1", | ||
"@babel/parser": "^7.27.1" | ||
"@babel/parser": "^7.27.2" | ||
}, | ||
@@ -34,0 +35,0 @@ "engines": { |
Sorry, the diff of this file is not supported yet
76174
5.07%492
6.72%5
25%+ Added