Skip to content

Commit b84cfb7

Browse files
committed
lib: unify bypass key validation in diagnostics_channel
Signed-off-by: Divyanshu Sharma <divyanshu88999@gmail.com>
1 parent e630f72 commit b84cfb7

1 file changed

Lines changed: 151 additions & 66 deletions

File tree

lib/diagnostics_channel.js

Lines changed: 151 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ function getSuppressionsStorage() {
4949
function withSuppressionsContext(set, fn, thisArg, args) {
5050
return getSuppressionsStorage().run(set, fn.bind(thisArg), ...args);
5151
}
52+
function validateBypassKey(value, name) {
53+
if (value == null) {
54+
throw new ERR_INVALID_ARG_TYPE(name, ['object', 'symbol'], value);
55+
}
56+
const type = typeof value;
57+
if (type !== 'object' && type !== 'symbol') {
58+
throw new ERR_INVALID_ARG_TYPE(name, ['object', 'symbol'], value);
59+
}
60+
}
61+
5262
// Can't delete when weakref count reaches 0 as it could increment again.
5363
// Only GC can be used as a valid time to clean up the channels map.
5464
class WeakRefMap extends SafeMap {
@@ -83,17 +93,24 @@ class WeakRefMap extends SafeMap {
8393
function markActive(channel) {
8494
// eslint-disable-next-line no-use-before-define
8595
ObjectSetPrototypeOf(channel, ActiveChannel.prototype);
86-
channel._subscribers = [];
87-
channel._stores = new SafeMap();
96+
channel._subscribers = []; // normal — plain functions
97+
channel._bypassSubscribers = null; // lazy — only if subscriberId used
98+
channel._stores = new SafeMap(); // normal — plain transforms
99+
channel._bypassStores = null; // lazy — only if subscriberId used
88100
}
89101

90102
function maybeMarkInactive(channel) {
91103
// When there are no more active subscribers or bound, restore to fast prototype.
92-
if (!channel._subscribers.length && !channel._stores.size) {
104+
if (!channel._subscribers.length &&
105+
!channel._stores.size &&
106+
!channel._bypassSubscribers?.length &&
107+
!channel._bypassStores?.size) {
93108
// eslint-disable-next-line no-use-before-define
94109
ObjectSetPrototypeOf(channel, Channel.prototype);
95110
channel._subscribers = undefined;
96111
channel._stores = undefined;
112+
channel._bypassSubscribers = undefined;
113+
channel._bypassStores = undefined;
97114
}
98115
}
99116

@@ -104,19 +121,33 @@ class RunStoresScope {
104121
// eslint-disable-next-line no-restricted-globals
105122
using stack = new DisposableStack();
106123

107-
// Enter stores using withScope
124+
// Normal stores — exactly as before, zero extra cost
108125
if (activeChannel._stores) {
109-
const activeKeys = getSuppressionsStorage().getStore();
110126
for (const entry of activeChannel._stores.entries()) {
111127
const store = entry[0];
112-
const { transform, subscriberId = null } = entry[1];
113-
114-
// Skip this bound store if it opted into suppression and its key
115-
// is active in the current async context.
116-
if (subscriberId !== null && activeKeys?.has(subscriberId)) {
117-
continue;
128+
const transform = entry[1];
129+
let newContext = data;
130+
if (transform) {
131+
try {
132+
newContext = transform(data);
133+
} catch (err) {
134+
process.nextTick(() => {
135+
triggerUncaughtException(err, false);
136+
});
137+
continue;
138+
}
118139
}
140+
stack.use(store.withScope(newContext));
141+
}
142+
}
119143

144+
// Bypass stores — only entered if bypass stores exist
145+
if (activeChannel._bypassStores) {
146+
const activeKeys = getSuppressionsStorage().getStore();
147+
for (const entry of activeChannel._bypassStores.entries()) {
148+
const store = entry[0];
149+
const { transform, subscriberId } = entry[1];
150+
if (activeKeys?.has(subscriberId)) continue;
120151
let newContext = data;
121152
if (transform) {
122153
try {
@@ -128,7 +159,6 @@ class RunStoresScope {
128159
continue;
129160
}
130161
}
131-
132162
stack.use(store.withScope(newContext));
133163
}
134164
}
@@ -149,95 +179,156 @@ class RunStoresScope {
149179
class ActiveChannel {
150180
subscribe(subscription, options = {}) {
151181
validateFunction(subscription, 'subscription');
152-
const subscriberId = options && options.subscriberId !== undefined ? options.subscriberId : null;
153-
if (subscriberId !== null) {
154-
const t = typeof subscriberId;
155-
if (t === 'string' || t === 'number' || t === 'bigint' || t === 'boolean') {
156-
throw new ERR_INVALID_ARG_TYPE('subscriberId', ['object', 'symbol', 'function'], subscriberId);
182+
const subscriberId = options?.subscriberId;
183+
184+
if (subscriberId !== undefined) {
185+
validateBypassKey(subscriberId, 'subscriberId');
186+
// Bypass path — lazy separate array
187+
if (this._bypassSubscribers === null) {
188+
this._bypassSubscribers = [];
157189
}
190+
this._bypassSubscribers = ArrayPrototypeSlice(this._bypassSubscribers);
191+
ArrayPrototypePush(this._bypassSubscribers, { handler: subscription, subscriberId });
192+
} else {
193+
// Normal path — plain function, zero extra cost
194+
this._subscribers = ArrayPrototypeSlice(this._subscribers);
195+
ArrayPrototypePush(this._subscribers, subscription);
158196
}
159197

160-
const handler = subscription;
161-
this._subscribers = ArrayPrototypeSlice(this._subscribers);
162-
ArrayPrototypePush(this._subscribers, { handler, subscriberId });
163198
channels.incRef(this.name);
164199
if (this._index !== undefined) subscriberCounts[this._index]++;
165200
}
166201

167202
unsubscribe(subscription) {
168-
// Find subscriber entry by handler identity.
203+
// Check normal subscribers first
169204
let index = -1;
170-
for (let i = 0; i < (this._subscribers?.length || 0); i++) {
171-
if (this._subscribers[i].handler === subscription) {
205+
for (let i = 0; i < this._subscribers.length; i++) {
206+
if (this._subscribers[i] === subscription) {
172207
index = i;
173208
break;
174209
}
175210
}
176-
if (index === -1) return false;
177211

178-
const before = ArrayPrototypeSlice(this._subscribers, 0, index);
179-
const after = ArrayPrototypeSlice(this._subscribers, index + 1);
180-
this._subscribers = before;
181-
ArrayPrototypePushApply(this._subscribers, after);
212+
if (index !== -1) {
213+
const before = ArrayPrototypeSlice(this._subscribers, 0, index);
214+
const after = ArrayPrototypeSlice(this._subscribers, index + 1);
215+
this._subscribers = before;
216+
ArrayPrototypePushApply(this._subscribers, after);
217+
channels.decRef(this.name);
218+
if (this._index !== undefined) subscriberCounts[this._index]--;
219+
maybeMarkInactive(this);
220+
return true;
221+
}
182222

183-
channels.decRef(this.name);
184-
if (this._index !== undefined) subscriberCounts[this._index]--;
185-
maybeMarkInactive(this);
223+
// Check bypass subscribers
224+
if (this._bypassSubscribers !== null) {
225+
let bypassIndex = -1;
226+
for (let i = 0; i < this._bypassSubscribers.length; i++) {
227+
if (this._bypassSubscribers[i].handler === subscription) {
228+
bypassIndex = i;
229+
break;
230+
}
231+
}
232+
if (bypassIndex !== -1) {
233+
const before = ArrayPrototypeSlice(this._bypassSubscribers, 0, bypassIndex);
234+
const after = ArrayPrototypeSlice(this._bypassSubscribers, bypassIndex + 1);
235+
this._bypassSubscribers = before;
236+
ArrayPrototypePushApply(this._bypassSubscribers, after);
237+
if (this._bypassSubscribers.length === 0) {
238+
this._bypassSubscribers = null;
239+
}
240+
channels.decRef(this.name);
241+
if (this._index !== undefined) subscriberCounts[this._index]--;
242+
maybeMarkInactive(this);
243+
return true;
244+
}
245+
}
186246

187-
return true;
247+
return false;
188248
}
189249

190250
bindStore(store, transform, options = {}) {
191-
const subscriberId = options && options.subscriberId !== undefined ? options.subscriberId : null;
192-
if (subscriberId !== null) {
193-
const t = typeof subscriberId;
194-
if (t === 'string' || t === 'number' || t === 'bigint' || t === 'boolean') {
195-
throw new ERR_INVALID_ARG_TYPE('subscriberId', ['object', 'symbol', 'function'], subscriberId);
196-
}
197-
}
251+
const subscriberId = options?.subscriberId;
198252

199-
const replacing = this._stores.has(store);
200-
if (!replacing) {
201-
channels.incRef(this.name);
202-
if (this._index !== undefined) subscriberCounts[this._index]++;
253+
if (subscriberId !== undefined) {
254+
validateBypassKey(subscriberId, 'subscriberId');
255+
// Bypass path — lazy separate SafeMap
256+
if (this._bypassStores === null) {
257+
this._bypassStores = new SafeMap();
258+
}
259+
const replacing = this._bypassStores.has(store);
260+
if (!replacing) {
261+
channels.incRef(this.name);
262+
if (this._index !== undefined) subscriberCounts[this._index]++;
263+
}
264+
this._bypassStores.set(store, { transform, subscriberId });
265+
} else {
266+
// Normal path — plain transform, zero extra cost
267+
const replacing = this._stores.has(store);
268+
if (!replacing) {
269+
channels.incRef(this.name);
270+
if (this._index !== undefined) subscriberCounts[this._index]++;
271+
}
272+
this._stores.set(store, transform);
203273
}
204-
this._stores.set(store, { transform, subscriberId });
205274
}
206275

207276
unbindStore(store) {
208-
if (!this._stores.has(store)) {
209-
return false;
277+
if (this._stores.has(store)) {
278+
this._stores.delete(store);
279+
channels.decRef(this.name);
280+
if (this._index !== undefined) subscriberCounts[this._index]--;
281+
maybeMarkInactive(this);
282+
return true;
210283
}
211284

212-
this._stores.delete(store);
213-
214-
channels.decRef(this.name);
215-
if (this._index !== undefined) subscriberCounts[this._index]--;
216-
maybeMarkInactive(this);
285+
if (this._bypassStores?.has(store)) {
286+
this._bypassStores.delete(store);
287+
if (this._bypassStores.size === 0) {
288+
this._bypassStores = null;
289+
}
290+
channels.decRef(this.name);
291+
if (this._index !== undefined) subscriberCounts[this._index]--;
292+
maybeMarkInactive(this);
293+
return true;
294+
}
217295

218-
return true;
296+
return false;
219297
}
220298

221299
get hasSubscribers() {
222300
return true;
223301
}
224302

225303
publish(data) {
304+
// Normal path — no ALS lookup, plain function call, zero overhead
226305
const subscribers = this._subscribers;
227-
const activeKeys = getSuppressionsStorage().getStore();
228-
for (let i = 0; i < (subscribers?.length || 0); i++) {
306+
for (let i = 0; i < subscribers.length; i++) {
229307
try {
230-
const { handler, subscriberId = null } = subscribers[i];
231-
if (subscriberId !== null && activeKeys?.has(subscriberId)) {
232-
continue;
233-
}
234-
handler(data, this.name);
308+
subscribers[i](data, this.name);
235309
} catch (err) {
236310
process.nextTick(() => {
237311
triggerUncaughtException(err, false);
238312
});
239313
}
240314
}
315+
316+
// Bypass path — only entered if bypass subscribers exist
317+
if (this._bypassSubscribers !== null) {
318+
const activeKeys = getSuppressionsStorage().getStore();
319+
const bypassSubscribers = this._bypassSubscribers;
320+
for (let i = 0; i < bypassSubscribers.length; i++) {
321+
try {
322+
const { handler, subscriberId } = bypassSubscribers[i];
323+
if (activeKeys?.has(subscriberId)) continue;
324+
handler(data, this.name);
325+
} catch (err) {
326+
process.nextTick(() => {
327+
triggerUncaughtException(err, false);
328+
});
329+
}
330+
}
331+
}
241332
}
242333

243334
withStoreScope(data) {
@@ -684,13 +775,7 @@ dc_binding.linkNativeChannel((name) => channel(name));
684775
function suppressed(key, fn, thisArg, ...args) {
685776
validateFunction(fn, 'fn');
686777

687-
if (key === null || key === undefined) {
688-
throw new ERR_INVALID_ARG_TYPE('key', ['object', 'symbol', 'function'], key);
689-
}
690-
const t = typeof key;
691-
if (t === 'string' || t === 'number' || t === 'bigint' || t === 'boolean') {
692-
throw new ERR_INVALID_ARG_TYPE('key', ['object', 'symbol', 'function'], key);
693-
}
778+
validateBypassKey(key, 'key');
694779

695780
const currentSet = getSuppressionsStorage().getStore();
696781
const next = currentSet ? new SafeSet(currentSet) : new SafeSet();

0 commit comments

Comments
 (0)