From a60443e3ecf0bb9bf6ec02a68d902a9d9dd4c412 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Wed, 14 Sep 2022 11:22:00 +0300 Subject: [PATCH] bugfix (Chromium issue 1361981) + reworked generator promise API (.then(..) -> .unwind(..))... Signed-off-by: Alex A. Naanou --- README.md | 13 +++++++++++-- generator.js | 39 +++++++++++++++++++++++---------------- package.json | 2 +- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index e0af658..7efff44 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ Library of JavaScript type extensions, types and utilities. - [`.shift()` / `.pop()` / `.gshift()` / `.gpop()`](#generatorshift--generatorpop--generatorgshift--generatorgpop) - [`.unshift(..)` / `.push(..)`](#generatorunshift--generatorpush) - [`.join(..)`](#generatorjoin) + - [`.unwind(..)`](#generatorunwind) - [`.then(..)` / `.catch(..)` / `.finally(..)`](#generatorthen--generatorcatch--generatorfinally) - [`.toArray()`](#generatortoarray) - [Treating iterators the same as generators](#treating-iterators-the-same-as-generators) @@ -124,7 +125,7 @@ Library of JavaScript type extensions, types and utilities. - [`.between(..)`](#generatorbetween-1) - [`.toArray()`](#generatortoarray-1) - [`.join(..)`](#generatorjoin-1) - - [`.then(..)` / `.catch(..)` / `.finally(..)`](#generatorthen--generatorcatch--generatorfinally-1) + - [`.unwind(..)`](#generatorunwind-1) - [Generator combinators](#generator-combinators) - [`.chain(..)` / `.chain(..)`](#generatorchain--generatorchain) - [`.concat(..)` / `.concat(..)`](#generatorconcat--generatorconcat) @@ -136,6 +137,7 @@ Library of JavaScript type extensions, types and utilities. - [`generator.stoppable(..)`](#generatorstoppable) - [Async generator extensions](#async-generator-extensions) - [`generator.AsyncGenerator`](#generatorasyncgenerator) + - [`.unwind(..)`](#async-generatorunwind) - [`.then(..)` / `.catch(..)` / `.finally(..)`](#async-generatorthen--async-generatorcatch--async-generatorfinally) - [`.iter(..)`](#async-generatoriter) - [`.map(..)` / `.filter(..)` / `.reduce(..)`](#async-generatormap--async-generatorfilter--async-generatorreduce) @@ -2292,6 +2294,11 @@ _next_ call to `.next()`, regardless of the current generator state. XXX +#### `.unwind(..)` + +XXX + + #### `.then(..)` / `.catch(..)` / `.finally(..)` Return a promise and resolve it with the generator value. @@ -2513,7 +2520,7 @@ Return a function that will return a `` output as an `Array`. XXX -#### `.then(..)` / `.catch(..)` / `.finally(..)` +#### `.unwind(..)` @@ -2641,6 +2648,8 @@ XXX EXPERIMENTAL #### `generator.AsyncGenerator` +#### `.unwind(..)` + #### `.then(..)` / `.catch(..)` / `.finally(..)` #### `.iter(..)` diff --git a/generator.js b/generator.js index 23cd3ab..5cf3084 100644 --- a/generator.js +++ b/generator.js @@ -189,11 +189,11 @@ var makeGenerator = function(name, pre){ ].join('\n ') }, }) } } // XXX do a better doc... -var makePromise = function(name){ +var makeProxy = function(name){ return function(...args){ var that = this return function(){ - return that(...arguments)[name](func) } } } + return that(...arguments)[name](...args) } } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -267,9 +267,12 @@ object.Mixin('GeneratorMixin', 'soft', { // promises... // - then: makePromise('then'), - catch: makePromise('catch'), - finally: makePromise('finally'), + // NOTE: .then(..) and friends are intentionally not defined here to + // prevent control deadlocks when awaiting for a generator that + // expects manual unwinding e.g.: + // g = function*(){} + // await g // will hang waiting for g to resolve + unwind: makeProxy('unwind'), // combinators... // @@ -450,7 +453,8 @@ object.Mixin('GeneratorProtoMixin', 'soft', { // promises... // - then: function(onresolve, onreject){ + // NOTE: this will unwind the generator... + unwind: function(onresolve, onreject){ var that = this var p = new Promise( function(resolve){ @@ -459,10 +463,12 @@ object.Mixin('GeneratorProtoMixin', 'soft', { p.then(...arguments) : p return p }, + then: function(...args){ + return this.unwind(...args) }, catch: function(func){ - return this.then().catch(func) }, + return this.unwind().catch(...arguments) }, finally: function(func){ - return this.then().finally(func) }, + return this.unwind.finally(...arguments) }, // combinators... // @@ -531,22 +537,23 @@ object.Mixin('AsyncGeneratorProtoMixin', 'soft', { // // NOTE: this will unwind the generator... // XXX create an iterator promise??? - // XXX should we unwind??? - then: function(resolve, reject){ + unwind: function(onresolve, onreject){ var that = this - var p = new Promise(async function(_resolve, _reject){ + var p = new Promise(async function(resolve){ var res = [] for await(var elem of that){ res.push(elem) } - _resolve(res) }) - p = (resolve || reject) ? + resolve(res) }) + p = (onresolve || onreject) ? p.then(...arguments) : p return p }, + then: function(...args){ + return this.unwind(...args) }, catch: function(func){ - return this.then().catch(func) }, - finally: function(){ - return this.then().finally(func) }, + return this.unwind().catch(...arguments) }, + finally: function(func){ + return this.unwind.finally(...arguments) }, // XXX might be a good idea to use this approach above... iter: stoppable(async function*(handler=undefined){ diff --git a/package.json b/package.json index e00d5f4..433011d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ig-types", - "version": "6.19.0", + "version": "6.20.0", "description": "Generic JavaScript types and type extensions...", "main": "main.js", "scripts": {