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:
Sebastian Markbåge 2017-04-27 18:11:37 -07:00 committed by GitHub
parent 752761c7b9
commit 8f9e912deb
20 changed files with 383 additions and 236 deletions

View File

@ -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"));

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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
View 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;
}

View 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
});
}

View 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
});
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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"));

View File

@ -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
View 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
});
}
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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: "> ",

View File

@ -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));