| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,83 +1,91 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | - const common = require('../common'); | ||
| 3 | + require('../common'); | ||
| 4 | 4 | const { ok, strictEqual } = require('assert'); | |
| 5 | - const { setImmediate: pause } = require('timers/promises'); | ||
| 5 | + const { setImmediate: sleep } = require('timers/promises'); | ||
| 6 | 6 | const { | |
| 7 | 7 | transferableAbortSignal, | |
| 8 | 8 | transferableAbortController, | |
| 9 | 9 | } = require('util'); | |
| 10 | + const { | ||
| 11 | + test, | ||
| 12 | + mock, | ||
| 13 | + } = require('node:test'); | ||
| 10 | 14 | ||
| 11 | - | ||
| 12 | - function deferred() { | ||
| 13 | - let res; | ||
| 14 | - const promise = new Promise((resolve) => res = resolve); | ||
| 15 | - return { res, promise }; | ||
| 16 | - } | ||
| 17 | - | ||
| 18 | - (async () => { | ||
| 15 | + test('Can create a transferable abort controller', async () => { | ||
| 19 | 16 | const ac = transferableAbortController(); | |
| 20 | 17 | const mc = new MessageChannel(); | |
| 21 | 18 | ||
| 22 | - const deferred1 = deferred(); | ||
| 23 | - const deferred2 = deferred(); | ||
| 24 | - const resolvers = [deferred1, deferred2]; | ||
| 19 | + const setup1 = Promise.withResolvers(); | ||
| 20 | + const setup2 = Promise.withResolvers(); | ||
| 21 | + const setupResolvers = [setup1, setup2]; | ||
| 25 | 22 | ||
| 26 | - mc.port1.onmessage = common.mustCall(({ data }) => { | ||
| 27 | - data.addEventListener('abort', common.mustCall(() => { | ||
| 23 | + const abort1 = Promise.withResolvers(); | ||
| 24 | + const abort2 = Promise.withResolvers(); | ||
| 25 | + const abort3 = Promise.withResolvers(); | ||
| 26 | + const abortResolvers = [abort1, abort2, abort3]; | ||
| 27 | + | ||
| 28 | + mc.port1.onmessage = ({ data }) => { | ||
| 29 | + data.addEventListener('abort', () => { | ||
| 28 | 30 | strictEqual(data.reason, 'boom'); | |
| 29 | - })); | ||
| 30 | - resolvers.shift().res(); | ||
| 31 | - }, 2); | ||
| 31 | + abortResolvers.shift().resolve(); | ||
| 32 | + }); | ||
| 33 | + setupResolvers.shift().resolve(); | ||
| 34 | + }; | ||
| 32 | 35 | ||
| 33 | 36 | mc.port2.postMessage(ac.signal, [ac.signal]); | |
| 34 | 37 | ||
| 35 | 38 | // Can be cloned/transferd multiple times and they all still work | |
| 36 | 39 | mc.port2.postMessage(ac.signal, [ac.signal]); | |
| 37 | 40 | ||
| 38 | - mc.port2.close(); | ||
| 39 | - | ||
| 40 | 41 | // Although we're using transfer semantics, the local AbortSignal | |
| 41 | 42 | // is still usable locally. | |
| 42 | - ac.signal.addEventListener('abort', common.mustCall(() => { | ||
| 43 | + ac.signal.addEventListener('abort', () => { | ||
| 43 | 44 | strictEqual(ac.signal.reason, 'boom'); | |
| 44 | - })); | ||
| 45 | + abortResolvers.shift().resolve(); | ||
| 46 | + }); | ||
| 45 | 47 | ||
| 46 | - await Promise.all([ deferred1.promise, deferred2.promise ]); | ||
| 48 | + await Promise.all([ setup1.promise, setup2.promise ]); | ||
| 47 | 49 | ||
| 48 | 50 | ac.abort('boom'); | |
| 49 | 51 | ||
| 50 | - // Because the postMessage used by the underlying AbortSignal | ||
| 51 | - // takes at least one turn of the event loop to be processed, | ||
| 52 | - // and because it is unref'd, it won't, by itself, keep the | ||
| 53 | - // event loop open long enough for the test to complete, so | ||
| 54 | - // we schedule two back to back turns of the event to ensure | ||
| 55 | - // the loop runs long enough for the test to complete. | ||
| 56 | - await pause(); | ||
| 57 | - await pause(); | ||
| 52 | + await Promise.all([ abort1.promise, abort2.promise, abort3.promise ]); | ||
| 53 | + | ||
| 54 | + mc.port2.close(); | ||
| 58 | 55 | ||
| 59 | - })().then(common.mustCall()); | ||
| 56 | + }); | ||
| 60 | 57 | ||
| 61 | - { | ||
| 58 | + test('Can create a transferable abort signal', async () => { | ||
| 62 | 59 | const signal = transferableAbortSignal(AbortSignal.abort('boom')); | |
| 63 | 60 | ok(signal.aborted); | |
| 64 | 61 | strictEqual(signal.reason, 'boom'); | |
| 65 | 62 | const mc = new MessageChannel(); | |
| 66 | - mc.port1.onmessage = common.mustCall(({ data }) => { | ||
| 63 | + const { promise, resolve } = Promise.withResolvers(); | ||
| 64 | + mc.port1.onmessage = ({ data }) => { | ||
| 67 | 65 | ok(data instanceof AbortSignal); | |
| 68 | 66 | ok(data.aborted); | |
| 69 | 67 | strictEqual(data.reason, 'boom'); | |
| 70 | - mc.port1.close(); | ||
| 71 | - }); | ||
| 68 | + resolve(); | ||
| 69 | + }; | ||
| 72 | 70 | mc.port2.postMessage(signal, [signal]); | |
| 73 | - } | ||
| 71 | + await promise; | ||
| 72 | + mc.port1.close(); | ||
| 73 | + }); | ||
| 74 | 74 | ||
| 75 | - { | ||
| 76 | - // The cloned AbortSignal does not keep the event loop open | ||
| 77 | - // waiting for the abort to be triggered. | ||
| 75 | + test('A cloned AbortSignal does not keep the event loop open', async () => { | ||
| 78 | 76 | const ac = transferableAbortController(); | |
| 79 | 77 | const mc = new MessageChannel(); | |
| 80 | - mc.port1.onmessage = common.mustCall(); | ||
| 78 | + const fn = mock.fn(); | ||
| 79 | + mc.port1.onmessage = fn; | ||
| 81 | 80 | mc.port2.postMessage(ac.signal, [ac.signal]); | |
| 81 | + // Because the postMessage used by the underlying AbortSignal | ||
| 82 | + // takes at least one turn of the event loop to be processed, | ||
| 83 | + // and because it is unref'd, it won't, by itself, keep the | ||
| 84 | + // event loop open long enough for the test to complete, so | ||
| 85 | + // we schedule two back to back turns of the event to ensure | ||
| 86 | + // the loop runs long enough for the test to complete. | ||
| 87 | + await sleep(); | ||
| 88 | + await sleep(); | ||
| 89 | + strictEqual(fn.mock.calls.length, 1); | ||
| 82 | 90 | mc.port2.close(); | |
| 83 | - } | ||
| 91 | + }); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments