prepack
Version:
Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.
211 lines (170 loc) • 10.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.prepackVersion = undefined;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /**
* 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.
*/
/* APIs for running Prepack for code where a model of the environment is supplied as part of the code. */
exports.prepackSources = prepackSources;
exports.prepackString = prepackString;
exports.prepack = prepack;
exports.prepackFromAst = prepackFromAst;
var _index = require("./serializer/index.js");
var _index2 = _interopRequireDefault(_index);
var _construct_realm = require("./construct_realm.js");
var _construct_realm2 = _interopRequireDefault(_construct_realm);
var _globals = require("./globals.js");
var _globals2 = _interopRequireDefault(_globals);
var _babelTypes = require("babel-types");
var t = _interopRequireWildcard(_babelTypes);
var _index3 = require("./methods/index.js");
var _prepackOptions = require("./prepack-options");
var _errors = require("./errors.js");
var _completions = require("./completions.js");
var _options = require("./options");
var _invariant = require("./invariant.js");
var _invariant2 = _interopRequireDefault(_invariant);
var _package = require("../package.json");
var _types = require("./serializer/types.js");
var _ResidualHeapVisitor = require("./serializer/ResidualHeapVisitor.js");
var _modules = require("./utils/modules.js");
var _logger = require("./utils/logger.js");
var _generator = require("./utils/generator.js");
var _index4 = require("./values/index.js");
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)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function prepackSources(sources, options = _options.defaultOptions, debugChannel = undefined) {
let realmOptions = (0, _prepackOptions.getRealmOptions)(options);
realmOptions.errorHandler = options.errorHandler;
let realm = (0, _construct_realm2.default)(realmOptions, debugChannel);
(0, _globals2.default)(realm);
if (typeof options.additionalGlobals === "function") {
options.additionalGlobals(realm);
}
if (options.check) {
realm.generator = new _generator.Generator(realm, "main");
let logger = new _logger.Logger(realm, !!options.internalDebug);
let modules = new _modules.Modules(realm, logger, new _types.SerializerStatistics(), !!options.logModules, !!options.delayUnsupportedRequires, !!options.accelerateUnsupportedRequires);
let [result] = realm.$GlobalEnv.executeSources(sources);
if (result instanceof _completions.AbruptCompletion) throw result;
(0, _invariant2.default)(options.check);
checkResidualFunctions(modules, options.check[0], options.check[1]);
return { code: "", map: undefined };
} else if (options.serialize || !options.residual) {
let serializer = new _index2.default(realm, (0, _prepackOptions.getSerializerOptions)(options));
let serialized = serializer.init(sources, options.sourceMaps);
//Turn off the debugger if there is one
if (realm.debuggerInstance) {
realm.debuggerInstance.shutdown();
}
if (!serialized) {
throw new _errors.FatalError("serializer failed");
}
if (!options.residual) return serialized;
let residualSources = [{
filePath: options.outputFilename || "unknown",
fileContents: serialized.code,
sourceMapContents: serialized.map && JSON.stringify(serialized.map)
}];
realm = (0, _construct_realm2.default)(realmOptions, debugChannel);
(0, _globals2.default)(realm);
if (typeof options.additionalGlobals === "function") {
options.additionalGlobals(realm);
}
realm.generator = new _generator.Generator(realm, "main");
let result = realm.$GlobalEnv.executePartialEvaluator(residualSources, options);
if (result instanceof _completions.AbruptCompletion) throw result;
return _extends({}, result);
} else {
(0, _invariant2.default)(options.residual);
realm.generator = new _generator.Generator(realm, "main");
let result = realm.$GlobalEnv.executePartialEvaluator(sources, options);
if (result instanceof _completions.AbruptCompletion) throw result;
return _extends({}, result);
}
}
/* deprecated: please use prepackSources instead. */
function prepackString(filename, code, sourceMap, options = _options.defaultOptions) {
return prepackSources([{ filePath: filename, fileContents: code, sourceMapContents: sourceMap }], options);
}
/* deprecated: please use prepackSources instead. */
function prepack(code, options = _options.defaultOptions) {
let filename = options.filename || "unknown";
let sources = [{ filePath: filename, fileContents: code }];
let realmOptions = (0, _prepackOptions.getRealmOptions)(options);
realmOptions.errorHandler = options.errorHandler;
let realm = (0, _construct_realm2.default)(realmOptions);
(0, _globals2.default)(realm);
let serializer = new _index2.default(realm, (0, _prepackOptions.getSerializerOptions)(options));
let serialized = serializer.init(sources, options.sourceMaps);
if (!serialized) {
throw new _errors.FatalError("serializer failed");
}
return serialized;
}
/* deprecated: please use prepackSources instead. */
function prepackFromAst(ast, code, options = _options.defaultOptions) {
if (ast && ast.type === "Program") {
ast = t.file(ast, [], []);
}
(0, _invariant2.default)(ast && ast.type === "File");
let filename = options.filename || ast.loc && ast.loc.source || "unknown";
let sources = [{ filePath: filename, fileContents: code }];
let realm = (0, _construct_realm2.default)((0, _prepackOptions.getRealmOptions)(options));
(0, _globals2.default)(realm);
let serializer = new _index2.default(realm, (0, _prepackOptions.getSerializerOptions)(options));
let serialized = serializer.init(sources, options.sourceMaps);
if (!serialized) {
throw new _errors.FatalError("serializer failed");
}
return serialized;
}
function checkResidualFunctions(modules, startFunc, totalToAnalyze) {
let realm = modules.realm;
let env = realm.$GlobalEnv;
realm.$GlobalObject.makeSimple();
let errorHandler = realm.errorHandler;
if (!errorHandler) errorHandler = diag => realm.handleError(diag);
realm.errorHandler = diag => {
(0, _invariant2.default)(errorHandler);
if (diag.severity === "FatalError") return errorHandler(diag);else return "Recover";
};
modules.resolveInitializedModules();
let residualHeapVisitor = new _ResidualHeapVisitor.ResidualHeapVisitor(realm, modules.logger, modules, new Map(), "NO_REFERENTIALIZE");
residualHeapVisitor.visitRoots();
if (modules.logger.hasErrors()) return;
let totalFunctions = 0;
let nonFatalFunctions = 0;
for (let fi of residualHeapVisitor.functionInstances.values()) {
totalFunctions++;
if (totalFunctions <= startFunc) continue;
let fv = fi.functionValue;
console.log("analyzing: " + totalFunctions);
let thisValue = realm.intrinsics.null;
let n = fv.getLength() || 0;
let args = [];
for (let i = 0; i < n; i++) {
let name = "dummy parameter";
let ob = _index4.AbstractValue.createFromType(realm, _index4.ObjectValue, name);
ob.makeSimple("transitive");
ob.intrinsicName = name;
args[i] = ob;
}
// todo: eventually join these effects, apply them to the global state and iterate to a fixed point
try {
realm.evaluateForEffectsInGlobalEnv(() => (0, _index3.EvaluateDirectCallWithArgList)(modules.realm, true, env, fv, fv, thisValue, args));
nonFatalFunctions++;
} catch (e) {}
if (totalFunctions >= startFunc + totalToAnalyze) break;
}
console.log(`Analyzed ${totalToAnalyze} functions starting at ${startFunc} of which ${nonFatalFunctions} did not have fatal errors.`);
}
const prepackVersion = exports.prepackVersion = _package.version;
//# sourceMappingURL=prepack-standalone.js.map