Skip to content

Commit 2991622

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

1 file changed

Lines changed: 150 additions & 64 deletions

File tree

lib/diagnostics_channel.js

Lines changed: 150 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ function getSuppressionsStorage() {
4949
function withSuppressionsContext(set, fn, thisArg, args) {
5050
return getSuppressionsStorage().run(set, fn.bind(thisArg), ...args);
5151
}
52+
53+
function validateBypassKey(value, name) {
54+
if (value == null) {
55+
throw new ERR_INVALID_ARG_TYPE(name, ['object', 'symbol'], value);
56+
}
57+
const type = typeof value;
58+
if (type !== 'object' && type !== 'symbol') {
59+
throw new ERR_INVALID_ARG_TYPE(name, ['object', 'symbol'], value);
60+
}
61+
}
62+
5263
// Can't delete when weakref count reaches 0 as it could increment again.
5364
// Only GC can be used as a valid time to clean up the channels map.
5465
class WeakRefMap extends SafeMap {
@@ -84,16 +95,23 @@ function markActive(channel) {
8495
// eslint-disable-next-line no-use-before-define
8596
ObjectSetPrototypeOf(channel, ActiveChannel.prototype);
8697
channel._subscribers = [];
98+
channel._bypassSubscribers = null;
8799
channel._stores = new SafeMap();
100+
channel._bypassStores = null;
88101
}
89102

90103
function maybeMarkInactive(channel) {
91104
// When there are no more active subscribers or bound, restore to fast prototype.
92-
if (!channel._subscribers.length && !channel._stores.size) {
105+
if (!channel._subscribers.length &&
106+
!channel._stores.size &&
107+
!channel._bypassSubscribers?.length &&
108+
!channel._bypassStores?.size) {
93109
// eslint-disable-next-line no-use-before-define
94110
ObjectSetPrototypeOf(channel, Channel.prototype);
95111
channel._subscribers = undefined;
96112
channel._stores = undefined;
113+
channel._bypassSubscribers = undefined;
114+
channel._bypassStores = undefined;
97115
}
98116
}
99117

@@ -104,19 +122,33 @@ class RunStoresScope {
104122
// eslint-disable-next-line no-restricted-globals
105123
using stack = new DisposableStack();
106124

107-
// Enter stores using withScope
125+
// Normal stores — exactly as before, zero extra cost
108126
if (activeChannel._stores) {
109-
const activeKeys = getSuppressionsStorage().getStore();
110127
for (const entry of activeChannel._stores.entries()) {
111128
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;
129+
const transform = entry[1];
130+
let newContext = data;
131+
if (transform) {
132+
try {
133+
newContext = transform(data);
134+
} catch (err) {
135+
process.nextTick(() => {
136+
triggerUncaughtException(err, false);
137+
});
138+
continue;
139+
}
118140
}
141+
stack.use(store.withScope(newContext));
142+
}
143+
}
119144

145+
// Bypass stores — only entered if bypass stores exist
146+
if (activeChannel._bypassStores) {
147+
const activeKeys = getSuppressionsStorage().getStore();
148+
for (const entry of activeChannel._bypassStores.entries()) {
149+
const store = entry[0];
150+
const { transform, subscriberId } = entry[1];
151+
if (activeKeys?.has(subscriberId)) continue;
120152
let newContext = data;
121153
if (transform) {
122154
try {
@@ -128,7 +160,6 @@ class RunStoresScope {
128160
continue;
129161
}
130162
}
131-
132163
stack.use(store.withScope(newContext));
133164
}
134165
}
@@ -149,95 +180,156 @@ class RunStoresScope {
149180
class ActiveChannel {
150181
subscribe(subscription, options = {}) {
151182
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);
183+
const subscriberId = options?.subscriberId;
184+
185+
if (subscriberId !== undefined) {
186+
validateBypassKey(subscriberId, 'subscriberId');
187+
// Bypass path — lazy separate array
188+
if (this._bypassSubscribers === null) {
189+
this._bypassSubscribers = [];
157190
}
191+
this._bypassSubscribers = ArrayPrototypeSlice(this._bypassSubscribers);
192+
ArrayPrototypePush(this._bypassSubscribers, { handler: subscription, subscriberId });
193+
} else {
194+
// Normal path — plain function, zero extra cost
195+
this._subscribers = ArrayPrototypeSlice(this._subscribers);
196+
ArrayPrototypePush(this._subscribers, subscription);
158197
}
159198

160-
const handler = subscription;
161-
this._subscribers = ArrayPrototypeSlice(this._subscribers);
162-
ArrayPrototypePush(this._subscribers, { handler, subscriberId });
163199
channels.incRef(this.name);
164200
if (this._index !== undefined) subscriberCounts[this._index]++;
165201
}
166202

167203
unsubscribe(subscription) {
168-
// Find subscriber entry by handler identity.
204+
// Check normal subscribers first
169205
let index = -1;
170-
for (let i = 0; i < (this._subscribers?.length || 0); i++) {
171-
if (this._subscribers[i].handler === subscription) {
206+
for (let i = 0; i < this._subscribers.length; i++) {
207+
if (this._subscribers[i] === subscription) {
172208
index = i;
173209
break;
174210
}
175211
}
176-
if (index === -1) return false;
177212

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);
213+
if (index !== -1) {
214+
const before = ArrayPrototypeSlice(this._subscribers, 0, index);
215+
const after = ArrayPrototypeSlice(this._subscribers, index + 1);
216+
this._subscribers = before;
217+
ArrayPrototypePushApply(this._subscribers, after);
218+
channels.decRef(this.name);
219+
if (this._index !== undefined) subscriberCounts[this._index]--;
220+
maybeMarkInactive(this);
221+
return true;
222+
}
182223

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

187-
return true;
248+
return false;
188249
}
189250

190251
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-
}
252+
const subscriberId = options?.subscriberId;
198253

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

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

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

218-
return true;
297+
return false;
219298
}
220299

221300
get hasSubscribers() {
222301
return true;
223302
}
224303

225304
publish(data) {
305+
// Normal path — no ALS lookup, plain function call, zero overhead
226306
const subscribers = this._subscribers;
227-
const activeKeys = getSuppressionsStorage().getStore();
228-
for (let i = 0; i < (subscribers?.length || 0); i++) {
307+
for (let i = 0; i < subscribers.length; i++) {
229308
try {
230-
const { handler, subscriberId = null } = subscribers[i];
231-
if (subscriberId !== null && activeKeys?.has(subscriberId)) {
232-
continue;
233-
}
234-
handler(data, this.name);
309+
subscribers[i](data, this.name);
235310
} catch (err) {
236311
process.nextTick(() => {
237312
triggerUncaughtException(err, false);
238313
});
239314
}
240315
}
316+
317+
// Bypass path — only entered if bypass subscribers exist
318+
if (this._bypassSubscribers !== null) {
319+
const activeKeys = getSuppressionsStorage().getStore();
320+
const bypassSubscribers = this._bypassSubscribers;
321+
for (let i = 0; i < bypassSubscribers.length; i++) {
322+
try {
323+
const { handler, subscriberId } = bypassSubscribers[i];
324+
if (activeKeys?.has(subscriberId)) continue;
325+
handler(data, this.name);
326+
} catch (err) {
327+
process.nextTick(() => {
328+
triggerUncaughtException(err, false);
329+
});
330+
}
331+
}
332+
}
241333
}
242334

243335
withStoreScope(data) {
@@ -684,13 +776,7 @@ dc_binding.linkNativeChannel((name) => channel(name));
684776
function suppressed(key, fn, thisArg, ...args) {
685777
validateFunction(fn, 'fn');
686778

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-
}
779+
validateBypassKey(key, 'key');
694780

695781
const currentSet = getSuppressionsStorage().getStore();
696782
const next = currentSet ? new SafeSet(currentSet) : new SafeSet();

0 commit comments

Comments
 (0)