• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4  
5  #include "src/runtime/runtime-utils.h"
6  
7  #include "src/arguments.h"
8  #include "src/compiler.h"
9  #include "src/debug/debug-coverage.h"
10  #include "src/debug/debug-evaluate.h"
11  #include "src/debug/debug-frames.h"
12  #include "src/debug/debug-scopes.h"
13  #include "src/debug/debug.h"
14  #include "src/debug/liveedit.h"
15  #include "src/frames-inl.h"
16  #include "src/globals.h"
17  #include "src/interpreter/bytecodes.h"
18  #include "src/interpreter/interpreter.h"
19  #include "src/isolate-inl.h"
20  #include "src/runtime/runtime.h"
21  #include "src/wasm/wasm-module.h"
22  #include "src/wasm/wasm-objects.h"
23  
24  namespace v8 {
25  namespace internal {
26  
RUNTIME_FUNCTION(Runtime_DebugBreak)27  RUNTIME_FUNCTION(Runtime_DebugBreak) {
28    SealHandleScope shs(isolate);
29    DCHECK_EQ(1, args.length());
30    CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
31    HandleScope scope(isolate);
32    ReturnValueScope result_scope(isolate->debug());
33    isolate->debug()->set_return_value(*value);
34  
35    // Get the top-most JavaScript frame.
36    JavaScriptFrameIterator it(isolate);
37    isolate->debug()->Break(it.frame());
38    return isolate->debug()->return_value();
39  }
40  
RUNTIME_FUNCTION(Runtime_DebugBreakOnBytecode)41  RUNTIME_FUNCTION(Runtime_DebugBreakOnBytecode) {
42    SealHandleScope shs(isolate);
43    DCHECK_EQ(1, args.length());
44    CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
45    HandleScope scope(isolate);
46    ReturnValueScope result_scope(isolate->debug());
47    isolate->debug()->set_return_value(*value);
48  
49    // Get the top-most JavaScript frame.
50    JavaScriptFrameIterator it(isolate);
51    isolate->debug()->Break(it.frame());
52  
53    // Return the handler from the original bytecode array.
54    DCHECK(it.frame()->is_interpreted());
55    InterpretedFrame* interpreted_frame =
56        reinterpret_cast<InterpretedFrame*>(it.frame());
57    SharedFunctionInfo* shared = interpreted_frame->function()->shared();
58    BytecodeArray* bytecode_array = shared->bytecode_array();
59    int bytecode_offset = interpreted_frame->GetBytecodeOffset();
60    interpreter::Bytecode bytecode =
61        interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
62    return isolate->interpreter()->GetBytecodeHandler(
63        bytecode, interpreter::OperandScale::kSingle);
64  }
65  
66  
RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement)67  RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
68    SealHandleScope shs(isolate);
69    DCHECK_EQ(0, args.length());
70    if (isolate->debug()->break_points_active()) {
71      isolate->debug()->HandleDebugBreak();
72    }
73    return isolate->heap()->undefined_value();
74  }
75  
76  
77  // Adds a JavaScript function as a debug event listener.
78  // args[0]: debug event listener function to set or null or undefined for
79  //          clearing the event listener function
80  // args[1]: object supplied during callback
RUNTIME_FUNCTION(Runtime_SetDebugEventListener)81  RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
82    SealHandleScope shs(isolate);
83    DCHECK_EQ(2, args.length());
84    CHECK(args[0]->IsJSFunction() || args[0]->IsNullOrUndefined(isolate));
85    CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
86    CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
87    if (callback->IsJSFunction()) {
88      JavaScriptDebugDelegate* delegate = new JavaScriptDebugDelegate(
89          isolate, Handle<JSFunction>::cast(callback), data);
90      isolate->debug()->SetDebugDelegate(delegate, true);
91    } else {
92      isolate->debug()->SetDebugDelegate(nullptr, false);
93    }
94    return isolate->heap()->undefined_value();
95  }
96  
97  
RUNTIME_FUNCTION(Runtime_ScheduleBreak)98  RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
99    SealHandleScope shs(isolate);
100    DCHECK_EQ(0, args.length());
101    isolate->stack_guard()->RequestDebugBreak();
102    return isolate->heap()->undefined_value();
103  }
104  
105  
DebugGetProperty(LookupIterator * it,bool * has_caught=NULL)106  static Handle<Object> DebugGetProperty(LookupIterator* it,
107                                         bool* has_caught = NULL) {
108    for (; it->IsFound(); it->Next()) {
109      switch (it->state()) {
110        case LookupIterator::NOT_FOUND:
111        case LookupIterator::TRANSITION:
112          UNREACHABLE();
113        case LookupIterator::ACCESS_CHECK:
114          // Ignore access checks.
115          break;
116        case LookupIterator::INTEGER_INDEXED_EXOTIC:
117        case LookupIterator::INTERCEPTOR:
118        case LookupIterator::JSPROXY:
119          return it->isolate()->factory()->undefined_value();
120        case LookupIterator::ACCESSOR: {
121          Handle<Object> accessors = it->GetAccessors();
122          if (!accessors->IsAccessorInfo()) {
123            return it->isolate()->factory()->undefined_value();
124          }
125          MaybeHandle<Object> maybe_result =
126              JSObject::GetPropertyWithAccessor(it);
127          Handle<Object> result;
128          if (!maybe_result.ToHandle(&result)) {
129            result = handle(it->isolate()->pending_exception(), it->isolate());
130            it->isolate()->clear_pending_exception();
131            if (has_caught != NULL) *has_caught = true;
132          }
133          return result;
134        }
135  
136        case LookupIterator::DATA:
137          return it->GetDataValue();
138      }
139    }
140  
141    return it->isolate()->factory()->undefined_value();
142  }
143  
144  template <class IteratorType>
GetIteratorInternalProperties(Isolate * isolate,Handle<IteratorType> object)145  static MaybeHandle<JSArray> GetIteratorInternalProperties(
146      Isolate* isolate, Handle<IteratorType> object) {
147    Factory* factory = isolate->factory();
148    Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
149    CHECK(iterator->kind()->IsSmi());
150    const char* kind = NULL;
151    switch (Smi::cast(iterator->kind())->value()) {
152      case IteratorType::kKindKeys:
153        kind = "keys";
154        break;
155      case IteratorType::kKindValues:
156        kind = "values";
157        break;
158      case IteratorType::kKindEntries:
159        kind = "entries";
160        break;
161      default:
162        UNREACHABLE();
163    }
164  
165    Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
166    Handle<String> has_more =
167        factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
168    result->set(0, *has_more);
169    result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
170  
171    Handle<String> index =
172        factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
173    result->set(2, *index);
174    result->set(3, iterator->index());
175  
176    Handle<String> iterator_kind =
177        factory->NewStringFromAsciiChecked("[[IteratorKind]]");
178    result->set(4, *iterator_kind);
179    Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
180    result->set(5, *kind_str);
181    return factory->NewJSArrayWithElements(result);
182  }
183  
184  
GetInternalProperties(Isolate * isolate,Handle<Object> object)185  MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
186                                                      Handle<Object> object) {
187    Factory* factory = isolate->factory();
188    if (object->IsJSBoundFunction()) {
189      Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
190  
191      Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
192      Handle<String> target =
193          factory->NewStringFromAsciiChecked("[[TargetFunction]]");
194      result->set(0, *target);
195      result->set(1, function->bound_target_function());
196  
197      Handle<String> bound_this =
198          factory->NewStringFromAsciiChecked("[[BoundThis]]");
199      result->set(2, *bound_this);
200      result->set(3, function->bound_this());
201  
202      Handle<String> bound_args =
203          factory->NewStringFromAsciiChecked("[[BoundArgs]]");
204      result->set(4, *bound_args);
205      Handle<FixedArray> bound_arguments =
206          factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
207      Handle<JSArray> arguments_array =
208          factory->NewJSArrayWithElements(bound_arguments);
209      result->set(5, *arguments_array);
210      return factory->NewJSArrayWithElements(result);
211    } else if (object->IsJSMapIterator()) {
212      Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
213      return GetIteratorInternalProperties(isolate, iterator);
214    } else if (object->IsJSSetIterator()) {
215      Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
216      return GetIteratorInternalProperties(isolate, iterator);
217    } else if (object->IsJSGeneratorObject()) {
218      Handle<JSGeneratorObject> generator =
219          Handle<JSGeneratorObject>::cast(object);
220  
221      const char* status = "suspended";
222      if (generator->is_closed()) {
223        status = "closed";
224      } else if (generator->is_executing()) {
225        status = "running";
226      } else {
227        DCHECK(generator->is_suspended());
228      }
229  
230      Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
231      Handle<String> generator_status =
232          factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
233      result->set(0, *generator_status);
234      Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
235      result->set(1, *status_str);
236  
237      Handle<String> function =
238          factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
239      result->set(2, *function);
240      result->set(3, generator->function());
241  
242      Handle<String> receiver =
243          factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
244      result->set(4, *receiver);
245      result->set(5, generator->receiver());
246      return factory->NewJSArrayWithElements(result);
247    } else if (object->IsJSPromise()) {
248      Handle<JSPromise> promise = Handle<JSPromise>::cast(object);
249      const char* status = JSPromise::Status(promise->status());
250      Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
251      Handle<String> promise_status =
252          factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
253      result->set(0, *promise_status);
254      Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
255      result->set(1, *status_str);
256  
257      Handle<Object> value_obj(promise->result(), isolate);
258      Handle<String> promise_value =
259          factory->NewStringFromAsciiChecked("[[PromiseValue]]");
260      result->set(2, *promise_value);
261      result->set(3, *value_obj);
262      return factory->NewJSArrayWithElements(result);
263    } else if (object->IsJSProxy()) {
264      Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object);
265      Handle<FixedArray> result = factory->NewFixedArray(3 * 2);
266  
267      Handle<String> handler_str =
268          factory->NewStringFromAsciiChecked("[[Handler]]");
269      result->set(0, *handler_str);
270      result->set(1, js_proxy->handler());
271  
272      Handle<String> target_str =
273          factory->NewStringFromAsciiChecked("[[Target]]");
274      result->set(2, *target_str);
275      result->set(3, js_proxy->target());
276  
277      Handle<String> is_revoked_str =
278          factory->NewStringFromAsciiChecked("[[IsRevoked]]");
279      result->set(4, *is_revoked_str);
280      result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked()));
281      return factory->NewJSArrayWithElements(result);
282    } else if (object->IsJSValue()) {
283      Handle<JSValue> js_value = Handle<JSValue>::cast(object);
284  
285      Handle<FixedArray> result = factory->NewFixedArray(2);
286      Handle<String> primitive_value =
287          factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
288      result->set(0, *primitive_value);
289      result->set(1, js_value->value());
290      return factory->NewJSArrayWithElements(result);
291    }
292    return factory->NewJSArray(0);
293  }
294  
295  
RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties)296  RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
297    HandleScope scope(isolate);
298    DCHECK_EQ(1, args.length());
299    CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
300    RETURN_RESULT_OR_FAILURE(isolate,
301                             Runtime::GetInternalProperties(isolate, obj));
302  }
303  
304  
305  // Get debugger related details for an object property, in the following format:
306  // 0: Property value
307  // 1: Property details
308  // 2: Property value is exception
309  // 3: Getter function if defined
310  // 4: Setter function if defined
311  // Items 2-4 are only filled if the property has either a getter or a setter.
RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails)312  RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
313    HandleScope scope(isolate);
314    DCHECK_EQ(2, args.length());
315    CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
316    CONVERT_ARG_HANDLE_CHECKED(Object, name_obj, 1);
317  
318    // Convert the {name_obj} to a Name.
319    Handle<Name> name;
320    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
321                                       Object::ToName(isolate, name_obj));
322  
323    // Make sure to set the current context to the context before the debugger was
324    // entered (if the debugger is entered). The reason for switching context here
325    // is that for some property lookups (accessors and interceptors) callbacks
326    // into the embedding application can occour, and the embedding application
327    // could have the assumption that its own native context is the current
328    // context and not some internal debugger context.
329    SaveContext save(isolate);
330    if (isolate->debug()->in_debug_scope()) {
331      isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
332    }
333  
334    // Check if the name is trivially convertible to an index and get the element
335    // if so.
336    uint32_t index;
337    // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
338    // this special case.
339    if (name->AsArrayIndex(&index)) {
340      Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
341      Handle<Object> element_or_char;
342      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
343          isolate, element_or_char, JSReceiver::GetElement(isolate, obj, index));
344      details->set(0, *element_or_char);
345      details->set(1, PropertyDetails::Empty().AsSmi());
346      return *isolate->factory()->NewJSArrayWithElements(details);
347    }
348  
349    LookupIterator it(obj, name, LookupIterator::OWN);
350    bool has_caught = false;
351    Handle<Object> value = DebugGetProperty(&it, &has_caught);
352    if (!it.IsFound()) return isolate->heap()->undefined_value();
353  
354    Handle<Object> maybe_pair;
355    if (it.state() == LookupIterator::ACCESSOR) {
356      maybe_pair = it.GetAccessors();
357    }
358  
359    // If the callback object is a fixed array then it contains JavaScript
360    // getter and/or setter.
361    bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
362    Handle<FixedArray> details =
363        isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
364    details->set(0, *value);
365    // TODO(verwaest): Get rid of this random way of handling interceptors.
366    PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
367                            ? PropertyDetails::Empty()
368                            : it.property_details();
369    details->set(1, d.AsSmi());
370    details->set(
371        2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
372    if (has_js_accessors) {
373      Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_pair);
374      details->set(3, isolate->heap()->ToBoolean(has_caught));
375      Handle<Object> getter =
376          AccessorPair::GetComponent(accessors, ACCESSOR_GETTER);
377      Handle<Object> setter =
378          AccessorPair::GetComponent(accessors, ACCESSOR_SETTER);
379      details->set(4, *getter);
380      details->set(5, *setter);
381    }
382  
383    return *isolate->factory()->NewJSArrayWithElements(details);
384  }
385  
386  
RUNTIME_FUNCTION(Runtime_DebugGetProperty)387  RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
388    HandleScope scope(isolate);
389  
390    DCHECK_EQ(2, args.length());
391  
392    CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
393    CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
394  
395    LookupIterator it(obj, name);
396    return *DebugGetProperty(&it);
397  }
398  
399  // Return the property kind calculated from the property details.
400  // args[0]: smi with property details.
RUNTIME_FUNCTION(Runtime_DebugPropertyKindFromDetails)401  RUNTIME_FUNCTION(Runtime_DebugPropertyKindFromDetails) {
402    SealHandleScope shs(isolate);
403    DCHECK_EQ(1, args.length());
404    CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
405    return Smi::FromInt(static_cast<int>(details.kind()));
406  }
407  
408  
409  // Return the property attribute calculated from the property details.
410  // args[0]: smi with property details.
RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails)411  RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
412    SealHandleScope shs(isolate);
413    DCHECK_EQ(1, args.length());
414    CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
415    return Smi::FromInt(static_cast<int>(details.attributes()));
416  }
417  
418  
RUNTIME_FUNCTION(Runtime_CheckExecutionState)419  RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
420    SealHandleScope shs(isolate);
421    DCHECK_EQ(1, args.length());
422    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
423    CHECK(isolate->debug()->CheckExecutionState(break_id));
424    return isolate->heap()->true_value();
425  }
426  
427  
RUNTIME_FUNCTION(Runtime_GetFrameCount)428  RUNTIME_FUNCTION(Runtime_GetFrameCount) {
429    HandleScope scope(isolate);
430    DCHECK_EQ(1, args.length());
431    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
432    CHECK(isolate->debug()->CheckExecutionState(break_id));
433  
434    // Count all frames which are relevant to debugging stack trace.
435    int n = 0;
436    StackFrame::Id id = isolate->debug()->break_frame_id();
437    if (id == StackFrame::NO_ID) {
438      // If there is no JavaScript stack frame count is 0.
439      return Smi::kZero;
440    }
441  
442    List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
443    for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) {
444      frames.Clear();
445      it.frame()->Summarize(&frames);
446      for (int i = frames.length() - 1; i >= 0; i--) {
447        // Omit functions from native and extension scripts.
448        if (frames[i].is_subject_to_debugging()) n++;
449      }
450    }
451    return Smi::FromInt(n);
452  }
453  
454  static const int kFrameDetailsFrameIdIndex = 0;
455  static const int kFrameDetailsReceiverIndex = 1;
456  static const int kFrameDetailsFunctionIndex = 2;
457  static const int kFrameDetailsScriptIndex = 3;
458  static const int kFrameDetailsArgumentCountIndex = 4;
459  static const int kFrameDetailsLocalCountIndex = 5;
460  static const int kFrameDetailsSourcePositionIndex = 6;
461  static const int kFrameDetailsConstructCallIndex = 7;
462  static const int kFrameDetailsAtReturnIndex = 8;
463  static const int kFrameDetailsFlagsIndex = 9;
464  static const int kFrameDetailsFirstDynamicIndex = 10;
465  
466  // Return an array with frame details
467  // args[0]: number: break id
468  // args[1]: number: frame index
469  //
470  // The array returned contains the following information:
471  // 0: Frame id
472  // 1: Receiver
473  // 2: Function
474  // 3: Script
475  // 4: Argument count
476  // 5: Local count
477  // 6: Source position
478  // 7: Constructor call
479  // 8: Is at return
480  // 9: Flags
481  // Arguments name, value
482  // Locals name, value
483  // Return value if any
RUNTIME_FUNCTION(Runtime_GetFrameDetails)484  RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
485    HandleScope scope(isolate);
486    DCHECK_EQ(2, args.length());
487    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
488    CHECK(isolate->debug()->CheckExecutionState(break_id));
489  
490    CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
491    Heap* heap = isolate->heap();
492  
493    // Find the relevant frame with the requested index.
494    StackFrame::Id id = isolate->debug()->break_frame_id();
495    if (id == StackFrame::NO_ID) {
496      // If there are no JavaScript stack frames return undefined.
497      return heap->undefined_value();
498    }
499  
500    StackTraceFrameIterator it(isolate, id);
501    // Inlined frame index in optimized frame, starting from outer function.
502    int inlined_frame_index =
503        DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
504    if (inlined_frame_index == -1) return heap->undefined_value();
505  
506    FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
507  
508    // Traverse the saved contexts chain to find the active context for the
509    // selected frame.
510    SaveContext* save =
511        DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
512  
513    // Get the frame id.
514    Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
515                            isolate);
516  
517    if (frame_inspector.summary().IsWasm()) {
518      // Create the details array (no dynamic information for wasm).
519      Handle<FixedArray> details =
520          isolate->factory()->NewFixedArray(kFrameDetailsFirstDynamicIndex);
521  
522      // Add the frame id.
523      details->set(kFrameDetailsFrameIdIndex, *frame_id);
524  
525      // Add the function name.
526      Handle<String> func_name = frame_inspector.summary().FunctionName();
527      details->set(kFrameDetailsFunctionIndex, *func_name);
528  
529      // Add the script wrapper
530      Handle<Object> script_wrapper =
531          Script::GetWrapper(frame_inspector.GetScript());
532      details->set(kFrameDetailsScriptIndex, *script_wrapper);
533  
534      // Add the arguments count.
535      details->set(kFrameDetailsArgumentCountIndex, Smi::kZero);
536  
537      // Add the locals count
538      details->set(kFrameDetailsLocalCountIndex, Smi::kZero);
539  
540      // Add the source position.
541      int position = frame_inspector.summary().SourcePosition();
542      details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
543  
544      // Add the constructor information.
545      details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(false));
546  
547      // Add the at return information.
548      details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(false));
549  
550      // Add flags to indicate information on whether this frame is
551      //   bit 0: invoked in the debugger context.
552      //   bit 1: optimized frame.
553      //   bit 2: inlined in optimized frame
554      int flags = 0;
555      if (*save->context() == *isolate->debug()->debug_context()) {
556        flags |= 1 << 0;
557      }
558      details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
559  
560      return *isolate->factory()->NewJSArrayWithElements(details);
561    }
562  
563    // Find source position in unoptimized code.
564    int position = frame_inspector.GetSourcePosition();
565  
566    // Handle JavaScript frames.
567    bool is_optimized = it.frame()->is_optimized();
568  
569    // Check for constructor frame.
570    bool constructor = frame_inspector.IsConstructor();
571  
572    // Get scope info and read from it for local variable information.
573    Handle<JSFunction> function =
574        Handle<JSFunction>::cast(frame_inspector.GetFunction());
575    CHECK(function->shared()->IsSubjectToDebugging());
576    Handle<SharedFunctionInfo> shared(function->shared());
577    Handle<ScopeInfo> scope_info(shared->scope_info());
578    DCHECK(*scope_info != ScopeInfo::Empty(isolate));
579  
580    // Get the locals names and values into a temporary array.
581    Handle<Object> maybe_context = frame_inspector.GetContext();
582    const int local_count_with_synthetic = maybe_context->IsContext()
583                                               ? scope_info->LocalCount()
584                                               : scope_info->StackLocalCount();
585    int local_count = local_count_with_synthetic;
586    for (int slot = 0; slot < local_count_with_synthetic; ++slot) {
587      // Hide compiler-introduced temporary variables, whether on the stack or on
588      // the context.
589      if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) {
590        local_count--;
591      }
592    }
593  
594    List<Handle<Object>> locals;
595    // Fill in the values of the locals.
596    int i = 0;
597    for (; i < scope_info->StackLocalCount(); ++i) {
598      // Use the value from the stack.
599      if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue;
600      locals.Add(Handle<String>(scope_info->LocalName(i), isolate));
601      Handle<Object> value =
602          frame_inspector.GetExpression(scope_info->StackLocalIndex(i));
603      // TODO(yangguo): We convert optimized out values to {undefined} when they
604      // are passed to the debugger. Eventually we should handle them somehow.
605      if (value->IsOptimizedOut(isolate)) {
606        value = isolate->factory()->undefined_value();
607      }
608      locals.Add(value);
609    }
610    if (locals.length() < local_count * 2) {
611      // Get the context containing declarations.
612      DCHECK(maybe_context->IsContext());
613      Handle<Context> context(Context::cast(*maybe_context)->closure_context());
614  
615      for (; i < scope_info->LocalCount(); ++i) {
616        Handle<String> name(scope_info->LocalName(i));
617        if (ScopeInfo::VariableIsSynthetic(*name)) continue;
618        VariableMode mode;
619        InitializationFlag init_flag;
620        MaybeAssignedFlag maybe_assigned_flag;
621        locals.Add(name);
622        int context_slot_index = ScopeInfo::ContextSlotIndex(
623            scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
624        Object* value = context->get(context_slot_index);
625        locals.Add(Handle<Object>(value, isolate));
626      }
627    }
628  
629    // Check whether this frame is positioned at return. If not top
630    // frame or if the frame is optimized it cannot be at a return.
631    bool at_return = false;
632    if (!is_optimized && index == 0) {
633      at_return = isolate->debug()->IsBreakAtReturn(it.javascript_frame());
634    }
635  
636    // If positioned just before return find the value to be returned and add it
637    // to the frame information.
638    Handle<Object> return_value = isolate->factory()->undefined_value();
639    if (at_return) {
640      return_value = handle(isolate->debug()->return_value(), isolate);
641    }
642  
643    // Now advance to the arguments adapter frame (if any). It contains all
644    // the provided parameters whereas the function frame always have the number
645    // of arguments matching the functions parameters. The rest of the
646    // information (except for what is collected above) is the same.
647    if ((inlined_frame_index == 0) &&
648        it.javascript_frame()->has_adapted_arguments()) {
649      it.AdvanceToArgumentsFrame();
650      frame_inspector.SetArgumentsFrame(it.frame());
651    }
652  
653    // Find the number of arguments to fill. At least fill the number of
654    // parameters for the function and fill more if more parameters are provided.
655    int argument_count = scope_info->ParameterCount();
656    if (argument_count < frame_inspector.GetParametersCount()) {
657      argument_count = frame_inspector.GetParametersCount();
658    }
659  
660    // Calculate the size of the result.
661    int details_size = kFrameDetailsFirstDynamicIndex +
662                       2 * (argument_count + local_count) + (at_return ? 1 : 0);
663    Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
664  
665    // Add the frame id.
666    details->set(kFrameDetailsFrameIdIndex, *frame_id);
667  
668    // Add the function (same as in function frame).
669    details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction()));
670  
671    // Add the script wrapper
672    Handle<Object> script_wrapper =
673        Script::GetWrapper(frame_inspector.GetScript());
674    details->set(kFrameDetailsScriptIndex, *script_wrapper);
675  
676    // Add the arguments count.
677    details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
678  
679    // Add the locals count
680    details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
681  
682    // Add the source position.
683    if (position != kNoSourcePosition) {
684      details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
685    } else {
686      details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
687    }
688  
689    // Add the constructor information.
690    details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
691  
692    // Add the at return information.
693    details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
694  
695    // Add flags to indicate information on whether this frame is
696    //   bit 0: invoked in the debugger context.
697    //   bit 1: optimized frame.
698    //   bit 2: inlined in optimized frame
699    int flags = 0;
700    if (*save->context() == *isolate->debug()->debug_context()) {
701      flags |= 1 << 0;
702    }
703    if (is_optimized) {
704      flags |= 1 << 1;
705      flags |= inlined_frame_index << 2;
706    }
707    details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
708  
709    // Fill the dynamic part.
710    int details_index = kFrameDetailsFirstDynamicIndex;
711  
712    // Add arguments name and value.
713    for (int i = 0; i < argument_count; i++) {
714      // Name of the argument.
715      if (i < scope_info->ParameterCount()) {
716        details->set(details_index++, scope_info->ParameterName(i));
717      } else {
718        details->set(details_index++, heap->undefined_value());
719      }
720  
721      // Parameter value.
722      if (i < frame_inspector.GetParametersCount()) {
723        // Get the value from the stack.
724        details->set(details_index++, *(frame_inspector.GetParameter(i)));
725      } else {
726        details->set(details_index++, heap->undefined_value());
727      }
728    }
729  
730    // Add locals name and value from the temporary copy from the function frame.
731    for (const auto& local : locals) details->set(details_index++, *local);
732  
733    // Add the value being returned.
734    if (at_return) {
735      details->set(details_index++, *return_value);
736    }
737  
738    // Add the receiver (same as in function frame).
739    Handle<Object> receiver = frame_inspector.summary().receiver();
740    DCHECK(function->shared()->IsUserJavaScript());
741    // Optimized frames only restore the receiver as best-effort (see
742    // OptimizedFrame::Summarize).
743    DCHECK_IMPLIES(!is_optimized && is_sloppy(shared->language_mode()),
744                   receiver->IsJSReceiver());
745    details->set(kFrameDetailsReceiverIndex, *receiver);
746  
747    DCHECK_EQ(details_size, details_index);
748    return *isolate->factory()->NewJSArrayWithElements(details);
749  }
750  
751  
RUNTIME_FUNCTION(Runtime_GetScopeCount)752  RUNTIME_FUNCTION(Runtime_GetScopeCount) {
753    HandleScope scope(isolate);
754    DCHECK_EQ(2, args.length());
755    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
756    CHECK(isolate->debug()->CheckExecutionState(break_id));
757  
758    CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
759  
760    // Get the frame where the debugging is performed.
761    StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
762    StackTraceFrameIterator it(isolate, id);
763    StandardFrame* frame = it.frame();
764    if (it.frame()->is_wasm()) return 0;
765  
766    FrameInspector frame_inspector(frame, 0, isolate);
767  
768    // Count the visible scopes.
769    int n = 0;
770    for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
771      n++;
772    }
773  
774    return Smi::FromInt(n);
775  }
776  
777  
778  // Return an array with scope details
779  // args[0]: number: break id
780  // args[1]: number: frame index
781  // args[2]: number: inlined frame index
782  // args[3]: number: scope index
783  //
784  // The array returned contains the following information:
785  // 0: Scope type
786  // 1: Scope object
RUNTIME_FUNCTION(Runtime_GetScopeDetails)787  RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
788    HandleScope scope(isolate);
789    DCHECK_EQ(4, args.length());
790    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
791    CHECK(isolate->debug()->CheckExecutionState(break_id));
792  
793    CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
794    CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
795    CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
796  
797    // Get the frame where the debugging is performed.
798    StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
799    StackTraceFrameIterator frame_it(isolate, id);
800    // Wasm has no scopes, this must be javascript.
801    JavaScriptFrame* frame = JavaScriptFrame::cast(frame_it.frame());
802    FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
803  
804    // Find the requested scope.
805    int n = 0;
806    ScopeIterator it(isolate, &frame_inspector);
807    for (; !it.Done() && n < index; it.Next()) {
808      n++;
809    }
810    if (it.Done()) {
811      return isolate->heap()->undefined_value();
812    }
813    RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
814  }
815  
816  
817  // Return an array of scope details
818  // args[0]: number: break id
819  // args[1]: number: frame index
820  // args[2]: number: inlined frame index
821  // args[3]: boolean: ignore nested scopes
822  //
823  // The array returned contains arrays with the following information:
824  // 0: Scope type
825  // 1: Scope object
RUNTIME_FUNCTION(Runtime_GetAllScopesDetails)826  RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
827    HandleScope scope(isolate);
828    DCHECK(args.length() == 3 || args.length() == 4);
829    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
830    CHECK(isolate->debug()->CheckExecutionState(break_id));
831  
832    CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
833    CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
834  
835    ScopeIterator::Option option = ScopeIterator::DEFAULT;
836    if (args.length() == 4) {
837      CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
838      if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
839    }
840  
841    // Get the frame where the debugging is performed.
842    StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
843    StackTraceFrameIterator frame_it(isolate, id);
844    StandardFrame* frame = frame_it.frame();
845    FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
846  
847    List<Handle<JSObject> > result(4);
848    ScopeIterator it(isolate, &frame_inspector, option);
849    for (; !it.Done(); it.Next()) {
850      Handle<JSObject> details;
851      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
852                                         it.MaterializeScopeDetails());
853      result.Add(details);
854    }
855  
856    Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
857    for (int i = 0; i < result.length(); ++i) {
858      array->set(i, *result[i]);
859    }
860    return *isolate->factory()->NewJSArrayWithElements(array);
861  }
862  
863  
RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount)864  RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
865    HandleScope scope(isolate);
866    DCHECK_EQ(1, args.length());
867  
868    // Check arguments.
869    CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
870  
871    // Count the visible scopes.
872    int n = 0;
873    if (function->IsJSFunction()) {
874      for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
875           !it.Done(); it.Next()) {
876        n++;
877      }
878    }
879  
880    return Smi::FromInt(n);
881  }
882  
883  
RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails)884  RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
885    HandleScope scope(isolate);
886    DCHECK_EQ(2, args.length());
887  
888    // Check arguments.
889    CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
890    CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
891  
892    // Find the requested scope.
893    int n = 0;
894    ScopeIterator it(isolate, fun);
895    for (; !it.Done() && n < index; it.Next()) {
896      n++;
897    }
898    if (it.Done()) {
899      return isolate->heap()->undefined_value();
900    }
901  
902    RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
903  }
904  
RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount)905  RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) {
906    HandleScope scope(isolate);
907    DCHECK_EQ(1, args.length());
908  
909    if (!args[0]->IsJSGeneratorObject()) return Smi::kZero;
910  
911    // Check arguments.
912    CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
913  
914    // Count the visible scopes.
915    int n = 0;
916    for (ScopeIterator it(isolate, gen); !it.Done(); it.Next()) {
917      n++;
918    }
919  
920    return Smi::FromInt(n);
921  }
922  
RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails)923  RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails) {
924    HandleScope scope(isolate);
925    DCHECK_EQ(2, args.length());
926  
927    if (!args[0]->IsJSGeneratorObject()) {
928      return isolate->heap()->undefined_value();
929    }
930  
931    // Check arguments.
932    CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
933    CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
934  
935    // Find the requested scope.
936    int n = 0;
937    ScopeIterator it(isolate, gen);
938    for (; !it.Done() && n < index; it.Next()) {
939      n++;
940    }
941    if (it.Done()) {
942      return isolate->heap()->undefined_value();
943    }
944  
945    RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
946  }
947  
SetScopeVariableValue(ScopeIterator * it,int index,Handle<String> variable_name,Handle<Object> new_value)948  static bool SetScopeVariableValue(ScopeIterator* it, int index,
949                                    Handle<String> variable_name,
950                                    Handle<Object> new_value) {
951    for (int n = 0; !it->Done() && n < index; it->Next()) {
952      n++;
953    }
954    if (it->Done()) {
955      return false;
956    }
957    return it->SetVariableValue(variable_name, new_value);
958  }
959  
960  
961  // Change variable value in closure or local scope
962  // args[0]: number or JsFunction: break id or function
963  // args[1]: number: frame index (when arg[0] is break id)
964  // args[2]: number: inlined frame index (when arg[0] is break id)
965  // args[3]: number: scope index
966  // args[4]: string: variable name
967  // args[5]: object: new value
968  //
969  // Return true if success and false otherwise
RUNTIME_FUNCTION(Runtime_SetScopeVariableValue)970  RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
971    HandleScope scope(isolate);
972    DCHECK_EQ(6, args.length());
973  
974    // Check arguments.
975    CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
976    CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
977    CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
978  
979    bool res;
980    if (args[0]->IsNumber()) {
981      CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
982      CHECK(isolate->debug()->CheckExecutionState(break_id));
983  
984      CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
985      CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
986  
987      // Get the frame where the debugging is performed.
988      StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
989      StackTraceFrameIterator frame_it(isolate, id);
990      // Wasm has no scopes, this must be javascript.
991      JavaScriptFrame* frame = JavaScriptFrame::cast(frame_it.frame());
992      FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
993  
994      ScopeIterator it(isolate, &frame_inspector);
995      res = SetScopeVariableValue(&it, index, variable_name, new_value);
996    } else if (args[0]->IsJSFunction()) {
997      CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
998      ScopeIterator it(isolate, fun);
999      res = SetScopeVariableValue(&it, index, variable_name, new_value);
1000    } else {
1001      CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
1002      ScopeIterator it(isolate, gen);
1003      res = SetScopeVariableValue(&it, index, variable_name, new_value);
1004    }
1005  
1006    return isolate->heap()->ToBoolean(res);
1007  }
1008  
1009  
RUNTIME_FUNCTION(Runtime_DebugPrintScopes)1010  RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
1011    HandleScope scope(isolate);
1012    DCHECK_EQ(0, args.length());
1013  
1014  #ifdef DEBUG
1015    // Print the scopes for the top frame.
1016    StackFrameLocator locator(isolate);
1017    JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
1018    FrameInspector frame_inspector(frame, 0, isolate);
1019  
1020    for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
1021      it.DebugPrint();
1022    }
1023  #endif
1024    return isolate->heap()->undefined_value();
1025  }
1026  
1027  
1028  // Sets the disable break state
1029  // args[0]: disable break state
RUNTIME_FUNCTION(Runtime_SetBreakPointsActive)1030  RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
1031    HandleScope scope(isolate);
1032    DCHECK_EQ(1, args.length());
1033    CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
1034    isolate->debug()->set_break_points_active(active);
1035    return isolate->heap()->undefined_value();
1036  }
1037  
1038  
IsPositionAlignmentCodeCorrect(int alignment)1039  static bool IsPositionAlignmentCodeCorrect(int alignment) {
1040    return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
1041  }
1042  
1043  
RUNTIME_FUNCTION(Runtime_GetBreakLocations)1044  RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
1045    HandleScope scope(isolate);
1046    DCHECK_EQ(2, args.length());
1047    CHECK(isolate->debug()->is_active());
1048    CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1049    CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
1050  
1051    if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1052      return isolate->ThrowIllegalOperation();
1053    }
1054    BreakPositionAlignment alignment =
1055        static_cast<BreakPositionAlignment>(statement_aligned_code);
1056  
1057    Handle<SharedFunctionInfo> shared(fun->shared());
1058    // Find the number of break points
1059    Handle<Object> break_locations =
1060        Debug::GetSourceBreakLocations(shared, alignment);
1061    if (break_locations->IsUndefined(isolate)) {
1062      return isolate->heap()->undefined_value();
1063    }
1064    // Return array as JS array
1065    return *isolate->factory()->NewJSArrayWithElements(
1066        Handle<FixedArray>::cast(break_locations));
1067  }
1068  
1069  
1070  // Set a break point in a function.
1071  // args[0]: function
1072  // args[1]: number: break source position (within the function source)
1073  // args[2]: number: break point object
RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint)1074  RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
1075    HandleScope scope(isolate);
1076    DCHECK_EQ(3, args.length());
1077    CHECK(isolate->debug()->is_active());
1078    CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1079    CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1080    CHECK(source_position >= function->shared()->start_position() &&
1081          source_position <= function->shared()->end_position());
1082    CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
1083  
1084    // Set break point.
1085    CHECK(isolate->debug()->SetBreakPoint(function, break_point_object_arg,
1086                                          &source_position));
1087  
1088    return Smi::FromInt(source_position);
1089  }
1090  
1091  
1092  // Changes the state of a break point in a script and returns source position
1093  // where break point was set. NOTE: Regarding performance see the NOTE for
1094  // GetScriptFromScriptData.
1095  // args[0]: script to set break point in
1096  // args[1]: number: break source position (within the script source)
1097  // args[2]: number, breakpoint position alignment
1098  // args[3]: number: break point object
RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint)1099  RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
1100    HandleScope scope(isolate);
1101    DCHECK_EQ(4, args.length());
1102    CHECK(isolate->debug()->is_active());
1103    CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
1104    CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1105    CHECK(source_position >= 0);
1106    CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
1107    CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
1108  
1109    if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1110      return isolate->ThrowIllegalOperation();
1111    }
1112    BreakPositionAlignment alignment =
1113        static_cast<BreakPositionAlignment>(statement_aligned_code);
1114  
1115    // Get the script from the script wrapper.
1116    CHECK(wrapper->value()->IsScript());
1117    Handle<Script> script(Script::cast(wrapper->value()));
1118  
1119    // Set break point.
1120    if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
1121                                                  &source_position, alignment)) {
1122      return isolate->heap()->undefined_value();
1123    }
1124  
1125    return Smi::FromInt(source_position);
1126  }
1127  
1128  
1129  // Clear a break point
1130  // args[0]: number: break point object
RUNTIME_FUNCTION(Runtime_ClearBreakPoint)1131  RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
1132    HandleScope scope(isolate);
1133    DCHECK_EQ(1, args.length());
1134    CHECK(isolate->debug()->is_active());
1135    CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
1136  
1137    // Clear break point.
1138    isolate->debug()->ClearBreakPoint(break_point_object_arg);
1139  
1140    return isolate->heap()->undefined_value();
1141  }
1142  
1143  
1144  // Change the state of break on exceptions.
1145  // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
1146  // args[1]: Boolean indicating on/off.
RUNTIME_FUNCTION(Runtime_ChangeBreakOnException)1147  RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
1148    HandleScope scope(isolate);
1149    DCHECK_EQ(2, args.length());
1150    CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1151    CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
1152  
1153    // If the number doesn't match an enum value, the ChangeBreakOnException
1154    // function will default to affecting caught exceptions.
1155    ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1156    // Update break point state.
1157    isolate->debug()->ChangeBreakOnException(type, enable);
1158    return isolate->heap()->undefined_value();
1159  }
1160  
1161  
1162  // Returns the state of break on exceptions
1163  // args[0]: boolean indicating uncaught exceptions
RUNTIME_FUNCTION(Runtime_IsBreakOnException)1164  RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
1165    HandleScope scope(isolate);
1166    DCHECK_EQ(1, args.length());
1167    CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1168  
1169    ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1170    bool result = isolate->debug()->IsBreakOnException(type);
1171    return Smi::FromInt(result);
1172  }
1173  
1174  
1175  // Prepare for stepping
1176  // args[0]: break id for checking execution state
1177  // args[1]: step action from the enumeration StepAction
1178  // args[2]: number of times to perform the step, for step out it is the number
1179  //          of frames to step down.
RUNTIME_FUNCTION(Runtime_PrepareStep)1180  RUNTIME_FUNCTION(Runtime_PrepareStep) {
1181    HandleScope scope(isolate);
1182    DCHECK_EQ(2, args.length());
1183    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1184    CHECK(isolate->debug()->CheckExecutionState(break_id));
1185  
1186    if (!args[1]->IsNumber()) {
1187      return isolate->Throw(isolate->heap()->illegal_argument_string());
1188    }
1189  
1190    // Get the step action and check validity.
1191    StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
1192    if (step_action != StepIn && step_action != StepNext &&
1193        step_action != StepOut) {
1194      return isolate->Throw(isolate->heap()->illegal_argument_string());
1195    }
1196  
1197    // Clear all current stepping setup.
1198    isolate->debug()->ClearStepping();
1199  
1200    // Prepare step.
1201    isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
1202    return isolate->heap()->undefined_value();
1203  }
1204  
1205  // Clear all stepping set by PrepareStep.
RUNTIME_FUNCTION(Runtime_ClearStepping)1206  RUNTIME_FUNCTION(Runtime_ClearStepping) {
1207    HandleScope scope(isolate);
1208    DCHECK_EQ(0, args.length());
1209    CHECK(isolate->debug()->is_active());
1210    isolate->debug()->ClearStepping();
1211    return isolate->heap()->undefined_value();
1212  }
1213  
1214  
RUNTIME_FUNCTION(Runtime_DebugEvaluate)1215  RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
1216    HandleScope scope(isolate);
1217  
1218    // Check the execution state and decode arguments frame and source to be
1219    // evaluated.
1220    DCHECK_EQ(5, args.length());
1221    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1222    CHECK(isolate->debug()->CheckExecutionState(break_id));
1223  
1224    CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1225    CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1226    CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
1227    CONVERT_BOOLEAN_ARG_CHECKED(throw_on_side_effect, 4);
1228  
1229    StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
1230  
1231    RETURN_RESULT_OR_FAILURE(
1232        isolate, DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
1233                                      throw_on_side_effect));
1234  }
1235  
1236  
RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal)1237  RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
1238    HandleScope scope(isolate);
1239  
1240    // Check the execution state and decode arguments frame and source to be
1241    // evaluated.
1242    DCHECK_EQ(2, args.length());
1243    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1244    CHECK(isolate->debug()->CheckExecutionState(break_id));
1245  
1246    CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1247  
1248    RETURN_RESULT_OR_FAILURE(isolate, DebugEvaluate::Global(isolate, source));
1249  }
1250  
1251  
RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts)1252  RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
1253    HandleScope scope(isolate);
1254    DCHECK_EQ(0, args.length());
1255  
1256    Handle<FixedArray> instances;
1257    {
1258      DebugScope debug_scope(isolate->debug());
1259      if (debug_scope.failed()) {
1260        DCHECK(isolate->has_pending_exception());
1261        return isolate->heap()->exception();
1262      }
1263      // Fill the script objects.
1264      instances = isolate->debug()->GetLoadedScripts();
1265    }
1266  
1267    // Convert the script objects to proper JS objects.
1268    for (int i = 0; i < instances->length(); i++) {
1269      Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
1270      // Get the script wrapper in a local handle before calling GetScriptWrapper,
1271      // because using
1272      //   instances->set(i, *GetScriptWrapper(script))
1273      // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
1274      // already have dereferenced the instances handle.
1275      Handle<JSObject> wrapper = Script::GetWrapper(script);
1276      instances->set(i, *wrapper);
1277    }
1278  
1279    // Return result as a JS array.
1280    return *isolate->factory()->NewJSArrayWithElements(instances);
1281  }
1282  
HasInPrototypeChainIgnoringProxies(Isolate * isolate,JSObject * object,Object * proto)1283  static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate,
1284                                                 JSObject* object,
1285                                                 Object* proto) {
1286    PrototypeIterator iter(isolate, object, kStartAtReceiver);
1287    while (true) {
1288      iter.AdvanceIgnoringProxies();
1289      if (iter.IsAtEnd()) return false;
1290      if (iter.GetCurrent() == proto) return true;
1291    }
1292  }
1293  
1294  
1295  // Scan the heap for objects with direct references to an object
1296  // args[0]: the object to find references to
1297  // args[1]: constructor function for instances to exclude (Mirror)
1298  // args[2]: the the maximum number of objects to return
RUNTIME_FUNCTION(Runtime_DebugReferencedBy)1299  RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
1300    HandleScope scope(isolate);
1301    DCHECK_EQ(3, args.length());
1302    CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
1303    CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
1304    CHECK(filter->IsUndefined(isolate) || filter->IsJSObject());
1305    CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
1306    CHECK(max_references >= 0);
1307  
1308    List<Handle<JSObject> > instances;
1309    Heap* heap = isolate->heap();
1310    {
1311      HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1312      // Get the constructor function for context extension and arguments array.
1313      Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
1314      HeapObject* heap_obj;
1315      while ((heap_obj = iterator.next())) {
1316        if (!heap_obj->IsJSObject()) continue;
1317        JSObject* obj = JSObject::cast(heap_obj);
1318        if (obj->IsJSContextExtensionObject()) continue;
1319        if (obj->map()->GetConstructor() == arguments_fun) continue;
1320        if (!obj->ReferencesObject(*target)) continue;
1321        // Check filter if supplied. This is normally used to avoid
1322        // references from mirror objects.
1323        if (!filter->IsUndefined(isolate) &&
1324            HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
1325          continue;
1326        }
1327        if (obj->IsJSGlobalObject()) {
1328          obj = JSGlobalObject::cast(obj)->global_proxy();
1329        }
1330        instances.Add(Handle<JSObject>(obj));
1331        if (instances.length() == max_references) break;
1332      }
1333      // Iterate the rest of the heap to satisfy HeapIterator constraints.
1334      while (iterator.next()) {
1335      }
1336    }
1337  
1338    Handle<FixedArray> result;
1339    if (instances.length() == 1 && instances.last().is_identical_to(target)) {
1340      // Check for circular reference only. This can happen when the object is
1341      // only referenced from mirrors and has a circular reference in which case
1342      // the object is not really alive and would have been garbage collected if
1343      // not referenced from the mirror.
1344      result = isolate->factory()->empty_fixed_array();
1345    } else {
1346      result = isolate->factory()->NewFixedArray(instances.length());
1347      for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1348    }
1349    return *isolate->factory()->NewJSArrayWithElements(result);
1350  }
1351  
1352  
1353  // Scan the heap for objects constructed by a specific function.
1354  // args[0]: the constructor to find instances of
1355  // args[1]: the the maximum number of objects to return
RUNTIME_FUNCTION(Runtime_DebugConstructedBy)1356  RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
1357    HandleScope scope(isolate);
1358    DCHECK_EQ(2, args.length());
1359    CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
1360    CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
1361    CHECK(max_references >= 0);
1362  
1363    List<Handle<JSObject> > instances;
1364    Heap* heap = isolate->heap();
1365    {
1366      HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1367      HeapObject* heap_obj;
1368      while ((heap_obj = iterator.next())) {
1369        if (!heap_obj->IsJSObject()) continue;
1370        JSObject* obj = JSObject::cast(heap_obj);
1371        if (obj->map()->GetConstructor() != *constructor) continue;
1372        instances.Add(Handle<JSObject>(obj));
1373        if (instances.length() == max_references) break;
1374      }
1375      // Iterate the rest of the heap to satisfy HeapIterator constraints.
1376      while (iterator.next()) {
1377      }
1378    }
1379  
1380    Handle<FixedArray> result =
1381        isolate->factory()->NewFixedArray(instances.length());
1382    for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1383    return *isolate->factory()->NewJSArrayWithElements(result);
1384  }
1385  
1386  
1387  // Find the effective prototype object as returned by __proto__.
1388  // args[0]: the object to find the prototype for.
RUNTIME_FUNCTION(Runtime_DebugGetPrototype)1389  RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
1390    HandleScope shs(isolate);
1391    DCHECK_EQ(1, args.length());
1392    CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1393    // TODO(1543): Come up with a solution for clients to handle potential errors
1394    // thrown by an intermediate proxy.
1395    RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
1396  }
1397  
1398  
1399  // Patches script source (should be called upon BeforeCompile event).
1400  // TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_DebugSetScriptSource)1401  RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
1402    HandleScope scope(isolate);
1403    DCHECK_EQ(2, args.length());
1404  
1405    CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
1406    CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1407  
1408    CHECK(script_wrapper->value()->IsScript());
1409    Handle<Script> script(Script::cast(script_wrapper->value()));
1410  
1411    // The following condition is not guaranteed to hold and a failure is also
1412    // propagated to callers. Hence we fail gracefully here and don't crash.
1413    if (script->compilation_state() != Script::COMPILATION_STATE_INITIAL) {
1414      return isolate->ThrowIllegalOperation();
1415    }
1416  
1417    script->set_source(*source);
1418  
1419    return isolate->heap()->undefined_value();
1420  }
1421  
1422  
RUNTIME_FUNCTION(Runtime_FunctionGetInferredName)1423  RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
1424    SealHandleScope shs(isolate);
1425    DCHECK_EQ(1, args.length());
1426  
1427    CONVERT_ARG_CHECKED(Object, f, 0);
1428    if (f->IsJSFunction()) {
1429      return JSFunction::cast(f)->shared()->inferred_name();
1430    }
1431    return isolate->heap()->empty_string();
1432  }
1433  
1434  
RUNTIME_FUNCTION(Runtime_FunctionGetDebugName)1435  RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
1436    HandleScope scope(isolate);
1437    DCHECK_EQ(1, args.length());
1438  
1439    CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
1440  
1441    if (function->IsJSBoundFunction()) {
1442      RETURN_RESULT_OR_FAILURE(
1443          isolate, JSBoundFunction::GetName(
1444                       isolate, Handle<JSBoundFunction>::cast(function)));
1445    } else {
1446      return *JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
1447    }
1448  }
1449  
1450  
RUNTIME_FUNCTION(Runtime_GetDebugContext)1451  RUNTIME_FUNCTION(Runtime_GetDebugContext) {
1452    HandleScope scope(isolate);
1453    DCHECK_EQ(0, args.length());
1454    Handle<Context> context;
1455    {
1456      DebugScope debug_scope(isolate->debug());
1457      if (debug_scope.failed()) {
1458        DCHECK(isolate->has_pending_exception());
1459        return isolate->heap()->exception();
1460      }
1461      context = isolate->debug()->GetDebugContext();
1462    }
1463    if (context.is_null()) return isolate->heap()->undefined_value();
1464    context->set_security_token(isolate->native_context()->security_token());
1465    return context->global_proxy();
1466  }
1467  
1468  
1469  // Performs a GC.
1470  // Presently, it only does a full GC.
RUNTIME_FUNCTION(Runtime_CollectGarbage)1471  RUNTIME_FUNCTION(Runtime_CollectGarbage) {
1472    SealHandleScope shs(isolate);
1473    DCHECK_EQ(1, args.length());
1474    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
1475                                       GarbageCollectionReason::kRuntime);
1476    return isolate->heap()->undefined_value();
1477  }
1478  
1479  
1480  // Gets the current heap usage.
RUNTIME_FUNCTION(Runtime_GetHeapUsage)1481  RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
1482    SealHandleScope shs(isolate);
1483    DCHECK_EQ(0, args.length());
1484    int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
1485    if (!Smi::IsValid(usage)) {
1486      return *isolate->factory()->NewNumberFromInt(usage);
1487    }
1488    return Smi::FromInt(usage);
1489  }
1490  
1491  
1492  // Finds the script object from the script data. NOTE: This operation uses
1493  // heap traversal to find the function generated for the source position
1494  // for the requested break point. For lazily compiled functions several heap
1495  // traversals might be required rendering this operation as a rather slow
1496  // operation. However for setting break points which is normally done through
1497  // some kind of user interaction the performance is not crucial.
RUNTIME_FUNCTION(Runtime_GetScript)1498  RUNTIME_FUNCTION(Runtime_GetScript) {
1499    HandleScope scope(isolate);
1500    DCHECK_EQ(1, args.length());
1501    CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
1502  
1503    Handle<Script> found;
1504    {
1505      Script::Iterator iterator(isolate);
1506      Script* script = NULL;
1507      while ((script = iterator.Next()) != NULL) {
1508        if (!script->name()->IsString()) continue;
1509        String* name = String::cast(script->name());
1510        if (name->Equals(*script_name)) {
1511          found = Handle<Script>(script, isolate);
1512          break;
1513        }
1514      }
1515    }
1516  
1517    if (found.is_null()) return isolate->heap()->undefined_value();
1518    return *Script::GetWrapper(found);
1519  }
1520  
1521  // TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_ScriptLineCount)1522  RUNTIME_FUNCTION(Runtime_ScriptLineCount) {
1523    HandleScope scope(isolate);
1524    DCHECK_EQ(1, args.length());
1525    CONVERT_ARG_CHECKED(JSValue, script, 0);
1526  
1527    CHECK(script->value()->IsScript());
1528    Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1529  
1530    if (script_handle->type() == Script::TYPE_WASM) {
1531      // Return 0 for now; this function will disappear soon anyway.
1532      return Smi::FromInt(0);
1533    }
1534  
1535    Script::InitLineEnds(script_handle);
1536  
1537    FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1538    return Smi::FromInt(line_ends_array->length());
1539  }
1540  
1541  namespace {
1542  
ScriptLinePosition(Handle<Script> script,int line)1543  int ScriptLinePosition(Handle<Script> script, int line) {
1544    if (line < 0) return -1;
1545  
1546    if (script->type() == Script::TYPE_WASM) {
1547      return WasmCompiledModule::cast(script->wasm_compiled_module())
1548          ->GetFunctionOffset(line);
1549    }
1550  
1551    Script::InitLineEnds(script);
1552  
1553    FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
1554    const int line_count = line_ends_array->length();
1555    DCHECK_LT(0, line_count);
1556  
1557    if (line == 0) return 0;
1558    // If line == line_count, we return the first position beyond the last line.
1559    if (line > line_count) return -1;
1560    return Smi::cast(line_ends_array->get(line - 1))->value() + 1;
1561  }
1562  
1563  }  // namespace
1564  
1565  // TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition)1566  RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) {
1567    HandleScope scope(isolate);
1568    DCHECK_EQ(2, args.length());
1569    CONVERT_ARG_CHECKED(JSValue, script, 0);
1570    CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1571  
1572    CHECK(script->value()->IsScript());
1573    Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1574  
1575    return Smi::FromInt(ScriptLinePosition(script_handle, line));
1576  }
1577  
1578  // TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition)1579  RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) {
1580    HandleScope scope(isolate);
1581    DCHECK_EQ(2, args.length());
1582    CONVERT_ARG_CHECKED(JSValue, script, 0);
1583    CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1584  
1585    CHECK(script->value()->IsScript());
1586    Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1587  
1588    if (script_handle->type() == Script::TYPE_WASM) {
1589      // Return zero for now; this function will disappear soon anyway.
1590      return Smi::FromInt(0);
1591    }
1592  
1593    Script::InitLineEnds(script_handle);
1594  
1595    FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1596    const int line_count = line_ends_array->length();
1597  
1598    if (line < 0 || line >= line_count) {
1599      return Smi::FromInt(-1);
1600    } else {
1601      return Smi::cast(line_ends_array->get(line));
1602    }
1603  }
1604  
GetJSPositionInfo(Handle<Script> script,int position,Script::OffsetFlag offset_flag,Isolate * isolate)1605  static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
1606                                          Script::OffsetFlag offset_flag,
1607                                          Isolate* isolate) {
1608    Script::PositionInfo info;
1609    if (!Script::GetPositionInfo(script, position, &info, offset_flag)) {
1610      return isolate->factory()->null_value();
1611    }
1612  
1613    Handle<String> source = handle(String::cast(script->source()), isolate);
1614    Handle<String> sourceText = script->type() == Script::TYPE_WASM
1615                                    ? isolate->factory()->empty_string()
1616                                    : isolate->factory()->NewSubString(
1617                                          source, info.line_start, info.line_end);
1618  
1619    Handle<JSObject> jsinfo =
1620        isolate->factory()->NewJSObject(isolate->object_function());
1621  
1622    JSObject::AddProperty(jsinfo, isolate->factory()->script_string(), script,
1623                          NONE);
1624    JSObject::AddProperty(jsinfo, isolate->factory()->position_string(),
1625                          handle(Smi::FromInt(position), isolate), NONE);
1626    JSObject::AddProperty(jsinfo, isolate->factory()->line_string(),
1627                          handle(Smi::FromInt(info.line), isolate), NONE);
1628    JSObject::AddProperty(jsinfo, isolate->factory()->column_string(),
1629                          handle(Smi::FromInt(info.column), isolate), NONE);
1630    JSObject::AddProperty(jsinfo, isolate->factory()->sourceText_string(),
1631                          sourceText, NONE);
1632  
1633    return jsinfo;
1634  }
1635  
1636  namespace {
1637  
ScriptLinePositionWithOffset(Handle<Script> script,int line,int offset)1638  int ScriptLinePositionWithOffset(Handle<Script> script, int line, int offset) {
1639    if (line < 0 || offset < 0) return -1;
1640  
1641    if (line == 0 || offset == 0)
1642      return ScriptLinePosition(script, line) + offset;
1643  
1644    Script::PositionInfo info;
1645    if (!Script::GetPositionInfo(script, offset, &info, Script::NO_OFFSET)) {
1646      return -1;
1647    }
1648  
1649    const int total_line = info.line + line;
1650    return ScriptLinePosition(script, total_line);
1651  }
1652  
ScriptLocationFromLine(Isolate * isolate,Handle<Script> script,Handle<Object> opt_line,Handle<Object> opt_column,int32_t offset)1653  Handle<Object> ScriptLocationFromLine(Isolate* isolate, Handle<Script> script,
1654                                        Handle<Object> opt_line,
1655                                        Handle<Object> opt_column,
1656                                        int32_t offset) {
1657    // Line and column are possibly undefined and we need to handle these cases,
1658    // additionally subtracting corresponding offsets.
1659  
1660    int32_t line = 0;
1661    if (!opt_line->IsNullOrUndefined(isolate)) {
1662      CHECK(opt_line->IsNumber());
1663      line = NumberToInt32(*opt_line) - script->line_offset();
1664    }
1665  
1666    int32_t column = 0;
1667    if (!opt_column->IsNullOrUndefined(isolate)) {
1668      CHECK(opt_column->IsNumber());
1669      column = NumberToInt32(*opt_column);
1670      if (line == 0) column -= script->column_offset();
1671    }
1672  
1673    int line_position = ScriptLinePositionWithOffset(script, line, offset);
1674    if (line_position < 0 || column < 0) return isolate->factory()->null_value();
1675  
1676    return GetJSPositionInfo(script, line_position + column, Script::NO_OFFSET,
1677                             isolate);
1678  }
1679  
1680  // Slow traversal over all scripts on the heap.
GetScriptById(Isolate * isolate,int needle,Handle<Script> * result)1681  bool GetScriptById(Isolate* isolate, int needle, Handle<Script>* result) {
1682    Script::Iterator iterator(isolate);
1683    Script* script = NULL;
1684    while ((script = iterator.Next()) != NULL) {
1685      if (script->id() == needle) {
1686        *result = handle(script);
1687        return true;
1688      }
1689    }
1690  
1691    return false;
1692  }
1693  
1694  }  // namespace
1695  
1696  // Get information on a specific source line and column possibly offset by a
1697  // fixed source position. This function is used to find a source position from
1698  // a line and column position. The fixed source position offset is typically
1699  // used to find a source position in a function based on a line and column in
1700  // the source for the function alone. The offset passed will then be the
1701  // start position of the source for the function within the full script source.
1702  // Note that incoming line and column parameters may be undefined, and are
1703  // assumed to be passed *with* offsets.
1704  // TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine)1705  RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) {
1706    HandleScope scope(isolate);
1707    DCHECK_EQ(4, args.length());
1708    CONVERT_ARG_HANDLE_CHECKED(JSValue, script, 0);
1709    CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1);
1710    CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2);
1711    CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]);
1712  
1713    CHECK(script->value()->IsScript());
1714    Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1715  
1716    return *ScriptLocationFromLine(isolate, script_handle, opt_line, opt_column,
1717                                   offset);
1718  }
1719  
1720  // TODO(5530): Rename once conflicting function has been deleted.
RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine2)1721  RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine2) {
1722    HandleScope scope(isolate);
1723    DCHECK_EQ(4, args.length());
1724    CONVERT_NUMBER_CHECKED(int32_t, scriptid, Int32, args[0]);
1725    CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1);
1726    CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2);
1727    CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]);
1728  
1729    Handle<Script> script;
1730    CHECK(GetScriptById(isolate, scriptid, &script));
1731  
1732    return *ScriptLocationFromLine(isolate, script, opt_line, opt_column, offset);
1733  }
1734  
1735  // TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_ScriptPositionInfo)1736  RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) {
1737    HandleScope scope(isolate);
1738    DCHECK_EQ(3, args.length());
1739    CONVERT_ARG_CHECKED(JSValue, script, 0);
1740    CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
1741    CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
1742  
1743    CHECK(script->value()->IsScript());
1744    Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1745  
1746    const Script::OffsetFlag offset_flag =
1747        with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
1748    return *GetJSPositionInfo(script_handle, position, offset_flag, isolate);
1749  }
1750  
1751  // TODO(5530): Rename once conflicting function has been deleted.
RUNTIME_FUNCTION(Runtime_ScriptPositionInfo2)1752  RUNTIME_FUNCTION(Runtime_ScriptPositionInfo2) {
1753    HandleScope scope(isolate);
1754    DCHECK_EQ(3, args.length());
1755    CONVERT_NUMBER_CHECKED(int32_t, scriptid, Int32, args[0]);
1756    CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
1757    CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
1758  
1759    Handle<Script> script;
1760    CHECK(GetScriptById(isolate, scriptid, &script));
1761  
1762    const Script::OffsetFlag offset_flag =
1763        with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
1764    return *GetJSPositionInfo(script, position, offset_flag, isolate);
1765  }
1766  
1767  // Returns the given line as a string, or null if line is out of bounds.
1768  // The parameter line is expected to include the script's line offset.
1769  // TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_ScriptSourceLine)1770  RUNTIME_FUNCTION(Runtime_ScriptSourceLine) {
1771    HandleScope scope(isolate);
1772    DCHECK_EQ(2, args.length());
1773    CONVERT_ARG_CHECKED(JSValue, script, 0);
1774    CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1775  
1776    CHECK(script->value()->IsScript());
1777    Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1778  
1779    if (script_handle->type() == Script::TYPE_WASM) {
1780      // Return null for now; this function will disappear soon anyway.
1781      return isolate->heap()->null_value();
1782    }
1783  
1784    Script::InitLineEnds(script_handle);
1785  
1786    FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1787    const int line_count = line_ends_array->length();
1788  
1789    line -= script_handle->line_offset();
1790    if (line < 0 || line_count <= line) {
1791      return isolate->heap()->null_value();
1792    }
1793  
1794    const int start =
1795        (line == 0) ? 0 : Smi::cast(line_ends_array->get(line - 1))->value() + 1;
1796    const int end = Smi::cast(line_ends_array->get(line))->value();
1797  
1798    Handle<String> source =
1799        handle(String::cast(script_handle->source()), isolate);
1800    Handle<String> str = isolate->factory()->NewSubString(source, start, end);
1801  
1802    return *str;
1803  }
1804  
1805  // On function call, depending on circumstances, prepare for stepping in,
1806  // or perform a side effect check.
RUNTIME_FUNCTION(Runtime_DebugOnFunctionCall)1807  RUNTIME_FUNCTION(Runtime_DebugOnFunctionCall) {
1808    HandleScope scope(isolate);
1809    DCHECK_EQ(1, args.length());
1810    CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1811    if (isolate->debug()->last_step_action() >= StepIn) {
1812      isolate->debug()->PrepareStepIn(fun);
1813    }
1814    if (isolate->needs_side_effect_check() &&
1815        !isolate->debug()->PerformSideEffectCheck(fun)) {
1816      return isolate->heap()->exception();
1817    }
1818    return isolate->heap()->undefined_value();
1819  }
1820  
1821  // Set one shot breakpoints for the suspended generator object.
RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator)1822  RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) {
1823    HandleScope scope(isolate);
1824    DCHECK_EQ(0, args.length());
1825    isolate->debug()->PrepareStepInSuspendedGenerator();
1826    return isolate->heap()->undefined_value();
1827  }
1828  
RUNTIME_FUNCTION(Runtime_DebugRecordGenerator)1829  RUNTIME_FUNCTION(Runtime_DebugRecordGenerator) {
1830    HandleScope scope(isolate);
1831    DCHECK_EQ(1, args.length());
1832    CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
1833    CHECK(isolate->debug()->last_step_action() >= StepNext);
1834    isolate->debug()->RecordGenerator(generator);
1835    return isolate->heap()->undefined_value();
1836  }
1837  
RUNTIME_FUNCTION(Runtime_DebugPushPromise)1838  RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
1839    DCHECK_EQ(1, args.length());
1840    HandleScope scope(isolate);
1841    CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
1842    isolate->PushPromise(promise);
1843    return isolate->heap()->undefined_value();
1844  }
1845  
1846  
RUNTIME_FUNCTION(Runtime_DebugPopPromise)1847  RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
1848    DCHECK_EQ(0, args.length());
1849    SealHandleScope shs(isolate);
1850    isolate->PopPromise();
1851    return isolate->heap()->undefined_value();
1852  }
1853  
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionPromiseCreated)1854  RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionPromiseCreated) {
1855    DCHECK_EQ(1, args.length());
1856    HandleScope scope(isolate);
1857    CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
1858    isolate->PushPromise(promise);
1859    int id = isolate->debug()->NextAsyncTaskId(promise);
1860    Handle<Symbol> async_stack_id_symbol =
1861        isolate->factory()->promise_async_stack_id_symbol();
1862    JSObject::SetProperty(promise, async_stack_id_symbol,
1863                          handle(Smi::FromInt(id), isolate), STRICT)
1864        .Assert();
1865    isolate->debug()->OnAsyncTaskEvent(debug::kDebugEnqueueAsyncFunction, id, 0);
1866    return isolate->heap()->undefined_value();
1867  }
1868  
RUNTIME_FUNCTION(Runtime_DebugPromiseReject)1869  RUNTIME_FUNCTION(Runtime_DebugPromiseReject) {
1870    HandleScope scope(isolate);
1871    DCHECK_EQ(2, args.length());
1872    CONVERT_ARG_HANDLE_CHECKED(JSPromise, rejected_promise, 0);
1873    CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1874  
1875    isolate->debug()->OnPromiseReject(rejected_promise, value);
1876    return isolate->heap()->undefined_value();
1877  }
1878  
RUNTIME_FUNCTION(Runtime_DebugAsyncEventEnqueueRecurring)1879  RUNTIME_FUNCTION(Runtime_DebugAsyncEventEnqueueRecurring) {
1880    HandleScope scope(isolate);
1881    DCHECK_EQ(2, args.length());
1882    CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
1883    CONVERT_SMI_ARG_CHECKED(status, 1);
1884    if (isolate->debug()->is_active()) {
1885      isolate->debug()->OnAsyncTaskEvent(
1886          status == v8::Promise::kFulfilled ? debug::kDebugEnqueuePromiseResolve
1887                                            : debug::kDebugEnqueuePromiseReject,
1888          isolate->debug()->NextAsyncTaskId(promise), 0);
1889    }
1890    return isolate->heap()->undefined_value();
1891  }
1892  
RUNTIME_FUNCTION(Runtime_DebugIsActive)1893  RUNTIME_FUNCTION(Runtime_DebugIsActive) {
1894    SealHandleScope shs(isolate);
1895    return Smi::FromInt(isolate->debug()->is_active());
1896  }
1897  
RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode)1898  RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
1899    UNIMPLEMENTED();
1900    return NULL;
1901  }
1902  
RUNTIME_FUNCTION(Runtime_DebugCollectCoverage)1903  RUNTIME_FUNCTION(Runtime_DebugCollectCoverage) {
1904    HandleScope scope(isolate);
1905    DCHECK_EQ(0, args.length());
1906    // Collect coverage data.
1907    std::unique_ptr<Coverage> coverage(Coverage::Collect(isolate, false));
1908    Factory* factory = isolate->factory();
1909    // Turn the returned data structure into JavaScript.
1910    // Create an array of scripts.
1911    int num_scripts = static_cast<int>(coverage->size());
1912    // Prepare property keys.
1913    Handle<FixedArray> scripts_array = factory->NewFixedArray(num_scripts);
1914    Handle<String> script_string = factory->NewStringFromStaticChars("script");
1915    Handle<String> start_string = factory->NewStringFromStaticChars("start");
1916    Handle<String> end_string = factory->NewStringFromStaticChars("end");
1917    Handle<String> count_string = factory->NewStringFromStaticChars("count");
1918    for (int i = 0; i < num_scripts; i++) {
1919      const auto& script_data = coverage->at(i);
1920      HandleScope inner_scope(isolate);
1921      int num_functions = static_cast<int>(script_data.functions.size());
1922      Handle<FixedArray> functions_array = factory->NewFixedArray(num_functions);
1923      for (int j = 0; j < num_functions; j++) {
1924        const auto& function_data = script_data.functions[j];
1925        Handle<JSObject> range_obj = factory->NewJSObjectWithNullProto();
1926        JSObject::AddProperty(range_obj, start_string,
1927                              factory->NewNumberFromInt(function_data.start),
1928                              NONE);
1929        JSObject::AddProperty(range_obj, end_string,
1930                              factory->NewNumberFromInt(function_data.end), NONE);
1931        JSObject::AddProperty(range_obj, count_string,
1932                              factory->NewNumberFromUint(function_data.count),
1933                              NONE);
1934        functions_array->set(j, *range_obj);
1935      }
1936      Handle<JSArray> script_obj =
1937          factory->NewJSArrayWithElements(functions_array, FAST_ELEMENTS);
1938      Handle<JSObject> wrapper = Script::GetWrapper(script_data.script);
1939      JSObject::AddProperty(script_obj, script_string, wrapper, NONE);
1940      scripts_array->set(i, *script_obj);
1941    }
1942    return *factory->NewJSArrayWithElements(scripts_array, FAST_ELEMENTS);
1943  }
1944  
RUNTIME_FUNCTION(Runtime_DebugTogglePreciseCoverage)1945  RUNTIME_FUNCTION(Runtime_DebugTogglePreciseCoverage) {
1946    SealHandleScope shs(isolate);
1947    CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
1948    Coverage::TogglePrecise(isolate, enable);
1949    return isolate->heap()->undefined_value();
1950  }
1951  
1952  }  // namespace internal
1953  }  // namespace v8
1954