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; |
} |