Files
Robo 07a3f54605 build: enable dangling raw_ptr checks (#54619)
* fix: clear vibrancy view before destruction

Keep the removed NativeViewHost alive until vibrant_native_view_host_ has been cleared.

Memory was freed at:

0 Electron Framework 0x000000012b8e4940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012b8cfa00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x000000012b8ea86c base::allocator::(anonymous namespace)::DanglingRawPtrDetected(unsigned long) + 764
3 Electron Framework 0x000000012b996bcc void partition_alloc::PartitionRoot::FreeInline<(partition_alloc::internal::FreeFlags)8>(void*) + 5392
4 Electron Framework 0x00000001335fe8f4 views::NativeViewHost::~NativeViewHost() + 16
5 Electron Framework 0x0000000124916004 ___ZN8electron15NativeWindowMac11SetVibrancyERKNSt4__Cr12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEi_block_invoke + 140
6 Electron Framework 0x0000000124915a74 electron::NativeWindowMac::SetVibrancy(std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>> const&, int) + 1048

The dangling raw_ptr was released at:

0 Electron Framework 0x000000012b8e4940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012b8cfa00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x000000012b8eb158 void base::allocator::(anonymous namespace)::DanglingRawPtrReleased<(base::features::DanglingPtrMode)1, (base::features::DanglingPtrType)0>(unsigned long) + 92
3 Electron Framework 0x000000012b93c3b4 base::internal::RawPtrBackupRefImpl<false>::ReleaseInternal(unsigned long) + 480
4 Electron Framework 0x0000000124916058 ___ZN8electron15NativeWindowMac11SetVibrancyERKNSt4__Cr12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEi_block_invoke + 224
5 Electron Framework 0x0000000124915a74 electron::NativeWindowMac::SetVibrancy(std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>> const&, int) + 1048

* fix: clear notification delegate before callback

Release delegate_ before NotificationDestroyed() can synchronously delete the delegate.

Memory was freed at:

0 Electron Framework 0x000000012b8e4940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012b8cfa00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x000000012b8ea86c base::allocator::(anonymous namespace)::DanglingRawPtrDetected(unsigned long) + 764
3 Electron Framework 0x000000012b9aa080 void partition_alloc::PartitionRoot::FreeInline<(partition_alloc::internal::FreeFlags)22>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)22)>::Type) + 5928
4 Electron Framework 0x000000012b99f940 void partition_alloc::PartitionRoot::FreeInUnknownRoot<(partition_alloc::internal::FreeFlags)22>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)22)>::Type) + 1324
5 Electron Framework 0x000000012b9c3a50 allocator_shim::internal::PartitionAllocFunctionsInternal<(partition_alloc::internal::AllocFlags)16, (partition_alloc::internal::FreeFlags)6>::FreeWithSize(void*, unsigned long, void*) + 200
6 Electron Framework 0x00000001247f797c electron::Notification::~Notification() + 72
7 Electron Framework 0x0000000124919fbc electron::CocoaNotification::~CocoaNotification() + 220
8 Electron Framework 0x000000012491a014 electron::CocoaNotification::~CocoaNotification() + 12
9 Electron Framework 0x00000001247f81cc electron::NotificationPresenter::RemoveNotification(electron::Notification*) + 200

The dangling raw_ptr was released at:

0 Electron Framework 0x000000012b8e4940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012b8cfa00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x000000012b8eb158 void base::allocator::(anonymous namespace)::DanglingRawPtrReleased<(base::features::DanglingPtrMode)1, (base::features::DanglingPtrType)0>(unsigned long) + 92
3 Electron Framework 0x000000012b93c3b4 base::internal::RawPtrBackupRefImpl<false>::ReleaseInternal(unsigned long) + 480
4 Electron Framework 0x00000001247f7a50 electron::Notification::~Notification() + 284
5 Electron Framework 0x0000000124919fbc electron::CocoaNotification::~CocoaNotification() + 220
6 Electron Framework 0x000000012491a014 electron::CocoaNotification::~CocoaNotification() + 12
7 Electron Framework 0x00000001247f81cc electron::NotificationPresenter::RemoveNotification(electron::Notification*) + 200

* fix: erase notifications before destruction

Remove each raw_ptr from notifications_ before deleting the Notification it references.

Memory was freed at:

