diff --git a/dist/index.d.ts b/dist/index.d.ts index 92537ba..f9981bd 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -6,16 +6,18 @@ declare class WaitQueue { done: boolean; }; }; - queue: LinkedList; - listeners: LinkedList; + queue: LinkedList; + listeners: LinkedList<(err?: Error | undefined) => unknown>; get length(): number; + numWaiters(): number; empty(): void; clear(): void; clearListeners(): void; - unshift(...items: T[]): number; - push(...items: T[]): number; - shift(): Promise; - pop(): Promise; + unshift(item: T): number; + push(item: T): number; + private _remove; + shift(timeout?: number): Promise; + pop(timeout?: number): Promise; private _flush; } export = WaitQueue; diff --git a/dist/index.js b/dist/index.js index 4ef58ac..38fd695 100644 --- a/dist/index.js +++ b/dist/index.js @@ -10,26 +10,6 @@ var __values = (this && this.__values) || function(o) { }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; -var __read = (this && this.__read) || function (o, n) { - var m = typeof Symbol === "function" && o[Symbol.iterator]; - if (!m) return o; - var i = m.call(o), r, ar = [], e; - try { - while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); - } - catch (error) { e = { error: error }; } - finally { - try { - if (r && !r.done && (m = i["return"])) m.call(i); - } - finally { if (e) throw e.error; } - } - return ar; -}; -var __spread = (this && this.__spread) || function () { - for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); - return ar; -}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -38,13 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { * https://github.com/flarestart/wait-queue */ var LinkedList_1 = __importDefault(require("./libs/LinkedList")); -var nextLoop = (function () { - if (typeof setImmediate === 'function') { - return setImmediate; - } - /* istanbul ignore next */ - return function (fn) { return setTimeout(fn, 0); }; -})(); var WaitQueue = /** @class */ (function () { function WaitQueue() { this.queue = new LinkedList_1.default(); @@ -54,9 +27,12 @@ var WaitQueue = /** @class */ (function () { get: function () { return this.queue.length; }, - enumerable: true, + enumerable: false, configurable: true }); + WaitQueue.prototype.numWaiters = function () { + return this.listeners.length; + }; WaitQueue.prototype.empty = function () { this.queue = new LinkedList_1.default(); }; @@ -80,83 +56,70 @@ var WaitQueue = /** @class */ (function () { } this.listeners = new LinkedList_1.default(); }; - WaitQueue.prototype.unshift = function () { - var _a; - var items = []; - for (var _i = 0; _i < arguments.length; _i++) { - items[_i] = arguments[_i]; - } - (_a = this.queue).unshift.apply(_a, __spread(items)); + WaitQueue.prototype.unshift = function (item) { + this.queue.unshift(item); this._flush(); return this.length; }; - WaitQueue.prototype.push = function () { - var _a; - var items = []; - for (var _i = 0; _i < arguments.length; _i++) { - items[_i] = arguments[_i]; - } - (_a = this.queue).push.apply(_a, __spread(items)); + WaitQueue.prototype.push = function (item) { + this.queue.push(item); this._flush(); return this.length; }; - WaitQueue.prototype.shift = function () { + WaitQueue.prototype._remove = function (type, timeout) { var _this = this; + var fn; + switch (type) { + case 'SHIFT': + fn = this.queue.shift.bind(this.queue); + break; + case 'POP': + fn = this.queue.pop.bind(this.queue); + break; + } return new Promise(function (resolve, reject) { - if (_this.queue.length > 0) { - return resolve(_this.queue.shift()); + var self = _this; + if (self.queue.length > 0) { + return resolve(fn()); } else { - _this.listeners.push(function (err) { - if (err) { - return reject(err); + var timerId_1; + var listener_1 = self.listeners.push(function (err) { + if (timerId_1) { + clearTimeout(timerId_1); + timerId_1 = undefined; } - return resolve(_this.queue.shift()); - }); - } - }); - }; - WaitQueue.prototype.pop = function () { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.queue.length > 0) { - return resolve(_this.queue.pop()); - } - else { - _this.listeners.push(function (err) { if (err) { return reject(err); } - return resolve(_this.queue.pop()); + return resolve(fn()); }); + timerId_1 = (timeout && timeout > 0) ? + setTimeout(function () { + timerId_1 = undefined; + self.listeners.remove(listener_1); + reject(new Error("Timed Out")); + }, timeout) : undefined; } }); }; + WaitQueue.prototype.shift = function (timeout) { + return this._remove('SHIFT', timeout); + }; + WaitQueue.prototype.pop = function (timeout) { + return this._remove('POP', timeout); + }; WaitQueue.prototype._flush = function () { - if (this.queue.length > 0 && this.listeners.length > 0) { + while (this.queue.length > 0 && this.listeners.length > 0) { var listener = this.listeners.shift(); listener.call(this); - // delay next loop - nextLoop(this._flush.bind(this)); } }; return WaitQueue; }()); if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { WaitQueue.prototype[Symbol.iterator] = function () { - var node = this.queue._front; - return { - next: function () { - if (node === null) { - return { value: null, done: true }; - } - else { - var r = { value: node.item, done: false }; - node = node._next; - return r; - } - }, - }; + return this.queue[Symbol.iterator](); }; } module.exports = WaitQueue; diff --git a/dist/libs/LinkedList.d.ts b/dist/libs/LinkedList.d.ts index 5773c6d..c3b6ce3 100644 --- a/dist/libs/LinkedList.d.ts +++ b/dist/libs/LinkedList.d.ts @@ -1,23 +1,25 @@ -interface Node { - _next: Node | null; - _prev: Node | null; - item: any; +interface Node { + _next: Node; + _prev: Node; + _removed?: boolean; + item: T; } -declare class LinkedList { +declare class LinkedList { [Symbol.iterator]: () => { next: () => { - value: any; + value: T; done: boolean; }; }; _length: number; - _front: Node | null; - _end: Node | null; - get length(): number; + _head: Node; + constructor(); empty(): void; - push(...items: any[]): number; - shift(): any; - unshift(...items: any[]): number; - pop(): any; + get length(): number; + push(item: T): Node; + unshift(item: T): Node; + pop(): T; + shift(): T; + remove(node: Node): void; } export default LinkedList; diff --git a/dist/libs/LinkedList.js b/dist/libs/LinkedList.js index 88eec0d..9d25812 100644 --- a/dist/libs/LinkedList.js +++ b/dist/libs/LinkedList.js @@ -1,115 +1,103 @@ "use strict"; +/* + * Javascript WaitQueue Object in ES5 + * https://github.com/flarestart/wait-queue-es5 + */ Object.defineProperty(exports, "__esModule", { value: true }); function createNode(item) { - return { + var tmp = { _next: null, _prev: null, item: item }; + tmp._next = tmp; + tmp._prev = tmp; + return tmp; } var LinkedList = /** @class */ (function () { + /* same as empty */ function LinkedList() { this._length = 0; - this._front = null; - this._end = null; + this._head = createNode(); + this._length = 0; } + /* same as constructor */ + LinkedList.prototype.empty = function () { + this._head = createNode(); + this._length = 0; + }; Object.defineProperty(LinkedList.prototype, "length", { get: function () { return this._length; }, - enumerable: true, + enumerable: false, configurable: true }); - LinkedList.prototype.empty = function () { - this._length = 0; - this._front = null; - this._end = null; - }; - LinkedList.prototype.push = function () { - var _this = this; - var items = []; - for (var _i = 0; _i < arguments.length; _i++) { - items[_i] = arguments[_i]; + LinkedList.prototype.push = function (item) { + var node = createNode(item); + node._next = this._head; + node._prev = this._head._prev; + this._head._prev._next = node; + this._head._prev = node; + if (this._head._next == this._head) { + this._head._next = node; } - items.forEach(function (item) { - var node = createNode(item); - if (_this._front && _this._end) { - _this._end._next = node; - node._prev = _this._end; - _this._end = node; - } - else { - _this._front = node; - _this._end = node; - } - _this._length++; - }); - return this._length; + this._length++; + return node; }; - LinkedList.prototype.shift = function () { - var item = this._front; - if (item === null) { - return null; - } - if (item._next != null) { - this._front = item._next; - this._front._prev = null; + LinkedList.prototype.unshift = function (item) { + var node = createNode(item); + node._prev = this._head; + node._next = this._head._next; + this._head._next._prev = node; + this._head._next = node; + if (this._head._prev == this._head) { + this._head._prev = node; } - else { - this._front = null; - this._end = null; + this._length++; + return node; + }; + LinkedList.prototype.pop = function () { + if (this._head._prev == this._head) { + throw new Error("empty list"); } - item._next = null; + var item = this._head._prev; + this._head._prev = item._prev; + item._prev._next = this._head; + item._removed = true; this._length--; return item.item; }; - LinkedList.prototype.unshift = function () { - var _this = this; - var items = []; - for (var _i = 0; _i < arguments.length; _i++) { - items[_i] = arguments[_i]; + LinkedList.prototype.shift = function () { + if (this._head._next == this._head) { + throw new Error("empty list"); } - items.forEach(function (item) { - var node = createNode(item); - if (_this._front === null) { - _this._front = node; - _this._end = node; - } - else { - node._next = _this._front; - _this._front._prev = node; - _this._front = node; - } - _this._length++; - }); - return this._length; + var item = this._head._next; + this._head._next = item._next; + item._next._prev = this._head; + item._removed = true; + this._length--; + return item.item; }; - LinkedList.prototype.pop = function () { - var item = this._end; - if (item === null) { - return null; - } - if (item._prev != null) { - this._end = item._prev; - this._end._next = null; - } - else { - this._front = null; - this._end = null; + LinkedList.prototype.remove = function (node) { + if (node._removed) { + return; } + node._prev._next = node._next; + node._next._prev = node._prev; + node._removed = true; this._length--; - item._prev = null; - return item.item; }; return LinkedList; }()); /* istanbul ignore next */ if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { LinkedList.prototype[Symbol.iterator] = function () { - var node = this._front; + var head = this._head; + var node = this._head._next; return { next: function () { - if (node === null) { + if (node === head) { return { value: null, done: true }; } var r = { value: node.item, done: false }; diff --git a/src/index.ts b/src/index.ts index 90c46e1..4534389 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,98 +4,106 @@ */ import LinkedList from './libs/LinkedList'; -const nextLoop = (() => { - if (typeof setImmediate === 'function') { - return setImmediate; - } - /* istanbul ignore next */ - return (fn: (...args: any[]) => void) => setTimeout(fn, 0); -})(); - class WaitQueue { [Symbol.iterator]: () => { next: () => { value: any; done: boolean } }; - queue = new LinkedList(); - listeners = new LinkedList(); + queue = new LinkedList(); + listeners = new LinkedList<(err?: Error) => unknown>(); get length(): number { return this.queue.length; } + + numWaiters(): number { + return this.listeners.length; + } + empty(): void { this.queue = new LinkedList(); } clear(): void { this.queue = new LinkedList(); } + clearListeners(): void { for (const listener of this.listeners) { listener(new Error('Clear Listeners')); } this.listeners = new LinkedList(); } - unshift(...items: T[]): number { - this.queue.unshift(...items); + + unshift(item: T): number { + this.queue.unshift(item); this._flush(); return this.length; } - push(...items: T[]): number { - this.queue.push(...items); + + push(item: T): number { + this.queue.push(item); this._flush(); return this.length; } - shift(): Promise { + + private _remove(type: "SHIFT" | "POP", timeout?: number): Promise { + let fn: () => any; + switch (type) { + case 'SHIFT': + fn = this.queue.shift.bind(this.queue); + break; + case 'POP': + fn = this.queue.pop.bind(this.queue); + break; + } + return new Promise((resolve, reject) => { - if (this.queue.length > 0) { - return resolve(this.queue.shift()); + const self = this; + + if (self.queue.length > 0) { + return resolve(fn()); } else { - this.listeners.push((err: Error) => { - if (err) { - return reject(err); + let timerId: NodeJS.Timeout | undefined; + + const listener = self.listeners.push((err?: Error) => { + if (timerId) { + clearTimeout(timerId); + timerId = undefined; } - return resolve(this.queue.shift()); - }); - } - }); - } - pop(): Promise { - return new Promise((resolve, reject) => { - if (this.queue.length > 0) { - return resolve(this.queue.pop()); - } else { - this.listeners.push((err: Error) => { + if (err) { return reject(err); } - return resolve(this.queue.pop()); + + return resolve(fn()); }); + + timerId = (timeout && timeout > 0) ? + setTimeout(() => { + timerId = undefined; + self.listeners.remove(listener); + reject(new Error("Timed Out")); + }, timeout) : undefined; } }); } + shift(timeout?: number): Promise { + return this._remove('SHIFT', timeout); + } + pop(timeout?: number): Promise { + return this._remove('POP', timeout); + } + private _flush(): void { - if (this.queue.length > 0 && this.listeners.length > 0) { + while (this.queue.length > 0 && this.listeners.length > 0) { const listener = this.listeners.shift(); listener.call(this); - // delay next loop - nextLoop(this._flush.bind(this)); } } } if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { WaitQueue.prototype[Symbol.iterator] = function () { - let node = this.queue._front; - return { - next() { - if (node === null) { - return { value: null, done: true }; - } else { - const r = { value: node.item, done: false }; - node = node._next; - return r; - } - }, - }; + return this.queue[Symbol.iterator](); }; } diff --git a/src/libs/LinkedList.ts b/src/libs/LinkedList.ts index 1921f90..3118ebc 100644 --- a/src/libs/LinkedList.ts +++ b/src/libs/LinkedList.ts @@ -2,106 +2,133 @@ * Javascript WaitQueue Object in ES5 * https://github.com/flarestart/wait-queue-es5 */ -interface Node { - _next: Node | null; - _prev: Node | null; - item: any; + +interface Node { + _next: Node; + _prev: Node; + _removed?: boolean; + item: T } -function createNode(item: any): Node { - return { +function createNode(item?: T): Node { + const tmp : { + _next: Node | null; + _prev: Node | null; + item?: T +} = { _next: null, _prev: null, - item - }; + item: item + } + + tmp._next = tmp as Node; + tmp._prev = tmp as Node; + + return tmp as Node; } -class LinkedList { - [Symbol.iterator]: () => { next: () => { value: any; done: boolean } }; +class LinkedList { + [Symbol.iterator]: () => { next: () => { value: T; done: boolean } }; _length = 0; - _front: Node | null = null; - _end: Node | null = null; + _head: Node; - get length() { - return this._length; + /* same as empty */ + constructor() { + this._head = createNode(); + this._length = 0; } + + /* same as constructor */ empty() { + this._head = createNode(); this._length = 0; - this._front = null; - this._end = null; } - push(...items: any[]) { - items.forEach(item => { - const node = createNode(item); - if (this._front && this._end) { - this._end._next = node; - node._prev = this._end; - this._end = node; - } else { - this._front = node; - this._end = node; - } - this._length++; - }); + + get length() { return this._length; } - shift() { - const item = this._front; - if (item === null) { - return null; - } - if (item._next != null) { - this._front = item._next; - this._front._prev = null; - } else { - this._front = null; - this._end = null; + + push(item: T) { + const node = createNode(item); + + node._next = this._head; + node._prev = this._head._prev; + this._head._prev._next = node; + this._head._prev = node; + if (this._head._next == this._head) { + this._head._next = node; } - item._next = null; - this._length--; - return item.item; + this._length++; + + return node; } - unshift(...items: any[]) { - items.forEach(item => { - const node = createNode(item); - if (this._front === null) { - this._front = node; - this._end = node; - } else { - node._next = this._front; - this._front._prev = node; - this._front = node; - } - this._length++; - }); - return this._length; + + unshift(item: T) { + const node = createNode(item); + + node._prev = this._head; + node._next = this._head._next; + this._head._next._prev = node; + this._head._next = node; + if (this._head._prev == this._head) { + this._head._prev = node; + } + this._length++; + + return node; } + pop() { - const item = this._end; - if (item === null) { - return null; + if (this._head._prev == this._head) { + throw new Error("empty list") + } + + const item = this._head._prev; + this._head._prev = item._prev; + item._prev._next = this._head + + item._removed = true; + this._length--; + + return item.item + } + + shift() { + if (this._head._next == this._head) { + throw new Error("empty list") } - if (item._prev != null) { - this._end = item._prev; - this._end._next = null; - } else { - this._front = null; - this._end = null; + + const item = this._head._next; + this._head._next = item._next + item._next._prev = this._head; + + item._removed = true; + this._length--; + + return item.item + } + + remove(node: Node) { + if (node._removed) { + return; } + node._prev._next = node._next; + node._next._prev = node._prev; + + node._removed = true; this._length--; - item._prev = null; - return item.item; } } /* istanbul ignore next */ if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { LinkedList.prototype[Symbol.iterator] = function() { - let node = this._front; + const head = this._head; + let node = this._head._next; return { next() { - if (node === null) { + if (node === head) { return { value: null, done: true }; } const r = { value: node.item, done: false }; diff --git a/tests/LinkedList.test.ts b/tests/LinkedList.test.ts index 453999f..fd29adb 100644 --- a/tests/LinkedList.test.ts +++ b/tests/LinkedList.test.ts @@ -3,16 +3,19 @@ import LinkedList from '../src/libs/LinkedList'; describe('LinkedList', function() { const ll = new LinkedList(); + beforeEach(function() { // clear waitqueue ll.empty(); }); + it('length should equal to 10', function() { for (let n = 0; n < 10; n++) { ll.push(n); } assert.deepStrictEqual(10, ll.length); }); + it('set length will throw an error in strict mode', function() { assert.throws(function() { 'use strict'; @@ -21,61 +24,62 @@ describe('LinkedList', function() { obj.length = 10; }, /Cannot set property/); }); + it('empty()', function() { ll.push(1); ll.empty(); - assert.strictEqual(null, ll._front); - assert.strictEqual(null, ll._end); + assert.strictEqual(ll._head._next, ll._head); + assert.strictEqual(ll._head._prev, ll._head); assert.strictEqual(0, ll.length); }); + it('push 10 times', function() { for (let n = 0; n < 10; n++) { ll.push(n); } - assert.deepStrictEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], Array.from(ll)); + assert.deepStrictEqual(Array.from(ll), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); }); + it('push() should be sequence', function() { for (let n = 0; n < 5; n++) { ll.push(n); } - assert.deepStrictEqual([0, 1, 2, 3, 4], Array.from(ll)); - }); - it('push() can receive multi args', function() { - ll.push(0, 1, 2, 3, 4); - assert.deepStrictEqual([0, 1, 2, 3, 4], Array.from(ll)); - }); - it('unshift() should return queue length', function() { - assert.strictEqual(1, ll.unshift(1)); + assert.deepStrictEqual(Array.from(ll), [0, 1, 2, 3, 4]); }); + it('unshift() should be reverse', function() { for (let n = 0; n < 5; n++) { ll.unshift(n); } - assert.deepStrictEqual([4, 3, 2, 1, 0], Array.from(ll)); - }); - it('unshift() can receive multi args', function() { - ll.unshift(0, 1, 2, 3, 4); - assert.deepStrictEqual([4, 3, 2, 1, 0], Array.from(ll)); + assert.deepStrictEqual(Array.from(ll), [4, 3, 2, 1, 0]); }); - it('shift() should return null', function() { - const ret = ll.shift(); - assert.equal(ret, null); + it('shift() should return error', function() { + try { + ll.shift(); + assert.equal(true, false); + } catch (err) { + assert.deepStrictEqual(err, new Error("empty list")); + } }); - it('pop() should return null', function() { - const ret = ll.pop(); - assert.equal(ret, null); + it('pop() should return error', function() { + try { + ll.pop(); + assert.equal(true, false); + } catch (err) { + assert.deepStrictEqual(err, new Error("empty list")); + } }); - it('shift() should return null', function() { + it('shift() should return value', function() { ll.push('step1'); ll.push('step2'); const ret = ll.shift(); assert.equal(ret, 'step1'); }); - it('pop() should return null', function() { + it('pop() should return value', function() { ll.push('step1'); ll.push('step2'); const ret = ll.pop(); diff --git a/tests/WaitQueue.test.ts b/tests/WaitQueue.test.ts index f450f0e..b452970 100644 --- a/tests/WaitQueue.test.ts +++ b/tests/WaitQueue.test.ts @@ -3,17 +3,20 @@ import WaitQueue from '../src/index'; describe('Methods of WaitQueue', function() { const wq = new WaitQueue(); + beforeEach(function() { // clear waitqueue wq.clear(); wq.clearListeners(); }); + it('length is equal to 10', function() { for (let n = 0; n < 10; n++) { wq.push(n); } assert.deepStrictEqual(10, wq.length); }); + it('set length will throw an error in strict mode', function() { assert.throws(function() { 'use strict'; @@ -22,11 +25,13 @@ describe('Methods of WaitQueue', function() { obj.length = 10; }, /Cannot set property/); }); + it('empty()', function() { wq.push(1); wq.empty(); assert.deepStrictEqual([], Array.from(wq)); }); + it('clearListeners() will send error to wait listeners', function(done) { const w = new WaitQueue(); let num = 0; @@ -43,36 +48,30 @@ describe('Methods of WaitQueue', function() { w.pop().catch(handler); w.clearListeners(); }); + it('push() should return queue length', function() { assert.strictEqual(1, wq.push(1)); }); + it('push() should be sequence', function() { for (let n = 0; n < 5; n++) { wq.push(n); } assert.deepStrictEqual([0, 1, 2, 3, 4], Array.from(wq)); }); - it('push() can receive multi args', function() { - wq.push(0, 1, 2, 3, 4); - assert.deepStrictEqual([0, 1, 2, 3, 4], Array.from(wq)); - }); - it('unshift() should return queue length', function() { - assert.strictEqual(1, wq.unshift(1)); - }); + it('unshift() should be reverse', function() { for (let n = 0; n < 5; n++) { wq.unshift(n); } assert.deepStrictEqual([4, 3, 2, 1, 0], Array.from(wq)); }); - it('unshift() can receive multi args', function() { - wq.unshift(0, 1, 2, 3, 4); - assert.deepStrictEqual([4, 3, 2, 1, 0], Array.from(wq)); - }); + it('shift() should return a promise', function() { wq.push(1); assert.ok(wq.shift() instanceof Promise); }); + it('pop() should return a promise', function() { wq.push(1); assert.ok(wq.pop() instanceof Promise); @@ -100,6 +99,56 @@ describe('Methods of WaitQueue', function() { assert.equal(obj.name, 'test'); }); + it('multiple shifts are in correct order', async function() { + for (let i=0; i < 5; i++) { + wq.push(i); + } + for(let i=0; i < 5; i++) { + assert.strictEqual(await wq.shift(), i) + } + }) + + it('multiple pops are in correct order', async function() { + for (let i=0; i < 5; i++) { + wq.push(i); + } + for(let i=4; i >= 0; i--) { + assert.strictEqual(await wq.pop(), i) + } + }) + + it('pop(timeout) should error out', async function() { + assert.rejects(wq.pop(1)) + }); + + it('timed out listener, should try next listener', async function() { + const p1 = wq.pop(1); + const p2 = wq.pop(); + setTimeout(() => wq.push(1), 10); + try { + await p1; + assert.strictEqual(true, false); + } catch (err) { + assert.deepStrictEqual(err, new Error("Timed Out")) + } + assert.strictEqual(await p2, 1); + }) + + it('count number of waiting promises', async function() { + const p1 = wq.pop(1); + const p2 = wq.pop(); + wq.pop().catch(() => {}); // this will be cleared, so ignore error + + assert.strictEqual(wq.numWaiters(), 3); + setTimeout(() => assert.strictEqual(wq.numWaiters(), 2), 10); + setTimeout(() => wq.push(1), 20); + assert.rejects(p1); + assert.strictEqual(await p2, 1); + assert.strictEqual(wq.numWaiters(), 1) + wq.clearListeners(); + assert.strictEqual(wq.numWaiters(), 0); + }) + it('Iterator for(... of ...)', function() { for (let n = 0; n < 5; n++) { wq.push(n); diff --git a/tests/require.test.ts b/tests/require.test.ts index e136e8d..9f562bd 100644 --- a/tests/require.test.ts +++ b/tests/require.test.ts @@ -5,6 +5,7 @@ describe('require WaitQueue', function () { it('expect WaitQueue to be a function', function () { expect(typeof WaitQueue).toEqual('function'); }); + it('new WaitQueue', function () { expect(new WaitQueue()).toBeInstanceOf(WaitQueue); });