Chromium Code Reviews| Index: src/runtime.cc |
| diff --git a/src/runtime.cc b/src/runtime.cc |
| index f9b5fde7ae3035e18651f59790b68ac004dcc7ac..1ecadf5d0a4e02983cedae7070115f46f409059c 100644 |
| --- a/src/runtime.cc |
| +++ b/src/runtime.cc |
| @@ -1289,13 +1289,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { |
| // We have to declare a global const property. To capture we only |
| // assign to it when evaluating the assignment for "const x = |
| // <expr>" the initial value is the hole. |
| - bool is_const_property = value->IsTheHole(); |
| + bool is_const = value->IsTheHole(); |
| bool is_function_declaration = false; |
| - if (value->IsUndefined() || is_const_property) { |
| + if (value->IsUndefined() || is_const) { |
| // Lookup the property in the global object, and don't set the |
| // value of the variable if the property is already there. |
| + // Do the lookup locally only, see ES5 errata. |
| LookupResult lookup(isolate); |
| - global->Lookup(*name, &lookup); |
| + global->LocalLookup(*name, &lookup); |
| if (lookup.IsProperty()) { |
| // We found an existing property. Unless it was an interceptor |
| // that claims the property is absent, skip this declaration. |
| @@ -1333,46 +1334,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { |
| attr |= DONT_DELETE; |
| } |
| bool is_native = DeclareGlobalsNativeFlag::decode(flags); |
| - if (is_const_property || (is_native && is_function_declaration)) { |
| + if (is_const || (is_native && is_function_declaration)) { |
| attr |= READ_ONLY; |
| } |
| LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags); |
| - // Safari does not allow the invocation of callback setters for |
| - // function declarations. To mimic this behavior, we do not allow |
| - // the invocation of setters for function values. This makes a |
| - // difference for global functions with the same names as event |
| - // handlers such as "function onload() {}". Firefox does call the |
| - // onload setter in those case and Safari does not. We follow |
| - // Safari for compatibility. |
| - if (is_function_declaration) { |
| - if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) { |
| - // Do not overwrite READ_ONLY properties. |
| - if (lookup.GetAttributes() & READ_ONLY) { |
| - if (language_mode != CLASSIC_MODE) { |
| - Handle<Object> args[] = { name }; |
| - return isolate->Throw(*isolate->factory()->NewTypeError( |
| - "strict_cannot_assign", HandleVector(args, ARRAY_SIZE(args)))); |
| - } |
| - continue; |
| + if (!lookup.IsProperty() || is_function_declaration) { |
| + // If the local property exists, check that we can either reconfigure it |
|
Michael Starzinger
2012/04/16 11:32:30
This sentences is missing the "or" part of "either
rossberg
2012/04/16 13:15:44
Done.
|
| + // as required for function declarations. |
| + if (lookup.IsProperty() && lookup.IsDontDelete()) { |
| + if (lookup.IsReadOnly() || lookup.IsDontEnum() || |
| + lookup.type() == CALLBACKS) { |
| + return ThrowRedeclarationError(isolate, "function", name); |
| } |
| - // Do not change DONT_DELETE to false from true. |
| - attr |= lookup.GetAttributes() & DONT_DELETE; |
| + // If the existing property is not configurable, keep its attributes. |
| + attr = lookup.GetAttributes(); |
| } |
| - PropertyAttributes attributes = static_cast<PropertyAttributes>(attr); |
| - |
| - RETURN_IF_EMPTY_HANDLE( |
| - isolate, |
| - JSObject::SetLocalPropertyIgnoreAttributes(global, name, value, |
| - attributes)); |
| + // Define or redefine own property. |
| + RETURN_IF_EMPTY_HANDLE(isolate, |
| + JSObject::SetLocalPropertyIgnoreAttributes( |
| + global, name, value, static_cast<PropertyAttributes>(attr))); |
| } else { |
| - RETURN_IF_EMPTY_HANDLE( |
| - isolate, |
| - JSReceiver::SetProperty(global, name, value, |
| - static_cast<PropertyAttributes>(attr), |
| - language_mode == CLASSIC_MODE |
| - ? kNonStrictMode : kStrictMode)); |
| + // Do a [[Put]] on the existing (own) property. |
| + RETURN_IF_EMPTY_HANDLE(isolate, |
| + JSObject::SetProperty( |
| + global, name, value, static_cast<PropertyAttributes>(attr), |
| + language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode)); |
| } |
| } |
| @@ -1405,6 +1393,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { |
| if (attributes != ABSENT) { |
| // The name was declared before; check for conflicting re-declarations. |
| + // Note: this is actually inconsistent with what happens for globals (where |
| + // we silently ignore such declarations). |
| if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) { |
| // Functions are not read-only. |
| ASSERT(mode != READ_ONLY || initial_value->IsTheHole()); |
| @@ -1467,9 +1457,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { |
| return ThrowRedeclarationError(isolate, "const", name); |
| } |
| } |
| - RETURN_IF_EMPTY_HANDLE( |
| - isolate, |
| - JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode)); |
| + if (object->IsJSGlobalObject()) { |
| + // Define own property on the global object. |
| + RETURN_IF_EMPTY_HANDLE(isolate, |
| + JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode)); |
| + } else { |
| + RETURN_IF_EMPTY_HANDLE(isolate, |
| + JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode)); |
| + } |
| } |
| return isolate->heap()->undefined_value(); |
| @@ -1498,6 +1493,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { |
| // not be deletable. |
| PropertyAttributes attributes = DONT_DELETE; |
| + /*ERRATUM: no longer need to traverse the prototype chain?*/ |
|
Michael Starzinger
2012/04/16 11:32:30
This looks like a leftover, should that be a TODO?
rossberg
2012/04/16 13:15:44
Done.
|
| // Lookup the property locally in the global object. If it isn't |
| // there, there is a property with this name in the prototype chain. |
| // We follow Safari and Firefox behavior and only set the property |