Skip to content

Commit 127b87a

Browse files
committed
apply pr suggestions
1 parent 80bbdc7 commit 127b87a

File tree

6 files changed

+113
-37
lines changed

6 files changed

+113
-37
lines changed

lib/diagnostics_channel.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,10 +446,7 @@ function tracingChannel(nameOrChannels) {
446446
return new TracingChannel(nameOrChannels);
447447
}
448448

449-
dc_binding.setPublishCallback((name, message) => {
450-
const ch = channels.get(name);
451-
if (ch) ch.publish(message);
452-
});
449+
dc_binding.linkNativeChannel((name) => channel(name));
453450

454451
module.exports = {
455452
channel,

lib/internal/process/pre_execution.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -622,17 +622,11 @@ function initializeClusterIPC() {
622622
}
623623

624624
function setupDiagnosticsChannel() {
625-
// The C++ Channel::Publish() API needs a JS callback to dispatch
626-
// messages. This callback is stored in BindingData but cleared during
627-
// snapshot serialization. Since lib/diagnostics_channel.js module body
628-
// may not re-run after snapshot deserialization, we must explicitly
629-
// re-register it here.
625+
// Re-link native channels after snapshot deserialization since
626+
// JS references are cleared during serialization.
630627
const dc = require('diagnostics_channel');
631628
const dc_binding = internalBinding('diagnostics_channel');
632-
dc_binding.setPublishCallback((name, message) => {
633-
const ch = dc.channel(name);
634-
if (ch.hasSubscribers) ch.publish(message);
635-
});
629+
dc_binding.linkNativeChannel((name) => dc.channel(name));
636630
}
637631

638632
function initializePermission() {

src/node_diagnostics_channel.cc

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace node {
1111
namespace diagnostics_channel {
1212

1313
using v8::Context;
14+
using v8::Function;
1415
using v8::FunctionCallbackInfo;
1516
using v8::HandleScope;
1617
using v8::Isolate;
@@ -66,22 +67,49 @@ void BindingData::GetOrCreateChannelIndex(
6667
args.GetReturnValue().Set(index);
6768
}
6869

69-
void BindingData::SetPublishCallback(const FunctionCallbackInfo<Value>& args) {
70+
void BindingData::LinkNativeChannel(const FunctionCallbackInfo<Value>& args) {
7071
Realm* realm = Realm::GetCurrent(args);
7172
BindingData* binding = realm->GetBindingData<BindingData>();
7273
CHECK_NOT_NULL(binding);
7374

7475
CHECK(args[0]->IsFunction());
75-
binding->publish_callback_.Reset(realm->isolate(),
76-
args[0].As<v8::Function>());
76+
Isolate* isolate = realm->isolate();
77+
Local<Context> context = realm->context();
78+
binding->link_callback_.Reset(isolate, args[0].As<Function>());
79+
80+
// Resolve channels created before the link callback was available.
81+
for (uint32_t index : binding->pending_channels_) {
82+
for (const auto& pair : binding->channel_indices_) {
83+
if (pair.second == index) {
84+
Local<String> name =
85+
String::NewFromUtf8(isolate, pair.first.c_str()).ToLocalChecked();
86+
Local<Value> argv[] = {name};
87+
Local<Value> result;
88+
if (binding->link_callback_.Get(isolate)
89+
->Call(context, v8::Undefined(isolate), 1, argv)
90+
.ToLocal(&result) &&
91+
result->IsObject()) {
92+
if (index >= binding->js_channels_.size()) {
93+
binding->js_channels_.resize(index + 1);
94+
}
95+
binding->js_channels_[index].Reset(isolate, result.As<Object>());
96+
}
97+
break;
98+
}
99+
}
100+
}
101+
binding->pending_channels_.clear();
77102
}
78103

79104
bool BindingData::PrepareForSerialization(Local<Context> context,
80105
SnapshotCreator* creator) {
81106
DCHECK_NULL(internal_field_info_);
82107
internal_field_info_ = InternalFieldInfoBase::New<InternalFieldInfo>(type());
83108
internal_field_info_->subscribers = subscribers_.Serialize(context, creator);
84-
publish_callback_.Reset();
109+
link_callback_.Reset();
110+
for (auto& global : js_channels_) {
111+
global.Reset();
112+
}
85113
return true;
86114
}
87115

@@ -109,7 +137,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
109137
Isolate* isolate = isolate_data->isolate();
110138
SetMethod(
111139
isolate, target, "getOrCreateChannelIndex", GetOrCreateChannelIndex);
112-
SetMethod(isolate, target, "setPublishCallback", SetPublishCallback);
140+
SetMethod(isolate, target, "linkNativeChannel", LinkNativeChannel);
113141
}
114142

115143
void BindingData::CreatePerContextProperties(Local<Object> target,
@@ -124,38 +152,72 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
124152
void BindingData::RegisterExternalReferences(
125153
ExternalReferenceRegistry* registry) {
126154
registry->Register(GetOrCreateChannelIndex);
127-
registry->Register(SetPublishCallback);
155+
registry->Register(LinkNativeChannel);
128156
}
129157

130-
Channel::Channel(BindingData* binding_data, uint32_t index, const char* name)
131-
: binding_data_(binding_data), index_(index), name_(name) {}
158+
Channel::Channel(BindingData* binding_data, uint32_t index)
159+
: binding_data_(binding_data), index_(index) {}
132160

133161
Channel Channel::Get(Environment* env, const char* name) {
134162
Realm* realm = env->principal_realm();
135163
BindingData* binding = realm->GetBindingData<BindingData>();
136164
if (binding == nullptr) {
137-
return Channel(nullptr, 0, name);
165+
return Channel(nullptr, 0);
138166
}
139167
uint32_t index = binding->GetOrCreateChannelIndex(std::string(name));
140-
return Channel(binding, index, name);
168+
169+
if (!binding->link_callback_.IsEmpty()) {
170+
if (index >= binding->js_channels_.size()) {
171+
binding->js_channels_.resize(index + 1);
172+
}
173+
if (binding->js_channels_[index].IsEmpty()) {
174+
Isolate* isolate = env->isolate();
175+
HandleScope handle_scope(isolate);
176+
Local<Context> context = env->context();
177+
Local<String> js_name =
178+
String::NewFromUtf8(isolate, name).ToLocalChecked();
179+
Local<Value> argv[] = {js_name};
180+
Local<Value> result;
181+
if (binding->link_callback_.Get(isolate)
182+
->Call(context, v8::Undefined(isolate), 1, argv)
183+
.ToLocal(&result) &&
184+
result->IsObject()) {
185+
binding->js_channels_[index].Reset(isolate, result.As<Object>());
186+
}
187+
}
188+
} else {
189+
binding->pending_channels_.push_back(index);
190+
}
191+
192+
return Channel(binding, index);
141193
}
142194

143195
void Channel::Publish(Environment* env, Local<Value> message) const {
144196
if (!HasSubscribers()) return;
145197

198+
if (binding_data_ == nullptr) return;
199+
146200
Isolate* isolate = env->isolate();
147201
HandleScope handle_scope(isolate);
148202
Local<Context> context = env->context();
149203
Context::Scope context_scope(context);
150204

151-
if (binding_data_->publish_callback_.IsEmpty()) return;
205+
if (index_ >= binding_data_->js_channels_.size() ||
206+
binding_data_->js_channels_[index_].IsEmpty()) {
207+
return;
208+
}
152209

153-
Local<v8::Function> callback = binding_data_->publish_callback_.Get(isolate);
154-
Local<String> channel_name =
155-
String::NewFromUtf8(isolate, name_).ToLocalChecked();
210+
Local<Object> js_channel =
211+
binding_data_->js_channels_[index_].Get(isolate);
212+
Local<Value> publish_val;
213+
if (!js_channel->Get(context, FIXED_ONE_BYTE_STRING(isolate, "publish"))
214+
.ToLocal(&publish_val) ||
215+
!publish_val->IsFunction()) {
216+
return;
217+
}
156218

157-
Local<Value> argv[] = {channel_name, message};
158-
USE(callback->Call(context, v8::Undefined(isolate), 2, argv));
219+
Local<Value> argv[] = {message};
220+
USE(publish_val.As<Function>()->Call(context, js_channel, 1, argv));
159221
}
160222

161223
} // namespace diagnostics_channel

src/node_diagnostics_channel.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <cinttypes>
77
#include <string>
88
#include <unordered_map>
9+
#include <vector>
910
#include "aliased_buffer.h"
1011
#include "node_snapshotable.h"
1112

@@ -42,11 +43,13 @@ class BindingData : public SnapshotableObject {
4243

4344
uint32_t GetOrCreateChannelIndex(const std::string& name);
4445

45-
v8::Global<v8::Function> publish_callback_;
46+
v8::Global<v8::Function> link_callback_;
47+
std::vector<v8::Global<v8::Object>> js_channels_;
48+
std::vector<uint32_t> pending_channels_;
4649

4750
static void GetOrCreateChannelIndex(
4851
const v8::FunctionCallbackInfo<v8::Value>& args);
49-
static void SetPublishCallback(
52+
static void LinkNativeChannel(
5053
const v8::FunctionCallbackInfo<v8::Value>& args);
5154

5255
static void CreatePerIsolateProperties(IsolateData* isolate_data,
@@ -72,11 +75,12 @@ class Channel {
7275
void Publish(Environment* env, v8::Local<v8::Value> message) const;
7376

7477
private:
75-
Channel(BindingData* binding_data, uint32_t index, const char* name);
78+
friend class BindingData;
79+
80+
Channel(BindingData* binding_data, uint32_t index);
7681

7782
BindingData* binding_data_;
7883
uint32_t index_;
79-
const char* name_;
8084
};
8185

8286
} // namespace diagnostics_channel

src/permission/permission.cc

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace permission {
2828

2929
namespace {
3030

31-
const char* GetDiagnosticsChannelName(PermissionScope scope) {
31+
constexpr std::string_view GetDiagnosticsChannelName(PermissionScope scope) {
3232
switch (scope) {
3333
case PermissionScope::kFileSystem:
3434
case PermissionScope::kFileSystemRead:
@@ -215,16 +215,16 @@ bool Permission::is_scope_granted(Environment* env,
215215
}
216216

217217
if (!result && !publishing_) {
218-
const char* channel_name = GetDiagnosticsChannelName(permission);
218+
auto channel_name = GetDiagnosticsChannelName(permission);
219219
if (channel_name != nullptr) {
220220
diagnostics_channel::Channel ch =
221-
diagnostics_channel::Channel::Get(env, channel_name);
221+
GetOrCreateChannel(env, permission);
222222
if (ch.HasSubscribers()) {
223223
publishing_ = true;
224224
v8::Isolate* isolate = env->isolate();
225225
v8::HandleScope handle_scope(isolate);
226226
v8::Local<v8::Context> context = env->context();
227-
v8::Local<v8::Object> msg = v8::Object::New(isolate);
227+
v8::Local<v8::Object> msg = v8::Object::New(isolate, v8::Null(isolate), nullptr, nullptr, 0);
228228
const char* perm_str = PermissionToString(permission);
229229
msg->Set(context,
230230
FIXED_ONE_BYTE_STRING(isolate, "permission"),
@@ -247,6 +247,19 @@ bool Permission::is_scope_granted(Environment* env,
247247
return result;
248248
}
249249

250+
diagnostics_channel::Channel Permission::GetOrCreateChannel(
251+
Environment* env, PermissionScope scope) const {
252+
auto it = channels_.find(scope);
253+
if (it != channels_.end()) {
254+
return it->second;
255+
}
256+
const char* name = GetDiagnosticsChannelName(scope);
257+
diagnostics_channel::Channel ch =
258+
diagnostics_channel::Channel::Get(env, name);
259+
channels_.emplace(scope, ch);
260+
return ch;
261+
}
262+
250263
void Permission::Apply(Environment* env,
251264
const std::vector<std::string>& allow,
252265
PermissionScope scope) {

src/permission/permission.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "permission/permission_base.h"
1414
#include "permission/wasi_permission.h"
1515
#include "permission/worker_permission.h"
16+
#include "node_diagnostics_channel.h"
1617
#include "v8.h"
1718

1819
#include <string_view>
@@ -124,10 +125,15 @@ class Permission {
124125
const PermissionScope permission,
125126
const std::string_view& res = "") const;
126127

128+
diagnostics_channel::Channel GetOrCreateChannel(
129+
Environment* env, PermissionScope scope) const;
130+
127131
std::unordered_map<PermissionScope, std::shared_ptr<PermissionBase>> nodes_;
128132
bool enabled_;
129133
bool warning_only_;
130134
mutable bool publishing_ = false;
135+
mutable std::unordered_map<PermissionScope, diagnostics_channel::Channel>
136+
channels_;
131137
};
132138

133139
v8::MaybeLocal<v8::Value> CreateAccessDeniedError(Environment* env,

0 commit comments

Comments
 (0)