UNPKG

prepack

Version:

Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.

118 lines (93 loc) 3.89 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClosureRefVisitor = void 0; var _realm = require("../realm.js"); var t = _interopRequireWildcard(require("@babel/types")); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ /* strict-local */ function visitName(path, state, node, modified) { // Is the name bound to some local identifier? If so, we don't need to do anything if (path.scope.hasBinding(node.name, /*noGlobals*/ true)) return; // Otherwise, let's record that there's an unbound identifier let nodes = state.functionInfo.unbound.get(node.name); if (nodes === undefined) state.functionInfo.unbound.set(node.name, nodes = []); nodes.push(node); if (modified) state.functionInfo.modified.add(node.name); } function ignorePath(path) { let parent = path.parent; return t.isLabeledStatement(parent) || t.isBreakStatement(parent) || t.isContinueStatement(parent); } let ClosureRefVisitor = { "FunctionDeclaration|ArrowFunctionExpression|FunctionExpression": { enter(path, state) { state.functionInfo.depth++; }, exit(path, state) { state.functionInfo.depth--; } }, ArrowFunctionExpression: { enter(path, state) { state.functionInfo.depth++; state.functionInfo.lexicalDepth++; }, exit(path, state) { state.functionInfo.depth--; state.functionInfo.lexicalDepth--; } }, CallExpression(path, state) { // Here we apply the require optimization by replacing require calls with their // corresponding initialized modules. if (state.getModuleIdIfNodeIsRequireFunction === undefined) return; let moduleId = state.getModuleIdIfNodeIsRequireFunction(path.scope, path.node); if (moduleId === undefined) return; state.functionInfo.requireCalls.set(path.node, moduleId); }, ReferencedIdentifier(path, state) { if (ignorePath(path)) return; let innerName = path.node.name; if (innerName === "arguments") { if (state.functionInfo.depth === 1) { state.functionInfo.usesArguments = true; } // "arguments" bound to local scope. therefore, there's no need to visit this identifier. return; } visitName(path, state, path.node, false); }, ThisExpression(path, state) { if (state.functionInfo.depth - state.functionInfo.lexicalDepth === 1) { state.functionInfo.usesThis = true; } }, "AssignmentExpression|UpdateExpression"(path, state) { let ids = path.getBindingIdentifiers(); for (let name in ids) { visitName(path, state, ids[name], true); } }, "ForInStatement|ForOfStatement"(path, state) { if (path.node.left !== "VariableDeclaration") { // `LeftHandSideExpression`s in a for-in/for-of statement perform `DestructuringAssignment` on the current loop // value so we need to make sure we visit these bindings and mark them as modified. const ids = path.get("left").getBindingIdentifiers(); for (const name in ids) { visitName(path, state, ids[name], true); } } } }; exports.ClosureRefVisitor = ClosureRefVisitor; //# sourceMappingURL=visitors.js.map