1 line
8.1 KiB
Plaintext
1 line
8.1 KiB
Plaintext
{"version":3,"file":"Runner.mjs","sources":["../src/Runner.ts"],"sourcesContent":["export type RunnerListenerCallback<ARG extends unknown[] = any[]> = (...args: ARG) => unknown;\n\ntype RunnerItemValid<T extends string, ARG extends unknown[] = any[]> =\n { [K in T]: RunnerListenerCallback<ARG> | unknown };\n\ntype RunnerItemAny = Record<string, unknown>;\n\ntype RunnerItemEmpty = Record<string, never>;\n\nexport type RunnerItem<T = string, ARG extends unknown[] = any[]> =\n T extends string ?\n RunnerItemValid<T, ARG> & RunnerItemAny | RunnerItemEmpty :\n unknown;\n\n/**\n * A Runner is a highly performant and simple alternative to signals. Best used in situations\n * where events are dispatched to many objects at high frequency (say every frame!)\n *\n * Like a signal:\n *\n * ```js\n * import { Runner } from '@pixi/runner';\n *\n * const myObject = {\n * loaded: new Runner('loaded'),\n * };\n *\n * const listener = {\n * loaded: function() {\n * // Do something when loaded\n * }\n * };\n *\n * myObject.loaded.add(listener);\n *\n * myObject.loaded.emit();\n * ```\n *\n * Or for handling calling the same function on many items:\n *\n * ```js\n * import { Runner } from '@pixi/runner';\n *\n * const myGame = {\n * update: new Runner('update'),\n * };\n *\n * const gameObject = {\n * update: function(time) {\n * // Update my gamey state\n * },\n * };\n *\n * myGame.update.add(gameObject);\n *\n * myGame.update.emit(time);\n * ```\n *\n * Type safety:\n *\n * ```ts\n *\n * import { Runner } from '@pixi/runner';\n *\n * let runner: Runner<'update', [number]>;\n *\n * // This won't work because the function name 'update' is expected\n * runner = new Runner('destroy');\n *\n * // This is fine\n * runner = new Runner('update');\n *\n * // This won't work because the number is expected\n * runner.emit(\"10\");\n *\n * // This is fine\n * runner.emit(10);\n *\n * // This won't work because provided object does not contain 'update' key\n * runner.add({\n * destroy: function() {\n * // Destroy the game\n * },\n * });\n *\n * // This is fine\n * runner.add({\n * update: function(time) {\n * // Update my gamey state\n * },\n * destroy: function() {\n * // Destroy the game\n * },\n * });\n *\n * ```\n * @template T - The event type.\n * @template ARG - The argument types for the event handler functions.\n * @memberof PIXI\n */\nexport class Runner<T = any, ARG extends unknown[] = any[]>\n{\n public items: any[];\n private _name: T;\n private _aliasCount: number;\n\n /**\n * @param {string} name - The function name that will be executed on the listeners added to this Runner.\n */\n constructor(name: T)\n {\n this.items = [];\n this._name = name;\n this._aliasCount = 0;\n }\n\n /* eslint-disable jsdoc/require-param, jsdoc/check-param-names */\n /**\n * Dispatch/Broadcast Runner to all listeners added to the queue.\n * @param {...any} params - (optional) parameters to pass to each listener\n */\n /* eslint-enable jsdoc/require-param, jsdoc/check-param-names */\n public emit(a0?: ARG[0], a1?: ARG[1], a2?: ARG[2], a3?: ARG[3],\n a4?: ARG[4], a5?: ARG[5], a6?: ARG[6], a7?: ARG[7]): this\n {\n if (arguments.length > 8)\n {\n throw new Error('max arguments reached');\n }\n\n const { name, items } = this;\n\n this._aliasCount++;\n\n for (let i = 0, len = items.length; i < len; i++)\n {\n items[i][name](a0, a1, a2, a3, a4, a5, a6, a7);\n }\n\n if (items === this.items)\n {\n this._aliasCount--;\n }\n\n return this;\n }\n\n private ensureNonAliasedItems(): void\n {\n if (this._aliasCount > 0 && this.items.length > 1)\n {\n this._aliasCount = 0;\n this.items = this.items.slice(0);\n }\n }\n\n /**\n * Add a listener to the Runner\n *\n * Runners do not need to have scope or functions passed to them.\n * All that is required is to pass the listening object and ensure that it has contains a function that has the same name\n * as the name provided to the Runner when it was created.\n *\n * E.g. A listener passed to this Runner will require a 'complete' function.\n *\n * ```js\n * import { Runner } from '@pixi/runner';\n *\n * const complete = new Runner('complete');\n * ```\n *\n * The scope used will be the object itself.\n * @param {any} item - The object that will be listening.\n */\n public add(item: RunnerItem<T, ARG>): this\n {\n if ((item as any)[this._name])\n {\n this.ensureNonAliasedItems();\n this.remove(item);\n this.items.push(item);\n }\n\n return this;\n }\n\n /**\n * Remove a single listener from the dispatch queue.\n * @param {any} item - The listener that you would like to remove.\n */\n public remove(item: RunnerItem<T, ARG>): this\n {\n const index = this.items.indexOf(item);\n\n if (index !== -1)\n {\n this.ensureNonAliasedItems();\n this.items.splice(index, 1);\n }\n\n return this;\n }\n\n /**\n * Check to see if the listener is already in the Runner\n * @param {any} item - The listener that you would like to check.\n */\n public contains(item: RunnerItem<T, ARG>): boolean\n {\n return this.items.includes(item);\n }\n\n /** Remove all listeners from the Runner */\n public removeAll(): this\n {\n this.ensureNonAliasedItems();\n this.items.length = 0;\n\n return this;\n }\n\n /** Remove all references, don't use after this. */\n public destroy(): void\n {\n this.removeAll();\n this.items.length = 0;\n this._name = '' as T;\n }\n\n /**\n * `true` if there are no this Runner contains no listeners\n * @readonly\n */\n public get empty(): boolean\n {\n return this.items.length === 0;\n }\n\n /**\n * The name of the runner.\n * @type {string}\n */\n public get name(): T\n {\n return this._name;\n }\n}\n\nObject.defineProperties(Runner.prototype, {\n /**\n * Alias for `emit`\n * @memberof PIXI.Runner#\n * @method dispatch\n * @see PIXI.Runner#emit\n */\n dispatch: { value: Runner.prototype.emit },\n /**\n * Alias for `emit`\n * @memberof PIXI.Runner#\n * @method run\n * @see PIXI.Runner#emit\n */\n run: { value: Runner.prototype.emit },\n});\n"],"names":[],"mappings":"AAoGO,MAAM,OACb;AAAA;AAAA;AAAA;AAAA,EAQI,YAAY,MACZ;AACI,SAAK,QAAQ,CAAA,GACb,KAAK,QAAQ,MACb,KAAK,cAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,KAAK,IAAa,IAAa,IAAa,IAC/C,IAAa,IAAa,IAAa,IAC3C;AACI,QAAI,UAAU,SAAS;AAEb,YAAA,IAAI,MAAM,uBAAuB;AAGrC,UAAA,EAAE,MAAM,MAAU,IAAA;AAEnB,SAAA;AAEL,aAAS,IAAI,GAAG,MAAM,MAAM,QAAQ,IAAI,KAAK;AAEnC,YAAA,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAGjD,WAAI,UAAU,KAAK,SAEf,KAAK,eAGF;AAAA,EACX;AAAA,EAEQ,wBACR;AACQ,SAAK,cAAc,KAAK,KAAK,MAAM,SAAS,MAE5C,KAAK,cAAc,GACnB,KAAK,QAAQ,KAAK,MAAM,MAAM,CAAC;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBO,IAAI,MACX;AACI,WAAK,KAAa,KAAK,KAAK,MAExB,KAAK,sBAAsB,GAC3B,KAAK,OAAO,IAAI,GAChB,KAAK,MAAM,KAAK,IAAI,IAGjB;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,OAAO,MACd;AACI,UAAM,QAAQ,KAAK,MAAM,QAAQ,IAAI;AAEjC,WAAA,UAAU,OAEV,KAAK,sBAAsB,GAC3B,KAAK,MAAM,OAAO,OAAO,CAAC,IAGvB;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,SAAS,MAChB;AACW,WAAA,KAAK,MAAM,SAAS,IAAI;AAAA,EACnC;AAAA;AAAA,EAGO,YACP;AACI,WAAA,KAAK,yBACL,KAAK,MAAM,SAAS,GAEb;AAAA,EACX;AAAA;AAAA,EAGO,UACP;AACI,SAAK,aACL,KAAK,MAAM,SAAS,GACpB,KAAK,QAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAW,QACX;AACW,WAAA,KAAK,MAAM,WAAW;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAW,OACX;AACI,WAAO,KAAK;AAAA,EAChB;AACJ;AAEA,OAAO,iBAAiB,OAAO,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtC,UAAU,EAAE,OAAO,OAAO,UAAU,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOzC,KAAK,EAAE,OAAO,OAAO,UAAU,KAAK;AACxC,CAAC;"} |