0 Electron Framework 0x000000012cacd6e0 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012cab6968 base::debug::StackTrace::StackTrace(unsigned long) + 168
2 Electron Framework 0x000000012cad3a24 base::allocator::(anonymous namespace)::DanglingRawPtrDetected(unsigned long) + 764
3 Electron Framework 0x000000012cbbb9ac void partition_alloc::PartitionRoot::FreeInline<(partition_alloc::internal::FreeFlags)22>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)22)>::Type) + 5868
4 Electron Framework 0x000000012cbb1264 void partition_alloc::PartitionRoot::FreeInUnknownRoot<(partition_alloc::internal::FreeFlags)22>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)22)>::Type) + 1324
5 Electron Framework 0x000000012cbd522c allocator_shim::internal::PartitionAllocFunctionsInternal<(partition_alloc::internal::AllocFlags)16, (partition_alloc::internal::FreeFlags)6>::FreeWithSize(void*, unsigned long, void*) + 200
6 Electron Framework 0x00000001258ed394 electron::NotificationPresenter::~NotificationPresenter() + 72
7 Electron Framework 0x0000000125a0ee60 electron::NotificationPresenterMac::~NotificationPresenterMac() + 356
8 Electron Framework 0x0000000125a0ef00 electron::NotificationPresenterMac::~NotificationPresenterMac() + 12
9 Electron Framework 0x0000000125868dfc electron::ElectronBrowserClient::~ElectronBrowserClient() + 500

The dangling raw_ptr was released at:

0 Electron Framework 0x000000012cacd6e0 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012cab6968 base::debug::StackTrace::StackTrace(unsigned long) + 168
2 Electron Framework 0x000000012cad3aec void base::allocator::(anonymous namespace)::DanglingRawPtrReleased<(base::features::DanglingPtrMode)0, (base::features::DanglingPtrType)0>(unsigned long) + 84
3 Electron Framework 0x000000012cb27fc8 base::internal::RawPtrBackupRefImpl<false>::ReleaseInternal(unsigned long) + 480
4 Electron Framework 0x00000001258b87c8 void std::__Cr::__destroy_at[abi:sqn240000]<base::raw_ptr<DraggableRegionProvider, (partition_alloc::internal::RawPtrTraits)0>>(base::raw_ptr<DraggableRegionProvider, (partition_alloc::internal::RawPtrTraits)0>*) + 136
5 Electron Framework 0x00000001258eda14 std::__Cr::__tree<base::raw_ptr<electron::Notification, (partition_alloc::internal::RawPtrTraits)0>, std::__Cr::less<base::raw_ptr<electron::Notification, (partition_alloc::internal::RawPtrTraits)0>>, std::__Cr::allocator<base::raw_ptr<electron::Notification, (partition_alloc::internal::RawPtrTraits)0>>>::__tree_deleter::operator()[abi:sqn240000](std::__Cr::__tree_node<base::raw_ptr<electron::Notification, (partition_alloc::internal::RawPtrTraits)0>, void*>*) + 52
6 Electron Framework 0x00000001258ed3d4 electron::NotificationPresenter::~NotificationPresenter() + 136
7 Electron Framework 0x0000000125a0ee60 electron::NotificationPresenterMac::~NotificationPresenterMac() + 356
8 Electron Framework 0x0000000125a0ef00 electron::NotificationPresenterMac::~NotificationPresenterMac() + 12
9 Electron Framework 0x0000000125868dfc electron::ElectronBrowserClient::~ElectronBrowserClient() + 500

* fix: clear Node environment before teardown

Clear NodeBindings::uv_env_ before NodeService releases the node::Environment.

Memory was freed at:

0 Electron Framework 0x0000000129b78940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x0000000129b63a00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x0000000129b7e86c base::allocator::(anonymous namespace)::DanglingRawPtrDetected(unsigned long) + 764
3 Electron Framework 0x0000000129c3c93c void partition_alloc::PartitionRoot::FreeInline<(partition_alloc::internal::FreeFlags)18>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)18)>::Type) + 8480
4 Electron Framework 0x0000000129c33390 void partition_alloc::PartitionRoot::FreeInUnknownRoot<(partition_alloc::internal::FreeFlags)18>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)18)>::Type) + 1324
5 Electron Framework 0x0000000129c56ce8 allocator_shim::internal::PartitionAllocFunctionsInternal<(partition_alloc::internal::AllocFlags)16, (partition_alloc::internal::FreeFlags)2>::FreeWithSize(void*, unsigned long, void*) + 200
6 Electron Framework 0x0000000122c4bd24 node::FreeEnvironment(node::Environment*) + 248
7 Electron Framework 0x0000000122b3a74c _ZNSt4__Cr20__shared_ptr_pointerB9sqn240000IPN4node11EnvironmentEZN8electron12NodeBindings17CreateEnvironmentEPN2v87IsolateENS6_5LocalINS6_7ContextEEEPNS1_20MultiIsolatePlatformEmNS_6vectorINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEENSI_ISK_EEEESM_NS_8optionalIN4base17RepeatingCallbackIFvvEEEEEE3$_0NSI_IS2_EEE16__on_zero_sharedEv + 188
8 Electron Framework 0x0000000122b7ee40 electron::NodeService::~NodeService() + 416
9 Electron Framework 0x0000000122b7ef2c electron::NodeService::~NodeService() + 12

The dangling raw_ptr was released at:

0 Electron Framework 0x0000000129b78940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x0000000129b63a00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x0000000129b7e934 void base::allocator::(anonymous namespace)::DanglingRawPtrReleased<(base::features::DanglingPtrMode)0, (base::features::DanglingPtrType)0>(unsigned long) + 84
3 Electron Framework 0x0000000129bd03b4 base::internal::RawPtrBackupRefImpl<false>::ReleaseInternal(unsigned long) + 480
4 Electron Framework 0x0000000122b34b94 electron::NodeBindings::~NodeBindings() + 372
5 Electron Framework 0x0000000122bde08c electron::NodeBindingsMac::~NodeBindingsMac() + 12
6 Electron Framework 0x0000000122b7edf8 electron::NodeService::~NodeService() + 344
7 Electron Framework 0x0000000122b7ef2c electron::NodeService::~NodeService() + 12

* fix: enable dangling raw_ptr checks

* fix: avoid retaining isolate in PromiseBase

Resolve PromiseHandle traced references with the currently entered
isolate instead of retaining a raw pointer that can outlive
IsolateHolder. Promise operations already require execution on their
creation thread with the isolate entered.

```
gin::IsolateHolder::~IsolateHolder -> JavascriptEnvironment::~JavascriptEnvironment -> isolate free

static Promise<void> destruction -> PromiseBase::~PromiseBase -> isolate_ raw_ptr release
```

* fix: annotate additional dangling raw pointers

* fix(win): annotate additional dangling raw_ptr
2026-10-04 14:30:39 -05:00

314 lines
12 KiB
C++

