node/test/parallel/test-worker-message-mark-as-uncloneable.js
Jason Zhang d2ad9b4fb6
worker: add markAsUncloneable api
External modules need a way to decorate their objects so that node can
recognize it as a host object for serialization process. Exposing a way
for turning off instead of turning on is much safer.

PR-URL: https://github.com/nodejs/node/pull/55234
Refs: https://github.com/nodejs/node/pull/55178
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
2024-10-04 07:09:37 +00:00

71 lines
2.0 KiB
JavaScript

'use strict';
require('../common');
const assert = require('assert');
const { markAsUncloneable } = require('node:worker_threads');
const { mustCall } = require('../common');
const expectedErrorName = 'DataCloneError';
// Uncloneables cannot be cloned during message posting
{
const anyObject = { foo: 'bar' };
markAsUncloneable(anyObject);
const { port1 } = new MessageChannel();
assert.throws(() => port1.postMessage(anyObject), {
constructor: DOMException,
name: expectedErrorName,
code: 25,
}, `Should throw ${expectedErrorName} when posting uncloneables`);
}
// Uncloneables cannot be cloned during structured cloning
{
class MockResponse extends Response {
constructor() {
super();
markAsUncloneable(this);
}
}
structuredClone(MockResponse.prototype);
markAsUncloneable(MockResponse.prototype);
const r = new MockResponse();
assert.throws(() => structuredClone(r), {
constructor: DOMException,
name: expectedErrorName,
code: 25,
}, `Should throw ${expectedErrorName} when cloning uncloneables`);
}
// markAsUncloneable cannot affect ArrayBuffer
{
const pooledBuffer = new ArrayBuffer(8);
const { port1, port2 } = new MessageChannel();
markAsUncloneable(pooledBuffer);
port1.postMessage(pooledBuffer);
port2.on('message', mustCall((value) => {
assert.deepStrictEqual(value, pooledBuffer);
port2.close(mustCall());
}));
}
// markAsUncloneable can affect Node.js built-in object like Blob
{
const cloneableBlob = new Blob();
const { port1, port2 } = new MessageChannel();
port1.postMessage(cloneableBlob);
port2.on('message', mustCall((value) => {
assert.deepStrictEqual(value, cloneableBlob);
port2.close(mustCall());
}));
const uncloneableBlob = new Blob();
markAsUncloneable(uncloneableBlob);
assert.throws(() => port1.postMessage(uncloneableBlob), {
constructor: DOMException,
name: expectedErrorName,
code: 25,
}, `Should throw ${expectedErrorName} when cloning uncloneables`);
}