Revision: 3362 Author: [email protected] Date: Wed Nov 25 07:45:37 2009 Log: When processing global vars initialization account for the case of splitted global object (using hidden prototypes):
1) setters might be not on the global object itself, but on its prototypes; 2) if property on one of prototypes is readonly, we could shadow it. Review URL: http://codereview.chromium.org/434035 http://code.google.com/p/v8/source/detail?r=3362 Modified: /branches/bleeding_edge/src/runtime.cc ======================================= --- /branches/bleeding_edge/src/runtime.cc Tue Nov 24 06:45:27 2009 +++ /branches/bleeding_edge/src/runtime.cc Wed Nov 25 07:45:37 2009 @@ -788,51 +788,72 @@ // case of callbacks in the prototype chain (this rules out using // SetProperty). We have IgnoreAttributesAndSetLocalProperty for // this. + // Note that objects can have hidden prototypes, so we need to traverse + // the whole chain of hidden prototypes to do a 'local' lookup. + JSObject* real_holder = global; LookupResult lookup; - global->LocalLookup(*name, &lookup); - if (!lookup.IsProperty()) { - if (assign) { - return global->IgnoreAttributesAndSetLocalProperty(*name, - args[1], - attributes); - } - return Heap::undefined_value(); - } - - // Determine if this is a redeclaration of something read-only. - if (lookup.IsReadOnly()) { - return ThrowRedeclarationError("const", name); - } - - // Determine if this is a redeclaration of an intercepted read-only - // property and figure out if the property exists at all. - bool found = true; - PropertyType type = lookup.type(); - if (type == INTERCEPTOR) { - PropertyAttributes intercepted = global->GetPropertyAttribute(*name); - if (intercepted == ABSENT) { - // The interceptor claims the property isn't there. We need to - // make sure to introduce it. - found = false; - } else if ((intercepted & READ_ONLY) != 0) { - // The property is present, but read-only. Since we're trying to - // overwrite it with a variable declaration we must throw a - // re-declaration error. - return ThrowRedeclarationError("const", name); - } - // Restore global object from context (in case of GC). - global = Top::context()->global(); - } - - if (found && !assign) { - // The global property is there and we're not assigning any value - // to it. Just return. - return Heap::undefined_value(); + while (true) { + real_holder->LocalLookup(*name, &lookup); + if (lookup.IsProperty()) { + // Determine if this is a redeclaration of something read-only. + if (lookup.IsReadOnly()) { + // If we found readonly property on one of hidden prototypes, + // just shadow it. + if (real_holder != Top::context()->global()) break; + return ThrowRedeclarationError("const", name); + } + + // Determine if this is a redeclaration of an intercepted read-only + // property and figure out if the property exists at all. + bool found = true; + PropertyType type = lookup.type(); + if (type == INTERCEPTOR) { + HandleScope handle_scope; + Handle<JSObject> holder(real_holder); + PropertyAttributes intercepted = holder->GetPropertyAttribute(*name); + real_holder = *holder; + if (intercepted == ABSENT) { + // The interceptor claims the property isn't there. We need to + // make sure to introduce it. + found = false; + } else if ((intercepted & READ_ONLY) != 0) { + // The property is present, but read-only. Since we're trying to + // overwrite it with a variable declaration we must throw a + // re-declaration error. However if we found readonly property + // on one of hidden prototypes, just shadow it. + if (real_holder != Top::context()->global()) break; + return ThrowRedeclarationError("const", name); + } + } + + if (found && !assign) { + // The global property is there and we're not assigning any value + // to it. Just return. + return Heap::undefined_value(); + } + + // Assign the value (or undefined) to the property. + Object* value = (assign) ? args[1] : Heap::undefined_value(); + return real_holder->SetProperty(&lookup, *name, value, attributes); + } + + Object* proto = real_holder->GetPrototype(); + if (!proto->IsJSObject()) + break; + + if (!JSObject::cast(proto)->map()->is_hidden_prototype()) + break; + + real_holder = JSObject::cast(proto); } - // Assign the value (or undefined) to the property. - Object* value = (assign) ? args[1] : Heap::undefined_value(); - return global->SetProperty(&lookup, *name, value, attributes); + global = Top::context()->global(); + if (assign) { + return global->IgnoreAttributesAndSetLocalProperty(*name, + args[1], + attributes); + } + return Heap::undefined_value(); } --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
