UNPKG

@ava/cooperate

Version:

Plugin to enable cooperation between AVA test files

313 lines 12.6 kB
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _Lock_context, _ManagedSemaphore_context, _UnmanagedSemaphore_context; import { registerSharedWorker } from 'ava/plugin'; import never from 'never'; const protocol = registerSharedWorker({ filename: new URL('worker.js', import.meta.url), supportedProtocols: ['ava-4'], }); export class Lock { constructor(context, id) { Object.defineProperty(this, "id", { enumerable: true, configurable: true, writable: true, value: id }); _Lock_context.set(this, void 0); __classPrivateFieldSet(this, _Lock_context, context, "f"); } async acquire() { // Allow acquire() to be called before the shared worker is availabe. await protocol.available; const message = protocol.publish({ type: 10 /* LOCK */, contextId: __classPrivateFieldGet(this, _Lock_context, "f").id, lockId: this.id, wait: true, }); for await (const reply of message.replies()) { if (reply.data.type === 11 /* LOCK_ACQUIRED */) { return () => { reply.reply({ type: 13 /* LOCK_RELEASE */ }); }; } } // The above loop will never actually break if the lock is not acquired. return never(); } async acquireNow() { // Publish immediately, which will fail if the protocol is not available. // "Now" should not mean "wait until we're ready." const message = protocol.publish({ type: 10 /* LOCK */, contextId: __classPrivateFieldGet(this, _Lock_context, "f").id, lockId: this.id, wait: false, }); for await (const reply of message.replies()) { if (reply.data.type === 11 /* LOCK_ACQUIRED */) { return () => { reply.reply({ type: 13 /* LOCK_RELEASE */ }); }; } if (reply.data.type === 12 /* LOCK_FAILED */) { throw new LockAcquisitionError(this.id); } } // The above loop will never actually break if the lock is not acquired. return never(); } } _Lock_context = new WeakMap(); export class LockAcquisitionError extends Error { constructor(lockId) { super('Could not immediately acquire the lock'); Object.defineProperty(this, "lockId", { enumerable: true, configurable: true, writable: true, value: lockId }); } get name() { return 'LockAcquisitionError'; } } export class ManagedSemaphore { constructor(context, id, initialValue) { Object.defineProperty(this, "id", { enumerable: true, configurable: true, writable: true, value: id }); Object.defineProperty(this, "initialValue", { enumerable: true, configurable: true, writable: true, value: initialValue }); _ManagedSemaphore_context.set(this, void 0); if (initialValue < 0 || !Number.isSafeInteger(initialValue)) { throw new RangeError('initialValue must be a non-negative safe integer'); } __classPrivateFieldSet(this, _ManagedSemaphore_context, context, "f"); } async acquire(amount = 1) { if (amount < 0 || !Number.isSafeInteger(amount)) { throw new RangeError('amount must be a non-negative safe integer'); } // Allow acquire() to be called before the shared worker is availabe. await protocol.available; const reply = await downSemaphore(this, __classPrivateFieldGet(this, _ManagedSemaphore_context, "f").id, amount, true); return (release = amount) => { if (release < 0 || !Number.isSafeInteger(release) || release > amount) { throw new RangeError('Amount to release must be a non-negative safe integer and <= remaining amount'); } amount -= release; reply.reply({ type: 33 /* SEMAPHORE_RELEASE */, amount: release, }); }; } async acquireNow(amount = 1) { if (amount < 0 || !Number.isSafeInteger(amount)) { throw new RangeError('amount must be a non-negative safe integer'); } // Down immediately, which will fail if the protocol is not available. // "Now" should not mean "wait until we're ready." const reply = await downSemaphore(this, __classPrivateFieldGet(this, _ManagedSemaphore_context, "f").id, amount, false); return (release = amount) => { if (release < 0 || release > amount) { throw new RangeError('Amount to release must be >= 0 and <= remaining amount'); } amount -= release; reply.reply({ type: 33 /* SEMAPHORE_RELEASE */, amount: release, }); }; } } _ManagedSemaphore_context = new WeakMap(); export class UnmanagedSemaphore { constructor(context, id, initialValue) { Object.defineProperty(this, "id", { enumerable: true, configurable: true, writable: true, value: id }); Object.defineProperty(this, "initialValue", { enumerable: true, configurable: true, writable: true, value: initialValue }); _UnmanagedSemaphore_context.set(this, void 0); if (initialValue < 0 || !Number.isSafeInteger(initialValue)) { throw new RangeError('initialValue must be a non-negative safe integer'); } __classPrivateFieldSet(this, _UnmanagedSemaphore_context, context, "f"); } async down(amount = 1) { if (amount < 0 || !Number.isSafeInteger(amount)) { throw new RangeError('amount must be a non-negative safe integer'); } // Allow down() to be called before the shared worker is availabe. await protocol.available; await downSemaphore(this, __classPrivateFieldGet(this, _UnmanagedSemaphore_context, "f").id, amount, true); } async downNow(amount = 1) { if (amount < 0 || !Number.isSafeInteger(amount)) { throw new RangeError('amount must be a non-negative safe integer'); } // Down immediately, which will fail if the protocol is not available. // "Now" should not mean "wait until we're ready." await downSemaphore(this, __classPrivateFieldGet(this, _UnmanagedSemaphore_context, "f").id, amount, false); } async up(amount = 1) { if (amount < 0 || !Number.isSafeInteger(amount)) { throw new RangeError('amount must be a non-negative safe integer'); } // Allow up() to be called before the shared worker is availabe. await protocol.available; const { id, initialValue } = this; const message = protocol.publish({ type: 35 /* SEMAPHORE_UP */, contextId: __classPrivateFieldGet(this, _UnmanagedSemaphore_context, "f").id, semaphore: { managed: false, id, initialValue }, amount, }); for await (const reply of message.replies()) { if (reply.data.type === 34 /* SEMAPHORE_SUCCEEDED */) { return; } if (reply.data.type === 30 /* SEMAPHORE_CREATION_FAILED */) { throw new SemaphoreCreationError(this, reply.data); } } // The above loop will never actually break if the resources are not acquired. return never(); } } _UnmanagedSemaphore_context = new WeakMap(); async function downSemaphore(semaphore, contextId, amount, wait) { const { id, initialValue } = semaphore; const message = protocol.publish({ type: 31 /* SEMAPHORE_DOWN */, contextId, semaphore: { managed: semaphore instanceof ManagedSemaphore, id, initialValue }, amount, wait, }); for await (const reply of message.replies()) { if (reply.data.type === 34 /* SEMAPHORE_SUCCEEDED */) { return reply; } if (reply.data.type === 32 /* SEMAPHORE_FAILED */) { throw new SemaphoreDownError(id, amount); } if (reply.data.type === 30 /* SEMAPHORE_CREATION_FAILED */) { throw new SemaphoreCreationError(semaphore, reply.data); } } // The above loop will never actually break if the resources are not acquired. return never(); } export class SemaphoreDownError extends Error { constructor(semaphoreId, amount) { super(`Could not immediately decrement with ${amount}`); Object.defineProperty(this, "semaphoreId", { enumerable: true, configurable: true, writable: true, value: semaphoreId }); Object.defineProperty(this, "amount", { enumerable: true, configurable: true, writable: true, value: amount }); } get name() { return 'SemaphoreDownError'; } } const creationMessage = (semaphore, { initialValue, managed }) => { const initialValueSuffix = `initial value ${semaphore.initialValue} (got ${initialValue})`; if (semaphore instanceof ManagedSemaphore) { if (managed) { return `Failed to create semaphore: expected ${initialValueSuffix}`; } return `Failed to create semaphore: expected unmanaged and ${initialValueSuffix}`; } if (managed) { return `Failed to create unmanaged semaphore: expected managed and ${initialValueSuffix}`; } return `Failed to create unmanaged semaphore: expected ${initialValueSuffix}`; }; export class SemaphoreCreationError extends Error { constructor(semaphore, reason) { super(creationMessage(semaphore, reason)); Object.defineProperty(this, "semaphoreId", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.semaphoreId = semaphore.id; } get name() { return 'SemaphoreCreationError'; } } export class SharedContext { constructor(id) { Object.defineProperty(this, "id", { enumerable: true, configurable: true, writable: true, value: id }); } createLock(id) { return new Lock(this, id); } createSemaphore(id, initialValue) { return new ManagedSemaphore(this, id, initialValue); } createUnmanagedSemaphore(id, initialValue) { return new UnmanagedSemaphore(this, id, initialValue); } async reserve(...values) { // Allow reserve() to be called before the shared worker is availabe. await protocol.available; const message = protocol.publish({ type: 20 /* RESERVE */, contextId: this.id, values, }); for await (const { data } of message.replies()) { if (data.type === 21 /* RESERVED_INDEXES */) { return data.indexes.map(index => { var _a; return (_a = values[index]) !== null && _a !== void 0 ? _a : never(); }); } } // The above loop will never actually break if the lock is not acquired. return never(); } } //# sourceMappingURL=index.js.map