Support constructor returning an unknown abstract value (#2535)

Summary:
The following test case currently fails:

```js
function F() {
  this.a = 1;
  this.b = 2;
  if (global.__abstract) return global.__abstract(undefined, "undefined");
}

const result = new F();

global.inspect = () => JSON.stringify(result);
```

We hit this bug in our internal React Native bundle. I only added support for `base` construction kinds since the template for `derived` construction kinds would get more complicated.
Pull Request resolved: https://github.com/facebook/prepack/pull/2535

Differential Revision: D9906309

Pulled By: trueadm

fbshipit-source-id: 49a71ceaf30a851075879295e63e98ce7e1bbe2d
This commit is contained in:
Caleb Meredith 2018-09-18 05:23:47 -07:00 committed by Facebook Github Bot
parent 781cae5b38
commit a4620bd4bf
2 changed files with 32 additions and 8 deletions

View File

@ -276,17 +276,32 @@ function InternalConstruct(
function map(value: Value) {
if (value === realm.intrinsics.__bottomValue) return value;
if (value instanceof AbstractValue && value.kind === "conditional") {
const [condition, consequent, alternate] = value.args;
return realm.evaluateWithAbstractConditional(
condition,
() => realm.evaluateForEffects(() => map(consequent), undefined, "AbstractValue/conditional/true"),
() => realm.evaluateForEffects(() => map(alternate), undefined, "AbstractValue/conditional/false")
);
if (value instanceof AbstractValue) {
if (value.kind === "conditional") {
const [condition, consequent, alternate] = value.args;
return realm.evaluateWithAbstractConditional(
condition,
() => realm.evaluateForEffects(() => map(consequent), undefined, "AbstractValue/conditional/true"),
() => realm.evaluateForEffects(() => map(alternate), undefined, "AbstractValue/conditional/false")
);
}
if (!(value instanceof AbstractObjectValue)) {
if (kind === "base") {
invariant(thisArgument, "this wasn't initialized for some reason");
return AbstractValue.createFromTemplate(
realm,
"typeof A === 'object' || typeof A === 'function' ? A : B",
ObjectValue,
[value, thisArgument]
);
} else {
value.throwIfNotConcreteObject(); // Not yet supported.
}
}
}
// a. If Type(result.[[Value]]) is Object, return NormalCompletion(result.[[Value]]).
if (value.mightBeObject()) return value.throwIfNotConcreteObject();
if (value instanceof ObjectValue || value instanceof AbstractObjectValue) return value;
// b. If kind is "base", return NormalCompletion(thisArgument).
if (kind === "base") {

View File

@ -0,0 +1,9 @@
function F() {
this.a = 1;
this.b = 2;
if (global.__abstract) return global.__abstract(undefined, "undefined");
}
const result = new F();
global.inspect = () => JSON.stringify(result);