mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-09-11 14:46:37 +03:00
Removes temporalAliasArgs for an existing approach using the preludeGenerator (#2199)
Summary: Release notes: none As pointed out by Herman in https://github.com/facebook/prepack/pull/2193#discussion_r199628160. We don't need `temporalAliasArgs`, so this PR removes it from the codebase and uses the existing way via the preludeGenerator. This also adds a helper function to make it easier to relate derived abstract values to their temporal args. Furthermore, `derivedIds` now stores the `TemporalBuildNodeEntryArgs` rather than `Array<Value>`, as the follow up PRs for doing the React related logic need to access more than just the array of args, it also needs access to `isPure`, `skipInvariant` etc so it can properly clone derived abstract values. Closes https://github.com/facebook/prepack/pull/2199 Differential Revision: D8724017 Pulled By: trueadm fbshipit-source-id: 3ad72d3b230f1d2dc7f81c2a8d07dd33d0c7aa5c
This commit is contained in:
parent
f12e0369f0
commit
8e37b36191
@ -522,8 +522,10 @@ export default function(realm: Realm): ObjectValue {
|
||||
// Enable cloning via JSON.parse(JSON.stringify(...)).
|
||||
let gen = realm.preludeGenerator;
|
||||
invariant(gen); // text is abstract, so we are doing abstract interpretation
|
||||
let args = gen.derivedIds.get(text.intrinsicName);
|
||||
invariant(args && args[0] instanceof Value); // since text.kind === "JSON.stringify(...)"
|
||||
let temporalBuildNodeEntryArgs = gen.derivedIds.get(text.intrinsicName);
|
||||
invariant(temporalBuildNodeEntryArgs !== undefined);
|
||||
let args = temporalBuildNodeEntryArgs.args;
|
||||
invariant(args[0] instanceof Value); // since text.kind === "JSON.stringify(...)"
|
||||
let inputClone = args[0]; // A temporal copy of the object that was the argument to stringify
|
||||
// Clone it so that every call to parse produces a different instance from stringify's clone
|
||||
let parseResult; // A clone of inputClone, because every call to parse produces a new object
|
||||
|
@ -295,10 +295,6 @@ export default function(realm: Realm): NativeFunctionValue {
|
||||
temporalTo.values = new ValuesDomain(to);
|
||||
}
|
||||
to.temporalAlias = temporalTo;
|
||||
// Store the args for the temporal so we can easily clone
|
||||
// and reconstruct the temporal at another point, rather than
|
||||
// mutate the existing temporal
|
||||
realm.temporalAliasArgs.set(temporalTo, temporalArgs);
|
||||
}
|
||||
return to;
|
||||
});
|
||||
|
@ -127,10 +127,6 @@ function createBabelHelpers(realm: Realm, global: ObjectValue | AbstractObjectVa
|
||||
let template = createObjectWithoutProperties(obj, keys);
|
||||
value.values = new ValuesDomain(template);
|
||||
}
|
||||
// Store the args for the temporal so we can easily clone
|
||||
// and reconstruct the temporal at another point, rather than
|
||||
// mutate the existing temporal
|
||||
realm.temporalAliasArgs.set(value, temporalArgs);
|
||||
// as we are returning an abstract object, we mark it as simple
|
||||
value.makeSimple();
|
||||
return value;
|
||||
|
@ -206,10 +206,6 @@ function createPropsObject(
|
||||
temporalTo.values = new ValuesDomain(props);
|
||||
}
|
||||
props.temporalAlias = temporalTo;
|
||||
// Store the args for the temporal so we can easily clone
|
||||
// and reconstruct the temporal at another point, rather than
|
||||
// mutate the existing temporal
|
||||
realm.temporalAliasArgs.set(temporalTo, temporalArgs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -948,8 +948,9 @@ function applyClonedTemporalAlias(realm: Realm, props: ObjectValue, clonedProps:
|
||||
// be a better option.
|
||||
invariant(false, "TODO applyClonedTemporalAlias conditional");
|
||||
}
|
||||
let temporalArgs = realm.temporalAliasArgs.get(temporalAlias);
|
||||
invariant(temporalArgs !== undefined);
|
||||
let temporalBuildNodeEntryArgs = realm.getTemporalBuildNodeEntryArgsFromDerivedValue(temporalAlias);
|
||||
invariant(temporalBuildNodeEntryArgs !== undefined);
|
||||
let temporalArgs = temporalBuildNodeEntryArgs.args;
|
||||
// replace the original props with the cloned one
|
||||
let newTemporalArgs = temporalArgs.map(arg => (arg === props ? clonedProps : arg));
|
||||
|
||||
@ -966,10 +967,6 @@ function applyClonedTemporalAlias(realm: Realm, props: ObjectValue, clonedProps:
|
||||
invariant(clonedProps instanceof ObjectValue);
|
||||
temporalTo.values = new ValuesDomain(clonedProps);
|
||||
clonedProps.temporalAlias = temporalTo;
|
||||
// Store the args for the temporal so we can easily clone
|
||||
// and reconstruct the temporal at another point, rather than
|
||||
// mutate the existing temporal
|
||||
realm.temporalAliasArgs.set(temporalTo, newTemporalArgs);
|
||||
}
|
||||
|
||||
export function cloneProps(realm: Realm, props: ObjectValue, newChildren?: Value): ObjectValue {
|
||||
@ -1079,10 +1076,6 @@ export function applyObjectAssignConfigsForReactElement(realm: Realm, to: Object
|
||||
invariant(temporalTo instanceof AbstractObjectValue);
|
||||
temporalTo.values = new ValuesDomain(to);
|
||||
to.temporalAlias = temporalTo;
|
||||
// Store the args for the temporal so we can easily clone
|
||||
// and reconstruct the temporal at another point, rather than
|
||||
// mutate the existing temporal
|
||||
realm.temporalAliasArgs.set(temporalTo, temporalArgs);
|
||||
return;
|
||||
} else {
|
||||
throw error;
|
||||
|
18
src/realm.js
18
src/realm.js
@ -63,7 +63,7 @@ import {
|
||||
import type { Compatibility, RealmOptions, ReactOutputTypes, InvariantModeTypes } from "./options.js";
|
||||
import invariant from "./invariant.js";
|
||||
import seedrandom from "seedrandom";
|
||||
import { Generator, PreludeGenerator } from "./utils/generator.js";
|
||||
import { Generator, PreludeGenerator, type TemporalBuildNodeEntryArgs } from "./utils/generator.js";
|
||||
import { emptyExpression, voidExpression } from "./utils/babelhelpers.js";
|
||||
import { Environment, Functions, Join, Properties, To, Widen, Path } from "./singletons.js";
|
||||
import type { ReactSymbolTypes } from "./react/utils.js";
|
||||
@ -246,7 +246,6 @@ export class Realm {
|
||||
this.evaluators = (Object.create(null): any);
|
||||
this.partialEvaluators = (Object.create(null): any);
|
||||
this.$GlobalEnv = ((undefined: any): LexicalEnvironment);
|
||||
this.temporalAliasArgs = new WeakMap();
|
||||
|
||||
this.instantRender = {
|
||||
enabled: opts.instantRender || false,
|
||||
@ -339,12 +338,6 @@ export class Realm {
|
||||
$GlobalEnv: LexicalEnvironment;
|
||||
intrinsics: Intrinsics;
|
||||
|
||||
// temporalAliasArgs is used to map a temporal abstract object value
|
||||
// to its respective temporal args used to originally create the temporal.
|
||||
// This is used to "clone" immutable objects where they have a dependency
|
||||
// on a temporal alias (for example, Object.assign) when used with snapshotting
|
||||
temporalAliasArgs: WeakMap<AbstractObjectValue | ObjectValue, Array<Value>>;
|
||||
|
||||
instantRender: {
|
||||
enabled: boolean,
|
||||
};
|
||||
@ -1745,4 +1738,13 @@ export class Realm {
|
||||
isNameStringUnique(nameString: string): boolean {
|
||||
return !this._abstractValuesDefined.has(nameString);
|
||||
}
|
||||
|
||||
getTemporalBuildNodeEntryArgsFromDerivedValue(value: Value): void | TemporalBuildNodeEntryArgs {
|
||||
let name = value.intrinsicName;
|
||||
invariant(name);
|
||||
let preludeGenerator = this.preludeGenerator;
|
||||
invariant(preludeGenerator !== undefined);
|
||||
let temporalBuildNodeEntryArgs = preludeGenerator.derivedIds.get(name);
|
||||
return temporalBuildNodeEntryArgs;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
} from "../values/index.js";
|
||||
import type { BabelNodeStatement } from "babel-types";
|
||||
import type { SerializedBody } from "./types.js";
|
||||
import { Generator } from "../utils/generator.js";
|
||||
import { Generator, type TemporalBuildNodeEntryArgs } from "../utils/generator.js";
|
||||
import invariant from "../invariant.js";
|
||||
import { BodyReference } from "./types.js";
|
||||
import { ResidualFunctions } from "./ResidualFunctions.js";
|
||||
@ -68,7 +68,7 @@ export class Emitter {
|
||||
residualFunctions: ResidualFunctions,
|
||||
referencedDeclaredValues: Map<Value, void | FunctionValue>,
|
||||
conditionalFeasibility: Map<AbstractValue, { t: boolean, f: boolean }>,
|
||||
derivedIds: Map<string, Array<Value>>
|
||||
derivedIds: Map<string, TemporalBuildNodeEntryArgs>
|
||||
) {
|
||||
this._mainBody = { type: "MainGenerator", parentBody: undefined, entries: [], done: false };
|
||||
this._waitingForValues = new Map();
|
||||
|
@ -115,7 +115,7 @@ export class GeneratorEntry {
|
||||
}
|
||||
}
|
||||
|
||||
type TemporalBuildNodeEntryArgs = {
|
||||
export type TemporalBuildNodeEntryArgs = {
|
||||
declared?: AbstractValue | ConcreteValue,
|
||||
args: Array<Value>,
|
||||
// If we're just trying to add roots for the serializer to notice, we don't need a buildNode.
|
||||
@ -926,13 +926,12 @@ export class Generator {
|
||||
): ConcreteValue {
|
||||
invariant(buildNode_ instanceof Function || args.length === 0);
|
||||
let id = t.identifier(this.preludeGenerator.nameGenerator.generate("derived"));
|
||||
this.preludeGenerator.derivedIds.set(id.name, args);
|
||||
let value = buildValue(id.name);
|
||||
if (value instanceof ObjectValue) {
|
||||
value.intrinsicNameGenerated = true;
|
||||
value._isScopedTemplate = true; // because this object doesn't exist ahead of time, and the visitor would otherwise declare it in the common scope
|
||||
}
|
||||
this._addEntry({
|
||||
this._addDerivedEntry(id.name, {
|
||||
isPure: optionalArgs ? optionalArgs.isPure : undefined,
|
||||
declared: value,
|
||||
args,
|
||||
@ -964,7 +963,6 @@ export class Generator {
|
||||
): AbstractValue {
|
||||
invariant(buildNode_ instanceof Function || args.length === 0);
|
||||
let id = t.identifier(this.preludeGenerator.nameGenerator.generate("derived"));
|
||||
this.preludeGenerator.derivedIds.set(id.name, args);
|
||||
let options = {};
|
||||
if (optionalArgs && optionalArgs.kind) options.kind = optionalArgs.kind;
|
||||
let Constructor = Value.isTypeCompatibleWith(types.getType(), ObjectValue) ? AbstractObjectValue : AbstractValue;
|
||||
@ -977,7 +975,7 @@ export class Generator {
|
||||
id,
|
||||
options
|
||||
);
|
||||
this._addEntry({
|
||||
this._addDerivedEntry(id.name, {
|
||||
isPure: optionalArgs ? optionalArgs.isPure : undefined,
|
||||
declared: res,
|
||||
args,
|
||||
@ -1072,10 +1070,15 @@ export class Generator {
|
||||
|
||||
// PITFALL Warning: adding a new kind of TemporalBuildNodeEntry that is not the result of a join or composition
|
||||
// will break this purgeEntriesWithGeneratorDepencies.
|
||||
_addEntry(entry: TemporalBuildNodeEntryArgs) {
|
||||
_addEntry(entry: TemporalBuildNodeEntryArgs): void {
|
||||
this._entries.push(new TemporalBuildNodeEntry(entry));
|
||||
}
|
||||
|
||||
_addDerivedEntry(id: string, entry: TemporalBuildNodeEntryArgs): void {
|
||||
this._addEntry(entry);
|
||||
this.preludeGenerator.derivedIds.set(id, entry);
|
||||
}
|
||||
|
||||
appendGenerator(other: Generator, leadingComment: string): void {
|
||||
invariant(other !== this);
|
||||
invariant(other.realm === this.realm);
|
||||
@ -1182,7 +1185,7 @@ export class PreludeGenerator {
|
||||
}
|
||||
|
||||
prelude: Array<BabelNodeStatement>;
|
||||
derivedIds: Map<string, Array<Value>>;
|
||||
derivedIds: Map<string, TemporalBuildNodeEntryArgs>;
|
||||
memoizedRefs: Map<string, BabelNodeIdentifier>;
|
||||
nameGenerator: NameGenerator;
|
||||
usesThis: boolean;
|
||||
|
@ -146,7 +146,9 @@ export default class AbstractValue extends Value {
|
||||
function add_intrinsic(name: string) {
|
||||
if (name.startsWith("_$")) {
|
||||
if (gen === undefined) return;
|
||||
add_args(gen.derivedIds.get(name));
|
||||
let temporalBuildNodeEntryArgs = gen.derivedIds.get(name);
|
||||
invariant(temporalBuildNodeEntryArgs !== undefined);
|
||||
add_args(temporalBuildNodeEntryArgs.args);
|
||||
} else if (names.indexOf(name) < 0) {
|
||||
names.push(name);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user