| Index: src/debug/debug-scopes.cc
 | 
| diff --git a/src/debug/debug-scopes.cc b/src/debug/debug-scopes.cc
 | 
| index 4703e9c3c450ad047f4c1b4e73de6fa53270b69b..8502c483bd86613388076cfc7bac56361bda6dee 100644
 | 
| --- a/src/debug/debug-scopes.cc
 | 
| +++ b/src/debug/debug-scopes.cc
 | 
| @@ -237,7 +237,8 @@ MaybeHandle<JSObject> ScopeIterator::ScopeObject() {
 | 
|        return MaterializeLocalScope();
 | 
|      case ScopeIterator::ScopeTypeWith:
 | 
|        // Return the with object.
 | 
| -      return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
 | 
| +      // TODO(neis): This breaks for proxies.
 | 
| +      return handle(JSObject::cast(CurrentContext()->extension_receiver()));
 | 
|      case ScopeIterator::ScopeTypeCatch:
 | 
|        return MaterializeCatchScope();
 | 
|      case ScopeIterator::ScopeTypeClosure:
 | 
| @@ -295,7 +296,7 @@ Handle<ScopeInfo> ScopeIterator::CurrentScopeInfo() {
 | 
|    if (!nested_scope_chain_.is_empty()) {
 | 
|      return nested_scope_chain_.last();
 | 
|    } else if (context_->IsBlockContext()) {
 | 
| -    return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
 | 
| +    return Handle<ScopeInfo>(context_->scope_info());
 | 
|    } else if (context_->IsFunctionContext()) {
 | 
|      return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
 | 
|    }
 | 
| @@ -410,7 +411,7 @@ MaybeHandle<JSObject> ScopeIterator::MaterializeScriptScope() {
 | 
|         context_index++) {
 | 
|      Handle<Context> context =
 | 
|          ScriptContextTable::GetContext(script_contexts, context_index);
 | 
| -    Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
 | 
| +    Handle<ScopeInfo> scope_info(context->scope_info());
 | 
|      CopyContextLocalsToScopeObject(scope_info, context, script_scope);
 | 
|    }
 | 
|    return script_scope;
 | 
| @@ -438,28 +439,13 @@ MaybeHandle<JSObject> ScopeIterator::MaterializeLocalScope() {
 | 
|  
 | 
|    // Finally copy any properties from the function context extension.
 | 
|    // These will be variables introduced by eval.
 | 
| -  if (function_context->closure() == *function) {
 | 
| -    if (function_context->has_extension() &&
 | 
| -        !function_context->IsNativeContext()) {
 | 
| -      Handle<JSObject> ext(JSObject::cast(function_context->extension()));
 | 
| -      Handle<FixedArray> keys;
 | 
| -      ASSIGN_RETURN_ON_EXCEPTION(
 | 
| -          isolate_, keys, JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS),
 | 
| -          JSObject);
 | 
| -
 | 
| -      for (int i = 0; i < keys->length(); i++) {
 | 
| -        // Names of variables introduced by eval are strings.
 | 
| -        DCHECK(keys->get(i)->IsString());
 | 
| -        Handle<String> key(String::cast(keys->get(i)));
 | 
| -        Handle<Object> value;
 | 
| -        ASSIGN_RETURN_ON_EXCEPTION(
 | 
| -            isolate_, value, Object::GetPropertyOrElement(ext, key), JSObject);
 | 
| -        RETURN_ON_EXCEPTION(isolate_,
 | 
| -                            Runtime::SetObjectProperty(isolate_, local_scope,
 | 
| -                                                       key, value, SLOPPY),
 | 
| -                            JSObject);
 | 
| -      }
 | 
| -    }
 | 
| +  if (function_context->closure() == *function &&
 | 
| +      function_context->has_extension() &&
 | 
| +      !function_context->IsNativeContext()) {
 | 
| +    bool success = CopyContextExtensionToScopeObject(
 | 
| +        handle(function_context->extension_object(), isolate_),
 | 
| +        local_scope, JSReceiver::INCLUDE_PROTOS);
 | 
| +    if (!success) return MaybeHandle<JSObject>();
 | 
|    }
 | 
|  
 | 
|    return local_scope;
 | 
| @@ -486,20 +472,11 @@ Handle<JSObject> ScopeIterator::MaterializeClosure() {
 | 
|    // Finally copy any properties from the function context extension. This will
 | 
|    // be variables introduced by eval.
 | 
|    if (context->has_extension()) {
 | 
| -    Handle<JSObject> ext(JSObject::cast(context->extension()));
 | 
| -    DCHECK(ext->IsJSContextExtensionObject());
 | 
| -    Handle<FixedArray> keys =
 | 
| -        JSReceiver::GetKeys(ext, JSReceiver::OWN_ONLY).ToHandleChecked();
 | 
| -
 | 
| -    for (int i = 0; i < keys->length(); i++) {
 | 
| -      HandleScope scope(isolate_);
 | 
| -      // Names of variables introduced by eval are strings.
 | 
| -      DCHECK(keys->get(i)->IsString());
 | 
| -      Handle<String> key(String::cast(keys->get(i)));
 | 
| -      Handle<Object> value = Object::GetProperty(ext, key).ToHandleChecked();
 | 
| -      JSObject::SetOwnPropertyIgnoreAttributes(closure_scope, key, value, NONE)
 | 
| -          .Check();
 | 
| -    }
 | 
| +    bool success = CopyContextExtensionToScopeObject(
 | 
| +        handle(context->extension_object(), isolate_), closure_scope,
 | 
| +        JSReceiver::OWN_ONLY);
 | 
| +    DCHECK(success);
 | 
| +    USE(success);
 | 
|    }
 | 
|  
 | 
|    return closure_scope;
 | 
| @@ -511,7 +488,7 @@ Handle<JSObject> ScopeIterator::MaterializeClosure() {
 | 
|  Handle<JSObject> ScopeIterator::MaterializeCatchScope() {
 | 
|    Handle<Context> context = CurrentContext();
 | 
|    DCHECK(context->IsCatchContext());
 | 
| -  Handle<String> name(String::cast(context->extension()));
 | 
| +  Handle<String> name(context->catch_name());
 | 
|    Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
 | 
|                                 isolate_);
 | 
|    Handle<JSObject> catch_scope =
 | 
| @@ -539,11 +516,17 @@ Handle<JSObject> ScopeIterator::MaterializeBlockScope() {
 | 
|    }
 | 
|  
 | 
|    if (!context.is_null()) {
 | 
| -    Handle<ScopeInfo> scope_info_from_context(
 | 
| -        ScopeInfo::cast(context->extension()));
 | 
|      // Fill all context locals.
 | 
| -    CopyContextLocalsToScopeObject(scope_info_from_context, context,
 | 
| -                                   block_scope);
 | 
| +    CopyContextLocalsToScopeObject(handle(context->scope_info()),
 | 
| +                                   context, block_scope);
 | 
| +    // Fill all extension variables.
 | 
| +    if (context->extension_object() != nullptr) {
 | 
| +      bool success = CopyContextExtensionToScopeObject(
 | 
| +          handle(context->extension_object()), block_scope,
 | 
| +          JSReceiver::OWN_ONLY);
 | 
| +      DCHECK(success);
 | 
| +      USE(success);
 | 
| +    }
 | 
|    }
 | 
|    return block_scope;
 | 
|  }
 | 
| @@ -554,7 +537,7 @@ Handle<JSObject> ScopeIterator::MaterializeBlockScope() {
 | 
|  MaybeHandle<JSObject> ScopeIterator::MaterializeModuleScope() {
 | 
|    Handle<Context> context = CurrentContext();
 | 
|    DCHECK(context->IsModuleContext());
 | 
| -  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
 | 
| +  Handle<ScopeInfo> scope_info(context->scope_info());
 | 
|  
 | 
|    // Allocate and initialize a JSObject with all the members of the debugged
 | 
|    // module.
 | 
| @@ -636,7 +619,7 @@ bool ScopeIterator::SetLocalVariableValue(Handle<String> variable_name,
 | 
|      if (function_context->closure() == *function) {
 | 
|        if (function_context->has_extension() &&
 | 
|            !function_context->IsNativeContext()) {
 | 
| -        Handle<JSObject> ext(JSObject::cast(function_context->extension()));
 | 
| +        Handle<JSObject> ext(function_context->extension_object());
 | 
|  
 | 
|          Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name);
 | 
|          DCHECK(maybe.IsJust());
 | 
| @@ -670,9 +653,25 @@ bool ScopeIterator::SetBlockVariableValue(Handle<String> variable_name,
 | 
|    }
 | 
|  
 | 
|    if (HasContext()) {
 | 
| -    return SetContextLocalValue(scope_info, CurrentContext(), variable_name,
 | 
| -                                new_value);
 | 
| +    Handle<Context> context = CurrentContext();
 | 
| +    if (SetContextLocalValue(scope_info, context, variable_name, new_value)) {
 | 
| +      return true;
 | 
| +    }
 | 
| +
 | 
| +    Handle<JSObject> ext(context->extension_object(), isolate_);
 | 
| +    if (!ext.is_null()) {
 | 
| +      Maybe<bool> maybe = JSReceiver::HasOwnProperty(ext, variable_name);
 | 
| +      DCHECK(maybe.IsJust());
 | 
| +      if (maybe.FromJust()) {
 | 
| +        // We don't expect this to do anything except replacing property value.
 | 
| +        JSObject::SetOwnPropertyIgnoreAttributes(ext, variable_name, new_value,
 | 
| +                                                 NONE)
 | 
| +            .Check();
 | 
| +        return true;
 | 
| +      }
 | 
| +    }
 | 
|    }
 | 
| +
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
| @@ -693,8 +692,7 @@ bool ScopeIterator::SetClosureVariableValue(Handle<String> variable_name,
 | 
|    // Properties from the function context extension. This will
 | 
|    // be variables introduced by eval.
 | 
|    if (context->has_extension()) {
 | 
| -    Handle<JSObject> ext(JSObject::cast(context->extension()));
 | 
| -    DCHECK(ext->IsJSContextExtensionObject());
 | 
| +    Handle<JSObject> ext(JSObject::cast(context->extension_object()));
 | 
|      Maybe<bool> maybe = JSReceiver::HasOwnProperty(ext, variable_name);
 | 
|      DCHECK(maybe.IsJust());
 | 
|      if (maybe.FromJust()) {
 | 
| @@ -732,7 +730,7 @@ bool ScopeIterator::SetCatchVariableValue(Handle<String> variable_name,
 | 
|                                            Handle<Object> new_value) {
 | 
|    Handle<Context> context = CurrentContext();
 | 
|    DCHECK(context->IsCatchContext());
 | 
| -  Handle<String> name(String::cast(context->extension()));
 | 
| +  Handle<String> name(context->catch_name());
 | 
|    if (!String::Equals(name, variable_name)) {
 | 
|      return false;
 | 
|    }
 | 
| @@ -765,5 +763,27 @@ void ScopeIterator::CopyContextLocalsToScopeObject(
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +
 | 
| +bool ScopeIterator::CopyContextExtensionToScopeObject(
 | 
| +    Handle<JSObject> extension, Handle<JSObject> scope_object,
 | 
| +    JSReceiver::KeyCollectionType type) {
 | 
| +  Handle<FixedArray> keys;
 | 
| +  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
 | 
| +      isolate_, keys, JSReceiver::GetKeys(extension, type), false);
 | 
| +
 | 
| +  for (int i = 0; i < keys->length(); i++) {
 | 
| +    // Names of variables introduced by eval are strings.
 | 
| +    DCHECK(keys->get(i)->IsString());
 | 
| +    Handle<String> key(String::cast(keys->get(i)));
 | 
| +    Handle<Object> value;
 | 
| +    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
 | 
| +        isolate_, value, Object::GetPropertyOrElement(extension, key), false);
 | 
| +    RETURN_ON_EXCEPTION_VALUE(
 | 
| +        isolate_, JSObject::SetOwnPropertyIgnoreAttributes(
 | 
| +            scope_object, key, value, NONE), false);
 | 
| +  }
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
|  }  // namespace internal
 | 
|  }  // namespace v8
 | 
| 
 |