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