388 lines
16 KiB
JavaScript
388 lines
16 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
|
|
|
exports.default = function (realm) {
|
|
var intrinsicName = 'process.binding("contextify")';
|
|
var obj = new _index.ObjectValue(realm, realm.intrinsics.ObjectPrototype, intrinsicName);
|
|
|
|
// Contextify
|
|
|
|
function runInDebugContextImpl(code) {
|
|
// TODO: Make this an abstract result.
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.Error, "The V8 debugger is not available from within Prepack.");
|
|
}
|
|
|
|
function makeContextImpl() {
|
|
// TODO: Allow sub-realms to be created and restored.
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.Error, "makeContext is not yet implemented in Prepack.");
|
|
}
|
|
|
|
function isContextImpl() {
|
|
// TODO: We don't have a way to create contexts so this is always false.
|
|
return realm.intrinsics.false;
|
|
}
|
|
|
|
// ContextifyScript
|
|
|
|
var ContextifyScriptInternal = function ContextifyScriptInternal(ast) {
|
|
_classCallCheck(this, ContextifyScriptInternal);
|
|
|
|
this.ast = ast;
|
|
};
|
|
|
|
function ContextifyScriptConstructor(context, args, argLength, newTarget) {
|
|
if (!newTarget) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.Error, "Must call vm.Script as a constructor.");
|
|
}
|
|
var proto = (0, _index2.Get)(realm, newTarget, "prototype");
|
|
if (!(proto instanceof _index.ObjectValue)) {
|
|
realm = (0, _index2.GetFunctionRealm)(realm, newTarget);
|
|
proto = ContextifyScriptPrototype;
|
|
}
|
|
|
|
(0, _invariant2.default)(args[0] instanceof _index.ConcreteValue);
|
|
var code = _singletons.To.ToString(realm, args[0]);
|
|
|
|
var options = args[1];
|
|
var filename = getFilenameArg(options);
|
|
var lineOffset = getLineOffsetArg(options);
|
|
var columnOffset = getColumnOffsetArg(options);
|
|
var displayErrors = getDisplayErrorsArg(options);
|
|
var cachedDataBuf = getCachedData(options);
|
|
var produceCachedData = getProduceCachedData(options);
|
|
|
|
var resolvedOptions = {
|
|
filename: filename,
|
|
lineOffset: lineOffset,
|
|
columnOffset: columnOffset,
|
|
displayErrors: displayErrors,
|
|
cachedDataBuf: undefined, // Not serializable.
|
|
produceCachedData: produceCachedData
|
|
};
|
|
|
|
var intrinsicConstructor = "new (" + intrinsicName + ").ContextifyScript(" + JSON.stringify(code) + ", " + JSON.stringify(resolvedOptions) + ")";
|
|
|
|
var self = new _index.ObjectValue(realm, proto, intrinsicConstructor);
|
|
|
|
if (cachedDataBuf.length) {
|
|
_singletons.Properties.Set(realm, obj, "cachedDataRejected", realm.intrinsics.true, true);
|
|
}
|
|
|
|
if (produceCachedData) {
|
|
_singletons.Properties.Set(realm, obj, "cachedDataProduced", realm.intrinsics.false, true);
|
|
}
|
|
|
|
var ast = void 0;
|
|
try {
|
|
// TODO: Somehow pass columnOffset to Babylon.
|
|
ast = (0, _parse2.default)(realm, transform(code, filename), filename, "script", 1 + lineOffset);
|
|
} catch (e) {
|
|
if (displayErrors && e instanceof _completions.ThrowCompletion) {
|
|
decorateErrorStack(e);
|
|
}
|
|
throw e;
|
|
}
|
|
// TODO: Pick up source map files and automatically fix up source locations.
|
|
|
|
self.$InternalSlot = new ContextifyScriptInternal(ast);
|
|
|
|
return self;
|
|
}
|
|
|
|
var runInDebugContext = new _index.NativeFunctionValue(realm, intrinsicName + ".runInDebugContext", "runInDebugContext", 0, runInDebugContextImpl);
|
|
_singletons.Properties.Set(realm, obj, "runInDebugContext", runInDebugContext, true);
|
|
|
|
var makeContext = new _index.NativeFunctionValue(realm, intrinsicName + ".makeContext", "makeContext", 0, makeContextImpl);
|
|
_singletons.Properties.Set(realm, obj, "makeContext", makeContext, true);
|
|
|
|
var isContext = new _index.NativeFunctionValue(realm, intrinsicName + ".isContext", "isContext", 0, isContextImpl);
|
|
_singletons.Properties.Set(realm, obj, "isContext", isContext, true);
|
|
|
|
var ContextifyScript = new _index.NativeFunctionValue(realm, intrinsicName + ".ContextifyScript", "ContextifyScript", 0, ContextifyScriptConstructor, true);
|
|
_singletons.Properties.Set(realm, obj, "ContextifyScript", ContextifyScript, true);
|
|
|
|
// ContextifyScript.prototype
|
|
|
|
function runInThisContext(self, args) {
|
|
var timeout = getTimeoutArg(args[0]);
|
|
var displayErrors = getDisplayErrorsArg(args[0]);
|
|
var breakOnSigint = getBreakOnSigintArg(args[0]);
|
|
return evalMachine(self, timeout, displayErrors, breakOnSigint);
|
|
}
|
|
|
|
function runInContext(self, _ref) {
|
|
var _ref2 = _slicedToArray(_ref, 2),
|
|
sandbox = _ref2[0],
|
|
options = _ref2[1];
|
|
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.Error, "Cannot run in arbitrary contexts within Prepack yet.");
|
|
}
|
|
|
|
function decorateErrorStack(completion) {
|
|
var error = completion.value;
|
|
if (!(error instanceof _index.ObjectValue)) {
|
|
return;
|
|
}
|
|
|
|
var errorData = error.$ErrorData;
|
|
if (!errorData) {
|
|
return;
|
|
}
|
|
var errorLocation = errorData.locationData;
|
|
if (!errorLocation || errorLocation.stackDecorated) {
|
|
return;
|
|
}
|
|
|
|
var stack = (0, _index2.Get)(realm, error, "stack");
|
|
if (!(stack instanceof _index.StringValue)) {
|
|
return;
|
|
}
|
|
|
|
var lines = errorLocation.sourceCode.split(/\r?\n/);
|
|
var line = lines[errorLocation.loc.line - 1] || "";
|
|
var arrow = " ".repeat(errorLocation.loc.column) + "^";
|
|
var decoratedStack = errorLocation.filename + ":" + errorLocation.loc.line + "\n" + line + "\n" + arrow + "\n" + stack.value;
|
|
_singletons.Properties.Set(realm, error, "stack", new _index.StringValue(realm, decoratedStack), false);
|
|
|
|
errorLocation.stackDecorated = true;
|
|
}
|
|
|
|
function getBreakOnSigintArg(options) {
|
|
if (options instanceof _index.UndefinedValue || options instanceof _index.StringValue) {
|
|
return false;
|
|
}
|
|
if (!(options instanceof _index.ObjectValue)) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "options must be an object");
|
|
}
|
|
|
|
var value = (0, _index2.Get)(realm, options, "breakOnSigint");
|
|
(0, _invariant2.default)(value instanceof _index.ConcreteValue);
|
|
return value instanceof _index.BooleanValue && value.value;
|
|
}
|
|
|
|
function getTimeoutArg(options) {
|
|
if (options instanceof _index.UndefinedValue || options instanceof _index.StringValue) {
|
|
return -1;
|
|
}
|
|
if (!(options instanceof _index.ObjectValue)) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "options must be an object");
|
|
}
|
|
|
|
var value = (0, _index2.Get)(realm, options, "timeout");
|
|
(0, _invariant2.default)(value instanceof _index.ConcreteValue);
|
|
if (value instanceof _index.UndefinedValue) {
|
|
return -1;
|
|
}
|
|
var timeout = _singletons.To.ToInteger(realm, value);
|
|
|
|
if (timeout <= 0) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.RangeError, "timeout must be a positive number");
|
|
}
|
|
|
|
return timeout;
|
|
}
|
|
|
|
function getDisplayErrorsArg(options) {
|
|
if (options instanceof _index.UndefinedValue || options instanceof _index.StringValue) {
|
|
return true;
|
|
}
|
|
if (!(options instanceof _index.ObjectValue)) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "options must be an object");
|
|
}
|
|
|
|
var value = (0, _index2.Get)(realm, options, "displayErrors");
|
|
(0, _invariant2.default)(value instanceof _index.ConcreteValue);
|
|
if (value instanceof _index.UndefinedValue) {
|
|
return true;
|
|
}
|
|
return _singletons.To.ToBoolean(realm, value);
|
|
}
|
|
|
|
function getFilenameArg(options) {
|
|
var defaultFilename = "evalmachine.<anonymous>";
|
|
if (options instanceof _index.UndefinedValue) {
|
|
return defaultFilename;
|
|
}
|
|
if (options instanceof _index.StringValue) {
|
|
return options.value;
|
|
}
|
|
if (!(options instanceof _index.ObjectValue)) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "options must be an object");
|
|
}
|
|
|
|
var value = (0, _index2.Get)(realm, options, "filename");
|
|
(0, _invariant2.default)(value instanceof _index.ConcreteValue);
|
|
if (value instanceof _index.UndefinedValue) {
|
|
return defaultFilename;
|
|
}
|
|
return _singletons.To.ToString(realm, value);
|
|
}
|
|
|
|
function getCachedData(options) {
|
|
if (!(options instanceof _index.ObjectValue)) {
|
|
return new Uint8Array(0);
|
|
}
|
|
|
|
var value = (0, _index2.Get)(realm, options, "cachedData");
|
|
(0, _invariant2.default)(value instanceof _index.ConcreteValue);
|
|
if (value instanceof _index.UndefinedValue) {
|
|
return new Uint8Array(0);
|
|
}
|
|
|
|
if (!value.$ViewedArrayBuffer || !(value.$ViewedArrayBuffer.$ArrayBufferData instanceof Uint8Array)) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "options.cachedData must be a Buffer instance");
|
|
}
|
|
|
|
return value.$ViewedArrayBuffer.$ArrayBufferData;
|
|
}
|
|
|
|
function getProduceCachedData(options) {
|
|
if (!(options instanceof _index.ObjectValue)) {
|
|
return false;
|
|
}
|
|
|
|
var value = (0, _index2.Get)(realm, options, "produceCachedData");
|
|
(0, _invariant2.default)(value instanceof _index.ConcreteValue);
|
|
return value instanceof _index.BooleanValue && value.value;
|
|
}
|
|
|
|
function getLineOffsetArg(options) {
|
|
var defaultLineOffset = 0;
|
|
if (!(options instanceof _index.ObjectValue)) {
|
|
return defaultLineOffset;
|
|
}
|
|
var value = (0, _index2.Get)(realm, options, "lineOffset");
|
|
(0, _invariant2.default)(value instanceof _index.ConcreteValue);
|
|
return value instanceof _index.UndefinedValue ? defaultLineOffset : _singletons.To.ToInteger(realm, value);
|
|
}
|
|
|
|
function getColumnOffsetArg(options) {
|
|
var defaultColumnOffset = 0;
|
|
if (!(options instanceof _index.ObjectValue)) {
|
|
return defaultColumnOffset;
|
|
}
|
|
var value = (0, _index2.Get)(realm, options, "columnOffset");
|
|
(0, _invariant2.default)(value instanceof _index.ConcreteValue);
|
|
return value instanceof _index.UndefinedValue ? defaultColumnOffset : _singletons.To.ToInteger(realm, value);
|
|
}
|
|
|
|
function evalMachine(self, timeout, displayErrors, breakOnSigint) {
|
|
if (!(self instanceof _index.ObjectValue) || !(self.$InternalSlot instanceof ContextifyScriptInternal)) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.Error, "Script methods can only be called on script instances.");
|
|
}
|
|
var script = self.$InternalSlot;
|
|
|
|
var environment = realm.$GlobalEnv;
|
|
|
|
var previousContext = realm.getRunningContext();
|
|
previousContext.suspend();
|
|
|
|
var context = realm.createExecutionContext();
|
|
context.lexicalEnvironment = environment;
|
|
context.variableEnvironment = environment;
|
|
context.realm = realm;
|
|
|
|
realm.pushContext(context);
|
|
|
|
var result = void 0;
|
|
try {
|
|
result = environment.evaluateCompletion(script.ast, false);
|
|
} finally {
|
|
context.suspend();
|
|
realm.popContext(context);
|
|
(0, _invariant2.default)(context.lexicalEnvironment === realm.$GlobalEnv);
|
|
realm.onDestroyScope(context.lexicalEnvironment);
|
|
}
|
|
(0, _invariant2.default)(realm.getRunningContext() === previousContext);
|
|
previousContext.resume();
|
|
|
|
if (result instanceof _index.EmptyValue) {
|
|
return realm.intrinsics.undefined;
|
|
} else if (result instanceof _index.Value) {
|
|
return result;
|
|
} else {
|
|
(0, _invariant2.default)(result instanceof _completions.AbruptCompletion);
|
|
if (displayErrors) {
|
|
decorateErrorStack(result);
|
|
}
|
|
throw result;
|
|
}
|
|
}
|
|
|
|
var ContextifyScriptPrototype = new _index.ObjectValue(realm, realm.intrinsics.ObjectPrototype, intrinsicName + ".ContextifyScript.prototype");
|
|
|
|
ContextifyScriptPrototype.defineNativeMethod("runInContext", 2, runInContext);
|
|
ContextifyScriptPrototype.defineNativeMethod("runInThisContext", 1, runInThisContext);
|
|
|
|
_singletons.Properties.DefinePropertyOrThrow(realm, ContextifyScript, "prototype", {
|
|
value: ContextifyScriptPrototype,
|
|
writable: true,
|
|
enumerable: false,
|
|
configurable: false
|
|
});
|
|
|
|
_singletons.Properties.DefinePropertyOrThrow(realm, ContextifyScriptPrototype, "constructor", {
|
|
value: ContextifyScript,
|
|
writable: true,
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
|
|
return obj;
|
|
};
|
|
|
|
var _invariant = require("../../invariant.js");
|
|
|
|
var _invariant2 = _interopRequireDefault(_invariant);
|
|
|
|
var _realm = require("../../realm.js");
|
|
|
|
var _completions = require("../../completions.js");
|
|
|
|
var _index = require("../../values/index.js");
|
|
|
|
var _index2 = require("../../methods/index.js");
|
|
|
|
var _singletons = require("../../singletons.js");
|
|
|
|
var _parse = require("../../utils/parse.js");
|
|
|
|
var _parse2 = _interopRequireDefault(_parse);
|
|
|
|
var _babelCore = require("babel-core");
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
|
|
* 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.
|
|
*/
|
|
|
|
// TODO: This creates a strong dependency on babel and its transforms even
|
|
// outside of devDependencies which is unfortunate. Get rid of this once classes
|
|
// and destructuring is fully implemented.
|
|
|
|
|
|
// Hook for transpiling
|
|
function transform(code, filename) {
|
|
var patchedCode = code.replace(
|
|
// Work around the fact that Babel classes can't extend natives.
|
|
/class FastBuffer extends Uint8Array {\s+constructor\(arg1, arg2, arg3\) {\s+super\(arg1, arg2, arg3\);\s+}\s+}/g, "function FastBuffer(arg1, arg2, arg3) {\n" + " var self = new Uint8Array(arg1, arg2, arg3);\n" + " Object.setPrototypeOf(self, FastBuffer.prototype);\n" + " return self;\n" + "}; Object.setPrototypeOf(FastBuffer, Uint8Array); Object.setPrototypeOf(FastBuffer.prototype, Uint8Array.prototype);");
|
|
var transformedCode = (0, _babelCore.transform)(patchedCode, {
|
|
plugins: [
|
|
// Prepack doesn't support classes or destructuring yet.
|
|
"transform-es2015-classes", "transform-es2015-destructuring", "transform-es2015-parameters"],
|
|
retainLines: true
|
|
});
|
|
return transformedCode.code;
|
|
}
|
|
//# sourceMappingURL=contextify.js.map
|