Skip to content

Commit dcab88a

Browse files
jasnelldanielleadams
authored andcommitted
worker: add brand checks for detached properties/methods
Add proper brand-checking for detached property and method accesses. Also adds a note about non-standard APIs and makes the standard accessors enumerable. Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: #39763 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
1 parent 5d66646 commit dcab88a

File tree

2 files changed

+56
-1
lines changed

2 files changed

+56
-1
lines changed

lib/internal/worker/io.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const { inspect } = require('internal/util/inspect');
5353
const {
5454
codes: {
5555
ERR_INVALID_ARG_TYPE,
56+
ERR_INVALID_THIS,
5657
ERR_MISSING_ARGS,
5758
}
5859
} = require('internal/errors');
@@ -74,6 +75,7 @@ const kStartedReading = Symbol('kStartedReading');
7475
const kStdioWantsMoreDataCallback = Symbol('kStdioWantsMoreDataCallback');
7576
const kCurrentlyReceivingPorts =
7677
SymbolFor('nodejs.internal.kCurrentlyReceivingPorts');
78+
const kType = Symbol('kType');
7779

7880
const messageTypes = {
7981
UP_AND_RUNNING: 'upAndRunning',
@@ -349,11 +351,16 @@ function onMessageEvent(type, data) {
349351
this.dispatchEvent(new MessageEvent(type, { data }));
350352
}
351353

354+
function isBroadcastChannel(value) {
355+
return value?.[kType] === 'BroadcastChannel';
356+
}
357+
352358
class BroadcastChannel extends EventTarget {
353359
constructor(name) {
354360
if (arguments.length === 0)
355361
throw new ERR_MISSING_ARGS('name');
356362
super();
363+
this[kType] = 'BroadcastChannel';
357364
this[kName] = `${name}`;
358365
this[kHandle] = broadcastChannel(this[kName]);
359366
this[kOnMessage] = FunctionPrototypeBind(onMessageEvent, this, 'message');
@@ -364,6 +371,8 @@ class BroadcastChannel extends EventTarget {
364371
}
365372

366373
[inspect.custom](depth, options) {
374+
if (!isBroadcastChannel(this))
375+
throw new ERR_INVALID_THIS('BroadcastChannel');
367376
if (depth < 0)
368377
return 'BroadcastChannel';
369378

@@ -378,9 +387,15 @@ class BroadcastChannel extends EventTarget {
378387
}, opts)}`;
379388
}
380389

381-
get name() { return this[kName]; }
390+
get name() {
391+
if (!isBroadcastChannel(this))
392+
throw new ERR_INVALID_THIS('BroadcastChannel');
393+
return this[kName];
394+
}
382395

383396
close() {
397+
if (!isBroadcastChannel(this))
398+
throw new ERR_INVALID_THIS('BroadcastChannel');
384399
if (this[kHandle] === undefined)
385400
return;
386401
this[kHandle].off('message', this[kOnMessage]);
@@ -392,6 +407,8 @@ class BroadcastChannel extends EventTarget {
392407
}
393408

394409
postMessage(message) {
410+
if (!isBroadcastChannel(this))
411+
throw new ERR_INVALID_THIS('BroadcastChannel');
395412
if (arguments.length === 0)
396413
throw new ERR_MISSING_ARGS('message');
397414
if (this[kHandle] === undefined)
@@ -400,19 +417,40 @@ class BroadcastChannel extends EventTarget {
400417
throw new DOMException('Message could not be posted.');
401418
}
402419

420+
// The ref() method is Node.js specific and not part of the standard
421+
// BroadcastChannel API definition. Typically we shouldn't extend Web
422+
// Platform APIs with Node.js specific methods but ref and unref
423+
// are a bit special.
403424
ref() {
425+
if (!isBroadcastChannel(this))
426+
throw new ERR_INVALID_THIS('BroadcastChannel');
404427
if (this[kHandle])
405428
this[kHandle].ref();
406429
return this;
407430
}
408431

432+
// The unref() method is Node.js specific and not part of the standard
433+
// BroadcastChannel API definition. Typically we shouldn't extend Web
434+
// Platform APIs with Node.js specific methods but ref and unref
435+
// are a bit special.
409436
unref() {
437+
if (!isBroadcastChannel(this))
438+
throw new ERR_INVALID_THIS('BroadcastChannel');
410439
if (this[kHandle])
411440
this[kHandle].unref();
412441
return this;
413442
}
414443
}
415444

445+
const kEnumerableProperty = ObjectCreate(null);
446+
kEnumerableProperty.enumerable = true;
447+
448+
ObjectDefineProperties(BroadcastChannel.prototype, {
449+
name: kEnumerableProperty,
450+
close: kEnumerableProperty,
451+
postMessage: kEnumerableProperty,
452+
});
453+
416454
defineEventHandler(BroadcastChannel.prototype, 'message');
417455
defineEventHandler(BroadcastChannel.prototype, 'messageerror');
418456

test/parallel/test-worker-broadcastchannel.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,20 @@ assert.throws(() => new BroadcastChannel(), {
151151
bc1.close();
152152
bc2.close();
153153
}
154+
155+
{
156+
assert.throws(() => Reflect.get(BroadcastChannel.prototype, 'name', {}), {
157+
code: 'ERR_INVALID_THIS',
158+
});
159+
160+
[
161+
'close',
162+
'postMessage',
163+
'ref',
164+
'unref',
165+
].forEach((i) => {
166+
assert.throws(() => Reflect.apply(BroadcastChannel.prototype[i], [], {}), {
167+
code: 'ERR_INVALID_THIS',
168+
});
169+
});
170+
}

0 commit comments

Comments
 (0)