From 836f79ec88ca215b2ff8693f0f9002a6dcd949d8 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Tue, 3 Nov 2020 16:32:56 +0300 Subject: [PATCH] cleanup + experimenting... Signed-off-by: Alex A. Naanou --- Promise.js | 118 ++++++++++++++++++++++++++++++++++++++++++--------- package.json | 2 +- 2 files changed, 98 insertions(+), 22 deletions(-) diff --git a/Promise.js b/Promise.js index 37b984b..ba9ff57 100644 --- a/Promise.js +++ b/Promise.js @@ -16,36 +16,27 @@ var CooperativePromise = module.CooperativePromise = Promise.cooperative = object.Constructor('CooperativePromise', Promise, { - // XXX do we actually need this??? - __promise: null, + get isSet(){ + return !this.__resolve && !this.__reject }, set: function(promise){ - if(this.__promise === null){ - // setting a non-promise... + if(!this.isSet){ + // non-promise... if(promise.catch == null && promise.then == null){ - Object.defineProperty(this, '__promise', { - value: false, - enumerable: false, - }) this.__resolve(promise) - - // setting a promise... + // promise... } else { - Object.defineProperty(this, '__promise', { - value: promise, - enumerable: false, - }) - // connect the base and the set promises... promise.catch(this.__reject.bind(this)) promise.then(this.__resolve.bind(this)) } - // cleanup... delete this.__resolve delete this.__reject - } else { - throw new Error('Setting a cooperative promise twice') } }, + return this } + + // err: already set... + throw new Error('CooperativePromise.set(..): can not set twice') }, __new__: function(_, func){ var methods = {} @@ -53,10 +44,23 @@ object.Constructor('CooperativePromise', Promise, { function(resolve, reject){ methods.resolve = resolve methods.reject = reject - func - && func.call(this, ...arguments) - } ], CooperativePromise) + if(func){ + return func.call(this, ...arguments) } } ], + CooperativePromise) + /*/ if we are fulfilled before being set, we are set :) + // XXX for some reason this breaks either .__new__(..) if called + // outside of setTimeout(..) or hangs the promise on resolve + // if inside... + setTimeout(function(){ + obj.finally(function(){ + delete obj.__resolve + delete obj.__reject + }) }, 0) + //*/ // XXX revise... + // XXX can we avoid creating these??? + // ...one way to do this is to create a local .set(..) + // that whould reference them through closure... Object.defineProperties(obj, { __resolve: { value: methods.resolve, @@ -69,6 +73,78 @@ object.Constructor('CooperativePromise', Promise, { configurable: true, }, }) + return obj }, + /* + __init__: function(){ + // if we are fulfilled before being set, we are set :) + this.finally(function(){ + delete this.__resolve + delete this.__reject + }.bind(this)) }, + //*/ +}) + + + +// XXX EXPERIMENTAL -- this hides internal state (.__resolve(..) / .__reject(..)) +// ...not sure if we actually need to do this... +var _CooperativePromise = +module._CooperativePromise = +//Promise.cooperative = +object.Constructor('_CooperativePromise', Promise, { + get isSet(){ + return this.set() }, + + //set: function(){}, + + __new__: function(_, func){ + // internal state... + // NOTE: when promise is set this will be set to false... + var methods = {} + + // instance... + var obj = Reflect.construct(_CooperativePromise.__proto__, [ + function(resolve, reject){ + methods.resolve = resolve + methods.reject = reject + // NOTE: this is here mostly for promise compatibilty... + if(func){ + // XXX this can resolve/reject a promise -- need to + // keep things consistent... + return func.call(this, ...arguments) } } ], + _CooperativePromise) + + // if we are fulfilled before being set, we are set :) + // XXX for some reason this breaks either .__new__(..) if called + // outside of setTimeout(..) or hangs the promise on resolve + // if inside... + setTimeout(function(){ + obj.finally(function(){ + methods = false }) }, 0) + + // create instance .set(..) + Object.defineProperty(obj, 'set', { + value: function(promise){ + // get state... + if(arguments.length == 0){ + return !!methods } + if(methods){ + // non-promise... + if(promise.catch == null && promise.then == null){ + methods.resolve(promise) + // promise... + } else { + // connect the base and the set promises... + promise.catch(methods.reject.bind(this)) + promise.then(methods.resolve.bind(this)) } + methods = false + return this } + // err: already set... + throw new Error('CooperativePromise.set(..): can not set twice') }, + enumerable: false, + configurable: true, + }) + return obj }, }) diff --git a/package.json b/package.json index 0b70903..7d39408 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ig-types", - "version": "3.0.2", + "version": "3.0.3", "description": "Generic JavaScript types and type extensions...", "main": "main.js", "scripts": {