From b4d21bb2b7a12de53d77090d73d4b381a9ce15a9 Mon Sep 17 00:00:00 2001 From: Jelle De Loecker Date: Fri, 22 Mar 2024 14:52:01 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20some=20`Swift`=20methods?= =?UTF-8?q?=20not=20using=20the=20correct=20schedulers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + lib/blast.js | 36 +++++++++++++++++- lib/function_flow.js | 34 ----------------- lib/pledge.js | 88 ++++++++++++++++++++++++++++++++++++++++---- test/pledge.js | 85 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 200 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 090638a..c722a12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Make `Function.getDescendant(name)` also try the lowercase version of the name * Add some devtools functions for custom inspect formatting * Add `Pledge#getResolvedFunction()` method, which can be passed as an old-style callback +* Fix some `Swift` methods not using the correct schedulers ## 0.9.2 (2024-02-25) diff --git a/lib/blast.js b/lib/blast.js index bdd308c..fdde726 100644 --- a/lib/blast.js +++ b/lib/blast.js @@ -1,4 +1,4 @@ -const defStat = Blast.createStaticDefiner(Blast); +const defStat = Blast.createStaticDefiner(Blast, true); /** * Turn the given list into a tree @@ -98,4 +98,36 @@ defStat(function createObjectId() { result += count; return result; -}); \ No newline at end of file +}); + +/** + * Create the ASYNC_SCHEDULER symbol + * + * @author Jelle De Loecker + * @since 0.7.21 + * @version 0.7.21 + * + * @type {symbol} + */ +defStat('asyncScheduler', Symbol('async_scheduler')); + +/** + * Create the FLOW_PLEDGE symbol + * + * @author Jelle De Loecker + * @since 0.8.15 + * @version 0.8.15 + * + * @type {symbol} + */ +defStat('flowPledgeClass', Symbol('flow_pledge_class')); + +/** + * Call a function right now. + * Meant to be used in response to setImmediate. + * + * @author Jelle De Loecker + * @since 0.1.3 + * @version 0.1.3 + */ +defStat('callNow', fnc => fnc()); \ No newline at end of file diff --git a/lib/function_flow.js b/lib/function_flow.js index 5ddb0e3..8cdb4d6 100644 --- a/lib/function_flow.js +++ b/lib/function_flow.js @@ -1,39 +1,5 @@ const defStat = Blast.createStaticDefiner('Function'); -/** - * Create the ASYNC_SCHEDULER symbol - * - * @author Jelle De Loecker - * @since 0.7.21 - * @version 0.7.21 - * - * @type {symbol} - */ -Blast.asyncScheduler = Symbol('async_scheduler'); - -/** - * Create the FLOW_PLEDGE symbol - * - * @author Jelle De Loecker - * @since 0.8.15 - * @version 0.8.15 - * - * @type {symbol} - */ -Blast.flowPledgeClass = Symbol('flow_pledge_class'); - -/** - * Call a function right now. - * Meant to be used in response to setImmediate. - * - * @author Jelle De Loecker - * @since 0.1.3 - * @version 0.1.3 - */ -Blast.callNow = function callNow(fnc) { - fnc(); -}; - /** * A dummy function * diff --git a/lib/pledge.js b/lib/pledge.js index d2f6865..8b4b268 100644 --- a/lib/pledge.js +++ b/lib/pledge.js @@ -264,20 +264,20 @@ AbstractPledge.setStatic(function hasPromiseInterface(obj) { * * @author Jelle De Loecker * @since 0.7.0 - * @version 0.9.0 + * @version 0.9.3 */ AbstractPledge.setStatic(function done(promise, callback) { let result; if (!promise || !promise.then) { - result = Pledge.resolve(promise); + result = this.resolve(promise); result.done(callback); } else { - result = Pledge.prototype.done.call(promise, callback); + result = this.prototype.done.call(promise, callback); if (!result) { - result = Pledge.resolve(); + result = this.resolve(); } } @@ -312,7 +312,6 @@ AbstractPledge.setStatic(function cast(value) { } return Pledge.resolve(value); - }); /** @@ -1397,9 +1396,84 @@ SwiftObject[Blast.flowPledgeClass] = Swift; SwiftObject[Blast.asyncScheduler] = Blast.callNow; Swift[FNC] = SwiftObject; +/** + * Do the given tasks in parallel + * + * @author Jelle De Loecker + * @since 0.9.3 + * @version 0.9.3 + * + * @param {*} tasks + * + * @return {Pledge.Swift|*} + */ +Swift.setStatic(function parallel(tasks) { + let result = SwiftObject.parallel(false, tasks); + return Swift.execute(result); +}); + +/** + * Map the given variable + * + * @author Jelle De Loecker + * @since 0.9.3 + * @version 0.9.3 + * + * @param {Object|Array} input + * @param {Function} task + * + * @return {Pledge.Swift|*} + */ +Swift.setStatic(function map(input, task) { + + if (!input || typeof input != 'object') { + return input; + } + + let mapped; + + if (Array.isArray(input)) { + mapped = input.map(task); + } else { + mapped = {}; + + for (let key in input) { + mapped[key] = task(input[key], key); + } + } + + return Swift.parallel(mapped); +}); + +/** + * Cast the given value to a pledge + * + * @author Jelle De Loecker + * @since 0.9.3 + * @version 0.9.3 + * + * @param {Mixed} value + * + * @return {SwiftPledge} + */ +Swift.setStatic(function cast(value) { + + if (!value || typeof value == 'function') { + return Swift.resolve(value); + } + + let result = Swift.execute(value); + + if (result && result instanceof Swift) { + return result; + } + + return Swift.resolve(result); +}); + /** * Execute the given function and return the value as swiftly as possible. - * If no promise is returned, the value will be returned as is. + * If no promise is given, the value will be returned as is. * If the given value is not a function, it will be returned as is. * * @author Jelle De Loecker @@ -1408,7 +1482,7 @@ Swift[FNC] = SwiftObject; * * @param {Mixed} value * - * @return {SwiftPledge|Mixed} + * @return {Pledge.Swift|*} */ Swift.setStatic(function execute(value) { diff --git a/test/pledge.js b/test/pledge.js index 5e23723..c14f3bc 100644 --- a/test/pledge.js +++ b/test/pledge.js @@ -914,6 +914,90 @@ describe('Swift', function() { }); }); + describe('.cast(input)', () => { + + it('should convert a normal Pledge to a Swift pledge', async () => { + + let normal = new Pledge(); + normal.resolve(97); + + let nr = await normal; + assert.strictEqual(nr, 97); + + let swift = Pledge.Swift.cast(normal); + + assert.strictEqual(swift instanceof Pledge.Swift, true); + + let sync_result; + + Pledge.Swift.done(swift, (err, res) => sync_result = res); + assert.strictEqual(sync_result, 97); + }); + }); + + describe('.done(pledge)', () => { + it('should synchronously call already resolved pledges', async () => { + + let pledge = new Pledge.Swift(); + pledge.resolve(47); + + let result; + + Pledge.Swift.done(pledge, (err, res) => result = res); + + assert.strictEqual(result, 47); + }); + + it('should synchronously call next with non-promise values', () => { + let result; + Pledge.Swift.done(47, (err, res) => result = res); + assert.strictEqual(result, 47); + }); + }); + + describe('.execute(task)', async () => { + + it('should return the actual value if no async task was given', () => { + assert.strictEqual(Pledge.Swift.execute(1), 1); + + let arr = []; + assert.strictEqual(Pledge.Swift.execute(arr), arr); + }); + + it('should unroll swift pledges', async () => { + + let pledge = new Pledge.Swift(); + pledge.resolve(47); + + assert.strictEqual(Pledge.Swift.execute(pledge), 47); + }); + }); + + describe('.waterfall(...tasks)', async () => { + it('should return the actual value if no async tasks were given', () => { + let result = Pledge.Swift.waterfall(1, 2, 3); + assert.strictEqual(result, 3); + }); + + it('should handle asynchronous tasks', async () => { + + let result = await Pledge.Swift.waterfall( + 47, + val => { + let pledge = new Pledge(); + + setTimeout(() => { + pledge.resolve(val - 5); + }, 1); + + return pledge; + } + ); + + assert.strictEqual(result, 42); + }); + }); + describe('#cancel()', () => { it('should cancel the pledge and call `finally`', async () => { return pledgeCancelTestOne(Pledge.Swift); @@ -923,7 +1007,6 @@ describe('Swift', function() { return pledgeCancelTestTwo(Pledge.Swift); }); }); - }); async function pledgeAllTestOne(constructor, do_wait = true) {