[proxies] Make Array.isArray respect proxies.
An array is either a JSArray or a proxy whose target is an array. R=bmeurer@chromium.org BUG= Review URL: https://codereview.chromium.org/1497483004 Cr-Commit-Position: refs/heads/master@{#32558}
This commit is contained in:
parent
a32096c43c
commit
82d974799b
@ -1014,6 +1014,20 @@ void Genesis::HookUpGlobalObject(Handle<JSGlobalObject> global_object) {
|
||||
}
|
||||
|
||||
|
||||
static void SimpleInstallFunction(Handle<JSObject> base, Handle<Name> name,
|
||||
Builtins::Name call, int len, bool adapt) {
|
||||
Handle<JSFunction> fun =
|
||||
InstallFunction(base, name, JS_OBJECT_TYPE, JSObject::kHeaderSize,
|
||||
MaybeHandle<JSObject>(), call, DONT_ENUM);
|
||||
if (adapt) {
|
||||
fun->shared()->set_internal_formal_parameter_count(len);
|
||||
} else {
|
||||
fun->shared()->DontAdaptArguments();
|
||||
}
|
||||
fun->shared()->set_length(len);
|
||||
}
|
||||
|
||||
|
||||
// This is only called if we are not using snapshots. The equivalent
|
||||
// work in the snapshot case is done in HookUpGlobalObject.
|
||||
void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
@ -1100,6 +1114,10 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
Map::Copy(initial_map, "SetInstancePrototype");
|
||||
initial_strong_map->set_is_strong();
|
||||
CacheInitialJSArrayMaps(native_context(), initial_strong_map);
|
||||
|
||||
SimpleInstallFunction(array_function,
|
||||
factory->NewStringFromAsciiChecked("isArray"),
|
||||
Builtins::kArrayIsArray, 1, true);
|
||||
}
|
||||
|
||||
{ // --- N u m b e r ---
|
||||
@ -1969,20 +1987,6 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_do_expressions)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_regexp_lookbehind)
|
||||
|
||||
|
||||
static void SimpleInstallFunction(Handle<JSObject> base, Handle<Name> name,
|
||||
Builtins::Name call, int len, bool adapt) {
|
||||
Handle<JSFunction> fun =
|
||||
InstallFunction(base, name, JS_OBJECT_TYPE, JSObject::kHeaderSize,
|
||||
MaybeHandle<JSObject>(), call, DONT_ENUM);
|
||||
if (adapt) {
|
||||
fun->shared()->set_internal_formal_parameter_count(len);
|
||||
} else {
|
||||
fun->shared()->DontAdaptArguments();
|
||||
}
|
||||
fun->shared()->set_length(len);
|
||||
}
|
||||
|
||||
|
||||
void InstallPublicSymbol(Factory* factory, Handle<Context> native_context,
|
||||
const char* name, Handle<Symbol> value) {
|
||||
Handle<JSGlobalObject> global(
|
||||
|
@ -1423,6 +1423,17 @@ BUILTIN(ArrayConcat) {
|
||||
}
|
||||
|
||||
|
||||
// ES6 section 22.1.2.2 Array.isArray
|
||||
BUILTIN(ArrayIsArray) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
Handle<Object> object = args.at<Object>(1);
|
||||
Maybe<bool> result = Object::IsArray(object);
|
||||
MAYBE_RETURN(result, isolate->heap()->exception());
|
||||
return *isolate->factory()->ToBoolean(result.FromJust());
|
||||
}
|
||||
|
||||
|
||||
// ES6 section 26.1.3 Reflect.defineProperty
|
||||
BUILTIN(ReflectDefineProperty) {
|
||||
HandleScope scope(isolate);
|
||||
|
@ -56,13 +56,14 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
|
||||
\
|
||||
V(EmptyFunction, kNone) \
|
||||
\
|
||||
V(ArrayPush, kNone) \
|
||||
V(ArrayConcat, kNone) \
|
||||
V(ArrayIsArray, kNone) \
|
||||
V(ArrayPop, kNone) \
|
||||
V(ArrayPush, kNone) \
|
||||
V(ArrayShift, kNone) \
|
||||
V(ArrayUnshift, kNone) \
|
||||
V(ArraySlice, kNone) \
|
||||
V(ArraySplice, kNone) \
|
||||
V(ArrayConcat, kNone) \
|
||||
V(ArrayUnshift, kNone) \
|
||||
\
|
||||
V(DateToPrimitive, kNone) \
|
||||
\
|
||||
|
@ -1697,12 +1697,6 @@ function ArrayFill(value, start, end) {
|
||||
}
|
||||
|
||||
|
||||
// ES5, 15.4.3.2
|
||||
function ArrayIsArray(obj) {
|
||||
return IS_ARRAY(obj);
|
||||
}
|
||||
|
||||
|
||||
function AddArrayElement(constructor, array, i, value) {
|
||||
if (constructor === GlobalArray) {
|
||||
AddIndexedProperty(array, i, value);
|
||||
@ -1816,7 +1810,6 @@ var unscopables = {
|
||||
|
||||
// Set up non-enumerable functions on the Array object.
|
||||
utils.InstallFunctions(GlobalArray, DONT_ENUM, [
|
||||
"isArray", ArrayIsArray,
|
||||
"from", ArrayFrom,
|
||||
"of", ArrayOf
|
||||
]);
|
||||
|
@ -624,6 +624,23 @@ MaybeHandle<Object> Object::BitwiseXor(Isolate* isolate, Handle<Object> lhs,
|
||||
}
|
||||
|
||||
|
||||
Maybe<bool> Object::IsArray(Handle<Object> object) {
|
||||
if (object->IsJSArray()) return Just(true);
|
||||
if (object->IsJSProxy()) {
|
||||
Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
|
||||
Isolate* isolate = proxy->GetIsolate();
|
||||
if (proxy->IsRevoked()) {
|
||||
isolate->Throw(*isolate->factory()->NewTypeError(
|
||||
MessageTemplate::kProxyRevoked,
|
||||
isolate->factory()->NewStringFromAsciiChecked("IsArray")));
|
||||
return Nothing<bool>();
|
||||
}
|
||||
return Object::IsArray(handle(proxy->target(), isolate));
|
||||
}
|
||||
return Just(false);
|
||||
}
|
||||
|
||||
|
||||
bool Object::IsPromise(Handle<Object> object) {
|
||||
if (!object->IsJSObject()) return false;
|
||||
auto js_object = Handle<JSObject>::cast(object);
|
||||
@ -996,7 +1013,7 @@ MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
|
||||
}
|
||||
|
||||
|
||||
bool JSProxy::IsRevoked() {
|
||||
bool JSProxy::IsRevoked() const {
|
||||
// TODO(neis): Decide on how to represent revocation. For now, revocation is
|
||||
// unsupported.
|
||||
DCHECK(target()->IsJSReceiver());
|
||||
|
@ -1055,6 +1055,9 @@ class Object {
|
||||
STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
|
||||
#undef DECLARE_STRUCT_PREDICATE
|
||||
|
||||
// ES6, section 7.2.2 IsArray. NOT to be confused with %_IsArray.
|
||||
MUST_USE_RESULT static Maybe<bool> IsArray(Handle<Object> object);
|
||||
|
||||
// ES6, section 7.2.3 IsCallable.
|
||||
INLINE(bool IsCallable() const);
|
||||
|
||||
@ -9498,7 +9501,7 @@ class JSProxy: public JSReceiver {
|
||||
|
||||
DECLARE_CAST(JSProxy)
|
||||
|
||||
bool IsRevoked();
|
||||
bool IsRevoked() const;
|
||||
|
||||
// ES6 9.5.1
|
||||
static MaybeHandle<Object> GetPrototype(Handle<JSProxy> receiver);
|
||||
|
16
test/mjsunit/array-isarray.js
Normal file
16
test/mjsunit/array-isarray.js
Normal file
@ -0,0 +1,16 @@
|
||||
// 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-proxies
|
||||
|
||||
|
||||
assertTrue(Array.isArray([]));
|
||||
assertFalse(Array.isArray({}));
|
||||
assertFalse(Array.isArray(null));
|
||||
|
||||
assertTrue(Array.isArray(new Proxy([], {})));
|
||||
assertFalse(Array.isArray(new Proxy({}, {})));
|
||||
|
||||
assertTrue(Array.isArray(new Proxy(new Proxy([], {}), {})));
|
||||
assertFalse(Array.isArray(new Proxy(new Proxy({}, {}), {})));
|
Loading…
Reference in New Issue
Block a user