mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-09-11 14:46:37 +03:00
Refactor global intrinsics initialization (#477)
We used initialize all possible environments in a single intrinsics entry point. That doesn't quite scale to many and complex environments. So the goal of this refactor is to invert the initialization of globals. Now a Realm is created with only the standard ECMA262 intrinsics. This is also important because we should be able to create new realms from within user code to model things like iframes, node.js contextify and the new standard Realm API that is used to create new realms. All of these basically starts out with a standard realm that can then be expanded. Then the actual initialization of the global happens outside of the serializer so that the serializer dependency isn't coupled to any particular set of environments. To do this I created a "global.js" file for each environment inside of intrinsics. It's interesting to note that "console" and timers isn't part of the standard realm. Another interesting one is that "global" isn't actually part of the DOM environment yet. It might be if this proposal gets through: https://github.com/tc39/proposal-global However, since so many tests depend on global, including in test262, I model it as already part of ECMA262 globals. I also had move the initialization of the realm out of the serializer API so that it is possible to initialize the realm with arbitrary intrinsics before that happens. However, when I did that I had to move the attaching of of the generator into the serializer because otherwise mutations to intrinsics during initialization gets tracked as something to serialize. This might help avoid the cycle problem that construct_realm was meant to fix so that we can just go back to using a simple constructor for Realm.
This commit is contained in:
parent
752761c7b9
commit
8f9e912deb
@ -60,8 +60,8 @@ madge('./lib/').then((res) => {
|
||||
}
|
||||
|
||||
for (let dep in deps) {
|
||||
// Nothing in intrinsics/ecma262 depends on anything but intrinsics/index except Error.
|
||||
if (dep.startsWith("intrinsics/ecma262") && dep !== "intrinsics/ecma262/Error") {
|
||||
// Nothing in intrinsics/ecma262 depends on anything but intrinsics/index except Error and global.
|
||||
if (dep.startsWith("intrinsics/ecma262") && dep !== "intrinsics/ecma262/Error" && dep !== "intrinsics/ecma262/global") {
|
||||
let ext_deps =
|
||||
res.depends(dep).filter(
|
||||
(depend) => depend !== "intrinsics/index" && !depend.startsWith("intrinsics/ecma262"));
|
||||
|
@ -10,6 +10,8 @@
|
||||
/* @flow */
|
||||
|
||||
import Serializer from "../lib/serializer/index.js";
|
||||
import construct_realm from "../lib/construct_realm.js";
|
||||
import initializeGlobals from "../lib/globals.js";
|
||||
import invariant from "../lib/invariant.js";
|
||||
|
||||
let chalk = require("chalk");
|
||||
@ -43,7 +45,10 @@ function generateTest(name: string, test_path: string, code: string): boolean {
|
||||
console.log(chalk.inverse(name));
|
||||
let newCode1, newMap1, newCode2, newMap2;
|
||||
try {
|
||||
let s = new Serializer({ partial: true }, { internalDebug: true }).init(test_path, code, "", true);
|
||||
let realm = construct_realm({ partial: true });
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(realm, { internalDebug: true });
|
||||
let s = serializer.init(test_path, code, "", true);
|
||||
if (!s) {
|
||||
process.exit(1);
|
||||
invariant(false);
|
||||
@ -52,7 +57,10 @@ function generateTest(name: string, test_path: string, code: string): boolean {
|
||||
fs.writeFileSync(name + ".new1.js", newCode1);
|
||||
newMap1 = s.map;
|
||||
fs.writeFileSync(name + ".new1.js.map", JSON.stringify(newMap1));
|
||||
s = new Serializer({ partial: true, compatibility: "node" }, { internalDebug: true }).init(
|
||||
realm = construct_realm({ partial: true, compatibility: "node" });
|
||||
initializeGlobals(realm);
|
||||
serializer = new Serializer(realm, { internalDebug: true });
|
||||
s = serializer.init(
|
||||
test_path, newCode1, JSON.stringify(newMap1), true);
|
||||
if (!s) {
|
||||
process.exit(1);
|
||||
|
@ -10,6 +10,8 @@
|
||||
/* @flow */
|
||||
|
||||
import Serializer from "../lib/serializer/index.js";
|
||||
import construct_realm from "../lib/construct_realm.js";
|
||||
import initializeGlobals from "../lib/globals.js";
|
||||
|
||||
let chalk = require("chalk");
|
||||
let path = require("path");
|
||||
@ -41,7 +43,10 @@ let tests = search(`${__dirname}/../test/internal`, "test/internal");
|
||||
function runTest(name: string, code: string): boolean {
|
||||
console.log(chalk.inverse(name));
|
||||
try {
|
||||
let serialized = new Serializer({ partial: true, compatibility: "jsc-600-1-4-17", mathRandomSeed: "0" }, { internalDebug: true, initializeMoreModules: true }).init(name, code, "", false);
|
||||
let realm = construct_realm({ partial: true, compatibility: "jsc-600-1-4-17", mathRandomSeed: "0" });
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(realm, { internalDebug: true, initializeMoreModules: true });
|
||||
let serialized = serializer.init(name, code, "", false);
|
||||
if (!serialized) {
|
||||
console.log(chalk.red("Error during serialization"));
|
||||
return false;
|
||||
|
@ -10,6 +10,8 @@
|
||||
/* @flow */
|
||||
|
||||
let Serializer = require("../lib/serializer/index.js").default;
|
||||
let construct_realm = require("../lib/construct_realm.js").default;
|
||||
let initializeGlobals = require("../lib/globals.js").default;
|
||||
let IsIntrospectionError = require("../lib/methods/index.js").IsIntrospectionError;
|
||||
|
||||
let chalk = require("chalk");
|
||||
@ -86,7 +88,10 @@ function runTest(name, code) {
|
||||
throw new Success();
|
||||
};
|
||||
try {
|
||||
let serialized = new Serializer(realmOptions, serializerOptions).init(name, code, "", false, onError);
|
||||
let realm = construct_realm(realmOptions);
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(realm, serializerOptions);
|
||||
let serialized = serializer.init(name, code, "", false, onError);
|
||||
if (!serialized) {
|
||||
console.log(chalk.red("Error during serialization"));
|
||||
} else {
|
||||
@ -100,7 +105,10 @@ function runTest(name, code) {
|
||||
return false;
|
||||
} else if (code.includes("// no effect")) {
|
||||
try {
|
||||
let serialized = new Serializer(realmOptions, serializerOptions).init(name, code);
|
||||
let realm = construct_realm(realmOptions);
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(realm, serializerOptions);
|
||||
let serialized = serializer.init(name, code);
|
||||
if (!serialized) {
|
||||
console.log(chalk.red("Error during serialization!"));
|
||||
return false;
|
||||
@ -140,7 +148,10 @@ function runTest(name, code) {
|
||||
for (; i < max; i++) {
|
||||
let newUniqueSuffix = `_unique${unique++}`;
|
||||
realmOptions.uniqueSuffix = newUniqueSuffix;
|
||||
let serialized = new Serializer(realmOptions, serializerOptions).init(name, oldCode);
|
||||
let realm = construct_realm(realmOptions);
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(realm, serializerOptions);
|
||||
let serialized = serializer.init(name, oldCode);
|
||||
if (!serialized) {
|
||||
console.log(chalk.red("Error during serialization!"));
|
||||
break;
|
||||
|
@ -13,6 +13,7 @@ import { AbruptCompletion, ThrowCompletion } from "../lib/completions.js";
|
||||
import { ObjectValue, StringValue } from "../lib/values/index.js";
|
||||
import { Realm, ExecutionContext } from "../lib/realm.js";
|
||||
import construct_realm from "../lib/construct_realm.js";
|
||||
import initializeGlobals from "../lib/globals.js";
|
||||
import { DetachArrayBuffer } from "../lib/methods/arraybuffer.js";
|
||||
import { ToStringPartial } from "../lib/methods/to.js";
|
||||
import { Get } from "../lib/methods/get.js";
|
||||
@ -901,6 +902,7 @@ function prepareTest(
|
||||
function createRealm(timeout: number): { realm: Realm, $: ObjectValue } {
|
||||
// Create a new realm.
|
||||
let realm = construct_realm({ timeout: timeout * 1000 });
|
||||
initializeGlobals(realm);
|
||||
let executionContext = new ExecutionContext();
|
||||
executionContext.realm = realm;
|
||||
realm.pushContext(executionContext);
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
import type { Compatibility } from "./types.js";
|
||||
import Serializer from "./serializer/index.js";
|
||||
import construct_realm from "./construct_realm.js";
|
||||
import initializeGlobals from "./globals.js";
|
||||
import invariant from "./invariant.js";
|
||||
|
||||
let chalk = require("chalk");
|
||||
@ -130,7 +132,10 @@ function dump(name: string, raw: string, min: string = raw, compatibility?: "bro
|
||||
let beforeStats = line("Before", min, compatibility);
|
||||
|
||||
let start = Date.now();
|
||||
let serialized = new Serializer({ partial: true, compatibility }).init(name, raw);
|
||||
let realm = construct_realm({ partial: true, compatibility });
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(realm);
|
||||
let serialized = serializer.init(name, raw);
|
||||
if (!serialized) {
|
||||
process.exit(1);
|
||||
invariant(false);
|
||||
|
@ -11,22 +11,21 @@
|
||||
|
||||
import { Realm } from "./realm.js";
|
||||
import { initialize as initializeIntrinsics } from "./intrinsics/index.js";
|
||||
import initializeGlobal from "./global.js";
|
||||
import initializeGlobal from "./intrinsics/ecma262/global.js";
|
||||
import type { RealmOptions } from "./types.js";
|
||||
import * as evaluators from "./evaluators/index.js";
|
||||
import { NewGlobalEnvironment } from "./methods/index.js";
|
||||
import { Generator } from "./utils/generator.js";
|
||||
|
||||
import { ObjectValue } from "./values/index.js";
|
||||
|
||||
export default function(opts: RealmOptions = {}): Realm {
|
||||
let r = new Realm(opts);
|
||||
let i = r.intrinsics;
|
||||
initializeIntrinsics(i, r);
|
||||
r.$GlobalObject = initializeGlobal(r);
|
||||
// TODO: Find a way to let different environments initialize their own global
|
||||
// object for special magic host objects such as the window object in the DOM.
|
||||
r.$GlobalObject = new ObjectValue(r, i.ObjectPrototype, "this");
|
||||
initializeGlobal(r);
|
||||
for (let name in evaluators) r.evaluators[name] = evaluators[name];
|
||||
r.$GlobalEnv = NewGlobalEnvironment(r, r.$GlobalObject, r.$GlobalObject);
|
||||
if (opts.partial) {
|
||||
r.generator = new Generator(r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
26
src/globals.js
Normal file
26
src/globals.js
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @flow */
|
||||
|
||||
import type { Realm } from "./realm.js";
|
||||
import initializePrepackGlobals from "./intrinsics/prepack/global.js";
|
||||
import initializeDOMGlobals from "./intrinsics/dom/global.js";
|
||||
import initializeReactNativeGlobals from "./intrinsics/react-native/global.js";
|
||||
|
||||
export default function (realm: Realm): Realm {
|
||||
initializePrepackGlobals(realm);
|
||||
if (realm.isCompatibleWith("browser")) {
|
||||
initializeDOMGlobals(realm);
|
||||
}
|
||||
if (realm.isCompatibleWith(realm.MOBILE_JSC_VERSION)) {
|
||||
initializeReactNativeGlobals(realm);
|
||||
}
|
||||
return realm;
|
||||
}
|
66
src/intrinsics/dom/global.js
Normal file
66
src/intrinsics/dom/global.js
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @flow */
|
||||
|
||||
import type { Realm } from "../../realm.js";
|
||||
|
||||
import { NativeFunctionValue } from "../../values/index.js";
|
||||
import initializeDocument from "./document.js";
|
||||
import initializeConsole from "../common/console.js";
|
||||
|
||||
export default function (realm: Realm): void {
|
||||
let global = realm.$GlobalObject;
|
||||
|
||||
global.$DefineOwnProperty("console", {
|
||||
value: initializeConsole(realm),
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
global.$DefineOwnProperty("self", {
|
||||
value: global,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
global.$DefineOwnProperty("window", {
|
||||
value: global,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
global.$DefineOwnProperty("document", {
|
||||
value: initializeDocument(realm),
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
global.$DefineOwnProperty("setTimeout", {
|
||||
value: new NativeFunctionValue(realm, "global.setTimeout", "", 2, (context, args) => {
|
||||
throw new Error("TODO: implement global.setTimeout");
|
||||
}),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
global.$DefineOwnProperty("setInterval", {
|
||||
value: new NativeFunctionValue(realm, "global.setInterval", "", 2, (context, args) => {
|
||||
throw new Error("TODO: implement global.setInterval");
|
||||
}),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
}
|
109
src/intrinsics/ecma262/global.js
Normal file
109
src/intrinsics/ecma262/global.js
Normal file
@ -0,0 +1,109 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @flow */
|
||||
|
||||
import type { Realm } from "../../realm.js";
|
||||
|
||||
export default function (realm: Realm): void {
|
||||
let global = realm.$GlobalObject;
|
||||
|
||||
global.$DefineOwnProperty("global", {
|
||||
value: global,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
for (let name of [
|
||||
"undefined",
|
||||
"NaN",
|
||||
"Infinity"
|
||||
]) {
|
||||
global.$DefineOwnProperty(name, {
|
||||
value: realm.intrinsics[name],
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false
|
||||
});
|
||||
}
|
||||
let typeNames = [
|
||||
"String",
|
||||
"Object",
|
||||
"Function",
|
||||
"Array",
|
||||
"Number",
|
||||
"RegExp",
|
||||
"Date",
|
||||
"Math",
|
||||
"Error",
|
||||
"Function",
|
||||
"TypeError",
|
||||
"RangeError",
|
||||
"ReferenceError",
|
||||
"SyntaxError",
|
||||
"URIError",
|
||||
"EvalError",
|
||||
"Boolean",
|
||||
"DataView",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
"Int8Array",
|
||||
"Int16Array",
|
||||
"Int32Array",
|
||||
"Map",
|
||||
"WeakMap",
|
||||
"Set",
|
||||
"Uint8Array",
|
||||
"Uint8ClampedArray",
|
||||
"Uint16Array",
|
||||
"Uint32Array",
|
||||
"ArrayBuffer",
|
||||
"JSON"
|
||||
];
|
||||
if (!realm.isCompatibleWith(realm.MOBILE_JSC_VERSION))
|
||||
typeNames = typeNames.concat(
|
||||
"Symbol",
|
||||
"Promise",
|
||||
"WeakSet",
|
||||
"WeakMap",
|
||||
"Proxy",
|
||||
"Reflect"
|
||||
);
|
||||
for (let name of typeNames) {
|
||||
// need to check if the property exists (it may not due to --compatibility)
|
||||
if (realm.intrinsics[name]) {
|
||||
global.$DefineOwnProperty(name, {
|
||||
value: realm.intrinsics[name],
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
for (let name of [
|
||||
"parseFloat",
|
||||
"parseInt",
|
||||
"console",
|
||||
"isNaN",
|
||||
"eval",
|
||||
"isFinite",
|
||||
"encodeURI",
|
||||
"decodeURI",
|
||||
"encodeURIComponent",
|
||||
"decodeURIComponent"
|
||||
]) {
|
||||
global.$DefineOwnProperty(name, {
|
||||
value: realm.intrinsics[name],
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
@ -120,7 +120,6 @@ import initializeArrayBufferPrototype from "./ecma262/ArrayBufferPrototype.js";
|
||||
import initializeJSON from "./ecma262/JSON.js";
|
||||
import initializeReflect from "./ecma262/Reflect.js";
|
||||
import initializeMath from "./ecma262/Math.js";
|
||||
import initializeConsole from "./ecma262/console.js";
|
||||
|
||||
import initializeProxy from "./ecma262/Proxy.js";
|
||||
|
||||
@ -145,9 +144,8 @@ import initializeObjectProto_toString from "./ecma262/ObjectProto_toString.js";
|
||||
import initializeTypedArrayProto_values from "./ecma262/TypedArrayProto_values.js";
|
||||
import initializeThrowTypeError from "./ecma262/ThrowTypeError.js";
|
||||
|
||||
import initializeDocument from "./dom/document.js";
|
||||
import initialize__IntrospectionError from "./__IntrospectionError.js";
|
||||
import initialize__IntrospectionErrorPrototype from "./__IntrospectionErrorPrototype.js";
|
||||
import initialize__IntrospectionError from "./prepack/__IntrospectionError.js";
|
||||
import initialize__IntrospectionErrorPrototype from "./prepack/__IntrospectionErrorPrototype.js";
|
||||
|
||||
|
||||
export function initialize(i: Intrinsics, realm: Realm): Intrinsics {
|
||||
@ -292,9 +290,6 @@ export function initialize(i: Intrinsics, realm: Realm): Intrinsics {
|
||||
initializeMapIteratorPrototype(realm, i.MapIteratorPrototype);
|
||||
initializeSetIteratorPrototype(realm, i.SetIteratorPrototype);
|
||||
|
||||
// browser
|
||||
i.document = initializeDocument(realm);
|
||||
|
||||
//
|
||||
i.Object = initializeObject(realm);
|
||||
i.Function = initializeFunction(realm);
|
||||
@ -450,7 +445,6 @@ export function initialize(i: Intrinsics, realm: Realm): Intrinsics {
|
||||
i.encodeURIComponent = initializeEncodeURIComponent(realm);
|
||||
i.ThrowTypeError = initializeThrowTypeError(realm);
|
||||
i.eval = initializeEval(realm);
|
||||
i.console = initializeConsole(realm);
|
||||
|
||||
// 8.2.2, step 12
|
||||
AddRestrictedFunctionProperties(i.FunctionPrototype, realm);
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
/* @flow */
|
||||
|
||||
import type { Realm } from "../realm.js";
|
||||
import type { NativeFunctionValue } from "../values/index.js";
|
||||
import { build } from "./ecma262/Error.js";
|
||||
import type { Realm } from "../../realm.js";
|
||||
import type { NativeFunctionValue } from "../../values/index.js";
|
||||
import { build } from "../ecma262/Error.js";
|
||||
|
||||
export default function (realm: Realm): NativeFunctionValue {
|
||||
return build("__IntrospectionError", realm, false);
|
@ -9,8 +9,8 @@
|
||||
|
||||
/* @flow */
|
||||
|
||||
import type { Realm } from "../realm.js";
|
||||
import { ObjectValue, StringValue } from "../values/index.js";
|
||||
import type { Realm } from "../../realm.js";
|
||||
import { ObjectValue, StringValue } from "../../values/index.js";
|
||||
|
||||
export default function (realm: Realm, obj: ObjectValue): void {
|
||||
obj.defineNativeProperty("name", new StringValue(realm, "__IntrospectionError"));
|
@ -9,63 +9,24 @@
|
||||
|
||||
/* @flow */
|
||||
|
||||
import type { Realm } from "./realm.js";
|
||||
import { Value, StringValue, BooleanValue, ObjectValue, FunctionValue, NativeFunctionValue, AbstractValue, AbstractObjectValue, UndefinedValue } from "./values/index.js";
|
||||
import { ToStringPartial } from "./methods/index.js";
|
||||
import { ThrowCompletion } from "./completions.js";
|
||||
import { Construct, ObjectCreate } from "./methods/index.js";
|
||||
import { TypesDomain, ValuesDomain } from "./domains/index.js";
|
||||
import buildExpressionTemplate from "./utils/builder.js";
|
||||
import type { Realm } from "../../realm.js";
|
||||
import { Value, StringValue, BooleanValue, ObjectValue, FunctionValue, NativeFunctionValue, AbstractValue, AbstractObjectValue, UndefinedValue } from "../../values/index.js";
|
||||
import { ToStringPartial } from "../../methods/index.js";
|
||||
import { ThrowCompletion } from "../../completions.js";
|
||||
import { Construct, ObjectCreate } from "../../methods/index.js";
|
||||
import { TypesDomain, ValuesDomain } from "../../domains/index.js";
|
||||
import buildExpressionTemplate from "../../utils/builder.js";
|
||||
import * as t from "babel-types";
|
||||
import type { BabelNodeExpression, BabelNodeSpreadElement, BabelNodeIdentifier } from "babel-types";
|
||||
import invariant from "./invariant.js";
|
||||
import { describeLocation } from "./intrinsics/ecma262/Error.js";
|
||||
import invariant from "../../invariant.js";
|
||||
import { describeLocation } from "../ecma262/Error.js";
|
||||
|
||||
let buildThrowErrorAbstractValue = buildExpressionTemplate("(function(){throw new Error('abstract value defined at ' + LOCATION);})()");
|
||||
|
||||
export default function (realm: Realm): ObjectValue {
|
||||
let obj = new ObjectValue(realm, realm.intrinsics.ObjectPrototype, "this");
|
||||
export default function (realm: Realm): void {
|
||||
let global = realm.$GlobalObject;
|
||||
|
||||
obj.$DefineOwnProperty("global", {
|
||||
value: obj,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
if (realm.isCompatibleWith("browser")) obj.$DefineOwnProperty("self", {
|
||||
value: obj,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
if (realm.isCompatibleWith("browser")) obj.$DefineOwnProperty("window", {
|
||||
value: obj,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
obj.$DefineOwnProperty("setTimeout", {
|
||||
value: new NativeFunctionValue(realm, "global.setTimeout", "", 2, (context, args) => {
|
||||
throw new Error("TODO: implement global.setTimeout");
|
||||
}),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
obj.$DefineOwnProperty("setInterval", {
|
||||
value: new NativeFunctionValue(realm, "global.setInterval", "", 2, (context, args) => {
|
||||
throw new Error("TODO: implement global.setInterval");
|
||||
}),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
obj.$DefineOwnProperty("dump", {
|
||||
global.$DefineOwnProperty("dump", {
|
||||
value: new NativeFunctionValue(realm, "global.dump", "dump", 0, (context, args) => {
|
||||
console.log("dump", args.map((arg) => arg.serialize()));
|
||||
return context;
|
||||
@ -102,7 +63,7 @@ export default function (realm: Realm): ObjectValue {
|
||||
// where typeNameOrTemplate either either 'string', 'boolean', 'number', 'object', or an actual object defining known properties.
|
||||
// If the abstract value gets somehow embedded in the final heap,
|
||||
// it will be referred to by the supplied name in the generated code.
|
||||
obj.$DefineOwnProperty("__abstract", {
|
||||
global.$DefineOwnProperty("__abstract", {
|
||||
value: new NativeFunctionValue(realm, "global.__abstract", "__abstract", 0, (context, [typeNameOrTemplate, name]) => {
|
||||
if (!realm.isPartial) {
|
||||
throw new ThrowCompletion(
|
||||
@ -148,7 +109,7 @@ export default function (realm: Realm): ObjectValue {
|
||||
// where typeNameOrTemplate either either 'string', 'boolean', 'number', 'object', or an actual object defining known properties.
|
||||
// The function must not have side effects, and it must not access any state (besides the supplied arguments).
|
||||
// TODO: In some distant future, Prepack should be able to figure out automatically what computations need to remain part of the residual program.
|
||||
obj.$DefineOwnProperty("__residual", {
|
||||
global.$DefineOwnProperty("__residual", {
|
||||
value: new NativeFunctionValue(realm, "global.__residual", "__residual", 2, (context, [typeNameOrTemplate, f, ...args]) => {
|
||||
if (!realm.isPartial) {
|
||||
throw new ThrowCompletion(
|
||||
@ -181,7 +142,7 @@ export default function (realm: Realm): ObjectValue {
|
||||
});
|
||||
|
||||
// TODO: Remove this property. It's just here as some existing internal test cases assume that the __annotate property is exists and is readable.
|
||||
obj.$DefineOwnProperty("__annotate", {
|
||||
global.$DefineOwnProperty("__annotate", {
|
||||
value: realm.intrinsics.undefined,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
@ -190,7 +151,7 @@ export default function (realm: Realm): ObjectValue {
|
||||
|
||||
// Internal helper function for tests.
|
||||
// __isAbstract(value) checks if a given value is abstract.
|
||||
obj.$DefineOwnProperty("__isAbstract", {
|
||||
global.$DefineOwnProperty("__isAbstract", {
|
||||
value: new NativeFunctionValue(realm, "global.__isAbstract", "__isAbstract", 1, (context, [value]) => {
|
||||
return new BooleanValue(realm, value instanceof AbstractValue);
|
||||
}),
|
||||
@ -200,7 +161,7 @@ export default function (realm: Realm): ObjectValue {
|
||||
});
|
||||
|
||||
// __makePartial(object) marks an (abstract) object as partial.
|
||||
obj.$DefineOwnProperty("__makePartial", {
|
||||
global.$DefineOwnProperty("__makePartial", {
|
||||
value: new NativeFunctionValue(realm, "global.__makePartial", "__isPartial", 1, (context, [object]) => {
|
||||
// casting to any to avoid Flow bug
|
||||
if ((object: any) instanceof AbstractObjectValue || (object: any) instanceof ObjectValue) {
|
||||
@ -217,7 +178,7 @@ export default function (realm: Realm): ObjectValue {
|
||||
});
|
||||
|
||||
// __makeSimple(object) marks an (abstract) object as one that has no getters or setters.
|
||||
obj.$DefineOwnProperty("__makeSimple", {
|
||||
global.$DefineOwnProperty("__makeSimple", {
|
||||
value: new NativeFunctionValue(realm, "global.__makeSimple", "__makeSimple", 1, (context, [object]) => {
|
||||
// casting to any to avoid Flow bug
|
||||
if ((object: any) instanceof AbstractObjectValue || (object: any) instanceof ObjectValue) {
|
||||
@ -234,7 +195,7 @@ export default function (realm: Realm): ObjectValue {
|
||||
});
|
||||
|
||||
// Helper function that emits a check whether a given object property has a particular value.
|
||||
obj.$DefineOwnProperty("__assumeDataProperty", {
|
||||
global.$DefineOwnProperty("__assumeDataProperty", {
|
||||
value: new NativeFunctionValue(realm, "global.__assumeDataProperty", "__assumeDataProperty", 3, (context, [object, propertyName, value]) => {
|
||||
if (!realm.isPartial) {
|
||||
throw new ThrowCompletion(
|
||||
@ -269,134 +230,10 @@ export default function (realm: Realm): ObjectValue {
|
||||
configurable: true
|
||||
});
|
||||
|
||||
for (let name of [
|
||||
"undefined",
|
||||
"NaN",
|
||||
"Infinity"
|
||||
]) {
|
||||
obj.$DefineOwnProperty(name, {
|
||||
value: realm.intrinsics[name],
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false
|
||||
});
|
||||
}
|
||||
let typeNames = [
|
||||
"String",
|
||||
"Object",
|
||||
"Function",
|
||||
"Array",
|
||||
"Number",
|
||||
"RegExp",
|
||||
"Date",
|
||||
"Math",
|
||||
"Error",
|
||||
"Function",
|
||||
"TypeError",
|
||||
"RangeError",
|
||||
"ReferenceError",
|
||||
"SyntaxError",
|
||||
"URIError",
|
||||
"EvalError",
|
||||
"Boolean",
|
||||
"DataView",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
"Int8Array",
|
||||
"Int16Array",
|
||||
"Int32Array",
|
||||
"Map",
|
||||
"WeakMap",
|
||||
"Set",
|
||||
"Uint8Array",
|
||||
"Uint8ClampedArray",
|
||||
"Uint16Array",
|
||||
"Uint32Array",
|
||||
"ArrayBuffer",
|
||||
"JSON",
|
||||
"__IntrospectionError"
|
||||
];
|
||||
if (!realm.isCompatibleWith(realm.MOBILE_JSC_VERSION))
|
||||
typeNames = typeNames.concat(
|
||||
"Symbol",
|
||||
"Promise",
|
||||
"WeakSet",
|
||||
"WeakMap",
|
||||
"Proxy",
|
||||
"Reflect",
|
||||
);
|
||||
for (let name of typeNames) {
|
||||
// need to check if the property exists (it may not due to --compatibility)
|
||||
if (realm.intrinsics[name]) {
|
||||
obj.$DefineOwnProperty(name, {
|
||||
value: realm.intrinsics[name],
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
if (realm.isCompatibleWith(realm.MOBILE_JSC_VERSION)) {
|
||||
for (let name of [
|
||||
"window",
|
||||
"process",
|
||||
"setImmediate",
|
||||
"clearTimeout",
|
||||
"clearInterval",
|
||||
"clearImmediate",
|
||||
"alert",
|
||||
"navigator",
|
||||
"module",
|
||||
"requestAnimationFrame",
|
||||
"cancelAnimationFrame",
|
||||
"requestIdleCallback",
|
||||
"cancelIdleCallback",
|
||||
"Symbol",
|
||||
"Promise",
|
||||
"WeakSet",
|
||||
"WeakMap",
|
||||
"Proxy",
|
||||
"WebSocket",
|
||||
"Request",
|
||||
"Response",
|
||||
"Headers",
|
||||
"FormData",
|
||||
"Worker",
|
||||
"Node",
|
||||
"Blob",
|
||||
"URLSearchParams",
|
||||
"FileReader",
|
||||
"XMLHttpRequest"
|
||||
]) {
|
||||
obj.$DefineOwnProperty(name, {
|
||||
value: realm.intrinsics.undefined,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (let name of [
|
||||
"parseFloat",
|
||||
"parseInt",
|
||||
"console",
|
||||
"isNaN",
|
||||
"eval",
|
||||
"isFinite",
|
||||
"encodeURI",
|
||||
"decodeURI",
|
||||
"encodeURIComponent",
|
||||
"decodeURIComponent",
|
||||
"document"
|
||||
]) {
|
||||
obj.$DefineOwnProperty(name, {
|
||||
value: realm.intrinsics[name],
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
return obj;
|
||||
global.$DefineOwnProperty("__IntrospectionError", {
|
||||
value: realm.intrinsics.__IntrospectionError,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
70
src/intrinsics/react-native/global.js
vendored
Normal file
70
src/intrinsics/react-native/global.js
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @flow */
|
||||
|
||||
import type { Realm } from "../../realm.js";
|
||||
|
||||
import initializeConsole from "../common/console.js";
|
||||
|
||||
export default function (realm: Realm): void {
|
||||
let global = realm.$GlobalObject;
|
||||
|
||||
global.$DefineOwnProperty("console", {
|
||||
value: initializeConsole(realm),
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
for (let name of [
|
||||
// TODO: I'm not sure if these three document, setTimeout and setInterval
|
||||
// should be here.
|
||||
"document",
|
||||
"setTimeout",
|
||||
"setInterval",
|
||||
|
||||
"window",
|
||||
"process",
|
||||
"setImmediate",
|
||||
"clearTimeout",
|
||||
"clearInterval",
|
||||
"clearImmediate",
|
||||
"alert",
|
||||
"navigator",
|
||||
"module",
|
||||
"requestAnimationFrame",
|
||||
"cancelAnimationFrame",
|
||||
"requestIdleCallback",
|
||||
"cancelIdleCallback",
|
||||
"Symbol",
|
||||
"Promise",
|
||||
"WeakSet",
|
||||
"WeakMap",
|
||||
"Proxy",
|
||||
"WebSocket",
|
||||
"Request",
|
||||
"Response",
|
||||
"Headers",
|
||||
"FormData",
|
||||
"Worker",
|
||||
"Node",
|
||||
"Blob",
|
||||
"URLSearchParams",
|
||||
"FileReader",
|
||||
"XMLHttpRequest"
|
||||
]) {
|
||||
global.$DefineOwnProperty(name, {
|
||||
value: realm.intrinsics.undefined,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@
|
||||
|
||||
/* @flow */
|
||||
import Serializer from "./serializer/index.js";
|
||||
import construct_realm from "./construct_realm.js";
|
||||
import initializeGlobals from "./globals.js";
|
||||
import fs from "fs";
|
||||
import { getRealmOptions, getSerializerOptions } from "./options";
|
||||
import { InitializationError } from "./prepack-standalone";
|
||||
@ -31,10 +33,13 @@ export function prepackFile(filename: string, options: Options = {}, callback: F
|
||||
}
|
||||
let serialized;
|
||||
try {
|
||||
serialized = new Serializer(
|
||||
getRealmOptions(options),
|
||||
let realm = construct_realm(getRealmOptions(options));
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(
|
||||
realm,
|
||||
getSerializerOptions(options),
|
||||
).init(filename, code, sourceMap, options.sourceMaps);
|
||||
);
|
||||
serialized = serializer.init(filename, code, sourceMap, options.sourceMaps);
|
||||
if (!serialized) {
|
||||
throw new InitializationError();
|
||||
}
|
||||
@ -56,10 +61,13 @@ export function prepackFileSync(filename: string, options: Options = {}) {
|
||||
} catch (_e) {
|
||||
console.log(`No sourcemap found at ${sourceMapFilename}.`);
|
||||
}
|
||||
let serialized = new Serializer(
|
||||
getRealmOptions(options),
|
||||
let realm = construct_realm(getRealmOptions(options));
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(
|
||||
realm,
|
||||
getSerializerOptions(options),
|
||||
).init(filename, code, sourceMap, options.sourceMaps);
|
||||
);
|
||||
let serialized = serializer.init(filename, code, sourceMap, options.sourceMaps);
|
||||
if (!serialized) {
|
||||
throw new InitializationError();
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
/* @flow */
|
||||
import Serializer from "./serializer/index.js";
|
||||
import construct_realm from "./construct_realm.js";
|
||||
import initializeGlobals from "./globals.js";
|
||||
import * as t from "babel-types";
|
||||
import { getRealmOptions, getSerializerOptions } from "./options";
|
||||
|
||||
@ -28,10 +30,10 @@ Object.setPrototypeOf(InitializationError.prototype, Error.prototype);
|
||||
|
||||
export function prepack(code: string, options: Options = {}) {
|
||||
let filename = options.filename || 'unknown';
|
||||
let serialized = new Serializer(
|
||||
getRealmOptions(options),
|
||||
getSerializerOptions(options),
|
||||
).init(filename, code, "", false);
|
||||
let realm = construct_realm(getRealmOptions(options));
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(realm, getSerializerOptions(options));
|
||||
let serialized = serializer.init(filename, code, "", false);
|
||||
if (!serialized) {
|
||||
throw new InitializationError();
|
||||
}
|
||||
@ -48,10 +50,10 @@ export function prepackFromAst(ast: BabelNodeFile | BabelNodeProgram, code: stri
|
||||
// TODO: Expose an option to wire an already parsed ast all the way through
|
||||
// to the execution environment. For now, we just reparse.
|
||||
|
||||
let serialized = new Serializer(
|
||||
getRealmOptions(options),
|
||||
getSerializerOptions(options),
|
||||
).init("", code, "", options.sourceMaps);
|
||||
let realm = construct_realm(getRealmOptions(options));
|
||||
initializeGlobals(realm);
|
||||
let serializer = new Serializer(realm, getSerializerOptions(options));
|
||||
let serialized = serializer.init("", code, "", options.sourceMaps);
|
||||
if (!serialized) {
|
||||
throw new InitializationError();
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import { ToStringPartial, InstanceofOperator } from "./methods/index.js";
|
||||
import { AbruptCompletion, ThrowCompletion } from "./completions.js";
|
||||
import { Value, ObjectValue } from "./values/index.js";
|
||||
import construct_realm from "./construct_realm.js";
|
||||
import initializeGlobals from "./globals.js";
|
||||
|
||||
// $FlowFixMe: Why does Flow not know about this Node module?
|
||||
let repl = require("repl");
|
||||
|
||||
@ -46,6 +48,7 @@ function serialize(realm: Realm, res: Value | AbruptCompletion): any {
|
||||
}
|
||||
|
||||
let realm = construct_realm();
|
||||
initializeGlobals(realm);
|
||||
|
||||
repl.start({
|
||||
prompt: "> ",
|
||||
|
@ -11,8 +11,7 @@
|
||||
|
||||
import { GlobalEnvironmentRecord, DeclarativeEnvironmentRecord } from "../environment.js";
|
||||
import { Realm, ExecutionContext } from "../realm.js";
|
||||
import construct_realm from "../construct_realm.js";
|
||||
import type { RealmOptions, Descriptor, PropertyBinding } from "../types.js";
|
||||
import type { Descriptor, PropertyBinding } from "../types.js";
|
||||
import { IsUnresolvableReference, ResolveBinding, ToLength, IsArray, Get } from "../methods/index.js";
|
||||
import { Completion } from "../completions.js";
|
||||
import { ArrayValue, BoundFunctionValue, ProxyValue, SymbolValue, AbstractValue, EmptyValue, FunctionValue, Value, ObjectValue, PrimitiveValue, NativeFunctionValue, UndefinedValue } from "../values/index.js";
|
||||
@ -55,9 +54,12 @@ function isSameNode(left, right) {
|
||||
}
|
||||
|
||||
export class Serializer {
|
||||
constructor(realmOptions: RealmOptions = {}, serializerOptions: SerializerOptions = {}) {
|
||||
this.realm = construct_realm(realmOptions);
|
||||
invariant(this.realm.isPartial);
|
||||
constructor(realm: Realm, serializerOptions: SerializerOptions = {}) {
|
||||
invariant(realm.isPartial);
|
||||
// Start tracking mutations
|
||||
realm.generator = new Generator(realm);
|
||||
|
||||
this.realm = realm;
|
||||
this.logger = new Logger(this.realm, !!serializerOptions.internalDebug);
|
||||
this.modules = new Modules(this.realm, this.logger, !!serializerOptions.logModules, !!serializerOptions.delayUnsupportedRequires);
|
||||
if (serializerOptions.trace) this.realm.tracers.push(new LoggingTracer(this.realm));
|
||||
|
Loading…
Reference in New Issue
Block a user