%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
// Copyright 2021 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/debug/debug-interface.h" #include "src/api/api-inl.h" #include "src/base/utils/random-number-generator.h" #include "src/codegen/script-details.h" #include "src/debug/debug-coverage.h" #include "src/debug/debug-evaluate.h" #include "src/debug/debug-property-iterator.h" #include "src/debug/debug-type-profile.h" #include "src/debug/debug.h" #include "src/execution/vm-state-inl.h" #include "src/objects/js-generator-inl.h" #include "src/objects/stack-frame-info-inl.h" #include "src/profiler/heap-profiler.h" #include "src/regexp/regexp-stack.h" #include "src/strings/string-builder-inl.h" #if V8_ENABLE_WEBASSEMBLY #include "src/debug/debug-wasm-objects-inl.h" #include "src/wasm/wasm-engine.h" #endif // V8_ENABLE_WEBASSEMBLY // Has to be the last include (doesn't have include guards): #include "src/api/api-macros.h" namespace v8 { namespace debug { void SetContextId(Local<Context> context, int id) { Utils::OpenHandle(*context)->set_debug_context_id(i::Smi::FromInt(id)); } int GetContextId(Local<Context> context) { i::Object value = Utils::OpenHandle(*context)->debug_context_id(); return (value.IsSmi()) ? i::Smi::ToInt(value) : 0; } void SetInspector(Isolate* isolate, v8_inspector::V8Inspector* inspector) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i_isolate->set_inspector(inspector); } v8_inspector::V8Inspector* GetInspector(Isolate* isolate) { return reinterpret_cast<i::Isolate*>(isolate)->inspector(); } Local<String> GetFunctionDebugName(Local<StackFrame> frame) { #if V8_ENABLE_WEBASSEMBLY auto info = Utils::OpenHandle(*frame); if (info->IsWasm()) { auto isolate = info->GetIsolate(); auto instance = handle(info->GetWasmInstance(), isolate); auto func_index = info->GetWasmFunctionIndex(); return Utils::ToLocal( i::GetWasmFunctionDebugName(isolate, instance, func_index)); } #endif // V8_ENABLE_WEBASSEMBLY return frame->GetFunctionName(); } Local<String> GetFunctionDescription(Local<Function> function) { auto receiver = Utils::OpenHandle(*function); if (receiver->IsJSBoundFunction()) { return Utils::ToLocal(i::JSBoundFunction::ToString( i::Handle<i::JSBoundFunction>::cast(receiver))); } if (receiver->IsJSFunction()) { auto function = i::Handle<i::JSFunction>::cast(receiver); #if V8_ENABLE_WEBASSEMBLY if (function->shared().HasWasmExportedFunctionData()) { auto isolate = function->GetIsolate(); auto func_index = function->shared().wasm_exported_function_data().function_index(); auto instance = i::handle( function->shared().wasm_exported_function_data().instance(), isolate); if (instance->module()->origin == i::wasm::kWasmOrigin) { // For asm.js functions, we can still print the source // code (hopefully), so don't bother with them here. auto debug_name = i::GetWasmFunctionDebugName(isolate, instance, func_index); i::IncrementalStringBuilder builder(isolate); builder.AppendCString("function "); builder.AppendString(debug_name); builder.AppendCString("() { [native code] }"); return Utils::ToLocal(builder.Finish().ToHandleChecked()); } } #endif // V8_ENABLE_WEBASSEMBLY return Utils::ToLocal(i::JSFunction::ToString(function)); } return Utils::ToLocal( receiver->GetIsolate()->factory()->function_native_code_string()); } void SetBreakOnNextFunctionCall(Isolate* isolate) { reinterpret_cast<i::Isolate*>(isolate)->debug()->SetBreakOnNextFunctionCall(); } void ClearBreakOnNextFunctionCall(Isolate* isolate) { reinterpret_cast<i::Isolate*>(isolate) ->debug() ->ClearBreakOnNextFunctionCall(); } MaybeLocal<Array> GetInternalProperties(Isolate* v8_isolate, Local<Value> value) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::Handle<i::Object> val = Utils::OpenHandle(*value); i::Handle<i::JSArray> result; if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result)) return MaybeLocal<Array>(); return Utils::ToLocal(result); } namespace { void 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) { i::Handle<i::ScopeInfo> scope_info(context->scope_info(), isolate); int local_count = scope_info->ContextLocalCount(); for (int j = 0; j < local_count; ++j) { i::VariableMode mode = scope_info->ContextLocalMode(j); i::IsStaticFlag flag = scope_info->ContextLocalIsStaticFlag(j); if (!i::IsPrivateMethodOrAccessorVariableMode(mode) || flag != is_static_flag) { continue; } i::Handle<i::String> name(scope_info->ContextLocalName(j), isolate); int context_index = scope_info->ContextHeaderLength() + j; i::Handle<i::Object> slot_value(context->get(context_index), isolate); DCHECK_IMPLIES(mode == i::VariableMode::kPrivateMethod, slot_value->IsJSFunction()); DCHECK_IMPLIES(mode != i::VariableMode::kPrivateMethod, slot_value->IsAccessorPair()); names_out->push_back(Utils::ToLocal(name)); values_out->push_back(Utils::ToLocal(slot_value)); } } } // namespace bool GetPrivateMembers(Local<Context> context, Local<Object> value, std::vector<Local<Value>>* names_out, std::vector<Local<Value>>* values_out) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate()); LOG_API(isolate, debug, GetPrivateMembers); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::Handle<i::JSReceiver> receiver = Utils::OpenHandle(*value); i::Handle<i::JSArray> names; i::Handle<i::FixedArray> values; i::PropertyFilter key_filter = static_cast<i::PropertyFilter>(i::PropertyFilter::PRIVATE_NAMES_ONLY); i::Handle<i::FixedArray> keys; ASSIGN_RETURN_ON_EXCEPTION_VALUE( isolate, keys, i::KeyAccumulator::GetKeys(receiver, i::KeyCollectionMode::kOwnOnly, key_filter, i::GetKeysConversion::kConvertToString), false); // Estimate number of private fields and private instance methods/accessors. int private_entries_count = 0; for (int i = 0; i < keys->length(); ++i) { // Exclude the private brand symbols. i::Handle<i::Symbol> key(i::Symbol::cast(keys->get(i)), isolate); if (key->is_private_brand()) { i::Handle<i::Object> value; ASSIGN_RETURN_ON_EXCEPTION_VALUE( isolate, value, i::Object::GetProperty(isolate, receiver, key), false); i::Handle<i::Context> context(i::Context::cast(*value), isolate); i::Handle<i::ScopeInfo> scope_info(context->scope_info(), isolate); // At least one slot contains the brand symbol so it does not count. private_entries_count += (scope_info->ContextLocalCount() - 1); } else { private_entries_count++; } } // Estimate number of static private methods/accessors for classes. bool has_static_private_methods_or_accessors = false; if (receiver->IsJSFunction()) { i::Handle<i::JSFunction> func(i::JSFunction::cast(*receiver), isolate); i::Handle<i::SharedFunctionInfo> shared(func->shared(), isolate); if (shared->is_class_constructor() && shared->has_static_private_methods_or_accessors()) { has_static_private_methods_or_accessors = true; i::Handle<i::Context> context(func->context(), isolate); i::Handle<i::ScopeInfo> scope_info(context->scope_info(), isolate); int local_count = scope_info->ContextLocalCount(); for (int j = 0; j < local_count; ++j) { i::VariableMode mode = scope_info->ContextLocalMode(j); i::IsStaticFlag is_static_flag = scope_info->ContextLocalIsStaticFlag(j); if (i::IsPrivateMethodOrAccessorVariableMode(mode) && is_static_flag == i::IsStaticFlag::kStatic) { private_entries_count += local_count; break; } } } } DCHECK(names_out->empty()); names_out->reserve(private_entries_count); DCHECK(values_out->empty()); values_out->reserve(private_entries_count); if (has_static_private_methods_or_accessors) { i::Handle<i::Context> context(i::JSFunction::cast(*receiver).context(), isolate); CollectPrivateMethodsAndAccessorsFromContext( isolate, context, i::IsStaticFlag::kStatic, names_out, values_out); } for (int i = 0; i < keys->length(); ++i) { i::Handle<i::Object> obj_key(keys->get(i), isolate); i::Handle<i::Symbol> key(i::Symbol::cast(*obj_key), isolate); CHECK(key->is_private_name()); i::Handle<i::Object> value; ASSIGN_RETURN_ON_EXCEPTION_VALUE( isolate, value, i::Object::GetProperty(isolate, receiver, key), false); if (key->is_private_brand()) { DCHECK(value->IsContext()); i::Handle<i::Context> context(i::Context::cast(*value), isolate); CollectPrivateMethodsAndAccessorsFromContext( isolate, context, i::IsStaticFlag::kNotStatic, names_out, values_out); } else { // Private fields i::Handle<i::String> name( i::String::cast(i::Symbol::cast(*key).description()), isolate); names_out->push_back(Utils::ToLocal(name)); values_out->push_back(Utils::ToLocal(value)); } } DCHECK_EQ(names_out->size(), values_out->size()); DCHECK_LE(names_out->size(), private_entries_count); return true; } MaybeLocal<Context> GetCreationContext(Local<Object> value) { i::Handle<i::Object> val = Utils::OpenHandle(*value); if (val->IsJSGlobalProxy()) { return MaybeLocal<Context>(); } return value->GetCreationContext(); } void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState type) { i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); internal_isolate->debug()->ChangeBreakOnException( i::BreakException, type == BreakOnAnyException); internal_isolate->debug()->ChangeBreakOnException(i::BreakUncaughtException, type != NoBreakOnException); } void SetBreakPointsActive(Isolate* v8_isolate, bool is_active) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); isolate->debug()->set_break_points_active(is_active); } void PrepareStep(Isolate* v8_isolate, StepAction action) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_DO_NOT_USE(isolate); CHECK(isolate->debug()->CheckExecutionState()); // Clear all current stepping setup. isolate->debug()->ClearStepping(); // Prepare step. isolate->debug()->PrepareStep(static_cast<i::StepAction>(action)); } void ClearStepping(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); // Clear all current stepping setup. isolate->debug()->ClearStepping(); } void BreakRightNow(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_DO_NOT_USE(isolate); isolate->debug()->HandleDebugBreak(i::kIgnoreIfAllFramesBlackboxed); } void SetTerminateOnResume(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); isolate->debug()->SetTerminateOnResume(); } bool CanBreakProgram(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_DO_NOT_USE(isolate); // We cannot break a program if we are currently running a regexp. // TODO(yangguo): fix this exception. return !isolate->regexp_stack()->is_in_use() && isolate->debug()->AllFramesOnStackAreBlackboxed(); } Isolate* Script::GetIsolate() const { return reinterpret_cast<Isolate*>(Utils::OpenHandle(this)->GetIsolate()); } ScriptOriginOptions Script::OriginOptions() const { return Utils::OpenHandle(this)->origin_options(); } bool Script::WasCompiled() const { return Utils::OpenHandle(this)->compilation_state() == i::Script::COMPILATION_STATE_COMPILED; } bool Script::IsEmbedded() const { i::Handle<i::Script> script = Utils::OpenHandle(this); return script->context_data() == script->GetReadOnlyRoots().uninitialized_symbol(); } int Script::Id() const { return Utils::OpenHandle(this)->id(); } int Script::LineOffset() const { return Utils::OpenHandle(this)->line_offset(); } int Script::ColumnOffset() const { return Utils::OpenHandle(this)->column_offset(); } std::vector<int> Script::LineEnds() const { i::Handle<i::Script> script = Utils::OpenHandle(this); #if V8_ENABLE_WEBASSEMBLY if (script->type() == i::Script::TYPE_WASM) return {}; #endif // V8_ENABLE_WEBASSEMBLY i::Isolate* isolate = script->GetIsolate(); i::HandleScope scope(isolate); i::Script::InitLineEnds(isolate, script); CHECK(script->line_ends().IsFixedArray()); i::Handle<i::FixedArray> line_ends(i::FixedArray::cast(script->line_ends()), isolate); std::vector<int> result(line_ends->length()); for (int i = 0; i < line_ends->length(); ++i) { i::Smi line_end = i::Smi::cast(line_ends->get(i)); result[i] = line_end.value(); } return result; } MaybeLocal<String> Script::Name() const { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Isolate* isolate = script->GetIsolate(); i::HandleScope handle_scope(isolate); i::Handle<i::Object> value(script->name(), isolate); if (!value->IsString()) return MaybeLocal<String>(); return Utils::ToLocal( handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); } MaybeLocal<String> Script::SourceURL() const { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Isolate* isolate = script->GetIsolate(); i::HandleScope handle_scope(isolate); i::Handle<i::Object> value(script->source_url(), isolate); if (!value->IsString()) return MaybeLocal<String>(); return Utils::ToLocal( handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); } MaybeLocal<String> Script::SourceMappingURL() const { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Isolate* isolate = script->GetIsolate(); i::HandleScope handle_scope(isolate); i::Handle<i::Object> value(script->source_mapping_url(), isolate); if (!value->IsString()) return MaybeLocal<String>(); return Utils::ToLocal( handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); } Maybe<int> Script::ContextId() const { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Isolate* isolate = script->GetIsolate(); i::HandleScope handle_scope(isolate); i::Object value = script->context_data(); if (value.IsSmi()) return Just(i::Smi::ToInt(value)); return Nothing<int>(); } MaybeLocal<String> Script::Source() const { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Isolate* isolate = script->GetIsolate(); i::HandleScope handle_scope(isolate); i::Handle<i::Object> value(script->source(), isolate); if (!value->IsString()) return MaybeLocal<String>(); return Utils::ToLocal( handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); } #if V8_ENABLE_WEBASSEMBLY bool Script::IsWasm() const { return Utils::OpenHandle(this)->type() == i::Script::TYPE_WASM; } #endif // V8_ENABLE_WEBASSEMBLY bool Script::IsModule() const { return Utils::OpenHandle(this)->origin_options().IsModule(); } namespace { int GetSmiValue(i::Handle<i::FixedArray> array, int index) { return i::Smi::ToInt(array->get(index)); } bool CompareBreakLocation(const i::BreakLocation& loc1, const i::BreakLocation& loc2) { return loc1.position() < loc2.position(); } } // namespace bool Script::GetPossibleBreakpoints( const Location& start, const Location& end, bool restrict_to_function, std::vector<BreakLocation>* locations) const { CHECK(!start.IsEmpty()); i::Handle<i::Script> script = Utils::OpenHandle(this); #if V8_ENABLE_WEBASSEMBLY if (script->type() == i::Script::TYPE_WASM) { i::wasm::NativeModule* native_module = script->wasm_native_module(); return i::WasmScript::GetPossibleBreakpoints(native_module, start, end, locations); } #endif // V8_ENABLE_WEBASSEMBLY i::Isolate* isolate = script->GetIsolate(); i::Script::InitLineEnds(isolate, script); CHECK(script->line_ends().IsFixedArray()); i::Handle<i::FixedArray> line_ends = i::Handle<i::FixedArray>::cast(i::handle(script->line_ends(), isolate)); CHECK(line_ends->length()); int start_offset = GetSourceOffset(start); int end_offset = end.IsEmpty() ? GetSmiValue(line_ends, line_ends->length() - 1) + 1 : GetSourceOffset(end); if (start_offset >= end_offset) return true; std::vector<i::BreakLocation> v8_locations; if (!isolate->debug()->GetPossibleBreakpoints( script, start_offset, end_offset, restrict_to_function, &v8_locations)) { return false; } std::sort(v8_locations.begin(), v8_locations.end(), CompareBreakLocation); int current_line_end_index = 0; for (const auto& v8_location : v8_locations) { int offset = v8_location.position(); while (offset > GetSmiValue(line_ends, current_line_end_index)) { ++current_line_end_index; CHECK(current_line_end_index < line_ends->length()); } int line_offset = 0; if (current_line_end_index > 0) { line_offset = GetSmiValue(line_ends, current_line_end_index - 1) + 1; } locations->emplace_back( current_line_end_index + script->line_offset(), offset - line_offset + (current_line_end_index == 0 ? script->column_offset() : 0), v8_location.type()); } return true; } int Script::GetSourceOffset(const Location& location) const { i::Handle<i::Script> script = Utils::OpenHandle(this); #if V8_ENABLE_WEBASSEMBLY if (script->type() == i::Script::TYPE_WASM) { DCHECK_EQ(0, location.GetLineNumber()); return location.GetColumnNumber(); } #endif // V8_ENABLE_WEBASSEMBLY int line = std::max(location.GetLineNumber() - script->line_offset(), 0); int column = location.GetColumnNumber(); if (line == 0) { column = std::max(0, column - script->column_offset()); } i::Script::InitLineEnds(script->GetIsolate(), script); CHECK(script->line_ends().IsFixedArray()); i::Handle<i::FixedArray> line_ends = i::Handle<i::FixedArray>::cast( i::handle(script->line_ends(), script->GetIsolate())); CHECK(line_ends->length()); if (line >= line_ends->length()) return GetSmiValue(line_ends, line_ends->length() - 1); int line_offset = GetSmiValue(line_ends, line); if (line == 0) return std::min(column, line_offset); int prev_line_offset = GetSmiValue(line_ends, line - 1); return std::min(prev_line_offset + column + 1, line_offset); } Location Script::GetSourceLocation(int offset) const { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Script::PositionInfo info; i::Script::GetPositionInfo(script, offset, &info, i::Script::WITH_OFFSET); return Location(info.line, info.column); } bool Script::SetScriptSource(Local<String> newSource, bool preview, LiveEditResult* result) const { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Isolate* isolate = script->GetIsolate(); return isolate->debug()->SetScriptSource( script, Utils::OpenHandle(*newSource), preview, result); } bool Script::SetBreakpoint(Local<String> condition, Location* location, BreakpointId* id) const { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Isolate* isolate = script->GetIsolate(); int offset = GetSourceOffset(*location); if (!isolate->debug()->SetBreakPointForScript( script, Utils::OpenHandle(*condition), &offset, id)) { return false; } *location = GetSourceLocation(offset); return true; } bool Script::SetBreakpointOnScriptEntry(BreakpointId* id) const { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Isolate* isolate = script->GetIsolate(); #if V8_ENABLE_WEBASSEMBLY if (script->type() == i::Script::TYPE_WASM) { isolate->debug()->SetOnEntryBreakpointForWasmScript(script, id); return true; } #endif // V8_ENABLE_WEBASSEMBLY i::SharedFunctionInfo::ScriptIterator it(isolate, *script); for (i::SharedFunctionInfo sfi = it.Next(); !sfi.is_null(); sfi = it.Next()) { if (sfi.is_toplevel()) { return isolate->debug()->SetBreakpointForFunction( handle(sfi, isolate), isolate->factory()->empty_string(), id); } } return false; } #if V8_ENABLE_WEBASSEMBLY void Script::RemoveWasmBreakpoint(BreakpointId id) { i::Handle<i::Script> script = Utils::OpenHandle(this); i::Isolate* isolate = script->GetIsolate(); isolate->debug()->RemoveBreakpointForWasmScript(script, id); } #endif // V8_ENABLE_WEBASSEMBLY void RemoveBreakpoint(Isolate* v8_isolate, BreakpointId id) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); i::HandleScope handle_scope(isolate); isolate->debug()->RemoveBreakpoint(id); } Platform* GetCurrentPlatform() { return i::V8::GetCurrentPlatform(); } void ForceGarbageCollection( Isolate* isolate, EmbedderHeapTracer::EmbedderStackState embedder_stack_state) { i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap(); heap->SetEmbedderStackStateForNextFinalization(embedder_stack_state); isolate->LowMemoryNotification(); } #if V8_ENABLE_WEBASSEMBLY WasmScript* WasmScript::Cast(Script* script) { CHECK(script->IsWasm()); return static_cast<WasmScript*>(script); } WasmScript::DebugSymbolsType WasmScript::GetDebugSymbolType() const { i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); switch (script->wasm_native_module()->module()->debug_symbols.type) { case i::wasm::WasmDebugSymbols::Type::None: return WasmScript::DebugSymbolsType::None; case i::wasm::WasmDebugSymbols::Type::EmbeddedDWARF: return WasmScript::DebugSymbolsType::EmbeddedDWARF; case i::wasm::WasmDebugSymbols::Type::ExternalDWARF: return WasmScript::DebugSymbolsType::ExternalDWARF; case i::wasm::WasmDebugSymbols::Type::SourceMap: return WasmScript::DebugSymbolsType::SourceMap; } } MemorySpan<const char> WasmScript::ExternalSymbolsURL() const { i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); const i::wasm::WasmDebugSymbols& symbols = script->wasm_native_module()->module()->debug_symbols; if (symbols.external_url.is_empty()) return {}; internal::wasm::ModuleWireBytes wire_bytes( script->wasm_native_module()->wire_bytes()); i::wasm::WasmName external_url = wire_bytes.GetNameOrNull(symbols.external_url); return {external_url.data(), external_url.size()}; } int WasmScript::NumFunctions() const { i::DisallowGarbageCollection no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); i::wasm::NativeModule* native_module = script->wasm_native_module(); const i::wasm::WasmModule* module = native_module->module(); DCHECK_GE(i::kMaxInt, module->functions.size()); return static_cast<int>(module->functions.size()); } int WasmScript::NumImportedFunctions() const { i::DisallowGarbageCollection no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); i::wasm::NativeModule* native_module = script->wasm_native_module(); const i::wasm::WasmModule* module = native_module->module(); DCHECK_GE(i::kMaxInt, module->num_imported_functions); return static_cast<int>(module->num_imported_functions); } MemorySpan<const uint8_t> WasmScript::Bytecode() const { i::Handle<i::Script> script = Utils::OpenHandle(this); base::Vector<const uint8_t> wire_bytes = script->wasm_native_module()->wire_bytes(); return {wire_bytes.begin(), wire_bytes.size()}; } std::pair<int, int> WasmScript::GetFunctionRange(int function_index) const { i::DisallowGarbageCollection no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); i::wasm::NativeModule* native_module = script->wasm_native_module(); const i::wasm::WasmModule* module = native_module->module(); DCHECK_LE(0, function_index); DCHECK_GT(module->functions.size(), function_index); const i::wasm::WasmFunction& func = module->functions[function_index]; DCHECK_GE(i::kMaxInt, func.code.offset()); DCHECK_GE(i::kMaxInt, func.code.end_offset()); return std::make_pair(static_cast<int>(func.code.offset()), static_cast<int>(func.code.end_offset())); } int WasmScript::GetContainingFunction(int byte_offset) const { i::DisallowGarbageCollection no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); i::wasm::NativeModule* native_module = script->wasm_native_module(); const i::wasm::WasmModule* module = native_module->module(); DCHECK_LE(0, byte_offset); return i::wasm::GetContainingWasmFunction(module, byte_offset); } uint32_t WasmScript::GetFunctionHash(int function_index) { i::DisallowGarbageCollection no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); i::wasm::NativeModule* native_module = script->wasm_native_module(); const i::wasm::WasmModule* module = native_module->module(); DCHECK_LE(0, function_index); DCHECK_GT(module->functions.size(), function_index); const i::wasm::WasmFunction& func = module->functions[function_index]; i::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes()); base::Vector<const i::byte> function_bytes = wire_bytes.GetFunctionBytes(&func); // TODO(herhut): Maybe also take module, name and signature into account. return i::StringHasher::HashSequentialString(function_bytes.begin(), function_bytes.length(), 0); } int WasmScript::CodeOffset() const { i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); i::wasm::NativeModule* native_module = script->wasm_native_module(); const i::wasm::WasmModule* module = native_module->module(); // If the module contains at least one function, the code offset must have // been initialized, and it cannot be zero. DCHECK_IMPLIES(module->num_declared_functions > 0, module->code.offset() != 0); return module->code.offset(); } #endif // V8_ENABLE_WEBASSEMBLY Location::Location(int line_number, int column_number) : line_number_(line_number), column_number_(column_number), is_empty_(false) {} Location::Location() : line_number_(Function::kLineOffsetNotFound), column_number_(Function::kLineOffsetNotFound), is_empty_(true) {} int Location::GetLineNumber() const { DCHECK(!IsEmpty()); return line_number_; } int Location::GetColumnNumber() const { DCHECK(!IsEmpty()); return column_number_; } bool Location::IsEmpty() const { return is_empty_; } void GetLoadedScripts(Isolate* v8_isolate, PersistentValueVector<Script>& scripts) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); { i::DisallowGarbageCollection no_gc; i::Script::Iterator iterator(isolate); for (i::Script script = iterator.Next(); !script.is_null(); script = iterator.Next()) { #if V8_ENABLE_WEBASSEMBLY if (script.type() != i::Script::TYPE_NORMAL && script.type() != i::Script::TYPE_WASM) { continue; } #else if (script.type() != i::Script::TYPE_NORMAL) continue; #endif // V8_ENABLE_WEBASSEMBLY if (!script.HasValidSource()) continue; i::HandleScope handle_scope(isolate); i::Handle<i::Script> script_handle(script, isolate); scripts.Append(ToApiHandle<Script>(script_handle)); } } } MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* v8_isolate, Local<String> source) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, UnboundScript); i::Handle<i::String> str = Utils::OpenHandle(*source); i::Handle<i::SharedFunctionInfo> result; { i::ScriptData* script_data = nullptr; i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info = i::Compiler::GetSharedFunctionInfoForScript( isolate, str, i::ScriptDetails(), nullptr, script_data, ScriptCompiler::kNoCompileOptions, ScriptCompiler::kNoCacheBecauseInspector, i::FLAG_expose_inspector_scripts ? i::NOT_NATIVES_CODE : i::INSPECTOR_CODE); has_pending_exception = !maybe_function_info.ToHandle(&result); RETURN_ON_FAILED_EXECUTION(UnboundScript); } RETURN_ESCAPED(ToApiHandle<UnboundScript>(result)); } #if V8_ENABLE_WEBASSEMBLY void TierDownAllModulesPerIsolate(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); i::wasm::GetWasmEngine()->TierDownAllModulesPerIsolate(isolate); } void TierUpAllModulesPerIsolate(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); i::wasm::GetWasmEngine()->TierUpAllModulesPerIsolate(isolate); } #endif // V8_ENABLE_WEBASSEMBLY void SetDebugDelegate(Isolate* v8_isolate, DebugDelegate* delegate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); isolate->debug()->SetDebugDelegate(delegate); } void SetAsyncEventDelegate(Isolate* v8_isolate, AsyncEventDelegate* delegate) { reinterpret_cast<i::Isolate*>(v8_isolate)->set_async_event_delegate(delegate); } void ResetBlackboxedStateCache(Isolate* v8_isolate, Local<Script> script) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::DisallowGarbageCollection no_gc; i::SharedFunctionInfo::ScriptIterator iter(isolate, *Utils::OpenHandle(*script)); for (i::SharedFunctionInfo info = iter.Next(); !info.is_null(); info = iter.Next()) { if (info.HasDebugInfo()) { info.GetDebugInfo().set_computed_debug_is_blackboxed(false); } } } int EstimatedValueSize(Isolate* v8_isolate, Local<Value> value) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::Handle<i::Object> object = Utils::OpenHandle(*value); if (object->IsSmi()) return i::kTaggedSize; CHECK(object->IsHeapObject()); return i::Handle<i::HeapObject>::cast(object)->Size(); } void AccessorPair::CheckCast(Value* that) { i::Handle<i::Object> obj = Utils::OpenHandle(that); Utils::ApiCheck(obj->IsAccessorPair(), "v8::debug::AccessorPair::Cast", "Value is not a v8::debug::AccessorPair"); } #if V8_ENABLE_WEBASSEMBLY void WasmValueObject::CheckCast(Value* that) { i::Handle<i::Object> obj = Utils::OpenHandle(that); Utils::ApiCheck(obj->IsWasmValueObject(), "v8::debug::WasmValueObject::Cast", "Value is not a v8::debug::WasmValueObject"); } bool WasmValueObject::IsWasmValueObject(Local<Value> that) { i::Handle<i::Object> obj = Utils::OpenHandle(*that); return obj->IsWasmValueObject(); } Local<String> WasmValueObject::type() const { i::Handle<i::WasmValueObject> object = i::Handle<i::WasmValueObject>::cast(Utils::OpenHandle(this)); i::Isolate* isolate = object->GetIsolate(); i::Handle<i::String> type(object->type(), isolate); return Utils::ToLocal(type); } #endif // V8_ENABLE_WEBASSEMBLY Local<Function> GetBuiltin(Isolate* v8_isolate, Builtin requested_builtin) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope handle_scope(isolate); CHECK_EQ(requested_builtin, kStringToLowerCase); i::Builtin builtin = i::Builtin::kStringPrototypeToLocaleLowerCase; i::Factory* factory = isolate->factory(); i::Handle<i::String> name = isolate->factory()->empty_string(); i::Handle<i::NativeContext> context(isolate->native_context()); i::Handle<i::SharedFunctionInfo> info = factory->NewSharedFunctionInfoForBuiltin(name, builtin); info->set_language_mode(i::LanguageMode::kStrict); i::Handle<i::JSFunction> fun = i::Factory::JSFunctionBuilder{isolate, info, context} .set_map(isolate->strict_function_without_prototype_map()) .Build(); fun->shared().set_internal_formal_parameter_count(0); fun->shared().set_length(0); return Utils::ToLocal(handle_scope.CloseAndEscape(fun)); } void SetConsoleDelegate(Isolate* v8_isolate, ConsoleDelegate* delegate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); isolate->set_console_delegate(delegate); } ConsoleCallArguments::ConsoleCallArguments( const v8::FunctionCallbackInfo<v8::Value>& info) : v8::FunctionCallbackInfo<v8::Value>(nullptr, info.values_, info.length_) { } ConsoleCallArguments::ConsoleCallArguments( const internal::BuiltinArguments& args) : v8::FunctionCallbackInfo<v8::Value>( nullptr, // Drop the first argument (receiver, i.e. the "console" object). args.length() > 1 ? args.address_of_first_argument() : nullptr, args.length() - 1) {} // Marked V8_DEPRECATED. int GetStackFrameId(v8::Local<v8::StackFrame> frame) { return 0; } v8::Local<v8::StackTrace> GetDetailedStackTrace( Isolate* v8_isolate, v8::Local<v8::Object> v8_error) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); i::Handle<i::JSReceiver> error = Utils::OpenHandle(*v8_error); if (!error->IsJSObject()) { return v8::Local<v8::StackTrace>(); } i::Handle<i::FixedArray> stack_trace = isolate->GetDetailedStackTrace(i::Handle<i::JSObject>::cast(error)); return Utils::StackTraceToLocal(stack_trace); } MaybeLocal<Script> GeneratorObject::Script() { i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this); i::Object maybe_script = obj->function().shared().script(); if (!maybe_script.IsScript()) return {}; i::Handle<i::Script> script(i::Script::cast(maybe_script), obj->GetIsolate()); return ToApiHandle<v8::debug::Script>(script); } Local<Function> GeneratorObject::Function() { i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this); return Utils::ToLocal(handle(obj->function(), obj->GetIsolate())); } Location GeneratorObject::SuspendedLocation() { i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this); CHECK(obj->is_suspended()); i::Object maybe_script = obj->function().shared().script(); if (!maybe_script.IsScript()) return Location(); i::Isolate* isolate = obj->GetIsolate(); i::Handle<i::Script> script(i::Script::cast(maybe_script), isolate); i::Script::PositionInfo info; i::SharedFunctionInfo::EnsureSourcePositionsAvailable( isolate, i::handle(obj->function().shared(), isolate)); i::Script::GetPositionInfo(script, obj->source_position(), &info, i::Script::WITH_OFFSET); return Location(info.line, info.column); } bool GeneratorObject::IsSuspended() { return Utils::OpenHandle(this)->is_suspended(); } v8::Local<GeneratorObject> GeneratorObject::Cast(v8::Local<v8::Value> value) { CHECK(value->IsGeneratorObject()); return ToApiHandle<GeneratorObject>(Utils::OpenHandle(*value)); } MaybeLocal<Value> CallFunctionOn(Local<Context> context, Local<Function> function, Local<Value> recv, int argc, Local<Value> argv[], bool throw_on_side_effect) { auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate()); PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, Value); auto self = Utils::OpenHandle(*function); auto recv_obj = Utils::OpenHandle(*recv); STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Handle<i::Object>)); auto args = reinterpret_cast<i::Handle<i::Object>*>(argv); // Disable breaks in side-effect free mode. i::DisableBreak disable_break_scope(isolate->debug(), throw_on_side_effect); if (throw_on_side_effect) { isolate->debug()->StartSideEffectCheckMode(); } Local<Value> result; has_pending_exception = !ToLocal<Value>( i::Execution::Call(isolate, self, recv_obj, argc, args), &result); if (throw_on_side_effect) { isolate->debug()->StopSideEffectCheckMode(); } RETURN_ON_FAILED_EXECUTION(Value); RETURN_ESCAPED(result); } MaybeLocal<v8::Value> EvaluateGlobal(v8::Isolate* isolate, v8::Local<v8::String> source, EvaluateGlobalMode mode, bool repl) { i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(internal_isolate, Value); i::REPLMode repl_mode = repl ? i::REPLMode::kYes : i::REPLMode::kNo; Local<Value> result; has_pending_exception = !ToLocal<Value>( i::DebugEvaluate::Global(internal_isolate, Utils::OpenHandle(*source), mode, repl_mode), &result); RETURN_ON_FAILED_EXECUTION(Value); RETURN_ESCAPED(result); } v8::MaybeLocal<v8::Value> EvaluateGlobalForTesting( v8::Isolate* isolate, v8::Local<v8::Script> function, v8::debug::EvaluateGlobalMode mode, bool repl) { i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(internal_isolate, Value); i::REPLMode repl_mode = repl ? i::REPLMode::kYes : i::REPLMode::kNo; Local<Value> result; has_pending_exception = !ToLocal<Value>( i::DebugEvaluate::Global(internal_isolate, Utils::OpenHandle(*function), mode, repl_mode), &result); RETURN_ON_FAILED_EXECUTION(Value); RETURN_ESCAPED(result); } void QueryObjects(v8::Local<v8::Context> v8_context, QueryObjectPredicate* predicate, PersistentValueVector<v8::Object>* objects) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_context->GetIsolate()); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); isolate->heap_profiler()->QueryObjects(Utils::OpenHandle(*v8_context), predicate, objects); } void GlobalLexicalScopeNames(v8::Local<v8::Context> v8_context, v8::PersistentValueVector<v8::String>* names) { i::Handle<i::Context> context = Utils::OpenHandle(*v8_context); i::Isolate* isolate = context->GetIsolate(); i::Handle<i::ScriptContextTable> table( context->global_object().native_context().script_context_table(), isolate); for (int i = 0; i < table->used(kAcquireLoad); i++) { i::Handle<i::Context> context = i::ScriptContextTable::GetContext(isolate, table, i); DCHECK(context->IsScriptContext()); i::Handle<i::ScopeInfo> scope_info(context->scope_info(), isolate); int local_count = scope_info->ContextLocalCount(); for (int j = 0; j < local_count; ++j) { i::String name = scope_info->ContextLocalName(j); if (i::ScopeInfo::VariableIsSynthetic(name)) continue; names->Append(Utils::ToLocal(handle(name, isolate))); } } } void SetReturnValue(v8::Isolate* v8_isolate, v8::Local<v8::Value> value) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); isolate->debug()->set_return_value(*Utils::OpenHandle(*value)); } int64_t GetNextRandomInt64(v8::Isolate* v8_isolate) { return reinterpret_cast<i::Isolate*>(v8_isolate) ->random_number_generator() ->NextInt64(); } void EnumerateRuntimeCallCounters(v8::Isolate* v8_isolate, RuntimeCallCounterCallback callback) { #ifdef V8_RUNTIME_CALL_STATS i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); if (isolate->counters()) { isolate->counters()->runtime_call_stats()->EnumerateCounters(callback); } #endif // V8_RUNTIME_CALL_STATS } int GetDebuggingId(v8::Local<v8::Function> function) { i::Handle<i::JSReceiver> callable = v8::Utils::OpenHandle(*function); if (!callable->IsJSFunction()) return i::DebugInfo::kNoDebuggingId; i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(callable); int id = func->GetIsolate()->debug()->GetFunctionDebuggingId(func); DCHECK_NE(i::DebugInfo::kNoDebuggingId, id); return id; } bool SetFunctionBreakpoint(v8::Local<v8::Function> function, v8::Local<v8::String> condition, BreakpointId* id) { i::Handle<i::JSReceiver> callable = Utils::OpenHandle(*function); if (!callable->IsJSFunction()) return false; i::Handle<i::JSFunction> jsfunction = i::Handle<i::JSFunction>::cast(callable); i::Isolate* isolate = jsfunction->GetIsolate(); i::Handle<i::String> condition_string = condition.IsEmpty() ? isolate->factory()->empty_string() : Utils::OpenHandle(*condition); return isolate->debug()->SetBreakpointForFunction( handle(jsfunction->shared(), isolate), condition_string, id); } PostponeInterruptsScope::PostponeInterruptsScope(v8::Isolate* isolate) : scope_( new i::PostponeInterruptsScope(reinterpret_cast<i::Isolate*>(isolate), i::StackGuard::API_INTERRUPT)) {} PostponeInterruptsScope::~PostponeInterruptsScope() = default; DisableBreakScope::DisableBreakScope(v8::Isolate* isolate) : scope_(std::make_unique<i::DisableBreak>( reinterpret_cast<i::Isolate*>(isolate)->debug())) {} DisableBreakScope::~DisableBreakScope() = default; int Coverage::BlockData::StartOffset() const { return block_->start; } int Coverage::BlockData::EndOffset() const { return block_->end; } uint32_t Coverage::BlockData::Count() const { return block_->count; } int Coverage::FunctionData::StartOffset() const { return function_->start; } int Coverage::FunctionData::EndOffset() const { return function_->end; } uint32_t Coverage::FunctionData::Count() const { return function_->count; } MaybeLocal<String> Coverage::FunctionData::Name() const { return ToApiHandle<String>(function_->name); } size_t Coverage::FunctionData::BlockCount() const { return function_->blocks.size(); } bool Coverage::FunctionData::HasBlockCoverage() const { return function_->has_block_coverage; } Coverage::BlockData Coverage::FunctionData::GetBlockData(size_t i) const { return BlockData(&function_->blocks.at(i), coverage_); } Local<Script> Coverage::ScriptData::GetScript() const { return ToApiHandle<Script>(script_->script); } size_t Coverage::ScriptData::FunctionCount() const { return script_->functions.size(); } Coverage::FunctionData Coverage::ScriptData::GetFunctionData(size_t i) const { return FunctionData(&script_->functions.at(i), coverage_); } Coverage::ScriptData::ScriptData(size_t index, std::shared_ptr<i::Coverage> coverage) : script_(&coverage->at(index)), coverage_(std::move(coverage)) {} size_t Coverage::ScriptCount() const { return coverage_->size(); } Coverage::ScriptData Coverage::GetScriptData(size_t i) const { return ScriptData(i, coverage_); } Coverage Coverage::CollectPrecise(Isolate* isolate) { return Coverage( i::Coverage::CollectPrecise(reinterpret_cast<i::Isolate*>(isolate))); } Coverage Coverage::CollectBestEffort(Isolate* isolate) { return Coverage( i::Coverage::CollectBestEffort(reinterpret_cast<i::Isolate*>(isolate))); } void Coverage::SelectMode(Isolate* isolate, CoverageMode mode) { i::Coverage::SelectMode(reinterpret_cast<i::Isolate*>(isolate), mode); } int TypeProfile::Entry::SourcePosition() const { return entry_->position; } std::vector<MaybeLocal<String>> TypeProfile::Entry::Types() const { std::vector<MaybeLocal<String>> result; for (const internal::Handle<internal::String>& type : entry_->types) { result.emplace_back(ToApiHandle<String>(type)); } return result; } TypeProfile::ScriptData::ScriptData( size_t index, std::shared_ptr<i::TypeProfile> type_profile) : script_(&type_profile->at(index)), type_profile_(std::move(type_profile)) {} Local<Script> TypeProfile::ScriptData::GetScript() const { return ToApiHandle<Script>(script_->script); } std::vector<TypeProfile::Entry> TypeProfile::ScriptData::Entries() const { std::vector<TypeProfile::Entry> result; for (const internal::TypeProfileEntry& entry : script_->entries) { result.push_back(TypeProfile::Entry(&entry, type_profile_)); } return result; } TypeProfile TypeProfile::Collect(Isolate* isolate) { return TypeProfile( i::TypeProfile::Collect(reinterpret_cast<i::Isolate*>(isolate))); } void TypeProfile::SelectMode(Isolate* isolate, TypeProfileMode mode) { i::TypeProfile::SelectMode(reinterpret_cast<i::Isolate*>(isolate), mode); } size_t TypeProfile::ScriptCount() const { return type_profile_->size(); } TypeProfile::ScriptData TypeProfile::GetScriptData(size_t i) const { return ScriptData(i, type_profile_); } v8::MaybeLocal<v8::Value> WeakMap::Get(v8::Local<v8::Context> context, v8::Local<v8::Value> key) { PREPARE_FOR_EXECUTION(context, WeakMap, Get, Value); auto self = Utils::OpenHandle(this); Local<Value> result; i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)}; has_pending_exception = !ToLocal<Value>(i::Execution::CallBuiltin(isolate, isolate->weakmap_get(), self, arraysize(argv), argv), &result); RETURN_ON_FAILED_EXECUTION(Value); RETURN_ESCAPED(result); } v8::Maybe<bool> WeakMap::Delete(v8::Local<v8::Context> context, v8::Local<v8::Value> key) { PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, WeakMap, Delete, Nothing<bool>(), InternalEscapableScope, false); auto self = Utils::OpenHandle(this); Local<Value> result; i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)}; has_pending_exception = !ToLocal<Value>( i::Execution::CallBuiltin(isolate, isolate->weakmap_delete(), self, arraysize(argv), argv), &result); RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); return Just(result->IsTrue()); } v8::MaybeLocal<WeakMap> WeakMap::Set(v8::Local<v8::Context> context, v8::Local<v8::Value> key, v8::Local<v8::Value> value) { PREPARE_FOR_EXECUTION(context, WeakMap, Set, WeakMap); auto self = Utils::OpenHandle(this); i::Handle<i::Object> result; i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key), Utils::OpenHandle(*value)}; has_pending_exception = !i::Execution::CallBuiltin(isolate, isolate->weakmap_set(), self, arraysize(argv), argv) .ToHandle(&result); RETURN_ON_FAILED_EXECUTION(WeakMap); RETURN_ESCAPED(Local<WeakMap>::Cast(Utils::ToLocal(result))); } Local<WeakMap> WeakMap::New(v8::Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, WeakMap, New); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::JSWeakMap> obj = i_isolate->factory()->NewJSWeakMap(); return ToApiHandle<WeakMap>(obj); } WeakMap* WeakMap::Cast(v8::Value* value) { return static_cast<WeakMap*>(value); } Local<Value> AccessorPair::getter() { i::Handle<i::AccessorPair> accessors = Utils::OpenHandle(this); i::Isolate* isolate = accessors->GetIsolate(); i::Handle<i::Object> getter(accessors->getter(), isolate); return Utils::ToLocal(getter); } Local<Value> AccessorPair::setter() { i::Handle<i::AccessorPair> accessors = Utils::OpenHandle(this); i::Isolate* isolate = accessors->GetIsolate(); i::Handle<i::Object> setter(accessors->setter(), isolate); return Utils::ToLocal(setter); } bool AccessorPair::IsAccessorPair(Local<Value> that) { i::Handle<i::Object> obj = Utils::OpenHandle(*that); return obj->IsAccessorPair(); } MaybeLocal<Message> GetMessageFromPromise(Local<Promise> p) { i::Handle<i::JSPromise> promise = Utils::OpenHandle(*p); i::Isolate* isolate = promise->GetIsolate(); i::Handle<i::Symbol> key = isolate->factory()->promise_debug_message_symbol(); i::Handle<i::Object> maybeMessage = i::JSReceiver::GetDataProperty(promise, key); if (!maybeMessage->IsJSMessageObject(isolate)) return MaybeLocal<Message>(); return ToApiHandle<Message>( i::Handle<i::JSMessageObject>::cast(maybeMessage)); } std::unique_ptr<PropertyIterator> PropertyIterator::Create( Local<Context> context, Local<Object> object) { internal::Isolate* isolate = reinterpret_cast<i::Isolate*>(object->GetIsolate()); if (IsExecutionTerminatingCheck(isolate)) { return nullptr; } CallDepthScope<false> call_depth_scope(isolate, context); auto result = i::DebugPropertyIterator::Create(isolate, Utils::OpenHandle(*object)); if (!result) { DCHECK(isolate->has_pending_exception()); call_depth_scope.Escape(); } return result; } } // namespace debug namespace internal { Maybe<bool> DebugPropertyIterator::Advance() { if (IsExecutionTerminatingCheck(isolate_)) { return Nothing<bool>(); } Local<v8::Context> context = Utils::ToLocal(handle(isolate_->context(), isolate_)); CallDepthScope<false> call_depth_scope(isolate_, context); if (!AdvanceInternal()) { DCHECK(isolate_->has_pending_exception()); call_depth_scope.Escape(); return Nothing<bool>(); } return Just(true); } } // namespace internal } // namespace v8 #include "src/api/api-macros-undef.h"