From 3adfc443b7d0537ee1e92a63cafab505a6016bca Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Sat, 5 Jun 2021 11:53:31 +0100 Subject: [PATCH 01/14] feat(ShardClientUtil): add parameterList to broadcastEval --- src/sharding/ShardClientUtil.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sharding/ShardClientUtil.js b/src/sharding/ShardClientUtil.js index 044d8ab35818..2d31dab31a34 100644 --- a/src/sharding/ShardClientUtil.js +++ b/src/sharding/ShardClientUtil.js @@ -129,6 +129,7 @@ class ShardClientUtil { * Evaluates a script or function on all shards, or a given shard, in the context of the {@link Client}s. * @param {string|Function} script JavaScript to run on each shard * @param {number} [shard] Shard to run script on, all if undefined + * @param {Object} [parameterList={}] The JSON-stringifiable parameters to call the function with * @returns {Promise<*>|Promise>} Results of the script execution * @example * client.shard.broadcastEval('this.guilds.cache.size') @@ -136,10 +137,10 @@ class ShardClientUtil { * .catch(console.error); * @see {@link ShardingManager#broadcastEval} */ - broadcastEval(script, shard) { + broadcastEval(script, shard, parameterList = {}) { return new Promise((resolve, reject) => { const parent = this.parentPort || process; - script = typeof script === 'function' ? `(${script})(this)` : script; + script = typeof script === 'function' ? `(${script})(this, ${JSON.stringify(parameterList)})` : script; const listener = message => { if (!message || message._sEval !== script || message._sEvalShard !== shard) return; From 27987d581c91bf37f38b536fb8d2598dc8254967 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Sat, 5 Jun 2021 12:17:38 +0100 Subject: [PATCH 02/14] feat(ShardingManager): add parameterList to broadcastEval --- src/sharding/ShardingManager.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index bd8452c1e2c0..3cf4bdd018f5 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -228,12 +228,17 @@ class ShardingManager extends EventEmitter { /** * Evaluates a script on all shards, or a given shard, in the context of the {@link Client}s. - * @param {string} script JavaScript to run on each shard - * @param {number} [shard] Shard to run on, all if undefined + * @param {string|Function} script JavaScript to run on each shard + * @param {number} [shard] Shard to run script on, all if undefined + * @param {Object} [parameterList={}] The JSON-stringifiable parameters to call the function with * @returns {Promise<*>|Promise>} Results of the script execution */ - broadcastEval(script, shard) { - return this._performOnShards('eval', [script], shard); + broadcastEval(script, shard, parameterList = {}) { + return this._performOnShards( + 'eval', + [typeof script === 'function' ? `(${script})(this, ${JSON.stringify(parameterList)})` : script], + shard, + ); } /** From 8061d5683deac51c22dcdb0ee7076ccbc0118a45 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Sat, 5 Jun 2021 12:20:10 +0100 Subject: [PATCH 03/14] chore: update typings --- typings/index.d.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 0a11c2b64ed2..3e18634ea54c 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1697,8 +1697,8 @@ declare module 'discord.js' { public parentPort: any | null; public broadcastEval(script: string): Promise; public broadcastEval(script: string, shard: number): Promise; - public broadcastEval(fn: (client: Client) => T): Promise; - public broadcastEval(fn: (client: Client) => T, shard: number): Promise; + public broadcastEval(fn: (client: Client, parameterList: P) => T, shard: undefined, parameterList: P): Promise; + public broadcastEval(fn: (client: Client, parameterList: P) => T, shard: number, parameterList: P): Promise; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; public respawnAll(options?: { shardDelay?: number; respawnDelay?: number; timeout?: number }): Promise; @@ -1723,6 +1723,8 @@ declare module 'discord.js' { public broadcast(message: any): Promise; public broadcastEval(script: string): Promise; public broadcastEval(script: string, shard: number): Promise; + public broadcastEval(fn: (client: Client, parameterList: P) => T, shard: undefined, parameterList: P): Promise; + public broadcastEval(fn: (client: Client, parameterList: P) => T, shard: number, parameterList: P): Promise; public createShard(id: number): Shard; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; From d8718cb4d95f3af4aa410f02b147fd81374c8a61 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Sat, 5 Jun 2021 13:22:27 +0100 Subject: [PATCH 04/14] refactor(Sharding*): use BroadcastEvalOptions --- src/sharding/Shard.js | 2 +- src/sharding/ShardClientUtil.js | 11 +++++------ src/sharding/ShardingManager.js | 16 +++++++++++----- typings/index.d.ts | 21 +++++++++++++-------- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/sharding/Shard.js b/src/sharding/Shard.js index d98aaa2f0136..e8cd0a522b6c 100644 --- a/src/sharding/Shard.js +++ b/src/sharding/Shard.js @@ -348,7 +348,7 @@ class Shard extends EventEmitter { // Shard is requesting an eval broadcast if (message._sEval) { const resp = { _sEval: message._sEval, _sEvalShard: message._sEvalShard }; - this.manager.broadcastEval(message._sEval, message._sEvalShard).then( + this.manager.broadcastEval(message._sEval, { shard: message._sEvalShard }).then( results => this.send({ ...resp, _result: results }), err => this.send({ ...resp, _error: Util.makePlainError(err) }), ); diff --git a/src/sharding/ShardClientUtil.js b/src/sharding/ShardClientUtil.js index 2d31dab31a34..3aa04a0c3063 100644 --- a/src/sharding/ShardClientUtil.js +++ b/src/sharding/ShardClientUtil.js @@ -128,8 +128,7 @@ class ShardClientUtil { /** * Evaluates a script or function on all shards, or a given shard, in the context of the {@link Client}s. * @param {string|Function} script JavaScript to run on each shard - * @param {number} [shard] Shard to run script on, all if undefined - * @param {Object} [parameterList={}] The JSON-stringifiable parameters to call the function with + * @param {BroadcastEvalOptions} [options={}] The options for the broadcast * @returns {Promise<*>|Promise>} Results of the script execution * @example * client.shard.broadcastEval('this.guilds.cache.size') @@ -137,20 +136,20 @@ class ShardClientUtil { * .catch(console.error); * @see {@link ShardingManager#broadcastEval} */ - broadcastEval(script, shard, parameterList = {}) { + broadcastEval(script, options = {}) { return new Promise((resolve, reject) => { const parent = this.parentPort || process; - script = typeof script === 'function' ? `(${script})(this, ${JSON.stringify(parameterList)})` : script; + script = typeof script === 'function' ? `(${script})(this, ${JSON.stringify(options.context ?? {})})` : script; const listener = message => { - if (!message || message._sEval !== script || message._sEvalShard !== shard) return; + if (!message || message._sEval !== script || message._sEvalShard !== options.shard) return; parent.removeListener('message', listener); if (!message._error) resolve(message._result); else reject(Util.makeError(message._error)); }; parent.on('message', listener); - this.send({ _sEval: script, _sEvalShard: shard }).catch(err => { + this.send({ _sEval: script, _sEvalShard: options.shard }).catch(err => { parent.removeListener('message', listener); reject(err); }); diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index 3cf4bdd018f5..d370f681c061 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -226,18 +226,24 @@ class ShardingManager extends EventEmitter { return Promise.all(promises); } + /** + * Options for {@link ShardingManager#broadcastEval} and {@link ShardClientUtil#broadcastEval}. + * @typedef {Object} BroadcastEvalOptions + * @property {number} [shard] Shard to run script on, all if undefined + * @property {*} [context={}] The JSON-stringifiable values to call the function with + */ + /** * Evaluates a script on all shards, or a given shard, in the context of the {@link Client}s. * @param {string|Function} script JavaScript to run on each shard - * @param {number} [shard] Shard to run script on, all if undefined - * @param {Object} [parameterList={}] The JSON-stringifiable parameters to call the function with + * @param {BroadcastEvalOptions} [options={}] The options for the broadcast * @returns {Promise<*>|Promise>} Results of the script execution */ - broadcastEval(script, shard, parameterList = {}) { + broadcastEval(script, options = {}) { return this._performOnShards( 'eval', - [typeof script === 'function' ? `(${script})(this, ${JSON.stringify(parameterList)})` : script], - shard, + [typeof script === 'function' ? `(${script})(this, ${JSON.stringify(options.context ?? {})})` : script], + options.shard, ); } diff --git a/typings/index.d.ts b/typings/index.d.ts index 3e18634ea54c..9e0278273b85 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1695,10 +1695,10 @@ declare module 'discord.js' { public readonly ids: number[]; public mode: ShardingManagerMode; public parentPort: any | null; - public broadcastEval(script: string): Promise; - public broadcastEval(script: string, shard: number): Promise; - public broadcastEval(fn: (client: Client, parameterList: P) => T, shard: undefined, parameterList: P): Promise; - public broadcastEval(fn: (client: Client, parameterList: P) => T, shard: number, parameterList: P): Promise; + public broadcastEval(script: string, { shard: undefined }: BroadcastEvalOptions): Promise; + public broadcastEval(script: string, { shard: number }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, parameterList: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, parameterList: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; public respawnAll(options?: { shardDelay?: number; respawnDelay?: number; timeout?: number }): Promise; @@ -1721,10 +1721,10 @@ declare module 'discord.js' { public totalShards: number | 'auto'; public shardList: number[] | 'auto'; public broadcast(message: any): Promise; - public broadcastEval(script: string): Promise; - public broadcastEval(script: string, shard: number): Promise; - public broadcastEval(fn: (client: Client, parameterList: P) => T, shard: undefined, parameterList: P): Promise; - public broadcastEval(fn: (client: Client, parameterList: P) => T, shard: number, parameterList: P): Promise; + public broadcastEval(script: string, { shard: undefined }: BroadcastEvalOptions): Promise; + public broadcastEval(script: string, { shard: number }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, parameterList: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, parameterList: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public createShard(id: number): Shard; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; @@ -2731,6 +2731,11 @@ declare module 'discord.js' { | N | Readonly>; + interface BroadcastEvalOptions { + shard?: number; + context?: T; + } + type BufferResolvable = Buffer | string; interface ChannelCreationOverwrites { From 995811c9bfbf61df46c97af5bf68dce6ac722772 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Sat, 5 Jun 2021 13:24:13 +0100 Subject: [PATCH 05/14] chore: update typings --- typings/index.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 9e0278273b85..9892f907ea3b 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1697,8 +1697,8 @@ declare module 'discord.js' { public parentPort: any | null; public broadcastEval(script: string, { shard: undefined }: BroadcastEvalOptions): Promise; public broadcastEval(script: string, { shard: number }: BroadcastEvalOptions): Promise; - public broadcastEval(fn: (client: Client, parameterList: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; - public broadcastEval(fn: (client: Client, parameterList: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; public respawnAll(options?: { shardDelay?: number; respawnDelay?: number; timeout?: number }): Promise; @@ -1723,8 +1723,8 @@ declare module 'discord.js' { public broadcast(message: any): Promise; public broadcastEval(script: string, { shard: undefined }: BroadcastEvalOptions): Promise; public broadcastEval(script: string, { shard: number }: BroadcastEvalOptions): Promise; - public broadcastEval(fn: (client: Client, parameterList: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; - public broadcastEval(fn: (client: Client, parameterList: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public createShard(id: number): Shard; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; From 909502e4ab9dd4b29f6ae60997c94669eabc1a41 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Sat, 5 Jun 2021 13:26:04 +0100 Subject: [PATCH 06/14] docs: use serializable instead of stringifiable --- src/sharding/ShardingManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index d370f681c061..62558be02f0c 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -230,7 +230,7 @@ class ShardingManager extends EventEmitter { * Options for {@link ShardingManager#broadcastEval} and {@link ShardClientUtil#broadcastEval}. * @typedef {Object} BroadcastEvalOptions * @property {number} [shard] Shard to run script on, all if undefined - * @property {*} [context={}] The JSON-stringifiable values to call the function with + * @property {*} [context={}] The JSON-serializable values to call the script with */ /** From 4699e3af41520f244f2475ca5e8076bf57b159fc Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Sun, 6 Jun 2021 10:17:55 +0100 Subject: [PATCH 07/14] refactor: don't set broadcastEval default context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Antonio Román --- src/sharding/ShardClientUtil.js | 2 +- src/sharding/ShardingManager.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sharding/ShardClientUtil.js b/src/sharding/ShardClientUtil.js index 3aa04a0c3063..f2fb92a71683 100644 --- a/src/sharding/ShardClientUtil.js +++ b/src/sharding/ShardClientUtil.js @@ -139,7 +139,7 @@ class ShardClientUtil { broadcastEval(script, options = {}) { return new Promise((resolve, reject) => { const parent = this.parentPort || process; - script = typeof script === 'function' ? `(${script})(this, ${JSON.stringify(options.context ?? {})})` : script; + script = typeof script === 'function' ? `(${script})(this, ${JSON.stringify(options.context)})` : script; const listener = message => { if (!message || message._sEval !== script || message._sEvalShard !== options.shard) return; diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index 62558be02f0c..d1f7a4c12848 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -230,7 +230,7 @@ class ShardingManager extends EventEmitter { * Options for {@link ShardingManager#broadcastEval} and {@link ShardClientUtil#broadcastEval}. * @typedef {Object} BroadcastEvalOptions * @property {number} [shard] Shard to run script on, all if undefined - * @property {*} [context={}] The JSON-serializable values to call the script with + * @property {*} [context] The JSON-serializable values to call the script with */ /** @@ -242,7 +242,7 @@ class ShardingManager extends EventEmitter { broadcastEval(script, options = {}) { return this._performOnShards( 'eval', - [typeof script === 'function' ? `(${script})(this, ${JSON.stringify(options.context ?? {})})` : script], + [typeof script === 'function' ? `(${script})(this, ${JSON.stringify(options.context)})` : script], options.shard, ); } From dd487e49841a6e1684e4f5b483cc730d55b70885 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Sun, 6 Jun 2021 18:57:54 +0100 Subject: [PATCH 08/14] chore: fix inaccuracy in typings --- typings/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 9892f907ea3b..3d8f5fa25a46 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1698,7 +1698,7 @@ declare module 'discord.js' { public broadcastEval(script: string, { shard: undefined }: BroadcastEvalOptions): Promise; public broadcastEval(script: string, { shard: number }: BroadcastEvalOptions): Promise; public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; - public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; public respawnAll(options?: { shardDelay?: number; respawnDelay?: number; timeout?: number }): Promise; @@ -1724,7 +1724,7 @@ declare module 'discord.js' { public broadcastEval(script: string, { shard: undefined }: BroadcastEvalOptions): Promise; public broadcastEval(script: string, { shard: number }: BroadcastEvalOptions): Promise; public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; - public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public createShard(id: number): Shard; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; From 8ffa8ae6a8e38c72c510cec2f2f845208b6a044a Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Tue, 8 Jun 2021 21:14:47 +0100 Subject: [PATCH 09/14] refactor(Sharding*): remove string-based broadcastEval --- src/sharding/Shard.js | 2 +- src/sharding/ShardClientUtil.js | 6 +++--- src/sharding/ShardingManager.js | 18 ++++++++++++------ typings/index.d.ts | 4 ---- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/sharding/Shard.js b/src/sharding/Shard.js index e8cd0a522b6c..58c1fc588aed 100644 --- a/src/sharding/Shard.js +++ b/src/sharding/Shard.js @@ -348,7 +348,7 @@ class Shard extends EventEmitter { // Shard is requesting an eval broadcast if (message._sEval) { const resp = { _sEval: message._sEval, _sEvalShard: message._sEvalShard }; - this.manager.broadcastEval(message._sEval, { shard: message._sEvalShard }).then( + this.manager.broadcastEvalRaw(message._sEval, { shard: message._sEvalShard }).then( results => this.send({ ...resp, _result: results }), err => this.send({ ...resp, _error: Util.makePlainError(err) }), ); diff --git a/src/sharding/ShardClientUtil.js b/src/sharding/ShardClientUtil.js index f2fb92a71683..fc8502fe6072 100644 --- a/src/sharding/ShardClientUtil.js +++ b/src/sharding/ShardClientUtil.js @@ -127,11 +127,11 @@ class ShardClientUtil { /** * Evaluates a script or function on all shards, or a given shard, in the context of the {@link Client}s. - * @param {string|Function} script JavaScript to run on each shard + * @param {Function} script JavaScript to run on each shard * @param {BroadcastEvalOptions} [options={}] The options for the broadcast * @returns {Promise<*>|Promise>} Results of the script execution * @example - * client.shard.broadcastEval('this.guilds.cache.size') + * client.shard.broadcastEval(client => client.guilds.cache.size) * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`)) * .catch(console.error); * @see {@link ShardingManager#broadcastEval} @@ -139,7 +139,7 @@ class ShardClientUtil { broadcastEval(script, options = {}) { return new Promise((resolve, reject) => { const parent = this.parentPort || process; - script = typeof script === 'function' ? `(${script})(this, ${JSON.stringify(options.context)})` : script; + script = `(${script})(this, ${JSON.stringify(options.context)})`; const listener = message => { if (!message || message._sEval !== script || message._sEvalShard !== options.shard) return; diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index d1f7a4c12848..348fe041d33c 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -235,16 +235,22 @@ class ShardingManager extends EventEmitter { /** * Evaluates a script on all shards, or a given shard, in the context of the {@link Client}s. - * @param {string|Function} script JavaScript to run on each shard + * @param {Function} script JavaScript to run on each shard * @param {BroadcastEvalOptions} [options={}] The options for the broadcast * @returns {Promise<*>|Promise>} Results of the script execution */ broadcastEval(script, options = {}) { - return this._performOnShards( - 'eval', - [typeof script === 'function' ? `(${script})(this, ${JSON.stringify(options.context)})` : script], - options.shard, - ); + return this._broadcastEvalRaw(`(${script})(this, ${JSON.stringify(options.context)})`, options); + } + /** + * Evaluates a raw script on all shards, or a given shard, in the context of the {@link Client}s. + * @param {string} script JavaScript to run on each shard + * @param {BroadcastEvalOptions} [options={}] The options for the broadcast + * @returns {Promise<*>|Promise>} Results of the script execution + * @private + */ + _broadcastEvalRaw(script, options = {}) { + return this._performOnShards('eval', [script], options.shard); } /** diff --git a/typings/index.d.ts b/typings/index.d.ts index 3d8f5fa25a46..5d656dd43d9f 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1695,8 +1695,6 @@ declare module 'discord.js' { public readonly ids: number[]; public mode: ShardingManagerMode; public parentPort: any | null; - public broadcastEval(script: string, { shard: undefined }: BroadcastEvalOptions): Promise; - public broadcastEval(script: string, { shard: number }: BroadcastEvalOptions): Promise; public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public fetchClientValues(prop: string): Promise; @@ -1721,8 +1719,6 @@ declare module 'discord.js' { public totalShards: number | 'auto'; public shardList: number[] | 'auto'; public broadcast(message: any): Promise; - public broadcastEval(script: string, { shard: undefined }: BroadcastEvalOptions): Promise; - public broadcastEval(script: string, { shard: number }: BroadcastEvalOptions): Promise; public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public createShard(id: number): Shard; From 630150abadac05e7ef9828f5189a83a51a6e1759 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Tue, 8 Jun 2021 21:21:48 +0100 Subject: [PATCH 10/14] fix(ShardingManager): incorrect usage of _broadcastEvalRaw --- src/sharding/Shard.js | 2 +- src/sharding/ShardingManager.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sharding/Shard.js b/src/sharding/Shard.js index 58c1fc588aed..69a4fd0b245f 100644 --- a/src/sharding/Shard.js +++ b/src/sharding/Shard.js @@ -348,7 +348,7 @@ class Shard extends EventEmitter { // Shard is requesting an eval broadcast if (message._sEval) { const resp = { _sEval: message._sEval, _sEvalShard: message._sEvalShard }; - this.manager.broadcastEvalRaw(message._sEval, { shard: message._sEvalShard }).then( + this.manager._broadcastEvalRaw(message._sEval, message._sEvalShard).then( results => this.send({ ...resp, _result: results }), err => this.send({ ...resp, _error: Util.makePlainError(err) }), ); diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index 348fe041d33c..ccfab244297d 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -240,17 +240,17 @@ class ShardingManager extends EventEmitter { * @returns {Promise<*>|Promise>} Results of the script execution */ broadcastEval(script, options = {}) { - return this._broadcastEvalRaw(`(${script})(this, ${JSON.stringify(options.context)})`, options); + return this._broadcastEvalRaw(`(${script})(this, ${JSON.stringify(options.context)})`, options.shard); } /** * Evaluates a raw script on all shards, or a given shard, in the context of the {@link Client}s. * @param {string} script JavaScript to run on each shard - * @param {BroadcastEvalOptions} [options={}] The options for the broadcast + * @param {number} [shard] Shard to run script on, all if undefined * @returns {Promise<*>|Promise>} Results of the script execution * @private */ - _broadcastEvalRaw(script, options = {}) { - return this._performOnShards('eval', [script], options.shard); + _broadcastEvalRaw(script, shard) { + return this._performOnShards('eval', [script], shard); } /** From 2863313adfa9f0759032c2d8e0d7b4ed4e709355 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Tue, 8 Jun 2021 21:27:51 +0100 Subject: [PATCH 11/14] refactor(ShardingManager): remove unnecessary method --- src/sharding/Shard.js | 2 +- src/sharding/ShardingManager.js | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/sharding/Shard.js b/src/sharding/Shard.js index 69a4fd0b245f..6f840c714a33 100644 --- a/src/sharding/Shard.js +++ b/src/sharding/Shard.js @@ -348,7 +348,7 @@ class Shard extends EventEmitter { // Shard is requesting an eval broadcast if (message._sEval) { const resp = { _sEval: message._sEval, _sEvalShard: message._sEvalShard }; - this.manager._broadcastEvalRaw(message._sEval, message._sEvalShard).then( + this.manager._performOnShards('eval', [message._sEval], message._sEvalShard).then( results => this.send({ ...resp, _result: results }), err => this.send({ ...resp, _error: Util.makePlainError(err) }), ); diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index ccfab244297d..4b7cdaa677ec 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -240,17 +240,7 @@ class ShardingManager extends EventEmitter { * @returns {Promise<*>|Promise>} Results of the script execution */ broadcastEval(script, options = {}) { - return this._broadcastEvalRaw(`(${script})(this, ${JSON.stringify(options.context)})`, options.shard); - } - /** - * Evaluates a raw script on all shards, or a given shard, in the context of the {@link Client}s. - * @param {string} script JavaScript to run on each shard - * @param {number} [shard] Shard to run script on, all if undefined - * @returns {Promise<*>|Promise>} Results of the script execution - * @private - */ - _broadcastEvalRaw(script, shard) { - return this._performOnShards('eval', [script], shard); + return this._performOnShards('eval', [`(${script})(this, ${JSON.stringify(options.context)})`], options.shard); } /** From 106150c1288ec8cf6a96f41ae87c9386e6d7c2f7 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Wed, 9 Jun 2021 14:13:35 +0100 Subject: [PATCH 12/14] refactor(Sharding*): type check the eval script --- src/errors/Messages.js | 1 + src/sharding/ShardClientUtil.js | 4 ++++ src/sharding/ShardingManager.js | 1 + 3 files changed, 6 insertions(+) diff --git a/src/errors/Messages.js b/src/errors/Messages.js index f864d71eec9c..c2c7d9c92dc3 100644 --- a/src/errors/Messages.js +++ b/src/errors/Messages.js @@ -23,6 +23,7 @@ const Messages = { DISALLOWED_INTENTS: 'Privileged intent provided is not enabled or whitelisted.', SHARDING_NO_SHARDS: 'No shards have been spawned.', SHARDING_IN_PROCESS: 'Shards are still being spawned.', + SHARDING_INVALID_EVAL_BROADCAST: 'Script to evaluate must be a function', SHARDING_SHARD_NOT_FOUND: id => `Shard ${id} could not be found.`, SHARDING_ALREADY_SPAWNED: count => `Already spawned ${count} shards.`, SHARDING_PROCESS_EXISTS: id => `Shard ${id} already has an active process.`, diff --git a/src/sharding/ShardClientUtil.js b/src/sharding/ShardClientUtil.js index fc8502fe6072..b93142376817 100644 --- a/src/sharding/ShardClientUtil.js +++ b/src/sharding/ShardClientUtil.js @@ -139,6 +139,10 @@ class ShardClientUtil { broadcastEval(script, options = {}) { return new Promise((resolve, reject) => { const parent = this.parentPort || process; + if (typeof script !== 'function') { + reject(new TypeError('SHARDING_INVALID_EVAL_BROADCAST')); + return; + } script = `(${script})(this, ${JSON.stringify(options.context)})`; const listener = message => { diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index 4b7cdaa677ec..212015d3445f 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -240,6 +240,7 @@ class ShardingManager extends EventEmitter { * @returns {Promise<*>|Promise>} Results of the script execution */ broadcastEval(script, options = {}) { + if (typeof script !== 'function') throw new TypeError('SHARDING_INVALID_EVAL_BROADCAST'); return this._performOnShards('eval', [`(${script})(this, ${JSON.stringify(options.context)})`], options.shard); } From c37c9549e5c49535c88fd27e3a430bea20643fad Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Wed, 9 Jun 2021 14:18:05 +0100 Subject: [PATCH 13/14] fix(ShardingManager): return Promise rejection rather than throwing an error Co-authored-by: SpaceEEC --- src/sharding/ShardingManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index 212015d3445f..cf43553ac551 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -240,7 +240,7 @@ class ShardingManager extends EventEmitter { * @returns {Promise<*>|Promise>} Results of the script execution */ broadcastEval(script, options = {}) { - if (typeof script !== 'function') throw new TypeError('SHARDING_INVALID_EVAL_BROADCAST'); + if (typeof script !== 'function') return Promise.reject(new TypeError('SHARDING_INVALID_EVAL_BROADCAST')); return this._performOnShards('eval', [`(${script})(this, ${JSON.stringify(options.context)})`], options.shard); } From 53261009d18ea78758d3f24fc9177504af51f5c9 Mon Sep 17 00:00:00 2001 From: Amish Shah Date: Wed, 9 Jun 2021 14:28:28 +0100 Subject: [PATCH 14/14] chore: fix typings Co-authored-by: SpaceEEC --- typings/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 5d656dd43d9f..5c9e3d5de217 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1695,7 +1695,7 @@ declare module 'discord.js' { public readonly ids: number[]; public mode: ShardingManagerMode; public parentPort: any | null; - public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }?: BroadcastEvalOptions): Promise; public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; @@ -1719,7 +1719,7 @@ declare module 'discord.js' { public totalShards: number | 'auto'; public shardList: number[] | 'auto'; public broadcast(message: any): Promise; - public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }: BroadcastEvalOptions): Promise; + public broadcastEval(fn: (client: Client, context: P) => T, { shard: undefined, context: P }?: BroadcastEvalOptions): Promise; public broadcastEval(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise; public createShard(id: number): Shard; public fetchClientValues(prop: string): Promise;