From 26105034da4fcce7ac883c899d781f016559310d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Nov 2018 00:38:48 +0800 Subject: switch to vuepress --- .../@babel/plugin-transform-parameters/lib/rest.js | 286 +++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 node_modules/@babel/plugin-transform-parameters/lib/rest.js (limited to 'node_modules/@babel/plugin-transform-parameters/lib/rest.js') diff --git a/node_modules/@babel/plugin-transform-parameters/lib/rest.js b/node_modules/@babel/plugin-transform-parameters/lib/rest.js new file mode 100644 index 00000000..82238e81 --- /dev/null +++ b/node_modules/@babel/plugin-transform-parameters/lib/rest.js @@ -0,0 +1,286 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = convertFunctionRest; + +function _core() { + const data = require("@babel/core"); + + _core = function _core() { + return data; + }; + + return data; +} + +const buildRest = (0, _core().template)(` + for (var LEN = ARGUMENTS.length, + ARRAY = new Array(ARRAY_LEN), + KEY = START; + KEY < LEN; + KEY++) { + ARRAY[ARRAY_KEY] = ARGUMENTS[KEY]; + } +`); +const restIndex = (0, _core().template)(` + (INDEX < OFFSET || ARGUMENTS.length <= INDEX) ? undefined : ARGUMENTS[INDEX] +`); +const restIndexImpure = (0, _core().template)(` + REF = INDEX, (REF < OFFSET || ARGUMENTS.length <= REF) ? undefined : ARGUMENTS[REF] +`); +const restLength = (0, _core().template)(` + ARGUMENTS.length <= OFFSET ? 0 : ARGUMENTS.length - OFFSET +`); + +function referencesRest(path, state) { + if (path.node.name === state.name) { + return path.scope.bindingIdentifierEquals(state.name, state.outerBinding); + } + + return false; +} + +const memberExpressionOptimisationVisitor = { + Scope(path, state) { + if (!path.scope.bindingIdentifierEquals(state.name, state.outerBinding)) { + path.skip(); + } + }, + + Flow(path) { + if (path.isTypeCastExpression()) return; + path.skip(); + }, + + Function(path, state) { + const oldNoOptimise = state.noOptimise; + state.noOptimise = true; + path.traverse(memberExpressionOptimisationVisitor, state); + state.noOptimise = oldNoOptimise; + path.skip(); + }, + + ReferencedIdentifier(path, state) { + const node = path.node; + + if (node.name === "arguments") { + state.deopted = true; + } + + if (!referencesRest(path, state)) return; + + if (state.noOptimise) { + state.deopted = true; + } else { + const parentPath = path.parentPath; + + if (parentPath.listKey === "params" && parentPath.key < state.offset) { + return; + } + + if (parentPath.isMemberExpression({ + object: node + })) { + const grandparentPath = parentPath.parentPath; + const argsOptEligible = !state.deopted && !(grandparentPath.isAssignmentExpression() && parentPath.node === grandparentPath.node.left || grandparentPath.isLVal() || grandparentPath.isForXStatement() || grandparentPath.isUpdateExpression() || grandparentPath.isUnaryExpression({ + operator: "delete" + }) || (grandparentPath.isCallExpression() || grandparentPath.isNewExpression()) && parentPath.node === grandparentPath.node.callee); + + if (argsOptEligible) { + if (parentPath.node.computed) { + if (parentPath.get("property").isBaseType("number")) { + state.candidates.push({ + cause: "indexGetter", + path + }); + return; + } + } else if (parentPath.node.property.name === "length") { + state.candidates.push({ + cause: "lengthGetter", + path + }); + return; + } + } + } + + if (state.offset === 0 && parentPath.isSpreadElement()) { + const call = parentPath.parentPath; + + if (call.isCallExpression() && call.node.arguments.length === 1) { + state.candidates.push({ + cause: "argSpread", + path + }); + return; + } + } + + state.references.push(path); + } + }, + + BindingIdentifier(path, state) { + if (referencesRest(path, state)) { + state.deopted = true; + } + } + +}; + +function hasRest(node) { + const length = node.params.length; + return length > 0 && _core().types.isRestElement(node.params[length - 1]); +} + +function optimiseIndexGetter(path, argsId, offset) { + const offsetLiteral = _core().types.numericLiteral(offset); + + let index; + + if (_core().types.isNumericLiteral(path.parent.property)) { + index = _core().types.numericLiteral(path.parent.property.value + offset); + } else if (offset === 0) { + index = path.parent.property; + } else { + index = _core().types.binaryExpression("+", path.parent.property, _core().types.cloneNode(offsetLiteral)); + } + + const scope = path.scope; + + if (!scope.isPure(index)) { + const temp = scope.generateUidIdentifierBasedOnNode(index); + scope.push({ + id: temp, + kind: "var" + }); + path.parentPath.replaceWith(restIndexImpure({ + ARGUMENTS: argsId, + OFFSET: offsetLiteral, + INDEX: index, + REF: _core().types.cloneNode(temp) + })); + } else { + const parentPath = path.parentPath; + parentPath.replaceWith(restIndex({ + ARGUMENTS: argsId, + OFFSET: offsetLiteral, + INDEX: index + })); + const offsetTestPath = parentPath.get("test").get("left"); + const valRes = offsetTestPath.evaluate(); + + if (valRes.confident) { + if (valRes.value === true) { + parentPath.replaceWith(parentPath.scope.buildUndefinedNode()); + } else { + parentPath.get("test").replaceWith(parentPath.get("test").get("right")); + } + } + } +} + +function optimiseLengthGetter(path, argsId, offset) { + if (offset) { + path.parentPath.replaceWith(restLength({ + ARGUMENTS: argsId, + OFFSET: _core().types.numericLiteral(offset) + })); + } else { + path.replaceWith(argsId); + } +} + +function convertFunctionRest(path) { + const node = path.node, + scope = path.scope; + if (!hasRest(node)) return false; + const rest = node.params.pop().argument; + + const argsId = _core().types.identifier("arguments"); + + const state = { + references: [], + offset: node.params.length, + argumentsNode: argsId, + outerBinding: scope.getBindingIdentifier(rest.name), + candidates: [], + name: rest.name, + deopted: false + }; + path.traverse(memberExpressionOptimisationVisitor, state); + + if (!state.deopted && !state.references.length) { + var _arr = state.candidates; + + for (var _i = 0; _i < _arr.length; _i++) { + const _ref = _arr[_i]; + const path = _ref.path, + cause = _ref.cause; + + const clonedArgsId = _core().types.cloneNode(argsId); + + switch (cause) { + case "indexGetter": + optimiseIndexGetter(path, clonedArgsId, state.offset); + break; + + case "lengthGetter": + optimiseLengthGetter(path, clonedArgsId, state.offset); + break; + + default: + path.replaceWith(clonedArgsId); + } + } + + return true; + } + + state.references = state.references.concat(state.candidates.map(({ + path + }) => path)); + + const start = _core().types.numericLiteral(node.params.length); + + const key = scope.generateUidIdentifier("key"); + const len = scope.generateUidIdentifier("len"); + let arrKey, arrLen; + + if (node.params.length) { + arrKey = _core().types.binaryExpression("-", _core().types.cloneNode(key), _core().types.cloneNode(start)); + arrLen = _core().types.conditionalExpression(_core().types.binaryExpression(">", _core().types.cloneNode(len), _core().types.cloneNode(start)), _core().types.binaryExpression("-", _core().types.cloneNode(len), _core().types.cloneNode(start)), _core().types.numericLiteral(0)); + } else { + arrKey = _core().types.identifier(key.name); + arrLen = _core().types.identifier(len.name); + } + + const loop = buildRest({ + ARGUMENTS: argsId, + ARRAY_KEY: arrKey, + ARRAY_LEN: arrLen, + START: start, + ARRAY: rest, + KEY: key, + LEN: len + }); + + if (state.deopted) { + node.body.body.unshift(loop); + } else { + let target = path.getEarliestCommonAncestorFrom(state.references).getStatementParent(); + target.findParent(path => { + if (path.isLoop()) { + target = path; + } else { + return path.isFunction(); + } + }); + target.insertBefore(loop); + } + + return true; +} \ No newline at end of file -- cgit v1.2.3