Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-10-08 13:04:49 +03:00
parent 7f183d3479
commit 4865d3ff71
6 changed files with 62 additions and 17 deletions

View File

@ -16,6 +16,7 @@ LOCAL_MODULES := \
EXT_MODULES := \ EXT_MODULES := \
$(wildcard node_modules/pouchdb/dist/*) \ $(wildcard node_modules/pouchdb/dist/*) \
$(wildcard node_modules/jszip/dist/*) \ $(wildcard node_modules/jszip/dist/*) \
$(wildcard node_modules/idb-keyval/dist/*.js) \
$(wildcard node_modules/showdown/dist/*) $(wildcard node_modules/showdown/dist/*)
POUCH_DB := \ POUCH_DB := \

View File

@ -249,6 +249,15 @@ object.Constructor('IterablePromise', Promise, {
: (await Promise.all(list)) : (await Promise.all(list))
.flat() }, .flat() },
[Symbol.asyncIterator]: async function*(){
var list = this.__packed
if(list instanceof Promise){
yield this.__unpack(await list)
return }
for await(var elem of list){
yield* elem instanceof Array ?
elem
: [elem] } },
// iterator methods... // iterator methods...
// //

View File

@ -8,11 +8,29 @@
/*********************************************************************/ /*********************************************************************/
var object = require('ig-object') var object = require('ig-object')
var stoppable = require('ig-stoppable')
/*********************************************************************/ /*********************************************************************/
// Wrap .map(..) / .filter(..) / .reduce(..) / .. to support STOP...
//
// NOTE: internally these are implemented as for-of loops (./generator.js)
var stoppableSet = function(iter){
return function(func){
return new Set([...this][iter](...arguments)) } }
var stoppableValue = function(iter, no_return=false){
return function(func){
var res = [...this][iter](...arguments)
return no_return ?
undefined
: res } }
//---------------------------------------------------------------------
var SetProtoMixin = var SetProtoMixin =
module.SetProtoMixin = module.SetProtoMixin =
object.Mixin('SetMixin', 'soft', { object.Mixin('SetMixin', 'soft', {
@ -110,6 +128,12 @@ object.Mixin('SetMixin', 'soft', {
this.sort(order) this.sort(order)
return removed }, return removed },
filter: stoppableSet('filter'),
map: stoppableSet('map'),
reduce: stoppableValue('reduce'),
reduceRight: stoppableValue('reduceRight'),
forEach: stoppableValue('map', true),
}) })

View File

@ -189,11 +189,11 @@ var makeGenerator = function(name, pre){
].join('\n ') }, }) } } ].join('\n ') }, }) } }
// XXX do a better doc... // XXX do a better doc...
var makePromise = function(name){ var makeProxy = function(name){
return function(...args){ return function(...args){
var that = this var that = this
return function(){ return function(){
return that(...arguments)[name](func) } } } return that(...arguments)[name](...args) } } }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -267,9 +267,12 @@ object.Mixin('GeneratorMixin', 'soft', {
// promises... // promises...
// //
then: makePromise('then'), // NOTE: .then(..) and friends are intentionally not defined here to
catch: makePromise('catch'), // prevent control deadlocks when awaiting for a generator that
finally: makePromise('finally'), // expects manual unwinding e.g.:
// g = function*(){}
// await g // will hang waiting for g to resolve
unwind: makeProxy('unwind'),
// combinators... // combinators...
// //
@ -450,7 +453,8 @@ object.Mixin('GeneratorProtoMixin', 'soft', {
// promises... // promises...
// //
then: function(onresolve, onreject){ // NOTE: this will unwind the generator...
unwind: function(onresolve, onreject){
var that = this var that = this
var p = new Promise( var p = new Promise(
function(resolve){ function(resolve){
@ -459,10 +463,12 @@ object.Mixin('GeneratorProtoMixin', 'soft', {
p.then(...arguments) p.then(...arguments)
: p : p
return p }, return p },
then: function(...args){
return this.unwind(...args) },
catch: function(func){ catch: function(func){
return this.then().catch(func) }, return this.unwind().catch(...arguments) },
finally: function(func){ finally: function(func){
return this.then().finally(func) }, return this.unwind.finally(...arguments) },
// combinators... // combinators...
// //
@ -531,22 +537,23 @@ object.Mixin('AsyncGeneratorProtoMixin', 'soft', {
// //
// NOTE: this will unwind the generator... // NOTE: this will unwind the generator...
// XXX create an iterator promise??? // XXX create an iterator promise???
// XXX should we unwind??? unwind: function(onresolve, onreject){
then: function(resolve, reject){
var that = this var that = this
var p = new Promise(async function(_resolve, _reject){ var p = new Promise(async function(resolve){
var res = [] var res = []
for await(var elem of that){ for await(var elem of that){
res.push(elem) } res.push(elem) }
_resolve(res) }) resolve(res) })
p = (resolve || reject) ? p = (onresolve || onreject) ?
p.then(...arguments) p.then(...arguments)
: p : p
return p }, return p },
then: function(...args){
return this.unwind(...args) },
catch: function(func){ catch: function(func){
return this.then().catch(func) }, return this.unwind().catch(...arguments) },
finally: function(){ finally: function(func){
return this.then().finally(func) }, return this.unwind.finally(...arguments) },
// XXX might be a good idea to use this approach above... // XXX might be a good idea to use this approach above...
iter: stoppable(async function*(handler=undefined){ iter: stoppable(async function*(handler=undefined){

View File

@ -6,6 +6,7 @@
"dependencies": { "dependencies": {
"@toast-ui/editor": "^3.2.0", "@toast-ui/editor": "^3.2.0",
"glob": "*", "glob": "*",
"idb-keyval": "^6.2.0",
"ig-actions": "*", "ig-actions": "*",
"ig-features": "*", "ig-features": "*",
"ig-object": "*", "ig-object": "*",

View File

@ -12,11 +12,14 @@
* - images * - images
* *
* *
* XXX test: can we store the file handler with permissions in a ServiceWorker??
* XXX store: add an indexedDB backend -- save on serialization...
* - idb-keyval
* - native???
* XXX might be a good idea to wrap the wysiwig editor into a separate template * XXX might be a good idea to wrap the wysiwig editor into a separate template
* and use it in the main edit template to make it user-selectable... * and use it in the main edit template to make it user-selectable...
* XXX generalize html/dom api... * XXX generalize html/dom api...
* ...see refresh() in pwiki2.html * ...see refresh() in pwiki2.html
* XXX npx http-server ... -- for testing file access...
* XXX test pouchdb latency at scale in browser... * XXX test pouchdb latency at scale in browser...
* XXX BUG: for some reason deleting and refreshing takes ~2x as long as * XXX BUG: for some reason deleting and refreshing takes ~2x as long as
* refreshing... * refreshing...