first commit
This commit is contained in:
291
app_vue/node_modules/@babel/plugin-transform-block-scoping/lib/loop.js
generated
vendored
Normal file
291
app_vue/node_modules/@babel/plugin-transform-block-scoping/lib/loop.js
generated
vendored
Normal file
@ -0,0 +1,291 @@
|
||||
"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));
|
||||
} else if (_core.types.isForXStatement(varPath.parent, {
|
||||
left: varPath.node
|
||||
})) {
|
||||
assign.push(decl.id);
|
||||
}
|
||||
}
|
||||
if (assign.length > 0) {
|
||||
const replacement = assign.length === 1 ? assign[0] : _core.types.sequenceExpression(assign);
|
||||
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
|
Reference in New Issue
Block a user