| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 1116)
|
| +++ src/runtime.cc (working copy)
|
| @@ -4536,6 +4536,21 @@
|
| }
|
|
|
|
|
| +// 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, LookupResult* result,
|
| bool* caught_exception) {
|
| Object* value;
|
| @@ -4611,6 +4626,13 @@
|
| CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
| CONVERT_ARG_CHECKED(String, name, 1);
|
|
|
| + // 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()));
|
| + }
|
| +
|
| +
|
| // Check if the name is trivially convertible to an index and get the element
|
| // if so.
|
| uint32_t index;
|
| @@ -4621,9 +4643,22 @@
|
| return *Factory::NewJSArrayWithElements(details);
|
| }
|
|
|
| - // Perform standard local lookup on the object.
|
| + // Find the number of objects making up this.
|
| + int length = LocalPrototypeChainLength(*obj);
|
| +
|
| + // Try local lookup on each of the objects.
|
| LookupResult result;
|
| - obj->LocalLookup(*name, &result);
|
| + Handle<JSObject> jsproto = obj;
|
| + for (int i = 0; i < length; i++) {
|
| + jsproto->LocalLookup(*name, &result);
|
| + if (result.IsProperty()) {
|
| + break;
|
| + }
|
| + if (i < length - 1) {
|
| + jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
| + }
|
| + }
|
| +
|
| if (result.IsProperty()) {
|
| bool caught_exception = false;
|
| Handle<Object> value(DebugLookupResultValue(*obj, &result,
|
| @@ -4676,12 +4711,43 @@
|
| }
|
| 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()));
|
| }
|
| - int n = obj->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
|
| - Handle<FixedArray> names = Factory::NewFixedArray(n);
|
| - obj->GetLocalPropertyNames(*names);
|
| +
|
| + // 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;
|
| + for (int i = 0; i < length; i++) {
|
| + jsproto->GetLocalPropertyNames(*names,
|
| + i == 0 ? 0 : local_property_count[i - 1]);
|
| + if (i < length - 1) {
|
| + jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
| + }
|
| + }
|
| +
|
| + DeleteArray(local_property_count);
|
| return *Factory::NewJSArrayWithElements(names);
|
| }
|
|
|
| @@ -5809,12 +5875,15 @@
|
| }
|
|
|
|
|
| -static Object* Runtime_GetPrototype(Arguments args) {
|
| +// Find the effective prototype object as returned by __proto__.
|
| +// args[0]: the object to find the prototype for.
|
| +static Object* Runtime_DebugGetPrototype(Arguments args) {
|
| ASSERT(args.length() == 1);
|
|
|
| CONVERT_CHECKED(JSObject, obj, args[0]);
|
|
|
| - return obj->GetPrototype();
|
| + // Use the __proto__ accessor.
|
| + return Accessors::ObjectPrototype.getter(obj, NULL);
|
| }
|
|
|
|
|
|
|