Skip to content

Commit

Permalink
worker: add brand checks for detached properties/methods
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
jasnell authored and danielleadams committed Aug 16, 2021
1 parent 5d66646 commit dcab88a
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
40 changes: 39 additions & 1 deletion lib/internal/worker/io.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const { inspect } = require('internal/util/inspect');
const {
codes: {
ERR_INVALID_ARG_TYPE,
ERR_INVALID_THIS,
ERR_MISSING_ARGS,
}
} = require('internal/errors');
Expand All @@ -74,6 +75,7 @@ const kStartedReading = Symbol('kStartedReading');
const kStdioWantsMoreDataCallback = Symbol('kStdioWantsMoreDataCallback');
const kCurrentlyReceivingPorts =
SymbolFor('nodejs.internal.kCurrentlyReceivingPorts');
const kType = Symbol('kType');

const messageTypes = {
UP_AND_RUNNING: 'upAndRunning',
Expand Down Expand Up @@ -349,11 +351,16 @@ function onMessageEvent(type, data) {
this.dispatchEvent(new MessageEvent(type, { data }));
}

function isBroadcastChannel(value) {
return value?.[kType] === 'BroadcastChannel';
}

class BroadcastChannel extends EventTarget {
constructor(name) {
if (arguments.length === 0)
throw new ERR_MISSING_ARGS('name');
super();
this[kType] = 'BroadcastChannel';
this[kName] = `${name}`;
this[kHandle] = broadcastChannel(this[kName]);
this[kOnMessage] = FunctionPrototypeBind(onMessageEvent, this, 'message');
Expand All @@ -364,6 +371,8 @@ class BroadcastChannel extends EventTarget {
}

[inspect.custom](depth, options) {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (depth < 0)
return 'BroadcastChannel';

Expand All @@ -378,9 +387,15 @@ class BroadcastChannel extends EventTarget {
}, opts)}`;
}

get name() { return this[kName]; }
get name() {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
return this[kName];
}

close() {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (this[kHandle] === undefined)
return;
this[kHandle].off('message', this[kOnMessage]);
Expand All @@ -392,6 +407,8 @@ class BroadcastChannel extends EventTarget {
}

postMessage(message) {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (arguments.length === 0)
throw new ERR_MISSING_ARGS('message');
if (this[kHandle] === undefined)
Expand All @@ -400,19 +417,40 @@ class BroadcastChannel extends EventTarget {
throw new DOMException('Message could not be posted.');
}

// The ref() method is Node.js specific and not part of the standard
// BroadcastChannel API definition. Typically we shouldn't extend Web
// Platform APIs with Node.js specific methods but ref and unref
// are a bit special.
ref() {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (this[kHandle])
this[kHandle].ref();
return this;
}

// The unref() method is Node.js specific and not part of the standard
// BroadcastChannel API definition. Typically we shouldn't extend Web
// Platform APIs with Node.js specific methods but ref and unref
// are a bit special.
unref() {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (this[kHandle])
this[kHandle].unref();
return this;
}
}

const kEnumerableProperty = ObjectCreate(null);
kEnumerableProperty.enumerable = true;

ObjectDefineProperties(BroadcastChannel.prototype, {
name: kEnumerableProperty,
close: kEnumerableProperty,
postMessage: kEnumerableProperty,
});

defineEventHandler(BroadcastChannel.prototype, 'message');
defineEventHandler(BroadcastChannel.prototype, 'messageerror');

Expand Down
17 changes: 17 additions & 0 deletions test/parallel/test-worker-broadcastchannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,20 @@ assert.throws(() => new BroadcastChannel(), {
bc1.close();
bc2.close();
}

{
assert.throws(() => Reflect.get(BroadcastChannel.prototype, 'name', {}), {
code: 'ERR_INVALID_THIS',
});

[
'close',
'postMessage',
'ref',
'unref',
].forEach((i) => {
assert.throws(() => Reflect.apply(BroadcastChannel.prototype[i], [], {}), {
code: 'ERR_INVALID_THIS',
});
});
}

0 comments on commit dcab88a

Please sign in to comment.