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",
|
result_not_primitive: "Result of %0 must be a primitive, was %1",
|
||||||
invalid_json: "String '%0' is not valid JSON",
|
invalid_json: "String '%0' is not valid JSON",
|
||||||
circular_structure: "Converting circular structure to JSON",
|
circular_structure: "Converting circular structure to JSON",
|
||||||
object_keys_non_object: "Object.keys called on non-object",
|
obj_ctor_property_non_object: "Object.%0 called on non-object",
|
||||||
object_get_prototype_non_object: "Object.getPrototypeOf called on non-object",
|
|
||||||
array_indexof_not_defined: "Array.getIndexOf: Argument undefined"
|
array_indexof_not_defined: "Array.getIndexOf: Argument undefined"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -600,14 +600,14 @@ ObjectMirror.prototype.protoObject = function() {
|
|||||||
|
|
||||||
ObjectMirror.prototype.hasNamedInterceptor = function() {
|
ObjectMirror.prototype.hasNamedInterceptor = function() {
|
||||||
// Get information on interceptors for this object.
|
// Get information on interceptors for this object.
|
||||||
var x = %DebugInterceptorInfo(this.value_);
|
var x = %GetInterceptorInfo(this.value_);
|
||||||
return (x & 2) != 0;
|
return (x & 2) != 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
ObjectMirror.prototype.hasIndexedInterceptor = function() {
|
ObjectMirror.prototype.hasIndexedInterceptor = function() {
|
||||||
// Get information on interceptors for this object.
|
// Get information on interceptors for this object.
|
||||||
var x = %DebugInterceptorInfo(this.value_);
|
var x = %GetInterceptorInfo(this.value_);
|
||||||
return (x & 1) != 0;
|
return (x & 1) != 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -631,13 +631,13 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
|
|||||||
// Find all the named properties.
|
// Find all the named properties.
|
||||||
if (kind & PropertyKind.Named) {
|
if (kind & PropertyKind.Named) {
|
||||||
// Get the local property names.
|
// Get the local property names.
|
||||||
propertyNames = %DebugLocalPropertyNames(this.value_);
|
propertyNames = %GetLocalPropertyNames(this.value_);
|
||||||
total += propertyNames.length;
|
total += propertyNames.length;
|
||||||
|
|
||||||
// Get names for named interceptor properties if any.
|
// Get names for named interceptor properties if any.
|
||||||
if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
|
if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
|
||||||
var namedInterceptorNames =
|
var namedInterceptorNames =
|
||||||
%DebugNamedInterceptorPropertyNames(this.value_);
|
%GetNamedInterceptorPropertyNames(this.value_);
|
||||||
if (namedInterceptorNames) {
|
if (namedInterceptorNames) {
|
||||||
propertyNames = propertyNames.concat(namedInterceptorNames);
|
propertyNames = propertyNames.concat(namedInterceptorNames);
|
||||||
total += namedInterceptorNames.length;
|
total += namedInterceptorNames.length;
|
||||||
@ -648,13 +648,13 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
|
|||||||
// Find all the indexed properties.
|
// Find all the indexed properties.
|
||||||
if (kind & PropertyKind.Indexed) {
|
if (kind & PropertyKind.Indexed) {
|
||||||
// Get the local element names.
|
// Get the local element names.
|
||||||
elementNames = %DebugLocalElementNames(this.value_);
|
elementNames = %GetLocalElementNames(this.value_);
|
||||||
total += elementNames.length;
|
total += elementNames.length;
|
||||||
|
|
||||||
// Get names for indexed interceptor properties.
|
// Get names for indexed interceptor properties.
|
||||||
if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
|
if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
|
||||||
var indexedInterceptorNames =
|
var indexedInterceptorNames =
|
||||||
%DebugIndexedInterceptorElementNames(this.value_);
|
%GetIndexedInterceptorElementNames(this.value_);
|
||||||
if (indexedInterceptorNames) {
|
if (indexedInterceptorNames) {
|
||||||
elementNames = elementNames.concat(indexedInterceptorNames);
|
elementNames = elementNames.concat(indexedInterceptorNames);
|
||||||
total += indexedInterceptorNames.length;
|
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) {
|
static Object* Runtime_LocalKeys(Arguments args) {
|
||||||
ASSERT_EQ(args.length(), 1);
|
ASSERT_EQ(args.length(), 1);
|
||||||
CONVERT_CHECKED(JSObject, raw_object, args[0]);
|
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,
|
static Object* DebugLookupResultValue(Object* receiver, String* name,
|
||||||
LookupResult* result,
|
LookupResult* result,
|
||||||
bool* caught_exception) {
|
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.
|
// Return the property type calculated from the property details.
|
||||||
// args[0]: smi with property details.
|
// args[0]: smi with property details.
|
||||||
static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
|
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.
|
// Return property value from named interceptor.
|
||||||
// args[0]: object
|
// args[0]: object
|
||||||
// args[1]: property name
|
// args[1]: property name
|
||||||
|
@ -52,6 +52,11 @@ namespace internal {
|
|||||||
F(IsPropertyEnumerable, 2, 1) \
|
F(IsPropertyEnumerable, 2, 1) \
|
||||||
F(GetPropertyNames, 1, 1) \
|
F(GetPropertyNames, 1, 1) \
|
||||||
F(GetPropertyNamesFast, 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(GetArgumentsProperty, 1, 1) \
|
||||||
F(ToFastProperties, 1, 1) \
|
F(ToFastProperties, 1, 1) \
|
||||||
F(ToSlowProperties, 1, 1) \
|
F(ToSlowProperties, 1, 1) \
|
||||||
@ -285,14 +290,9 @@ namespace internal {
|
|||||||
F(Break, 0, 1) \
|
F(Break, 0, 1) \
|
||||||
F(DebugGetPropertyDetails, 2, 1) \
|
F(DebugGetPropertyDetails, 2, 1) \
|
||||||
F(DebugGetProperty, 2, 1) \
|
F(DebugGetProperty, 2, 1) \
|
||||||
F(DebugLocalPropertyNames, 1, 1) \
|
|
||||||
F(DebugLocalElementNames, 1, 1) \
|
|
||||||
F(DebugPropertyTypeFromDetails, 1, 1) \
|
F(DebugPropertyTypeFromDetails, 1, 1) \
|
||||||
F(DebugPropertyAttributesFromDetails, 1, 1) \
|
F(DebugPropertyAttributesFromDetails, 1, 1) \
|
||||||
F(DebugPropertyIndexFromDetails, 1, 1) \
|
F(DebugPropertyIndexFromDetails, 1, 1) \
|
||||||
F(DebugInterceptorInfo, 1, 1) \
|
|
||||||
F(DebugNamedInterceptorPropertyNames, 1, 1) \
|
|
||||||
F(DebugIndexedInterceptorElementNames, 1, 1) \
|
|
||||||
F(DebugNamedInterceptorPropertyValue, 2, 1) \
|
F(DebugNamedInterceptorPropertyValue, 2, 1) \
|
||||||
F(DebugIndexedInterceptorElementValue, 2, 1) \
|
F(DebugIndexedInterceptorElementValue, 2, 1) \
|
||||||
F(CheckExecutionState, 1, 1) \
|
F(CheckExecutionState, 1, 1) \
|
||||||
|
@ -276,7 +276,7 @@ function ObjectLookupSetter(name) {
|
|||||||
|
|
||||||
function ObjectKeys(obj) {
|
function ObjectKeys(obj) {
|
||||||
if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(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);
|
return %LocalKeys(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,23 +493,59 @@ function DefineOwnProperty(obj, p, desc, should_throw) {
|
|||||||
|
|
||||||
// ES5 section 15.2.3.2.
|
// ES5 section 15.2.3.2.
|
||||||
function ObjectGetPrototypeOf(obj) {
|
function ObjectGetPrototypeOf(obj) {
|
||||||
if (!IS_OBJECT(obj) && !IS_FUNCTION(obj)) {
|
if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
|
||||||
throw MakeTypeError("object_get_prototype_non_object", [obj]);
|
throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]);
|
||||||
}
|
return obj.__proto__;
|
||||||
return obj.__proto__;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ES5 section 15.2.3.3
|
// ES5 section 15.2.3.3
|
||||||
function ObjectGetOwnPropertyDescriptor(obj, p) {
|
function ObjectGetOwnPropertyDescriptor(obj, p) {
|
||||||
if (!IS_OBJECT(obj) && !IS_FUNCTION(obj)) {
|
if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
|
||||||
throw MakeTypeError("object_get_prototype_non_object", [obj]);
|
throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescriptor"]);
|
||||||
}
|
|
||||||
var desc = GetOwnProperty(obj, p);
|
var desc = GetOwnProperty(obj, p);
|
||||||
return FromPropertyDescriptor(desc);
|
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.
|
// ES5 section 15.2.3.5.
|
||||||
function ObjectCreate(proto, properties) {
|
function ObjectCreate(proto, properties) {
|
||||||
if (!IS_OBJECT(proto) && !IS_NULL(proto)) {
|
if (!IS_OBJECT(proto) && !IS_NULL(proto)) {
|
||||||
@ -576,7 +612,8 @@ function SetupObject() {
|
|||||||
"keys", ObjectKeys,
|
"keys", ObjectKeys,
|
||||||
"create", ObjectCreate,
|
"create", ObjectCreate,
|
||||||
"getPrototypeOf", ObjectGetPrototypeOf,
|
"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) {
|
Object.extend = function (dest, source) {
|
||||||
for (property in source) dest[property] = source[property];
|
for (property in source) dest[property] = source[property];
|
||||||
return dest;
|
return dest;
|
||||||
|
Loading…
Reference in New Issue
Block a user