1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "src/accessors.h"
8 #include "src/arguments.h"
10 #include "src/deoptimizer.h"
11 #include "src/isolate-inl.h"
12 #include "src/parser.h"
13 #include "src/runtime/runtime.h"
14 #include "src/runtime/runtime-utils.h"
19 RUNTIME_FUNCTION(Runtime_DebugBreak) {
20 SealHandleScope shs(isolate);
21 DCHECK(args.length() == 0);
22 isolate->debug()->HandleDebugBreak();
23 return isolate->heap()->undefined_value();
27 // Helper functions for wrapping and unwrapping stack frame ids.
28 static Smi* WrapFrameId(StackFrame::Id id) {
29 DCHECK(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
30 return Smi::FromInt(id >> 2);
34 static StackFrame::Id UnwrapFrameId(int wrapped) {
35 return static_cast<StackFrame::Id>(wrapped << 2);
39 // Adds a JavaScript function as a debug event listener.
40 // args[0]: debug event listener function to set or null or undefined for
41 // clearing the event listener function
42 // args[1]: object supplied during callback
43 RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
44 SealHandleScope shs(isolate);
45 DCHECK(args.length() == 2);
46 RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() ||
48 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
49 CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
50 isolate->debug()->SetEventListener(callback, data);
52 return isolate->heap()->undefined_value();
56 RUNTIME_FUNCTION(Runtime_Break) {
57 SealHandleScope shs(isolate);
58 DCHECK(args.length() == 0);
59 isolate->stack_guard()->RequestDebugBreak();
60 return isolate->heap()->undefined_value();
64 static Handle<Object> DebugGetProperty(LookupIterator* it,
65 bool* has_caught = NULL) {
66 for (; it->IsFound(); it->Next()) {
67 switch (it->state()) {
68 case LookupIterator::NOT_FOUND:
69 case LookupIterator::TRANSITION:
71 case LookupIterator::ACCESS_CHECK:
72 // Ignore access checks.
74 case LookupIterator::INTERCEPTOR:
75 case LookupIterator::JSPROXY:
76 return it->isolate()->factory()->undefined_value();
77 case LookupIterator::ACCESSOR: {
78 Handle<Object> accessors = it->GetAccessors();
79 if (!accessors->IsAccessorInfo()) {
80 return it->isolate()->factory()->undefined_value();
82 MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithAccessor(
83 it->GetReceiver(), it->name(), it->GetHolder<JSObject>(),
85 Handle<Object> result;
86 if (!maybe_result.ToHandle(&result)) {
87 result = handle(it->isolate()->pending_exception(), it->isolate());
88 it->isolate()->clear_pending_exception();
89 if (has_caught != NULL) *has_caught = true;
94 case LookupIterator::DATA:
95 return it->GetDataValue();
99 return it->isolate()->factory()->undefined_value();
103 // Get debugger related details for an object property, in the following format:
105 // 1: Property details
106 // 2: Property value is exception
107 // 3: Getter function if defined
108 // 4: Setter function if defined
109 // Items 2-4 are only filled if the property has either a getter or a setter.
110 RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
111 HandleScope scope(isolate);
113 DCHECK(args.length() == 2);
115 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
116 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
118 // Make sure to set the current context to the context before the debugger was
119 // entered (if the debugger is entered). The reason for switching context here
120 // is that for some property lookups (accessors and interceptors) callbacks
121 // into the embedding application can occour, and the embedding application
122 // could have the assumption that its own native context is the current
123 // context and not some internal debugger context.
124 SaveContext save(isolate);
125 if (isolate->debug()->in_debug_scope()) {
126 isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
129 // Check if the name is trivially convertible to an index and get the element
132 if (name->AsArrayIndex(&index)) {
133 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
134 Handle<Object> element_or_char;
135 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
136 isolate, element_or_char,
137 Runtime::GetElementOrCharAt(isolate, obj, index));
138 details->set(0, *element_or_char);
139 details->set(1, PropertyDetails(NONE, DATA, 0).AsSmi());
140 return *isolate->factory()->NewJSArrayWithElements(details);
143 LookupIterator it(obj, name, LookupIterator::HIDDEN);
144 bool has_caught = false;
145 Handle<Object> value = DebugGetProperty(&it, &has_caught);
146 if (!it.IsFound()) return isolate->heap()->undefined_value();
148 Handle<Object> maybe_pair;
149 if (it.state() == LookupIterator::ACCESSOR) {
150 maybe_pair = it.GetAccessors();
153 // If the callback object is a fixed array then it contains JavaScript
154 // getter and/or setter.
155 bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
156 Handle<FixedArray> details =
157 isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
158 details->set(0, *value);
159 // TODO(verwaest): Get rid of this random way of handling interceptors.
160 PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
161 ? PropertyDetails(NONE, DATA, 0)
162 : it.property_details();
163 details->set(1, d.AsSmi());
165 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
166 if (has_js_accessors) {
167 AccessorPair* accessors = AccessorPair::cast(*maybe_pair);
168 details->set(3, isolate->heap()->ToBoolean(has_caught));
169 details->set(4, accessors->GetComponent(ACCESSOR_GETTER));
170 details->set(5, accessors->GetComponent(ACCESSOR_SETTER));
173 return *isolate->factory()->NewJSArrayWithElements(details);
177 RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
178 HandleScope scope(isolate);
180 DCHECK(args.length() == 2);
182 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
183 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
185 LookupIterator it(obj, name);
186 return *DebugGetProperty(&it);
190 // Return the property type calculated from the property details.
191 // args[0]: smi with property details.
192 RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
193 SealHandleScope shs(isolate);
194 DCHECK(args.length() == 1);
195 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
196 return Smi::FromInt(static_cast<int>(details.type()));
200 // Return the property attribute calculated from the property details.
201 // args[0]: smi with property details.
202 RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
203 SealHandleScope shs(isolate);
204 DCHECK(args.length() == 1);
205 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
206 return Smi::FromInt(static_cast<int>(details.attributes()));
210 // Return the property insertion index calculated from the property details.
211 // args[0]: smi with property details.
212 RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) {
213 SealHandleScope shs(isolate);
214 DCHECK(args.length() == 1);
215 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
216 // TODO(verwaest): Works only for dictionary mode holders.
217 return Smi::FromInt(details.dictionary_index());
221 // Return property value from named interceptor.
223 // args[1]: property name
224 RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) {
225 HandleScope scope(isolate);
226 DCHECK(args.length() == 2);
227 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
228 RUNTIME_ASSERT(obj->HasNamedInterceptor());
229 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
231 Handle<Object> result;
232 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
233 JSObject::GetProperty(obj, name));
238 // Return element value from indexed interceptor.
241 RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
242 HandleScope scope(isolate);
243 DCHECK(args.length() == 2);
244 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
245 RUNTIME_ASSERT(obj->HasIndexedInterceptor());
246 CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
247 Handle<Object> result;
248 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
250 JSObject::GetElementWithInterceptor(obj, obj, index, true));
255 RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
256 SealHandleScope shs(isolate);
257 DCHECK(args.length() == 1);
258 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
259 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
260 return isolate->heap()->true_value();
264 RUNTIME_FUNCTION(Runtime_GetFrameCount) {
265 HandleScope scope(isolate);
266 DCHECK(args.length() == 1);
267 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
268 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
270 // Count all frames which are relevant to debugging stack trace.
272 StackFrame::Id id = isolate->debug()->break_frame_id();
273 if (id == StackFrame::NO_ID) {
274 // If there is no JavaScript stack frame count is 0.
275 return Smi::FromInt(0);
278 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
279 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
280 it.frame()->Summarize(&frames);
281 for (int i = frames.length() - 1; i >= 0; i--) {
282 // Omit functions from native scripts.
283 if (!frames[i].function()->IsFromNativeScript()) n++;
286 return Smi::FromInt(n);
290 class FrameInspector {
292 FrameInspector(JavaScriptFrame* frame, int inlined_jsframe_index,
294 : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
295 // Calculate the deoptimized frame.
296 if (frame->is_optimized()) {
297 deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
298 frame, inlined_jsframe_index, isolate);
300 has_adapted_arguments_ = frame_->has_adapted_arguments();
301 is_bottommost_ = inlined_jsframe_index == 0;
302 is_optimized_ = frame_->is_optimized();
306 // Get rid of the calculated deoptimized frame if any.
307 if (deoptimized_frame_ != NULL) {
308 Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_, isolate_);
312 int GetParametersCount() {
313 return is_optimized_ ? deoptimized_frame_->parameters_count()
314 : frame_->ComputeParametersCount();
316 int expression_count() { return deoptimized_frame_->expression_count(); }
317 Object* GetFunction() {
318 return is_optimized_ ? deoptimized_frame_->GetFunction()
319 : frame_->function();
321 Object* GetParameter(int index) {
322 return is_optimized_ ? deoptimized_frame_->GetParameter(index)
323 : frame_->GetParameter(index);
325 Object* GetExpression(int index) {
326 return is_optimized_ ? deoptimized_frame_->GetExpression(index)
327 : frame_->GetExpression(index);
329 int GetSourcePosition() {
330 return is_optimized_ ? deoptimized_frame_->GetSourcePosition()
331 : frame_->LookupCode()->SourcePosition(frame_->pc());
333 bool IsConstructor() {
334 return is_optimized_ && !is_bottommost_
335 ? deoptimized_frame_->HasConstructStub()
336 : frame_->IsConstructor();
338 Object* GetContext() {
339 return is_optimized_ ? deoptimized_frame_->GetContext() : frame_->context();
342 // To inspect all the provided arguments the frame might need to be
343 // replaced with the arguments frame.
344 void SetArgumentsFrame(JavaScriptFrame* frame) {
345 DCHECK(has_adapted_arguments_);
347 is_optimized_ = frame_->is_optimized();
348 DCHECK(!is_optimized_);
352 JavaScriptFrame* frame_;
353 DeoptimizedFrameInfo* deoptimized_frame_;
357 bool has_adapted_arguments_;
359 DISALLOW_COPY_AND_ASSIGN(FrameInspector);
363 static const int kFrameDetailsFrameIdIndex = 0;
364 static const int kFrameDetailsReceiverIndex = 1;
365 static const int kFrameDetailsFunctionIndex = 2;
366 static const int kFrameDetailsArgumentCountIndex = 3;
367 static const int kFrameDetailsLocalCountIndex = 4;
368 static const int kFrameDetailsSourcePositionIndex = 5;
369 static const int kFrameDetailsConstructCallIndex = 6;
370 static const int kFrameDetailsAtReturnIndex = 7;
371 static const int kFrameDetailsFlagsIndex = 8;
372 static const int kFrameDetailsFirstDynamicIndex = 9;
375 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
376 JavaScriptFrame* frame) {
377 SaveContext* save = isolate->save_context();
378 while (save != NULL && !save->IsBelowFrame(frame)) {
381 DCHECK(save != NULL);
386 // Advances the iterator to the frame that matches the index and returns the
387 // inlined frame index, or -1 if not found. Skips native JS functions.
388 int Runtime::FindIndexedNonNativeFrame(JavaScriptFrameIterator* it, int index) {
390 for (; !it->done(); it->Advance()) {
391 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
392 it->frame()->Summarize(&frames);
393 for (int i = frames.length() - 1; i >= 0; i--) {
394 // Omit functions from native scripts.
395 if (frames[i].function()->IsFromNativeScript()) continue;
396 if (++count == index) return i;
403 // Return an array with frame details
404 // args[0]: number: break id
405 // args[1]: number: frame index
407 // The array returned contains the following information:
413 // 5: Source position
414 // 6: Constructor call
417 // Arguments name, value
418 // Locals name, value
419 // Return value if any
420 RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
421 HandleScope scope(isolate);
422 DCHECK(args.length() == 2);
423 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
424 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
426 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
427 Heap* heap = isolate->heap();
429 // Find the relevant frame with the requested index.
430 StackFrame::Id id = isolate->debug()->break_frame_id();
431 if (id == StackFrame::NO_ID) {
432 // If there are no JavaScript stack frames return undefined.
433 return heap->undefined_value();
436 JavaScriptFrameIterator it(isolate, id);
437 // Inlined frame index in optimized frame, starting from outer function.
438 int inlined_jsframe_index = Runtime::FindIndexedNonNativeFrame(&it, index);
439 if (inlined_jsframe_index == -1) return heap->undefined_value();
441 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
442 bool is_optimized = it.frame()->is_optimized();
444 // Traverse the saved contexts chain to find the active context for the
446 SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
449 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
451 // Find source position in unoptimized code.
452 int position = frame_inspector.GetSourcePosition();
454 // Check for constructor frame.
455 bool constructor = frame_inspector.IsConstructor();
457 // Get scope info and read from it for local variable information.
458 Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
459 Handle<SharedFunctionInfo> shared(function->shared());
460 Handle<ScopeInfo> scope_info(shared->scope_info());
461 DCHECK(*scope_info != ScopeInfo::Empty(isolate));
463 // Get the locals names and values into a temporary array.
464 int local_count = scope_info->LocalCount();
465 for (int slot = 0; slot < scope_info->LocalCount(); ++slot) {
466 // Hide compiler-introduced temporary variables, whether on the stack or on
468 if (scope_info->LocalIsSynthetic(slot)) local_count--;
471 Handle<FixedArray> locals =
472 isolate->factory()->NewFixedArray(local_count * 2);
474 // Fill in the values of the locals.
477 for (; i < scope_info->StackLocalCount(); ++i) {
478 // Use the value from the stack.
479 if (scope_info->LocalIsSynthetic(i)) continue;
480 locals->set(local * 2, scope_info->LocalName(i));
481 locals->set(local * 2 + 1, frame_inspector.GetExpression(i));
484 if (local < local_count) {
485 // Get the context containing declarations.
486 Handle<Context> context(
487 Context::cast(frame_inspector.GetContext())->declaration_context());
488 for (; i < scope_info->LocalCount(); ++i) {
489 if (scope_info->LocalIsSynthetic(i)) continue;
490 Handle<String> name(scope_info->LocalName(i));
492 InitializationFlag init_flag;
493 MaybeAssignedFlag maybe_assigned_flag;
494 locals->set(local * 2, *name);
495 int context_slot_index = ScopeInfo::ContextSlotIndex(
496 scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
497 Object* value = context->get(context_slot_index);
498 locals->set(local * 2 + 1, value);
503 // Check whether this frame is positioned at return. If not top
504 // frame or if the frame is optimized it cannot be at a return.
505 bool at_return = false;
506 if (!is_optimized && index == 0) {
507 at_return = isolate->debug()->IsBreakAtReturn(it.frame());
510 // If positioned just before return find the value to be returned and add it
511 // to the frame information.
512 Handle<Object> return_value = isolate->factory()->undefined_value();
514 StackFrameIterator it2(isolate);
515 Address internal_frame_sp = NULL;
516 while (!it2.done()) {
517 if (it2.frame()->is_internal()) {
518 internal_frame_sp = it2.frame()->sp();
520 if (it2.frame()->is_java_script()) {
521 if (it2.frame()->id() == it.frame()->id()) {
522 // The internal frame just before the JavaScript frame contains the
523 // value to return on top. A debug break at return will create an
524 // internal frame to store the return value (eax/rax/r0) before
525 // entering the debug break exit frame.
526 if (internal_frame_sp != NULL) {
528 Handle<Object>(Memory::Object_at(internal_frame_sp), isolate);
534 // Indicate that the previous frame was not an internal frame.
535 internal_frame_sp = NULL;
541 // Now advance to the arguments adapter frame (if any). It contains all
542 // the provided parameters whereas the function frame always have the number
543 // of arguments matching the functions parameters. The rest of the
544 // information (except for what is collected above) is the same.
545 if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
546 it.AdvanceToArgumentsFrame();
547 frame_inspector.SetArgumentsFrame(it.frame());
550 // Find the number of arguments to fill. At least fill the number of
551 // parameters for the function and fill more if more parameters are provided.
552 int argument_count = scope_info->ParameterCount();
553 if (argument_count < frame_inspector.GetParametersCount()) {
554 argument_count = frame_inspector.GetParametersCount();
557 // Calculate the size of the result.
558 int details_size = kFrameDetailsFirstDynamicIndex +
559 2 * (argument_count + local_count) + (at_return ? 1 : 0);
560 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
563 details->set(kFrameDetailsFrameIdIndex, *frame_id);
565 // Add the function (same as in function frame).
566 details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
568 // Add the arguments count.
569 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
571 // Add the locals count
572 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
574 // Add the source position.
575 if (position != RelocInfo::kNoPosition) {
576 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
578 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
581 // Add the constructor information.
582 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
584 // Add the at return information.
585 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
587 // Add flags to indicate information on whether this frame is
588 // bit 0: invoked in the debugger context.
589 // bit 1: optimized frame.
590 // bit 2: inlined in optimized frame
592 if (*save->context() == *isolate->debug()->debug_context()) {
597 flags |= inlined_jsframe_index << 2;
599 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
601 // Fill the dynamic part.
602 int details_index = kFrameDetailsFirstDynamicIndex;
604 // Add arguments name and value.
605 for (int i = 0; i < argument_count; i++) {
606 // Name of the argument.
607 if (i < scope_info->ParameterCount()) {
608 details->set(details_index++, scope_info->ParameterName(i));
610 details->set(details_index++, heap->undefined_value());
614 if (i < frame_inspector.GetParametersCount()) {
615 // Get the value from the stack.
616 details->set(details_index++, frame_inspector.GetParameter(i));
618 details->set(details_index++, heap->undefined_value());
622 // Add locals name and value from the temporary copy from the function frame.
623 for (int i = 0; i < local_count * 2; i++) {
624 details->set(details_index++, locals->get(i));
627 // Add the value being returned.
629 details->set(details_index++, *return_value);
632 // Add the receiver (same as in function frame).
633 // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
634 // THE FRAME ITERATOR TO WRAP THE RECEIVER.
635 Handle<Object> receiver(it.frame()->receiver(), isolate);
636 if (!receiver->IsJSObject() && is_sloppy(shared->language_mode()) &&
637 !function->IsBuiltin()) {
638 // If the receiver is not a JSObject and the function is not a
639 // builtin or strict-mode we have hit an optimization where a
640 // value object is not converted into a wrapped JS objects. To
641 // hide this optimization from the debugger, we wrap the receiver
642 // by creating correct wrapper object based on the calling frame's
645 if (receiver->IsUndefined()) {
646 receiver = handle(function->global_proxy());
648 Context* context = Context::cast(it.frame()->context());
649 Handle<Context> native_context(Context::cast(context->native_context()));
650 if (!Object::ToObject(isolate, receiver, native_context)
651 .ToHandle(&receiver)) {
652 // This only happens if the receiver is forcibly set in %_CallFunction.
653 return heap->undefined_value();
657 details->set(kFrameDetailsReceiverIndex, *receiver);
659 DCHECK_EQ(details_size, details_index);
660 return *isolate->factory()->NewJSArrayWithElements(details);
664 static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,
665 Handle<String> parameter_name) {
667 InitializationFlag init_flag;
668 MaybeAssignedFlag maybe_assigned_flag;
669 return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
670 &maybe_assigned_flag) != -1;
674 // Create a plain JSObject which materializes the local scope for the specified
677 static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector(
678 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function,
679 FrameInspector* frame_inspector) {
680 Handle<SharedFunctionInfo> shared(function->shared());
681 Handle<ScopeInfo> scope_info(shared->scope_info());
683 // First fill all parameters.
684 for (int i = 0; i < scope_info->ParameterCount(); ++i) {
685 // Do not materialize the parameter if it is shadowed by a context local.
686 Handle<String> name(scope_info->ParameterName(i));
687 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
689 HandleScope scope(isolate);
690 Handle<Object> value(i < frame_inspector->GetParametersCount()
691 ? frame_inspector->GetParameter(i)
692 : isolate->heap()->undefined_value(),
694 DCHECK(!value->IsTheHole());
696 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty(
697 isolate, target, name, value, SLOPPY),
701 // Second fill all stack locals.
702 for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
703 if (scope_info->LocalIsSynthetic(i)) continue;
704 Handle<String> name(scope_info->StackLocalName(i));
705 Handle<Object> value(frame_inspector->GetExpression(i), isolate);
706 if (value->IsTheHole()) continue;
708 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty(
709 isolate, target, name, value, SLOPPY),
717 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
718 Handle<JSObject> target,
719 Handle<JSFunction> function,
720 JavaScriptFrame* frame,
721 int inlined_jsframe_index) {
722 if (inlined_jsframe_index != 0 || frame->is_optimized()) {
723 // Optimized frames are not supported.
724 // TODO(yangguo): make sure all code deoptimized when debugger is active
725 // and assert that this cannot happen.
729 Handle<SharedFunctionInfo> shared(function->shared());
730 Handle<ScopeInfo> scope_info(shared->scope_info());
733 for (int i = 0; i < scope_info->ParameterCount(); ++i) {
734 // Shadowed parameters were not materialized.
735 Handle<String> name(scope_info->ParameterName(i));
736 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
738 DCHECK(!frame->GetParameter(i)->IsTheHole());
739 HandleScope scope(isolate);
740 Handle<Object> value =
741 Object::GetPropertyOrElement(target, name).ToHandleChecked();
742 frame->SetParameterValue(i, *value);
746 for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
747 if (scope_info->LocalIsSynthetic(i)) continue;
748 if (frame->GetExpression(i)->IsTheHole()) continue;
749 HandleScope scope(isolate);
750 Handle<Object> value = Object::GetPropertyOrElement(
751 target, handle(scope_info->StackLocalName(i),
752 isolate)).ToHandleChecked();
753 frame->SetExpression(i, *value);
758 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext(
759 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function,
760 JavaScriptFrame* frame) {
761 HandleScope scope(isolate);
762 Handle<SharedFunctionInfo> shared(function->shared());
763 Handle<ScopeInfo> scope_info(shared->scope_info());
765 if (!scope_info->HasContext()) return target;
767 // Third fill all context locals.
768 Handle<Context> frame_context(Context::cast(frame->context()));
769 Handle<Context> function_context(frame_context->declaration_context());
770 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, function_context,
772 return MaybeHandle<JSObject>();
775 // Finally copy any properties from the function context extension.
776 // These will be variables introduced by eval.
777 if (function_context->closure() == *function) {
778 if (function_context->has_extension() &&
779 !function_context->IsNativeContext()) {
780 Handle<JSObject> ext(JSObject::cast(function_context->extension()));
781 Handle<FixedArray> keys;
782 ASSIGN_RETURN_ON_EXCEPTION(
783 isolate, keys, JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS),
786 for (int i = 0; i < keys->length(); i++) {
787 // Names of variables introduced by eval are strings.
788 DCHECK(keys->get(i)->IsString());
789 Handle<String> key(String::cast(keys->get(i)));
790 Handle<Object> value;
791 ASSIGN_RETURN_ON_EXCEPTION(
792 isolate, value, Object::GetPropertyOrElement(ext, key), JSObject);
793 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty(
794 isolate, target, key, value, SLOPPY),
804 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScriptScope(
805 Handle<GlobalObject> global) {
806 Isolate* isolate = global->GetIsolate();
807 Handle<ScriptContextTable> script_contexts(
808 global->native_context()->script_context_table());
810 Handle<JSObject> script_scope =
811 isolate->factory()->NewJSObject(isolate->object_function());
813 for (int context_index = 0; context_index < script_contexts->used();
815 Handle<Context> context =
816 ScriptContextTable::GetContext(script_contexts, context_index);
817 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
818 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context,
820 return MaybeHandle<JSObject>();
827 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalScope(
828 Isolate* isolate, JavaScriptFrame* frame, int inlined_jsframe_index) {
829 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
830 Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
832 Handle<JSObject> local_scope =
833 isolate->factory()->NewJSObject(isolate->object_function());
834 ASSIGN_RETURN_ON_EXCEPTION(
835 isolate, local_scope,
836 MaterializeStackLocalsWithFrameInspector(isolate, local_scope, function,
840 return MaterializeLocalContext(isolate, local_scope, function, frame);
844 // Set the context local variable value.
845 static bool SetContextLocalValue(Isolate* isolate, Handle<ScopeInfo> scope_info,
846 Handle<Context> context,
847 Handle<String> variable_name,
848 Handle<Object> new_value) {
849 for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
850 Handle<String> next_name(scope_info->ContextLocalName(i));
851 if (String::Equals(variable_name, next_name)) {
853 InitializationFlag init_flag;
854 MaybeAssignedFlag maybe_assigned_flag;
855 int context_index = ScopeInfo::ContextSlotIndex(
856 scope_info, next_name, &mode, &init_flag, &maybe_assigned_flag);
857 context->set(context_index, *new_value);
866 static bool SetLocalVariableValue(Isolate* isolate, JavaScriptFrame* frame,
867 int inlined_jsframe_index,
868 Handle<String> variable_name,
869 Handle<Object> new_value) {
870 if (inlined_jsframe_index != 0 || frame->is_optimized()) {
871 // Optimized frames are not supported.
875 Handle<JSFunction> function(frame->function());
876 Handle<SharedFunctionInfo> shared(function->shared());
877 Handle<ScopeInfo> scope_info(shared->scope_info());
879 bool default_result = false;
882 for (int i = 0; i < scope_info->ParameterCount(); ++i) {
883 HandleScope scope(isolate);
884 if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) {
885 frame->SetParameterValue(i, *new_value);
886 // Argument might be shadowed in heap context, don't stop here.
887 default_result = true;
892 for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
893 HandleScope scope(isolate);
894 if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
895 frame->SetExpression(i, *new_value);
900 if (scope_info->HasContext()) {
902 Handle<Context> frame_context(Context::cast(frame->context()));
903 Handle<Context> function_context(frame_context->declaration_context());
904 if (SetContextLocalValue(isolate, scope_info, function_context,
905 variable_name, new_value)) {
909 // Function context extension. These are variables introduced by eval.
910 if (function_context->closure() == *function) {
911 if (function_context->has_extension() &&
912 !function_context->IsNativeContext()) {
913 Handle<JSObject> ext(JSObject::cast(function_context->extension()));
915 Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name);
916 DCHECK(maybe.has_value);
918 // We don't expect this to do anything except replacing
920 Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
928 return default_result;
932 // Create a plain JSObject which materializes the closure content for the
934 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeClosure(
935 Isolate* isolate, Handle<Context> context) {
936 DCHECK(context->IsFunctionContext());
938 Handle<SharedFunctionInfo> shared(context->closure()->shared());
939 Handle<ScopeInfo> scope_info(shared->scope_info());
941 // Allocate and initialize a JSObject with all the content of this function
943 Handle<JSObject> closure_scope =
944 isolate->factory()->NewJSObject(isolate->object_function());
946 // Fill all context locals to the context extension.
947 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context,
949 return MaybeHandle<JSObject>();
952 // Finally copy any properties from the function context extension. This will
953 // be variables introduced by eval.
954 if (context->has_extension()) {
955 Handle<JSObject> ext(JSObject::cast(context->extension()));
956 Handle<FixedArray> keys;
957 ASSIGN_RETURN_ON_EXCEPTION(
958 isolate, keys, JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS),
961 for (int i = 0; i < keys->length(); i++) {
962 HandleScope scope(isolate);
963 // Names of variables introduced by eval are strings.
964 DCHECK(keys->get(i)->IsString());
965 Handle<String> key(String::cast(keys->get(i)));
966 Handle<Object> value;
967 ASSIGN_RETURN_ON_EXCEPTION(
968 isolate, value, Object::GetPropertyOrElement(ext, key), JSObject);
969 RETURN_ON_EXCEPTION(isolate, Runtime::DefineObjectProperty(
970 closure_scope, key, value, NONE),
975 return closure_scope;
979 // This method copies structure of MaterializeClosure method above.
980 static bool SetClosureVariableValue(Isolate* isolate, Handle<Context> context,
981 Handle<String> variable_name,
982 Handle<Object> new_value) {
983 DCHECK(context->IsFunctionContext());
985 Handle<SharedFunctionInfo> shared(context->closure()->shared());
986 Handle<ScopeInfo> scope_info(shared->scope_info());
988 // Context locals to the context extension.
989 if (SetContextLocalValue(isolate, scope_info, context, variable_name,
994 // Properties from the function context extension. This will
995 // be variables introduced by eval.
996 if (context->has_extension()) {
997 Handle<JSObject> ext(JSObject::cast(context->extension()));
998 Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name);
999 DCHECK(maybe.has_value);
1001 // We don't expect this to do anything except replacing property value.
1002 Runtime::DefineObjectProperty(ext, variable_name, new_value, NONE)
1012 static bool SetBlockContextVariableValue(Handle<Context> block_context,
1013 Handle<String> variable_name,
1014 Handle<Object> new_value) {
1015 DCHECK(block_context->IsBlockContext());
1016 Handle<ScopeInfo> scope_info(ScopeInfo::cast(block_context->extension()));
1018 return SetContextLocalValue(block_context->GetIsolate(), scope_info,
1019 block_context, variable_name, new_value);
1023 static bool SetScriptVariableValue(Handle<Context> context,
1024 Handle<String> variable_name,
1025 Handle<Object> new_value) {
1026 Handle<ScriptContextTable> script_contexts(
1027 context->global_object()->native_context()->script_context_table());
1028 ScriptContextTable::LookupResult lookup_result;
1029 if (ScriptContextTable::Lookup(script_contexts, variable_name,
1031 Handle<Context> script_context = ScriptContextTable::GetContext(
1032 script_contexts, lookup_result.context_index);
1033 script_context->set(lookup_result.slot_index, *new_value);
1041 // Create a plain JSObject which materializes the scope for the specified
1043 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeCatchScope(
1044 Isolate* isolate, Handle<Context> context) {
1045 DCHECK(context->IsCatchContext());
1046 Handle<String> name(String::cast(context->extension()));
1047 Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
1049 Handle<JSObject> catch_scope =
1050 isolate->factory()->NewJSObject(isolate->object_function());
1051 RETURN_ON_EXCEPTION(isolate, Runtime::DefineObjectProperty(
1052 catch_scope, name, thrown_object, NONE),
1058 static bool SetCatchVariableValue(Isolate* isolate, Handle<Context> context,
1059 Handle<String> variable_name,
1060 Handle<Object> new_value) {
1061 DCHECK(context->IsCatchContext());
1062 Handle<String> name(String::cast(context->extension()));
1063 if (!String::Equals(name, variable_name)) {
1066 context->set(Context::THROWN_OBJECT_INDEX, *new_value);
1071 // Create a plain JSObject which materializes the block scope for the specified
1073 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope(
1074 Isolate* isolate, Handle<Context> context) {
1075 DCHECK(context->IsBlockContext());
1076 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
1078 // Allocate and initialize a JSObject with all the arguments, stack locals
1079 // heap locals and extension properties of the debugged function.
1080 Handle<JSObject> block_scope =
1081 isolate->factory()->NewJSObject(isolate->object_function());
1083 // Fill all context locals.
1084 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context,
1086 return MaybeHandle<JSObject>();
1093 // Create a plain JSObject which materializes the module scope for the specified
1095 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope(
1096 Isolate* isolate, Handle<Context> context) {
1097 DCHECK(context->IsModuleContext());
1098 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
1100 // Allocate and initialize a JSObject with all the members of the debugged
1102 Handle<JSObject> module_scope =
1103 isolate->factory()->NewJSObject(isolate->object_function());
1105 // Fill all context locals.
1106 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context,
1108 return MaybeHandle<JSObject>();
1111 return module_scope;
1115 // Iterate over the actual scopes visible from a stack frame or from a closure.
1116 // The iteration proceeds from the innermost visible nested scope outwards.
1117 // All scopes are backed by an actual context except the local scope,
1118 // which is inserted "artificially" in the context chain.
1119 class ScopeIterator {
1122 ScopeTypeGlobal = 0,
1132 ScopeIterator(Isolate* isolate, JavaScriptFrame* frame,
1133 int inlined_jsframe_index, bool ignore_nested_scopes = false)
1134 : isolate_(isolate),
1136 inlined_jsframe_index_(inlined_jsframe_index),
1137 function_(frame->function()),
1138 context_(Context::cast(frame->context())),
1139 nested_scope_chain_(4),
1140 seen_script_scope_(false),
1142 // Catch the case when the debugger stops in an internal function.
1143 Handle<SharedFunctionInfo> shared_info(function_->shared());
1144 Handle<ScopeInfo> scope_info(shared_info->scope_info());
1145 if (shared_info->script() == isolate->heap()->undefined_value()) {
1146 while (context_->closure() == *function_) {
1147 context_ = Handle<Context>(context_->previous(), isolate_);
1152 // Get the debug info (create it if it does not exist).
1153 if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
1154 // Return if ensuring debug info failed.
1158 // Currently it takes too much time to find nested scopes due to script
1159 // parsing. Sometimes we want to run the ScopeIterator as fast as possible
1160 // (for example, while collecting async call stacks on every
1161 // addEventListener call), even if we drop some nested scopes.
1162 // Later we may optimize getting the nested scopes (cache the result?)
1163 // and include nested scopes into the "fast" iteration case as well.
1164 if (!ignore_nested_scopes) {
1165 Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
1167 // Find the break point where execution has stopped.
1168 BreakLocationIterator break_location_iterator(debug_info,
1169 ALL_BREAK_LOCATIONS);
1170 // pc points to the instruction after the current one, possibly a break
1171 // location as well. So the "- 1" to exclude it from the search.
1172 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
1174 // Within the return sequence at the moment it is not possible to
1175 // get a source position which is consistent with the current scope chain.
1176 // Thus all nested with, catch and block contexts are skipped and we only
1177 // provide the function scope.
1178 ignore_nested_scopes = break_location_iterator.IsExit();
1181 if (ignore_nested_scopes) {
1182 if (scope_info->HasContext()) {
1183 context_ = Handle<Context>(context_->declaration_context(), isolate_);
1185 while (context_->closure() == *function_) {
1186 context_ = Handle<Context>(context_->previous(), isolate_);
1189 if (scope_info->scope_type() == FUNCTION_SCOPE ||
1190 scope_info->scope_type() == ARROW_SCOPE) {
1191 nested_scope_chain_.Add(scope_info);
1194 // Reparse the code and analyze the scopes.
1195 Handle<Script> script(Script::cast(shared_info->script()));
1196 Scope* scope = NULL;
1198 // Check whether we are in global, eval or function code.
1199 Handle<ScopeInfo> scope_info(shared_info->scope_info());
1200 if (scope_info->scope_type() != FUNCTION_SCOPE &&
1201 scope_info->scope_type() != ARROW_SCOPE) {
1202 // Global or eval code.
1203 CompilationInfoWithZone info(script);
1204 if (scope_info->scope_type() == SCRIPT_SCOPE) {
1205 info.MarkAsGlobal();
1207 DCHECK(scope_info->scope_type() == EVAL_SCOPE);
1209 info.SetContext(Handle<Context>(function_->context()));
1211 if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
1212 scope = info.function()->scope();
1214 RetrieveScopeChain(scope, shared_info);
1217 CompilationInfoWithZone info(shared_info);
1218 if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
1219 scope = info.function()->scope();
1221 RetrieveScopeChain(scope, shared_info);
1226 ScopeIterator(Isolate* isolate, Handle<JSFunction> function)
1227 : isolate_(isolate),
1229 inlined_jsframe_index_(0),
1230 function_(function),
1231 context_(function->context()),
1232 seen_script_scope_(false),
1234 if (function->IsBuiltin()) {
1235 context_ = Handle<Context>();
1242 return context_.is_null();
1245 bool Failed() { return failed_; }
1247 // Move to the next scope.
1250 ScopeType scope_type = Type();
1251 if (scope_type == ScopeTypeGlobal) {
1252 // The global scope is always the last in the chain.
1253 DCHECK(context_->IsNativeContext());
1254 context_ = Handle<Context>();
1257 if (scope_type == ScopeTypeScript) seen_script_scope_ = true;
1258 if (nested_scope_chain_.is_empty()) {
1259 if (scope_type == ScopeTypeScript) {
1260 if (context_->IsScriptContext()) {
1261 context_ = Handle<Context>(context_->previous(), isolate_);
1263 CHECK(context_->IsNativeContext());
1265 context_ = Handle<Context>(context_->previous(), isolate_);
1268 if (nested_scope_chain_.last()->HasContext()) {
1269 DCHECK(context_->previous() != NULL);
1270 context_ = Handle<Context>(context_->previous(), isolate_);
1272 nested_scope_chain_.RemoveLast();
1276 // Return the type of the current scope.
1279 if (!nested_scope_chain_.is_empty()) {
1280 Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
1281 switch (scope_info->scope_type()) {
1282 case FUNCTION_SCOPE:
1284 DCHECK(context_->IsFunctionContext() || !scope_info->HasContext());
1285 return ScopeTypeLocal;
1287 DCHECK(context_->IsModuleContext());
1288 return ScopeTypeModule;
1290 DCHECK(context_->IsScriptContext() || context_->IsNativeContext());
1291 return ScopeTypeScript;
1293 DCHECK(context_->IsWithContext());
1294 return ScopeTypeWith;
1296 DCHECK(context_->IsCatchContext());
1297 return ScopeTypeCatch;
1299 DCHECK(!scope_info->HasContext() || context_->IsBlockContext());
1300 return ScopeTypeBlock;
1305 if (context_->IsNativeContext()) {
1306 DCHECK(context_->global_object()->IsGlobalObject());
1307 // If we are at the native context and have not yet seen script scope,
1309 return seen_script_scope_ ? ScopeTypeGlobal : ScopeTypeScript;
1311 if (context_->IsFunctionContext()) {
1312 return ScopeTypeClosure;
1314 if (context_->IsCatchContext()) {
1315 return ScopeTypeCatch;
1317 if (context_->IsBlockContext()) {
1318 return ScopeTypeBlock;
1320 if (context_->IsModuleContext()) {
1321 return ScopeTypeModule;
1323 if (context_->IsScriptContext()) {
1324 return ScopeTypeScript;
1326 DCHECK(context_->IsWithContext());
1327 return ScopeTypeWith;
1330 // Return the JavaScript object with the content of the current scope.
1331 MaybeHandle<JSObject> ScopeObject() {
1334 case ScopeIterator::ScopeTypeGlobal:
1335 return Handle<JSObject>(CurrentContext()->global_object());
1336 case ScopeIterator::ScopeTypeScript:
1337 return MaterializeScriptScope(
1338 Handle<GlobalObject>(CurrentContext()->global_object()));
1339 case ScopeIterator::ScopeTypeLocal:
1340 // Materialize the content of the local scope into a JSObject.
1341 DCHECK(nested_scope_chain_.length() == 1);
1342 return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
1343 case ScopeIterator::ScopeTypeWith:
1344 // Return the with object.
1345 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
1346 case ScopeIterator::ScopeTypeCatch:
1347 return MaterializeCatchScope(isolate_, CurrentContext());
1348 case ScopeIterator::ScopeTypeClosure:
1349 // Materialize the content of the closure scope into a JSObject.
1350 return MaterializeClosure(isolate_, CurrentContext());
1351 case ScopeIterator::ScopeTypeBlock:
1352 return MaterializeBlockScope(isolate_, CurrentContext());
1353 case ScopeIterator::ScopeTypeModule:
1354 return MaterializeModuleScope(isolate_, CurrentContext());
1357 return Handle<JSObject>();
1360 bool SetVariableValue(Handle<String> variable_name,
1361 Handle<Object> new_value) {
1364 case ScopeIterator::ScopeTypeGlobal:
1366 case ScopeIterator::ScopeTypeLocal:
1367 return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
1368 variable_name, new_value);
1369 case ScopeIterator::ScopeTypeWith:
1371 case ScopeIterator::ScopeTypeCatch:
1372 return SetCatchVariableValue(isolate_, CurrentContext(), variable_name,
1374 case ScopeIterator::ScopeTypeClosure:
1375 return SetClosureVariableValue(isolate_, CurrentContext(),
1376 variable_name, new_value);
1377 case ScopeIterator::ScopeTypeScript:
1378 return SetScriptVariableValue(CurrentContext(), variable_name,
1380 case ScopeIterator::ScopeTypeBlock:
1381 return SetBlockContextVariableValue(CurrentContext(), variable_name,
1383 case ScopeIterator::ScopeTypeModule:
1384 // TODO(2399): should we implement it?
1390 Handle<ScopeInfo> CurrentScopeInfo() {
1392 if (!nested_scope_chain_.is_empty()) {
1393 return nested_scope_chain_.last();
1394 } else if (context_->IsBlockContext()) {
1395 return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
1396 } else if (context_->IsFunctionContext()) {
1397 return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
1399 return Handle<ScopeInfo>::null();
1402 // Return the context for this scope. For the local context there might not
1403 // be an actual context.
1404 Handle<Context> CurrentContext() {
1406 if (Type() == ScopeTypeGlobal || Type() == ScopeTypeScript ||
1407 nested_scope_chain_.is_empty()) {
1409 } else if (nested_scope_chain_.last()->HasContext()) {
1412 return Handle<Context>();
1417 // Debug print of the content of the current scope.
1419 OFStream os(stdout);
1422 case ScopeIterator::ScopeTypeGlobal:
1424 CurrentContext()->Print(os);
1427 case ScopeIterator::ScopeTypeLocal: {
1429 function_->shared()->scope_info()->Print();
1430 if (!CurrentContext().is_null()) {
1431 CurrentContext()->Print(os);
1432 if (CurrentContext()->has_extension()) {
1433 Handle<Object> extension(CurrentContext()->extension(), isolate_);
1434 if (extension->IsJSContextExtensionObject()) {
1435 extension->Print(os);
1442 case ScopeIterator::ScopeTypeWith:
1444 CurrentContext()->extension()->Print(os);
1447 case ScopeIterator::ScopeTypeCatch:
1449 CurrentContext()->extension()->Print(os);
1450 CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print(os);
1453 case ScopeIterator::ScopeTypeClosure:
1455 CurrentContext()->Print(os);
1456 if (CurrentContext()->has_extension()) {
1457 Handle<Object> extension(CurrentContext()->extension(), isolate_);
1458 if (extension->IsJSContextExtensionObject()) {
1459 extension->Print(os);
1464 case ScopeIterator::ScopeTypeScript:
1469 ->script_context_table()
1482 JavaScriptFrame* frame_;
1483 int inlined_jsframe_index_;
1484 Handle<JSFunction> function_;
1485 Handle<Context> context_;
1486 List<Handle<ScopeInfo> > nested_scope_chain_;
1487 bool seen_script_scope_;
1490 void RetrieveScopeChain(Scope* scope,
1491 Handle<SharedFunctionInfo> shared_info) {
1492 if (scope != NULL) {
1493 int source_position = shared_info->code()->SourcePosition(frame_->pc());
1494 scope->GetNestedScopeChain(isolate_, &nested_scope_chain_,
1497 // A failed reparse indicates that the preparser has diverged from the
1498 // parser or that the preparse data given to the initial parse has been
1499 // faulty. We fail in debug mode but in release mode we only provide the
1500 // information we get from the context chain but nothing about
1501 // completely stack allocated scopes or stack allocated locals.
1502 // Or it could be due to stack overflow.
1503 DCHECK(isolate_->has_pending_exception());
1508 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
1512 RUNTIME_FUNCTION(Runtime_GetScopeCount) {
1513 HandleScope scope(isolate);
1514 DCHECK(args.length() == 2);
1515 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1516 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1518 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1520 // Get the frame where the debugging is performed.
1521 StackFrame::Id id = UnwrapFrameId(wrapped_id);
1522 JavaScriptFrameIterator it(isolate, id);
1523 JavaScriptFrame* frame = it.frame();
1525 // Count the visible scopes.
1527 for (ScopeIterator it(isolate, frame, 0); !it.Done(); it.Next()) {
1531 return Smi::FromInt(n);
1535 // Returns the list of step-in positions (text offset) in a function of the
1536 // stack frame in a range from the current debug break position to the end
1537 // of the corresponding statement.
1538 RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
1539 HandleScope scope(isolate);
1540 DCHECK(args.length() == 2);
1541 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1542 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1544 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1546 // Get the frame where the debugging is performed.
1547 StackFrame::Id id = UnwrapFrameId(wrapped_id);
1548 JavaScriptFrameIterator frame_it(isolate, id);
1549 RUNTIME_ASSERT(!frame_it.done());
1551 JavaScriptFrame* frame = frame_it.frame();
1553 Handle<JSFunction> fun = Handle<JSFunction>(frame->function());
1554 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared());
1556 if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
1557 return isolate->heap()->undefined_value();
1560 Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
1563 Handle<JSArray> array(isolate->factory()->NewJSArray(10));
1564 // Find the break point where execution has stopped.
1565 BreakLocationIterator break_location_iterator(debug_info,
1566 ALL_BREAK_LOCATIONS);
1568 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
1569 int current_statement_pos = break_location_iterator.statement_position();
1571 while (!break_location_iterator.Done()) {
1573 if (break_location_iterator.pc() > frame->pc()) {
1576 StackFrame::Id break_frame_id = isolate->debug()->break_frame_id();
1577 // The break point is near our pc. Could be a step-in possibility,
1578 // that is currently taken by active debugger call.
1579 if (break_frame_id == StackFrame::NO_ID) {
1580 // We are not stepping.
1583 JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id);
1584 // If our frame is a top frame and we are stepping, we can do step-in
1586 accept = additional_frame_it.frame()->id() == id;
1590 if (break_location_iterator.IsStepInLocation(isolate)) {
1591 Smi* position_value = Smi::FromInt(break_location_iterator.position());
1592 RETURN_FAILURE_ON_EXCEPTION(
1593 isolate, JSObject::SetElement(
1594 array, len, Handle<Object>(position_value, isolate),
1599 // Advance iterator.
1600 break_location_iterator.Next();
1601 if (current_statement_pos != break_location_iterator.statement_position()) {
1609 static const int kScopeDetailsTypeIndex = 0;
1610 static const int kScopeDetailsObjectIndex = 1;
1611 static const int kScopeDetailsSize = 2;
1614 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScopeDetails(
1615 Isolate* isolate, ScopeIterator* it) {
1616 // Calculate the size of the result.
1617 int details_size = kScopeDetailsSize;
1618 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
1620 // Fill in scope details.
1621 details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
1622 Handle<JSObject> scope_object;
1623 ASSIGN_RETURN_ON_EXCEPTION(isolate, scope_object, it->ScopeObject(),
1625 details->set(kScopeDetailsObjectIndex, *scope_object);
1627 return isolate->factory()->NewJSArrayWithElements(details);
1631 // Return an array with scope details
1632 // args[0]: number: break id
1633 // args[1]: number: frame index
1634 // args[2]: number: inlined frame index
1635 // args[3]: number: scope index
1637 // The array returned contains the following information:
1640 RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
1641 HandleScope scope(isolate);
1642 DCHECK(args.length() == 4);
1643 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1644 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1646 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1647 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1648 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
1650 // Get the frame where the debugging is performed.
1651 StackFrame::Id id = UnwrapFrameId(wrapped_id);
1652 JavaScriptFrameIterator frame_it(isolate, id);
1653 JavaScriptFrame* frame = frame_it.frame();
1655 // Find the requested scope.
1657 ScopeIterator it(isolate, frame, inlined_jsframe_index);
1658 for (; !it.Done() && n < index; it.Next()) {
1662 return isolate->heap()->undefined_value();
1664 Handle<JSObject> details;
1665 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
1666 MaterializeScopeDetails(isolate, &it));
1671 // Return an array of scope details
1672 // args[0]: number: break id
1673 // args[1]: number: frame index
1674 // args[2]: number: inlined frame index
1675 // args[3]: boolean: ignore nested scopes
1677 // The array returned contains arrays with the following information:
1680 RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
1681 HandleScope scope(isolate);
1682 DCHECK(args.length() == 3 || args.length() == 4);
1683 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1684 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1686 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1687 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1689 bool ignore_nested_scopes = false;
1690 if (args.length() == 4) {
1691 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
1692 ignore_nested_scopes = flag;
1695 // Get the frame where the debugging is performed.
1696 StackFrame::Id id = UnwrapFrameId(wrapped_id);
1697 JavaScriptFrameIterator frame_it(isolate, id);
1698 JavaScriptFrame* frame = frame_it.frame();
1700 List<Handle<JSObject> > result(4);
1701 ScopeIterator it(isolate, frame, inlined_jsframe_index, ignore_nested_scopes);
1702 for (; !it.Done(); it.Next()) {
1703 Handle<JSObject> details;
1704 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
1705 MaterializeScopeDetails(isolate, &it));
1706 result.Add(details);
1709 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
1710 for (int i = 0; i < result.length(); ++i) {
1711 array->set(i, *result[i]);
1713 return *isolate->factory()->NewJSArrayWithElements(array);
1717 RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
1718 HandleScope scope(isolate);
1719 DCHECK(args.length() == 1);
1722 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1724 // Count the visible scopes.
1726 for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
1730 return Smi::FromInt(n);
1734 RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
1735 HandleScope scope(isolate);
1736 DCHECK(args.length() == 2);
1739 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1740 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
1742 // Find the requested scope.
1744 ScopeIterator it(isolate, fun);
1745 for (; !it.Done() && n < index; it.Next()) {
1749 return isolate->heap()->undefined_value();
1752 Handle<JSObject> details;
1753 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
1754 MaterializeScopeDetails(isolate, &it));
1759 static bool SetScopeVariableValue(ScopeIterator* it, int index,
1760 Handle<String> variable_name,
1761 Handle<Object> new_value) {
1762 for (int n = 0; !it->Done() && n < index; it->Next()) {
1768 return it->SetVariableValue(variable_name, new_value);
1772 // Change variable value in closure or local scope
1773 // args[0]: number or JsFunction: break id or function
1774 // args[1]: number: frame index (when arg[0] is break id)
1775 // args[2]: number: inlined frame index (when arg[0] is break id)
1776 // args[3]: number: scope index
1777 // args[4]: string: variable name
1778 // args[5]: object: new value
1780 // Return true if success and false otherwise
1781 RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
1782 HandleScope scope(isolate);
1783 DCHECK(args.length() == 6);
1786 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
1787 CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
1788 CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
1791 if (args[0]->IsNumber()) {
1792 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1793 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1795 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1796 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1798 // Get the frame where the debugging is performed.
1799 StackFrame::Id id = UnwrapFrameId(wrapped_id);
1800 JavaScriptFrameIterator frame_it(isolate, id);
1801 JavaScriptFrame* frame = frame_it.frame();
1803 ScopeIterator it(isolate, frame, inlined_jsframe_index);
1804 res = SetScopeVariableValue(&it, index, variable_name, new_value);
1806 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1807 ScopeIterator it(isolate, fun);
1808 res = SetScopeVariableValue(&it, index, variable_name, new_value);
1811 return isolate->heap()->ToBoolean(res);
1815 RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
1816 HandleScope scope(isolate);
1817 DCHECK(args.length() == 0);
1820 // Print the scopes for the top frame.
1821 StackFrameLocator locator(isolate);
1822 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
1823 for (ScopeIterator it(isolate, frame, 0); !it.Done(); it.Next()) {
1827 return isolate->heap()->undefined_value();
1831 RUNTIME_FUNCTION(Runtime_GetThreadCount) {
1832 HandleScope scope(isolate);
1833 DCHECK(args.length() == 1);
1834 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1835 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1837 // Count all archived V8 threads.
1839 for (ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
1840 thread != NULL; thread = thread->Next()) {
1844 // Total number of threads is current thread and archived threads.
1845 return Smi::FromInt(n + 1);
1849 static const int kThreadDetailsCurrentThreadIndex = 0;
1850 static const int kThreadDetailsThreadIdIndex = 1;
1851 static const int kThreadDetailsSize = 2;
1853 // Return an array with thread details
1854 // args[0]: number: break id
1855 // args[1]: number: thread index
1857 // The array returned contains the following information:
1858 // 0: Is current thread?
1860 RUNTIME_FUNCTION(Runtime_GetThreadDetails) {
1861 HandleScope scope(isolate);
1862 DCHECK(args.length() == 2);
1863 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1864 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1866 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
1868 // Allocate array for result.
1869 Handle<FixedArray> details =
1870 isolate->factory()->NewFixedArray(kThreadDetailsSize);
1872 // Thread index 0 is current thread.
1874 // Fill the details.
1875 details->set(kThreadDetailsCurrentThreadIndex,
1876 isolate->heap()->true_value());
1877 details->set(kThreadDetailsThreadIdIndex,
1878 Smi::FromInt(ThreadId::Current().ToInteger()));
1880 // Find the thread with the requested index.
1882 ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
1883 while (index != n && thread != NULL) {
1884 thread = thread->Next();
1887 if (thread == NULL) {
1888 return isolate->heap()->undefined_value();
1891 // Fill the details.
1892 details->set(kThreadDetailsCurrentThreadIndex,
1893 isolate->heap()->false_value());
1894 details->set(kThreadDetailsThreadIdIndex,
1895 Smi::FromInt(thread->id().ToInteger()));
1898 // Convert to JS array and return.
1899 return *isolate->factory()->NewJSArrayWithElements(details);
1903 // Sets the disable break state
1904 // args[0]: disable break state
1905 RUNTIME_FUNCTION(Runtime_SetDisableBreak) {
1906 HandleScope scope(isolate);
1907 DCHECK(args.length() == 1);
1908 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
1909 isolate->debug()->set_disable_break(disable_break);
1910 return isolate->heap()->undefined_value();
1914 static bool IsPositionAlignmentCodeCorrect(int alignment) {
1915 return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
1919 RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
1920 HandleScope scope(isolate);
1921 DCHECK(args.length() == 2);
1923 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1924 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
1926 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1927 return isolate->ThrowIllegalOperation();
1929 BreakPositionAlignment alignment =
1930 static_cast<BreakPositionAlignment>(statement_aligned_code);
1932 Handle<SharedFunctionInfo> shared(fun->shared());
1933 // Find the number of break points
1934 Handle<Object> break_locations =
1935 Debug::GetSourceBreakLocations(shared, alignment);
1936 if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
1937 // Return array as JS array
1938 return *isolate->factory()->NewJSArrayWithElements(
1939 Handle<FixedArray>::cast(break_locations));
1943 // Set a break point in a function.
1944 // args[0]: function
1945 // args[1]: number: break source position (within the function source)
1946 // args[2]: number: break point object
1947 RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
1948 HandleScope scope(isolate);
1949 DCHECK(args.length() == 3);
1950 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1951 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1952 RUNTIME_ASSERT(source_position >= function->shared()->start_position() &&
1953 source_position <= function->shared()->end_position());
1954 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
1957 RUNTIME_ASSERT(isolate->debug()->SetBreakPoint(
1958 function, break_point_object_arg, &source_position));
1960 return Smi::FromInt(source_position);
1964 // Changes the state of a break point in a script and returns source position
1965 // where break point was set. NOTE: Regarding performance see the NOTE for
1966 // GetScriptFromScriptData.
1967 // args[0]: script to set break point in
1968 // args[1]: number: break source position (within the script source)
1969 // args[2]: number, breakpoint position alignment
1970 // args[3]: number: break point object
1971 RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
1972 HandleScope scope(isolate);
1973 DCHECK(args.length() == 4);
1974 CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
1975 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1976 RUNTIME_ASSERT(source_position >= 0);
1977 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
1978 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
1980 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1981 return isolate->ThrowIllegalOperation();
1983 BreakPositionAlignment alignment =
1984 static_cast<BreakPositionAlignment>(statement_aligned_code);
1986 // Get the script from the script wrapper.
1987 RUNTIME_ASSERT(wrapper->value()->IsScript());
1988 Handle<Script> script(Script::cast(wrapper->value()));
1991 if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
1992 &source_position, alignment)) {
1993 return isolate->heap()->undefined_value();
1996 return Smi::FromInt(source_position);
2000 // Clear a break point
2001 // args[0]: number: break point object
2002 RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
2003 HandleScope scope(isolate);
2004 DCHECK(args.length() == 1);
2005 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
2007 // Clear break point.
2008 isolate->debug()->ClearBreakPoint(break_point_object_arg);
2010 return isolate->heap()->undefined_value();
2014 // Change the state of break on exceptions.
2015 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
2016 // args[1]: Boolean indicating on/off.
2017 RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
2018 HandleScope scope(isolate);
2019 DCHECK(args.length() == 2);
2020 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
2021 CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
2023 // If the number doesn't match an enum value, the ChangeBreakOnException
2024 // function will default to affecting caught exceptions.
2025 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
2026 // Update break point state.
2027 isolate->debug()->ChangeBreakOnException(type, enable);
2028 return isolate->heap()->undefined_value();
2032 // Returns the state of break on exceptions
2033 // args[0]: boolean indicating uncaught exceptions
2034 RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
2035 HandleScope scope(isolate);
2036 DCHECK(args.length() == 1);
2037 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
2039 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
2040 bool result = isolate->debug()->IsBreakOnException(type);
2041 return Smi::FromInt(result);
2045 // Prepare for stepping
2046 // args[0]: break id for checking execution state
2047 // args[1]: step action from the enumeration StepAction
2048 // args[2]: number of times to perform the step, for step out it is the number
2049 // of frames to step down.
2050 RUNTIME_FUNCTION(Runtime_PrepareStep) {
2051 HandleScope scope(isolate);
2052 DCHECK(args.length() == 4);
2053 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
2054 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
2056 if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
2057 return isolate->Throw(isolate->heap()->illegal_argument_string());
2060 CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]);
2062 StackFrame::Id frame_id;
2063 if (wrapped_frame_id == 0) {
2064 frame_id = StackFrame::NO_ID;
2066 frame_id = UnwrapFrameId(wrapped_frame_id);
2069 // Get the step action and check validity.
2070 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
2071 if (step_action != StepIn && step_action != StepNext &&
2072 step_action != StepOut && step_action != StepInMin &&
2073 step_action != StepMin && step_action != StepFrame) {
2074 return isolate->Throw(isolate->heap()->illegal_argument_string());
2077 if (frame_id != StackFrame::NO_ID && step_action != StepNext &&
2078 step_action != StepMin && step_action != StepOut) {
2079 return isolate->ThrowIllegalOperation();
2082 // Get the number of steps.
2083 int step_count = NumberToInt32(args[2]);
2084 if (step_count < 1) {
2085 return isolate->Throw(isolate->heap()->illegal_argument_string());
2088 // Clear all current stepping setup.
2089 isolate->debug()->ClearStepping();
2092 isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
2093 step_count, frame_id);
2094 return isolate->heap()->undefined_value();
2098 // Clear all stepping set by PrepareStep.
2099 RUNTIME_FUNCTION(Runtime_ClearStepping) {
2100 HandleScope scope(isolate);
2101 DCHECK(args.length() == 0);
2102 isolate->debug()->ClearStepping();
2103 return isolate->heap()->undefined_value();
2107 // Helper function to find or create the arguments object for
2108 // Runtime_DebugEvaluate.
2109 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeArgumentsObject(
2110 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function) {
2111 // Do not materialize the arguments object for eval or top-level code.
2112 // Skip if "arguments" is already taken.
2113 if (!function->shared()->is_function()) return target;
2114 Maybe<bool> maybe = JSReceiver::HasOwnProperty(
2115 target, isolate->factory()->arguments_string());
2116 if (!maybe.has_value) return MaybeHandle<JSObject>();
2117 if (maybe.value) return target;
2119 // FunctionGetArguments can't throw an exception.
2120 Handle<JSObject> arguments =
2121 Handle<JSObject>::cast(Accessors::FunctionGetArguments(function));
2122 Handle<String> arguments_str = isolate->factory()->arguments_string();
2123 RETURN_ON_EXCEPTION(isolate, Runtime::DefineObjectProperty(
2124 target, arguments_str, arguments, NONE),
2130 // Compile and evaluate source for the given context.
2131 static MaybeHandle<Object> DebugEvaluate(Isolate* isolate,
2132 Handle<SharedFunctionInfo> outer_info,
2133 Handle<Context> context,
2134 Handle<Object> context_extension,
2135 Handle<Object> receiver,
2136 Handle<String> source) {
2137 if (context_extension->IsJSObject()) {
2138 Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
2139 Handle<JSFunction> closure(context->closure(), isolate);
2140 context = isolate->factory()->NewWithContext(closure, context, extension);
2143 Handle<JSFunction> eval_fun;
2144 ASSIGN_RETURN_ON_EXCEPTION(isolate, eval_fun,
2145 Compiler::GetFunctionFromEval(
2146 source, outer_info, context, SLOPPY,
2147 NO_PARSE_RESTRICTION, RelocInfo::kNoPosition),
2150 Handle<Object> result;
2151 ASSIGN_RETURN_ON_EXCEPTION(
2152 isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL),
2155 // Skip the global proxy as it has no properties and always delegates to the
2156 // real global object.
2157 if (result->IsJSGlobalProxy()) {
2158 PrototypeIterator iter(isolate, result);
2159 // TODO(verwaest): This will crash when the global proxy is detached.
2160 result = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
2163 // Clear the oneshot breakpoints so that the debugger does not step further.
2164 isolate->debug()->ClearStepping();
2169 static Handle<JSObject> NewJSObjectWithNullProto(Isolate* isolate) {
2170 Handle<JSObject> result =
2171 isolate->factory()->NewJSObject(isolate->object_function());
2172 Handle<Map> new_map =
2173 Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto");
2174 new_map->SetPrototype(isolate->factory()->null_value());
2175 JSObject::MigrateToMap(result, new_map);
2180 // Evaluate a piece of JavaScript in the context of a stack frame for
2181 // debugging. Things that need special attention are:
2182 // - Parameters and stack-allocated locals need to be materialized. Altered
2183 // values need to be written back to the stack afterwards.
2184 // - The arguments object needs to materialized.
2185 RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
2186 HandleScope scope(isolate);
2188 // Check the execution state and decode arguments frame and source to be
2190 DCHECK(args.length() == 6);
2191 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
2192 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
2194 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
2195 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
2196 CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
2197 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
2198 CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 5);
2200 // Handle the processing of break.
2201 DisableBreak disable_break_scope(isolate->debug(), disable_break);
2203 // Get the frame where the debugging is performed.
2204 StackFrame::Id id = UnwrapFrameId(wrapped_id);
2205 JavaScriptFrameIterator it(isolate, id);
2206 JavaScriptFrame* frame = it.frame();
2207 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
2208 Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
2209 Handle<SharedFunctionInfo> outer_info(function->shared());
2211 // Traverse the saved contexts chain to find the active context for the
2213 SaveContext* save = FindSavedContextForFrame(isolate, frame);
2215 SaveContext savex(isolate);
2216 isolate->set_context(*(save->context()));
2218 // Materialize stack locals and the arguments object.
2219 Handle<JSObject> materialized = NewJSObjectWithNullProto(isolate);
2221 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2222 isolate, materialized,
2223 MaterializeStackLocalsWithFrameInspector(isolate, materialized, function,
2226 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2227 isolate, materialized,
2228 MaterializeArgumentsObject(isolate, materialized, function));
2230 // At this point, the lookup chain may look like this:
2231 // [inner context] -> [function stack]+[function context] -> [outer context]
2232 // The function stack is not an actual context, it complements the function
2233 // context. In order to have the same lookup chain when debug-evaluating,
2234 // we materialize the stack and insert it into the context chain as a
2235 // with-context before the function context.
2236 // [inner context] -> [with context] -> [function context] -> [outer context]
2237 // Ordering the with-context before the function context forces a dynamic
2238 // lookup instead of a static lookup that could fail as the scope info is
2239 // outdated and may expect variables to still be stack-allocated.
2240 // Afterwards, we write changes to the with-context back to the stack
2241 // and remove it from the context chain.
2242 // This could cause lookup failures if debug-evaluate creates a closure that
2243 // uses this temporary context chain.
2245 Handle<Context> eval_context(Context::cast(frame_inspector.GetContext()));
2246 DCHECK(!eval_context.is_null());
2247 Handle<Context> function_context = eval_context;
2248 Handle<Context> outer_context(function->context(), isolate);
2249 Handle<Context> inner_context;
2250 // We iterate to find the function's context. If the function has no
2251 // context-allocated variables, we iterate until we hit the outer context.
2252 while (!function_context->IsFunctionContext() &&
2253 !function_context->IsScriptContext() &&
2254 !function_context.is_identical_to(outer_context)) {
2255 inner_context = function_context;
2256 function_context = Handle<Context>(function_context->previous(), isolate);
2259 Handle<Context> materialized_context = isolate->factory()->NewWithContext(
2260 function, function_context, materialized);
2262 if (inner_context.is_null()) {
2263 // No inner context. The with-context is now inner-most.
2264 eval_context = materialized_context;
2266 inner_context->set_previous(*materialized_context);
2269 Handle<Object> receiver(frame->receiver(), isolate);
2270 MaybeHandle<Object> maybe_result = DebugEvaluate(
2271 isolate, outer_info, eval_context, context_extension, receiver, source);
2273 // Remove with-context if it was inserted in between.
2274 if (!inner_context.is_null()) inner_context->set_previous(*function_context);
2276 Handle<Object> result;
2277 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result);
2279 // Write back potential changes to materialized stack locals to the stack.
2280 UpdateStackLocalsFromMaterializedObject(isolate, materialized, function,
2281 frame, inlined_jsframe_index);
2287 RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
2288 HandleScope scope(isolate);
2290 // Check the execution state and decode arguments frame and source to be
2292 DCHECK(args.length() == 4);
2293 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
2294 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
2296 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
2297 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
2298 CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 3);
2300 // Handle the processing of break.
2301 DisableBreak disable_break_scope(isolate->debug(), disable_break);
2303 // Enter the top context from before the debugger was invoked.
2304 SaveContext save(isolate);
2305 SaveContext* top = &save;
2306 while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
2310 isolate->set_context(*top->context());
2313 // Get the native context now set to the top context from before the
2314 // debugger was invoked.
2315 Handle<Context> context = isolate->native_context();
2316 Handle<JSObject> receiver(context->global_proxy());
2317 Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
2318 Handle<Object> result;
2319 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2320 isolate, result, DebugEvaluate(isolate, outer_info, context,
2321 context_extension, receiver, source));
2326 RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
2327 HandleScope scope(isolate);
2328 DCHECK(args.length() == 0);
2330 DebugScope debug_scope(isolate->debug());
2331 // Fill the script objects.
2332 Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
2334 // Convert the script objects to proper JS objects.
2335 for (int i = 0; i < instances->length(); i++) {
2336 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
2337 // Get the script wrapper in a local handle before calling GetScriptWrapper,
2339 // instances->set(i, *GetScriptWrapper(script))
2340 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
2341 // already have dereferenced the instances handle.
2342 Handle<JSObject> wrapper = Script::GetWrapper(script);
2343 instances->set(i, *wrapper);
2346 // Return result as a JS array.
2347 Handle<JSObject> result =
2348 isolate->factory()->NewJSObject(isolate->array_function());
2349 JSArray::SetContent(Handle<JSArray>::cast(result), instances);
2354 // Helper function used by Runtime_DebugReferencedBy below.
2355 static int DebugReferencedBy(HeapIterator* iterator, JSObject* target,
2356 Object* instance_filter, int max_references,
2357 FixedArray* instances, int instances_size,
2358 JSFunction* arguments_function) {
2359 Isolate* isolate = target->GetIsolate();
2360 SealHandleScope shs(isolate);
2361 DisallowHeapAllocation no_allocation;
2363 // Iterate the heap.
2365 JSObject* last = NULL;
2366 HeapObject* heap_obj = NULL;
2367 while (((heap_obj = iterator->next()) != NULL) &&
2368 (max_references == 0 || count < max_references)) {
2369 // Only look at all JSObjects.
2370 if (heap_obj->IsJSObject()) {
2371 // Skip context extension objects and argument arrays as these are
2372 // checked in the context of functions using them.
2373 JSObject* obj = JSObject::cast(heap_obj);
2374 if (obj->IsJSContextExtensionObject() ||
2375 obj->map()->constructor() == arguments_function) {
2379 // Check if the JS object has a reference to the object looked for.
2380 if (obj->ReferencesObject(target)) {
2381 // Check instance filter if supplied. This is normally used to avoid
2382 // references from mirror objects (see Runtime_IsInPrototypeChain).
2383 if (!instance_filter->IsUndefined()) {
2384 for (PrototypeIterator iter(isolate, obj); !iter.IsAtEnd();
2386 if (iter.GetCurrent() == instance_filter) {
2387 obj = NULL; // Don't add this object.
2394 // Valid reference found add to instance array if supplied an update
2396 if (instances != NULL && count < instances_size) {
2397 instances->set(count, obj);
2406 // Check for circular reference only. This can happen when the object is only
2407 // referenced from mirrors and has a circular reference in which case the
2408 // object is not really alive and would have been garbage collected if not
2409 // referenced from the mirror.
2410 if (count == 1 && last == target) {
2414 // Return the number of referencing objects found.
2419 // Scan the heap for objects with direct references to an object
2420 // args[0]: the object to find references to
2421 // args[1]: constructor function for instances to exclude (Mirror)
2422 // args[2]: the the maximum number of objects to return
2423 RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
2424 HandleScope scope(isolate);
2425 DCHECK(args.length() == 3);
2427 // Check parameters.
2428 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
2429 CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1);
2430 RUNTIME_ASSERT(instance_filter->IsUndefined() ||
2431 instance_filter->IsJSObject());
2432 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
2433 RUNTIME_ASSERT(max_references >= 0);
2436 // Get the constructor function for context extension and arguments array.
2437 Handle<JSFunction> arguments_function(
2438 JSFunction::cast(isolate->sloppy_arguments_map()->constructor()));
2440 // Get the number of referencing objects.
2442 // First perform a full GC in order to avoid dead objects and to make the heap
2444 Heap* heap = isolate->heap();
2445 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
2447 HeapIterator heap_iterator(heap);
2448 count = DebugReferencedBy(&heap_iterator, *target, *instance_filter,
2449 max_references, NULL, 0, *arguments_function);
2452 // Allocate an array to hold the result.
2453 Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
2455 // Fill the referencing objects.
2457 HeapIterator heap_iterator(heap);
2458 count = DebugReferencedBy(&heap_iterator, *target, *instance_filter,
2459 max_references, *instances, count,
2460 *arguments_function);
2463 // Return result as JS array.
2464 Handle<JSFunction> constructor = isolate->array_function();
2466 Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
2467 JSArray::SetContent(Handle<JSArray>::cast(result), instances);
2472 // Helper function used by Runtime_DebugConstructedBy below.
2473 static int DebugConstructedBy(HeapIterator* iterator, JSFunction* constructor,
2474 int max_references, FixedArray* instances,
2475 int instances_size) {
2476 DisallowHeapAllocation no_allocation;
2478 // Iterate the heap.
2480 HeapObject* heap_obj = NULL;
2481 while (((heap_obj = iterator->next()) != NULL) &&
2482 (max_references == 0 || count < max_references)) {
2483 // Only look at all JSObjects.
2484 if (heap_obj->IsJSObject()) {
2485 JSObject* obj = JSObject::cast(heap_obj);
2486 if (obj->map()->constructor() == constructor) {
2487 // Valid reference found add to instance array if supplied an update
2489 if (instances != NULL && count < instances_size) {
2490 instances->set(count, obj);
2497 // Return the number of referencing objects found.
2502 // Scan the heap for objects constructed by a specific function.
2503 // args[0]: the constructor to find instances of
2504 // args[1]: the the maximum number of objects to return
2505 RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
2506 HandleScope scope(isolate);
2507 DCHECK(args.length() == 2);
2510 // Check parameters.
2511 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
2512 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
2513 RUNTIME_ASSERT(max_references >= 0);
2515 // Get the number of referencing objects.
2517 // First perform a full GC in order to avoid dead objects and to make the heap
2519 Heap* heap = isolate->heap();
2520 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
2522 HeapIterator heap_iterator(heap);
2523 count = DebugConstructedBy(&heap_iterator, *constructor, max_references,
2527 // Allocate an array to hold the result.
2528 Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
2530 // Fill the referencing objects.
2532 HeapIterator heap_iterator2(heap);
2533 count = DebugConstructedBy(&heap_iterator2, *constructor, max_references,
2537 // Return result as JS array.
2538 Handle<JSFunction> array_function = isolate->array_function();
2539 Handle<JSObject> result = isolate->factory()->NewJSObject(array_function);
2540 JSArray::SetContent(Handle<JSArray>::cast(result), instances);
2545 // Find the effective prototype object as returned by __proto__.
2546 // args[0]: the object to find the prototype for.
2547 RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
2548 HandleScope shs(isolate);
2549 DCHECK(args.length() == 1);
2550 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
2551 return *Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
2555 // Patches script source (should be called upon BeforeCompile event).
2556 RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
2557 HandleScope scope(isolate);
2558 DCHECK(args.length() == 2);
2560 CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
2561 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
2563 RUNTIME_ASSERT(script_wrapper->value()->IsScript());
2564 Handle<Script> script(Script::cast(script_wrapper->value()));
2566 int compilation_state = script->compilation_state();
2567 RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
2568 script->set_source(*source);
2570 return isolate->heap()->undefined_value();
2574 RUNTIME_FUNCTION(Runtime_DebugDisassembleFunction) {
2575 HandleScope scope(isolate);
2577 DCHECK(args.length() == 1);
2578 // Get the function and make sure it is compiled.
2579 CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
2580 if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
2581 return isolate->heap()->exception();
2583 OFStream os(stdout);
2584 func->code()->Print(os);
2587 return isolate->heap()->undefined_value();
2591 RUNTIME_FUNCTION(Runtime_DebugDisassembleConstructor) {
2592 HandleScope scope(isolate);
2594 DCHECK(args.length() == 1);
2595 // Get the function and make sure it is compiled.
2596 CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
2597 if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
2598 return isolate->heap()->exception();
2600 OFStream os(stdout);
2601 func->shared()->construct_stub()->Print(os);
2604 return isolate->heap()->undefined_value();
2608 RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
2609 SealHandleScope shs(isolate);
2610 DCHECK(args.length() == 1);
2612 CONVERT_ARG_CHECKED(JSFunction, f, 0);
2613 return f->shared()->inferred_name();
2617 // A testing entry. Returns statement position which is the closest to
2619 RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
2620 HandleScope scope(isolate);
2621 CHECK(isolate->debug()->live_edit_enabled());
2622 DCHECK(args.length() == 2);
2623 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2624 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
2626 Handle<Code> code(function->code(), isolate);
2628 if (code->kind() != Code::FUNCTION &&
2629 code->kind() != Code::OPTIMIZED_FUNCTION) {
2630 return isolate->heap()->undefined_value();
2633 RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
2635 int distance = kMaxInt;
2636 while (!it.done()) {
2637 int statement_position = static_cast<int>(it.rinfo()->data());
2638 // Check if this break point is closer that what was previously found.
2639 if (source_position <= statement_position &&
2640 statement_position - source_position < distance) {
2642 static_cast<int>(it.rinfo()->pc() - code->instruction_start());
2643 distance = statement_position - source_position;
2644 // Check whether we can't get any closer.
2645 if (distance == 0) break;
2650 return Smi::FromInt(closest_pc);
2654 // Calls specified function with or without entering the debugger.
2655 // This is used in unit tests to run code as if debugger is entered or simply
2656 // to have a stack with C++ frame in the middle.
2657 RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
2658 HandleScope scope(isolate);
2659 DCHECK(args.length() == 2);
2660 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2661 CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
2663 MaybeHandle<Object> maybe_result;
2664 if (without_debugger) {
2665 maybe_result = Execution::Call(isolate, function,
2666 handle(function->global_proxy()), 0, NULL);
2668 DebugScope debug_scope(isolate->debug());
2669 maybe_result = Execution::Call(isolate, function,
2670 handle(function->global_proxy()), 0, NULL);
2672 Handle<Object> result;
2673 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result);
2678 RUNTIME_FUNCTION(Runtime_GetDebugContext) {
2679 HandleScope scope(isolate);
2680 DCHECK(args.length() == 0);
2681 Handle<Context> context = isolate->debug()->GetDebugContext();
2682 context->set_security_token(isolate->native_context()->security_token());
2683 return context->global_proxy();
2688 // Presently, it only does a full GC.
2689 RUNTIME_FUNCTION(Runtime_CollectGarbage) {
2690 SealHandleScope shs(isolate);
2691 DCHECK(args.length() == 1);
2692 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
2693 return isolate->heap()->undefined_value();
2697 // Gets the current heap usage.
2698 RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
2699 SealHandleScope shs(isolate);
2700 DCHECK(args.length() == 0);
2701 int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
2702 if (!Smi::IsValid(usage)) {
2703 return *isolate->factory()->NewNumberFromInt(usage);
2705 return Smi::FromInt(usage);
2709 // Finds the script object from the script data. NOTE: This operation uses
2710 // heap traversal to find the function generated for the source position
2711 // for the requested break point. For lazily compiled functions several heap
2712 // traversals might be required rendering this operation as a rather slow
2713 // operation. However for setting break points which is normally done through
2714 // some kind of user interaction the performance is not crucial.
2715 RUNTIME_FUNCTION(Runtime_GetScript) {
2716 HandleScope scope(isolate);
2717 DCHECK(args.length() == 1);
2718 CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
2720 Handle<Script> found;
2721 Heap* heap = isolate->heap();
2723 HeapIterator iterator(heap);
2724 HeapObject* obj = NULL;
2725 while ((obj = iterator.next()) != NULL) {
2726 if (!obj->IsScript()) continue;
2727 Script* script = Script::cast(obj);
2728 if (!script->name()->IsString()) continue;
2729 String* name = String::cast(script->name());
2730 if (name->Equals(*script_name)) {
2731 found = Handle<Script>(script, isolate);
2737 if (found.is_null()) return heap->undefined_value();
2738 return *Script::GetWrapper(found);
2742 // Check whether debugger and is about to step into the callback that is passed
2743 // to a built-in function such as Array.forEach.
2744 RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) {
2745 DCHECK(args.length() == 1);
2746 Debug* debug = isolate->debug();
2747 if (!debug->is_active() || !debug->IsStepping() ||
2748 debug->last_step_action() != StepIn) {
2749 return isolate->heap()->false_value();
2751 CONVERT_ARG_CHECKED(Object, callback, 0);
2752 // We do not step into the callback if it's a builtin or not even a function.
2753 return isolate->heap()->ToBoolean(callback->IsJSFunction() &&
2754 !JSFunction::cast(callback)->IsBuiltin());
2758 // Set one shot breakpoints for the callback function that is passed to a
2759 // built-in function such as Array.forEach to enable stepping into the callback.
2760 RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
2761 DCHECK(args.length() == 1);
2762 Debug* debug = isolate->debug();
2763 if (!debug->IsStepping()) return isolate->heap()->undefined_value();
2765 HandleScope scope(isolate);
2766 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
2767 RUNTIME_ASSERT(object->IsJSFunction() || object->IsJSGeneratorObject());
2768 Handle<JSFunction> fun;
2769 if (object->IsJSFunction()) {
2770 fun = Handle<JSFunction>::cast(object);
2772 fun = Handle<JSFunction>(
2773 Handle<JSGeneratorObject>::cast(object)->function(), isolate);
2775 // When leaving the function, step out has been activated, but not performed
2776 // if we do not leave the builtin. To be able to step into the function
2777 // again, we need to clear the step out at this point.
2778 debug->ClearStepOut();
2779 debug->FloodWithOneShot(fun);
2780 return isolate->heap()->undefined_value();
2784 RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
2785 DCHECK(args.length() == 1);
2786 HandleScope scope(isolate);
2787 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
2788 isolate->PushPromise(promise);
2789 return isolate->heap()->undefined_value();
2793 RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
2794 DCHECK(args.length() == 0);
2795 SealHandleScope shs(isolate);
2796 isolate->PopPromise();
2797 return isolate->heap()->undefined_value();
2801 RUNTIME_FUNCTION(Runtime_DebugPromiseEvent) {
2802 DCHECK(args.length() == 1);
2803 HandleScope scope(isolate);
2804 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
2805 isolate->debug()->OnPromiseEvent(data);
2806 return isolate->heap()->undefined_value();
2810 RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) {
2811 DCHECK(args.length() == 1);
2812 HandleScope scope(isolate);
2813 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
2814 isolate->debug()->OnAsyncTaskEvent(data);
2815 return isolate->heap()->undefined_value();
2819 RUNTIME_FUNCTION(RuntimeReference_DebugIsActive) {
2820 SealHandleScope shs(isolate);
2821 return Smi::FromInt(isolate->debug()->is_active());
2825 RUNTIME_FUNCTION(RuntimeReference_DebugBreakInOptimizedCode) {
2830 } // namespace v8::internal