[proxies] Recognize arraylike proxies in Object.prototype.toString.
We must print "[object Array]" for proxies that satisfy Array.isArray. Cosmetic change on the side: move ObjectProtoToString from JSObject to Object since it deals with arbitrary objects. R=adamk@chromium.org, verwaest@chromium.org BUG=v8:1543 LOG=n Review URL: https://codereview.chromium.org/1526023002 Cr-Commit-Position: refs/heads/master@{#32902}
This commit is contained in:
parent
01662f1b1d
commit
f723b12336
@ -1,4 +1,4 @@
|
||||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// 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.
|
||||
|
||||
@ -2333,6 +2333,18 @@ String* JSReceiver::class_name() {
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<String> JSReceiver::BuiltinStringTag(Handle<JSReceiver> object) {
|
||||
Maybe<bool> is_array = Object::IsArray(object);
|
||||
MAYBE_RETURN(is_array, MaybeHandle<String>());
|
||||
if (is_array.FromJust()) {
|
||||
return object->GetIsolate()->factory()->Array_string();
|
||||
}
|
||||
// TODO(adamk): class_name() is expensive, replace with instance type
|
||||
// checks where possible.
|
||||
return handle(object->class_name());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
|
||||
Isolate* isolate = receiver->GetIsolate();
|
||||
@ -16267,7 +16279,7 @@ int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) {
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<String> JSObject::ObjectProtoToString(Isolate* isolate,
|
||||
MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate,
|
||||
Handle<Object> object) {
|
||||
if (object->IsUndefined()) return isolate->factory()->undefined_to_string();
|
||||
if (object->IsNull()) return isolate->factory()->null_to_string();
|
||||
@ -16288,9 +16300,8 @@ MaybeHandle<String> JSObject::ObjectProtoToString(Isolate* isolate,
|
||||
}
|
||||
|
||||
if (tag.is_null()) {
|
||||
// TODO(adamk): class_name() is expensive, replace with instance type
|
||||
// checks where possible.
|
||||
tag = handle(receiver->class_name(), isolate);
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, tag,
|
||||
JSReceiver::BuiltinStringTag(receiver), String);
|
||||
}
|
||||
|
||||
IncrementalStringBuilder builder(isolate);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// 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.
|
||||
|
||||
@ -1359,6 +1359,10 @@ class Object {
|
||||
|
||||
inline void VerifyApiCallResultType();
|
||||
|
||||
// ES6 19.1.3.6 Object.prototype.toString
|
||||
MUST_USE_RESULT static MaybeHandle<String> ObjectProtoToString(
|
||||
Isolate* isolate, Handle<Object> object);
|
||||
|
||||
// Prints this object without details.
|
||||
void ShortPrint(FILE* out = stdout);
|
||||
|
||||
@ -1887,6 +1891,10 @@ class JSReceiver: public HeapObject {
|
||||
// Returns the class name ([[Class]] property in the specification).
|
||||
String* class_name();
|
||||
|
||||
// Returns the builtin string tag used in Object.prototype.toString.
|
||||
MUST_USE_RESULT static MaybeHandle<String> BuiltinStringTag(
|
||||
Handle<JSReceiver> object);
|
||||
|
||||
// Returns the constructor name (the name (possibly, inferred name) of the
|
||||
// function that was used to instantiate the object).
|
||||
static Handle<String> GetConstructorName(Handle<JSReceiver> receiver);
|
||||
@ -2472,10 +2480,6 @@ class JSObject: public JSReceiver {
|
||||
static bool AllCanRead(LookupIterator* it);
|
||||
static bool AllCanWrite(LookupIterator* it);
|
||||
|
||||
// ES6 19.1.3.6 Object.prototype.toString
|
||||
MUST_USE_RESULT static MaybeHandle<String> ObjectProtoToString(
|
||||
Isolate* isolate, Handle<Object> object);
|
||||
|
||||
private:
|
||||
friend class JSReceiver;
|
||||
friend class Object;
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// 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: --harmony-tostring
|
||||
// Flags: --harmony-tostring --harmony-proxies
|
||||
|
||||
var global = this;
|
||||
|
||||
@ -137,3 +137,25 @@ function testObjectToStringOwnNonStringValue() {
|
||||
assertEquals("[object Object]", ({}).toString.call(obj));
|
||||
}
|
||||
testObjectToStringOwnNonStringValue();
|
||||
|
||||
|
||||
// Proxies
|
||||
|
||||
function assertTag(tag, obj) {
|
||||
assertEquals("[object " + tag + "]", Object.prototype.toString.call(obj));
|
||||
}
|
||||
|
||||
assertTag("Object", new Proxy({}, {}));
|
||||
assertTag("Array", new Proxy([], {}));
|
||||
assertTag("Function", new Proxy(() => 42, {}));
|
||||
assertTag("Foo", new Proxy(() => 42, {get() {return "Foo"}}));
|
||||
assertTag("Function", new Proxy(() => 42, {get() {return 666}}));
|
||||
|
||||
revocable = Proxy.revocable([], {});
|
||||
revocable.revoke();
|
||||
assertThrows(() => Object.prototype.toString.call(revocable.proxy), TypeError);
|
||||
|
||||
handler = {};
|
||||
revocable = Proxy.revocable([], handler);
|
||||
handler.get = () => revocable.revoke();
|
||||
assertThrows(() => Object.prototype.toString.call(revocable.proxy), TypeError);
|
||||
|
Loading…
Reference in New Issue
Block a user