• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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/debug/debug-interface.h"
6 
7 #include "include/v8-function.h"
8 #include "src/api/api-inl.h"
9 #include "src/base/utils/random-number-generator.h"
10 #include "src/codegen/compiler.h"
11 #include "src/codegen/script-details.h"
12 #include "src/date/date.h"
13 #include "src/debug/debug-coverage.h"
14 #include "src/debug/debug-evaluate.h"
15 #include "src/debug/debug-property-iterator.h"
16 #include "src/debug/debug-type-profile.h"
17 #include "src/debug/debug.h"
18 #include "src/execution/vm-state-inl.h"
19 #include "src/heap/heap.h"
20 #include "src/objects/js-generator-inl.h"
21 #include "src/profiler/heap-profiler.h"
22 #include "src/strings/string-builder-inl.h"
23 
24 #if V8_ENABLE_WEBASSEMBLY
25 #include "src/debug/debug-wasm-objects-inl.h"
26 #include "src/wasm/wasm-engine.h"
27 #endif  // V8_ENABLE_WEBASSEMBLY
28 
29 // Has to be the last include (doesn't have include guards):
30 #include "src/api/api-macros.h"
31 
32 namespace v8 {
33 namespace debug {
34 
SetContextId(Local<Context> context,int id)35 void SetContextId(Local<Context> context, int id) {
36   Utils::OpenHandle(*context)->set_debug_context_id(i::Smi::FromInt(id));
37 }
38 
GetContextId(Local<Context> context)39 int GetContextId(Local<Context> context) {
40   i::Object value = Utils::OpenHandle(*context)->debug_context_id();
41   return (value.IsSmi()) ? i::Smi::ToInt(value) : 0;
42 }
43 
SetInspector(Isolate * isolate,v8_inspector::V8Inspector * inspector)44 void SetInspector(Isolate* isolate, v8_inspector::V8Inspector* inspector) {
45   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
46   i_isolate->set_inspector(inspector);
47 }
48 
GetInspector(Isolate * isolate)49 v8_inspector::V8Inspector* GetInspector(Isolate* isolate) {
50   return reinterpret_cast<i::Isolate*>(isolate)->inspector();
51 }
52 
GetBigIntDescription(Isolate * isolate,Local<BigInt> bigint)53 Local<String> GetBigIntDescription(Isolate* isolate, Local<BigInt> bigint) {
54   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
55   i::Handle<i::BigInt> i_bigint = Utils::OpenHandle(*bigint);
56   // For large BigInts computing the decimal string representation
57   // can take a long time, so we go with hexadecimal in that case.
58   int radix = (i_bigint->Words64Count() > 100 * 1000) ? 16 : 10;
59   i::Handle<i::String> string =
60       i::BigInt::ToString(i_isolate, i_bigint, radix, i::kDontThrow)
61           .ToHandleChecked();
62   if (radix == 16) {
63     if (i_bigint->IsNegative()) {
64       string = i_isolate->factory()
65                    ->NewConsString(
66                        i_isolate->factory()->NewStringFromAsciiChecked("-0x"),
67                        i_isolate->factory()->NewProperSubString(
68                            string, 1, string->length() - 1))
69                    .ToHandleChecked();
70     } else {
71       string =
72           i_isolate->factory()
73               ->NewConsString(
74                   i_isolate->factory()->NewStringFromAsciiChecked("0x"), string)
75               .ToHandleChecked();
76     }
77   }
78   i::Handle<i::String> description =
79       i_isolate->factory()
80           ->NewConsString(
81               string,
82               i_isolate->factory()->LookupSingleCharacterStringFromCode('n'))
83           .ToHandleChecked();
84   return Utils::ToLocal(description);
85 }
86 
GetDateDescription(Local<Date> date)87 Local<String> GetDateDescription(Local<Date> date) {
88   auto receiver = Utils::OpenHandle(*date);
89   i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(receiver);
90   i::Isolate* isolate = jsdate->GetIsolate();
91   auto buffer = i::ToDateString(jsdate->value().Number(), isolate->date_cache(),
92                                 i::ToDateStringMode::kLocalDateAndTime);
93   return Utils::ToLocal(isolate->factory()
94                             ->NewStringFromUtf8(base::VectorOf(buffer))
95                             .ToHandleChecked());
96 }
97 
GetFunctionDescription(Local<Function> function)98 Local<String> GetFunctionDescription(Local<Function> function) {
99   auto receiver = Utils::OpenHandle(*function);
100   if (receiver->IsJSBoundFunction()) {
101     return Utils::ToLocal(i::JSBoundFunction::ToString(
102         i::Handle<i::JSBoundFunction>::cast(receiver)));
103   }
104   if (receiver->IsJSFunction()) {
105     auto js_function = i::Handle<i::JSFunction>::cast(receiver);
106 #if V8_ENABLE_WEBASSEMBLY
107     if (js_function->shared().HasWasmExportedFunctionData()) {
108       auto isolate = js_function->GetIsolate();
109       auto func_index =
110           js_function->shared().wasm_exported_function_data().function_index();
111       auto instance = i::handle(
112           js_function->shared().wasm_exported_function_data().instance(),
113           isolate);
114       if (instance->module()->origin == i::wasm::kWasmOrigin) {
115         // For asm.js functions, we can still print the source
116         // code (hopefully), so don't bother with them here.
117         auto debug_name =
118             i::GetWasmFunctionDebugName(isolate, instance, func_index);
119         i::IncrementalStringBuilder builder(isolate);
120         builder.AppendCStringLiteral("function ");
121         builder.AppendString(debug_name);
122         builder.AppendCStringLiteral("() { [native code] }");
123         return Utils::ToLocal(builder.Finish().ToHandleChecked());
124       }
125     }
126 #endif  // V8_ENABLE_WEBASSEMBLY
127     return Utils::ToLocal(i::JSFunction::ToString(js_function));
128   }
129   return Utils::ToLocal(
130       receiver->GetIsolate()->factory()->function_native_code_string());
131 }
132 
SetBreakOnNextFunctionCall(Isolate * isolate)133 void SetBreakOnNextFunctionCall(Isolate* isolate) {
134   reinterpret_cast<i::Isolate*>(isolate)->debug()->SetBreakOnNextFunctionCall();
135 }
136 
ClearBreakOnNextFunctionCall(Isolate * isolate)137 void ClearBreakOnNextFunctionCall(Isolate* isolate) {
138   reinterpret_cast<i::Isolate*>(isolate)
139       ->debug()
140       ->ClearBreakOnNextFunctionCall();
141 }
142 
GetInternalProperties(Isolate * v8_isolate,Local<Value> value)143 MaybeLocal<Array> GetInternalProperties(Isolate* v8_isolate,
144                                         Local<Value> value) {
145   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
146   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
147   i::Handle<i::Object> val = Utils::OpenHandle(*value);
148   i::Handle<i::JSArray> result;
149   if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result))
150     return MaybeLocal<Array>();
151   return Utils::ToLocal(result);
152 }
153 
154 namespace {
155 
CollectPrivateMethodsAndAccessorsFromContext(i::Isolate * isolate,i::Handle<i::Context> context,i::IsStaticFlag is_static_flag,std::vector<Local<Value>> * names_out,std::vector<Local<Value>> * values_out)156 void CollectPrivateMethodsAndAccessorsFromContext(
157     i::Isolate* isolate, i::Handle<i::Context> context,
158     i::IsStaticFlag is_static_flag, std::vector<Local<Value>>* names_out,
159     std::vector<Local<Value>>* values_out) {
160   i::Handle<i::ScopeInfo> scope_info(context->scope_info(), isolate);
161   for (auto it : i::ScopeInfo::IterateLocalNames(scope_info)) {
162     i::Handle<i::String> name(it->name(), isolate);
163     i::VariableMode mode = scope_info->ContextLocalMode(it->index());
164     i::IsStaticFlag flag = scope_info->ContextLocalIsStaticFlag(it->index());
165     if (!i::IsPrivateMethodOrAccessorVariableMode(mode) ||
166         flag != is_static_flag) {
167       continue;
168     }
169     int context_index = scope_info->ContextHeaderLength() + it->index();
170     i::Handle<i::Object> slot_value(context->get(context_index), isolate);
171     DCHECK_IMPLIES(mode == i::VariableMode::kPrivateMethod,
172                    slot_value->IsJSFunction());
173     DCHECK_IMPLIES(mode != i::VariableMode::kPrivateMethod,
174                    slot_value->IsAccessorPair());
175     names_out->push_back(Utils::ToLocal(name));
176     values_out->push_back(Utils::ToLocal(slot_value));
177   }
178 }
179 
180 }  // namespace
181 
GetPrivateMembers(Local<Context> context,Local<Object> object,std::vector<Local<Value>> * names_out,std::vector<Local<Value>> * values_out)182 bool GetPrivateMembers(Local<Context> context, Local<Object> object,
183                        std::vector<Local<Value>>* names_out,
184                        std::vector<Local<Value>>* values_out) {
185   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
186   API_RCS_SCOPE(isolate, debug, GetPrivateMembers);
187   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
188   i::Handle<i::JSReceiver> receiver = Utils::OpenHandle(*object);
189   i::Handle<i::JSArray> names;
190   i::Handle<i::FixedArray> values;
191 
192   i::PropertyFilter key_filter =
193       static_cast<i::PropertyFilter>(i::PropertyFilter::PRIVATE_NAMES_ONLY);
194   i::Handle<i::FixedArray> keys;
195   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
196       isolate, keys,
197       i::KeyAccumulator::GetKeys(receiver, i::KeyCollectionMode::kOwnOnly,
198                                  key_filter,
199                                  i::GetKeysConversion::kConvertToString),
200       false);
201 
202   // Estimate number of private fields and private instance methods/accessors.
203   int private_entries_count = 0;
204   for (int i = 0; i < keys->length(); ++i) {
205     // Exclude the private brand symbols.
206     i::Handle<i::Symbol> key(i::Symbol::cast(keys->get(i)), isolate);
207     if (key->is_private_brand()) {
208       i::Handle<i::Object> value;
209       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
210           isolate, value, i::Object::GetProperty(isolate, receiver, key),
211           false);
212 
213       i::Handle<i::Context> value_context(i::Context::cast(*value), isolate);
214       i::Handle<i::ScopeInfo> scope_info(value_context->scope_info(), isolate);
215       // At least one slot contains the brand symbol so it does not count.
216       private_entries_count += (scope_info->ContextLocalCount() - 1);
217     } else {
218       private_entries_count++;
219     }
220   }
221 
222   // Estimate number of static private methods/accessors for classes.
223   bool has_static_private_methods_or_accessors = false;
224   if (receiver->IsJSFunction()) {
225     i::Handle<i::JSFunction> func(i::JSFunction::cast(*receiver), isolate);
226     i::Handle<i::SharedFunctionInfo> shared(func->shared(), isolate);
227     if (shared->is_class_constructor() &&
228         shared->has_static_private_methods_or_accessors()) {
229       has_static_private_methods_or_accessors = true;
230       i::Handle<i::Context> func_context(func->context(), isolate);
231       i::Handle<i::ScopeInfo> scope_info(func_context->scope_info(), isolate);
232       int local_count = scope_info->ContextLocalCount();
233       for (int j = 0; j < local_count; ++j) {
234         i::VariableMode mode = scope_info->ContextLocalMode(j);
235         i::IsStaticFlag is_static_flag =
236             scope_info->ContextLocalIsStaticFlag(j);
237         if (i::IsPrivateMethodOrAccessorVariableMode(mode) &&
238             is_static_flag == i::IsStaticFlag::kStatic) {
239           private_entries_count += local_count;
240           break;
241         }
242       }
243     }
244   }
245 
246   DCHECK(names_out->empty());
247   names_out->reserve(private_entries_count);
248   DCHECK(values_out->empty());
249   values_out->reserve(private_entries_count);
250 
251   if (has_static_private_methods_or_accessors) {
252     i::Handle<i::Context> recevier_context(
253         i::JSFunction::cast(*receiver).context(), isolate);
254     CollectPrivateMethodsAndAccessorsFromContext(isolate, recevier_context,
255                                                  i::IsStaticFlag::kStatic,
256                                                  names_out, values_out);
257   }
258 
259   for (int i = 0; i < keys->length(); ++i) {
260     i::Handle<i::Object> obj_key(keys->get(i), isolate);
261     i::Handle<i::Symbol> key(i::Symbol::cast(*obj_key), isolate);
262     CHECK(key->is_private_name());
263     i::Handle<i::Object> value;
264     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
265         isolate, value, i::Object::GetProperty(isolate, receiver, key), false);
266 
267     if (key->is_private_brand()) {
268       DCHECK(value->IsContext());
269       i::Handle<i::Context> value_context(i::Context::cast(*value), isolate);
270       CollectPrivateMethodsAndAccessorsFromContext(isolate, value_context,
271                                                    i::IsStaticFlag::kNotStatic,
272                                                    names_out, values_out);
273     } else {  // Private fields
274       i::Handle<i::String> name(
275           i::String::cast(i::Symbol::cast(*key).description()), isolate);
276       names_out->push_back(Utils::ToLocal(name));
277       values_out->push_back(Utils::ToLocal(value));
278     }
279   }
280 
281   DCHECK_EQ(names_out->size(), values_out->size());
282   DCHECK_LE(names_out->size(), private_entries_count);
283   return true;
284 }
285 
GetCreationContext(Local<Object> value)286 MaybeLocal<Context> GetCreationContext(Local<Object> value) {
287   i::Handle<i::Object> val = Utils::OpenHandle(*value);
288   if (val->IsJSGlobalProxy()) {
289     return MaybeLocal<Context>();
290   }
291   return value->GetCreationContext();
292 }
293 
ChangeBreakOnException(Isolate * isolate,ExceptionBreakState type)294 void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState type) {
295   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
296   internal_isolate->debug()->ChangeBreakOnException(
297       i::BreakException, type == BreakOnAnyException);
298   internal_isolate->debug()->ChangeBreakOnException(i::BreakUncaughtException,
299                                                     type != NoBreakOnException);
300 }
301 
SetBreakPointsActive(Isolate * v8_isolate,bool is_active)302 void SetBreakPointsActive(Isolate* v8_isolate, bool is_active) {
303   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
304   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
305   isolate->debug()->set_break_points_active(is_active);
306 }
307 
PrepareStep(Isolate * v8_isolate,StepAction action)308 void PrepareStep(Isolate* v8_isolate, StepAction action) {
309   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
310   ENTER_V8_DO_NOT_USE(isolate);
311   CHECK(isolate->debug()->CheckExecutionState());
312   // Clear all current stepping setup.
313   isolate->debug()->ClearStepping();
314   // Prepare step.
315   isolate->debug()->PrepareStep(static_cast<i::StepAction>(action));
316 }
317 
ClearStepping(Isolate * v8_isolate)318 void ClearStepping(Isolate* v8_isolate) {
319   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
320   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
321   // Clear all current stepping setup.
322   isolate->debug()->ClearStepping();
323 }
324 
BreakRightNow(Isolate * v8_isolate,base::EnumSet<debug::BreakReason> break_reasons)325 void BreakRightNow(Isolate* v8_isolate,
326                    base::EnumSet<debug::BreakReason> break_reasons) {
327   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
328   ENTER_V8_DO_NOT_USE(isolate);
329   isolate->debug()->HandleDebugBreak(i::kIgnoreIfAllFramesBlackboxed,
330                                      break_reasons);
331 }
332 
SetTerminateOnResume(Isolate * v8_isolate)333 void SetTerminateOnResume(Isolate* v8_isolate) {
334   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
335   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
336   isolate->debug()->SetTerminateOnResume();
337 }
338 
CanBreakProgram(Isolate * v8_isolate)339 bool CanBreakProgram(Isolate* v8_isolate) {
340   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
341   ENTER_V8_DO_NOT_USE(isolate);
342   return !isolate->debug()->AllFramesOnStackAreBlackboxed();
343 }
344 
Length() const345 size_t ScriptSource::Length() const {
346   i::Handle<i::HeapObject> source = Utils::OpenHandle(this);
347   if (source->IsString()) return i::Handle<i::String>::cast(source)->length();
348   return Size();
349 }
350 
Size() const351 size_t ScriptSource::Size() const {
352 #if V8_ENABLE_WEBASSEMBLY
353   MemorySpan<const uint8_t> wasm_bytecode;
354   if (WasmBytecode().To(&wasm_bytecode)) {
355     return wasm_bytecode.size();
356   }
357 #endif  // V8_ENABLE_WEBASSEMBLY
358   i::Handle<i::HeapObject> source = Utils::OpenHandle(this);
359   if (!source->IsString()) return 0;
360   i::Handle<i::String> string = i::Handle<i::String>::cast(source);
361   return string->length() * (string->IsTwoByteRepresentation() ? 2 : 1);
362 }
363 
JavaScriptCode() const364 MaybeLocal<String> ScriptSource::JavaScriptCode() const {
365   i::Handle<i::HeapObject> source = Utils::OpenHandle(this);
366   if (!source->IsString()) return MaybeLocal<String>();
367   return Utils::ToLocal(i::Handle<i::String>::cast(source));
368 }
369 
370 #if V8_ENABLE_WEBASSEMBLY
WasmBytecode() const371 Maybe<MemorySpan<const uint8_t>> ScriptSource::WasmBytecode() const {
372   i::Handle<i::HeapObject> source = Utils::OpenHandle(this);
373   if (!source->IsForeign()) return Nothing<MemorySpan<const uint8_t>>();
374   base::Vector<const uint8_t> wire_bytes =
375       i::Managed<i::wasm::NativeModule>::cast(*source).raw()->wire_bytes();
376   return Just(MemorySpan<const uint8_t>{wire_bytes.begin(), wire_bytes.size()});
377 }
378 #endif  // V8_ENABLE_WEBASSEMBLY
379 
GetIsolate() const380 Isolate* Script::GetIsolate() const {
381   return reinterpret_cast<Isolate*>(Utils::OpenHandle(this)->GetIsolate());
382 }
383 
OriginOptions() const384 ScriptOriginOptions Script::OriginOptions() const {
385   return Utils::OpenHandle(this)->origin_options();
386 }
387 
WasCompiled() const388 bool Script::WasCompiled() const {
389   return Utils::OpenHandle(this)->compilation_state() ==
390          i::Script::COMPILATION_STATE_COMPILED;
391 }
392 
IsEmbedded() const393 bool Script::IsEmbedded() const {
394   i::Handle<i::Script> script = Utils::OpenHandle(this);
395   return script->context_data() ==
396          script->GetReadOnlyRoots().uninitialized_symbol();
397 }
398 
Id() const399 int Script::Id() const { return Utils::OpenHandle(this)->id(); }
400 
StartLine() const401 int Script::StartLine() const { return Utils::OpenHandle(this)->line_offset(); }
402 
StartColumn() const403 int Script::StartColumn() const {
404   return Utils::OpenHandle(this)->column_offset();
405 }
406 
EndLine() const407 int Script::EndLine() const {
408   i::Handle<i::Script> script = Utils::OpenHandle(this);
409 #if V8_ENABLE_WEBASSEMBLY
410   if (script->type() == i::Script::TYPE_WASM) return 0;
411 #endif  // V8_ENABLE_WEBASSEMBLY
412   if (!script->source().IsString()) {
413     return script->line_offset();
414   }
415   i::Isolate* isolate = script->GetIsolate();
416   i::HandleScope scope(isolate);
417   i::Script::PositionInfo info;
418   i::Script::GetPositionInfo(script, i::String::cast(script->source()).length(),
419                              &info, i::Script::WITH_OFFSET);
420   return info.line;
421 }
422 
EndColumn() const423 int Script::EndColumn() const {
424   i::Handle<i::Script> script = Utils::OpenHandle(this);
425 #if V8_ENABLE_WEBASSEMBLY
426   if (script->type() == i::Script::TYPE_WASM) {
427     return script->wasm_native_module()->wire_bytes().length();
428   }
429 #endif  // V8_ENABLE_WEBASSEMBLY
430   if (!script->source().IsString()) {
431     return script->column_offset();
432   }
433   i::Isolate* isolate = script->GetIsolate();
434   i::HandleScope scope(isolate);
435   i::Script::PositionInfo info;
436   i::Script::GetPositionInfo(script, i::String::cast(script->source()).length(),
437                              &info, i::Script::WITH_OFFSET);
438   return info.column;
439 }
440 
Name() const441 MaybeLocal<String> Script::Name() const {
442   i::Handle<i::Script> script = Utils::OpenHandle(this);
443   i::Isolate* isolate = script->GetIsolate();
444   i::Handle<i::Object> value(script->name(), isolate);
445   if (!value->IsString()) return MaybeLocal<String>();
446   return Utils::ToLocal(i::Handle<i::String>::cast(value));
447 }
448 
SourceURL() const449 MaybeLocal<String> Script::SourceURL() const {
450   i::Handle<i::Script> script = Utils::OpenHandle(this);
451   i::Isolate* isolate = script->GetIsolate();
452   i::Handle<i::PrimitiveHeapObject> value(script->source_url(), isolate);
453   if (!value->IsString()) return MaybeLocal<String>();
454   return Utils::ToLocal(i::Handle<i::String>::cast(value));
455 }
456 
SourceMappingURL() const457 MaybeLocal<String> Script::SourceMappingURL() const {
458   i::Handle<i::Script> script = Utils::OpenHandle(this);
459   i::Isolate* isolate = script->GetIsolate();
460   i::Handle<i::Object> value(script->source_mapping_url(), isolate);
461   if (!value->IsString()) return MaybeLocal<String>();
462   return Utils::ToLocal(i::Handle<i::String>::cast(value));
463 }
464 
ContextId() const465 Maybe<int> Script::ContextId() const {
466   i::Handle<i::Script> script = Utils::OpenHandle(this);
467   i::Object value = script->context_data();
468   if (value.IsSmi()) return Just(i::Smi::ToInt(value));
469   return Nothing<int>();
470 }
471 
Source() const472 Local<ScriptSource> Script::Source() const {
473   i::Handle<i::Script> script = Utils::OpenHandle(this);
474   i::Isolate* isolate = script->GetIsolate();
475 #if V8_ENABLE_WEBASSEMBLY
476   if (script->type() == i::Script::TYPE_WASM) {
477     i::Handle<i::Object> wasm_native_module(
478         script->wasm_managed_native_module(), isolate);
479     return Utils::Convert<i::Object, ScriptSource>(wasm_native_module);
480   }
481 #endif  // V8_ENABLE_WEBASSEMBLY
482   i::Handle<i::PrimitiveHeapObject> source(script->source(), isolate);
483   return Utils::Convert<i::PrimitiveHeapObject, ScriptSource>(source);
484 }
485 
486 #if V8_ENABLE_WEBASSEMBLY
IsWasm() const487 bool Script::IsWasm() const {
488   return Utils::OpenHandle(this)->type() == i::Script::TYPE_WASM;
489 }
490 #endif  // V8_ENABLE_WEBASSEMBLY
491 
IsModule() const492 bool Script::IsModule() const {
493   return Utils::OpenHandle(this)->origin_options().IsModule();
494 }
495 
496 namespace {
497 
GetSmiValue(i::Handle<i::FixedArray> array,int index)498 int GetSmiValue(i::Handle<i::FixedArray> array, int index) {
499   return i::Smi::ToInt(array->get(index));
500 }
501 
CompareBreakLocation(const i::BreakLocation & loc1,const i::BreakLocation & loc2)502 bool CompareBreakLocation(const i::BreakLocation& loc1,
503                           const i::BreakLocation& loc2) {
504   return loc1.position() < loc2.position();
505 }
506 
507 }  // namespace
508 
GetPossibleBreakpoints(const Location & start,const Location & end,bool restrict_to_function,std::vector<BreakLocation> * locations) const509 bool Script::GetPossibleBreakpoints(
510     const Location& start, const Location& end, bool restrict_to_function,
511     std::vector<BreakLocation>* locations) const {
512   CHECK(!start.IsEmpty());
513   i::Handle<i::Script> script = Utils::OpenHandle(this);
514 #if V8_ENABLE_WEBASSEMBLY
515   if (script->type() == i::Script::TYPE_WASM) {
516     i::wasm::NativeModule* native_module = script->wasm_native_module();
517     return i::WasmScript::GetPossibleBreakpoints(native_module, start, end,
518                                                  locations);
519   }
520 #endif  // V8_ENABLE_WEBASSEMBLY
521 
522   i::Isolate* isolate = script->GetIsolate();
523   i::Script::InitLineEnds(isolate, script);
524   CHECK(script->line_ends().IsFixedArray());
525   i::Handle<i::FixedArray> line_ends =
526       i::Handle<i::FixedArray>::cast(i::handle(script->line_ends(), isolate));
527   CHECK(line_ends->length());
528 
529   int start_offset = GetSourceOffset(start);
530   int end_offset = end.IsEmpty()
531                        ? GetSmiValue(line_ends, line_ends->length() - 1) + 1
532                        : GetSourceOffset(end);
533   if (start_offset >= end_offset) return true;
534 
535   std::vector<i::BreakLocation> v8_locations;
536   if (!isolate->debug()->GetPossibleBreakpoints(
537           script, start_offset, end_offset, restrict_to_function,
538           &v8_locations)) {
539     return false;
540   }
541 
542   std::sort(v8_locations.begin(), v8_locations.end(), CompareBreakLocation);
543   int current_line_end_index = 0;
544   for (const auto& v8_location : v8_locations) {
545     int offset = v8_location.position();
546     while (offset > GetSmiValue(line_ends, current_line_end_index)) {
547       ++current_line_end_index;
548       CHECK(current_line_end_index < line_ends->length());
549     }
550     int line_offset = 0;
551 
552     if (current_line_end_index > 0) {
553       line_offset = GetSmiValue(line_ends, current_line_end_index - 1) + 1;
554     }
555     locations->emplace_back(
556         current_line_end_index + script->line_offset(),
557         offset - line_offset +
558             (current_line_end_index == 0 ? script->column_offset() : 0),
559         v8_location.type());
560   }
561   return true;
562 }
563 
GetSourceOffset(const Location & location) const564 int Script::GetSourceOffset(const Location& location) const {
565   i::Handle<i::Script> script = Utils::OpenHandle(this);
566 #if V8_ENABLE_WEBASSEMBLY
567   if (script->type() == i::Script::TYPE_WASM) {
568     DCHECK_EQ(0, location.GetLineNumber());
569     return location.GetColumnNumber();
570   }
571 #endif  // V8_ENABLE_WEBASSEMBLY
572 
573   int line = std::max(location.GetLineNumber() - script->line_offset(), 0);
574   int column = location.GetColumnNumber();
575   if (line == 0) {
576     column = std::max(0, column - script->column_offset());
577   }
578 
579   i::Script::InitLineEnds(script->GetIsolate(), script);
580   CHECK(script->line_ends().IsFixedArray());
581   i::Handle<i::FixedArray> line_ends = i::Handle<i::FixedArray>::cast(
582       i::handle(script->line_ends(), script->GetIsolate()));
583   CHECK(line_ends->length());
584   if (line >= line_ends->length())
585     return GetSmiValue(line_ends, line_ends->length() - 1);
586   int line_offset = GetSmiValue(line_ends, line);
587   if (line == 0) return std::min(column, line_offset);
588   int prev_line_offset = GetSmiValue(line_ends, line - 1);
589   return std::min(prev_line_offset + column + 1, line_offset);
590 }
591 
GetSourceLocation(int offset) const592 Location Script::GetSourceLocation(int offset) const {
593   i::Handle<i::Script> script = Utils::OpenHandle(this);
594   i::Script::PositionInfo info;
595   i::Script::GetPositionInfo(script, offset, &info, i::Script::WITH_OFFSET);
596   if (script->HasSourceURLComment()) {
597     info.line -= script->line_offset();
598     if (info.line == 0) info.column -= script->column_offset();
599   }
600   return Location(info.line, info.column);
601 }
602 
SetScriptSource(Local<String> newSource,bool preview,LiveEditResult * result) const603 bool Script::SetScriptSource(Local<String> newSource, bool preview,
604                              LiveEditResult* result) const {
605   i::Handle<i::Script> script = Utils::OpenHandle(this);
606   i::Isolate* isolate = script->GetIsolate();
607   return isolate->debug()->SetScriptSource(
608       script, Utils::OpenHandle(*newSource), preview, result);
609 }
610 
SetBreakpoint(Local<String> condition,Location * location,BreakpointId * id) const611 bool Script::SetBreakpoint(Local<String> condition, Location* location,
612                            BreakpointId* id) const {
613   i::Handle<i::Script> script = Utils::OpenHandle(this);
614   i::Isolate* isolate = script->GetIsolate();
615   int offset = GetSourceOffset(*location);
616   if (!isolate->debug()->SetBreakPointForScript(
617           script, Utils::OpenHandle(*condition), &offset, id)) {
618     return false;
619   }
620   *location = GetSourceLocation(offset);
621   return true;
622 }
623 
SetInstrumentationBreakpoint(BreakpointId * id) const624 bool Script::SetInstrumentationBreakpoint(BreakpointId* id) const {
625   i::Handle<i::Script> script = Utils::OpenHandle(this);
626   i::Isolate* isolate = script->GetIsolate();
627 #if V8_ENABLE_WEBASSEMBLY
628   if (script->type() == i::Script::TYPE_WASM) {
629     isolate->debug()->SetInstrumentationBreakpointForWasmScript(script, id);
630     return true;
631   }
632 #endif  // V8_ENABLE_WEBASSEMBLY
633   i::SharedFunctionInfo::ScriptIterator it(isolate, *script);
634   for (i::SharedFunctionInfo sfi = it.Next(); !sfi.is_null(); sfi = it.Next()) {
635     if (sfi.is_toplevel()) {
636       return isolate->debug()->SetBreakpointForFunction(
637           handle(sfi, isolate), isolate->factory()->empty_string(), id,
638           internal::Debug::kInstrumentation);
639     }
640   }
641   return false;
642 }
643 
644 #if V8_ENABLE_WEBASSEMBLY
RemoveWasmBreakpoint(BreakpointId id)645 void Script::RemoveWasmBreakpoint(BreakpointId id) {
646   i::Handle<i::Script> script = Utils::OpenHandle(this);
647   i::Isolate* isolate = script->GetIsolate();
648   isolate->debug()->RemoveBreakpointForWasmScript(script, id);
649 }
650 #endif  //  V8_ENABLE_WEBASSEMBLY
651 
RemoveBreakpoint(Isolate * v8_isolate,BreakpointId id)652 void RemoveBreakpoint(Isolate* v8_isolate, BreakpointId id) {
653   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
654   i::HandleScope handle_scope(isolate);
655   isolate->debug()->RemoveBreakpoint(id);
656 }
657 
GetCurrentPlatform()658 Platform* GetCurrentPlatform() { return i::V8::GetCurrentPlatform(); }
659 
ForceGarbageCollection(Isolate * isolate,EmbedderHeapTracer::EmbedderStackState embedder_stack_state)660 void ForceGarbageCollection(
661     Isolate* isolate,
662     EmbedderHeapTracer::EmbedderStackState embedder_stack_state) {
663   i::EmbedderStackStateScope stack_scope(
664       reinterpret_cast<i::Isolate*>(isolate)->heap(),
665       i::EmbedderStackStateScope::kImplicitThroughTask, embedder_stack_state);
666   isolate->LowMemoryNotification();
667 }
668 
669 #if V8_ENABLE_WEBASSEMBLY
Cast(Script * script)670 WasmScript* WasmScript::Cast(Script* script) {
671   CHECK(script->IsWasm());
672   return static_cast<WasmScript*>(script);
673 }
674 
GetDebugSymbolType() const675 WasmScript::DebugSymbolsType WasmScript::GetDebugSymbolType() const {
676   i::Handle<i::Script> script = Utils::OpenHandle(this);
677   DCHECK_EQ(i::Script::TYPE_WASM, script->type());
678   switch (script->wasm_native_module()->module()->debug_symbols.type) {
679     case i::wasm::WasmDebugSymbols::Type::None:
680       return WasmScript::DebugSymbolsType::None;
681     case i::wasm::WasmDebugSymbols::Type::EmbeddedDWARF:
682       return WasmScript::DebugSymbolsType::EmbeddedDWARF;
683     case i::wasm::WasmDebugSymbols::Type::ExternalDWARF:
684       return WasmScript::DebugSymbolsType::ExternalDWARF;
685     case i::wasm::WasmDebugSymbols::Type::SourceMap:
686       return WasmScript::DebugSymbolsType::SourceMap;
687   }
688 }
689 
ExternalSymbolsURL() const690 MemorySpan<const char> WasmScript::ExternalSymbolsURL() const {
691   i::Handle<i::Script> script = Utils::OpenHandle(this);
692   DCHECK_EQ(i::Script::TYPE_WASM, script->type());
693 
694   const i::wasm::WasmDebugSymbols& symbols =
695       script->wasm_native_module()->module()->debug_symbols;
696   if (symbols.external_url.is_empty()) return {};
697 
698   internal::wasm::ModuleWireBytes wire_bytes(
699       script->wasm_native_module()->wire_bytes());
700   i::wasm::WasmName external_url =
701       wire_bytes.GetNameOrNull(symbols.external_url);
702   return {external_url.data(), external_url.size()};
703 }
704 
NumFunctions() const705 int WasmScript::NumFunctions() const {
706   i::DisallowGarbageCollection no_gc;
707   i::Handle<i::Script> script = Utils::OpenHandle(this);
708   DCHECK_EQ(i::Script::TYPE_WASM, script->type());
709   i::wasm::NativeModule* native_module = script->wasm_native_module();
710   const i::wasm::WasmModule* module = native_module->module();
711   DCHECK_GE(i::kMaxInt, module->functions.size());
712   return static_cast<int>(module->functions.size());
713 }
714 
NumImportedFunctions() const715 int WasmScript::NumImportedFunctions() const {
716   i::DisallowGarbageCollection no_gc;
717   i::Handle<i::Script> script = Utils::OpenHandle(this);
718   DCHECK_EQ(i::Script::TYPE_WASM, script->type());
719   i::wasm::NativeModule* native_module = script->wasm_native_module();
720   const i::wasm::WasmModule* module = native_module->module();
721   DCHECK_GE(i::kMaxInt, module->num_imported_functions);
722   return static_cast<int>(module->num_imported_functions);
723 }
724 
GetFunctionRange(int function_index) const725 std::pair<int, int> WasmScript::GetFunctionRange(int function_index) const {
726   i::DisallowGarbageCollection no_gc;
727   i::Handle<i::Script> script = Utils::OpenHandle(this);
728   DCHECK_EQ(i::Script::TYPE_WASM, script->type());
729   i::wasm::NativeModule* native_module = script->wasm_native_module();
730   const i::wasm::WasmModule* module = native_module->module();
731   DCHECK_LE(0, function_index);
732   DCHECK_GT(module->functions.size(), function_index);
733   const i::wasm::WasmFunction& func = module->functions[function_index];
734   DCHECK_GE(i::kMaxInt, func.code.offset());
735   DCHECK_GE(i::kMaxInt, func.code.end_offset());
736   return std::make_pair(static_cast<int>(func.code.offset()),
737                         static_cast<int>(func.code.end_offset()));
738 }
739 
GetContainingFunction(int byte_offset) const740 int WasmScript::GetContainingFunction(int byte_offset) const {
741   i::DisallowGarbageCollection no_gc;
742   i::Handle<i::Script> script = Utils::OpenHandle(this);
743   DCHECK_EQ(i::Script::TYPE_WASM, script->type());
744   i::wasm::NativeModule* native_module = script->wasm_native_module();
745   const i::wasm::WasmModule* module = native_module->module();
746   DCHECK_LE(0, byte_offset);
747 
748   return i::wasm::GetContainingWasmFunction(module, byte_offset);
749 }
750 
GetFunctionHash(int function_index)751 uint32_t WasmScript::GetFunctionHash(int function_index) {
752   i::DisallowGarbageCollection no_gc;
753   i::Handle<i::Script> script = Utils::OpenHandle(this);
754   DCHECK_EQ(i::Script::TYPE_WASM, script->type());
755   i::wasm::NativeModule* native_module = script->wasm_native_module();
756   const i::wasm::WasmModule* module = native_module->module();
757   DCHECK_LE(0, function_index);
758   DCHECK_GT(module->functions.size(), function_index);
759   const i::wasm::WasmFunction& func = module->functions[function_index];
760   i::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes());
761   base::Vector<const i::byte> function_bytes =
762       wire_bytes.GetFunctionBytes(&func);
763   // TODO(herhut): Maybe also take module, name and signature into account.
764   return i::StringHasher::HashSequentialString(function_bytes.begin(),
765                                                function_bytes.length(), 0);
766 }
767 
CodeOffset() const768 int WasmScript::CodeOffset() const {
769   i::Handle<i::Script> script = Utils::OpenHandle(this);
770   DCHECK_EQ(i::Script::TYPE_WASM, script->type());
771   i::wasm::NativeModule* native_module = script->wasm_native_module();
772   const i::wasm::WasmModule* module = native_module->module();
773 
774   // If the module contains at least one function, the code offset must have
775   // been initialized, and it cannot be zero.
776   DCHECK_IMPLIES(module->num_declared_functions > 0,
777                  module->code.offset() != 0);
778   return module->code.offset();
779 }
780 #endif  // V8_ENABLE_WEBASSEMBLY
781 
Location(int line_number,int column_number)782 Location::Location(int line_number, int column_number)
783     : line_number_(line_number),
784       column_number_(column_number),
785       is_empty_(false) {}
786 
Location()787 Location::Location()
788     : line_number_(Function::kLineOffsetNotFound),
789       column_number_(Function::kLineOffsetNotFound),
790       is_empty_(true) {}
791 
GetLineNumber() const792 int Location::GetLineNumber() const {
793   DCHECK(!IsEmpty());
794   return line_number_;
795 }
796 
GetColumnNumber() const797 int Location::GetColumnNumber() const {
798   DCHECK(!IsEmpty());
799   return column_number_;
800 }
801 
IsEmpty() const802 bool Location::IsEmpty() const { return is_empty_; }
803 
GetLoadedScripts(Isolate * v8_isolate,PersistentValueVector<Script> & scripts)804 void GetLoadedScripts(Isolate* v8_isolate,
805                       PersistentValueVector<Script>& scripts) {
806   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
807   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
808   {
809     i::DisallowGarbageCollection no_gc;
810     i::Script::Iterator iterator(isolate);
811     for (i::Script script = iterator.Next(); !script.is_null();
812          script = iterator.Next()) {
813 #if V8_ENABLE_WEBASSEMBLY
814       if (script.type() != i::Script::TYPE_NORMAL &&
815           script.type() != i::Script::TYPE_WASM) {
816         continue;
817       }
818 #else
819       if (script.type() != i::Script::TYPE_NORMAL) continue;
820 #endif  // V8_ENABLE_WEBASSEMBLY
821       if (!script.HasValidSource()) continue;
822       i::HandleScope handle_scope(isolate);
823       i::Handle<i::Script> script_handle(script, isolate);
824       scripts.Append(ToApiHandle<Script>(script_handle));
825     }
826   }
827 }
828 
CompileInspectorScript(Isolate * v8_isolate,Local<String> source)829 MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* v8_isolate,
830                                                  Local<String> source) {
831   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
832   PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, UnboundScript);
833   i::Handle<i::String> str = Utils::OpenHandle(*source);
834   i::Handle<i::SharedFunctionInfo> result;
835   {
836     i::AlignedCachedData* cached_data = nullptr;
837     i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info =
838         i::Compiler::GetSharedFunctionInfoForScriptWithCachedData(
839             isolate, str, i::ScriptDetails(), cached_data,
840             ScriptCompiler::kNoCompileOptions,
841             ScriptCompiler::kNoCacheBecauseInspector,
842             i::FLAG_expose_inspector_scripts ? i::NOT_NATIVES_CODE
843                                              : i::INSPECTOR_CODE);
844     has_pending_exception = !maybe_function_info.ToHandle(&result);
845     RETURN_ON_FAILED_EXECUTION(UnboundScript);
846   }
847   RETURN_ESCAPED(ToApiHandle<UnboundScript>(result));
848 }
849 
850 #if V8_ENABLE_WEBASSEMBLY
TierDownAllModulesPerIsolate(Isolate * v8_isolate)851 void TierDownAllModulesPerIsolate(Isolate* v8_isolate) {
852   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
853   i::wasm::GetWasmEngine()->TierDownAllModulesPerIsolate(isolate);
854 }
855 
TierUpAllModulesPerIsolate(Isolate * v8_isolate)856 void TierUpAllModulesPerIsolate(Isolate* v8_isolate) {
857   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
858   i::wasm::GetWasmEngine()->TierUpAllModulesPerIsolate(isolate);
859 }
860 #endif  // V8_ENABLE_WEBASSEMBLY
861 
SetDebugDelegate(Isolate * v8_isolate,DebugDelegate * delegate)862 void SetDebugDelegate(Isolate* v8_isolate, DebugDelegate* delegate) {
863   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
864   isolate->debug()->SetDebugDelegate(delegate);
865 }
866 
SetAsyncEventDelegate(Isolate * v8_isolate,AsyncEventDelegate * delegate)867 void SetAsyncEventDelegate(Isolate* v8_isolate, AsyncEventDelegate* delegate) {
868   reinterpret_cast<i::Isolate*>(v8_isolate)->set_async_event_delegate(delegate);
869 }
870 
ResetBlackboxedStateCache(Isolate * v8_isolate,Local<Script> script)871 void ResetBlackboxedStateCache(Isolate* v8_isolate, Local<Script> script) {
872   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
873   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
874   i::DisallowGarbageCollection no_gc;
875   i::SharedFunctionInfo::ScriptIterator iter(isolate,
876                                              *Utils::OpenHandle(*script));
877   for (i::SharedFunctionInfo info = iter.Next(); !info.is_null();
878        info = iter.Next()) {
879     if (info.HasDebugInfo()) {
880       info.GetDebugInfo().set_computed_debug_is_blackboxed(false);
881     }
882   }
883 }
884 
EstimatedValueSize(Isolate * v8_isolate,Local<Value> value)885 int EstimatedValueSize(Isolate* v8_isolate, Local<Value> value) {
886   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
887   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
888   i::Handle<i::Object> object = Utils::OpenHandle(*value);
889   if (object->IsSmi()) return i::kTaggedSize;
890   CHECK(object->IsHeapObject());
891   return i::Handle<i::HeapObject>::cast(object)->Size();
892 }
893 
CheckCast(Value * that)894 void AccessorPair::CheckCast(Value* that) {
895   i::Handle<i::Object> obj = Utils::OpenHandle(that);
896   Utils::ApiCheck(obj->IsAccessorPair(), "v8::debug::AccessorPair::Cast",
897                   "Value is not a v8::debug::AccessorPair");
898 }
899 
900 #if V8_ENABLE_WEBASSEMBLY
CheckCast(Value * that)901 void WasmValueObject::CheckCast(Value* that) {
902   i::Handle<i::Object> obj = Utils::OpenHandle(that);
903   Utils::ApiCheck(obj->IsWasmValueObject(), "v8::debug::WasmValueObject::Cast",
904                   "Value is not a v8::debug::WasmValueObject");
905 }
906 
IsWasmValueObject(Local<Value> that)907 bool WasmValueObject::IsWasmValueObject(Local<Value> that) {
908   i::Handle<i::Object> obj = Utils::OpenHandle(*that);
909   return obj->IsWasmValueObject();
910 }
911 
type() const912 Local<String> WasmValueObject::type() const {
913   i::Handle<i::WasmValueObject> object =
914       i::Handle<i::WasmValueObject>::cast(Utils::OpenHandle(this));
915   i::Isolate* isolate = object->GetIsolate();
916   i::Handle<i::String> type(object->type(), isolate);
917   return Utils::ToLocal(type);
918 }
919 #endif  // V8_ENABLE_WEBASSEMBLY
920 
GetBuiltin(Isolate * v8_isolate,Builtin requested_builtin)921 Local<Function> GetBuiltin(Isolate* v8_isolate, Builtin requested_builtin) {
922   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
923   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
924   i::HandleScope handle_scope(isolate);
925 
926   CHECK_EQ(requested_builtin, kStringToLowerCase);
927   i::Builtin builtin = i::Builtin::kStringPrototypeToLocaleLowerCase;
928 
929   i::Factory* factory = isolate->factory();
930   i::Handle<i::String> name = isolate->factory()->empty_string();
931   i::Handle<i::NativeContext> context(isolate->native_context());
932   i::Handle<i::SharedFunctionInfo> info =
933       factory->NewSharedFunctionInfoForBuiltin(name, builtin);
934   info->set_language_mode(i::LanguageMode::kStrict);
935   i::Handle<i::JSFunction> fun =
936       i::Factory::JSFunctionBuilder{isolate, info, context}
937           .set_map(isolate->strict_function_without_prototype_map())
938           .Build();
939 
940   fun->shared().set_internal_formal_parameter_count(i::JSParameterCount(0));
941   fun->shared().set_length(0);
942   return Utils::ToLocal(handle_scope.CloseAndEscape(fun));
943 }
944 
SetConsoleDelegate(Isolate * v8_isolate,ConsoleDelegate * delegate)945 void SetConsoleDelegate(Isolate* v8_isolate, ConsoleDelegate* delegate) {
946   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
947   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
948   isolate->set_console_delegate(delegate);
949 }
950 
ConsoleCallArguments(const v8::FunctionCallbackInfo<v8::Value> & info)951 ConsoleCallArguments::ConsoleCallArguments(
952     const v8::FunctionCallbackInfo<v8::Value>& info)
953     : v8::FunctionCallbackInfo<v8::Value>(nullptr, info.values_, info.length_) {
954 }
955 
ConsoleCallArguments(const internal::BuiltinArguments & args)956 ConsoleCallArguments::ConsoleCallArguments(
957     const internal::BuiltinArguments& args)
958     : v8::FunctionCallbackInfo<v8::Value>(
959           nullptr,
960           // Drop the first argument (receiver, i.e. the "console" object).
961           args.length() > 1 ? args.address_of_first_argument() : nullptr,
962           args.length() - 1) {}
963 
CreateMessageFromException(Isolate * v8_isolate,v8::Local<v8::Value> v8_error)964 v8::Local<v8::Message> CreateMessageFromException(
965     Isolate* v8_isolate, v8::Local<v8::Value> v8_error) {
966   i::Handle<i::Object> obj = Utils::OpenHandle(*v8_error);
967   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
968   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
969   i::HandleScope scope(isolate);
970   return Utils::MessageToLocal(
971       scope.CloseAndEscape(isolate->CreateMessageFromException(obj)));
972 }
973 
Script()974 MaybeLocal<Script> GeneratorObject::Script() {
975   i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this);
976   i::Object maybe_script = obj->function().shared().script();
977   if (!maybe_script.IsScript()) return {};
978   i::Handle<i::Script> script(i::Script::cast(maybe_script), obj->GetIsolate());
979   return ToApiHandle<v8::debug::Script>(script);
980 }
981 
Function()982 Local<Function> GeneratorObject::Function() {
983   i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this);
984   return Utils::ToLocal(handle(obj->function(), obj->GetIsolate()));
985 }
986 
SuspendedLocation()987 Location GeneratorObject::SuspendedLocation() {
988   i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this);
989   CHECK(obj->is_suspended());
990   i::Object maybe_script = obj->function().shared().script();
991   if (!maybe_script.IsScript()) return Location();
992   i::Isolate* isolate = obj->GetIsolate();
993   i::Handle<i::Script> script(i::Script::cast(maybe_script), isolate);
994   i::Script::PositionInfo info;
995   i::SharedFunctionInfo::EnsureSourcePositionsAvailable(
996       isolate, i::handle(obj->function().shared(), isolate));
997   i::Script::GetPositionInfo(script, obj->source_position(), &info,
998                              i::Script::WITH_OFFSET);
999   return Location(info.line, info.column);
1000 }
1001 
IsSuspended()1002 bool GeneratorObject::IsSuspended() {
1003   return Utils::OpenHandle(this)->is_suspended();
1004 }
1005 
Cast(v8::Local<v8::Value> value)1006 v8::Local<GeneratorObject> GeneratorObject::Cast(v8::Local<v8::Value> value) {
1007   CHECK(value->IsGeneratorObject());
1008   return ToApiHandle<GeneratorObject>(Utils::OpenHandle(*value));
1009 }
1010 
CallFunctionOn(Local<Context> context,Local<Function> function,Local<Value> recv,int argc,Local<Value> argv[],bool throw_on_side_effect)1011 MaybeLocal<Value> CallFunctionOn(Local<Context> context,
1012                                  Local<Function> function, Local<Value> recv,
1013                                  int argc, Local<Value> argv[],
1014                                  bool throw_on_side_effect) {
1015   auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
1016   PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, Value);
1017   auto self = Utils::OpenHandle(*function);
1018   auto recv_obj = Utils::OpenHandle(*recv);
1019   STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>));
1020   auto args = reinterpret_cast<i::Handle<i::Object>*>(argv);
1021   // Disable breaks in side-effect free mode.
1022   i::DisableBreak disable_break_scope(isolate->debug(), throw_on_side_effect);
1023   if (throw_on_side_effect) {
1024     isolate->debug()->StartSideEffectCheckMode();
1025   }
1026   Local<Value> result;
1027   has_pending_exception = !ToLocal<Value>(
1028       i::Execution::Call(isolate, self, recv_obj, argc, args), &result);
1029   if (throw_on_side_effect) {
1030     isolate->debug()->StopSideEffectCheckMode();
1031   }
1032   RETURN_ON_FAILED_EXECUTION(Value);
1033   RETURN_ESCAPED(result);
1034 }
1035 
EvaluateGlobal(v8::Isolate * isolate,v8::Local<v8::String> source,EvaluateGlobalMode mode,bool repl)1036 MaybeLocal<v8::Value> EvaluateGlobal(v8::Isolate* isolate,
1037                                      v8::Local<v8::String> source,
1038                                      EvaluateGlobalMode mode, bool repl) {
1039   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
1040   PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(internal_isolate, Value);
1041   i::REPLMode repl_mode = repl ? i::REPLMode::kYes : i::REPLMode::kNo;
1042   Local<Value> result;
1043   has_pending_exception = !ToLocal<Value>(
1044       i::DebugEvaluate::Global(internal_isolate, Utils::OpenHandle(*source),
1045                                mode, repl_mode),
1046       &result);
1047   RETURN_ON_FAILED_EXECUTION(Value);
1048   RETURN_ESCAPED(result);
1049 }
1050 
EvaluateGlobalForTesting(v8::Isolate * isolate,v8::Local<v8::Script> function,v8::debug::EvaluateGlobalMode mode,bool repl)1051 v8::MaybeLocal<v8::Value> EvaluateGlobalForTesting(
1052     v8::Isolate* isolate, v8::Local<v8::Script> function,
1053     v8::debug::EvaluateGlobalMode mode, bool repl) {
1054   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
1055   PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(internal_isolate, Value);
1056   i::REPLMode repl_mode = repl ? i::REPLMode::kYes : i::REPLMode::kNo;
1057   Local<Value> result;
1058   has_pending_exception = !ToLocal<Value>(
1059       i::DebugEvaluate::Global(internal_isolate, Utils::OpenHandle(*function),
1060                                mode, repl_mode),
1061       &result);
1062   RETURN_ON_FAILED_EXECUTION(Value);
1063   RETURN_ESCAPED(result);
1064 }
1065 
QueryObjects(v8::Local<v8::Context> v8_context,QueryObjectPredicate * predicate,PersistentValueVector<v8::Object> * objects)1066 void QueryObjects(v8::Local<v8::Context> v8_context,
1067                   QueryObjectPredicate* predicate,
1068                   PersistentValueVector<v8::Object>* objects) {
1069   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_context->GetIsolate());
1070   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1071   isolate->heap_profiler()->QueryObjects(Utils::OpenHandle(*v8_context),
1072                                          predicate, objects);
1073 }
1074 
GlobalLexicalScopeNames(v8::Local<v8::Context> v8_context,v8::PersistentValueVector<v8::String> * names)1075 void GlobalLexicalScopeNames(v8::Local<v8::Context> v8_context,
1076                              v8::PersistentValueVector<v8::String>* names) {
1077   i::Handle<i::Context> context = Utils::OpenHandle(*v8_context);
1078   i::Isolate* isolate = context->GetIsolate();
1079   i::Handle<i::ScriptContextTable> table(
1080       context->global_object().native_context().script_context_table(),
1081       isolate);
1082   for (int i = 0; i < table->used(kAcquireLoad); i++) {
1083     i::Handle<i::Context> script_context =
1084         i::ScriptContextTable::GetContext(isolate, table, i);
1085     DCHECK(script_context->IsScriptContext());
1086     i::Handle<i::ScopeInfo> scope_info(script_context->scope_info(), isolate);
1087     for (auto it : i::ScopeInfo::IterateLocalNames(scope_info)) {
1088       if (i::ScopeInfo::VariableIsSynthetic(it->name())) continue;
1089       names->Append(Utils::ToLocal(handle(it->name(), isolate)));
1090     }
1091   }
1092 }
1093 
SetReturnValue(v8::Isolate * v8_isolate,v8::Local<v8::Value> value)1094 void SetReturnValue(v8::Isolate* v8_isolate, v8::Local<v8::Value> value) {
1095   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1096   isolate->debug()->set_return_value(*Utils::OpenHandle(*value));
1097 }
1098 
GetNextRandomInt64(v8::Isolate * v8_isolate)1099 int64_t GetNextRandomInt64(v8::Isolate* v8_isolate) {
1100   return reinterpret_cast<i::Isolate*>(v8_isolate)
1101       ->random_number_generator()
1102       ->NextInt64();
1103 }
1104 
GetDebuggingId(v8::Local<v8::Function> function)1105 int GetDebuggingId(v8::Local<v8::Function> function) {
1106   i::Handle<i::JSReceiver> callable = v8::Utils::OpenHandle(*function);
1107   if (!callable->IsJSFunction()) return i::DebugInfo::kNoDebuggingId;
1108   i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(callable);
1109   int id = func->GetIsolate()->debug()->GetFunctionDebuggingId(func);
1110   DCHECK_NE(i::DebugInfo::kNoDebuggingId, id);
1111   return id;
1112 }
1113 
SetFunctionBreakpoint(v8::Local<v8::Function> function,v8::Local<v8::String> condition,BreakpointId * id)1114 bool SetFunctionBreakpoint(v8::Local<v8::Function> function,
1115                            v8::Local<v8::String> condition, BreakpointId* id) {
1116   i::Handle<i::JSReceiver> callable = Utils::OpenHandle(*function);
1117   if (!callable->IsJSFunction()) return false;
1118   i::Handle<i::JSFunction> jsfunction =
1119       i::Handle<i::JSFunction>::cast(callable);
1120   i::Isolate* isolate = jsfunction->GetIsolate();
1121   i::Handle<i::String> condition_string =
1122       condition.IsEmpty() ? isolate->factory()->empty_string()
1123                           : Utils::OpenHandle(*condition);
1124   return isolate->debug()->SetBreakpointForFunction(
1125       handle(jsfunction->shared(), isolate), condition_string, id);
1126 }
1127 
PostponeInterruptsScope(v8::Isolate * isolate)1128 PostponeInterruptsScope::PostponeInterruptsScope(v8::Isolate* isolate)
1129     : scope_(
1130           new i::PostponeInterruptsScope(reinterpret_cast<i::Isolate*>(isolate),
1131                                          i::StackGuard::API_INTERRUPT)) {}
1132 
1133 PostponeInterruptsScope::~PostponeInterruptsScope() = default;
1134 
DisableBreakScope(v8::Isolate * isolate)1135 DisableBreakScope::DisableBreakScope(v8::Isolate* isolate)
1136     : scope_(std::make_unique<i::DisableBreak>(
1137           reinterpret_cast<i::Isolate*>(isolate)->debug())) {}
1138 
1139 DisableBreakScope::~DisableBreakScope() = default;
1140 
StartOffset() const1141 int Coverage::BlockData::StartOffset() const { return block_->start; }
1142 
EndOffset() const1143 int Coverage::BlockData::EndOffset() const { return block_->end; }
1144 
Count() const1145 uint32_t Coverage::BlockData::Count() const { return block_->count; }
1146 
StartOffset() const1147 int Coverage::FunctionData::StartOffset() const { return function_->start; }
1148 
EndOffset() const1149 int Coverage::FunctionData::EndOffset() const { return function_->end; }
1150 
Count() const1151 uint32_t Coverage::FunctionData::Count() const { return function_->count; }
1152 
Name() const1153 MaybeLocal<String> Coverage::FunctionData::Name() const {
1154   return ToApiHandle<String>(function_->name);
1155 }
1156 
BlockCount() const1157 size_t Coverage::FunctionData::BlockCount() const {
1158   return function_->blocks.size();
1159 }
1160 
HasBlockCoverage() const1161 bool Coverage::FunctionData::HasBlockCoverage() const {
1162   return function_->has_block_coverage;
1163 }
1164 
GetBlockData(size_t i) const1165 Coverage::BlockData Coverage::FunctionData::GetBlockData(size_t i) const {
1166   return BlockData(&function_->blocks.at(i), coverage_);
1167 }
1168 
GetScript() const1169 Local<Script> Coverage::ScriptData::GetScript() const {
1170   return ToApiHandle<Script>(script_->script);
1171 }
1172 
FunctionCount() const1173 size_t Coverage::ScriptData::FunctionCount() const {
1174   return script_->functions.size();
1175 }
1176 
GetFunctionData(size_t i) const1177 Coverage::FunctionData Coverage::ScriptData::GetFunctionData(size_t i) const {
1178   return FunctionData(&script_->functions.at(i), coverage_);
1179 }
1180 
ScriptData(size_t index,std::shared_ptr<i::Coverage> coverage)1181 Coverage::ScriptData::ScriptData(size_t index,
1182                                  std::shared_ptr<i::Coverage> coverage)
1183     : script_(&coverage->at(index)), coverage_(std::move(coverage)) {}
1184 
ScriptCount() const1185 size_t Coverage::ScriptCount() const { return coverage_->size(); }
1186 
GetScriptData(size_t i) const1187 Coverage::ScriptData Coverage::GetScriptData(size_t i) const {
1188   return ScriptData(i, coverage_);
1189 }
1190 
CollectPrecise(Isolate * isolate)1191 Coverage Coverage::CollectPrecise(Isolate* isolate) {
1192   return Coverage(
1193       i::Coverage::CollectPrecise(reinterpret_cast<i::Isolate*>(isolate)));
1194 }
1195 
CollectBestEffort(Isolate * isolate)1196 Coverage Coverage::CollectBestEffort(Isolate* isolate) {
1197   return Coverage(
1198       i::Coverage::CollectBestEffort(reinterpret_cast<i::Isolate*>(isolate)));
1199 }
1200 
SelectMode(Isolate * isolate,CoverageMode mode)1201 void Coverage::SelectMode(Isolate* isolate, CoverageMode mode) {
1202   i::Coverage::SelectMode(reinterpret_cast<i::Isolate*>(isolate), mode);
1203 }
1204 
SourcePosition() const1205 int TypeProfile::Entry::SourcePosition() const { return entry_->position; }
1206 
Types() const1207 std::vector<MaybeLocal<String>> TypeProfile::Entry::Types() const {
1208   std::vector<MaybeLocal<String>> result;
1209   for (const internal::Handle<internal::String>& type : entry_->types) {
1210     result.emplace_back(ToApiHandle<String>(type));
1211   }
1212   return result;
1213 }
1214 
ScriptData(size_t index,std::shared_ptr<i::TypeProfile> type_profile)1215 TypeProfile::ScriptData::ScriptData(
1216     size_t index, std::shared_ptr<i::TypeProfile> type_profile)
1217     : script_(&type_profile->at(index)),
1218       type_profile_(std::move(type_profile)) {}
1219 
GetScript() const1220 Local<Script> TypeProfile::ScriptData::GetScript() const {
1221   return ToApiHandle<Script>(script_->script);
1222 }
1223 
Entries() const1224 std::vector<TypeProfile::Entry> TypeProfile::ScriptData::Entries() const {
1225   std::vector<TypeProfile::Entry> result;
1226   for (const internal::TypeProfileEntry& entry : script_->entries) {
1227     result.push_back(TypeProfile::Entry(&entry, type_profile_));
1228   }
1229   return result;
1230 }
1231 
Collect(Isolate * isolate)1232 TypeProfile TypeProfile::Collect(Isolate* isolate) {
1233   return TypeProfile(
1234       i::TypeProfile::Collect(reinterpret_cast<i::Isolate*>(isolate)));
1235 }
1236 
SelectMode(Isolate * isolate,TypeProfileMode mode)1237 void TypeProfile::SelectMode(Isolate* isolate, TypeProfileMode mode) {
1238   i::TypeProfile::SelectMode(reinterpret_cast<i::Isolate*>(isolate), mode);
1239 }
1240 
ScriptCount() const1241 size_t TypeProfile::ScriptCount() const { return type_profile_->size(); }
1242 
GetScriptData(size_t i) const1243 TypeProfile::ScriptData TypeProfile::GetScriptData(size_t i) const {
1244   return ScriptData(i, type_profile_);
1245 }
1246 
Get(v8::Isolate * isolate,v8::Local<v8::Value> key)1247 MaybeLocal<v8::Value> EphemeronTable::Get(v8::Isolate* isolate,
1248                                           v8::Local<v8::Value> key) {
1249   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
1250   auto self = i::Handle<i::EphemeronHashTable>::cast(Utils::OpenHandle(this));
1251   i::Handle<i::Object> internal_key = Utils::OpenHandle(*key);
1252   DCHECK(internal_key->IsJSReceiver());
1253 
1254   i::Handle<i::Object> value(self->Lookup(internal_key), internal_isolate);
1255 
1256   if (value->IsTheHole()) return {};
1257   return Utils::ToLocal(value);
1258 }
1259 
Set(v8::Isolate * isolate,v8::Local<v8::Value> key,v8::Local<v8::Value> value)1260 Local<EphemeronTable> EphemeronTable::Set(v8::Isolate* isolate,
1261                                           v8::Local<v8::Value> key,
1262                                           v8::Local<v8::Value> value) {
1263   auto self = i::Handle<i::EphemeronHashTable>::cast(Utils::OpenHandle(this));
1264   i::Handle<i::Object> internal_key = Utils::OpenHandle(*key);
1265   i::Handle<i::Object> internal_value = Utils::OpenHandle(*value);
1266   DCHECK(internal_key->IsJSReceiver());
1267 
1268   i::Handle<i::EphemeronHashTable> result(
1269       i::EphemeronHashTable::Put(self, internal_key, internal_value));
1270 
1271   return ToApiHandle<EphemeronTable>(result);
1272 }
1273 
New(v8::Isolate * isolate)1274 Local<EphemeronTable> EphemeronTable::New(v8::Isolate* isolate) {
1275   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1276   ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1277   i::Handle<i::EphemeronHashTable> table =
1278       i::EphemeronHashTable::New(i_isolate, 0);
1279   return ToApiHandle<EphemeronTable>(table);
1280 }
1281 
Cast(v8::Value * value)1282 EphemeronTable* EphemeronTable::Cast(v8::Value* value) {
1283   return static_cast<EphemeronTable*>(value);
1284 }
1285 
getter()1286 Local<Value> AccessorPair::getter() {
1287   i::Handle<i::AccessorPair> accessors = Utils::OpenHandle(this);
1288   i::Isolate* isolate = accessors->GetIsolate();
1289   i::Handle<i::Object> getter(accessors->getter(), isolate);
1290   return Utils::ToLocal(getter);
1291 }
1292 
setter()1293 Local<Value> AccessorPair::setter() {
1294   i::Handle<i::AccessorPair> accessors = Utils::OpenHandle(this);
1295   i::Isolate* isolate = accessors->GetIsolate();
1296   i::Handle<i::Object> setter(accessors->setter(), isolate);
1297   return Utils::ToLocal(setter);
1298 }
1299 
IsAccessorPair(Local<Value> that)1300 bool AccessorPair::IsAccessorPair(Local<Value> that) {
1301   i::Handle<i::Object> obj = Utils::OpenHandle(*that);
1302   return obj->IsAccessorPair();
1303 }
1304 
GetMessageFromPromise(Local<Promise> p)1305 MaybeLocal<Message> GetMessageFromPromise(Local<Promise> p) {
1306   i::Handle<i::JSPromise> promise = Utils::OpenHandle(*p);
1307   i::Isolate* isolate = promise->GetIsolate();
1308 
1309   i::Handle<i::Symbol> key = isolate->factory()->promise_debug_message_symbol();
1310   i::Handle<i::Object> maybeMessage =
1311       i::JSReceiver::GetDataProperty(isolate, promise, key);
1312 
1313   if (!maybeMessage->IsJSMessageObject(isolate)) return MaybeLocal<Message>();
1314   return ToApiHandle<Message>(
1315       i::Handle<i::JSMessageObject>::cast(maybeMessage));
1316 }
1317 
isExperimentalAsyncStackTaggingApiEnabled()1318 bool isExperimentalAsyncStackTaggingApiEnabled() {
1319   return v8::internal::FLAG_experimental_async_stack_tagging_api;
1320 }
1321 
Create(Local<Context> context,Local<Object> object,bool skip_indices)1322 std::unique_ptr<PropertyIterator> PropertyIterator::Create(
1323     Local<Context> context, Local<Object> object, bool skip_indices) {
1324   internal::Isolate* isolate =
1325       reinterpret_cast<i::Isolate*>(object->GetIsolate());
1326   if (IsExecutionTerminatingCheck(isolate)) {
1327     return nullptr;
1328   }
1329   CallDepthScope<false> call_depth_scope(isolate, context);
1330 
1331   auto result = i::DebugPropertyIterator::Create(
1332       isolate, Utils::OpenHandle(*object), skip_indices);
1333   if (!result) {
1334     DCHECK(isolate->has_pending_exception());
1335     call_depth_scope.Escape();
1336   }
1337   return result;
1338 }
1339 
1340 }  // namespace debug
1341 
1342 namespace internal {
1343 
Advance()1344 Maybe<bool> DebugPropertyIterator::Advance() {
1345   if (IsExecutionTerminatingCheck(isolate_)) {
1346     return Nothing<bool>();
1347   }
1348   Local<v8::Context> context =
1349       Utils::ToLocal(handle(isolate_->context(), isolate_));
1350   CallDepthScope<false> call_depth_scope(isolate_, context);
1351 
1352   if (!AdvanceInternal()) {
1353     DCHECK(isolate_->has_pending_exception());
1354     call_depth_scope.Escape();
1355     return Nothing<bool>();
1356   }
1357   return Just(true);
1358 }
1359 
1360 }  // namespace internal
1361 }  // namespace v8
1362 
1363 #include "src/api/api-macros-undef.h"
1364