From bfc005a15bfacf429708a48aa2eb84bfa9c97163 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 21 Feb 2018 03:50:59 -0800 Subject: [PATCH] Handle more BinaryExpression cases Summary: Release notes: none Follow up to https://github.com/facebook/prepack/pull/1464. This adds serializer tests and fixes `+` binary expressions in pure mode. Closes https://github.com/facebook/prepack/pull/1473 Differential Revision: D7040965 Pulled By: trueadm fbshipit-source-id: ba2b377b6f7c6fc8260b0afcb5098c6e50c050ed --- src/evaluators/BinaryExpression.js | 29 +++++++++++++------ .../pure-functions/BinaryExpressions.js | 19 ++++++++++++ .../pure-functions/BinaryExpressions2.js | 19 ++++++++++++ 3 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 test/serializer/pure-functions/BinaryExpressions.js create mode 100644 test/serializer/pure-functions/BinaryExpressions2.js diff --git a/src/evaluators/BinaryExpression.js b/src/evaluators/BinaryExpression.js index f5b4eb15a..3c28a04f7 100644 --- a/src/evaluators/BinaryExpression.js +++ b/src/evaluators/BinaryExpression.js @@ -79,19 +79,30 @@ export function getPureBinaryOperationResultType( if (op === "+") { let ltype = To.GetToPrimitivePureResultType(realm, lval); let rtype = To.GetToPrimitivePureResultType(realm, rval); + + function recoverWithValue() { + // Assume that the unknown value is actually a primitive or otherwise a well behaved object. + ltype = lval.getType(); + rtype = rval.getType(); + if (ltype === StringValue || rtype === StringValue) return StringValue; + if (ltype === IntegralValue && rtype === IntegralValue) return IntegralValue; + if ((ltype === NumberValue || ltype === IntegralValue) && (rtype === NumberValue || rtype === IntegralValue)) + return NumberValue; + + return Value; + } + + if (realm.isInPureScope()) { + if (!ltype) Leak.leakValue(realm, lval); + if (!rtype) Leak.leakValue(realm, rval); + return recoverWithValue(); + } + if (ltype === undefined || rtype === undefined) { let loc = ltype === undefined ? lloc : rloc; let error = new CompilerDiagnostic(unknownValueOfOrToString, loc, "PP0002", "RecoverableError"); if (realm.handleError(error) === "Recover") { - // Assume that the unknown value is actually a primitive or otherwise a well behaved object. - ltype = lval.getType(); - rtype = rval.getType(); - if (ltype === StringValue || rtype === StringValue) return StringValue; - if (ltype === IntegralValue && rtype === IntegralValue) return IntegralValue; - if ((ltype === NumberValue || ltype === IntegralValue) && (rtype === NumberValue || rtype === IntegralValue)) - return NumberValue; - - return Value; + return recoverWithValue(); } throw new FatalError(); } diff --git a/test/serializer/pure-functions/BinaryExpressions.js b/test/serializer/pure-functions/BinaryExpressions.js new file mode 100644 index 000000000..e131c7d95 --- /dev/null +++ b/test/serializer/pure-functions/BinaryExpressions.js @@ -0,0 +1,19 @@ +// additional functions +// abstract effects + +let obj1 = global.__abstract ? __abstract('object', '({foo: {valueOf() { return 42; }}})') : {foo: {valueOf() { return 42; }}}; +let obj2 = global.__abstract ? __abstract('object', '({foo: {bar: {valueOf() { return 42; }}}})') : {foo: {bar: {valueOf() { return 42; }}}}; + +function additional1() { + return '' + obj1.foo; +} + +function additional2() { + return obj2.foo.bar + 10; +} + +inspect = function() { + let ret1 = additional1(); + let ret2 = additional2(); + return JSON.stringify({ ret1, ret2 }); +} diff --git a/test/serializer/pure-functions/BinaryExpressions2.js b/test/serializer/pure-functions/BinaryExpressions2.js new file mode 100644 index 000000000..b890b6424 --- /dev/null +++ b/test/serializer/pure-functions/BinaryExpressions2.js @@ -0,0 +1,19 @@ +// additional functions +// abstract effects + +let obj1 = global.__abstract ? __abstract('object', '({foo: {valueOf() { return 42; }}})') : {foo: {valueOf() { return 42; }}}; +let obj2 = global.__abstract ? __abstract('object', '({foo: {bar: {valueOf() { return 42; }}}})') : {foo: {bar: {valueOf() { return 42; }}}}; + +function additional1() { + return 42 < obj1.foo; +} + +function additional2() { + return obj2.foo.bar > 42; +} + +inspect = function() { + let ret1 = additional1(); + let ret2 = additional2(); + return JSON.stringify({ ret1, ret2 }); +}