| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/debug/debug-evaluate.h" | 5 #include "src/debug/debug-evaluate.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/contexts.h" | 8 #include "src/contexts.h" |
| 9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
| 10 #include "src/debug/debug-frames.h" | 10 #include "src/debug/debug-frames.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 | 66 |
| 67 // This is not a lot different than DebugEvaluate::Global, except that | 67 // This is not a lot different than DebugEvaluate::Global, except that |
| 68 // variables accessible by the function we are evaluating from are | 68 // variables accessible by the function we are evaluating from are |
| 69 // materialized and included on top of the native context. Changes to | 69 // materialized and included on top of the native context. Changes to |
| 70 // the materialized object are written back afterwards. | 70 // the materialized object are written back afterwards. |
| 71 // Note that the native context is taken from the original context chain, | 71 // Note that the native context is taken from the original context chain, |
| 72 // which may not be the current native context of the isolate. | 72 // which may not be the current native context of the isolate. |
| 73 ContextBuilder context_builder(isolate, frame, inlined_jsframe_index); | 73 ContextBuilder context_builder(isolate, frame, inlined_jsframe_index); |
| 74 if (isolate->has_pending_exception()) return MaybeHandle<Object>(); | 74 if (isolate->has_pending_exception()) return MaybeHandle<Object>(); |
| 75 | 75 |
| 76 Handle<Context> context = context_builder.native_context(); | 76 Handle<Context> context = context_builder.evaluation_context(); |
| 77 Handle<JSObject> receiver(context->global_proxy()); | 77 Handle<JSObject> receiver(context->global_proxy()); |
| 78 MaybeHandle<Object> maybe_result = Evaluate( | 78 MaybeHandle<Object> maybe_result = |
| 79 isolate, context_builder.outer_info(), | 79 Evaluate(isolate, context_builder.outer_info(), context, |
| 80 context_builder.innermost_context(), context_extension, receiver, source); | 80 context_extension, receiver, source); |
| 81 if (!maybe_result.is_null() && !FLAG_debug_eval_readonly_locals) { | 81 if (!maybe_result.is_null()) context_builder.UpdateValues(); |
| 82 context_builder.UpdateValues(); | |
| 83 } | |
| 84 return maybe_result; | 82 return maybe_result; |
| 85 } | 83 } |
| 86 | 84 |
| 87 | 85 |
| 88 // Compile and evaluate source for the given context. | 86 // Compile and evaluate source for the given context. |
| 89 MaybeHandle<Object> DebugEvaluate::Evaluate( | 87 MaybeHandle<Object> DebugEvaluate::Evaluate( |
| 90 Isolate* isolate, Handle<SharedFunctionInfo> outer_info, | 88 Isolate* isolate, Handle<SharedFunctionInfo> outer_info, |
| 91 Handle<Context> context, Handle<HeapObject> context_extension, | 89 Handle<Context> context, Handle<HeapObject> context_extension, |
| 92 Handle<Object> receiver, Handle<String> source) { | 90 Handle<Object> receiver, Handle<String> source) { |
| 93 if (context_extension->IsJSObject()) { | 91 if (context_extension->IsJSObject()) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 123 DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate, | 121 DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate, |
| 124 JavaScriptFrame* frame, | 122 JavaScriptFrame* frame, |
| 125 int inlined_jsframe_index) | 123 int inlined_jsframe_index) |
| 126 : isolate_(isolate), | 124 : isolate_(isolate), |
| 127 frame_(frame), | 125 frame_(frame), |
| 128 inlined_jsframe_index_(inlined_jsframe_index) { | 126 inlined_jsframe_index_(inlined_jsframe_index) { |
| 129 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); | 127 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); |
| 130 Handle<JSFunction> local_function = | 128 Handle<JSFunction> local_function = |
| 131 Handle<JSFunction>::cast(frame_inspector.GetFunction()); | 129 Handle<JSFunction>::cast(frame_inspector.GetFunction()); |
| 132 Handle<Context> outer_context(local_function->context()); | 130 Handle<Context> outer_context(local_function->context()); |
| 133 native_context_ = Handle<Context>(outer_context->native_context()); | 131 evaluation_context_ = outer_context; |
| 134 Handle<JSFunction> global_function(native_context_->closure()); | 132 outer_info_ = handle(local_function->shared()); |
| 135 outer_info_ = handle(global_function->shared()); | 133 Factory* factory = isolate->factory(); |
| 136 Handle<Context> inner_context; | |
| 137 | 134 |
| 138 bool stop = false; | 135 // To evaluate as if we were running eval at the point of the debug break, |
| 139 | 136 // we reconstruct the context chain as follows: |
| 140 // Iterate the original context chain to create a context chain that reflects | 137 // - To make stack-allocated variables visible, we materialize them and |
| 141 // our needs. The original context chain may look like this: | 138 // use a debug-evaluate context to wrap both the materialized object and |
| 142 // <native context> <outer contexts> <function context> <inner contexts> | 139 // the original context. |
| 143 // In the resulting context chain, we want to materialize the receiver, | 140 // - We use the original context chain from the function context to the |
| 144 // the parameters of the current function, the stack locals. We only | 141 // native context. |
| 145 // materialize context variables that the function already references, | 142 // - Between the function scope and the native context, we only resolve |
| 146 // because only for those variables we can be sure that they will be resolved | 143 // variable names that the current function already uses. Only for these |
| 147 // correctly. Variables that are not referenced by the function may be | 144 // names we can be sure that they will be correctly resolved. For the |
| 148 // context-allocated and thus accessible, but may be shadowed by stack- | 145 // rest, we only resolve to with, script, and native contexts. We use a |
| 149 // allocated variables and the resolution would be incorrect. | 146 // whitelist to implement that. |
| 150 // The result will look like this: | 147 // Context::Lookup has special handling for debug-evaluate contexts: |
| 151 // <native context> <receiver context> | 148 // - Look up in the materialized stack variables. |
| 152 // <materialized stack and accessible context vars> <inner contexts> | 149 // - Look up in the original context. |
| 153 // All contexts use the closure of the native context, since there is no | 150 // - Check the whitelist to find out whether to skip contexts during lookup. |
| 154 // function context in the chain. Variables that cannot be resolved are | |
| 155 // bound to toplevel (script contexts or global object). | |
| 156 // Once debug-evaluate has been executed, the changes to the materialized | |
| 157 // objects are written back to the original context chain. Any changes to | |
| 158 // the original context chain will therefore be overwritten. | |
| 159 const ScopeIterator::Option option = ScopeIterator::COLLECT_NON_LOCALS; | 151 const ScopeIterator::Option option = ScopeIterator::COLLECT_NON_LOCALS; |
| 160 for (ScopeIterator it(isolate, &frame_inspector, option); | 152 for (ScopeIterator it(isolate, &frame_inspector, option); |
| 161 !it.Failed() && !it.Done() && !stop; it.Next()) { | 153 !it.Failed() && !it.Done(); it.Next()) { |
| 162 ScopeIterator::ScopeType scope_type = it.Type(); | 154 ScopeIterator::ScopeType scope_type = it.Type(); |
| 163 if (scope_type == ScopeIterator::ScopeTypeLocal) { | 155 if (scope_type == ScopeIterator::ScopeTypeLocal) { |
| 164 DCHECK_EQ(FUNCTION_SCOPE, it.CurrentScopeInfo()->scope_type()); | 156 DCHECK_EQ(FUNCTION_SCOPE, it.CurrentScopeInfo()->scope_type()); |
| 165 it.GetNonLocals(&non_locals_); | 157 Handle<JSObject> materialized = NewJSObjectWithNullProto(); |
| 166 Handle<Context> local_context = | 158 Handle<Context> local_context = |
| 167 it.HasContext() ? it.CurrentContext() : outer_context; | 159 it.HasContext() ? it.CurrentContext() : outer_context; |
| 168 | 160 Handle<StringSet> non_locals = it.GetNonLocals(); |
| 169 // The "this" binding, if any, can't be bound via "with". If we need | 161 MaterializeReceiver(materialized, local_context, local_function, |
| 170 // to, add another node onto the outer context to bind "this". | 162 non_locals); |
| 171 Handle<Context> receiver_context = | 163 frame_inspector.MaterializeStackLocals(materialized, local_function); |
| 172 MaterializeReceiver(native_context_, local_context, local_function, | 164 MaterializeArgumentsObject(materialized, local_function); |
| 173 global_function, it.ThisIsNonLocal()); | |
| 174 | |
| 175 Handle<JSObject> materialized_function = NewJSObjectWithNullProto(); | |
| 176 frame_inspector.MaterializeStackLocals(materialized_function, | |
| 177 local_function); | |
| 178 MaterializeArgumentsObject(materialized_function, local_function); | |
| 179 MaterializeContextChain(materialized_function, local_context); | |
| 180 | |
| 181 Handle<Context> with_context = isolate->factory()->NewWithContext( | |
| 182 global_function, receiver_context, materialized_function); | |
| 183 | |
| 184 ContextChainElement context_chain_element; | 165 ContextChainElement context_chain_element; |
| 185 context_chain_element.original_context = local_context; | |
| 186 context_chain_element.materialized_object = materialized_function; | |
| 187 context_chain_element.scope_info = it.CurrentScopeInfo(); | 166 context_chain_element.scope_info = it.CurrentScopeInfo(); |
| 167 context_chain_element.materialized_object = materialized; |
| 168 // Non-locals that are already being referenced by the current function |
| 169 // are guaranteed to be correctly resolved. |
| 170 context_chain_element.whitelist = non_locals; |
| 171 if (it.HasContext()) { |
| 172 context_chain_element.wrapped_context = it.CurrentContext(); |
| 173 } |
| 188 context_chain_.Add(context_chain_element); | 174 context_chain_.Add(context_chain_element); |
| 189 | 175 evaluation_context_ = outer_context; |
| 190 stop = true; | 176 break; |
| 191 RecordContextsInChain(&inner_context, receiver_context, with_context); | |
| 192 } else if (scope_type == ScopeIterator::ScopeTypeCatch || | 177 } else if (scope_type == ScopeIterator::ScopeTypeCatch || |
| 193 scope_type == ScopeIterator::ScopeTypeWith) { | 178 scope_type == ScopeIterator::ScopeTypeWith) { |
| 194 Handle<Context> cloned_context = Handle<Context>::cast( | |
| 195 isolate->factory()->CopyFixedArray(it.CurrentContext())); | |
| 196 | |
| 197 ContextChainElement context_chain_element; | 179 ContextChainElement context_chain_element; |
| 198 context_chain_element.original_context = it.CurrentContext(); | 180 Handle<Context> current_context = it.CurrentContext(); |
| 199 context_chain_element.cloned_context = cloned_context; | 181 if (!current_context->IsDebugEvaluateContext()) { |
| 182 context_chain_element.wrapped_context = current_context; |
| 183 } |
| 200 context_chain_.Add(context_chain_element); | 184 context_chain_.Add(context_chain_element); |
| 201 | |
| 202 RecordContextsInChain(&inner_context, cloned_context, cloned_context); | |
| 203 } else if (scope_type == ScopeIterator::ScopeTypeBlock) { | 185 } else if (scope_type == ScopeIterator::ScopeTypeBlock) { |
| 204 Handle<JSObject> materialized_object = NewJSObjectWithNullProto(); | 186 Handle<JSObject> materialized = NewJSObjectWithNullProto(); |
| 205 frame_inspector.MaterializeStackLocals(materialized_object, | 187 frame_inspector.MaterializeStackLocals(materialized, |
| 206 it.CurrentScopeInfo()); | 188 it.CurrentScopeInfo()); |
| 189 ContextChainElement context_chain_element; |
| 190 context_chain_element.scope_info = it.CurrentScopeInfo(); |
| 191 context_chain_element.materialized_object = materialized; |
| 207 if (it.HasContext()) { | 192 if (it.HasContext()) { |
| 208 Handle<Context> cloned_context = Handle<Context>::cast( | 193 context_chain_element.wrapped_context = it.CurrentContext(); |
| 209 isolate->factory()->CopyFixedArray(it.CurrentContext())); | |
| 210 Handle<Context> with_context = isolate->factory()->NewWithContext( | |
| 211 global_function, cloned_context, materialized_object); | |
| 212 | |
| 213 ContextChainElement context_chain_element; | |
| 214 context_chain_element.original_context = it.CurrentContext(); | |
| 215 context_chain_element.cloned_context = cloned_context; | |
| 216 context_chain_element.materialized_object = materialized_object; | |
| 217 context_chain_element.scope_info = it.CurrentScopeInfo(); | |
| 218 context_chain_.Add(context_chain_element); | |
| 219 | |
| 220 RecordContextsInChain(&inner_context, cloned_context, with_context); | |
| 221 } else { | |
| 222 Handle<Context> with_context = isolate->factory()->NewWithContext( | |
| 223 global_function, outer_context, materialized_object); | |
| 224 | |
| 225 ContextChainElement context_chain_element; | |
| 226 context_chain_element.materialized_object = materialized_object; | |
| 227 context_chain_element.scope_info = it.CurrentScopeInfo(); | |
| 228 context_chain_.Add(context_chain_element); | |
| 229 | |
| 230 RecordContextsInChain(&inner_context, with_context, with_context); | |
| 231 } | 194 } |
| 195 context_chain_.Add(context_chain_element); |
| 232 } else { | 196 } else { |
| 233 stop = true; | 197 break; |
| 234 } | 198 } |
| 235 } | 199 } |
| 236 if (innermost_context_.is_null()) { | 200 |
| 237 innermost_context_ = outer_context; | 201 for (int i = context_chain_.length() - 1; i >= 0; i--) { |
| 202 evaluation_context_ = factory->NewDebugEvaluateContext( |
| 203 evaluation_context_, context_chain_[i].materialized_object, |
| 204 context_chain_[i].wrapped_context, context_chain_[i].whitelist); |
| 238 } | 205 } |
| 239 DCHECK(!innermost_context_.is_null()); | |
| 240 } | 206 } |
| 241 | 207 |
| 242 | 208 |
| 243 void DebugEvaluate::ContextBuilder::UpdateValues() { | 209 void DebugEvaluate::ContextBuilder::UpdateValues() { |
| 244 // TODO(yangguo): remove updating values. | 210 // TODO(yangguo): remove updating values. |
| 245 for (int i = 0; i < context_chain_.length(); i++) { | 211 for (int i = 0; i < context_chain_.length(); i++) { |
| 246 ContextChainElement element = context_chain_[i]; | 212 ContextChainElement element = context_chain_[i]; |
| 247 if (!element.original_context.is_null() && | |
| 248 !element.cloned_context.is_null()) { | |
| 249 Handle<Context> cloned_context = element.cloned_context; | |
| 250 cloned_context->CopyTo( | |
| 251 Context::MIN_CONTEXT_SLOTS, *element.original_context, | |
| 252 Context::MIN_CONTEXT_SLOTS, | |
| 253 cloned_context->length() - Context::MIN_CONTEXT_SLOTS); | |
| 254 } | |
| 255 if (!element.materialized_object.is_null()) { | 213 if (!element.materialized_object.is_null()) { |
| 256 // Write back potential changes to materialized stack locals to the | 214 // Write back potential changes to materialized stack locals to the stack. |
| 257 // stack. | |
| 258 FrameInspector(frame_, inlined_jsframe_index_, isolate_) | 215 FrameInspector(frame_, inlined_jsframe_index_, isolate_) |
| 259 .UpdateStackLocalsFromMaterializedObject(element.materialized_object, | 216 .UpdateStackLocalsFromMaterializedObject(element.materialized_object, |
| 260 element.scope_info); | 217 element.scope_info); |
| 261 if (element.scope_info->scope_type() == FUNCTION_SCOPE) { | |
| 262 DCHECK_EQ(context_chain_.length() - 1, i); | |
| 263 UpdateContextChainFromMaterializedObject(element.materialized_object, | |
| 264 element.original_context); | |
| 265 } | |
| 266 } | 218 } |
| 267 } | 219 } |
| 268 } | 220 } |
| 269 | 221 |
| 270 | 222 |
| 271 Handle<JSObject> DebugEvaluate::ContextBuilder::NewJSObjectWithNullProto() { | 223 Handle<JSObject> DebugEvaluate::ContextBuilder::NewJSObjectWithNullProto() { |
| 272 Handle<JSObject> result = | 224 Handle<JSObject> result = |
| 273 isolate_->factory()->NewJSObject(isolate_->object_function()); | 225 isolate_->factory()->NewJSObject(isolate_->object_function()); |
| 274 Handle<Map> new_map = | 226 Handle<Map> new_map = |
| 275 Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto"); | 227 Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto"); |
| 276 Map::SetPrototype(new_map, isolate_->factory()->null_value()); | 228 Map::SetPrototype(new_map, isolate_->factory()->null_value()); |
| 277 JSObject::MigrateToMap(result, new_map); | 229 JSObject::MigrateToMap(result, new_map); |
| 278 return result; | 230 return result; |
| 279 } | 231 } |
| 280 | 232 |
| 281 | 233 |
| 282 void DebugEvaluate::ContextBuilder::RecordContextsInChain( | |
| 283 Handle<Context>* inner_context, Handle<Context> first, | |
| 284 Handle<Context> last) { | |
| 285 if (!inner_context->is_null()) { | |
| 286 (*inner_context)->set_previous(*last); | |
| 287 } else { | |
| 288 innermost_context_ = last; | |
| 289 } | |
| 290 *inner_context = first; | |
| 291 } | |
| 292 | |
| 293 | |
| 294 void DebugEvaluate::ContextBuilder::MaterializeArgumentsObject( | 234 void DebugEvaluate::ContextBuilder::MaterializeArgumentsObject( |
| 295 Handle<JSObject> target, Handle<JSFunction> function) { | 235 Handle<JSObject> target, Handle<JSFunction> function) { |
| 296 // Do not materialize the arguments object for eval or top-level code. | 236 // Do not materialize the arguments object for eval or top-level code. |
| 297 // Skip if "arguments" is already taken. | 237 // Skip if "arguments" is already taken. |
| 298 if (!function->shared()->is_function()) return; | 238 if (!function->shared()->is_function()) return; |
| 299 Maybe<bool> maybe = JSReceiver::HasOwnProperty( | 239 Maybe<bool> maybe = JSReceiver::HasOwnProperty( |
| 300 target, isolate_->factory()->arguments_string()); | 240 target, isolate_->factory()->arguments_string()); |
| 301 DCHECK(maybe.IsJust()); | 241 DCHECK(maybe.IsJust()); |
| 302 if (maybe.FromJust()) return; | 242 if (maybe.FromJust()) return; |
| 303 | 243 |
| 304 // FunctionGetArguments can't throw an exception. | 244 // FunctionGetArguments can't throw an exception. |
| 305 Handle<JSObject> arguments = Accessors::FunctionGetArguments(function); | 245 Handle<JSObject> arguments = Accessors::FunctionGetArguments(function); |
| 306 Handle<String> arguments_str = isolate_->factory()->arguments_string(); | 246 Handle<String> arguments_str = isolate_->factory()->arguments_string(); |
| 307 JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments, | 247 JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments, |
| 308 NONE) | 248 NONE) |
| 309 .Check(); | 249 .Check(); |
| 310 } | 250 } |
| 311 | 251 |
| 312 | 252 void DebugEvaluate::ContextBuilder::MaterializeReceiver( |
| 313 MaybeHandle<Object> DebugEvaluate::ContextBuilder::LoadFromContext( | 253 Handle<JSObject> target, Handle<Context> local_context, |
| 314 Handle<Context> context, Handle<String> name, bool* global) { | 254 Handle<JSFunction> local_function, Handle<StringSet> non_locals) { |
| 315 static const ContextLookupFlags flags = FOLLOW_CONTEXT_CHAIN; | 255 Handle<Object> recv = isolate_->factory()->undefined_value(); |
| 316 int index; | 256 Handle<String> name = isolate_->factory()->this_string(); |
| 317 PropertyAttributes attributes; | 257 if (non_locals->Has(name)) { |
| 318 BindingFlags binding; | 258 // 'this' is allocated in an outer context and is is already being |
| 319 Handle<Object> holder = | 259 // referenced by the current function, so it can be correctly resolved. |
| 320 context->Lookup(name, flags, &index, &attributes, &binding); | 260 return; |
| 321 if (holder.is_null()) return MaybeHandle<Object>(); | 261 } else if (local_function->shared()->scope_info()->HasReceiver()) { |
| 322 Handle<Object> value; | 262 recv = handle(frame_->receiver(), isolate_); |
| 323 if (index != Context::kNotFound) { // Found on context. | |
| 324 Handle<Context> context = Handle<Context>::cast(holder); | |
| 325 // Do not shadow variables on the script context. | |
| 326 *global = context->IsScriptContext(); | |
| 327 return Handle<Object>(context->get(index), isolate_); | |
| 328 } else { // Found on object. | |
| 329 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); | |
| 330 // Do not shadow properties on the global object. | |
| 331 *global = object->IsJSGlobalObject(); | |
| 332 return JSReceiver::GetDataProperty(object, name); | |
| 333 } | 263 } |
| 334 } | 264 JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check(); |
| 335 | |
| 336 | |
| 337 void DebugEvaluate::ContextBuilder::MaterializeContextChain( | |
| 338 Handle<JSObject> target, Handle<Context> context) { | |
| 339 for (const Handle<String>& name : non_locals_) { | |
| 340 HandleScope scope(isolate_); | |
| 341 Handle<Object> value; | |
| 342 bool global; | |
| 343 if (!LoadFromContext(context, name, &global).ToHandle(&value) || global) { | |
| 344 // If resolving the variable fails, skip it. If it resolves to a global | |
| 345 // variable, skip it as well since it's not read-only and can be resolved | |
| 346 // within debug-evaluate. | |
| 347 continue; | |
| 348 } | |
| 349 JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check(); | |
| 350 } | |
| 351 } | |
| 352 | |
| 353 | |
| 354 void DebugEvaluate::ContextBuilder::StoreToContext(Handle<Context> context, | |
| 355 Handle<String> name, | |
| 356 Handle<Object> value) { | |
| 357 static const ContextLookupFlags flags = FOLLOW_CONTEXT_CHAIN; | |
| 358 int index; | |
| 359 PropertyAttributes attributes; | |
| 360 BindingFlags binding; | |
| 361 Handle<Object> holder = | |
| 362 context->Lookup(name, flags, &index, &attributes, &binding); | |
| 363 if (holder.is_null()) return; | |
| 364 if (attributes & READ_ONLY) return; | |
| 365 if (index != Context::kNotFound) { // Found on context. | |
| 366 Handle<Context> context = Handle<Context>::cast(holder); | |
| 367 context->set(index, *value); | |
| 368 } else { // Found on object. | |
| 369 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); | |
| 370 LookupIterator lookup(object, name); | |
| 371 if (lookup.state() != LookupIterator::DATA) return; | |
| 372 CHECK(JSReceiver::SetDataProperty(&lookup, value).FromJust()); | |
| 373 } | |
| 374 } | |
| 375 | |
| 376 | |
| 377 void DebugEvaluate::ContextBuilder::UpdateContextChainFromMaterializedObject( | |
| 378 Handle<JSObject> source, Handle<Context> context) { | |
| 379 // TODO(yangguo): check whether overwriting context fields is actually safe | |
| 380 // wrt fields we consider constant. | |
| 381 for (const Handle<String>& name : non_locals_) { | |
| 382 HandleScope scope(isolate_); | |
| 383 Handle<Object> value = JSReceiver::GetDataProperty(source, name); | |
| 384 StoreToContext(context, name, value); | |
| 385 } | |
| 386 } | |
| 387 | |
| 388 | |
| 389 Handle<Context> DebugEvaluate::ContextBuilder::MaterializeReceiver( | |
| 390 Handle<Context> parent_context, Handle<Context> lookup_context, | |
| 391 Handle<JSFunction> local_function, Handle<JSFunction> global_function, | |
| 392 bool this_is_non_local) { | |
| 393 Handle<Object> receiver = isolate_->factory()->undefined_value(); | |
| 394 Handle<String> this_string = isolate_->factory()->this_string(); | |
| 395 if (this_is_non_local) { | |
| 396 bool global; | |
| 397 LoadFromContext(lookup_context, this_string, &global).ToHandle(&receiver); | |
| 398 } else if (local_function->shared()->scope_info()->HasReceiver()) { | |
| 399 receiver = handle(frame_->receiver(), isolate_); | |
| 400 } | |
| 401 return isolate_->factory()->NewCatchContext(global_function, parent_context, | |
| 402 this_string, receiver); | |
| 403 } | 265 } |
| 404 | 266 |
| 405 } // namespace internal | 267 } // namespace internal |
| 406 } // namespace v8 | 268 } // namespace v8 |
| OLD | NEW |