| Index: src/debug/debug-evaluate.cc
|
| diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc
|
| index 9d0d38446e0a6cd27ec9bca7e614544c4026b30b..e19b93eebea0174e85ae44adb4e2c011589b6405 100644
|
| --- a/src/debug/debug-evaluate.cc
|
| +++ b/src/debug/debug-evaluate.cc
|
| @@ -68,16 +68,19 @@ MaybeHandle<Object> DebugEvaluate::Local(Isolate* isolate,
|
| // variables accessible by the function we are evaluating from are
|
| // materialized and included on top of the native context. Changes to
|
| // the materialized object are written back afterwards.
|
| + // Note that the native context is taken from the original context chain,
|
| + // which may not be the current native context of the isolate.
|
| ContextBuilder context_builder(isolate, frame, inlined_jsframe_index);
|
| if (isolate->has_pending_exception()) return MaybeHandle<Object>();
|
|
|
| - Handle<Context> context = isolate->native_context();
|
| + Handle<Context> context = context_builder.native_context();
|
| Handle<JSObject> receiver(context->global_proxy());
|
| - Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
|
| MaybeHandle<Object> maybe_result = Evaluate(
|
| isolate, context_builder.outer_info(),
|
| context_builder.innermost_context(), context_extension, receiver, source);
|
| - if (!maybe_result.is_null()) context_builder.UpdateValues();
|
| + if (!maybe_result.is_null() && !FLAG_debug_eval_readonly_locals) {
|
| + context_builder.UpdateValues();
|
| + }
|
| return maybe_result;
|
| }
|
|
|
| @@ -127,8 +130,8 @@ DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate,
|
| Handle<JSFunction> local_function =
|
| handle(JSFunction::cast(frame_inspector.GetFunction()));
|
| Handle<Context> outer_context(local_function->context());
|
| - Handle<Context> native_context = isolate->native_context();
|
| - Handle<JSFunction> global_function(native_context->closure());
|
| + native_context_ = Handle<Context>(outer_context->native_context());
|
| + Handle<JSFunction> global_function(native_context_->closure());
|
| outer_info_ = handle(global_function->shared());
|
| Handle<Context> inner_context;
|
|
|
| @@ -166,7 +169,7 @@ DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate,
|
| // The "this" binding, if any, can't be bound via "with". If we need
|
| // to, add another node onto the outer context to bind "this".
|
| Handle<Context> receiver_context =
|
| - MaterializeReceiver(native_context, local_context, local_function,
|
| + MaterializeReceiver(native_context_, local_context, local_function,
|
| global_function, it.ThisIsNonLocal());
|
|
|
| Handle<JSObject> materialized_function = NewJSObjectWithNullProto();
|
| @@ -309,7 +312,7 @@ void DebugEvaluate::ContextBuilder::MaterializeArgumentsObject(
|
|
|
|
|
| MaybeHandle<Object> DebugEvaluate::ContextBuilder::LoadFromContext(
|
| - Handle<Context> context, Handle<String> name) {
|
| + Handle<Context> context, Handle<String> name, bool* global) {
|
| static const ContextLookupFlags flags = FOLLOW_CONTEXT_CHAIN;
|
| int index;
|
| PropertyAttributes attributes;
|
| @@ -320,9 +323,13 @@ MaybeHandle<Object> DebugEvaluate::ContextBuilder::LoadFromContext(
|
| Handle<Object> value;
|
| if (index != Context::kNotFound) { // Found on context.
|
| Handle<Context> context = Handle<Context>::cast(holder);
|
| + // Do not shadow variables on the script context.
|
| + *global = context->IsScriptContext();
|
| return Handle<Object>(context->get(index), isolate_);
|
| } else { // Found on object.
|
| Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
|
| + // Do not shadow properties on the global object.
|
| + *global = object->IsJSGlobalObject();
|
| return JSReceiver::GetDataProperty(object, name);
|
| }
|
| }
|
| @@ -333,7 +340,13 @@ void DebugEvaluate::ContextBuilder::MaterializeContextChain(
|
| for (const Handle<String>& name : non_locals_) {
|
| HandleScope scope(isolate_);
|
| Handle<Object> value;
|
| - if (!LoadFromContext(context, name).ToHandle(&value)) continue;
|
| + bool global;
|
| + if (!LoadFromContext(context, name, &global).ToHandle(&value) || global) {
|
| + // If resolving the variable fails, skip it. If it resolves to a global
|
| + // variable, skip it as well since it's not read-only and can be resolved
|
| + // within debug-evaluate.
|
| + continue;
|
| + }
|
| JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
|
| }
|
| }
|
| @@ -381,7 +394,8 @@ Handle<Context> DebugEvaluate::ContextBuilder::MaterializeReceiver(
|
| Handle<Object> receiver = isolate_->factory()->undefined_value();
|
| Handle<String> this_string = isolate_->factory()->this_string();
|
| if (this_is_non_local) {
|
| - LoadFromContext(lookup_context, this_string).ToHandle(&receiver);
|
| + bool global;
|
| + LoadFromContext(lookup_context, this_string, &global).ToHandle(&receiver);
|
| } else if (local_function->shared()->scope_info()->HasReceiver()) {
|
| receiver = handle(frame_->receiver(), isolate_);
|
| }
|
|
|