// Copyright (c) 2022 Microsoft, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/services/node/node_service.h"
#include <memory>
#include <sstream>
#include <utility>
#include "base/command_line.h"
#include "base/no_destructor.h"
#include "base/strings/utf_string_conversions.h"
#include "electron/buildflags/buildflags.h"
#include "electron/fuses.h"
#include "electron/mas.h"
#include "net/base/network_change_notifier.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/host_resolver.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "shell/browser/javascript_environment.h"
#include "shell/common/api/electron_bindings.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/node_bindings.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
#include "shell/services/node/parent_port.h"
#if !IS_MAS_BUILD()
#include "shell/common/crash_keys.h"
#endif
#if BUILDFLAG(ENABLE_PROMPT_API)
#include "shell/common/gin_helper/event_emitter_caller.h"
#include "shell/utility/ai/utility_ai_manager.h"
#include "shell/utility/api/electron_api_local_ai_handler.h"
#include "url/gurl.h"
#include "url/origin.h"
#endif // BUILDFLAG(ENABLE_PROMPT_API)
namespace electron {
mojo::Remote<node::mojom::NodeServiceClient>& GetRemote() {
static base::NoDestructor<mojo::Remote<node::mojom::NodeServiceClient>>
instance;
return *instance;
}
void V8FatalErrorCallback(const char* location, const char* message) {
if (GetRemote().is_bound() && GetRemote().is_connected()) {
auto* isolate = v8::Isolate::TryGetCurrent();
std::ostringstream outstream;
node::GetNodeReport(isolate, message, location,
v8::Local<v8::Object>() /* error */, outstream);
GetRemote()->OnV8FatalError(location, outstream.str());
}
#if !IS_MAS_BUILD()
electron::crash_keys::SetCrashKey("electron.v8-fatal.message", message);
electron::crash_keys::SetCrashKey("electron.v8-fatal.location", location);
#endif
volatile int* zero = nullptr;
*zero = 0; // NOLINT(clang-analyzer-core.NullDereference)
}
URLLoaderBundle::URLLoaderBundle() = default;
URLLoaderBundle::~URLLoaderBundle() = default;
URLLoaderBundle* URLLoaderBundle::GetInstance() {
static base::NoDestructor<URLLoaderBundle> instance;
return instance.get();
}
void URLLoaderBundle::SetURLLoaderFactory(
mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_factory,
mojo::Remote<network::mojom::HostResolver> host_resolver,
bool use_network_observer_from_url_loader_factory) {
factory_ = network::SharedURLLoaderFactory::Create(
std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
std::move(pending_factory)));
host_resolver_ = std::move(host_resolver);
should_use_network_observer_from_url_loader_factory_ =
use_network_observer_from_url_loader_factory;
}
scoped_refptr<network::SharedURLLoaderFactory>
URLLoaderBundle::GetSharedURLLoaderFactory() {
return factory_;
}
network::mojom::HostResolver* URLLoaderBundle::GetHostResolver() {
DCHECK(host_resolver_);
return host_resolver_.get();
}
bool URLLoaderBundle::ShouldUseNetworkObserverfromURLLoaderFactory() const {
return should_use_network_observer_from_url_loader_factory_;
}
NodeService::NodeService(
mojo::PendingReceiver<node::mojom::NodeService> receiver)
: node_bindings_{
NodeBindings::Create(NodeBindings::BrowserEnvironment::kUtility,
uv_default_loop())},
electron_bindings_{
std::make_unique<ElectronBindings>(node_bindings_->uv_loop())} {
if (receiver.is_valid())
receiver_.Bind(std::move(receiver));
}
NodeService::~NodeService() {
#if BUILDFLAG(ENABLE_PROMPT_API)
electron::api::local_ai_handler::SetHandlerChangedCallback({});
// Tear down the AI receivers while the isolate is still alive; their
// destructors call into V8.
ai_managers_.Clear();
#endif
if (!node_env_stopped_) {
node_env_->set_trace_sync_io(false);
ParentPort::GetInstance()->Close();
js_env_->DestroyMicrotasksRunner();
node::Stop(node_env_.get(), node::StopFlags::kDoNotTerminateIsolate);
GetRemote().reset();
}
node_bindings_->set_uv_env(nullptr);
}
void NodeService::Initialize(
node::mojom::NodeServiceParamsPtr params,
mojo::PendingRemote<node::mojom::NodeServiceClient> client_pending_remote) {
if (NodeBindings::IsInitialized())
return;
GetRemote().Bind(std::move(client_pending_remote));
GetRemote().reset_on_disconnect();
if (params->url_loader_factory_params) {
UpdateURLLoaderFactory(std::move(params->url_loader_factory_params));
}
// Enable trap handlers before creating the V8 isolate. V8 initialization
// calls IsTrapHandlerEnabled() which prevents later EnableTrapHandler calls.
#if ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)) && \
defined(ARCH_CPU_X86_64)) || \
((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)) && defined(ARCH_CPU_ARM64))
if (electron::fuses::IsWasmTrapHandlersEnabled()) {
electron::SetUpWebAssemblyTrapHandler();
}
#endif
js_env_.emplace(node_bindings_->uv_loop());
v8::Isolate* const isolate = js_env_->isolate();
v8::HandleScope scope{isolate};
// Empty when the isolate was created from the embedded Node startup
// snapshot: the main context is then materialized (with the whole
// bootstrapped environment) inside CreateEnvironment and entered below --
// the same path the browser process takes.
const v8::Local<v8::Context> context = isolate->GetCurrentContext();
node_bindings_->Initialize(isolate, context);
// ParentPort is a cppgc-managed wrappable, so it must be created after the
// V8 isolate (and its cppgc heap) exists. The connector is created paused and
// is not resumed until the entry script calls parentPort.start() during
// LoadEnvironment below, so binding the port here changes no observable
// behavior.
ParentPort::GetInstance()->Initialize(std::move(params->port));
network_change_notifier_ = net::NetworkChangeNotifier::CreateIfNeeded(
net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
net::NetworkChangeNotifier::ConnectionSubtype::SUBTYPE_UNKNOWN);
// Append program path for process.argv0
auto program = base::CommandLine::ForCurrentProcess()->GetProgram();
#if defined(OS_WIN)
params->args.insert(params->args.begin(), base::WideToUTF8(program.value()));
#else
params->args.insert(params->args.begin(), program.value());
#endif
// Create the global environment.
node_env_ = node_bindings_->CreateEnvironment(
isolate, context, js_env_->platform(),
js_env_->max_young_generation_size_in_bytes(), params->args,
params->exec_args);
if (context.IsEmpty())
node_env_->context()->Enter();
node_bindings_->SetUpIsolate(isolate);
// Override the default handler set by NodeBindings.
node_env_->isolate()->SetFatalErrorHandler(V8FatalErrorCallback);
node::SetProcessExitHandler(
node_env_.get(), [this](node::Environment* env, int exit_code) {
// Destroy node platform.
node_env_stopped_ = true;
ParentPort::GetInstance()->Close();
js_env_->DestroyMicrotasksRunner();
GetRemote().reset();
receiver_.ResetWithReason(exit_code, "process_exit_termination");
node::DefaultProcessExitHandler(env, exit_code);
});
node_env_->set_trace_sync_io(node_env_->options()->trace_sync_io);
// We do not want to crash the utility process on unhandled rejections.
node_env_->options()->unhandled_rejections = "warn-with-error-code";
// Add Electron extended APIs.
electron_bindings_->BindTo(node_env_->isolate(), node_env_->process_object());
// Add entry script to process object.
gin_helper::Dictionary process(node_env_->isolate(),
node_env_->process_object());
process.SetHidden("_serviceStartupScript", params->script);
// Setup microtask runner.
js_env_->CreateMicrotasksRunner();
// Wrap the uv loop with global env.
node_bindings_->set_uv_env(node_env_.get());
// LoadEnvironment should be called after setting up
// JavaScriptEnvironment including the microtask runner
// since this call will start compilation and execution
// of the entry script. If there is an uncaught exception
// the exit handler set above will be triggered and it expects
// both Node Env and JavaScriptEnvironment are setup to perform
// a clean shutdown of this process.
node_bindings_->LoadEnvironment(node_env_.get());
// Run entry script.
node_bindings_->PrepareEmbedThread();
node_bindings_->StartPolling();
}
void NodeService::UpdateURLLoaderFactory(
node::mojom::URLLoaderFactoryParamsPtr params) {
URLLoaderBundle::GetInstance()->SetURLLoaderFactory(
std::move(params->url_loader_factory),
mojo::Remote(std::move(params->host_resolver)),
params->use_network_observer_from_url_loader_factory);
}
#if BUILDFLAG(ENABLE_PROMPT_API)
NodeService::PendingAIManagerBinding::PendingAIManagerBinding(
node::mojom::BindAIManagerParamsPtr params,
mojo::PendingReceiver<blink::mojom::AIManager> receiver)
: params(std::move(params)), receiver(std::move(receiver)) {}
NodeService::PendingAIManagerBinding::~PendingAIManagerBinding() = default;
NodeService::PendingAIManagerBinding::PendingAIManagerBinding(
PendingAIManagerBinding&&) = default;
NodeService::PendingAIManagerBinding&
NodeService::PendingAIManagerBinding::operator=(PendingAIManagerBinding&&) =
default;
void NodeService::BindAIManager(
node::mojom::BindAIManagerParamsPtr params,
mojo::PendingReceiver<blink::mojom::AIManager> ai_manager) {
auto& handler = electron::api::local_ai_handler::GetPromptAPIHandler();
if (!handler.has_value()) {
// No handler set yet — register for notification on first pending binding.
if (pending_ai_manager_bindings_.empty()) {
electron::api::local_ai_handler::SetHandlerChangedCallback(
base::BindRepeating(&NodeService::FlushPendingAIManagerBindings,
base::Unretained(this)));
}
if (pending_ai_manager_bindings_.size() >= kMaxPendingAIManagerBindings) {
pending_ai_manager_bindings_.front().receiver.reset();
pending_ai_manager_bindings_.pop_front();
}
pending_ai_manager_bindings_.emplace_back(std::move(params),
std::move(ai_manager));
{
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope scope{isolate};
v8::Global<v8::Object>& module_object =
electron::api::local_ai_handler::GetModuleObject();
if (!module_object.IsEmpty()) {
gin_helper::EmitEvent(isolate, module_object.Get(isolate),
"-pending-bind-ai-manager");
}
}
return;
}
ai_managers_.Add(std::make_unique<UtilityAIManager>(
params->web_contents_id, params->security_origin,
params->frame_token, params->render_process_id),
std::move(ai_manager));
}
void NodeService::FlushPendingAIManagerBindings() {
auto pending = std::move(pending_ai_manager_bindings_);
for (auto& binding : pending) {
ai_managers_.Add(
std::make_unique<UtilityAIManager>(
binding.params->web_contents_id, binding.params->security_origin,
binding.params->frame_token, binding.params->render_process_id),
std::move(binding.receiver));
}
}
#endif // BUILDFLAG(ENABLE_PROMPT_API)
} // namespace electron