Chromium Code Reviews| Index: src/debug/debug-evaluate.cc |
| diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc |
| index 65bbc3fe50e134c06c2917e0014dc1afd8a80989..c08ea58c2579097864d9e36252a4f07b57d20604 100644 |
| --- a/src/debug/debug-evaluate.cc |
| +++ b/src/debug/debug-evaluate.cc |
| @@ -271,6 +271,23 @@ void DebugEvaluate::ContextBuilder::MaterializeArgumentsObject( |
| } |
| +// Iterate the context chain until a function context of a non-arrow function. |
| +// Return whether that function context-allocates the receiver. |
| +bool HasContextAllocatedReceiver(Context* context) { |
| + DisallowHeapAllocation no_gc; |
| + while (!context->IsNativeContext() && !context->IsScriptContext()) { |
|
Michael Starzinger
2015/12/07 10:42:57
This iteration seems to walk the context chain unt
|
| + ScopeInfo* scope_info = context->closure()->shared()->scope_info(); |
| + if (scope_info->HasReceiver()) { |
| + // Normal function. If the receiver is not context-allocated, we won't be |
| + // able to find the correct receiver value. |
| + return scope_info->HasContextAllocatedReceiver(); |
| + } |
| + context = context->previous(); |
| + } |
| + return false; |
| +} |
| + |
| + |
| Handle<Context> DebugEvaluate::ContextBuilder::MaterializeReceiver( |
| Handle<Context> target, Handle<JSFunction> function) { |
| Handle<SharedFunctionInfo> shared(function->shared()); |
| @@ -278,18 +295,21 @@ Handle<Context> DebugEvaluate::ContextBuilder::MaterializeReceiver( |
| Handle<Object> receiver; |
| switch (scope_info->scope_type()) { |
| case FUNCTION_SCOPE: { |
| - VariableMode mode; |
| - InitializationFlag init_flag; |
| - MaybeAssignedFlag maybe_assigned_flag; |
| - |
| - // Don't bother creating a fake context node if "this" is in the context |
| - // already. |
| - if (ScopeInfo::ContextSlotIndex(scope_info, |
| - isolate_->factory()->this_string(), &mode, |
| - &init_flag, &maybe_assigned_flag) >= 0) { |
| - return target; |
| + // Use existing context if it already includes "this". |
| + if (scope_info->ReceiverContextSlotIndex() >= 0) return target; |
| + if (!scope_info->HasReceiver()) { |
| + // Arrow functions do not have an own receiver. It is resolved like any |
| + // other variable from outer scopes. If it's not context-allocated in |
| + // outer contexts, we cannot find its value. In that case, prevent |
| + // resolving to the incorrect "this" by defaulting to undefined. |
| + if (HasContextAllocatedReceiver(*target)) { |
| + return target; |
| + } else { |
| + receiver = isolate_->factory()->undefined_value(); |
| + } |
| + } else { |
| + receiver = handle(frame_->receiver(), isolate_); |
| } |
| - receiver = handle(frame_->receiver(), isolate_); |
| break; |
| } |
| case MODULE_SCOPE: |
| @@ -299,8 +319,7 @@ Handle<Context> DebugEvaluate::ContextBuilder::MaterializeReceiver( |
| receiver = handle(function->global_proxy(), isolate_); |
| break; |
| default: |
| - // For eval code, arrow functions, and the like, there's no "this" binding |
| - // to materialize. |
| + // For eval code, there's no "this" binding to materialize. |
| return target; |
| } |