Commit 08aec7d7 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[es2015] Fix ToPrimitive conversions in relational comparisons.

The order in which ToNumber(left) and ToPrimitive(right,hint Number)
is called when performing an abstract relational comparison is
observable, and we need to make sure to trigger the conversions in
the correct order.

Bug: chromium:687063
Change-Id: Idc9edb99643c4cf1774b89dcdc319ed5dc7cdc8a
Reviewed-on: https://chromium-review.googlesource.com/1236557Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56125}
parent 5e8581a7
......@@ -10713,15 +10713,16 @@ Node* CodeStubAssembler::RelationalComparison(Operation op, Node* left,
}
// If {left} is a receiver, call ToPrimitive(left, hint Number).
// Otherwise call ToNumeric(left) and then ToNumeric(right).
// Otherwise call ToNumeric(right) and then ToNumeric(left), the
// order here is important as it's observable by user code.
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
Label if_left_receiver(this, Label::kDeferred);
GotoIf(IsJSReceiverInstanceType(left_instance_type),
&if_left_receiver);
var_right.Bind(CallBuiltin(Builtins::kToNumeric, context, right));
var_left.Bind(
CallBuiltin(Builtins::kNonNumberToNumeric, context, left));
var_right.Bind(CallBuiltin(Builtins::kToNumeric, context, right));
Goto(&loop);
BIND(&if_left_receiver);
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Collect the actual properties looked up on the Proxy.
const actual = [];
// Perform a relational comparison with a Proxy on the right hand
// side and a Symbol which cannot be turned into a Number on the
// left hand side.
function foo() {
actual.length = 0;
const lhs = Symbol();
const rhs = new Proxy({}, {
get: function(target, property, receiver) {
actual.push(property);
return undefined;
}
});
return lhs < rhs;
}
assertThrows(foo, TypeError);
assertEquals([Symbol.toPrimitive, 'valueOf', 'toString'], actual);
assertThrows(foo, TypeError);
assertEquals([Symbol.toPrimitive, 'valueOf', 'toString'], actual);
%OptimizeFunctionOnNextCall(foo);
assertThrows(foo, TypeError);
assertEquals([Symbol.toPrimitive, 'valueOf', 'toString'], actual);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment