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