Submit Object.getOwnPropertyNames patch by Pavel Feldman. See http://codereview.chromium.org/549050.
Add copyright to regression test to fix build broken by r3619. TBR=sgjesse@chromium.org Review URL: http://codereview.chromium.org/542092 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3620 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
4a90166dde
commit
a3c0f20035
@ -178,8 +178,7 @@ function FormatMessage(message) {
|
||||
result_not_primitive: "Result of %0 must be a primitive, was %1",
|
||||
invalid_json: "String '%0' is not valid JSON",
|
||||
circular_structure: "Converting circular structure to JSON",
|
||||
object_keys_non_object: "Object.keys called on non-object",
|
||||
object_get_prototype_non_object: "Object.getPrototypeOf called on non-object",
|
||||
obj_ctor_property_non_object: "Object.%0 called on non-object",
|
||||
array_indexof_not_defined: "Array.getIndexOf: Argument undefined"
|
||||
};
|
||||
}
|
||||
|
@ -600,14 +600,14 @@ ObjectMirror.prototype.protoObject = function() {
|
||||
|
||||
ObjectMirror.prototype.hasNamedInterceptor = function() {
|
||||
// Get information on interceptors for this object.
|
||||
var x = %DebugInterceptorInfo(this.value_);
|
||||
var x = %GetInterceptorInfo(this.value_);
|
||||
return (x & 2) != 0;
|
||||
};
|
||||
|
||||
|
||||
ObjectMirror.prototype.hasIndexedInterceptor = function() {
|
||||
// Get information on interceptors for this object.
|
||||
var x = %DebugInterceptorInfo(this.value_);
|
||||
var x = %GetInterceptorInfo(this.value_);
|
||||
return (x & 1) != 0;
|
||||
};
|
||||
|
||||
@ -631,13 +631,13 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
|
||||
// Find all the named properties.
|
||||
if (kind & PropertyKind.Named) {
|
||||
// Get the local property names.
|
||||
propertyNames = %DebugLocalPropertyNames(this.value_);
|
||||
propertyNames = %GetLocalPropertyNames(this.value_);
|
||||
total += propertyNames.length;
|
||||
|
||||
// Get names for named interceptor properties if any.
|
||||
if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
|
||||
var namedInterceptorNames =
|
||||
%DebugNamedInterceptorPropertyNames(this.value_);
|
||||
%GetNamedInterceptorPropertyNames(this.value_);
|
||||
if (namedInterceptorNames) {
|
||||
propertyNames = propertyNames.concat(namedInterceptorNames);
|
||||
total += namedInterceptorNames.length;
|
||||
@ -648,13 +648,13 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
|
||||
// Find all the indexed properties.
|
||||
if (kind & PropertyKind.Indexed) {
|
||||
// Get the local element names.
|
||||
elementNames = %DebugLocalElementNames(this.value_);
|
||||
elementNames = %GetLocalElementNames(this.value_);
|
||||
total += elementNames.length;
|
||||
|
||||
// Get names for indexed interceptor properties.
|
||||
if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
|
||||
var indexedInterceptorNames =
|
||||
%DebugIndexedInterceptorElementNames(this.value_);
|
||||
%GetIndexedInterceptorElementNames(this.value_);
|
||||
if (indexedInterceptorNames) {
|
||||
elementNames = elementNames.concat(indexedInterceptorNames);
|
||||
total += indexedInterceptorNames.length;
|
||||
|
300
src/runtime.cc
300
src/runtime.cc
@ -3213,6 +3213,156 @@ static Object* Runtime_GetPropertyNamesFast(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
// Find the length of the prototype chain that is to to handled as one. If a
|
||||
// prototype object is hidden it is to be viewed as part of the the object it
|
||||
// is prototype for.
|
||||
static int LocalPrototypeChainLength(JSObject* obj) {
|
||||
int count = 1;
|
||||
Object* proto = obj->GetPrototype();
|
||||
while (proto->IsJSObject() &&
|
||||
JSObject::cast(proto)->map()->is_hidden_prototype()) {
|
||||
count++;
|
||||
proto = JSObject::cast(proto)->GetPrototype();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// Return the names of the local named properties.
|
||||
// args[0]: object
|
||||
static Object* Runtime_GetLocalPropertyNames(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
if (!args[0]->IsJSObject()) {
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
// Skip the global proxy as it has no properties and always delegates to the
|
||||
// real global object.
|
||||
if (obj->IsJSGlobalProxy()) {
|
||||
obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
|
||||
}
|
||||
|
||||
// Find the number of objects making up this.
|
||||
int length = LocalPrototypeChainLength(*obj);
|
||||
|
||||
// Find the number of local properties for each of the objects.
|
||||
int* local_property_count = NewArray<int>(length);
|
||||
int total_property_count = 0;
|
||||
Handle<JSObject> jsproto = obj;
|
||||
for (int i = 0; i < length; i++) {
|
||||
int n;
|
||||
n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
|
||||
local_property_count[i] = n;
|
||||
total_property_count += n;
|
||||
if (i < length - 1) {
|
||||
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate an array with storage for all the property names.
|
||||
Handle<FixedArray> names = Factory::NewFixedArray(total_property_count);
|
||||
|
||||
// Get the property names.
|
||||
jsproto = obj;
|
||||
int proto_with_hidden_properties = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
jsproto->GetLocalPropertyNames(*names,
|
||||
i == 0 ? 0 : local_property_count[i - 1]);
|
||||
if (!GetHiddenProperties(jsproto, false)->IsUndefined()) {
|
||||
proto_with_hidden_properties++;
|
||||
}
|
||||
if (i < length - 1) {
|
||||
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out name of hidden propeties object.
|
||||
if (proto_with_hidden_properties > 0) {
|
||||
Handle<FixedArray> old_names = names;
|
||||
names = Factory::NewFixedArray(
|
||||
names->length() - proto_with_hidden_properties);
|
||||
int dest_pos = 0;
|
||||
for (int i = 0; i < total_property_count; i++) {
|
||||
Object* name = old_names->get(i);
|
||||
if (name == Heap::hidden_symbol()) {
|
||||
continue;
|
||||
}
|
||||
names->set(dest_pos++, name);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteArray(local_property_count);
|
||||
return *Factory::NewJSArrayWithElements(names);
|
||||
}
|
||||
|
||||
|
||||
// Return the names of the local indexed properties.
|
||||
// args[0]: object
|
||||
static Object* Runtime_GetLocalElementNames(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
if (!args[0]->IsJSObject()) {
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
|
||||
Handle<FixedArray> names = Factory::NewFixedArray(n);
|
||||
obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
|
||||
return *Factory::NewJSArrayWithElements(names);
|
||||
}
|
||||
|
||||
|
||||
// Return information on whether an object has a named or indexed interceptor.
|
||||
// args[0]: object
|
||||
static Object* Runtime_GetInterceptorInfo(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
if (!args[0]->IsJSObject()) {
|
||||
return Smi::FromInt(0);
|
||||
}
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
int result = 0;
|
||||
if (obj->HasNamedInterceptor()) result |= 2;
|
||||
if (obj->HasIndexedInterceptor()) result |= 1;
|
||||
|
||||
return Smi::FromInt(result);
|
||||
}
|
||||
|
||||
|
||||
// Return property names from named interceptor.
|
||||
// args[0]: object
|
||||
static Object* Runtime_GetNamedInterceptorPropertyNames(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
if (obj->HasNamedInterceptor()) {
|
||||
v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
|
||||
if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
|
||||
}
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
|
||||
|
||||
// Return element names from indexed interceptor.
|
||||
// args[0]: object
|
||||
static Object* Runtime_GetIndexedInterceptorElementNames(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
if (obj->HasIndexedInterceptor()) {
|
||||
v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
|
||||
if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
|
||||
}
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_LocalKeys(Arguments args) {
|
||||
ASSERT_EQ(args.length(), 1);
|
||||
CONVERT_CHECKED(JSObject, raw_object, args[0]);
|
||||
@ -6005,21 +6155,6 @@ static Object* Runtime_Break(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
// Find the length of the prototype chain that is to to handled as one. If a
|
||||
// prototype object is hidden it is to be viewed as part of the the object it
|
||||
// is prototype for.
|
||||
static int LocalPrototypeChainLength(JSObject* obj) {
|
||||
int count = 1;
|
||||
Object* proto = obj->GetPrototype();
|
||||
while (proto->IsJSObject() &&
|
||||
JSObject::cast(proto)->map()->is_hidden_prototype()) {
|
||||
count++;
|
||||
proto = JSObject::cast(proto)->GetPrototype();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static Object* DebugLookupResultValue(Object* receiver, String* name,
|
||||
LookupResult* result,
|
||||
bool* caught_exception) {
|
||||
@ -6189,93 +6324,6 @@ static Object* Runtime_DebugGetProperty(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
// Return the names of the local named properties.
|
||||
// args[0]: object
|
||||
static Object* Runtime_DebugLocalPropertyNames(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
if (!args[0]->IsJSObject()) {
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
// Skip the global proxy as it has no properties and always delegates to the
|
||||
// real global object.
|
||||
if (obj->IsJSGlobalProxy()) {
|
||||
obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
|
||||
}
|
||||
|
||||
// Find the number of objects making up this.
|
||||
int length = LocalPrototypeChainLength(*obj);
|
||||
|
||||
// Find the number of local properties for each of the objects.
|
||||
int* local_property_count = NewArray<int>(length);
|
||||
int total_property_count = 0;
|
||||
Handle<JSObject> jsproto = obj;
|
||||
for (int i = 0; i < length; i++) {
|
||||
int n;
|
||||
n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
|
||||
local_property_count[i] = n;
|
||||
total_property_count += n;
|
||||
if (i < length - 1) {
|
||||
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate an array with storage for all the property names.
|
||||
Handle<FixedArray> names = Factory::NewFixedArray(total_property_count);
|
||||
|
||||
// Get the property names.
|
||||
jsproto = obj;
|
||||
int proto_with_hidden_properties = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
jsproto->GetLocalPropertyNames(*names,
|
||||
i == 0 ? 0 : local_property_count[i - 1]);
|
||||
if (!GetHiddenProperties(jsproto, false)->IsUndefined()) {
|
||||
proto_with_hidden_properties++;
|
||||
}
|
||||
if (i < length - 1) {
|
||||
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out name of hidden propeties object.
|
||||
if (proto_with_hidden_properties > 0) {
|
||||
Handle<FixedArray> old_names = names;
|
||||
names = Factory::NewFixedArray(
|
||||
names->length() - proto_with_hidden_properties);
|
||||
int dest_pos = 0;
|
||||
for (int i = 0; i < total_property_count; i++) {
|
||||
Object* name = old_names->get(i);
|
||||
if (name == Heap::hidden_symbol()) {
|
||||
continue;
|
||||
}
|
||||
names->set(dest_pos++, name);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteArray(local_property_count);
|
||||
return *Factory::NewJSArrayWithElements(names);
|
||||
}
|
||||
|
||||
|
||||
// Return the names of the local indexed properties.
|
||||
// args[0]: object
|
||||
static Object* Runtime_DebugLocalElementNames(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
if (!args[0]->IsJSObject()) {
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
|
||||
Handle<FixedArray> names = Factory::NewFixedArray(n);
|
||||
obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
|
||||
return *Factory::NewJSArrayWithElements(names);
|
||||
}
|
||||
|
||||
|
||||
// Return the property type calculated from the property details.
|
||||
// args[0]: smi with property details.
|
||||
static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
|
||||
@ -6306,54 +6354,6 @@ static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
// Return information on whether an object has a named or indexed interceptor.
|
||||
// args[0]: object
|
||||
static Object* Runtime_DebugInterceptorInfo(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
if (!args[0]->IsJSObject()) {
|
||||
return Smi::FromInt(0);
|
||||
}
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
int result = 0;
|
||||
if (obj->HasNamedInterceptor()) result |= 2;
|
||||
if (obj->HasIndexedInterceptor()) result |= 1;
|
||||
|
||||
return Smi::FromInt(result);
|
||||
}
|
||||
|
||||
|
||||
// Return property names from named interceptor.
|
||||
// args[0]: object
|
||||
static Object* Runtime_DebugNamedInterceptorPropertyNames(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
if (obj->HasNamedInterceptor()) {
|
||||
v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
|
||||
if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
|
||||
}
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
|
||||
|
||||
// Return element names from indexed interceptor.
|
||||
// args[0]: object
|
||||
static Object* Runtime_DebugIndexedInterceptorElementNames(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 1);
|
||||
CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
||||
|
||||
if (obj->HasIndexedInterceptor()) {
|
||||
v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
|
||||
if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
|
||||
}
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
|
||||
|
||||
// Return property value from named interceptor.
|
||||
// args[0]: object
|
||||
// args[1]: property name
|
||||
|
@ -52,6 +52,11 @@ namespace internal {
|
||||
F(IsPropertyEnumerable, 2, 1) \
|
||||
F(GetPropertyNames, 1, 1) \
|
||||
F(GetPropertyNamesFast, 1, 1) \
|
||||
F(GetLocalPropertyNames, 1, 1) \
|
||||
F(GetLocalElementNames, 1, 1) \
|
||||
F(GetInterceptorInfo, 1, 1) \
|
||||
F(GetNamedInterceptorPropertyNames, 1, 1) \
|
||||
F(GetIndexedInterceptorElementNames, 1, 1) \
|
||||
F(GetArgumentsProperty, 1, 1) \
|
||||
F(ToFastProperties, 1, 1) \
|
||||
F(ToSlowProperties, 1, 1) \
|
||||
@ -285,14 +290,9 @@ namespace internal {
|
||||
F(Break, 0, 1) \
|
||||
F(DebugGetPropertyDetails, 2, 1) \
|
||||
F(DebugGetProperty, 2, 1) \
|
||||
F(DebugLocalPropertyNames, 1, 1) \
|
||||
F(DebugLocalElementNames, 1, 1) \
|
||||
F(DebugPropertyTypeFromDetails, 1, 1) \
|
||||
F(DebugPropertyAttributesFromDetails, 1, 1) \
|
||||
F(DebugPropertyIndexFromDetails, 1, 1) \
|
||||
F(DebugInterceptorInfo, 1, 1) \
|
||||
F(DebugNamedInterceptorPropertyNames, 1, 1) \
|
||||
F(DebugIndexedInterceptorElementNames, 1, 1) \
|
||||
F(DebugNamedInterceptorPropertyValue, 2, 1) \
|
||||
F(DebugIndexedInterceptorElementValue, 2, 1) \
|
||||
F(CheckExecutionState, 1, 1) \
|
||||
|
@ -276,7 +276,7 @@ function ObjectLookupSetter(name) {
|
||||
|
||||
function ObjectKeys(obj) {
|
||||
if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
|
||||
throw MakeTypeError('object_keys_non_object', [obj]);
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["keys"]);
|
||||
return %LocalKeys(obj);
|
||||
}
|
||||
|
||||
@ -493,23 +493,59 @@ function DefineOwnProperty(obj, p, desc, should_throw) {
|
||||
|
||||
// ES5 section 15.2.3.2.
|
||||
function ObjectGetPrototypeOf(obj) {
|
||||
if (!IS_OBJECT(obj) && !IS_FUNCTION(obj)) {
|
||||
throw MakeTypeError("object_get_prototype_non_object", [obj]);
|
||||
}
|
||||
return obj.__proto__;
|
||||
if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]);
|
||||
return obj.__proto__;
|
||||
}
|
||||
|
||||
|
||||
// ES5 section 15.2.3.3
|
||||
function ObjectGetOwnPropertyDescriptor(obj, p) {
|
||||
if (!IS_OBJECT(obj) && !IS_FUNCTION(obj)) {
|
||||
throw MakeTypeError("object_get_prototype_non_object", [obj]);
|
||||
}
|
||||
if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescriptor"]);
|
||||
var desc = GetOwnProperty(obj, p);
|
||||
return FromPropertyDescriptor(desc);
|
||||
}
|
||||
|
||||
|
||||
// ES5 section 15.2.3.4.
|
||||
function ObjectGetOwnPropertyNames(obj) {
|
||||
if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyNames"]);
|
||||
|
||||
// Find all the indexed properties.
|
||||
|
||||
// Get the local element names.
|
||||
var propertyNames = %GetLocalElementNames(obj);
|
||||
|
||||
// Get names for indexed interceptor properties.
|
||||
if (%GetInterceptorInfo(obj) & 1) {
|
||||
var indexedInterceptorNames =
|
||||
%GetIndexedInterceptorElementNames(obj);
|
||||
if (indexedInterceptorNames) {
|
||||
propertyNames = propertyNames.concat(indexedInterceptorNames);
|
||||
}
|
||||
}
|
||||
|
||||
// Find all the named properties.
|
||||
|
||||
// Get the local property names.
|
||||
propertyNames = propertyNames.concat(%GetLocalPropertyNames(obj));
|
||||
|
||||
// Get names for named interceptor properties if any.
|
||||
|
||||
if (%GetInterceptorInfo(obj) & 2) {
|
||||
var namedInterceptorNames =
|
||||
%GetNamedInterceptorPropertyNames(obj);
|
||||
if (namedInterceptorNames) {
|
||||
propertyNames = propertyNames.concat(namedInterceptorNames);
|
||||
}
|
||||
}
|
||||
|
||||
return propertyNames;
|
||||
}
|
||||
|
||||
|
||||
// ES5 section 15.2.3.5.
|
||||
function ObjectCreate(proto, properties) {
|
||||
if (!IS_OBJECT(proto) && !IS_NULL(proto)) {
|
||||
@ -576,7 +612,8 @@ function SetupObject() {
|
||||
"keys", ObjectKeys,
|
||||
"create", ObjectCreate,
|
||||
"getPrototypeOf", ObjectGetPrototypeOf,
|
||||
"getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor
|
||||
"getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor,
|
||||
"getOwnPropertyNames", ObjectGetOwnPropertyNames
|
||||
));
|
||||
}
|
||||
|
||||
|
104
test/mjsunit/object-get-own-property-names.js
Normal file
104
test/mjsunit/object-get-own-property-names.js
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2009 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Test ES5 section 15.2.3.4 Object.getOwnPropertyNames.
|
||||
|
||||
// Check simple cases.
|
||||
var obj = { a: 1, b: 2};
|
||||
var propertyNames = Object.getOwnPropertyNames(obj);
|
||||
propertyNames.sort();
|
||||
assertEquals(2, propertyNames.length);
|
||||
assertEquals("a", propertyNames[0]);
|
||||
assertEquals("b", propertyNames[1]);
|
||||
|
||||
var obj = { a: function(){}, b: function(){} };
|
||||
var propertyNames = Object.getOwnPropertyNames(obj);
|
||||
propertyNames.sort();
|
||||
assertEquals(2, propertyNames.length);
|
||||
assertEquals("a", propertyNames[0]);
|
||||
assertEquals("b", propertyNames[1]);
|
||||
|
||||
// Check slow case
|
||||
var obj = { a: 1, b: 2, c: 3 };
|
||||
delete obj.b;
|
||||
var propertyNames = Object.getOwnPropertyNames(obj)
|
||||
propertyNames.sort();
|
||||
assertEquals(2, propertyNames.length);
|
||||
assertEquals("a", propertyNames[0]);
|
||||
assertEquals("c", propertyNames[1]);
|
||||
|
||||
// Check that non-enumerable properties are being returned.
|
||||
var propertyNames = Object.getOwnPropertyNames([1, 2]);
|
||||
propertyNames.sort();
|
||||
assertEquals(3, propertyNames.length);
|
||||
assertEquals("0", propertyNames[0]);
|
||||
assertEquals("1", propertyNames[1]);
|
||||
assertEquals("length", propertyNames[2]);
|
||||
|
||||
// Check that no proto properties are returned.
|
||||
var obj = { foo: "foo" };
|
||||
obj.__proto__ = { bar: "bar" };
|
||||
propertyNames = Object.getOwnPropertyNames(obj);
|
||||
propertyNames.sort();
|
||||
assertEquals(1, propertyNames.length);
|
||||
assertEquals("foo", propertyNames[0]);
|
||||
|
||||
// Check that getter properties are returned.
|
||||
var obj = {};
|
||||
obj.__defineGetter__("getter", function() {});
|
||||
propertyNames = Object.getOwnPropertyNames(obj);
|
||||
propertyNames.sort();
|
||||
assertEquals(1, propertyNames.length);
|
||||
assertEquals("getter", propertyNames[0]);
|
||||
|
||||
try {
|
||||
Object.getOwnPropertyNames(4);
|
||||
assertTrue(false);
|
||||
} catch (e) {
|
||||
assertTrue(/on non-object/.test(e));
|
||||
}
|
||||
|
||||
try {
|
||||
Object.getOwnPropertyNames("foo");
|
||||
assertTrue(false);
|
||||
} catch (e) {
|
||||
assertTrue(/on non-object/.test(e));
|
||||
}
|
||||
|
||||
try {
|
||||
Object.getOwnPropertyNames(undefined);
|
||||
assertTrue(false);
|
||||
} catch (e) {
|
||||
assertTrue(/on non-object/.test(e));
|
||||
}
|
||||
|
||||
try {
|
||||
Object.getOwnPropertyNames(null);
|
||||
assertTrue(false);
|
||||
} catch (e) {
|
||||
assertTrue(/on non-object/.test(e));
|
||||
}
|
@ -1,3 +1,30 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Object.extend = function (dest, source) {
|
||||
for (property in source) dest[property] = source[property];
|
||||
return dest;
|
||||
|
Loading…
Reference in New Issue
Block a user