node/test/parallel/test-web-locks-query.js
ishabi 062e8b5a74 worker: add web locks api
PR-URL: https://github.com/nodejs/node/pull/58666
Fixes: https://github.com/nodejs/node/pull/36502
Refs: https://w3c.github.io/web-locks
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
2025-07-18 07:55:10 -07:00

92 lines
3.2 KiB
JavaScript

'use strict';
require('../common');
const { describe, it } = require('node:test');
const assert = require('node:assert');
const { Worker } = require('worker_threads');
describe('Web Locks - query missing WPT tests', () => {
it('should report different ids for held locks from different contexts', async () => {
const worker = new Worker(`
const { parentPort } = require('worker_threads');
navigator.locks.request('different-contexts-resource', { mode: 'shared' }, async (lock) => {
const state = await navigator.locks.query();
const heldLocks = state.held.filter(l => l.name === 'different-contexts-resource');
parentPort.postMessage({ clientId: heldLocks[0].clientId });
await new Promise(resolve => {
parentPort.once('message', () => resolve());
});
}).catch(err => parentPort.postMessage({ error: err.message }));
`, { eval: true });
const workerResult = await new Promise((resolve) => {
worker.once('message', resolve);
});
await navigator.locks.request('different-contexts-resource', { mode: 'shared' }, async (lock) => {
const state = await navigator.locks.query();
const heldLocks = state.held.filter((l) => l.name === 'different-contexts-resource');
const mainClientId = heldLocks[0].clientId;
assert.notStrictEqual(mainClientId, workerResult.clientId);
worker.postMessage('release');
});
await worker.terminate();
});
it('should observe a deadlock scenario', async () => {
const worker = new Worker(`
const { parentPort } = require('worker_threads');
navigator.locks.request('deadlock-resource-1', async (lock1) => {
parentPort.postMessage({ acquired: 'resource1' });
await new Promise(resolve => {
parentPort.once('message', () => resolve());
});
const result = await navigator.locks.request('deadlock-resource-2',
{ ifAvailable: true }, (lock2) => lock2 !== null);
parentPort.postMessage({ acquired2: result });
await new Promise(resolve => {
parentPort.once('message', () => resolve());
});
}).catch(err => parentPort.postMessage({ error: err.message }));
`, { eval: true });
const step1 = await new Promise((resolve) => {
worker.once('message', resolve);
});
assert.strictEqual(step1.acquired, 'resource1');
await navigator.locks.request('deadlock-resource-2', async (lock2) => {
worker.postMessage('try-resource2');
const step2 = await new Promise((resolve) => {
worker.once('message', resolve);
});
assert.strictEqual(step2.acquired2, false);
const canGetResource1 = await navigator.locks.request('deadlock-resource-1',
{ ifAvailable: true }, (lock1) => lock1 !== null);
assert.strictEqual(canGetResource1, false);
const state = await navigator.locks.query();
const resource2Lock = state.held.find((l) => l.name === 'deadlock-resource-2');
assert(resource2Lock);
worker.postMessage('release');
});
await worker.terminate();
});
});