From aa773172311dcada759dfbaac485f4bc6e00bc21 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sat, 14 Oct 2023 15:31:11 +0800 Subject: added babel --- .../plugin-transform-block-scoping/lib/loop.js | 294 +++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 node_modules/@babel/plugin-transform-block-scoping/lib/loop.js (limited to 'node_modules/@babel/plugin-transform-block-scoping/lib/loop.js') diff --git a/node_modules/@babel/plugin-transform-block-scoping/lib/loop.js b/node_modules/@babel/plugin-transform-block-scoping/lib/loop.js new file mode 100644 index 00000000..0c0a17f8 --- /dev/null +++ b/node_modules/@babel/plugin-transform-block-scoping/lib/loop.js @@ -0,0 +1,294 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getLoopBodyBindings = getLoopBodyBindings; +exports.getUsageInBody = getUsageInBody; +exports.isVarInLoopHead = isVarInLoopHead; +exports.wrapLoopBody = wrapLoopBody; +var _core = require("@babel/core"); +const collectLoopBodyBindingsVisitor = { + "Expression|Declaration|Loop"(path) { + path.skip(); + }, + Scope(path, state) { + if (path.isFunctionParent()) path.skip(); + const { + bindings + } = path.scope; + for (const name of Object.keys(bindings)) { + const binding = bindings[name]; + if (binding.kind === "let" || binding.kind === "const" || binding.kind === "hoisted") { + state.blockScoped.push(binding); + } + } + } +}; +function getLoopBodyBindings(loopPath) { + const state = { + blockScoped: [] + }; + loopPath.traverse(collectLoopBodyBindingsVisitor, state); + return state.blockScoped; +} +function getUsageInBody(binding, loopPath) { + const seen = new WeakSet(); + let capturedInClosure = false; + const constantViolations = filterMap(binding.constantViolations, path => { + const { + inBody, + inClosure + } = relativeLoopLocation(path, loopPath); + if (!inBody) return null; + capturedInClosure || (capturedInClosure = inClosure); + const id = path.isUpdateExpression() ? path.get("argument") : path.isAssignmentExpression() ? path.get("left") : null; + if (id) seen.add(id.node); + return id; + }); + const references = filterMap(binding.referencePaths, path => { + if (seen.has(path.node)) return null; + const { + inBody, + inClosure + } = relativeLoopLocation(path, loopPath); + if (!inBody) return null; + capturedInClosure || (capturedInClosure = inClosure); + return path; + }); + return { + capturedInClosure, + hasConstantViolations: constantViolations.length > 0, + usages: references.concat(constantViolations) + }; +} +function relativeLoopLocation(path, loopPath) { + const bodyPath = loopPath.get("body"); + let inClosure = false; + for (let currPath = path; currPath; currPath = currPath.parentPath) { + if (currPath.isFunction() || currPath.isClass() || currPath.isMethod()) { + inClosure = true; + } + if (currPath === bodyPath) { + return { + inBody: true, + inClosure + }; + } else if (currPath === loopPath) { + return { + inBody: false, + inClosure + }; + } + } + throw new Error("Internal Babel error: path is not in loop. Please report this as a bug."); +} +const collectCompletionsAndVarsVisitor = { + Function(path) { + path.skip(); + }, + LabeledStatement: { + enter({ + node + }, state) { + state.labelsStack.push(node.label.name); + }, + exit({ + node + }, state) { + const popped = state.labelsStack.pop(); + if (popped !== node.label.name) { + throw new Error("Assertion failure. Please report this bug to Babel."); + } + } + }, + Loop: { + enter(_, state) { + state.labellessContinueTargets++; + state.labellessBreakTargets++; + }, + exit(_, state) { + state.labellessContinueTargets--; + state.labellessBreakTargets--; + } + }, + SwitchStatement: { + enter(_, state) { + state.labellessBreakTargets++; + }, + exit(_, state) { + state.labellessBreakTargets--; + } + }, + "BreakStatement|ContinueStatement"(path, state) { + const { + label + } = path.node; + if (label) { + if (state.labelsStack.includes(label.name)) return; + } else if (path.isBreakStatement() ? state.labellessBreakTargets > 0 : state.labellessContinueTargets > 0) { + return; + } + state.breaksContinues.push(path); + }, + ReturnStatement(path, state) { + state.returns.push(path); + }, + VariableDeclaration(path, state) { + if (path.parent === state.loopNode && isVarInLoopHead(path)) return; + if (path.node.kind === "var") state.vars.push(path); + } +}; +function wrapLoopBody(loopPath, captured, updatedBindingsUsages) { + const loopNode = loopPath.node; + const state = { + breaksContinues: [], + returns: [], + labelsStack: [], + labellessBreakTargets: 0, + labellessContinueTargets: 0, + vars: [], + loopNode + }; + loopPath.traverse(collectCompletionsAndVarsVisitor, state); + const callArgs = []; + const closureParams = []; + const updater = []; + for (const [name, updatedUsage] of updatedBindingsUsages) { + callArgs.push(_core.types.identifier(name)); + const innerName = loopPath.scope.generateUid(name); + closureParams.push(_core.types.identifier(innerName)); + updater.push(_core.types.assignmentExpression("=", _core.types.identifier(name), _core.types.identifier(innerName))); + for (const path of updatedUsage) path.replaceWith(_core.types.identifier(innerName)); + } + for (const name of captured) { + if (updatedBindingsUsages.has(name)) continue; + callArgs.push(_core.types.identifier(name)); + closureParams.push(_core.types.identifier(name)); + } + const id = loopPath.scope.generateUid("loop"); + const fn = _core.types.functionExpression(null, closureParams, _core.types.toBlock(loopNode.body)); + let call = _core.types.callExpression(_core.types.identifier(id), callArgs); + const fnParent = loopPath.findParent(p => p.isFunction()); + if (fnParent) { + const { + async, + generator + } = fnParent.node; + fn.async = async; + fn.generator = generator; + if (generator) call = _core.types.yieldExpression(call, true);else if (async) call = _core.types.awaitExpression(call); + } + const updaterNode = updater.length > 0 ? _core.types.expressionStatement(_core.types.sequenceExpression(updater)) : null; + if (updaterNode) fn.body.body.push(updaterNode); + const [varPath] = loopPath.insertBefore(_core.types.variableDeclaration("var", [_core.types.variableDeclarator(_core.types.identifier(id), fn)])); + const bodyStmts = []; + const varNames = []; + for (const varPath of state.vars) { + const assign = []; + for (const decl of varPath.node.declarations) { + varNames.push(...Object.keys(_core.types.getBindingIdentifiers(decl.id))); + if (decl.init) { + assign.push(_core.types.assignmentExpression("=", decl.id, decl.init)); + } + } + if (assign.length > 0) { + let replacement = assign.length === 1 ? assign[0] : _core.types.sequenceExpression(assign); + if (!_core.types.isForStatement(varPath.parent, { + init: varPath.node + }) && !_core.types.isForXStatement(varPath.parent, { + left: varPath.node + })) { + replacement = _core.types.expressionStatement(replacement); + } + varPath.replaceWith(replacement); + } else { + varPath.remove(); + } + } + if (varNames.length) { + varPath.pushContainer("declarations", varNames.map(name => _core.types.variableDeclarator(_core.types.identifier(name)))); + } + const labelNum = state.breaksContinues.length; + const returnNum = state.returns.length; + if (labelNum + returnNum === 0) { + bodyStmts.push(_core.types.expressionStatement(call)); + } else if (labelNum === 1 && returnNum === 0) { + for (const path of state.breaksContinues) { + const { + node + } = path; + const { + type, + label + } = node; + let name = type === "BreakStatement" ? "break" : "continue"; + if (label) name += " " + label.name; + path.replaceWith(_core.types.addComment(_core.types.returnStatement(_core.types.numericLiteral(1)), "trailing", " " + name, true)); + if (updaterNode) path.insertBefore(_core.types.cloneNode(updaterNode)); + bodyStmts.push(_core.template.statement.ast` + if (${call}) ${node} + `); + } + } else { + const completionId = loopPath.scope.generateUid("ret"); + if (varPath.isVariableDeclaration()) { + varPath.pushContainer("declarations", [_core.types.variableDeclarator(_core.types.identifier(completionId))]); + bodyStmts.push(_core.types.expressionStatement(_core.types.assignmentExpression("=", _core.types.identifier(completionId), call))); + } else { + bodyStmts.push(_core.types.variableDeclaration("var", [_core.types.variableDeclarator(_core.types.identifier(completionId), call)])); + } + const injected = []; + for (const path of state.breaksContinues) { + const { + node + } = path; + const { + type, + label + } = node; + let name = type === "BreakStatement" ? "break" : "continue"; + if (label) name += " " + label.name; + let i = injected.indexOf(name); + const hasInjected = i !== -1; + if (!hasInjected) { + injected.push(name); + i = injected.length - 1; + } + path.replaceWith(_core.types.addComment(_core.types.returnStatement(_core.types.numericLiteral(i)), "trailing", " " + name, true)); + if (updaterNode) path.insertBefore(_core.types.cloneNode(updaterNode)); + if (hasInjected) continue; + bodyStmts.push(_core.template.statement.ast` + if (${_core.types.identifier(completionId)} === ${_core.types.numericLiteral(i)}) ${node} + `); + } + if (returnNum) { + for (const path of state.returns) { + const arg = path.node.argument || path.scope.buildUndefinedNode(); + path.replaceWith(_core.template.statement.ast` + return { v: ${arg} }; + `); + } + bodyStmts.push(_core.template.statement.ast` + if (${_core.types.identifier(completionId)}) return ${_core.types.identifier(completionId)}.v; + `); + } + } + loopNode.body = _core.types.blockStatement(bodyStmts); + return varPath; +} +function isVarInLoopHead(path) { + if (_core.types.isForStatement(path.parent)) return path.key === "init"; + if (_core.types.isForXStatement(path.parent)) return path.key === "left"; + return false; +} +function filterMap(list, fn) { + const result = []; + for (const item of list) { + const mapped = fn(item); + if (mapped) result.push(mapped); + } + return result; +} + +//# sourceMappingURL=loop.js.map -- cgit v1.2.3