| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 48ff69f5d273071e0615743e2b2760f2abb71e70..a6670bf718795e7069b5198fa8b0493614fa3846 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -1051,6 +1051,12 @@ static MaybeObject* Runtime_DeclareGlobals(Arguments args) {
|
| // Fall-through and introduce the absent property by using
|
| // SetProperty.
|
| } else {
|
| + // For const properties, we treat a callback with this name
|
| + // even in the prototype as a conflicting declaration.
|
| + if (is_const_property && (lookup.type() == CALLBACKS)) {
|
| + return ThrowRedeclarationError("const", name);
|
| + }
|
| + // Otherwise, we check for locally conflicting declarations.
|
| if (is_local && (is_read_only || is_const_property)) {
|
| const char* type = (is_read_only) ? "const" : "var";
|
| return ThrowRedeclarationError(type, name);
|
| @@ -1076,30 +1082,20 @@ static MaybeObject* Runtime_DeclareGlobals(Arguments args) {
|
| ? static_cast<PropertyAttributes>(base | READ_ONLY)
|
| : base;
|
|
|
| - if (lookup.IsProperty()) {
|
| - // There's a local property that we need to overwrite because
|
| - // we're either declaring a function or there's an interceptor
|
| - // that claims the property is absent.
|
| -
|
| - // Check for conflicting re-declarations. We cannot have
|
| - // conflicting types in case of intercepted properties because
|
| - // they are absent.
|
| - if (lookup.type() != INTERCEPTOR &&
|
| - (lookup.IsReadOnly() || is_const_property)) {
|
| - const char* type = (lookup.IsReadOnly()) ? "const" : "var";
|
| - return ThrowRedeclarationError(type, name);
|
| - }
|
| - RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes));
|
| - } else {
|
| - // If a property with this name does not already exist on the
|
| - // global object add the property locally. We take special
|
| - // precautions to always add it as a local property even in case
|
| - // of callbacks in the prototype chain (this rules out using
|
| - // SetProperty). Also, we must use the handle-based version to
|
| - // avoid GC issues.
|
| - RETURN_IF_EMPTY_HANDLE(
|
| - SetLocalPropertyIgnoreAttributes(global, name, value, attributes));
|
| + // There's a local property that we need to overwrite because
|
| + // we're either declaring a function or there's an interceptor
|
| + // that claims the property is absent.
|
| + //
|
| + // Check for conflicting re-declarations. We cannot have
|
| + // conflicting types in case of intercepted properties because
|
| + // they are absent.
|
| + if (lookup.IsProperty() &&
|
| + (lookup.type() != INTERCEPTOR) &&
|
| + (lookup.IsReadOnly() || is_const_property)) {
|
| + const char* type = (lookup.IsReadOnly()) ? "const" : "var";
|
| + return ThrowRedeclarationError(type, name);
|
| }
|
| + RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes));
|
| }
|
|
|
| ASSERT(!Top::has_pending_exception());
|
| @@ -1186,6 +1182,20 @@ static MaybeObject* Runtime_DeclareContextSlot(Arguments args) {
|
| ASSERT(!context_ext->HasLocalProperty(*name));
|
| Handle<Object> value(Heap::undefined_value());
|
| if (*initial_value != NULL) value = initial_value;
|
| + // Declaring a const context slot is a conflicting declaration if
|
| + // there is a callback with that name in a prototype. It is
|
| + // allowed to introduce const variables in
|
| + // JSContextExtensionObjects. They are treated specially in
|
| + // SetProperty and no setters are invoked for those since they are
|
| + // not real JSObjects.
|
| + if (initial_value->IsTheHole() &&
|
| + !context_ext->IsJSContextExtensionObject()) {
|
| + LookupResult lookup;
|
| + context_ext->Lookup(*name, &lookup);
|
| + if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) {
|
| + return ThrowRedeclarationError("const", name);
|
| + }
|
| + }
|
| RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode));
|
| }
|
|
|
| @@ -1212,11 +1222,7 @@ static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) {
|
| // there, there is a property with this name in the prototype chain.
|
| // We follow Safari and Firefox behavior and only set the property
|
| // locally if there is an explicit initialization value that we have
|
| - // to assign to the property. When adding the property we take
|
| - // special precautions to always add it as a local property even in
|
| - // case of callbacks in the prototype chain (this rules out using
|
| - // SetProperty). We have SetLocalPropertyIgnoreAttributes for
|
| - // this.
|
| + // to assign to the property.
|
| // 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;
|
| @@ -1277,11 +1283,7 @@ static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) {
|
| }
|
|
|
| global = Top::context()->global();
|
| - if (assign) {
|
| - return global->SetLocalPropertyIgnoreAttributes(*name,
|
| - args[1],
|
| - attributes);
|
| - }
|
| + if (assign) return global->SetProperty(*name, args[1], attributes);
|
| return Heap::undefined_value();
|
| }
|
|
|
|
|