v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
debug-interface.cc
Go to the documentation of this file.
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
6
8#include "src/api/api-inl.h"
12#include "src/date/date.h"
17#include "src/debug/debug.h"
19#include "src/heap/heap.h"
23
24#if V8_ENABLE_WEBASSEMBLY
28#endif // V8_ENABLE_WEBASSEMBLY
29
30// Has to be the last include (doesn't have include guards):
31#include "src/api/api-macros.h"
32
33namespace v8 {
34namespace debug {
35
36void SetContextId(Local<Context> context, int id) {
37 auto v8_context = Utils::OpenDirectHandle(*context);
38 DCHECK_NO_SCRIPT_NO_EXCEPTION(v8_context->GetIsolate());
39 v8_context->set_debug_context_id(i::Smi::FromInt(id));
40}
41
43 auto v8_context = Utils::OpenDirectHandle(*context);
44 DCHECK_NO_SCRIPT_NO_EXCEPTION(v8_context->GetIsolate());
45 i::Tagged<i::Object> value = v8_context->debug_context_id();
46 return (IsSmi(value)) ? i::Smi::ToInt(value) : 0;
47}
48
50 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
52 if (inspector == nullptr) {
53 i_isolate->set_inspector(nullptr);
54 } else {
55 i_isolate->set_inspector(inspector);
56 }
57}
58
60 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
62 return i_isolate->inspector();
63}
64
65namespace {
66
67i::Handle<i::String> GetBigIntStringPresentationHandle(
68 i::Isolate* i_isolate, i::DirectHandle<i::BigInt> i_bigint) {
69 // For large BigInts computing the decimal string representation
70 // can take a long time, so we go with hexadecimal in that case.
71 int radix = (i_bigint->Words64Count() > 100 * 1000) ? 16 : 10;
72 i::Handle<i::String> string_value =
73 i::BigInt::ToString(i_isolate, i_bigint, radix, i::kDontThrow)
74 .ToHandleChecked();
75 if (radix == 16) {
76 if (i_bigint->IsNegative()) {
77 string_value =
78 i_isolate->factory()
80 i_isolate->factory()->NewStringFromAsciiChecked("-0x"),
81 i_isolate->factory()->NewProperSubString(
82 string_value, 1, string_value->length() - 1))
83 .ToHandleChecked();
84 } else {
85 string_value =
86 i_isolate->factory()
88 i_isolate->factory()->NewStringFromAsciiChecked("0x"),
89 string_value)
90 .ToHandleChecked();
91 }
92 }
93 return string_value;
94}
95
96} // namespace
97
99 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
102
103 i::DirectHandle<i::String> string_value =
104 GetBigIntStringPresentationHandle(i_isolate, i_bigint);
105 return Utils::ToLocal(string_value);
106}
107
109 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
112
113 i::Handle<i::String> string_value =
114 GetBigIntStringPresentationHandle(i_isolate, i_bigint);
115
116 i::DirectHandle<i::String> description =
117 i_isolate->factory()
118 ->NewConsString(string_value, i_isolate->factory()->n_string())
119 .ToHandleChecked();
120 return Utils::ToLocal(description);
121}
122
125 auto jsdate = i::Cast<i::JSDate>(receiver);
126 i::Isolate* i_isolate = jsdate->GetIsolate();
128 auto buffer = i::ToDateString(jsdate->value(), i_isolate->date_cache(),
129 i::ToDateStringMode::kLocalDateAndTime);
130 return Utils::ToLocal(i_isolate->factory()
132 .ToHandleChecked());
133}
134
136 auto receiver = Utils::OpenHandle(*function);
137 auto i_isolate = receiver->GetIsolate();
139 if (IsJSBoundFunction(*receiver)) {
140 return Utils::ToLocal(
141 i::JSBoundFunction::ToString(i::Cast<i::JSBoundFunction>(receiver)));
142 }
143 if (IsJSFunction(*receiver)) {
144 auto js_function = i::Cast<i::JSFunction>(receiver);
145#if V8_ENABLE_WEBASSEMBLY
146 if (js_function->shared()->HasWasmExportedFunctionData()) {
148 js_function->shared()->wasm_exported_function_data(), i_isolate);
149 int func_index = function_data->function_index();
151 function_data->instance_data(), i_isolate);
152 if (instance_data->module()->origin == i::wasm::kWasmOrigin) {
153 // For asm.js functions, we can still print the source
154 // code (hopefully), so don't bother with them here.
155 auto debug_name =
156 i::GetWasmFunctionDebugName(i_isolate, instance_data, func_index);
157 i::IncrementalStringBuilder builder(i_isolate);
158 builder.AppendCStringLiteral("function ");
159 builder.AppendString(debug_name);
160 builder.AppendCStringLiteral("() { [native code] }");
161 return Utils::ToLocal(builder.Finish().ToHandleChecked());
162 }
163 }
164#endif // V8_ENABLE_WEBASSEMBLY
165 return Utils::ToLocal(i::JSFunction::ToString(js_function));
166 }
167 return Utils::ToLocal(
168 receiver->GetIsolate()->factory()->function_native_code_string());
169}
170
172 auto i_isolate = reinterpret_cast<i::Isolate*>(isolate);
174 i_isolate->debug()->SetBreakOnNextFunctionCall();
175}
176
178 auto i_isolate = reinterpret_cast<i::Isolate*>(isolate);
180 i_isolate->debug()->ClearBreakOnNextFunctionCall();
181}
182
184 Local<Value> value) {
185 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
189 if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result))
190 return MaybeLocal<Array>();
191 return Utils::ToLocal(result);
192}
193
194namespace {
195
196using FlagFilter = std::function<bool(i::IsStaticFlag)>;
197using VariableModeFilter = std::function<bool(i::VariableMode)>;
198using ContextLocalIterator = std::function<void(
200
201void ForEachContextLocal(i::Isolate* isolate,
203 const VariableModeFilter& var_mode_filter,
204 const FlagFilter& flag_filter,
205 const ContextLocalIterator& context_local_it) {
207 i::DirectHandle<i::ScopeInfo> scope_info(context->scope_info(), isolate);
208 for (auto it : i::ScopeInfo::IterateLocalNames(scope_info)) {
209 i::Handle<i::String> name(it->name(), isolate);
210 i::VariableMode mode = scope_info->ContextLocalMode(it->index());
211 if (!var_mode_filter(mode)) {
212 continue;
213 }
214 i::IsStaticFlag flag = scope_info->ContextLocalIsStaticFlag(it->index());
215 if (!flag_filter(flag)) {
216 continue;
217 }
218 int context_index = scope_info->ContextHeaderLength() + it->index();
219 i::Handle<i::Object> slot_value(context->get(context_index), isolate);
220 context_local_it(mode, name, slot_value);
221 }
222}
223
224} // namespace
225
226bool GetPrivateMembers(Local<Context> context, Local<Object> object, int filter,
227 LocalVector<Value>* names_out,
228 LocalVector<Value>* values_out) {
229 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
230 API_RCS_SCOPE(isolate, debug, GetPrivateMembers);
232
233 bool include_methods =
234 filter & static_cast<int>(PrivateMemberFilter::kPrivateMethods);
235 bool include_fields =
236 filter & static_cast<int>(PrivateMemberFilter::kPrivateFields);
237 bool include_accessors =
238 filter & static_cast<int>(PrivateMemberFilter::kPrivateAccessors);
239 bool include_methods_or_accessors = include_methods || include_accessors;
240
241 auto var_mode_filter =
242 include_methods
243 ? (include_accessors ? i::IsPrivateMethodOrAccessorVariableMode
246 auto constexpr instance_filter = [](i::IsStaticFlag flag) {
247 return flag == i::IsStaticFlag::kNotStatic;
248 };
249 auto constexpr static_filter = [](i::IsStaticFlag flag) {
250 return flag == i::IsStaticFlag::kStatic;
251 };
252
254
255 i::PropertyFilter key_filter =
256 static_cast<i::PropertyFilter>(i::PropertyFilter::PRIVATE_NAMES_ONLY);
259 isolate, keys,
260 i::KeyAccumulator::GetKeys(isolate, receiver,
261 i::KeyCollectionMode::kOwnOnly, key_filter,
262 i::GetKeysConversion::kConvertToString),
263 false);
264
265 // Estimate number of private fields and private instance methods/accessors.
266 int private_entries_count = 0;
267 auto count_private_entry =
269 i::DirectHandle<i::Object>) { private_entries_count++; };
270 for (int i = 0; i < keys->length(); ++i) {
271 // Exclude the private brand symbols.
273 if (key->is_private_brand()) {
274 if (include_methods_or_accessors) {
277 isolate, value, i::Object::GetProperty(isolate, receiver, key),
278 false);
279
281 isolate);
282 ForEachContextLocal(isolate, value_context, var_mode_filter,
283 instance_filter, count_private_entry);
284 }
285 } else if (include_fields) {
286 private_entries_count++;
287 }
288 }
289
290 // Estimate number of static private methods/accessors for classes.
291 bool has_static_private_methods_or_accessors = false;
292 if (include_methods_or_accessors) {
293 if (IsJSFunction(*receiver)) {
295 isolate);
296 i::DirectHandle<i::SharedFunctionInfo> shared(func->shared(), isolate);
297 if (shared->is_class_constructor() &&
298 shared->has_static_private_methods_or_accessors()) {
299 has_static_private_methods_or_accessors = true;
300 i::DirectHandle<i::Context> func_context(func->context(), isolate);
301 ForEachContextLocal(isolate, func_context, var_mode_filter,
302 static_filter, count_private_entry);
303 }
304 }
305 }
306
307 DCHECK(names_out->empty());
308 names_out->reserve(private_entries_count);
309 DCHECK(values_out->empty());
310 values_out->reserve(private_entries_count);
311
312 auto add_private_entry = [&](i::VariableMode mode,
315 DCHECK_IMPLIES(mode == i::VariableMode::kPrivateMethod,
316 IsJSFunction(*value));
317 DCHECK_IMPLIES(mode != i::VariableMode::kPrivateMethod,
318 IsAccessorPair(*value));
319 names_out->push_back(Utils::ToLocal(name));
320 values_out->push_back(Utils::ToLocal(value));
321 };
322 if (has_static_private_methods_or_accessors) {
323 i::DirectHandle<i::Context> receiver_context(
324 i::Cast<i::JSFunction>(*receiver)->context(), isolate);
325 ForEachContextLocal(isolate, receiver_context, var_mode_filter,
326 static_filter, add_private_entry);
327 }
328
329 for (int i = 0; i < keys->length(); ++i) {
330 i::DirectHandle<i::Object> obj_key(keys->get(i), isolate);
332 CHECK(key->is_private_name());
335 isolate, value, i::Object::GetProperty(isolate, receiver, key), false);
336 if (key->is_private_brand()) {
337 if (include_methods_or_accessors) {
338 DCHECK(IsContext(*value));
340 isolate);
341 ForEachContextLocal(isolate, value_context, var_mode_filter,
342 instance_filter, add_private_entry);
343 }
344 } else if (include_fields) { // Private fields
346 i::Cast<i::String>(i::Cast<i::Symbol>(*key)->description()), isolate);
347 names_out->push_back(Utils::ToLocal(name));
348 values_out->push_back(Utils::ToLocal(value));
349 }
350 }
351
352 DCHECK_EQ(names_out->size(), values_out->size());
353 DCHECK_LE(names_out->size(), private_entries_count);
354 return true;
355}
356
358 if (IsJSGlobalProxy(*Utils::OpenDirectHandle(*value))) {
359 return MaybeLocal<Context>();
360 }
362 return value->GetCreationContext();
364}
365
367 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
369 i_isolate->debug()->ChangeBreakOnException(
372 i_isolate->debug()->ChangeBreakOnException(
375}
376
377void SetBreakPointsActive(Isolate* v8_isolate, bool is_active) {
378 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
380 isolate->debug()->set_break_points_active(is_active);
381}
382
383void PrepareStep(Isolate* v8_isolate, StepAction action) {
384 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
385 ENTER_V8_BASIC(isolate);
386 CHECK(isolate->debug()->CheckExecutionState());
387 // Clear all current stepping setup.
388 isolate->debug()->ClearStepping();
389 // Prepare step.
390 isolate->debug()->PrepareStep(static_cast<i::StepAction>(action));
391}
392
393bool PrepareRestartFrame(Isolate* v8_isolate, int callFrameOrdinal) {
394 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
395 ENTER_V8_BASIC(isolate);
396 CHECK(isolate->debug()->CheckExecutionState());
397
398 i::DebugStackTraceIterator it(isolate, callFrameOrdinal);
399 if (it.Done() || !it.CanBeRestarted()) return false;
400
401 // Clear all current stepping setup.
402 isolate->debug()->ClearStepping();
403 it.PrepareRestart();
404 return true;
405}
406
407void ClearStepping(Isolate* v8_isolate) {
408 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
410 // Clear all current stepping setup.
411 isolate->debug()->ClearStepping();
412}
413
414void BreakRightNow(Isolate* v8_isolate,
415 base::EnumSet<debug::BreakReason> break_reasons) {
416 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
417 ENTER_V8_BASIC(isolate);
418 isolate->debug()->HandleDebugBreak(i::kIgnoreIfAllFramesBlackboxed,
419 break_reasons);
420}
421
422void SetTerminateOnResume(Isolate* v8_isolate) {
423 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
425 isolate->debug()->SetTerminateOnResume();
426}
427
428bool CanBreakProgram(Isolate* v8_isolate) {
429 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
430 ENTER_V8_BASIC(isolate);
431 return !isolate->debug()->AllFramesOnStackAreBlackboxed();
432}
433
434size_t ScriptSource::Length() const {
435 auto source = Utils::OpenDirectHandle(this);
436 if (IsString(*source)) {
437 return i::Cast<i::String>(source)->length();
438 }
439 return Size();
440}
441
442size_t ScriptSource::Size() const {
443#if V8_ENABLE_WEBASSEMBLY
444 MemorySpan<const uint8_t> wasm_bytecode;
445 if (WasmBytecode().To(&wasm_bytecode)) {
446 return wasm_bytecode.size();
447 }
448#endif // V8_ENABLE_WEBASSEMBLY
449 auto source = Utils::OpenDirectHandle(this);
450 if (!IsString(*source)) return 0;
451 auto string = i::Cast<i::String>(source);
452 return string->length() * (string->IsTwoByteRepresentation() ? 2 : 1);
453}
454
457 if (!IsString(*source)) return MaybeLocal<String>();
458 return Utils::ToLocal(i::Cast<i::String>(source));
459}
460
461#if V8_ENABLE_WEBASSEMBLY
462Maybe<MemorySpan<const uint8_t>> ScriptSource::WasmBytecode() const {
463 auto source = Utils::OpenDirectHandle(this);
464 if (!IsForeign(*source)) return Nothing<MemorySpan<const uint8_t>>();
465 base::Vector<const uint8_t> wire_bytes =
466 i::Cast<i::Managed<i::wasm::NativeModule>>(*source)->raw()->wire_bytes();
467 return Just(MemorySpan<const uint8_t>{wire_bytes.begin(), wire_bytes.size()});
468}
469#endif // V8_ENABLE_WEBASSEMBLY
470
472 return reinterpret_cast<Isolate*>(
473 Utils::OpenDirectHandle(this)->GetIsolate());
474}
475
477 return Utils::OpenDirectHandle(this)->origin_options();
478}
479
481 return Utils::OpenDirectHandle(this)->compilation_state() ==
482 i::Script::CompilationState::kCompiled;
483}
484
485bool Script::IsEmbedded() const {
486 auto script = Utils::OpenDirectHandle(this);
487 return script->context_data() == i::GetReadOnlyRoots().uninitialized_symbol();
488}
489
490int Script::Id() const { return Utils::OpenDirectHandle(this)->id(); }
491
492int Script::StartLine() const {
493 return Utils::OpenDirectHandle(this)->line_offset();
494}
495
497 return Utils::OpenDirectHandle(this)->column_offset();
498}
499
500int Script::EndLine() const {
502#if V8_ENABLE_WEBASSEMBLY
503 if (script->type() == i::Script::Type::kWasm) return 0;
504#endif // V8_ENABLE_WEBASSEMBLY
505 if (!IsString(script->source())) {
506 return script->line_offset();
507 }
508 i::Isolate* isolate = script->GetIsolate();
509 i::HandleScope scope(isolate);
510 i::Script::PositionInfo info;
511 i::Script::GetPositionInfo(
512 script, i::Cast<i::String>(script->source())->length(), &info);
513 return info.line;
514}
515
516int Script::EndColumn() const {
518#if V8_ENABLE_WEBASSEMBLY
519 if (script->type() == i::Script::Type::kWasm) {
520 return script->wasm_native_module()->wire_bytes().length();
521 }
522#endif // V8_ENABLE_WEBASSEMBLY
523 if (!IsString(script->source())) {
524 return script->column_offset();
525 }
526 i::Isolate* isolate = script->GetIsolate();
527 i::HandleScope scope(isolate);
528 i::Script::PositionInfo info;
529 i::Script::GetPositionInfo(
530 script, i::Cast<i::String>(script->source())->length(), &info);
531 return info.column;
532}
533
535 auto script = Utils::OpenDirectHandle(this);
536 i::Isolate* isolate = script->GetIsolate();
537 i::DirectHandle<i::Object> value(script->name(), isolate);
538 if (!IsString(*value)) return MaybeLocal<String>();
539 return Utils::ToLocal(i::Cast<i::String>(value));
540}
541
543 auto script = Utils::OpenDirectHandle(this);
544 i::Isolate* isolate = script->GetIsolate();
545 i::DirectHandle<i::PrimitiveHeapObject> value(script->source_url(), isolate);
546 if (!IsString(*value)) return MaybeLocal<String>();
547 return Utils::ToLocal(i::Cast<i::String>(value));
548}
549
551 auto script = Utils::OpenDirectHandle(this);
552 i::Isolate* isolate = script->GetIsolate();
553 i::DirectHandle<i::Object> value(script->source_mapping_url(), isolate);
554 if (!IsString(*value)) return MaybeLocal<String>();
555 return Utils::ToLocal(i::Cast<i::String>(value));
556}
557
560 i::Isolate* isolate = script->GetIsolate();
562 i::Script::GetScriptHash(isolate, script, /* forceForInspector: */ true);
563 return Utils::ToLocal(value);
564}
565
567 auto script = Utils::OpenDirectHandle(this);
568 i::Tagged<i::Object> value = script->context_data();
569 if (IsSmi(value)) return Just(i::Smi::ToInt(value));
570 return Nothing<int>();
571}
572
574 auto script = Utils::OpenDirectHandle(this);
575 i::Isolate* isolate = script->GetIsolate();
576#if V8_ENABLE_WEBASSEMBLY
577 if (script->type() == i::Script::Type::kWasm) {
578 i::DirectHandle<i::Object> wasm_native_module(
579 script->wasm_managed_native_module(), isolate);
580 return Utils::Convert<i::Object, ScriptSource>(wasm_native_module);
581 }
582#endif // V8_ENABLE_WEBASSEMBLY
583 i::DirectHandle<i::PrimitiveHeapObject> source(script->source(), isolate);
585}
586
587#if V8_ENABLE_WEBASSEMBLY
588bool Script::IsWasm() const {
589 return Utils::OpenDirectHandle(this)->type() == i::Script::Type::kWasm;
590}
591#endif // V8_ENABLE_WEBASSEMBLY
592
593bool Script::IsModule() const {
594 return Utils::OpenDirectHandle(this)->origin_options().IsModule();
595}
596
597namespace {
598
599int GetSmiValue(i::DirectHandle<i::FixedArray> array, int index) {
600 return i::Smi::ToInt(array->get(index));
601}
602
603bool CompareBreakLocation(const i::BreakLocation& loc1,
604 const i::BreakLocation& loc2) {
605 return loc1.position() < loc2.position();
606}
607
608} // namespace
609
611 const Location& start, const Location& end, bool restrict_to_function,
612 std::vector<BreakLocation>* locations) const {
613 CHECK(!start.IsEmpty());
615#if V8_ENABLE_WEBASSEMBLY
616 if (script->type() == i::Script::Type::kWasm) {
617 i::wasm::NativeModule* native_module = script->wasm_native_module();
618 return i::WasmScript::GetPossibleBreakpoints(native_module, start, end,
619 locations);
620 }
621#endif // V8_ENABLE_WEBASSEMBLY
622
623 i::Isolate* isolate = script->GetIsolate();
624
625 int start_offset, end_offset;
626 if (!GetSourceOffset(start, GetSourceOffsetMode::kClamp).To(&start_offset)) {
627 return false;
628 }
629 if (end.IsEmpty()) {
630 end_offset = std::numeric_limits<int>::max();
632 .To(&end_offset)) {
633 return false;
634 }
635 if (start_offset >= end_offset) return true;
636
637 std::vector<i::BreakLocation> v8_locations;
638 if (!isolate->debug()->GetPossibleBreakpoints(
639 script, start_offset, end_offset, restrict_to_function,
640 &v8_locations)) {
641 return false;
642 }
643
644 std::sort(v8_locations.begin(), v8_locations.end(), CompareBreakLocation);
645 for (const auto& v8_location : v8_locations) {
646 Location location = GetSourceLocation(v8_location.position());
647 locations->emplace_back(location.GetLineNumber(),
648 location.GetColumnNumber(), v8_location.type());
649 }
650 return true;
651}
652
654 GetSourceOffsetMode mode) const {
656#if V8_ENABLE_WEBASSEMBLY
657 if (script->type() == i::Script::Type::kWasm) {
658 return location.GetLineNumber() == 0 ? Just(location.GetColumnNumber())
659 : Nothing<int>();
660 }
661#endif // V8_ENABLE_WEBASSEMBLY
662
663 int line = location.GetLineNumber();
664 int column = location.GetColumnNumber();
665 if (!script->HasSourceURLComment()) {
666 // Line/column number for inline <script>s with sourceURL annotation
667 // are supposed to be related to the <script> tag, otherwise they
668 // are relative to the parent file. Keep this in sync with the logic
669 // in GetSourceLocation() below.
670 line -= script->line_offset();
671 if (line == 0) column -= script->column_offset();
672 }
673
674 i::Script::InitLineEnds(script->GetIsolate(), script);
675 auto line_ends = i::Cast<i::FixedArray>(
676 i::direct_handle(script->line_ends(), script->GetIsolate()));
677 if (line < 0) {
678 if (mode == GetSourceOffsetMode::kClamp) {
679 return Just(0);
680 }
681 return Nothing<int>();
682 }
683 if (line >= line_ends->length()) {
684 if (mode == GetSourceOffsetMode::kClamp) {
685 return Just(GetSmiValue(line_ends, line_ends->length() - 1));
686 }
687 return Nothing<int>();
688 }
689 if (column < 0) {
690 if (mode != GetSourceOffsetMode::kClamp) {
691 return Nothing<int>();
692 }
693 column = 0;
694 }
695 int offset = column;
696 if (line > 0) {
697 int prev_line_end_offset = GetSmiValue(line_ends, line - 1);
698 offset += prev_line_end_offset + 1;
699 }
700 int line_end_offset = GetSmiValue(line_ends, line);
701 if (offset > line_end_offset) {
702 // Be permissive with columns that don't exist,
703 // as long as they are clearly within the range
704 // of the script.
705 if (line < line_ends->length() - 1 || mode == GetSourceOffsetMode::kClamp) {
706 return Just(line_end_offset);
707 }
708 return Nothing<int>();
709 }
710 return Just(offset);
711}
712
715 i::Script::PositionInfo info;
716 i::Script::GetPositionInfo(script, offset, &info);
717 if (script->HasSourceURLComment()) {
718 // Line/column number for inline <script>s with sourceURL annotation
719 // are supposed to be related to the <script> tag, otherwise they
720 // are relative to the parent file. Keep this in sync with the logic
721 // in GetSourceOffset() above.
722 info.line -= script->line_offset();
723 if (info.line == 0) info.column -= script->column_offset();
724 }
725 return Location(info.line, info.column);
726}
727
728bool Script::SetScriptSource(Local<String> newSource, bool preview,
729 bool allow_top_frame_live_editing,
730 LiveEditResult* result) const {
732 i::Isolate* isolate = script->GetIsolate();
733 return isolate->debug()->SetScriptSource(
734 script, Utils::OpenHandle(*newSource), preview,
735 allow_top_frame_live_editing, result);
736}
737
739 BreakpointId* id) const {
741 i::Isolate* isolate = script->GetIsolate();
742 int offset;
743 if (!GetSourceOffset(*location).To(&offset)) {
744 return false;
745 }
746 if (!isolate->debug()->SetBreakPointForScript(
747 script, Utils::OpenDirectHandle(*condition), &offset, id)) {
748 return false;
749 }
750 *location = GetSourceLocation(offset);
751 return true;
752}
753
756 i::Isolate* isolate = script->GetIsolate();
757#if V8_ENABLE_WEBASSEMBLY
758 if (script->type() == i::Script::Type::kWasm) {
759 isolate->debug()->SetInstrumentationBreakpointForWasmScript(script, id);
760 return true;
761 }
762#endif // V8_ENABLE_WEBASSEMBLY
763 i::SharedFunctionInfo::ScriptIterator it(isolate, *script);
764 for (i::Tagged<i::SharedFunctionInfo> sfi = it.Next(); !sfi.is_null();
765 sfi = it.Next()) {
766 if (sfi->is_toplevel()) {
767 return isolate->debug()->SetBreakpointForFunction(
768 handle(sfi, isolate), isolate->factory()->empty_string(), id,
770 }
771 }
772 return false;
773}
774
775#if V8_ENABLE_WEBASSEMBLY
776void Script::RemoveWasmBreakpoint(BreakpointId id) {
778 i::Isolate* isolate = script->GetIsolate();
779 isolate->debug()->RemoveBreakpointForWasmScript(script, id);
780}
781#endif // V8_ENABLE_WEBASSEMBLY
782
783void RemoveBreakpoint(Isolate* v8_isolate, BreakpointId id) {
784 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
785 i::HandleScope handle_scope(isolate);
786 isolate->debug()->RemoveBreakpoint(id);
787}
788
789Platform* GetCurrentPlatform() { return i::V8::GetCurrentPlatform(); }
790
791void ForceGarbageCollection(Isolate* isolate, StackState embedder_stack_state) {
792 i::EmbedderStackStateScope stack_scope(
793 reinterpret_cast<i::Isolate*>(isolate)->heap(),
794 i::EmbedderStackStateOrigin::kImplicitThroughTask, embedder_stack_state);
795 isolate->LowMemoryNotification();
796}
797
798#if V8_ENABLE_WEBASSEMBLY
799WasmScript* WasmScript::Cast(Script* script) {
800 CHECK(script->IsWasm());
801 return static_cast<WasmScript*>(script);
802}
803
804Maybe<WasmScript::DebugSymbols::Type> GetDebugSymbolType(
805 i::wasm::WasmDebugSymbols::Type type) {
806 switch (type) {
807 case i::wasm::WasmDebugSymbols::Type::EmbeddedDWARF:
808 return Just(WasmScript::DebugSymbols::Type::EmbeddedDWARF);
809 case i::wasm::WasmDebugSymbols::Type::ExternalDWARF:
810 return Just(WasmScript::DebugSymbols::Type::ExternalDWARF);
811 case i::wasm::WasmDebugSymbols::Type::SourceMap:
812 return Just(WasmScript::DebugSymbols::Type::SourceMap);
813 case i::wasm::WasmDebugSymbols::Type::None:
815 }
816}
817
818std::vector<WasmScript::DebugSymbols> WasmScript::GetDebugSymbols() const {
819 auto script = Utils::OpenDirectHandle(this);
820 DCHECK_EQ(i::Script::Type::kWasm, script->type());
821
822 std::vector<WasmScript::DebugSymbols> debug_symbols;
823 auto symbols = script->wasm_native_module()->module()->debug_symbols;
824 for (size_t i = 0; i < symbols.size(); ++i) {
825 const i::wasm::WasmDebugSymbols& symbol = symbols[i];
826 Maybe<WasmScript::DebugSymbols::Type> type =
827 GetDebugSymbolType(symbol.type);
828 if (type.IsNothing()) continue;
829
830 internal::wasm::ModuleWireBytes wire_bytes(
831 script->wasm_native_module()->wire_bytes());
832 i::wasm::WasmName external_url =
833 wire_bytes.GetNameOrNull(symbol.external_url);
834 MemorySpan<const char> span = {external_url.data(), external_url.size()};
835 debug_symbols.push_back({type.FromJust(), span});
836 }
837 return debug_symbols;
838}
839
840int WasmScript::NumFunctions() const {
842 auto script = Utils::OpenDirectHandle(this);
843 DCHECK_EQ(i::Script::Type::kWasm, script->type());
844 i::wasm::NativeModule* native_module = script->wasm_native_module();
845 const i::wasm::WasmModule* module = native_module->module();
846 DCHECK_GE(i::kMaxInt, module->functions.size());
847 return static_cast<int>(module->functions.size());
848}
849
850int WasmScript::NumImportedFunctions() const {
852 auto script = Utils::OpenDirectHandle(this);
853 DCHECK_EQ(i::Script::Type::kWasm, script->type());
854 i::wasm::NativeModule* native_module = script->wasm_native_module();
855 const i::wasm::WasmModule* module = native_module->module();
856 DCHECK_GE(i::kMaxInt, module->num_imported_functions);
857 return static_cast<int>(module->num_imported_functions);
858}
859
860std::pair<int, int> WasmScript::GetFunctionRange(int function_index) const {
862 auto script = Utils::OpenDirectHandle(this);
863 DCHECK_EQ(i::Script::Type::kWasm, script->type());
864 i::wasm::NativeModule* native_module = script->wasm_native_module();
865 const i::wasm::WasmModule* module = native_module->module();
866 DCHECK_LE(0, function_index);
867 DCHECK_GT(module->functions.size(), function_index);
868 const i::wasm::WasmFunction& func = module->functions[function_index];
869 DCHECK_GE(i::kMaxInt, func.code.offset());
870 DCHECK_GE(i::kMaxInt, func.code.end_offset());
871 return std::make_pair(static_cast<int>(func.code.offset()),
872 static_cast<int>(func.code.end_offset()));
873}
874
875int WasmScript::GetContainingFunction(int byte_offset) const {
877 auto script = Utils::OpenDirectHandle(this);
878 DCHECK_EQ(i::Script::Type::kWasm, script->type());
879 i::wasm::NativeModule* native_module = script->wasm_native_module();
880 const i::wasm::WasmModule* module = native_module->module();
881 DCHECK_LE(0, byte_offset);
882
883 return i::wasm::GetContainingWasmFunction(module, byte_offset);
884}
885
886void WasmScript::Disassemble(DisassemblyCollector* collector,
887 std::vector<int>* function_body_offsets) {
889 auto script = Utils::OpenDirectHandle(this);
890 DCHECK_EQ(i::Script::Type::kWasm, script->type());
891 i::wasm::NativeModule* native_module = script->wasm_native_module();
892 const i::wasm::WasmModule* module = native_module->module();
893 i::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes());
894 i::wasm::Disassemble(module, wire_bytes, native_module->GetNamesProvider(),
895 collector, function_body_offsets);
896}
897
898void Disassemble(base::Vector<const uint8_t> wire_bytes,
899 DisassemblyCollector* collector,
900 std::vector<int>* function_body_offsets) {
901 i::wasm::Disassemble(wire_bytes, collector, function_body_offsets);
902}
903
904uint32_t WasmScript::GetFunctionHash(int function_index) {
906 auto script = Utils::OpenDirectHandle(this);
907 DCHECK_EQ(i::Script::Type::kWasm, script->type());
908 i::wasm::NativeModule* native_module = script->wasm_native_module();
909 const i::wasm::WasmModule* module = native_module->module();
910 DCHECK_LE(0, function_index);
911 DCHECK_GT(module->functions.size(), function_index);
912 const i::wasm::WasmFunction& func = module->functions[function_index];
913 i::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes());
914 base::Vector<const uint8_t> function_bytes =
915 wire_bytes.GetFunctionBytes(&func);
916 // TODO(herhut): Maybe also take module, name and signature into account.
917 return i::StringHasher::HashSequentialString(function_bytes.begin(),
918 function_bytes.length(), 0);
919}
920
921Maybe<v8::MemorySpan<const uint8_t>> WasmScript::GetModuleBuildId() const {
923 auto script = Utils::OpenDirectHandle(this);
924 DCHECK_EQ(i::Script::Type::kWasm, script->type());
925 i::wasm::NativeModule* native_module = script->wasm_native_module();
926 const i::wasm::WasmModule* wasm_module = native_module->module();
927 const i::wasm::WireBytesRef& build_id = wasm_module->build_id;
928 if (build_id.is_empty()) {
930 }
931 return Just(MemorySpan<const uint8_t>{
932 native_module->wire_bytes().begin() + build_id.offset(),
933 build_id.length()});
934}
935
936int WasmScript::CodeOffset() const {
937 auto script = Utils::OpenDirectHandle(this);
938 DCHECK_EQ(i::Script::Type::kWasm, script->type());
939 i::wasm::NativeModule* native_module = script->wasm_native_module();
940 const i::wasm::WasmModule* module = native_module->module();
941
942 // If the module contains at least one function, the code offset must have
943 // been initialized, and it cannot be zero.
944 DCHECK_IMPLIES(module->num_declared_functions > 0,
945 module->code.offset() != 0);
946 return module->code.offset();
947}
948#endif // V8_ENABLE_WEBASSEMBLY
949
950Location::Location(int line_number, int column_number)
951 : line_number_(line_number),
952 column_number_(column_number),
953 is_empty_(false) {}
954
956 : line_number_(Function::kLineOffsetNotFound),
957 column_number_(Function::kLineOffsetNotFound),
958 is_empty_(true) {}
959
961 DCHECK(!IsEmpty());
962 return line_number_;
963}
964
966 DCHECK(!IsEmpty());
967 return column_number_;
968}
969
970bool Location::IsEmpty() const { return is_empty_; }
971
972void GetLoadedScripts(Isolate* v8_isolate,
973 std::vector<v8::Global<Script>>& scripts) {
974 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
976 {
978 i::Script::Iterator iterator(isolate);
979 for (i::Tagged<i::Script> script = iterator.Next(); !script.is_null();
980 script = iterator.Next()) {
981#if V8_ENABLE_WEBASSEMBLY
982 if (script->type() != i::Script::Type::kNormal &&
983 script->type() != i::Script::Type::kWasm) {
984 continue;
985 }
986#else
987 if (script->type() != i::Script::Type::kNormal) continue;
988#endif // V8_ENABLE_WEBASSEMBLY
989 if (!script->HasValidSource()) continue;
990 i::HandleScope handle_scope(isolate);
991 i::DirectHandle<i::Script> script_handle(script, isolate);
992 scripts.emplace_back(v8_isolate, ToApiHandle<Script>(script_handle));
993 }
994 }
995}
996
998 Local<String> source) {
999 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1000 v8::Local<v8::Context> context = Utils::ToLocal(isolate->native_context());
1005 {
1006 i::AlignedCachedData* cached_data = nullptr;
1007 ScriptCompiler::CompilationDetails compilation_details;
1009 i::Compiler::GetSharedFunctionInfoForScriptWithCachedData(
1010 isolate, str, i::ScriptDetails(), cached_data,
1013 i::v8_flags.expose_inspector_scripts ? i::NOT_NATIVES_CODE
1015 &compilation_details);
1016 has_exception = !maybe_function_info.ToHandle(&result);
1018 }
1020}
1021
1022#if V8_ENABLE_WEBASSEMBLY
1023void EnterDebuggingForIsolate(Isolate* v8_isolate) {
1024 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1025 i::wasm::GetWasmEngine()->EnterDebuggingForIsolate(isolate);
1026}
1027
1028void LeaveDebuggingForIsolate(Isolate* v8_isolate) {
1029 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1030 i::wasm::GetWasmEngine()->LeaveDebuggingForIsolate(isolate);
1031}
1032#endif // V8_ENABLE_WEBASSEMBLY
1033
1034void SetDebugDelegate(Isolate* v8_isolate, DebugDelegate* delegate) {
1035 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1036 isolate->debug()->SetDebugDelegate(delegate);
1037}
1038
1040 reinterpret_cast<i::Isolate*>(v8_isolate)->set_async_event_delegate(delegate);
1041}
1042
1044 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1047 i::SharedFunctionInfo::ScriptIterator iter(isolate,
1048 *Utils::OpenDirectHandle(*script));
1049 for (i::Tagged<i::SharedFunctionInfo> info = iter.Next(); !info.is_null();
1050 info = iter.Next()) {
1051 if (auto debug_info = isolate->debug()->TryGetDebugInfo(info)) {
1052 debug_info.value()->set_computed_debug_is_blackboxed(false);
1053 }
1054 }
1055}
1056
1057int EstimatedValueSize(Isolate* v8_isolate, Local<Value> value) {
1058 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1060 auto object = Utils::OpenDirectHandle(*value);
1061 if (IsSmi(*object)) return i::kTaggedSize;
1062 CHECK(IsHeapObject(*object));
1063 return i::Cast<i::HeapObject>(object)->Size();
1064}
1065
1067 auto obj = Utils::OpenDirectHandle(that);
1068 Utils::ApiCheck(i::IsAccessorPair(*obj), "v8::debug::AccessorPair::Cast",
1069 "Value is not a v8::debug::AccessorPair");
1070}
1071
1072#if V8_ENABLE_WEBASSEMBLY
1073void WasmValueObject::CheckCast(Value* that) {
1074 auto obj = Utils::OpenDirectHandle(that);
1075 Utils::ApiCheck(i::IsWasmValueObject(*obj),
1076 "v8::debug::WasmValueObject::Cast",
1077 "Value is not a v8::debug::WasmValueObject");
1078}
1079
1080bool WasmValueObject::IsWasmValueObject(Local<Value> that) {
1081 auto obj = Utils::OpenDirectHandle(*that);
1082 return i::IsWasmValueObject(*obj);
1083}
1084
1085Local<String> WasmValueObject::type() const {
1087 i::Isolate* isolate = object->GetIsolate();
1088 i::DirectHandle<i::String> type(object->type(), isolate);
1089 return Utils::ToLocal(type);
1090}
1091#endif // V8_ENABLE_WEBASSEMBLY
1092
1093Local<Function> GetBuiltin(Isolate* v8_isolate, Builtin requested_builtin) {
1094 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1096 i::HandleScope handle_scope(isolate);
1097
1098 CHECK_EQ(requested_builtin, kStringToLowerCase);
1099 i::Builtin builtin = i::Builtin::kStringPrototypeToLocaleLowerCase;
1100
1101 i::Factory* factory = isolate->factory();
1102 i::DirectHandle<i::String> name = isolate->factory()->empty_string();
1103 i::DirectHandle<i::NativeContext> context(isolate->native_context());
1105 factory->NewSharedFunctionInfoForBuiltin(name, builtin, 0, i::kAdapt);
1106 info->set_language_mode(i::LanguageMode::kStrict);
1108 i::Factory::JSFunctionBuilder{isolate, info, context}
1109 .set_map(isolate->strict_function_without_prototype_map())
1110 .Build();
1111
1112 return Utils::ToLocal(handle_scope.CloseAndEscape(fun));
1113}
1114
1115void SetConsoleDelegate(Isolate* v8_isolate, ConsoleDelegate* delegate) {
1116 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1118 if (delegate == nullptr) {
1119 isolate->set_console_delegate(nullptr);
1120 } else {
1121 isolate->set_console_delegate(delegate);
1122 }
1123}
1124
1127 : isolate_(info.GetIsolate()),
1128 values_(info.values_),
1129 length_(info.Length()) {}
1130
1133 : isolate_(reinterpret_cast<v8::Isolate*>(isolate)),
1134 values_(args.length() > 1 ? args.address_of_first_argument() : nullptr),
1135 length_(args.length() - 1) {}
1136
1138 Isolate* v8_isolate, v8::Local<v8::Value> v8_error) {
1140 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1142 i::HandleScope scope(isolate);
1143 return Utils::MessageToLocal(
1144 scope.CloseAndEscape(isolate->CreateMessageFromException(obj)));
1145}
1146
1148 auto obj = Utils::OpenDirectHandle(this);
1149 i::Tagged<i::Object> maybe_script = obj->function()->shared()->script();
1150 if (!IsScript(maybe_script)) return {};
1151 i::Isolate* isolate = obj->GetIsolate();
1152 i::DirectHandle<i::Script> script(i::Cast<i::Script>(maybe_script), isolate);
1153 return ToApiHandle<v8::debug::Script>(script);
1154}
1155
1157 auto obj = Utils::OpenDirectHandle(this);
1158 return Utils::ToLocal(direct_handle(obj->function(), obj->GetIsolate()));
1159}
1160
1162 auto obj = Utils::OpenDirectHandle(this);
1163 CHECK(obj->is_suspended());
1164 i::Tagged<i::Object> maybe_script = obj->function()->shared()->script();
1165 if (!IsScript(maybe_script)) return Location();
1166 i::Isolate* isolate = obj->GetIsolate();
1167 i::DirectHandle<i::Script> script(i::Cast<i::Script>(maybe_script), isolate);
1168 i::Script::PositionInfo info;
1169 i::SharedFunctionInfo::EnsureSourcePositionsAvailable(
1170 isolate, i::direct_handle(obj->function()->shared(), isolate));
1171 i::Script::GetPositionInfo(script, obj->source_position(), &info);
1172 return Location(info.line, info.column);
1173}
1174
1176 return Utils::OpenDirectHandle(this)->is_suspended();
1177}
1178
1183
1185 Local<Function> function, Local<Value> recv,
1187 bool throw_on_side_effect) {
1188 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
1190 auto self = Utils::OpenHandle(*function);
1191 auto recv_obj = Utils::OpenHandle(*recv);
1192 static_assert(sizeof(v8::Global<v8::Value>) == sizeof(i::Handle<i::Object>));
1193 auto arguments = reinterpret_cast<i::DirectHandle<i::Object>*>(args.data());
1194 // Disable breaks in side-effect free mode.
1195 i::DisableBreak disable_break_scope(isolate->debug(), throw_on_side_effect);
1196 if (throw_on_side_effect) {
1197 isolate->debug()->StartSideEffectCheckMode();
1198 }
1200 has_exception = !ToLocal<Value>(
1201 i::Execution::Call(isolate, self, recv_obj, {arguments, args.size()}),
1202 &result);
1203 if (throw_on_side_effect) {
1204 isolate->debug()->StopSideEffectCheckMode();
1205 }
1208}
1209
1211 v8::Local<v8::String> source,
1212 EvaluateGlobalMode mode, bool repl) {
1213 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1214 v8::Local<v8::Context> context = Utils::ToLocal(i_isolate->native_context());
1216 i::REPLMode repl_mode = repl ? i::REPLMode::kYes : i::REPLMode::kNo;
1218 has_exception = !ToLocal<Value>(
1219 i::DebugEvaluate::Global(i_isolate, Utils::OpenHandle(*source), mode,
1220 repl_mode),
1221 &result);
1224}
1225
1227 std::vector<v8::Global<v8::String>>* names) {
1228 auto context = Utils::OpenDirectHandle(*v8_context);
1229 i::Isolate* isolate = context->GetIsolate();
1231 context->native_context()->script_context_table(), isolate);
1232 for (int i = 0; i < table->length(kAcquireLoad); i++) {
1233 i::DirectHandle<i::Context> script_context(table->get(i), isolate);
1234 DCHECK(script_context->IsScriptContext());
1235 i::DirectHandle<i::ScopeInfo> scope_info(script_context->scope_info(),
1236 isolate);
1237 for (auto it : i::ScopeInfo::IterateLocalNames(scope_info)) {
1238 if (i::ScopeInfo::VariableIsSynthetic(it->name())) continue;
1239 names->emplace_back(reinterpret_cast<Isolate*>(isolate),
1240 Utils::ToLocal(direct_handle(it->name(), isolate)));
1241 }
1242 }
1243}
1244
1246 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1247 isolate->debug()->set_return_value(*Utils::OpenDirectHandle(*value));
1248}
1249
1250int64_t GetNextRandomInt64(v8::Isolate* v8_isolate) {
1251 return reinterpret_cast<i::Isolate*>(v8_isolate)
1252 ->random_number_generator()
1253 ->NextInt64();
1254}
1255
1257 auto callable = v8::Utils::OpenDirectHandle(*function);
1258 if (!IsJSFunction(*callable)) return i::DebugInfo::kNoDebuggingId;
1259 auto func = i::Cast<i::JSFunction>(callable);
1260 int id = func->GetIsolate()->debug()->GetFunctionDebuggingId(func);
1261 DCHECK_NE(i::DebugInfo::kNoDebuggingId, id);
1262 return id;
1263}
1264
1267 auto callable = Utils::OpenDirectHandle(*function);
1268 if (!IsJSFunction(*callable)) return false;
1269 auto jsfunction = i::Cast<i::JSFunction>(callable);
1270 i::Isolate* isolate = jsfunction->GetIsolate();
1271 i::DirectHandle<i::String> condition_string =
1272 condition.IsEmpty()
1273 ? i::DirectHandle<i::String>(isolate->factory()->empty_string())
1275 return isolate->debug()->SetBreakpointForFunction(
1276 handle(jsfunction->shared(), isolate), condition_string, id);
1277}
1278
1280 : scope_(
1281 new i::PostponeInterruptsScope(reinterpret_cast<i::Isolate*>(isolate),
1282 i::StackGuard::API_INTERRUPT)) {}
1283
1285
1287 : scope_(std::make_unique<i::DisableBreak>(
1288 reinterpret_cast<i::Isolate*>(isolate)->debug())) {}
1289
1291
1293
1294int Coverage::BlockData::EndOffset() const { return block_->end; }
1295
1296uint32_t Coverage::BlockData::Count() const { return block_->count; }
1297
1299
1301
1302uint32_t Coverage::FunctionData::Count() const { return function_->count; }
1303
1307
1309 return function_->blocks.size();
1310}
1311
1313 return function_->has_block_coverage;
1314}
1315
1319
1323
1325 return script_->functions.size();
1326}
1327
1331
1333 std::shared_ptr<i::Coverage> coverage)
1334 : script_(&coverage->at(index)), coverage_(std::move(coverage)) {}
1335
1336size_t Coverage::ScriptCount() const { return coverage_->size(); }
1337
1341
1343 return Coverage(
1344 i::Coverage::CollectPrecise(reinterpret_cast<i::Isolate*>(isolate)));
1345}
1346
1348 return Coverage(
1349 i::Coverage::CollectBestEffort(reinterpret_cast<i::Isolate*>(isolate)));
1350}
1351
1353 i::Coverage::SelectMode(reinterpret_cast<i::Isolate*>(isolate), mode);
1354}
1355
1358 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1361 DCHECK(IsJSReceiver(*internal_key));
1362
1363 i::DirectHandle<i::Object> value(self->Lookup(internal_key), i_isolate);
1364
1365 if (IsTheHole(*value)) return {};
1366 return Utils::ToLocal(value);
1367}
1368
1371 v8::Local<v8::Value> value) {
1374 i::DirectHandle<i::Object> internal_value = Utils::OpenDirectHandle(*value);
1375 DCHECK(IsJSReceiver(*internal_key));
1376
1378 i::EphemeronHashTable::Put(self, internal_key, internal_value));
1379
1381}
1382
1384 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1387 i::EphemeronHashTable::New(i_isolate, 0);
1388 return ToApiHandle<EphemeronTable>(table);
1389}
1390
1392 return static_cast<EphemeronTable*>(value);
1393}
1394
1396 auto accessors = Utils::OpenDirectHandle(this);
1397 i::Isolate* isolate = accessors->GetIsolate();
1398 i::DirectHandle<i::Object> getter(accessors->getter(), isolate);
1399 return Utils::ToLocal(getter);
1400}
1401
1403 auto accessors = Utils::OpenDirectHandle(this);
1404 i::Isolate* isolate = accessors->GetIsolate();
1405 i::DirectHandle<i::Object> setter(accessors->setter(), isolate);
1406 return Utils::ToLocal(setter);
1407}
1408
1410 return i::IsAccessorPair(*Utils::OpenDirectHandle(*that));
1411}
1412
1415 i::Isolate* isolate = promise->GetIsolate();
1416
1418 isolate->factory()->promise_debug_message_symbol();
1419 i::DirectHandle<i::Object> maybeMessage =
1420 i::JSReceiver::GetDataProperty(isolate, promise, key);
1421
1422 if (!IsJSMessageObject(*maybeMessage, isolate)) return MaybeLocal<Message>();
1424}
1425
1427 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1429}
1430
1432 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1434}
1435
1436uint64_t GetIsolateId(v8::Isolate* v8_isolate) {
1437 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1438 return isolate->debug()->IsolateId();
1439}
1440
1441void SetIsolateId(v8::Isolate* v8_isolate, uint64_t id) {
1442 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1443 isolate->debug()->SetIsolateId(id);
1444}
1445
1446std::unique_ptr<PropertyIterator> PropertyIterator::Create(
1447 Local<Context> context, Local<Object> object, bool skip_indices) {
1448 internal::Isolate* isolate =
1449 reinterpret_cast<i::Isolate*>(context->GetIsolate());
1450 if (isolate->is_execution_terminating()) {
1451 return nullptr;
1452 }
1453 CallDepthScope<false> call_depth_scope(isolate, context);
1454
1455 return i::DebugPropertyIterator::Create(
1456 isolate, Utils::OpenDirectHandle(*object), skip_indices);
1457}
1458
1459} // namespace debug
1460
1461namespace internal {
1462
1463Maybe<bool> DebugPropertyIterator::Advance() {
1464 if (isolate_->is_execution_terminating()) {
1465 return Nothing<bool>();
1466 }
1467 Local<v8::Context> context = Utils::ToLocal(
1468 direct_handle(isolate_->context()->native_context(), isolate_));
1469 CallDepthScope<false> call_depth_scope(isolate_, context);
1470
1471 if (!AdvanceInternal()) {
1472 DCHECK(isolate_->has_exception());
1473 return Nothing<bool>();
1474 }
1475 return Just(true);
1476}
1477
1478} // namespace internal
1479} // namespace v8
1480
#define RETURN_ON_FAILED_EXECUTION(T)
Definition api-macros.h:106
#define DCHECK_NO_SCRIPT_NO_EXCEPTION(i_isolate)
Definition api-macros.h:97
#define PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(i_isolate, context, T)
Definition api-macros.h:51
#define ENTER_V8_BASIC(i_isolate)
Definition api-macros.h:36
#define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate)
Definition api-macros.h:99
#define API_RCS_SCOPE(i_isolate, class_name, function_name)
Definition api-macros.h:32
#define RETURN_ESCAPED(value)
Definition api-macros.h:112
Isolate * isolate_
const char * name
Definition builtins.cc:39
PropertyT * setter
PropertyT * getter
@ kAsyncStackTaggingCreateTaskCall
Definition v8-isolate.h:585
bool empty() const noexcept
void reserve(size_t n)
size_t size() const noexcept
void push_back(const Local< T > &x)
constexpr size_t size() const
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition api.h:274
static Local< To > Convert(v8::internal::DirectHandle< From > obj)
Definition api-inl.h:59
static v8::internal::DirectHandle< To > OpenDirectHandle(v8::Local< From > handle)
Definition api.h:279
static V8_INLINE bool ApiCheck(bool condition, const char *location, const char *message)
Definition api.h:214
static void CheckCast(v8::Value *obj)
v8::Local< v8::Value > setter()
static bool IsAccessorPair(v8::Local< v8::Value > obj)
v8::Local< v8::Value > getter()
ConsoleCallArguments(const v8::FunctionCallbackInfo< v8::Value > &)
BlockData GetBlockData(size_t i) const
MaybeLocal< String > Name() const
FunctionData GetFunctionData(size_t i) const
ScriptData(size_t index, std::shared_ptr< i::Coverage > c)
Local< debug::Script > GetScript() const
static void SelectMode(Isolate *isolate, CoverageMode mode)
Coverage(std::shared_ptr< i::Coverage > coverage)
static Coverage CollectPrecise(Isolate *isolate)
static Coverage CollectBestEffort(Isolate *isolate)
ScriptData GetScriptData(size_t i) const
std::shared_ptr< i::Coverage > coverage_
size_t ScriptCount() const
DisableBreakScope(v8::Isolate *isolate)
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT v8::MaybeLocal< v8::Value > Get(v8::Isolate *isolate, v8::Local< v8::Value > key)
static V8_EXPORT_PRIVATE Local< EphemeronTable > New(v8::Isolate *isolate)
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT v8::Local< EphemeronTable > Set(v8::Isolate *isolate, v8::Local< v8::Value > key, v8::Local< v8::Value > value)
static V8_INLINE EphemeronTable * Cast(Value *obj)
static v8::Local< debug::GeneratorObject > Cast(v8::Local< v8::Value > value)
debug::Location SuspendedLocation()
v8::MaybeLocal< debug::Script > Script()
v8::Local< v8::Function > Function()
PostponeInterruptsScope(v8::Isolate *isolate)
static V8_WARN_UNUSED_RESULT std::unique_ptr< PropertyIterator > Create(v8::Local< v8::Context > context, v8::Local< v8::Object > object, bool skip_indices=false)
MaybeLocal< String > JavaScriptCode() const
bool IsEmbedded() const
MaybeLocal< String > Name() const
MaybeLocal< String > SourceURL() const
MaybeLocal< String > GetSha256Hash() const
bool SetScriptSource(v8::Local< v8::String > newSource, bool preview, bool allow_top_frame_live_editing, LiveEditResult *result) const
Local< ScriptSource > Source() const
bool GetPossibleBreakpoints(const debug::Location &start, const debug::Location &end, bool restrict_to_function, std::vector< debug::BreakLocation > *locations) const
Maybe< int > ContextId() const
bool WasCompiled() const
v8::debug::Location GetSourceLocation(int offset) const
ScriptOriginOptions OriginOptions() const
v8::Isolate * GetIsolate() const
Maybe< int > GetSourceOffset(const debug::Location &location, GetSourceOffsetMode mode=GetSourceOffsetMode::kStrict) const
bool SetInstrumentationBreakpoint(BreakpointId *id) const
MaybeLocal< String > SourceMappingURL() const
bool SetBreakpoint(v8::Local< v8::String > condition, debug::Location *location, BreakpointId *id) const
void SetDebugDelegate(debug::DebugDelegate *delegate)
Definition debug.cc:2805
void NotifyDebuggerPausedEventSent()
Definition debug.cc:3384
void SetIsolateId(uint64_t id)
Definition debug.h:509
void ChangeBreakOnException(ExceptionBreakType type, bool enable)
Definition debug.cc:1255
void SetBreakOnNextFunctionCall()
Definition debug.cc:1308
uint64_t IsolateId() const
Definition debug.h:508
bool SetScriptSource(Handle< Script > script, Handle< String > source, bool preview, bool allow_top_frame_live_editing, debug::LiveEditResult *result)
Definition debug.cc:2745
void ClearBreakOnNextFunctionCall()
Definition debug.cc:1319
void set_return_value(Tagged< Object > value)
Definition debug.h:447
V8_WARN_UNUSED_RESULT HandleType< String >::MaybeType NewConsString(HandleType< String > left, HandleType< String > right, AllocationType allocation=AllocationType::kYoung)
Handle< String > NewStringFromAsciiChecked(const char *str, AllocationType allocation=AllocationType::kYoung)
Handle< SharedFunctionInfo > NewSharedFunctionInfoForBuiltin(MaybeDirectHandle< String > name, Builtin builtin, int len, AdaptArguments adapt, FunctionKind kind=FunctionKind::kNormalFunction)
Definition factory.cc:3904
V8_WARN_UNUSED_RESULT MaybeHandle< String > NewStringFromUtf8(base::Vector< const char > str, AllocationType allocation=AllocationType::kYoung)
Definition factory.cc:753
Handle< String > NewProperSubString(DirectHandle< String > str, uint32_t begin, uint32_t end)
Definition factory.cc:1090
HandleType< T > CloseAndEscape(HandleType< T > handle_value)
MaybeDirectHandle< String > Finish()
V8_INLINE void AppendString(std::string_view str)
V8_INLINE void AppendCStringLiteral(const char(&literal)[N])
DateCache * date_cache() const
Definition isolate.h:1619
void CountUsage(v8::Isolate::UseCounterFeature feature)
Definition isolate.cc:7028
Handle< NativeContext > native_context()
Definition isolate-inl.h:48
v8::internal::Factory * factory()
Definition isolate.h:1527
Debug * debug() const
Definition isolate.h:1474
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(DirectHandle< S > *out) const
V8_INLINE constexpr bool is_null() const
Definition tagged.h:502
const JSFunctionRef function_
std::atomic< bool > is_empty_
Definition sweeper.cc:213
int start
Handle< SharedFunctionInfo > info
int end
DeclarationScope * scope_
Handle< Script > script_
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
Definition isolate.h:276
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage report a tick only when allocated zone memory changes by this amount TracingFlags::gc_stats TracingFlags::gc_stats track native contexts that are expected to be garbage collected verify heap pointers before and after GC memory reducer runs GC with ReduceMemoryFootprint flag Maximum number of memory reducer GCs scheduled Old gen GC speed is computed directly from gc tracer counters Perform compaction on full GCs based on V8 s default heuristics Perform compaction on every full GC Perform code space compaction when finalizing a full GC with stack Stress GC compaction to flush out bugs with moving objects flush of baseline code when it has not been executed recently Use time base code flushing instead of age Use a progress bar to scan large objects in increments when incremental marking is active force incremental marking for small heaps and run it more often force marking at random points between and force scavenge at random points between and reclaim otherwise unreachable unmodified wrapper objects when possible less compaction in non memory reducing mode use high priority threads for concurrent Marking Test mode only flag It allows an unit test to select evacuation candidates use incremental marking for CppHeap cppheap_concurrent_marking c value for membalancer A special constant to balance between memory and space tradeoff The smaller the more memory it uses enable use of SSE4 instructions if available enable use of AVX VNNI instructions if available enable use of POPCNT instruction if available force all emitted branches to be in long mode(MIPS/PPC only)") DEFINE_BOOL(partial_constant_pool
Isolate * isolate
int32_t offset
TNode< Context > context
TNode< Object > receiver
SharedFunctionInfoRef shared
DateRecord date
ZoneVector< RpoNumber > & result
InstructionOperand source
const int length_
Definition mul-fft.cc:473
EmbedderStackState
Definition common.h:15
STL namespace.
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
void SetBreakPointsActive(Isolate *v8_isolate, bool is_active)
int EstimatedValueSize(Isolate *v8_isolate, Local< Value > value)
bool PrepareRestartFrame(Isolate *v8_isolate, int callFrameOrdinal)
MaybeLocal< Value > CallFunctionOn(Local< Context > context, Local< Function > function, Local< Value > recv, base::Vector< Local< Value > > args, bool throw_on_side_effect)
void ResetBlackboxedStateCache(Isolate *v8_isolate, Local< Script > script)
void GlobalLexicalScopeNames(v8::Local< v8::Context > v8_context, std::vector< v8::Global< v8::String > > *names)
void BreakRightNow(Isolate *v8_isolate, base::EnumSet< debug::BreakReason > break_reasons)
void SetReturnValue(v8::Isolate *v8_isolate, v8::Local< v8::Value > value)
void SetBreakOnNextFunctionCall(Isolate *isolate)
bool CanBreakProgram(Isolate *v8_isolate)
bool GetPrivateMembers(Local< Context > context, Local< Object > object, int filter, LocalVector< Value > *names_out, LocalVector< Value > *values_out)
void ForceGarbageCollection(Isolate *isolate, StackState embedder_stack_state)
void ChangeBreakOnException(Isolate *isolate, ExceptionBreakState type)
MaybeLocal< UnboundScript > CompileInspectorScript(Isolate *v8_isolate, Local< String > source)
Local< Function > GetBuiltin(Isolate *v8_isolate, Builtin requested_builtin)
bool SetFunctionBreakpoint(v8::Local< v8::Function > function, v8::Local< v8::String > condition, BreakpointId *id)
void SetConsoleDelegate(Isolate *v8_isolate, ConsoleDelegate *delegate)
MaybeLocal< Array > GetInternalProperties(Isolate *v8_isolate, Local< Value > value)
int GetContextId(Local< Context > context)
void SetIsolateId(v8::Isolate *v8_isolate, uint64_t id)
void SetTerminateOnResume(Isolate *v8_isolate)
Local< String > GetDateDescription(Local< Date > date)
MaybeLocal< v8::Value > EvaluateGlobal(v8::Isolate *isolate, v8::Local< v8::String > source, EvaluateGlobalMode mode, bool repl)
Local< String > GetFunctionDescription(Local< Function > function)
int64_t GetNextRandomInt64(v8::Isolate *v8_isolate)
void PrepareStep(Isolate *v8_isolate, StepAction action)
void ClearStepping(Isolate *v8_isolate)
MaybeLocal< Message > GetMessageFromPromise(Local< Promise > p)
void RemoveBreakpoint(Isolate *v8_isolate, BreakpointId id)
Platform * GetCurrentPlatform()
void RecordAsyncStackTaggingCreateTaskCall(v8::Isolate *v8_isolate)
int GetDebuggingId(v8::Local< v8::Function > function)
Local< String > GetBigIntStringValue(Isolate *isolate, Local< BigInt > bigint)
void GetLoadedScripts(Isolate *v8_isolate, std::vector< v8::Global< Script > > &scripts)
void SetAsyncEventDelegate(Isolate *v8_isolate, AsyncEventDelegate *delegate)
void ClearBreakOnNextFunctionCall(Isolate *isolate)
void NotifyDebuggerPausedEventSent(v8::Isolate *v8_isolate)
void SetInspector(Isolate *isolate, v8_inspector::V8Inspector *inspector)
uint64_t GetIsolateId(v8::Isolate *v8_isolate)
void SetContextId(Local< Context > context, int id)
v8_inspector::V8Inspector * GetInspector(Isolate *isolate)
v8::Local< v8::Message > CreateMessageFromException(Isolate *v8_isolate, v8::Local< v8::Value > v8_error)
void SetDebugDelegate(Isolate *v8_isolate, DebugDelegate *delegate)
MaybeLocal< Context > GetCreationContext(Local< Object > value)
Local< String > GetBigIntDescription(Isolate *isolate, Local< BigInt > bigint)
void Disassemble(const WasmModule *module, ModuleWireBytes wire_bytes, NamesProvider *names, v8::debug::DisassemblyCollector *collector, std::vector< int > *function_body_offsets)
constexpr int kTaggedSize
Definition globals.h:542
@ kIgnoreIfAllFramesBlackboxed
Definition debug.h:65
ReadOnlyRoots GetReadOnlyRoots()
Definition roots-inl.h:86
bool IsPrivateMethodVariableMode(VariableMode mode)
Definition globals.h:2131
DateBuffer ToDateString(double time_val, DateCache *date_cache, ToDateStringMode mode)
Definition date.cc:572
@ BreakCaughtException
Definition debug.h:48
@ BreakUncaughtException
Definition debug.h:49
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
constexpr AdaptArguments kAdapt
Definition globals.h:2775
V8_EXPORT_PRIVATE FlagValues v8_flags
bool IsPrivateAccessorVariableMode(VariableMode mode)
Definition globals.h:2126
bool IsPrivateMethodOrAccessorVariableMode(VariableMode mode)
Definition globals.h:2135
constexpr int kMaxInt
Definition globals.h:374
DirectHandle< String > GetWasmFunctionDebugName(Isolate *isolate, DirectHandle< WasmTrustedInstanceData > instance_data, uint32_t func_index)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Maybe< T > Nothing()
Definition v8-maybe.h:112
bool ToLocal(v8::internal::MaybeDirectHandle< v8::internal::Object > maybe, Local< T > *local)
Definition api.h:303
v8::Local< T > ToApiHandle(v8::internal::DirectHandle< v8::internal::Object > obj)
Definition api.h:297
static constexpr AcquireLoadTag kAcquireLoad
Definition globals.h:2908
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define END_ALLOW_USE_DEPRECATED()
Definition v8config.h:634
#define START_ALLOW_USE_DEPRECATED()
Definition v8config.h:633
std::unique_ptr< ValueMirror > value
std::unique_ptr< ValueMirror > key
wasm::ValueType type