}
-static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
- const char* name, InstanceType type,
- int instance_size,
- MaybeHandle<JSObject> maybe_prototype,
- Builtins::Name call,
- bool strict_function_map = false) {
+namespace {
+
+Handle<JSFunction> InstallFunction(Handle<JSObject> target, Handle<Name> name,
+ InstanceType type, int instance_size,
+ MaybeHandle<JSObject> maybe_prototype,
+ Builtins::Name call,
+ PropertyAttributes attributes,
+ bool strict_function_map = false) {
Isolate* isolate = target->GetIsolate();
Factory* factory = isolate->factory();
- Handle<String> internalized_name = factory->InternalizeUtf8String(name);
+ Handle<String> name_string = Name::ToFunctionName(name).ToHandleChecked();
Handle<Code> call_code = Handle<Code>(isolate->builtins()->builtin(call));
Handle<JSObject> prototype;
static const bool kReadOnlyPrototype = false;
static const bool kInstallConstructor = false;
Handle<JSFunction> function =
maybe_prototype.ToHandle(&prototype)
- ? factory->NewFunction(internalized_name, call_code, prototype, type,
+ ? factory->NewFunction(name_string, call_code, prototype, type,
instance_size, kReadOnlyPrototype,
kInstallConstructor, strict_function_map)
- : factory->NewFunctionWithoutPrototype(internalized_name, call_code,
+ : factory->NewFunctionWithoutPrototype(name_string, call_code,
strict_function_map);
+ JSObject::AddProperty(target, name, function, attributes);
+ if (target->IsJSGlobalObject()) {
+ function->shared()->set_instance_class_name(*name_string);
+ }
+ function->shared()->set_native(true);
+ return function;
+}
+
+
+Handle<JSFunction> InstallFunction(Handle<JSObject> target, const char* name,
+ InstanceType type, int instance_size,
+ MaybeHandle<JSObject> maybe_prototype,
+ Builtins::Name call,
+ bool strict_function_map = false) {
+ Factory* const factory = target->GetIsolate()->factory();
PropertyAttributes attributes;
if (target->IsJSBuiltinsObject()) {
attributes =
} else {
attributes = DONT_ENUM;
}
- JSObject::AddProperty(target, internalized_name, function, attributes);
- if (target->IsJSGlobalObject()) {
- function->shared()->set_instance_class_name(*internalized_name);
- }
- function->shared()->set_native(true);
- return function;
+ return InstallFunction(target, factory->InternalizeUtf8String(name), type,
+ instance_size, maybe_prototype, call, attributes,
+ strict_function_map);
}
+} // namespace
+
void Genesis::SetFunctionInstanceDescriptor(Handle<Map> map,
FunctionMode function_mode) {
native_context()->set_string_function_prototype_map(
HeapObject::cast(string_function->initial_map()->prototype())->map());
+ // Install Date.prototype[@@toPrimitive].
+ {
+ Handle<String> key = factory()->Date_string();
+ Handle<JSFunction> date = Handle<JSFunction>::cast(
+ Object::GetProperty(handle(native_context()->global_object()), key)
+ .ToHandleChecked());
+ Handle<JSObject> proto =
+ Handle<JSObject>(JSObject::cast(date->instance_prototype()));
+
+ // Install the @@toPrimitive function.
+ Handle<JSFunction> to_primitive =
+ InstallFunction(proto, factory()->to_primitive_symbol(), JS_OBJECT_TYPE,
+ JSObject::kHeaderSize, MaybeHandle<JSObject>(),
+ Builtins::kDateToPrimitive,
+ static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
+
+ // Set the expected parameters for @@toPrimitive to 1; required by builtin.
+ to_primitive->shared()->set_internal_formal_parameter_count(1);
+
+ // Set the length for the function to satisfy ECMA-262.
+ to_primitive->shared()->set_length(1);
+ }
+
// Install Function.prototype.call and apply.
{
Handle<String> key = factory()->Function_string();
// -----------------------------------------------------------------------------
+//
+
+
+// 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
+BUILTIN(DateToPrimitive) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(2, args.length());
+ if (!args.receiver()->IsJSReceiver()) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
+ isolate->factory()->NewStringFromAsciiChecked(
+ "Date.prototype [ @@toPrimitive ]"),
+ args.receiver()));
+ }
+ Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
+ Handle<Object> hint = args.at<Object>(1);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
+ JSDate::ToPrimitive(receiver, hint));
+ return *result;
+}
+
+
+// -----------------------------------------------------------------------------
// Throwers for restricted function properties and strict arguments object
// properties
V(ArraySplice, NO_EXTRA_ARGUMENTS) \
V(ArrayConcat, NO_EXTRA_ARGUMENTS) \
\
+ V(DateToPrimitive, NO_EXTRA_ARGUMENTS) \
+ \
V(HandleApiCall, NEEDS_CALLED_FUNCTION) \
V(HandleApiCallConstruct, NEEDS_CALLED_FUNCTION) \
V(HandleApiCallAsFunction, NO_EXTRA_ARGUMENTS) \
case Runtime::kInlineToPrimitive:
case Runtime::kInlineToPrimitive_Number:
case Runtime::kInlineToPrimitive_String:
- case Runtime::kInlineOrdinaryToPrimitive:
case Runtime::kInlineToNumber:
case Runtime::kInlineToString:
case Runtime::kInlineToName:
}
-// 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
-function DateToPrimitive(hint) {
- if (!IS_SPEC_OBJECT(this)) {
- throw MakeTypeError(kIncompatibleMethodReceiver,
- "Date.prototype [ @@toPrimitive ]", this);
- }
- if (hint === "default") {
- hint = "string";
- } else if (hint !== "number" && hint !== "string") {
- throw MakeTypeError(kInvalidHint, hint);
- }
- return %OrdinaryToPrimitive(this, hint);
-}
-
-
// ECMA 262 - 15.9.5.8
function DateValueOf() {
CHECK_DATE(this);
// Set up non-enumerable constructor property of the Date prototype object.
%AddNamedProperty(GlobalDate.prototype, "constructor", GlobalDate, DONT_ENUM);
-utils.SetFunctionName(DateToPrimitive, toPrimitiveSymbol);
-%AddNamedProperty(GlobalDate.prototype, toPrimitiveSymbol, DateToPrimitive,
- DONT_ENUM | READ_ONLY);
// Set up non-enumerable functions of the Date prototype object and
// set their names.
#include "src/objects-inl.h"
#include "src/prototype.h"
#include "src/safepoint-table.h"
+#include "src/string-builder.h"
#include "src/string-search.h"
#include "src/string-stream.h"
#include "src/utils.h"
NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
Object);
}
- return OrdinaryToPrimitive(receiver,
- (hint == ToPrimitiveHint::kString)
- ? isolate->factory()->string_string()
- : isolate->factory()->number_string());
+ return OrdinaryToPrimitive(receiver, (hint == ToPrimitiveHint::kString)
+ ? OrdinaryToPrimitiveHint::kString
+ : OrdinaryToPrimitiveHint::kNumber);
}
// static
-MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(Handle<JSReceiver> receiver,
- Handle<String> hint) {
+MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
+ Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint) {
Isolate* const isolate = receiver->GetIsolate();
Handle<String> method_names[2];
- if (hint.is_identical_to(isolate->factory()->number_string())) {
- method_names[0] = isolate->factory()->valueOf_string();
- method_names[1] = isolate->factory()->toString_string();
- } else {
- DCHECK(hint.is_identical_to(isolate->factory()->string_string()));
- method_names[0] = isolate->factory()->toString_string();
- method_names[1] = isolate->factory()->valueOf_string();
+ switch (hint) {
+ case OrdinaryToPrimitiveHint::kNumber:
+ method_names[0] = isolate->factory()->valueOf_string();
+ method_names[1] = isolate->factory()->toString_string();
+ break;
+ case OrdinaryToPrimitiveHint::kString:
+ method_names[0] = isolate->factory()->toString_string();
+ method_names[1] = isolate->factory()->valueOf_string();
+ break;
}
for (Handle<String> name : method_names) {
Handle<Object> method;
}
+// static
+MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) {
+ if (name->IsString()) return Handle<String>::cast(name);
+ // ES6 section 9.2.11 SetFunctionName, step 4.
+ Isolate* const isolate = name->GetIsolate();
+ Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
+ if (description->IsUndefined()) return isolate->factory()->empty_string();
+ IncrementalStringBuilder builder(isolate);
+ builder.AppendCharacter('[');
+ builder.AppendString(Handle<String>::cast(description));
+ builder.AppendCharacter(']');
+ return builder.Finish();
+}
+
+
namespace {
bool AreDigits(const uint8_t* s, int from, int to) {
}
+// static
+MaybeHandle<Object> JSDate::ToPrimitive(Handle<JSReceiver> receiver,
+ Handle<Object> hint) {
+ Isolate* const isolate = receiver->GetIsolate();
+ if (hint->IsString()) {
+ Handle<String> hint_string = Handle<String>::cast(hint);
+ if (hint_string->Equals(isolate->heap()->number_string())) {
+ return JSReceiver::OrdinaryToPrimitive(receiver,
+ OrdinaryToPrimitiveHint::kNumber);
+ }
+ if (hint_string->Equals(isolate->heap()->default_string()) ||
+ hint_string->Equals(isolate->heap()->string_string())) {
+ return JSReceiver::OrdinaryToPrimitive(receiver,
+ OrdinaryToPrimitiveHint::kString);
+ }
+ }
+ THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kInvalidHint, hint),
+ Object);
+}
+
+
void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
int days = DateCache::DaysFromTime(local_time_ms);
int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
enum class ToPrimitiveHint { kDefault, kNumber, kString };
+// Valid hints for the abstract operation OrdinaryToPrimitive,
+// implemented according to ES6, section 7.1.1.
+enum class OrdinaryToPrimitiveHint { kNumber, kString };
+
+
enum TypeofMode { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
Handle<JSReceiver> receiver,
ToPrimitiveHint hint = ToPrimitiveHint::kDefault);
MUST_USE_RESULT static MaybeHandle<Object> OrdinaryToPrimitive(
- Handle<JSReceiver> receiver, Handle<String> hint);
+ Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint);
// Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6.
MUST_USE_RESULT static inline Maybe<bool> HasProperty(
void SetValue(Object* value, bool is_value_nan);
+ // ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ]
+ static MUST_USE_RESULT MaybeHandle<Object> ToPrimitive(
+ Handle<JSReceiver> receiver, Handle<Object> hint);
// Dispatched behavior.
DECLARE_PRINTER(JSDate)
static inline Handle<Name> Flatten(Handle<Name> name,
PretenureFlag pretenure = NOT_TENURED);
+ // Return a string version of this name that is converted according to the
+ // rules described in ES6 section 9.2.11.
+ MUST_USE_RESULT static MaybeHandle<String> ToFunctionName(Handle<Name> name);
+
DECLARE_CAST(Name)
DECLARE_PRINTER(Name)
}
-RUNTIME_FUNCTION(Runtime_OrdinaryToPrimitive) {
- HandleScope scope(isolate);
- DCHECK_EQ(2, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
- CONVERT_ARG_HANDLE_CHECKED(String, hint, 1);
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, JSReceiver::OrdinaryToPrimitive(receiver, hint));
- return *result;
-}
-
-
RUNTIME_FUNCTION(Runtime_ToNumber) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
F(ToPrimitive, 1, 1) \
F(ToPrimitive_Number, 1, 1) \
F(ToPrimitive_String, 1, 1) \
- F(OrdinaryToPrimitive, 2, 1) \
F(ToNumber, 1, 1) \
F(ToString, 1, 1) \
F(ToName, 1, 1) \
};
assertEquals("string", %ToName(d));
assertEquals("string", %_ToName(d));
+
+var e = new Date(0);
+assertEquals(e.toString(), %ToName(e));
+assertEquals(e.toString(), %_ToName(e));
};
assertEquals(987654321, %ToNumber(d));
assertEquals(987654321, %_ToNumber(d));
+
+var e = new Date(0);
+assertEquals(0, %ToNumber(e));
+assertEquals(0, %_ToNumber(e));
assertEquals("xyz", %_ToPrimitive(a));
assertEquals("xyz", %_ToPrimitive_Number(a));
assertEquals("xyz", %_ToPrimitive_String(a));
-assertEquals("xyz", %OrdinaryToPrimitive(a, "number"));
-assertEquals("xyz", %OrdinaryToPrimitive(a, "string"));
-assertEquals("xyz", %_OrdinaryToPrimitive(a, "number"));
-assertEquals("xyz", %_OrdinaryToPrimitive(a, "string"));
var b = { valueOf: function() { return 42 }};
assertEquals(42, %ToPrimitive(b));
assertEquals(42, %_ToPrimitive(b));
assertEquals(42, %_ToPrimitive_Number(b));
assertEquals("[object Object]", %_ToPrimitive_String(b));
-assertEquals(42, %OrdinaryToPrimitive(b, "number"));
-assertEquals("[object Object]", %OrdinaryToPrimitive(b, "string"));
-assertEquals(42, %_OrdinaryToPrimitive(b, "number"));
-assertEquals("[object Object]", %_OrdinaryToPrimitive(b, "string"));
var c = {
toString: function() { return "x"},
assertEquals(123, %_ToPrimitive(c));
assertEquals(123, %_ToPrimitive_Number(c));
assertEquals("x", %_ToPrimitive_String(c));
-assertEquals(123, %OrdinaryToPrimitive(c, "number"));
-assertEquals("x", %OrdinaryToPrimitive(c, "string"));
-assertEquals(123, %_OrdinaryToPrimitive(c, "number"));
-assertEquals("x", %_OrdinaryToPrimitive(c, "string"));
var d = {
[Symbol.toPrimitive]: function(hint) { return hint }
assertEquals("default", %_ToPrimitive(d));
assertEquals("number", %_ToPrimitive_Number(d));
assertEquals("string", %_ToPrimitive_String(d));
+
+var e = new Date(0);
+assertEquals(e.toString(), %ToPrimitive(e));
+assertEquals(0, %ToPrimitive_Number(e));
+assertEquals(e.toString(), %ToPrimitive_String(e));
+assertEquals(e.toString(), %_ToPrimitive(e));
+assertEquals(0, %_ToPrimitive_Number(e));
+assertEquals(e.toString(), %_ToPrimitive_String(e));
};
assertEquals("string", %ToString(d));
assertEquals("string", %_ToString(d));
+
+var e = new Date(0);
+assertEquals(e.toString(), %ToName(e));
+assertEquals(e.toString(), %_ToName(e));