Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

Fix join of SimpleNormal with PossiblyNormal completions. #2250

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/completions.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ export class BreakCompletion extends AbruptCompletion {
export class ReturnCompletion extends AbruptCompletion {
constructor(value: Value, precedingEffects: void | Effects, location: ?BabelNodeSourceLocation) {
super(value, precedingEffects, location);
if (value instanceof EmptyValue) {
this.value = value.$Realm.intrinsics.undefined;
}
}
}

Expand Down
101 changes: 5 additions & 96 deletions src/methods/join.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,87 +334,11 @@ export class JoinImplementation {
}
}

updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(
joinNormalCompletions(
realm: Realm,
joinCondition: AbstractValue,
pnc: PossiblyNormalCompletion,
nc: SimpleNormalCompletion
): void {
let v = nc.value;
if (pnc.consequent instanceof AbruptCompletion) {
if (pnc.alternate instanceof SimpleNormalCompletion) {
nc.value = AbstractValue.createFromConditionalOp(realm, joinCondition, pnc.alternate.value, v);
pnc.alternateEffects.result = nc;
nc.effects = pnc.alternateEffects;
pnc.alternate = nc;
} else {
invariant(pnc.alternate instanceof PossiblyNormalCompletion);
this.updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(
realm,
joinCondition,
pnc.alternate,
nc
);
}
} else {
if (pnc.consequent instanceof SimpleNormalCompletion) {
nc.value = AbstractValue.createFromConditionalOp(realm, joinCondition, pnc.consequent.value, v);
pnc.consequentEffects.result = nc;
nc.effects = pnc.consequentEffects;
pnc.consequent = nc;
} else {
invariant(pnc.consequent instanceof PossiblyNormalCompletion);
this.updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(
realm,
joinCondition,
pnc.consequent,
nc
);
}
}
}

updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm: Realm,
joinCondition: AbstractValue,
pnc: PossiblyNormalCompletion,
nc: SimpleNormalCompletion
): void {
let v = nc.value;
if (pnc.consequent instanceof AbruptCompletion) {
if (pnc.alternate instanceof SimpleNormalCompletion) {
nc.value = AbstractValue.createFromConditionalOp(realm, joinCondition, v, pnc.alternate.value);
pnc = pnc.updateAlternateKeepingCurrentEffects(nc);
} else {
invariant(pnc.alternate instanceof PossiblyNormalCompletion);
this.updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm,
joinCondition,
pnc.alternate,
nc
);
}
} else {
if (pnc.consequent instanceof SimpleNormalCompletion) {
nc.value = AbstractValue.createFromConditionalOp(realm, joinCondition, v, pnc.consequent.value);
pnc = pnc.updateConsequentKeepingCurrentEffects(nc);
} else {
invariant(pnc.consequent instanceof PossiblyNormalCompletion);
this.updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm,
joinCondition,
pnc.consequent,
nc
);
}
}
}

joinPossiblyNormalCompletions(
realm: Realm,
joinCondition: AbstractValue,
c: PossiblyNormalCompletion,
a: PossiblyNormalCompletion
c: NormalCompletion,
a: NormalCompletion
): PossiblyNormalCompletion {
let getAbstractValue = (v1: void | Value, v2: void | Value): Value => {
if (v1 instanceof EmptyValue) return v2 || realm.intrinsics.undefined;
Expand Down Expand Up @@ -633,8 +557,8 @@ export class JoinImplementation {
if (result1 instanceof AbruptCompletion && result2 instanceof AbruptCompletion) {
return new ForkedAbruptCompletion(realm, joinCondition, result1, e1, result2, e2);
}
if (result1 instanceof PossiblyNormalCompletion && result2 instanceof PossiblyNormalCompletion) {
return this.joinPossiblyNormalCompletions(realm, joinCondition, result1, result2);
if (result1 instanceof NormalCompletion && result2 instanceof NormalCompletion) {
return this.joinNormalCompletions(realm, joinCondition, result1, result2);
}
if (result1 instanceof AbruptCompletion) {
let completion = result2;
Expand Down Expand Up @@ -678,21 +602,6 @@ export class JoinImplementation {
savedEffects
);
}
if (result1 instanceof PossiblyNormalCompletion) {
invariant(result2 instanceof SimpleNormalCompletion);
this.updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(realm, joinCondition, result1, result2);
return result1;
}
if (result2 instanceof PossiblyNormalCompletion) {
invariant(result1 instanceof SimpleNormalCompletion);
this.updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm,
joinCondition,
result2,
result1
);
return result2;
}
invariant(false);
}

Expand Down
15 changes: 0 additions & 15 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import {
AbruptCompletion,
Completion,
ForkedAbruptCompletion,
SimpleNormalCompletion,
PossiblyNormalCompletion,
NormalCompletion,
} from "./completions.js";
Expand Down Expand Up @@ -741,20 +740,6 @@ export type JoinType = {
e: Effects
): ForkedAbruptCompletion,

updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(
realm: Realm,
joinCondition: AbstractValue,
pnc: PossiblyNormalCompletion,
nc: SimpleNormalCompletion
): void,

updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm: Realm,
joinCondition: AbstractValue,
pnc: PossiblyNormalCompletion,
nc: SimpleNormalCompletion
): void,

extractAndJoinCompletionsOfType(CompletionType: typeof AbruptCompletion, realm: Realm, c: AbruptCompletion): Effects,

joinForkOrChoose(realm: Realm, joinCondition: Value, e1: Effects, e2: Effects): Effects,
Expand Down
14 changes: 14 additions & 0 deletions test/serializer/abstract/Throw10.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
let c1 = global.__abstract ? __abstract("boolean", "true") : true;
let c2 = global.__abstract ? __abstract("boolean", "false") : false;

function foo(cond) {
if (cond) throw "I am an error too!";
}

if (c2) {
foo(c1);
}

inspect = function() {
return "success";
};