Commit c403ede4 authored by bmeurer's avatar bmeurer Committed by Commit bot

[es6] Implement spec compliant ToName (actually ToPropertyKey).

This adds a %ToName runtime entry that uses the previously introduced
Object::ToName, which is based on the new Object::ToPrimitive method.
Also removes the need to expose ToName in various way via the builtins
and/or context.

Drive-by-fix: Let %HasProperty do the ToName conversion implicitly as
required.

BUG=v8:4307
LOG=n

Review URL: https://codereview.chromium.org/1319133002

Cr-Commit-Position: refs/heads/master@{#30435}
parent f6c6d713
......@@ -301,7 +301,7 @@ void JSGenericLowering::LowerJSToString(Node* node) {
void JSGenericLowering::LowerJSToName(Node* node) {
ReplaceWithBuiltinCall(node, Context::TO_NAME_BUILTIN_INDEX, 1);
ReplaceWithRuntimeCall(node, Runtime::kToName);
}
......
......@@ -250,6 +250,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
case Runtime::kInlineToPrimitive_String:
case Runtime::kInlineOrdinaryToPrimitive:
case Runtime::kInlineToNumber:
case Runtime::kInlineToName:
return 1;
case Runtime::kInlineDeoptimizeNow:
case Runtime::kInlineThrowNotDateError:
......
......@@ -85,7 +85,6 @@ enum BindingFlags {
V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \
V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \
V(TO_LENGTH_FUN_INDEX, JSFunction, to_length_fun) \
V(TO_NAME_INDEX, JSFunction, to_name) \
V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
V(TO_PRIMITIVE_INDEX, JSFunction, to_primitive) \
V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun)
......@@ -135,7 +134,6 @@ enum BindingFlags {
V(STRING_ADD_RIGHT_BUILTIN_INDEX, JSFunction, string_add_right_builtin) \
V(SUB_BUILTIN_INDEX, JSFunction, sub_builtin) \
V(SUB_STRONG_BUILTIN_INDEX, JSFunction, sub_strong_builtin) \
V(TO_NAME_BUILTIN_INDEX, JSFunction, to_name_builtin) \
V(TO_STRING_BUILTIN_INDEX, JSFunction, to_string_builtin)
......
......@@ -861,7 +861,7 @@ ObjectMirror.prototype.internalProperties = function() {
ObjectMirror.prototype.property = function(name) {
var details = %DebugGetPropertyDetails(this.value_, builtins.$toName(name));
var details = %DebugGetPropertyDetails(this.value_, TO_NAME(name));
if (details) {
return new PropertyMirror(this, name, details);
}
......
......@@ -883,7 +883,7 @@ void FullCodeGenerator::EmitUnwindBeforeReturn() {
void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property,
BailoutId bailout_id) {
VisitForStackValue(property->key());
__ InvokeBuiltin(Context::TO_NAME_BUILTIN_INDEX, CALL_FUNCTION);
__ CallRuntime(Runtime::kToName, 1);
PrepareForBailoutForId(bailout_id, NO_REGISTERS);
__ Push(result_register());
}
......
......@@ -156,6 +156,7 @@ macro TO_OBJECT(arg) = (%_ToObject(arg));
macro TO_PRIMITIVE(arg) = (%_ToPrimitive(arg));
macro TO_PRIMITIVE_NUMBER(arg) = (%_ToPrimitive_Number(arg));
macro TO_PRIMITIVE_STRING(arg) = (%_ToPrimitive_String(arg));
macro TO_NAME(arg) = (%_ToName(arg));
macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");
macro HAS_OWN_PROPERTY(arg, index) = (%_CallFunction(arg, index, ObjectHasOwnProperty));
macro SHOULD_CREATE_WRAPPER(functionName, receiver) = (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(functionName));
......
......@@ -19,7 +19,6 @@ var $sameValue;
var $sameValueZero;
var $toInteger;
var $toLength;
var $toName;
var $toNumber;
var $toPositiveInteger;
var $toPrimitive;
......@@ -434,7 +433,7 @@ function IN(x) {
}
return %HasElement(x, this);
}
return %HasProperty(x, %to_name(this));
return %HasProperty(x, this);
}
......@@ -616,12 +615,6 @@ function TO_STRING() {
}
// Convert the receiver to a string or symbol - forward to ToName.
function TO_NAME() {
return %to_name(this);
}
/* -------------------------------------
- - - C o n v e r s i o n s - - -
-------------------------------------
......@@ -690,12 +683,6 @@ function NonStringToString(x) {
}
// ES6 symbols
function ToName(x) {
return IS_SYMBOL(x) ? x : ToString(x);
}
// ECMA-262, section 9.4, page 34.
function ToInteger(x) {
if (%_IsSmi(x)) return x;
......@@ -833,7 +820,6 @@ $sameValue = SameValue;
$sameValueZero = SameValueZero;
$toInteger = ToInteger;
$toLength = ToLength;
$toName = ToName;
$toNumber = ToNumber;
$toPositiveInteger = ToPositiveInteger;
$toPrimitive = ToPrimitive;
......@@ -877,7 +863,6 @@ $toString = ToString;
"string_add_right_builtin", STRING_ADD_RIGHT,
"sub_builtin", SUB,
"sub_strong_builtin", SUB_STRONG,
"to_name_builtin", TO_NAME,
"to_string_builtin", TO_STRING,
]);
......@@ -887,7 +872,6 @@ $toString = ToString;
"non_string_to_string", NonStringToString,
"to_integer_fun", ToInteger,
"to_length_fun", ToLength,
"to_name", ToName,
"to_number_fun", ToNumber,
"to_primitive", ToPrimitive,
"to_string_fun", ToString,
......@@ -896,7 +880,6 @@ $toString = ToString;
utils.Export(function(to) {
to.ToBoolean = ToBoolean;
to.ToLength = ToLength;
to.ToName = ToName;
to.ToNumber = ToNumber;
to.ToPrimitive = ToPrimitive;
to.ToString = ToString;
......
......@@ -756,9 +756,12 @@ RUNTIME_FUNCTION(Runtime_HasProperty) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Maybe<bool> maybe = JSReceiver::HasProperty(receiver, key);
Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Object::ToName(isolate, key));
Maybe<bool> maybe = JSReceiver::HasProperty(receiver, name);
if (!maybe.IsJust()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(maybe.FromJust());
}
......@@ -1481,6 +1484,17 @@ RUNTIME_FUNCTION(Runtime_ToNumber) {
}
RUNTIME_FUNCTION(Runtime_ToName) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::ToName(isolate, input));
return *result;
}
RUNTIME_FUNCTION(Runtime_StrictEquals) {
SealHandleScope scope(isolate);
DCHECK_EQ(2, args.length());
......
......@@ -496,6 +496,7 @@ namespace internal {
F(ToPrimitive_String, 1, 1) \
F(OrdinaryToPrimitive, 2, 1) \
F(ToNumber, 1, 1) \
F(ToName, 1, 1) \
F(StrictEquals, 2, 1) \
F(InstanceOf, 2, 1) \
F(HasInPrototypeChain, 2, 1)
......
......@@ -176,7 +176,7 @@ function ObjectValueOf() {
// ECMA-262 - 15.2.4.5
function ObjectHasOwnProperty(value) {
var name = $toName(value);
var name = TO_NAME(value);
var object = TO_OBJECT(this);
if (%_IsJSProxy(object)) {
......@@ -200,7 +200,7 @@ function ObjectIsPrototypeOf(V) {
// ECMA-262 - 15.2.4.6
function ObjectPropertyIsEnumerable(V) {
var P = $toName(V);
var P = TO_NAME(V);
if (%_IsJSProxy(this)) {
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(V)) return false;
......@@ -225,7 +225,7 @@ function ObjectDefineGetter(name, fun) {
desc.setGet(fun);
desc.setEnumerable(true);
desc.setConfigurable(true);
DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false);
DefineOwnProperty(TO_OBJECT(receiver), TO_NAME(name), desc, false);
}
......@@ -234,7 +234,7 @@ function ObjectLookupGetter(name) {
if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
receiver = %GlobalProxy(ObjectLookupGetter);
}
return %LookupAccessor(TO_OBJECT(receiver), $toName(name), GETTER);
return %LookupAccessor(TO_OBJECT(receiver), TO_NAME(name), GETTER);
}
......@@ -250,7 +250,7 @@ function ObjectDefineSetter(name, fun) {
desc.setSet(fun);
desc.setEnumerable(true);
desc.setConfigurable(true);
DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false);
DefineOwnProperty(TO_OBJECT(receiver), TO_NAME(name), desc, false);
}
......@@ -259,7 +259,7 @@ function ObjectLookupSetter(name) {
if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
receiver = %GlobalProxy(ObjectLookupSetter);
}
return %LookupAccessor(TO_OBJECT(receiver), $toName(name), SETTER);
return %LookupAccessor(TO_OBJECT(receiver), TO_NAME(name), SETTER);
}
......@@ -561,7 +561,7 @@ function CallTrap2(handler, name, defaultTrap, x, y) {
// ES5 section 8.12.1.
function GetOwnPropertyJS(obj, v) {
var p = $toName(v);
var p = TO_NAME(v);
if (%_IsJSProxy(obj)) {
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(v)) return UNDEFINED;
......@@ -632,7 +632,7 @@ function DefineProxyProperty(obj, p, attributes, should_throw) {
// ES5 8.12.9.
function DefineObjectProperty(obj, p, desc, should_throw) {
var current_array = %GetOwnProperty(obj, $toName(p));
var current_array = %GetOwnProperty(obj, TO_NAME(p));
var current = ConvertDescriptorArrayToDescriptor(current_array);
var extensible = %IsExtensible(obj);
......@@ -906,7 +906,7 @@ function ToNameArray(obj, trap, includeSymbols) {
var realLength = 0;
var names = { __proto__: null }; // TODO(rossberg): use sets once ready.
for (var index = 0; index < n; index++) {
var s = $toName(obj[index]);
var s = TO_NAME(obj[index]);
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(s) && !includeSymbols) continue;
if (%HasOwnProperty(names, s)) {
......@@ -1032,7 +1032,7 @@ function ObjectDefineProperty(obj, p, attributes) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError(kCalledOnNonObject, "Object.defineProperty");
}
var name = $toName(p);
var name = TO_NAME(p);
if (%_IsJSProxy(obj)) {
// Clone the attributes object for protection.
// TODO(rossberg): not spec'ed yet, so not sure if this should involve
......
// Copyright 2015 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
assertEquals("1", %ToName(1));
assertEquals("1", %_ToName(1));
assertEquals("0.5", %ToName(.5));
assertEquals("0.5", %_ToName(.5));
assertEquals("null", %ToName(null));
assertEquals("null", %_ToName(null));
assertEquals("true", %ToName(true));
assertEquals("true", %_ToName(true));
assertEquals("false", %ToName(false));
assertEquals("false", %_ToName(false));
assertEquals("undefined", %ToName(undefined));
assertEquals("undefined", %_ToName(undefined));
assertEquals("random text", %ToName("random text"));
assertEquals("random text", %_ToName("random text"));
assertEquals(Symbol.toPrimitive, %ToName(Symbol.toPrimitive));
assertEquals(Symbol.toPrimitive, %_ToName(Symbol.toPrimitive));
var a = { toString: function() { return "xyz" }};
assertEquals("xyz", %ToName(a));
assertEquals("xyz", %_ToName(a));
var b = { valueOf: function() { return 42 }};
assertEquals("[object Object]", %ToName(b));
assertEquals("[object Object]", %_ToName(b));
var c = {
toString: function() { return "x"},
valueOf: function() { return 123 }
};
assertEquals("x", %ToName(c));
assertEquals("x", %_ToName(c));
var d = {
[Symbol.toPrimitive]: function(hint) { return hint }
};
assertEquals("string", %ToName(d));
assertEquals("string", %_ToName(d));
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