diff --git a/src/values/AbstractObjectValue.js b/src/values/AbstractObjectValue.js index 17fb9277f..f53c5ec7b 100644 --- a/src/values/AbstractObjectValue.js +++ b/src/values/AbstractObjectValue.js @@ -681,6 +681,34 @@ export default class AbstractObjectValue extends AbstractValue { return cv.$Set(P, V, Receiver === this ? cv : Receiver); } invariant(false); + } else if (this.kind === "conditional") { + // this is the join of two concrete/abstract objects + // use this join condition for the join of the two property values + let [cond, ob1, ob2] = this.args; + invariant(cond instanceof AbstractValue); + invariant(ob1 instanceof ObjectValue || ob1 instanceof AbstractObjectValue); + invariant(ob2 instanceof ObjectValue || ob2 instanceof AbstractObjectValue); + let d1 = ob1.$GetOwnProperty(P); + let d2 = ob2.$GetOwnProperty(P); + let oldVal1 = + d1 === undefined ? this.$Realm.intrinsics.empty : IsDataDescriptor(this.$Realm, d1) ? d1.value : undefined; + let oldVal2 = + d2 === undefined ? this.$Realm.intrinsics.empty : IsDataDescriptor(this.$Realm, d2) ? d2.value : undefined; + if (oldVal1 === undefined || oldVal2 === undefined) { + AbstractValue.reportIntrospectionError(this, P); + throw new FatalError(); + } + invariant(oldVal1 instanceof Value); + invariant(oldVal2 instanceof Value); + let newVal1 = AbstractValue.createFromConditionalOp(this.$Realm, cond, V, oldVal1); + let newVal2 = AbstractValue.createFromConditionalOp(this.$Realm, cond, oldVal2, V); + let result1 = ob1.$Set(P, newVal1, ob1); + let result2 = ob2.$Set(P, newVal2, ob2); + if (result1 !== result2) { + AbstractValue.reportIntrospectionError(this, P); + throw new FatalError(); + } + return result1; } else { let sawTrue = false; let sawFalse = false; diff --git a/test/serializer/abstract/ConditionalAbstractObjectValueSet.js b/test/serializer/abstract/ConditionalAbstractObjectValueSet.js new file mode 100644 index 000000000..de1b3eef0 --- /dev/null +++ b/test/serializer/abstract/ConditionalAbstractObjectValueSet.js @@ -0,0 +1,13 @@ +// does not contain:unnecessaryIndirection +(function () { + let c1 = global.__abstract ? __abstract("boolean", "(true)") : true; + let c2 = global.__abstract ? __abstract("boolean", "(!false)") : true; + var a = {unnecessaryIndirection:1}; + var b = {unnecessaryIndirection:2}; + var c = {unnecessaryIndirection:3}; + var obj1 = c1 ? a : b; + var obj2 = c2 ? obj1 : c; + obj2.unnecessaryIndirection = 5; + global.result = a.unnecessaryIndirection; + inspect = function() { return global.result; }; +})(); diff --git a/test/serializer/abstract/ConditionalAbstractObjectValueSetNewProperty.js b/test/serializer/abstract/ConditionalAbstractObjectValueSetNewProperty.js new file mode 100644 index 000000000..2c8b5a9ab --- /dev/null +++ b/test/serializer/abstract/ConditionalAbstractObjectValueSetNewProperty.js @@ -0,0 +1,15 @@ +(function () { + let c = global.__abstract ? __abstract("boolean", "(true)") : true; + var a = {x:1}; + var b = {}; + var obj = c ? a : b; + obj.x = 2; + global.result = a.x; + global.residualObject = b; + inspect = function() { + return ( + global.result + ' ' + + global.residualObject.x + ' ' + + global.residualObject.hasOwnProperty('x') + ); }; +})();