WebKit Version : WebKitGTK 2.32.2 Other browsers tested: Firefox: 89.0.2: OK V8 (Chromium/NodeJS/Deno): Same issue What steps will reproduce the problem? (1) Evaluate the JavaScript expression "{} + {}" What is the expected result? The numeric value "NaN" is returned, as per the spec (https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-applystringornumericbinaryoperator). What happens instead? The string '[object Object][object Object]' is returned.
I cannot reproduce this on macOS (Apple Silicon) with macOS 11.5 or 12 betas.
I've also tested WebKitGTK 2.33.2 and gotten the same result (GNOME Web / Epiphany, Fedora 34, Intel x86_64)
Where are you evaluating it? "[object Object][object Object]" is what I'd expect if it's being evaluated as a statement and not as an expression (as then you have an empty BlockStatement followed by a UnaryExpression, and not an AdditiveExpression).
(In reply to Sam Sneddon [:gsnedders] from comment #3) > Where are you evaluating it? > > "[object Object][object Object]" is what I'd expect if it's being evaluated > as a statement and not as an expression (as then you have an empty > BlockStatement followed by a UnaryExpression, and not an AdditiveExpression). In the browser console; running the statement alone gives the same result as assigning to a variable. Substituting "{}" by another object also exhibits the same issue
<rdar://problem/80990349>
I tried it in several versions of Safari, but I cannot reproduce it, so closing this issue. My guess is that the web page has `Object.prototype.toString` override, and opening a console in that web page causes it since the expression should be evaluated under the page's context. Please check the web page's script.
Ah, OK. I think I know what it is. https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-applystringornumericbinaryoperator The result "[object Object][object Object]" is the right value according to the spec. This is because ToPrimitive onto object should return "[object Object]". Let's look https://tc39.es/ecma262/multipage/abstract-operations.html#sec-toprimitive carefully. Since @@toPrimitive is not defined, we call OrdinaryToPrimitive with "default" preference. https://tc39.es/ecma262/multipage/abstract-operations.html#sec-ordinarytoprimitive Then, we first call object.valueOf(). But it returns an object itself. Since it is not a primitive value, we discard this, and then call object.toString() next. See step 5-b-ii "If Type(result) is not Object, return result.". Since valueOf returns an object, we call object.toString next (as listed in step 4-a). https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-applystringornumericbinaryoperator So, in step 2-c, both lprim and rprim are strings "[object Object]". Therefore, 2-c-iii will return "[object Object][object Object]". So, JSC and V8 behaviors are correct. Then, why SpiderMonkey returns NaN. In JSC and V8 consoles, we evaluate the input as "expression" first instead of "statement". This is convenient because users do not need to wrap the expression with "()". On the other hand, maybe, SpiderMonkey is evaluating it as "statement". Then, what is happening is that, {} + {} is evaluated as ({} + {}) in JSC and V8's console. {} + {} is evaluated as { // Block statement } +{}; // + and object => NaN. in SpiderMonkey. So, 1. {} + {} is correctly evaluated in JSC. If it is evaluated as an expression, the result should be "[object Object][object Object]" 2. {} + {} is evaluated differently in the console in Firefox, Safari, and V8. And this is engine's preference.
We can check this preference easily. Let's evaluate "{}" in each console. Safari / Chrome => empty object Firefox => undefined (Since Firefox evaluated it as empty block statement).