mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-08-17 10:30:32 +03:00
Improved reported error for PP1003 (#2305)
Summary: Previous error message: `Property access conflicts with write in optimized function (unknown function) at 11:11 to 11:16` New error message: `Write to property "func" on <unnamed object> at optimized function fn[20:13 22:22] conflicts with access in function nested[11:11]` Output generated off "Failure 2" in issue #2252 Pull Request resolved: https://github.com/facebook/prepack/pull/2305 Differential Revision: D8979410 Pulled By: cblappert fbshipit-source-id: a4f507d8a77a44a0f4ca7619faf3a9fe03dabf45
This commit is contained in:
parent
66115d4377
commit
62b11dcb6e
@ -38,6 +38,7 @@ import { handleReportedSideEffect } from "./utils.js";
|
||||
import { ShapeInformation } from "../utils/ShapeInformation";
|
||||
import type { ArgModel } from "../utils/ShapeInformation";
|
||||
import * as t from "@babel/types";
|
||||
import { stringOfLocation } from "../utils/babelhelpers";
|
||||
|
||||
type AdditionalFunctionEntry = {
|
||||
value: ECMAScriptSourceFunctionValue | AbstractValue,
|
||||
@ -299,7 +300,11 @@ export class Functions {
|
||||
let conflicts: Map<BabelNodeSourceLocation, CompilerDiagnostic> = new Map();
|
||||
for (let fun1 of additionalFunctions) {
|
||||
invariant(fun1 instanceof FunctionValue);
|
||||
let fun1Name = this.functionExpressions.get(fun1) || fun1.intrinsicName || "(unknown function)";
|
||||
let fun1Location = fun1.expressionLocation;
|
||||
let fun1Name =
|
||||
this.functionExpressions.get(fun1) ||
|
||||
fun1.getDebugName() ||
|
||||
`(unknown function ${fun1Location ? stringOfLocation(fun1Location) : ""})`;
|
||||
// Also do argument validation here
|
||||
let additionalFunctionEffects = this.writeEffects.get(fun1);
|
||||
invariant(additionalFunctionEffects !== undefined);
|
||||
@ -318,8 +323,13 @@ export class Functions {
|
||||
for (let fun2 of additionalFunctions) {
|
||||
if (fun1 === fun2) continue;
|
||||
invariant(fun2 instanceof FunctionValue);
|
||||
let fun2Location = fun2.expressionLocation;
|
||||
let fun2Name =
|
||||
this.functionExpressions.get(fun2) ||
|
||||
fun2.getDebugName() ||
|
||||
`(unknown function ${fun2Location ? stringOfLocation(fun2Location) : ""})`;
|
||||
let reportFn = () => {
|
||||
this.reportWriteConflicts(fun1Name, conflicts, e1.modifiedProperties, this._callOfFunction(fun2));
|
||||
this.reportWriteConflicts(fun1Name, fun2Name, conflicts, e1.modifiedProperties, this._callOfFunction(fun2));
|
||||
return null;
|
||||
};
|
||||
let fun2Effects = this.writeEffects.get(fun2);
|
||||
@ -344,14 +354,26 @@ export class Functions {
|
||||
}
|
||||
|
||||
reportWriteConflicts(
|
||||
fname: string,
|
||||
f1name: string,
|
||||
f2name: string,
|
||||
conflicts: Map<BabelNodeSourceLocation, CompilerDiagnostic>,
|
||||
pbs: PropertyBindings,
|
||||
call2: void => Value
|
||||
): void {
|
||||
let reportConflict = (location: BabelNodeSourceLocation) => {
|
||||
let reportConflict = (
|
||||
location: BabelNodeSourceLocation,
|
||||
object: string = "",
|
||||
key?: string,
|
||||
originalLocation: BabelNodeSourceLocation | void | null
|
||||
) => {
|
||||
let firstLocationString = originalLocation ? `${stringOfLocation(originalLocation)}` : "";
|
||||
let propString = key ? ` "${key}"` : "";
|
||||
let objectString = object ? ` on object "${object}" ` : "";
|
||||
if (!objectString && key) objectString = " on <unnamed object> ";
|
||||
let error = new CompilerDiagnostic(
|
||||
`Property access conflicts with write in optimized function ${fname}`,
|
||||
`Write to property${propString}${objectString}at optimized function ${f1name}[${firstLocationString}] conflicts with access in function ${f2name}[${
|
||||
location.start.line
|
||||
}:${location.start.column}]`,
|
||||
location,
|
||||
"PP1003",
|
||||
"FatalError"
|
||||
@ -366,14 +388,22 @@ export class Functions {
|
||||
this.realm.reportObjectGetOwnProperties = (ob: ObjectValue) => {
|
||||
let location = this.realm.currentLocation;
|
||||
invariant(location);
|
||||
if (writtenObjects.has(ob) && !conflicts.has(location)) reportConflict(location);
|
||||
if (writtenObjects.has(ob) && !conflicts.has(location))
|
||||
reportConflict(location, ob.getDebugName(), undefined, ob.expressionLocation);
|
||||
};
|
||||
let oldReportPropertyAccess = this.realm.reportPropertyAccess;
|
||||
this.realm.reportPropertyAccess = (pb: PropertyBinding) => {
|
||||
if (ObjectValue.refuseSerializationOnPropertyBinding(pb)) return;
|
||||
let location = this.realm.currentLocation;
|
||||
if (!location) return; // happens only when accessing an additional function property
|
||||
if (pbs.has(pb) && !conflicts.has(location)) reportConflict(location);
|
||||
if (pbs.has(pb) && !conflicts.has(location)) {
|
||||
let originalLocation =
|
||||
pb.descriptor && pb.descriptor.value && !Array.isArray(pb.descriptor.value)
|
||||
? pb.descriptor.value.expressionLocation
|
||||
: undefined;
|
||||
let keyString = pb.key instanceof Value ? pb.key.toDisplayString() : pb.key;
|
||||
reportConflict(location, pb.object ? pb.object.getDebugName() : undefined, keyString, originalLocation);
|
||||
}
|
||||
};
|
||||
try {
|
||||
ignoreErrorsIn(this.realm, () => this.realm.evaluateForEffectsInGlobalEnv(call2));
|
||||
|
@ -53,4 +53,8 @@ export default class FunctionValue extends ObjectValue {
|
||||
hasDefaultLength(): boolean {
|
||||
invariant(false, "abstract method; please override");
|
||||
}
|
||||
|
||||
getDebugName(): string {
|
||||
return super.getDebugName() || this.getName();
|
||||
}
|
||||
}
|
||||
|
@ -193,4 +193,8 @@ export default class Value {
|
||||
_serialize(set: Function, stack: Map<Value, any>): any {
|
||||
invariant(false, "abstract method; please override");
|
||||
}
|
||||
|
||||
getDebugName(): string | void {
|
||||
return this.intrinsicName || this.__originalName;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user