Comparing version 2.0.10 to 3.0.0
@@ -5,2 +5,7 @@ # Change Log | ||
<a name="3.0.0"></a> | ||
# [3.0.0](https://github.com/zerkalica/lom_atom/compare/v2.0.10...v3.0.0) (2017-11-25) | ||
<a name="2.0.10"></a> | ||
@@ -7,0 +12,0 @@ ## [2.0.10](https://github.com/zerkalica/lom_atom/compare/v2.0.9...v2.0.10) (2017-11-15) |
@@ -23,3 +23,2 @@ function _defineProperties(target, props) { | ||
// eslint-disable-line | ||
var ATOM_FORCE_NONE = 0; | ||
@@ -36,14 +35,2 @@ var ATOM_FORCE_CACHE = 1; | ||
var throwOnAccess = { | ||
get: function get(target, key) { | ||
if (key === origId) return target.valueOf(); | ||
throw target.valueOf(); | ||
}, | ||
ownKeys: function ownKeys(target) { | ||
throw target.valueOf(); | ||
} | ||
}; | ||
function createMock(error) { | ||
return new Proxy(error, throwOnAccess); | ||
} | ||
var AtomWait = | ||
@@ -70,2 +57,12 @@ /*#__PURE__*/ | ||
}(Error); | ||
function getId(t, hk) { | ||
return (t.constructor.displayName || t.constructor.name) + "." + hk; | ||
} | ||
function setFunctionName(fn, name) { | ||
Object.defineProperty(fn, 'name', { | ||
value: name, | ||
writable: false | ||
}); | ||
fn.displayName = name; | ||
} | ||
@@ -119,2 +116,12 @@ var handlers = new Map([[Array, function arrayHandler(target, source, stack) { | ||
var throwOnAccess = { | ||
get: function get(target, key) { | ||
if (key === origId) return target.valueOf(); | ||
throw target.valueOf(); | ||
}, | ||
ownKeys: function ownKeys(target) { | ||
throw target.valueOf(); | ||
} | ||
}; | ||
function checkSlave(slave) { | ||
@@ -150,3 +157,3 @@ slave.check(); | ||
this._context = context; | ||
this.current = context.create(this); | ||
this.current = undefined; | ||
this._next = undefined; | ||
@@ -195,40 +202,39 @@ this._suggested = undefined; | ||
_proto._get = function _get$$1(force) { | ||
var slave = this._context.last; | ||
_proto.value = function value(next) { | ||
var context = this._context; | ||
var prevForce = context.prevForce; | ||
if (slave && (!slave.isComponent || !this.isComponent)) { | ||
var slaves = this._slaves; | ||
if (context.force === ATOM_FORCE_CACHE) { | ||
this._push(next); | ||
} else { | ||
var normalized; | ||
if (!slaves) { | ||
this._context.unreap(this); | ||
slaves = this._slaves = new Set(); | ||
if (next !== undefined && (normalized = conform(next, this._suggested, this.isComponent)) !== this._suggested && (this.current instanceof Error || (normalized = conform(next, this.current, this.isComponent)) !== this.current)) { | ||
this._suggested = this._next = normalized; | ||
context.force = ATOM_FORCE_UPDATE; | ||
} | ||
slaves.add(slave); | ||
slave.addMaster(this); | ||
} | ||
var slave = context.current; | ||
if (force) { | ||
this._push(this._pull(force)); | ||
} else { | ||
this.actualize(); | ||
} | ||
if (slave && (!slave.isComponent || !this.isComponent)) { | ||
var slaves = this._slaves; | ||
return this.current; | ||
}; | ||
if (!slaves) { | ||
context.unreap(this); | ||
slaves = this._slaves = new Set(); | ||
} | ||
_proto.value = function value(next, force) { | ||
if (next === undefined) return this._get(force); | ||
if (force === ATOM_FORCE_CACHE) return this._push(next); | ||
var normalized = conform(next, this._suggested, this.isComponent); | ||
if (normalized === this._suggested) return this._get(force); | ||
slaves.add(slave); | ||
slave.addMaster(this); | ||
} | ||
if (!(this.current instanceof Error)) { | ||
normalized = conform(next, this.current, this.isComponent); | ||
if (normalized === this.current) return this._get(force); | ||
if (context.force === ATOM_FORCE_UPDATE) { | ||
this._push(this._pull()); | ||
} else { | ||
this.actualize(); | ||
} | ||
} | ||
this._suggested = this._next = normalized; | ||
return this._push(this._pull(ATOM_FORCE_UPDATE)); | ||
context.force = prevForce; | ||
return this.current; | ||
}; | ||
@@ -259,4 +265,2 @@ | ||
_proto._push = function _push(nextRaw) { | ||
this.status = ATOM_STATUS_ACTUAL; | ||
if (!(nextRaw instanceof AtomWait)) { | ||
@@ -268,9 +272,15 @@ this._suggested = this._next; | ||
var prev = this.current; | ||
if (nextRaw === undefined) return prev; | ||
var next = nextRaw instanceof Error ? createMock(nextRaw) : conform(nextRaw, prev, this.isComponent); | ||
if (nextRaw === undefined) { | ||
this.status = ATOM_STATUS_OBSOLETE; | ||
return prev; | ||
} | ||
this.status = ATOM_STATUS_ACTUAL; | ||
var next = nextRaw instanceof Error ? new Proxy(nextRaw, throwOnAccess) : conform(nextRaw, prev, this.isComponent); | ||
if (prev !== next) { | ||
this.current = next; | ||
this._context.newValue(this, prev, next, true); | ||
this._context.newValue(this, prev, next); | ||
@@ -281,7 +291,5 @@ if (this._slaves) { | ||
} | ||
return next; | ||
}; | ||
_proto._pull = function _pull(force) { | ||
_proto._pull = function _pull() { | ||
if (this._masters) { | ||
@@ -294,7 +302,7 @@ this._masters.forEach(disleadThis, this); | ||
var context = this._context; | ||
var slave = context.last; | ||
context.last = this; | ||
var slave = context.current; | ||
context.current = this; | ||
try { | ||
newValue = this.key === undefined ? this.owner[this.field + '$'](this._next, force, this.current) : this.owner[this.field + '$'](this.key, this._next, force, this.current); | ||
newValue = this.key === undefined ? this.owner[this.field + '$'](this._next) : this.owner[this.field + '$'](this.key, this._next); | ||
} catch (error) { | ||
@@ -309,3 +317,3 @@ if (error[catchedId] === undefined) { | ||
context.last = slave; | ||
context.current = slave; | ||
return newValue; | ||
@@ -389,3 +397,5 @@ }; | ||
this.last = null; | ||
this.current = null; | ||
this.force = ATOM_FORCE_NONE; | ||
this.prevForce = ATOM_FORCE_NONE; | ||
this._logger = undefined; | ||
@@ -412,8 +422,2 @@ this._updating = []; | ||
_proto.create = function create(atom) { | ||
if (this._logger !== undefined) { | ||
return this._logger.create(atom.owner, atom.field, atom.key); | ||
} | ||
}; | ||
_proto._destroyValue = function _destroyValue(atom, from) { | ||
@@ -444,3 +448,3 @@ if (this._owners.get(from) === atom) { | ||
_proto.newValue = function newValue(atom, from, to, isActualize) { | ||
_proto.newValue = function newValue(atom, from, to) { | ||
this._destroyValue(atom, from); | ||
@@ -456,7 +460,6 @@ | ||
try { | ||
if (!this._scheduled && this._logger !== undefined) { | ||
this._logger.beginGroup(this._namespace); | ||
} | ||
logger.newValue(atom, from instanceof Error && from[origId] ? from[origId] : from, to instanceof Error && to[origId] ? to[origId] : to, isActualize); | ||
// if (!this._scheduled && this._logger !== undefined) { | ||
// this._logger.beginGroup(this._namespace) | ||
// } | ||
logger.newValue(atom, from instanceof Error && from[origId] ? from[origId] : from, to instanceof Error && to[origId] ? to[origId] : to); | ||
} catch (error) { | ||
@@ -520,7 +523,6 @@ console.error(error); | ||
reaping.forEach(reap); | ||
} | ||
} // if (this._logger !== undefined) { | ||
// this._logger.endGroup() | ||
// } | ||
if (this._logger !== undefined) { | ||
this._logger.endGroup(); | ||
} | ||
@@ -553,240 +555,2 @@ this._scheduled = false; | ||
function getId(t, hk) { | ||
return (t.constructor.displayName || t.constructor.name) + "." + hk; | ||
} | ||
function memMethod(proto, name, descr, isComponent) { | ||
var longName = getId(proto, name); | ||
if (descr.value === undefined) { | ||
throw new TypeError(longName + " is not an function (next?: V)"); | ||
} | ||
proto[name + "$"] = descr.value; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
var forcedFn = function forcedFn(next, force) { | ||
return this[name](next, force === undefined ? ATOM_FORCE_CACHE : force); | ||
}; | ||
setFunctionName(forcedFn, longName + "*"); | ||
proto[name + "*"] = forcedFn; | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value: function value(next, force) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms, undefined, undefined, isComponent); | ||
hostAtoms.set(this, atom); | ||
} | ||
return atom.value(next, force); | ||
} | ||
}; | ||
} | ||
function createGetSetHandler(get, set) { | ||
return function getSetHandler(next) { | ||
if (next === undefined) { | ||
return get.call(this); | ||
} | ||
set.call(this, next); | ||
return next; | ||
}; | ||
} | ||
function createValueHandler(initializer) { | ||
return function valueHandler(next) { | ||
return next === undefined && initializer ? initializer.call(this) : next; | ||
}; | ||
} | ||
function setFunctionName(fn, name) { | ||
Object.defineProperty(fn, 'name', { | ||
value: name, | ||
writable: false | ||
}); | ||
fn.displayName = name; | ||
} | ||
var propForced = ATOM_FORCE_NONE; | ||
function memProp(proto, name, descr) { | ||
var handlerKey = name + "$"; | ||
if (proto[handlerKey] !== undefined) { | ||
return undefined; | ||
} | ||
var longName = getId(proto, name); | ||
if (descr.initializer) setFunctionName(descr.initializer, longName); | ||
if (descr.get) setFunctionName(descr.get, "get#" + longName); | ||
if (descr.set) setFunctionName(descr.set, "set#" + longName); | ||
var handler = proto[handlerKey] = descr.get === undefined && descr.set === undefined ? createValueHandler(descr.initializer) : createGetSetHandler(descr.get, descr.set); | ||
setFunctionName(handler, longName + "()"); | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get: function get() { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms); | ||
hostAtoms.set(this, atom); | ||
} | ||
var forced = propForced; | ||
propForced = ATOM_FORCE_NONE; | ||
return atom.value(undefined, forced); | ||
}, | ||
set: function set(val) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms); | ||
hostAtoms.set(this, atom); | ||
} | ||
var forced = propForced; | ||
propForced = ATOM_FORCE_NONE; | ||
atom.value(val, forced); | ||
} | ||
}; | ||
} | ||
function getKeyFromObj(params) { | ||
var keys = Object.keys(params).sort(); | ||
var result = ''; | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
var value = params[key]; | ||
result += "." + key + ":" + (typeof value === 'object' ? JSON.stringify(value) : value); | ||
} | ||
return result; | ||
} | ||
function getKey(params) { | ||
if (!params) return ''; | ||
if (params instanceof Array) return JSON.stringify(params); | ||
if (typeof params === 'object') return getKeyFromObj(params); | ||
return '' + params; | ||
} | ||
function memKeyMethod(proto, name, descr) { | ||
var longName = getId(proto, name); | ||
var handler = descr.value; | ||
if (handler === undefined) { | ||
throw new TypeError(longName + " is not an function (rawKey: K, next?: V)"); | ||
} | ||
proto[name + "$"] = handler; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
var forcedFn = function forcedFn(rawKey, next, force) { | ||
return this[name](rawKey, next, force === undefined ? ATOM_FORCE_CACHE : force); | ||
}; | ||
setFunctionName(forcedFn, longName + "*"); | ||
proto[name + "*"] = forcedFn; | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value: function value(rawKey, next, force) { | ||
var atomMap = hostAtoms.get(this); | ||
if (atomMap === undefined) { | ||
atomMap = new Map(); | ||
hostAtoms.set(this, atomMap); | ||
} | ||
var key = getKey(rawKey); | ||
var atom = atomMap.get(key); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, atomMap, rawKey, key); | ||
atomMap.set(key, atom); | ||
} | ||
return atom.value(next, force); | ||
} | ||
}; | ||
} | ||
function memkey() { | ||
var args = arguments; | ||
if (args.length === 3) { | ||
return memKeyMethod(args[0], args[1], args[2]); | ||
} | ||
return function (proto, name, descr) { | ||
return memKeyMethod(proto, name, descr); | ||
}; | ||
} | ||
var forceProxyOpts = { | ||
get: function get(t, name) { | ||
var forceFn = t[name + "*"]; | ||
if (forceFn === undefined) { | ||
// get/set handler | ||
propForced = ATOM_FORCE_CACHE; | ||
return t[name]; | ||
} | ||
return forceFn.bind(t); | ||
}, | ||
set: function set(t, name, val) { | ||
if (t[name + "*"] === undefined) { | ||
// get/set handler | ||
propForced = ATOM_FORCE_CACHE; | ||
t[name] = val; | ||
return true; | ||
} | ||
return false; | ||
} | ||
}; | ||
function force(proto, name, descr) { | ||
var proxyMap = new WeakMap(); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get: function get() { | ||
var proxy = proxyMap.get(this); | ||
if (proxy === undefined) { | ||
proxy = new Proxy(this, forceProxyOpts); | ||
proxyMap.set(this, proxy); | ||
} | ||
return proxy; | ||
} | ||
}; | ||
} | ||
function detached(proto, name, descr) { | ||
return memMethod(proto, name, descr, true); | ||
} | ||
function createActionMethod(t, name, context) { | ||
@@ -926,16 +690,175 @@ var longName = getId(t, name); | ||
} | ||
function mem() { | ||
var args = arguments; | ||
if (args.length === 3) { | ||
return args[2].value === undefined ? memProp(args[0], args[1], args[2]) : memMethod(args[0], args[1], args[2]); | ||
function detached(proto, name, descr) { | ||
proto[name + "$"] = descr.value; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value: function value(force) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms, undefined, undefined, true); | ||
hostAtoms.set(this, atom); | ||
} | ||
if (force) { | ||
defaultContext.prevForce = defaultContext.force; | ||
defaultContext.force = ATOM_FORCE_CACHE; | ||
} | ||
return atom.value(); | ||
} | ||
}; | ||
} | ||
function createGetSetHandler(get, set) { | ||
return function getSetHandler(next) { | ||
if (next === undefined) { | ||
return get.call(this); | ||
} | ||
set.call(this, next); | ||
return next; | ||
}; | ||
} | ||
function createValueHandler(initializer) { | ||
return function valueHandler(next) { | ||
return next === undefined && initializer ? initializer.call(this) : next; | ||
}; | ||
} | ||
function mem(proto, name, descr) { | ||
var handlerKey = name + "$"; | ||
if (proto[handlerKey] !== undefined) return descr; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
function value(next) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms); | ||
hostAtoms.set(this, atom); | ||
} | ||
return atom.value(next); | ||
} | ||
return function (proto, name, descr) { | ||
return descr.value === undefined ? memProp(proto, name, descr) : memMethod(proto, name, descr); | ||
if (descr.value !== undefined) { | ||
proto[handlerKey] = descr.value; | ||
descr.value = value; | ||
return descr; | ||
} | ||
var longName = getId(proto, name); | ||
if (descr.initializer) setFunctionName(descr.initializer, longName); | ||
if (descr.get) setFunctionName(descr.get, "get#" + longName); | ||
if (descr.set) setFunctionName(descr.set, "set#" + longName); | ||
proto[handlerKey] = descr.get === undefined && descr.set === undefined ? createValueHandler(descr.initializer) : createGetSetHandler(descr.get, descr.set); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get: value, | ||
set: value | ||
}; | ||
} | ||
function getKeyFromObj(params) { | ||
var keys = Object.keys(params).sort(); | ||
var result = ''; | ||
for (var i = 0; i < keys.length; i++) { | ||
var _key = keys[i]; | ||
var value = params[_key]; | ||
result += "." + _key + ":" + (typeof value === 'object' ? JSON.stringify(value) : value); | ||
} | ||
return result; | ||
} | ||
function getKey(params) { | ||
if (!params) return ''; | ||
if (params instanceof Array) return JSON.stringify(params); | ||
if (typeof params === 'object') return getKeyFromObj(params); | ||
return '' + params; | ||
} | ||
function memkey(proto, name, descr) { | ||
var longName = getId(proto, name); | ||
var handler = descr.value; | ||
if (handler === undefined) { | ||
throw new TypeError(longName + " is not an function (rawKey: K, next?: V)"); | ||
} | ||
proto[name + "$"] = handler; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
function value(rawKey, next) { | ||
var atomMap = hostAtoms.get(this); | ||
if (atomMap === undefined) { | ||
atomMap = new Map(); | ||
hostAtoms.set(this, atomMap); | ||
} | ||
var key = getKey(rawKey); | ||
var atom = atomMap.get(key); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, atomMap, rawKey, key); | ||
atomMap.set(key, atom); | ||
} | ||
return atom.value(next); | ||
} | ||
descr.value = value; | ||
return descr; | ||
} | ||
var proxyHandler = { | ||
get: function get(obj, key) { | ||
return obj[key + '()']; | ||
} | ||
}; | ||
function toAtom(obj) { | ||
return new Proxy(obj, proxyHandler); | ||
} | ||
function cache(data) { | ||
defaultContext.prevForce = defaultContext.force; | ||
defaultContext.force = ATOM_FORCE_CACHE; | ||
return data; | ||
} | ||
function force(data) { | ||
defaultContext.prevForce = defaultContext.force; | ||
defaultContext.force = ATOM_FORCE_UPDATE; | ||
return data; | ||
} | ||
mem.cache = cache; | ||
mem.force = force; | ||
mem.key = memkey; | ||
mem.Wait = AtomWait; | ||
mem.key = memkey; | ||
mem.detached = detached; | ||
mem.toAtom = toAtom; | ||
@@ -963,4 +886,2 @@ function stringToColor(str) { | ||
_proto.create = function create(owner, field, key) {}; | ||
_proto.beginGroup = function beginGroup(name) { | ||
@@ -980,3 +901,3 @@ console.group(name, 'sync'); | ||
_proto.newValue = function newValue(atom, from, to, isActualize) { | ||
_proto.newValue = function newValue(atom, from, to) { | ||
var name = atom.displayName; | ||
@@ -990,3 +911,3 @@ var filter = this._filter; | ||
var _useColors = this._useColors; | ||
console[from instanceof Error && !(from instanceof AtomWait) ? 'warn' : to instanceof Error && !(to instanceof AtomWait) ? 'error' : 'log'](_useColors ? '%c' + name : name, _useColors ? stringToColor(name) : '', from instanceof Error ? from.message : from, isActualize ? '➔' : '‣', to instanceof Error ? to.message : to); | ||
console[from instanceof Error && !(from instanceof AtomWait) ? 'warn' : to instanceof Error && !(to instanceof AtomWait) ? 'error' : 'log'](_useColors ? '%c' + name : name, _useColors ? stringToColor(name) : '', from instanceof Error ? from.message : from, '➔', to instanceof Error ? to.message : to); | ||
} | ||
@@ -998,3 +919,3 @@ }; | ||
export { Atom, mem, memkey, detached, force, action, ConsoleLogger, defaultContext, ATOM_FORCE_NONE, ATOM_FORCE_CACHE, ATOM_FORCE_UPDATE }; | ||
export { Atom, action, detached, mem, ConsoleLogger, defaultContext }; | ||
//# sourceMappingURL=lom_atom.es.js.map |
@@ -27,3 +27,2 @@ 'use strict'; | ||
// eslint-disable-line | ||
var ATOM_FORCE_NONE = 0; | ||
@@ -40,14 +39,2 @@ var ATOM_FORCE_CACHE = 1; | ||
var throwOnAccess = { | ||
get: function get(target, key) { | ||
if (key === origId) return target.valueOf(); | ||
throw target.valueOf(); | ||
}, | ||
ownKeys: function ownKeys(target) { | ||
throw target.valueOf(); | ||
} | ||
}; | ||
function createMock(error) { | ||
return new Proxy(error, throwOnAccess); | ||
} | ||
var AtomWait = | ||
@@ -74,2 +61,12 @@ /*#__PURE__*/ | ||
}(Error); | ||
function getId(t, hk) { | ||
return (t.constructor.displayName || t.constructor.name) + "." + hk; | ||
} | ||
function setFunctionName(fn, name) { | ||
Object.defineProperty(fn, 'name', { | ||
value: name, | ||
writable: false | ||
}); | ||
fn.displayName = name; | ||
} | ||
@@ -123,2 +120,12 @@ var handlers = new Map([[Array, function arrayHandler(target, source, stack) { | ||
var throwOnAccess = { | ||
get: function get(target, key) { | ||
if (key === origId) return target.valueOf(); | ||
throw target.valueOf(); | ||
}, | ||
ownKeys: function ownKeys(target) { | ||
throw target.valueOf(); | ||
} | ||
}; | ||
function checkSlave(slave) { | ||
@@ -154,3 +161,3 @@ slave.check(); | ||
this._context = context; | ||
this.current = context.create(this); | ||
this.current = undefined; | ||
this._next = undefined; | ||
@@ -199,40 +206,39 @@ this._suggested = undefined; | ||
_proto._get = function _get$$1(force) { | ||
var slave = this._context.last; | ||
_proto.value = function value(next) { | ||
var context = this._context; | ||
var prevForce = context.prevForce; | ||
if (slave && (!slave.isComponent || !this.isComponent)) { | ||
var slaves = this._slaves; | ||
if (context.force === ATOM_FORCE_CACHE) { | ||
this._push(next); | ||
} else { | ||
var normalized; | ||
if (!slaves) { | ||
this._context.unreap(this); | ||
slaves = this._slaves = new Set(); | ||
if (next !== undefined && (normalized = conform(next, this._suggested, this.isComponent)) !== this._suggested && (this.current instanceof Error || (normalized = conform(next, this.current, this.isComponent)) !== this.current)) { | ||
this._suggested = this._next = normalized; | ||
context.force = ATOM_FORCE_UPDATE; | ||
} | ||
slaves.add(slave); | ||
slave.addMaster(this); | ||
} | ||
var slave = context.current; | ||
if (force) { | ||
this._push(this._pull(force)); | ||
} else { | ||
this.actualize(); | ||
} | ||
if (slave && (!slave.isComponent || !this.isComponent)) { | ||
var slaves = this._slaves; | ||
return this.current; | ||
}; | ||
if (!slaves) { | ||
context.unreap(this); | ||
slaves = this._slaves = new Set(); | ||
} | ||
_proto.value = function value(next, force) { | ||
if (next === undefined) return this._get(force); | ||
if (force === ATOM_FORCE_CACHE) return this._push(next); | ||
var normalized = conform(next, this._suggested, this.isComponent); | ||
if (normalized === this._suggested) return this._get(force); | ||
slaves.add(slave); | ||
slave.addMaster(this); | ||
} | ||
if (!(this.current instanceof Error)) { | ||
normalized = conform(next, this.current, this.isComponent); | ||
if (normalized === this.current) return this._get(force); | ||
if (context.force === ATOM_FORCE_UPDATE) { | ||
this._push(this._pull()); | ||
} else { | ||
this.actualize(); | ||
} | ||
} | ||
this._suggested = this._next = normalized; | ||
return this._push(this._pull(ATOM_FORCE_UPDATE)); | ||
context.force = prevForce; | ||
return this.current; | ||
}; | ||
@@ -263,4 +269,2 @@ | ||
_proto._push = function _push(nextRaw) { | ||
this.status = ATOM_STATUS_ACTUAL; | ||
if (!(nextRaw instanceof AtomWait)) { | ||
@@ -272,9 +276,15 @@ this._suggested = this._next; | ||
var prev = this.current; | ||
if (nextRaw === undefined) return prev; | ||
var next = nextRaw instanceof Error ? createMock(nextRaw) : conform(nextRaw, prev, this.isComponent); | ||
if (nextRaw === undefined) { | ||
this.status = ATOM_STATUS_OBSOLETE; | ||
return prev; | ||
} | ||
this.status = ATOM_STATUS_ACTUAL; | ||
var next = nextRaw instanceof Error ? new Proxy(nextRaw, throwOnAccess) : conform(nextRaw, prev, this.isComponent); | ||
if (prev !== next) { | ||
this.current = next; | ||
this._context.newValue(this, prev, next, true); | ||
this._context.newValue(this, prev, next); | ||
@@ -285,7 +295,5 @@ if (this._slaves) { | ||
} | ||
return next; | ||
}; | ||
_proto._pull = function _pull(force) { | ||
_proto._pull = function _pull() { | ||
if (this._masters) { | ||
@@ -298,7 +306,7 @@ this._masters.forEach(disleadThis, this); | ||
var context = this._context; | ||
var slave = context.last; | ||
context.last = this; | ||
var slave = context.current; | ||
context.current = this; | ||
try { | ||
newValue = this.key === undefined ? this.owner[this.field + '$'](this._next, force, this.current) : this.owner[this.field + '$'](this.key, this._next, force, this.current); | ||
newValue = this.key === undefined ? this.owner[this.field + '$'](this._next) : this.owner[this.field + '$'](this.key, this._next); | ||
} catch (error) { | ||
@@ -313,3 +321,3 @@ if (error[catchedId] === undefined) { | ||
context.last = slave; | ||
context.current = slave; | ||
return newValue; | ||
@@ -393,3 +401,5 @@ }; | ||
this.last = null; | ||
this.current = null; | ||
this.force = ATOM_FORCE_NONE; | ||
this.prevForce = ATOM_FORCE_NONE; | ||
this._logger = undefined; | ||
@@ -416,8 +426,2 @@ this._updating = []; | ||
_proto.create = function create(atom) { | ||
if (this._logger !== undefined) { | ||
return this._logger.create(atom.owner, atom.field, atom.key); | ||
} | ||
}; | ||
_proto._destroyValue = function _destroyValue(atom, from) { | ||
@@ -448,3 +452,3 @@ if (this._owners.get(from) === atom) { | ||
_proto.newValue = function newValue(atom, from, to, isActualize) { | ||
_proto.newValue = function newValue(atom, from, to) { | ||
this._destroyValue(atom, from); | ||
@@ -460,7 +464,6 @@ | ||
try { | ||
if (!this._scheduled && this._logger !== undefined) { | ||
this._logger.beginGroup(this._namespace); | ||
} | ||
logger.newValue(atom, from instanceof Error && from[origId] ? from[origId] : from, to instanceof Error && to[origId] ? to[origId] : to, isActualize); | ||
// if (!this._scheduled && this._logger !== undefined) { | ||
// this._logger.beginGroup(this._namespace) | ||
// } | ||
logger.newValue(atom, from instanceof Error && from[origId] ? from[origId] : from, to instanceof Error && to[origId] ? to[origId] : to); | ||
} catch (error) { | ||
@@ -524,7 +527,6 @@ console.error(error); | ||
reaping.forEach(reap); | ||
} | ||
} // if (this._logger !== undefined) { | ||
// this._logger.endGroup() | ||
// } | ||
if (this._logger !== undefined) { | ||
this._logger.endGroup(); | ||
} | ||
@@ -557,240 +559,2 @@ this._scheduled = false; | ||
function getId(t, hk) { | ||
return (t.constructor.displayName || t.constructor.name) + "." + hk; | ||
} | ||
function memMethod(proto, name, descr, isComponent) { | ||
var longName = getId(proto, name); | ||
if (descr.value === undefined) { | ||
throw new TypeError(longName + " is not an function (next?: V)"); | ||
} | ||
proto[name + "$"] = descr.value; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
var forcedFn = function forcedFn(next, force) { | ||
return this[name](next, force === undefined ? ATOM_FORCE_CACHE : force); | ||
}; | ||
setFunctionName(forcedFn, longName + "*"); | ||
proto[name + "*"] = forcedFn; | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value: function value(next, force) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms, undefined, undefined, isComponent); | ||
hostAtoms.set(this, atom); | ||
} | ||
return atom.value(next, force); | ||
} | ||
}; | ||
} | ||
function createGetSetHandler(get, set) { | ||
return function getSetHandler(next) { | ||
if (next === undefined) { | ||
return get.call(this); | ||
} | ||
set.call(this, next); | ||
return next; | ||
}; | ||
} | ||
function createValueHandler(initializer) { | ||
return function valueHandler(next) { | ||
return next === undefined && initializer ? initializer.call(this) : next; | ||
}; | ||
} | ||
function setFunctionName(fn, name) { | ||
Object.defineProperty(fn, 'name', { | ||
value: name, | ||
writable: false | ||
}); | ||
fn.displayName = name; | ||
} | ||
var propForced = ATOM_FORCE_NONE; | ||
function memProp(proto, name, descr) { | ||
var handlerKey = name + "$"; | ||
if (proto[handlerKey] !== undefined) { | ||
return undefined; | ||
} | ||
var longName = getId(proto, name); | ||
if (descr.initializer) setFunctionName(descr.initializer, longName); | ||
if (descr.get) setFunctionName(descr.get, "get#" + longName); | ||
if (descr.set) setFunctionName(descr.set, "set#" + longName); | ||
var handler = proto[handlerKey] = descr.get === undefined && descr.set === undefined ? createValueHandler(descr.initializer) : createGetSetHandler(descr.get, descr.set); | ||
setFunctionName(handler, longName + "()"); | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get: function get() { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms); | ||
hostAtoms.set(this, atom); | ||
} | ||
var forced = propForced; | ||
propForced = ATOM_FORCE_NONE; | ||
return atom.value(undefined, forced); | ||
}, | ||
set: function set(val) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms); | ||
hostAtoms.set(this, atom); | ||
} | ||
var forced = propForced; | ||
propForced = ATOM_FORCE_NONE; | ||
atom.value(val, forced); | ||
} | ||
}; | ||
} | ||
function getKeyFromObj(params) { | ||
var keys = Object.keys(params).sort(); | ||
var result = ''; | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
var value = params[key]; | ||
result += "." + key + ":" + (typeof value === 'object' ? JSON.stringify(value) : value); | ||
} | ||
return result; | ||
} | ||
function getKey(params) { | ||
if (!params) return ''; | ||
if (params instanceof Array) return JSON.stringify(params); | ||
if (typeof params === 'object') return getKeyFromObj(params); | ||
return '' + params; | ||
} | ||
function memKeyMethod(proto, name, descr) { | ||
var longName = getId(proto, name); | ||
var handler = descr.value; | ||
if (handler === undefined) { | ||
throw new TypeError(longName + " is not an function (rawKey: K, next?: V)"); | ||
} | ||
proto[name + "$"] = handler; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
var forcedFn = function forcedFn(rawKey, next, force) { | ||
return this[name](rawKey, next, force === undefined ? ATOM_FORCE_CACHE : force); | ||
}; | ||
setFunctionName(forcedFn, longName + "*"); | ||
proto[name + "*"] = forcedFn; | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value: function value(rawKey, next, force) { | ||
var atomMap = hostAtoms.get(this); | ||
if (atomMap === undefined) { | ||
atomMap = new Map(); | ||
hostAtoms.set(this, atomMap); | ||
} | ||
var key = getKey(rawKey); | ||
var atom = atomMap.get(key); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, atomMap, rawKey, key); | ||
atomMap.set(key, atom); | ||
} | ||
return atom.value(next, force); | ||
} | ||
}; | ||
} | ||
function memkey() { | ||
var args = arguments; | ||
if (args.length === 3) { | ||
return memKeyMethod(args[0], args[1], args[2]); | ||
} | ||
return function (proto, name, descr) { | ||
return memKeyMethod(proto, name, descr); | ||
}; | ||
} | ||
var forceProxyOpts = { | ||
get: function get(t, name) { | ||
var forceFn = t[name + "*"]; | ||
if (forceFn === undefined) { | ||
// get/set handler | ||
propForced = ATOM_FORCE_CACHE; | ||
return t[name]; | ||
} | ||
return forceFn.bind(t); | ||
}, | ||
set: function set(t, name, val) { | ||
if (t[name + "*"] === undefined) { | ||
// get/set handler | ||
propForced = ATOM_FORCE_CACHE; | ||
t[name] = val; | ||
return true; | ||
} | ||
return false; | ||
} | ||
}; | ||
function force(proto, name, descr) { | ||
var proxyMap = new WeakMap(); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get: function get() { | ||
var proxy = proxyMap.get(this); | ||
if (proxy === undefined) { | ||
proxy = new Proxy(this, forceProxyOpts); | ||
proxyMap.set(this, proxy); | ||
} | ||
return proxy; | ||
} | ||
}; | ||
} | ||
function detached(proto, name, descr) { | ||
return memMethod(proto, name, descr, true); | ||
} | ||
function createActionMethod(t, name, context) { | ||
@@ -930,16 +694,175 @@ var longName = getId(t, name); | ||
} | ||
function mem() { | ||
var args = arguments; | ||
if (args.length === 3) { | ||
return args[2].value === undefined ? memProp(args[0], args[1], args[2]) : memMethod(args[0], args[1], args[2]); | ||
function detached(proto, name, descr) { | ||
proto[name + "$"] = descr.value; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value: function value(force) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms, undefined, undefined, true); | ||
hostAtoms.set(this, atom); | ||
} | ||
if (force) { | ||
defaultContext.prevForce = defaultContext.force; | ||
defaultContext.force = ATOM_FORCE_CACHE; | ||
} | ||
return atom.value(); | ||
} | ||
}; | ||
} | ||
function createGetSetHandler(get, set) { | ||
return function getSetHandler(next) { | ||
if (next === undefined) { | ||
return get.call(this); | ||
} | ||
set.call(this, next); | ||
return next; | ||
}; | ||
} | ||
function createValueHandler(initializer) { | ||
return function valueHandler(next) { | ||
return next === undefined && initializer ? initializer.call(this) : next; | ||
}; | ||
} | ||
function mem(proto, name, descr) { | ||
var handlerKey = name + "$"; | ||
if (proto[handlerKey] !== undefined) return descr; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
function value(next) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms); | ||
hostAtoms.set(this, atom); | ||
} | ||
return atom.value(next); | ||
} | ||
return function (proto, name, descr) { | ||
return descr.value === undefined ? memProp(proto, name, descr) : memMethod(proto, name, descr); | ||
if (descr.value !== undefined) { | ||
proto[handlerKey] = descr.value; | ||
descr.value = value; | ||
return descr; | ||
} | ||
var longName = getId(proto, name); | ||
if (descr.initializer) setFunctionName(descr.initializer, longName); | ||
if (descr.get) setFunctionName(descr.get, "get#" + longName); | ||
if (descr.set) setFunctionName(descr.set, "set#" + longName); | ||
proto[handlerKey] = descr.get === undefined && descr.set === undefined ? createValueHandler(descr.initializer) : createGetSetHandler(descr.get, descr.set); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get: value, | ||
set: value | ||
}; | ||
} | ||
function getKeyFromObj(params) { | ||
var keys = Object.keys(params).sort(); | ||
var result = ''; | ||
for (var i = 0; i < keys.length; i++) { | ||
var _key = keys[i]; | ||
var value = params[_key]; | ||
result += "." + _key + ":" + (typeof value === 'object' ? JSON.stringify(value) : value); | ||
} | ||
return result; | ||
} | ||
function getKey(params) { | ||
if (!params) return ''; | ||
if (params instanceof Array) return JSON.stringify(params); | ||
if (typeof params === 'object') return getKeyFromObj(params); | ||
return '' + params; | ||
} | ||
function memkey(proto, name, descr) { | ||
var longName = getId(proto, name); | ||
var handler = descr.value; | ||
if (handler === undefined) { | ||
throw new TypeError(longName + " is not an function (rawKey: K, next?: V)"); | ||
} | ||
proto[name + "$"] = handler; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
function value(rawKey, next) { | ||
var atomMap = hostAtoms.get(this); | ||
if (atomMap === undefined) { | ||
atomMap = new Map(); | ||
hostAtoms.set(this, atomMap); | ||
} | ||
var key = getKey(rawKey); | ||
var atom = atomMap.get(key); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, atomMap, rawKey, key); | ||
atomMap.set(key, atom); | ||
} | ||
return atom.value(next); | ||
} | ||
descr.value = value; | ||
return descr; | ||
} | ||
var proxyHandler = { | ||
get: function get(obj, key) { | ||
return obj[key + '()']; | ||
} | ||
}; | ||
function toAtom(obj) { | ||
return new Proxy(obj, proxyHandler); | ||
} | ||
function cache(data) { | ||
defaultContext.prevForce = defaultContext.force; | ||
defaultContext.force = ATOM_FORCE_CACHE; | ||
return data; | ||
} | ||
function force(data) { | ||
defaultContext.prevForce = defaultContext.force; | ||
defaultContext.force = ATOM_FORCE_UPDATE; | ||
return data; | ||
} | ||
mem.cache = cache; | ||
mem.force = force; | ||
mem.key = memkey; | ||
mem.Wait = AtomWait; | ||
mem.key = memkey; | ||
mem.detached = detached; | ||
mem.toAtom = toAtom; | ||
@@ -967,4 +890,2 @@ function stringToColor(str) { | ||
_proto.create = function create(owner, field, key) {}; | ||
_proto.beginGroup = function beginGroup(name) { | ||
@@ -984,3 +905,3 @@ console.group(name, 'sync'); | ||
_proto.newValue = function newValue(atom, from, to, isActualize) { | ||
_proto.newValue = function newValue(atom, from, to) { | ||
var name = atom.displayName; | ||
@@ -994,3 +915,3 @@ var filter = this._filter; | ||
var _useColors = this._useColors; | ||
console[from instanceof Error && !(from instanceof AtomWait) ? 'warn' : to instanceof Error && !(to instanceof AtomWait) ? 'error' : 'log'](_useColors ? '%c' + name : name, _useColors ? stringToColor(name) : '', from instanceof Error ? from.message : from, isActualize ? '➔' : '‣', to instanceof Error ? to.message : to); | ||
console[from instanceof Error && !(from instanceof AtomWait) ? 'warn' : to instanceof Error && !(to instanceof AtomWait) ? 'error' : 'log'](_useColors ? '%c' + name : name, _useColors ? stringToColor(name) : '', from instanceof Error ? from.message : from, '➔', to instanceof Error ? to.message : to); | ||
} | ||
@@ -1003,12 +924,7 @@ }; | ||
exports.Atom = Atom; | ||
exports.action = action; | ||
exports.detached = detached; | ||
exports.mem = mem; | ||
exports.memkey = memkey; | ||
exports.detached = detached; | ||
exports.force = force; | ||
exports.action = action; | ||
exports.ConsoleLogger = ConsoleLogger; | ||
exports.defaultContext = defaultContext; | ||
exports.ATOM_FORCE_NONE = ATOM_FORCE_NONE; | ||
exports.ATOM_FORCE_CACHE = ATOM_FORCE_CACHE; | ||
exports.ATOM_FORCE_UPDATE = ATOM_FORCE_UPDATE; | ||
//# sourceMappingURL=lom_atom.js.map |
@@ -29,3 +29,2 @@ (function (global, factory) { | ||
// eslint-disable-line | ||
var ATOM_FORCE_NONE = 0; | ||
@@ -42,14 +41,2 @@ var ATOM_FORCE_CACHE = 1; | ||
var throwOnAccess = { | ||
get: function get(target, key) { | ||
if (key === origId) return target.valueOf(); | ||
throw target.valueOf(); | ||
}, | ||
ownKeys: function ownKeys(target) { | ||
throw target.valueOf(); | ||
} | ||
}; | ||
function createMock(error) { | ||
return new Proxy(error, throwOnAccess); | ||
} | ||
var AtomWait = | ||
@@ -76,2 +63,12 @@ /*#__PURE__*/ | ||
}(Error); | ||
function getId(t, hk) { | ||
return (t.constructor.displayName || t.constructor.name) + "." + hk; | ||
} | ||
function setFunctionName(fn, name) { | ||
Object.defineProperty(fn, 'name', { | ||
value: name, | ||
writable: false | ||
}); | ||
fn.displayName = name; | ||
} | ||
@@ -125,2 +122,12 @@ var handlers = new Map([[Array, function arrayHandler(target, source, stack) { | ||
var throwOnAccess = { | ||
get: function get(target, key) { | ||
if (key === origId) return target.valueOf(); | ||
throw target.valueOf(); | ||
}, | ||
ownKeys: function ownKeys(target) { | ||
throw target.valueOf(); | ||
} | ||
}; | ||
function checkSlave(slave) { | ||
@@ -156,3 +163,3 @@ slave.check(); | ||
this._context = context; | ||
this.current = context.create(this); | ||
this.current = undefined; | ||
this._next = undefined; | ||
@@ -201,40 +208,39 @@ this._suggested = undefined; | ||
_proto._get = function _get$$1(force) { | ||
var slave = this._context.last; | ||
_proto.value = function value(next) { | ||
var context = this._context; | ||
var prevForce = context.prevForce; | ||
if (slave && (!slave.isComponent || !this.isComponent)) { | ||
var slaves = this._slaves; | ||
if (context.force === ATOM_FORCE_CACHE) { | ||
this._push(next); | ||
} else { | ||
var normalized; | ||
if (!slaves) { | ||
this._context.unreap(this); | ||
slaves = this._slaves = new Set(); | ||
if (next !== undefined && (normalized = conform(next, this._suggested, this.isComponent)) !== this._suggested && (this.current instanceof Error || (normalized = conform(next, this.current, this.isComponent)) !== this.current)) { | ||
this._suggested = this._next = normalized; | ||
context.force = ATOM_FORCE_UPDATE; | ||
} | ||
slaves.add(slave); | ||
slave.addMaster(this); | ||
} | ||
var slave = context.current; | ||
if (force) { | ||
this._push(this._pull(force)); | ||
} else { | ||
this.actualize(); | ||
} | ||
if (slave && (!slave.isComponent || !this.isComponent)) { | ||
var slaves = this._slaves; | ||
return this.current; | ||
}; | ||
if (!slaves) { | ||
context.unreap(this); | ||
slaves = this._slaves = new Set(); | ||
} | ||
_proto.value = function value(next, force) { | ||
if (next === undefined) return this._get(force); | ||
if (force === ATOM_FORCE_CACHE) return this._push(next); | ||
var normalized = conform(next, this._suggested, this.isComponent); | ||
if (normalized === this._suggested) return this._get(force); | ||
slaves.add(slave); | ||
slave.addMaster(this); | ||
} | ||
if (!(this.current instanceof Error)) { | ||
normalized = conform(next, this.current, this.isComponent); | ||
if (normalized === this.current) return this._get(force); | ||
if (context.force === ATOM_FORCE_UPDATE) { | ||
this._push(this._pull()); | ||
} else { | ||
this.actualize(); | ||
} | ||
} | ||
this._suggested = this._next = normalized; | ||
return this._push(this._pull(ATOM_FORCE_UPDATE)); | ||
context.force = prevForce; | ||
return this.current; | ||
}; | ||
@@ -265,4 +271,2 @@ | ||
_proto._push = function _push(nextRaw) { | ||
this.status = ATOM_STATUS_ACTUAL; | ||
if (!(nextRaw instanceof AtomWait)) { | ||
@@ -274,9 +278,15 @@ this._suggested = this._next; | ||
var prev = this.current; | ||
if (nextRaw === undefined) return prev; | ||
var next = nextRaw instanceof Error ? createMock(nextRaw) : conform(nextRaw, prev, this.isComponent); | ||
if (nextRaw === undefined) { | ||
this.status = ATOM_STATUS_OBSOLETE; | ||
return prev; | ||
} | ||
this.status = ATOM_STATUS_ACTUAL; | ||
var next = nextRaw instanceof Error ? new Proxy(nextRaw, throwOnAccess) : conform(nextRaw, prev, this.isComponent); | ||
if (prev !== next) { | ||
this.current = next; | ||
this._context.newValue(this, prev, next, true); | ||
this._context.newValue(this, prev, next); | ||
@@ -287,7 +297,5 @@ if (this._slaves) { | ||
} | ||
return next; | ||
}; | ||
_proto._pull = function _pull(force) { | ||
_proto._pull = function _pull() { | ||
if (this._masters) { | ||
@@ -300,7 +308,7 @@ this._masters.forEach(disleadThis, this); | ||
var context = this._context; | ||
var slave = context.last; | ||
context.last = this; | ||
var slave = context.current; | ||
context.current = this; | ||
try { | ||
newValue = this.key === undefined ? this.owner[this.field + '$'](this._next, force, this.current) : this.owner[this.field + '$'](this.key, this._next, force, this.current); | ||
newValue = this.key === undefined ? this.owner[this.field + '$'](this._next) : this.owner[this.field + '$'](this.key, this._next); | ||
} catch (error) { | ||
@@ -315,3 +323,3 @@ if (error[catchedId] === undefined) { | ||
context.last = slave; | ||
context.current = slave; | ||
return newValue; | ||
@@ -395,3 +403,5 @@ }; | ||
this.last = null; | ||
this.current = null; | ||
this.force = ATOM_FORCE_NONE; | ||
this.prevForce = ATOM_FORCE_NONE; | ||
this._logger = undefined; | ||
@@ -418,8 +428,2 @@ this._updating = []; | ||
_proto.create = function create(atom) { | ||
if (this._logger !== undefined) { | ||
return this._logger.create(atom.owner, atom.field, atom.key); | ||
} | ||
}; | ||
_proto._destroyValue = function _destroyValue(atom, from) { | ||
@@ -450,3 +454,3 @@ if (this._owners.get(from) === atom) { | ||
_proto.newValue = function newValue(atom, from, to, isActualize) { | ||
_proto.newValue = function newValue(atom, from, to) { | ||
this._destroyValue(atom, from); | ||
@@ -462,7 +466,6 @@ | ||
try { | ||
if (!this._scheduled && this._logger !== undefined) { | ||
this._logger.beginGroup(this._namespace); | ||
} | ||
logger.newValue(atom, from instanceof Error && from[origId] ? from[origId] : from, to instanceof Error && to[origId] ? to[origId] : to, isActualize); | ||
// if (!this._scheduled && this._logger !== undefined) { | ||
// this._logger.beginGroup(this._namespace) | ||
// } | ||
logger.newValue(atom, from instanceof Error && from[origId] ? from[origId] : from, to instanceof Error && to[origId] ? to[origId] : to); | ||
} catch (error) { | ||
@@ -526,7 +529,6 @@ console.error(error); | ||
reaping.forEach(reap); | ||
} | ||
} // if (this._logger !== undefined) { | ||
// this._logger.endGroup() | ||
// } | ||
if (this._logger !== undefined) { | ||
this._logger.endGroup(); | ||
} | ||
@@ -559,240 +561,2 @@ this._scheduled = false; | ||
function getId(t, hk) { | ||
return (t.constructor.displayName || t.constructor.name) + "." + hk; | ||
} | ||
function memMethod(proto, name, descr, isComponent) { | ||
var longName = getId(proto, name); | ||
if (descr.value === undefined) { | ||
throw new TypeError(longName + " is not an function (next?: V)"); | ||
} | ||
proto[name + "$"] = descr.value; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
var forcedFn = function forcedFn(next, force) { | ||
return this[name](next, force === undefined ? ATOM_FORCE_CACHE : force); | ||
}; | ||
setFunctionName(forcedFn, longName + "*"); | ||
proto[name + "*"] = forcedFn; | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value: function value(next, force) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms, undefined, undefined, isComponent); | ||
hostAtoms.set(this, atom); | ||
} | ||
return atom.value(next, force); | ||
} | ||
}; | ||
} | ||
function createGetSetHandler(get, set) { | ||
return function getSetHandler(next) { | ||
if (next === undefined) { | ||
return get.call(this); | ||
} | ||
set.call(this, next); | ||
return next; | ||
}; | ||
} | ||
function createValueHandler(initializer) { | ||
return function valueHandler(next) { | ||
return next === undefined && initializer ? initializer.call(this) : next; | ||
}; | ||
} | ||
function setFunctionName(fn, name) { | ||
Object.defineProperty(fn, 'name', { | ||
value: name, | ||
writable: false | ||
}); | ||
fn.displayName = name; | ||
} | ||
var propForced = ATOM_FORCE_NONE; | ||
function memProp(proto, name, descr) { | ||
var handlerKey = name + "$"; | ||
if (proto[handlerKey] !== undefined) { | ||
return undefined; | ||
} | ||
var longName = getId(proto, name); | ||
if (descr.initializer) setFunctionName(descr.initializer, longName); | ||
if (descr.get) setFunctionName(descr.get, "get#" + longName); | ||
if (descr.set) setFunctionName(descr.set, "set#" + longName); | ||
var handler = proto[handlerKey] = descr.get === undefined && descr.set === undefined ? createValueHandler(descr.initializer) : createGetSetHandler(descr.get, descr.set); | ||
setFunctionName(handler, longName + "()"); | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get: function get() { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms); | ||
hostAtoms.set(this, atom); | ||
} | ||
var forced = propForced; | ||
propForced = ATOM_FORCE_NONE; | ||
return atom.value(undefined, forced); | ||
}, | ||
set: function set(val) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms); | ||
hostAtoms.set(this, atom); | ||
} | ||
var forced = propForced; | ||
propForced = ATOM_FORCE_NONE; | ||
atom.value(val, forced); | ||
} | ||
}; | ||
} | ||
function getKeyFromObj(params) { | ||
var keys = Object.keys(params).sort(); | ||
var result = ''; | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
var value = params[key]; | ||
result += "." + key + ":" + (typeof value === 'object' ? JSON.stringify(value) : value); | ||
} | ||
return result; | ||
} | ||
function getKey(params) { | ||
if (!params) return ''; | ||
if (params instanceof Array) return JSON.stringify(params); | ||
if (typeof params === 'object') return getKeyFromObj(params); | ||
return '' + params; | ||
} | ||
function memKeyMethod(proto, name, descr) { | ||
var longName = getId(proto, name); | ||
var handler = descr.value; | ||
if (handler === undefined) { | ||
throw new TypeError(longName + " is not an function (rawKey: K, next?: V)"); | ||
} | ||
proto[name + "$"] = handler; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
var forcedFn = function forcedFn(rawKey, next, force) { | ||
return this[name](rawKey, next, force === undefined ? ATOM_FORCE_CACHE : force); | ||
}; | ||
setFunctionName(forcedFn, longName + "*"); | ||
proto[name + "*"] = forcedFn; | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value: function value(rawKey, next, force) { | ||
var atomMap = hostAtoms.get(this); | ||
if (atomMap === undefined) { | ||
atomMap = new Map(); | ||
hostAtoms.set(this, atomMap); | ||
} | ||
var key = getKey(rawKey); | ||
var atom = atomMap.get(key); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, atomMap, rawKey, key); | ||
atomMap.set(key, atom); | ||
} | ||
return atom.value(next, force); | ||
} | ||
}; | ||
} | ||
function memkey() { | ||
var args = arguments; | ||
if (args.length === 3) { | ||
return memKeyMethod(args[0], args[1], args[2]); | ||
} | ||
return function (proto, name, descr) { | ||
return memKeyMethod(proto, name, descr); | ||
}; | ||
} | ||
var forceProxyOpts = { | ||
get: function get(t, name) { | ||
var forceFn = t[name + "*"]; | ||
if (forceFn === undefined) { | ||
// get/set handler | ||
propForced = ATOM_FORCE_CACHE; | ||
return t[name]; | ||
} | ||
return forceFn.bind(t); | ||
}, | ||
set: function set(t, name, val) { | ||
if (t[name + "*"] === undefined) { | ||
// get/set handler | ||
propForced = ATOM_FORCE_CACHE; | ||
t[name] = val; | ||
return true; | ||
} | ||
return false; | ||
} | ||
}; | ||
function force(proto, name, descr) { | ||
var proxyMap = new WeakMap(); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get: function get() { | ||
var proxy = proxyMap.get(this); | ||
if (proxy === undefined) { | ||
proxy = new Proxy(this, forceProxyOpts); | ||
proxyMap.set(this, proxy); | ||
} | ||
return proxy; | ||
} | ||
}; | ||
} | ||
function detached(proto, name, descr) { | ||
return memMethod(proto, name, descr, true); | ||
} | ||
function createActionMethod(t, name, context) { | ||
@@ -932,16 +696,175 @@ var longName = getId(t, name); | ||
} | ||
function mem() { | ||
var args = arguments; | ||
if (args.length === 3) { | ||
return args[2].value === undefined ? memProp(args[0], args[1], args[2]) : memMethod(args[0], args[1], args[2]); | ||
function detached(proto, name, descr) { | ||
proto[name + "$"] = descr.value; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value: function value(force) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms, undefined, undefined, true); | ||
hostAtoms.set(this, atom); | ||
} | ||
if (force) { | ||
defaultContext.prevForce = defaultContext.force; | ||
defaultContext.force = ATOM_FORCE_CACHE; | ||
} | ||
return atom.value(); | ||
} | ||
}; | ||
} | ||
function createGetSetHandler(get, set) { | ||
return function getSetHandler(next) { | ||
if (next === undefined) { | ||
return get.call(this); | ||
} | ||
set.call(this, next); | ||
return next; | ||
}; | ||
} | ||
function createValueHandler(initializer) { | ||
return function valueHandler(next) { | ||
return next === undefined && initializer ? initializer.call(this) : next; | ||
}; | ||
} | ||
function mem(proto, name, descr) { | ||
var handlerKey = name + "$"; | ||
if (proto[handlerKey] !== undefined) return descr; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
function value(next) { | ||
var atom = hostAtoms.get(this); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms); | ||
hostAtoms.set(this, atom); | ||
} | ||
return atom.value(next); | ||
} | ||
return function (proto, name, descr) { | ||
return descr.value === undefined ? memProp(proto, name, descr) : memMethod(proto, name, descr); | ||
if (descr.value !== undefined) { | ||
proto[handlerKey] = descr.value; | ||
descr.value = value; | ||
return descr; | ||
} | ||
var longName = getId(proto, name); | ||
if (descr.initializer) setFunctionName(descr.initializer, longName); | ||
if (descr.get) setFunctionName(descr.get, "get#" + longName); | ||
if (descr.set) setFunctionName(descr.set, "set#" + longName); | ||
proto[handlerKey] = descr.get === undefined && descr.set === undefined ? createValueHandler(descr.initializer) : createGetSetHandler(descr.get, descr.set); | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get: value, | ||
set: value | ||
}; | ||
} | ||
function getKeyFromObj(params) { | ||
var keys = Object.keys(params).sort(); | ||
var result = ''; | ||
for (var i = 0; i < keys.length; i++) { | ||
var _key = keys[i]; | ||
var value = params[_key]; | ||
result += "." + _key + ":" + (typeof value === 'object' ? JSON.stringify(value) : value); | ||
} | ||
return result; | ||
} | ||
function getKey(params) { | ||
if (!params) return ''; | ||
if (params instanceof Array) return JSON.stringify(params); | ||
if (typeof params === 'object') return getKeyFromObj(params); | ||
return '' + params; | ||
} | ||
function memkey(proto, name, descr) { | ||
var longName = getId(proto, name); | ||
var handler = descr.value; | ||
if (handler === undefined) { | ||
throw new TypeError(longName + " is not an function (rawKey: K, next?: V)"); | ||
} | ||
proto[name + "$"] = handler; | ||
var hostAtoms = new WeakMap(); | ||
Object.defineProperty(proto, name + "()", { | ||
get: function get() { | ||
return hostAtoms.get(this); | ||
} | ||
}); | ||
function value(rawKey, next) { | ||
var atomMap = hostAtoms.get(this); | ||
if (atomMap === undefined) { | ||
atomMap = new Map(); | ||
hostAtoms.set(this, atomMap); | ||
} | ||
var key = getKey(rawKey); | ||
var atom = atomMap.get(key); | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, atomMap, rawKey, key); | ||
atomMap.set(key, atom); | ||
} | ||
return atom.value(next); | ||
} | ||
descr.value = value; | ||
return descr; | ||
} | ||
var proxyHandler = { | ||
get: function get(obj, key) { | ||
return obj[key + '()']; | ||
} | ||
}; | ||
function toAtom(obj) { | ||
return new Proxy(obj, proxyHandler); | ||
} | ||
function cache(data) { | ||
defaultContext.prevForce = defaultContext.force; | ||
defaultContext.force = ATOM_FORCE_CACHE; | ||
return data; | ||
} | ||
function force(data) { | ||
defaultContext.prevForce = defaultContext.force; | ||
defaultContext.force = ATOM_FORCE_UPDATE; | ||
return data; | ||
} | ||
mem.cache = cache; | ||
mem.force = force; | ||
mem.key = memkey; | ||
mem.Wait = AtomWait; | ||
mem.key = memkey; | ||
mem.detached = detached; | ||
mem.toAtom = toAtom; | ||
@@ -969,4 +892,2 @@ function stringToColor(str) { | ||
_proto.create = function create(owner, field, key) {}; | ||
_proto.beginGroup = function beginGroup(name) { | ||
@@ -986,3 +907,3 @@ console.group(name, 'sync'); | ||
_proto.newValue = function newValue(atom, from, to, isActualize) { | ||
_proto.newValue = function newValue(atom, from, to) { | ||
var name = atom.displayName; | ||
@@ -996,3 +917,3 @@ var filter = this._filter; | ||
var _useColors = this._useColors; | ||
console[from instanceof Error && !(from instanceof AtomWait) ? 'warn' : to instanceof Error && !(to instanceof AtomWait) ? 'error' : 'log'](_useColors ? '%c' + name : name, _useColors ? stringToColor(name) : '', from instanceof Error ? from.message : from, isActualize ? '➔' : '‣', to instanceof Error ? to.message : to); | ||
console[from instanceof Error && !(from instanceof AtomWait) ? 'warn' : to instanceof Error && !(to instanceof AtomWait) ? 'error' : 'log'](_useColors ? '%c' + name : name, _useColors ? stringToColor(name) : '', from instanceof Error ? from.message : from, '➔', to instanceof Error ? to.message : to); | ||
} | ||
@@ -1005,12 +926,7 @@ }; | ||
exports.Atom = Atom; | ||
exports.action = action; | ||
exports.detached = detached; | ||
exports.mem = mem; | ||
exports.memkey = memkey; | ||
exports.detached = detached; | ||
exports.force = force; | ||
exports.action = action; | ||
exports.ConsoleLogger = ConsoleLogger; | ||
exports.defaultContext = defaultContext; | ||
exports.ATOM_FORCE_NONE = ATOM_FORCE_NONE; | ||
exports.ATOM_FORCE_CACHE = ATOM_FORCE_CACHE; | ||
exports.ATOM_FORCE_UPDATE = ATOM_FORCE_UPDATE; | ||
@@ -1017,0 +933,0 @@ Object.defineProperty(exports, '__esModule', { value: true }); |
{ | ||
"name": "lom_atom", | ||
"version": "2.0.10", | ||
"version": "3.0.0", | ||
"description": "Alternative implementation of eigenmethod mol_atom state management library", | ||
@@ -5,0 +5,0 @@ "publishConfig": { |
127
README.md
@@ -20,3 +20,3 @@ # lom_atom | ||
- [Observable get/set](#observable-getset) | ||
- [Force mode cache management](#force-mode-cache-management) | ||
- [Controlling cache](#controlling-cache) | ||
- [Method-style properties](#method-style-properties) | ||
@@ -57,66 +57,2 @@ - [Computed values](#computed-values) | ||
## Force mode cache management | ||
Killer feature, grabbed from [mol_atom](https://github.com/eigenmethod/mol). We can reset cache on get or obviously set cache value, using magic force property. | ||
On set value: force mode talk lom to pass value through set handler. On get value: invoke handler with ``` undefined, true ``` and reset cache. | ||
```js | ||
import {force, mem} from 'lom_atom' | ||
class TodoList { | ||
@force force: TodoList | ||
@mem set todos(todos: Todo | Error) { | ||
console.log('set handler') | ||
} | ||
@mem get todos() { | ||
console.log('get handler') | ||
return [someTodo] | ||
} | ||
} | ||
const list = new TodoList() | ||
list.todos = [someTodo] // console: set handler | ||
list.todos = [someTodo] // someTodo already set - no handler call | ||
list.force.todos = [someTodo] // force, console: set handler | ||
list.todos // console: get handler | ||
list.todos // return cached value | ||
list.force.todos // console: get handler | ||
``` | ||
## Method-style properties | ||
In this form we can change value on set. Less magic, than regular properties. | ||
```js | ||
import {action, mem} from 'lom_atom' | ||
class Some { | ||
@force $: Some | ||
@mem name(next?: string, force?: boolean): string { | ||
// if next !== undefined - set mode | ||
if (next !== undefined) return next | ||
return 'default value' | ||
} | ||
} | ||
const some = new Some() | ||
some.name() === 'default value' | ||
some.name('new value') // Set value directly into atom cache, some.name() handler not called | ||
some.name() === 'new value' | ||
some.name('val', true) // Pass value through some.name() handler and set result into cache | ||
some.name(undefined, true) === 'default value' // Invoke some.name() handler and reset to default value | ||
``` | ||
``` some.force.name(val) ``` alias of ``` some.name(val, true) ``` | ||
And ``` some.force.name() ``` alias of ``` some.name(undefined, true) ``` | ||
## Computed values | ||
@@ -139,17 +75,18 @@ | ||
Like [mobx reaction](https://mobx.js.org/refguide/reaction.html) produces a side effect for making network requests, etc. But side effects in lom are simpler. | ||
Lom atom memoized property can interact with upstream (server, etc). Each observable or computed property can be used in 6 cases: get, force get, set, force set, reset, push. Modifiers helps to produce and control side effects for making network requests. | ||
Listener.listen throws errors on todo list store property access, if todo list loading finished with erorr or loading in progress. | ||
```js | ||
import {mem} from 'lom_atom' | ||
class TodoList { | ||
@mem set todos(todos: Todo | Error) {} | ||
@mem set todos(todos: Todo) { | ||
fetch({ | ||
url: '/todos', | ||
method: 'POST', | ||
body: JSON.stringify(todos) | ||
}) | ||
.catch(error => this.todos = mem.cache(error)) | ||
@mem get todos() { | ||
// Side effect, cached in mem | ||
fetch('/todos') | ||
.then((todos) => { | ||
this.todos = todos | ||
}) | ||
.catch(e => this.todos = e) | ||
console.log('set handler') | ||
@@ -159,27 +96,24 @@ throw new mem.Wait() | ||
@mem get unfinishedTodos() { | ||
return this.todos.filter((todo) => !todo.finished) | ||
} | ||
} | ||
@mem get todos() { | ||
console.log('get handler') | ||
class Listener { | ||
_list = new TodoList() | ||
@mem listen() { | ||
try { | ||
console.log('total todos:', this._list.todos.length) | ||
console.log('unfinished todos:', this._list.unfinishedTodos.length) | ||
} catch (e) { | ||
if (e instanceof mem.Wait) { | ||
console.log('loading...') | ||
} else { | ||
console.error('error', e.message) | ||
} | ||
} | ||
fetch('/todos') | ||
.then((data) => this.todos = mem.cache(data)) | ||
.catch(error => this.todos = mem.cache(error)) | ||
throw new mem.Wait() | ||
} | ||
} | ||
const listener = new Listener() | ||
listener.listen() | ||
const list = new TodoList() | ||
``` | ||
| Modifier usage | Description | When call handler | Handler | | ||
|-------------------------------------|--------------------------------------------------------|---------------------------------------|--------------------------------------| | ||
| ``` store.todos ``` | Try to get value from cache, if empty - fetch upstream | If cache is empty or upstream changed | ``` get todos (): Todo[] {} ``` | | ||
| ``` store.todos = mem.force() ``` | Reset cache and force load from upstream | Always | ``` get todos (): Todo[] {} ``` | | ||
| ``` store.todos = [] ``` | Set value to upstream | If value is differs from cache | ``` set todos (todos: Todo[]) {} ``` | | ||
| ``` store.todos = mem.force([]) ``` | Force set value to upstream | Always | ``` set todos (todos: Todo[]) {} ``` | | ||
| ``` store.todos = mem.cache() ``` | Reset cache, but not fetch from upstream | Never | No | | ||
| ``` store.todos = mem.cache([]) ``` | Save async answer from upstream to cache | Never | No | | ||
## Key-value | ||
@@ -191,4 +125,5 @@ | ||
class TodoList { | ||
@mem.key todo(id: string, next?: Todo, force?: boolean): Todo { | ||
@mem.key todo(id: string, next?: Todo): Todo { | ||
if (next === undefined) { | ||
// get mode | ||
return {} | ||
@@ -195,0 +130,0 @@ } |
111
src/Atom.js
@@ -5,2 +5,3 @@ // @flow | ||
catchedId, | ||
origId, | ||
ATOM_FORCE_NONE, | ||
@@ -24,5 +25,16 @@ ATOM_FORCE_CACHE, | ||
import {createMock, AtomWait} from './utils' | ||
import {AtomWait} from './utils' | ||
import conform from './conform' | ||
const throwOnAccess = { | ||
get<V: Object>(target: Error, key: string): V { | ||
if (key === origId) return (target: Object).valueOf() | ||
throw target.valueOf() | ||
}, | ||
ownKeys(target: Error): string[] { | ||
throw target.valueOf() | ||
} | ||
} | ||
function checkSlave(slave: IAtomInt) { | ||
@@ -78,3 +90,3 @@ slave.check() | ||
this._context = context | ||
this.current = context.create(this) | ||
this.current = undefined | ||
this._next = undefined | ||
@@ -124,38 +136,42 @@ this._suggested = undefined | ||
_get(force?: IAtomForce): V { | ||
const slave = this._context.last | ||
if (slave && (!slave.isComponent || !this.isComponent)) { | ||
let slaves = this._slaves | ||
if (!slaves) { | ||
this._context.unreap(this) | ||
slaves = this._slaves = new Set() | ||
value(next?: V | Error): V { | ||
const context = this._context | ||
const prevForce = context.prevForce | ||
if (context.force === ATOM_FORCE_CACHE) { | ||
this._push(next) | ||
} else { | ||
let normalized: V | Error | ||
if ( | ||
next !== undefined | ||
&& (normalized = conform(next, this._suggested, this.isComponent)) !== this._suggested | ||
&& ( | ||
this.current instanceof Error | ||
|| (normalized = conform(next, this.current, this.isComponent)) !== this.current | ||
) | ||
) { | ||
this._suggested = this._next = normalized | ||
context.force = ATOM_FORCE_UPDATE | ||
} | ||
slaves.add(slave) | ||
slave.addMaster(this) | ||
} | ||
if (force) { | ||
this._push(this._pull(force)) | ||
} else { | ||
this.actualize() | ||
} | ||
const slave = context.current | ||
if (slave && (!slave.isComponent || !this.isComponent)) { | ||
let slaves = this._slaves | ||
if (!slaves) { | ||
context.unreap(this) | ||
slaves = this._slaves = new Set() | ||
} | ||
slaves.add(slave) | ||
slave.addMaster(this) | ||
} | ||
return (this.current: any) | ||
} | ||
value(next?: V | Error, force?: IAtomForce): V { | ||
if (next === undefined) return this._get(force) | ||
if (force === ATOM_FORCE_CACHE) return this._push(next) | ||
let normalized: V | Error = conform(next, this._suggested, this.isComponent) | ||
if (normalized === this._suggested) return this._get(force) | ||
if (!(this.current instanceof Error)) { | ||
normalized = conform(next, this.current, this.isComponent) | ||
if (normalized === this.current) return this._get(force) | ||
if (context.force === ATOM_FORCE_UPDATE) { | ||
this._push(this._pull()) | ||
} else { | ||
this.actualize() | ||
} | ||
} | ||
this._suggested = this._next = normalized | ||
context.force = prevForce | ||
return this._push(this._pull(ATOM_FORCE_UPDATE)) | ||
return (this.current: any) | ||
} | ||
@@ -184,4 +200,3 @@ | ||
_push(nextRaw: V | Error): V { | ||
this.status = ATOM_STATUS_ACTUAL | ||
_push(nextRaw?: V | Error): void { | ||
if (!(nextRaw instanceof AtomWait)) { | ||
@@ -192,5 +207,9 @@ this._suggested = this._next | ||
const prev = this.current | ||
if (nextRaw === undefined) return (prev: any) | ||
if (nextRaw === undefined) { | ||
this.status = ATOM_STATUS_OBSOLETE | ||
return (prev: any) | ||
} | ||
this.status = ATOM_STATUS_ACTUAL | ||
const next: V | Error = nextRaw instanceof Error | ||
? createMock(nextRaw) | ||
? new Proxy(nextRaw, throwOnAccess) | ||
: conform(nextRaw, prev, this.isComponent) | ||
@@ -200,3 +219,3 @@ | ||
this.current = next | ||
this._context.newValue(this, prev, next, true) | ||
this._context.newValue(this, prev, next) | ||
if (this._slaves) { | ||
@@ -206,7 +225,5 @@ this._slaves.forEach(obsoleteSlave) | ||
} | ||
return (next: any) | ||
} | ||
_pull(force?: IAtomForce): V | Error { | ||
_pull(): V | Error { | ||
if (this._masters) { | ||
@@ -220,8 +237,8 @@ this._masters.forEach(disleadThis, this) | ||
const context = this._context | ||
const slave = context.last | ||
context.last = this | ||
const slave = context.current | ||
context.current = this | ||
try { | ||
newValue = this.key === undefined | ||
? (this.owner: any)[this.field + '$'](this._next, force, this.current) | ||
: (this.owner: any)[this.field + '$'](this.key, this._next, force, this.current) | ||
? (this.owner: any)[this.field + '$'](this._next) | ||
: (this.owner: any)[this.field + '$'](this.key, this._next) | ||
} catch (error) { | ||
@@ -232,5 +249,7 @@ if (error[catchedId] === undefined) { | ||
} | ||
newValue = error instanceof Error ? error : new Error(error.stack || error) | ||
newValue = error instanceof Error | ||
? error | ||
: new Error(error.stack || error) | ||
} | ||
context.last = slave | ||
context.current = slave | ||
@@ -237,0 +256,0 @@ return newValue |
// @flow | ||
export const handlers: Map<any, Function> = new Map([ | ||
export const handlers: Map<mixed, Function> = new Map([ | ||
[ | ||
Array, | ||
function arrayHandler<Target: Array<any>, Source: Array<any>>(target: Target, source: Source, stack: any[]) { | ||
function arrayHandler<Target: mixed[], Source: mixed[]>(target: Target, source: Source, stack: mixed[]) { | ||
let equal = target.length === source.length | ||
@@ -19,3 +19,3 @@ | ||
Object, | ||
function objectHandler<Target: Object, Source: Object>(target: Target, source: Source, stack: any[]) { | ||
function objectHandler<Target: Object, Source: Object>(target: Target, source: Source, stack: mixed[]) { | ||
let count = 0 | ||
@@ -51,3 +51,8 @@ let equal = true | ||
export default function conform<Target, Source>(target: Target, source: Source, isComponent: boolean, stack: any[] = []): Target { | ||
export default function conform<Target, Source>( | ||
target: Target, | ||
source: Source, | ||
isComponent: boolean, | ||
stack: mixed[] = [] | ||
): Target { | ||
if (target === source) return (source: any) | ||
@@ -54,0 +59,0 @@ |
@@ -28,4 +28,2 @@ // @flow | ||
create<V>(owner: Object, field: string, key?: mixed): V | void {} | ||
beginGroup(name: string) { | ||
@@ -45,3 +43,3 @@ console.group(name, 'sync') | ||
newValue<V>(atom: IAtom<V>, from?: V | Error, to: V | Error, isActualize?: boolean): void { | ||
newValue<V>(atom: IAtom<V>, from?: V | Error, to: V | Error): void { | ||
const name = atom.displayName | ||
@@ -62,3 +60,3 @@ const filter = this._filter | ||
from instanceof Error ? from.message : from, | ||
isActualize ? '➔' : '‣', | ||
'➔', | ||
to instanceof Error ? to.message : to | ||
@@ -65,0 +63,0 @@ ) |
// @flow | ||
import type { | ||
IAtomHandler, | ||
IAtomForce, | ||
@@ -10,7 +9,4 @@ IAtomInt, | ||
ILogger, | ||
ILoggerStatus | ||
} from './interfaces' | ||
import {origId, ATOM_FORCE_NONE, ATOM_STATUS_DESTROYED, ATOM_STATUS_ACTUAL} from './interfaces' | ||
import {AtomWait} from './utils' | ||
import Atom from './Atom' | ||
import {origId, ATOM_FORCE_NONE, ATOM_STATUS_DESTROYED} from './interfaces' | ||
@@ -29,3 +25,5 @@ const scheduleNative: (handler: () => void) => number = typeof requestAnimationFrame === 'function' | ||
export default class Context implements IContext { | ||
last: ?IAtomInt = null | ||
current: ?IAtomInt = null | ||
force: IAtomForce = ATOM_FORCE_NONE | ||
prevForce: IAtomForce = ATOM_FORCE_NONE | ||
@@ -39,8 +37,2 @@ _logger: ILogger | void = undefined | ||
create<V>(atom: IAtomInt): V | void { | ||
if (this._logger !== undefined) { | ||
return this._logger.create(atom.owner, atom.field, atom.key) | ||
} | ||
} | ||
_destroyValue<V>(atom: IAtom<V>, from: any) { | ||
@@ -69,3 +61,3 @@ if (this._owners.get(from) === atom) { | ||
newValue<V>(atom: IAtom<V>, from?: V | Error, to: V | Error, isActualize?: boolean) { | ||
newValue<V>(atom: IAtom<V>, from?: V | Error, to: V | Error) { | ||
this._destroyValue(atom, from) | ||
@@ -83,10 +75,9 @@ if ( | ||
try { | ||
if (!this._scheduled && this._logger !== undefined) { | ||
this._logger.beginGroup(this._namespace) | ||
} | ||
// if (!this._scheduled && this._logger !== undefined) { | ||
// this._logger.beginGroup(this._namespace) | ||
// } | ||
logger.newValue( | ||
atom, | ||
from instanceof Error && (from: Object)[origId] ? (from: Object)[origId] : from, | ||
to instanceof Error && (to: Object)[origId] ? (to: Object)[origId] : to, | ||
isActualize | ||
to instanceof Error && (to: Object)[origId] ? (to: Object)[origId] : to | ||
) | ||
@@ -154,5 +145,5 @@ } catch (error) { | ||
} | ||
if (this._logger !== undefined) { | ||
this._logger.endGroup() | ||
} | ||
// if (this._logger !== undefined) { | ||
// this._logger.endGroup() | ||
// } | ||
this._scheduled = false | ||
@@ -159,0 +150,0 @@ this._pendCount = 0 |
// @flow | ||
export {default as Atom} from './Atom' | ||
export {default as mem, memkey, detached, force, action} from './mem' | ||
export {default as action} from './action' | ||
export {default as detached} from './detached' | ||
export {default as mem} from './mem' | ||
export {default as ConsoleLogger} from './ConsoleLogger' | ||
@@ -9,17 +11,5 @@ export {defaultContext} from './Context' | ||
export type { | ||
ResultOf, | ||
IAtom, | ||
IAtomForce, | ||
IAtomStatus, | ||
IContext, | ||
IAtomHandler, | ||
NamesOf, | ||
ILoggerStatus, | ||
ILogger | ||
} from './interfaces' | ||
export { | ||
ATOM_FORCE_NONE, | ||
ATOM_FORCE_CACHE, | ||
ATOM_FORCE_UPDATE | ||
} from './interfaces' |
// @flow | ||
type _ResultOf<V, F: (...x: any[]) => V> = V // eslint-disable-line | ||
export type ResultOf<F> = _ResultOf<*, F> | ||
export type NamesOf<F> = {+[id: $Keys<ResultOf<F>>]: string} | ||
export type ILoggerStatus = 'waiting' | 'proposeToReap' | 'proposeToPull' | ||
export interface ILogger { | ||
/** | ||
* Invokes before atom creating | ||
* | ||
* @param owner Object Object with atom | ||
* @param field string property name | ||
* @param key mixed | void for dictionary atoms - dictionary key | ||
*/ | ||
create<V>(owner: Object, field: string, key?: mixed): V | void; | ||
beginGroup(name: string): void; | ||
@@ -34,12 +21,12 @@ endGroup(): void; | ||
* Atom value changed | ||
* @param isActualize bool if true - atom handler invoked, if false - only atom.cache value getted/setted | ||
*/ | ||
newValue<V>(atom: IAtom<V>, from?: V | Error, to: V | Error, isActualize?: boolean): void; | ||
newValue<V>(atom: IAtom<V>, from?: V | Error, to: V | Error): void; | ||
} | ||
export interface IContext { | ||
last: ?IAtomInt; | ||
create<V>(atom: IAtomInt): V | void; | ||
current: ?IAtomInt; | ||
force: IAtomForce; | ||
prevForce: IAtomForce; | ||
destroyHost(atom: IAtomInt): void; | ||
newValue<V>(t: IAtom<V>, from?: V | Error, to: V | Error, isActualize?: boolean): void; | ||
newValue<V>(t: IAtom<V>, from?: V | Error, to: V | Error): void; | ||
setLogger(logger: ILogger): void; | ||
@@ -75,3 +62,3 @@ proposeToPull(atom: IAtomInt): void; | ||
+displayName: string; | ||
value(v?: V | Error, force?: IAtomForce): V; | ||
value(v?: V | Error): V; | ||
destructor(): void; | ||
@@ -91,7 +78,5 @@ } | ||
} | ||
export type IAtomPropHandler<V> = (next?: V | Error, force?: IAtomForce, oldValue?: V) => V | ||
// | Error | ||
export type IAtomHandler<V, K> = (key: K, next?: V | Error, force?: IAtomForce, oldValue?: V) => V | ||
| IAtomPropHandler<V> | ||
export type IAtomHandler<V, K> = (key: K, next?: V | Error) => V | ||
| (next?: V | Error) => V | ||
@@ -110,3 +95,3 @@ export interface IAtomOwner { | ||
get?: () => T; | ||
set?: (value: T | Error) => void; | ||
set?: (value: T) => void; | ||
} |
395
src/mem.js
// @flow | ||
import {ATOM_FORCE_CACHE, ATOM_FORCE_NONE, ATOM_FORCE_UPDATE} from './interfaces' | ||
import type {TypedPropertyDescriptor, IAtom, IAtomPropHandler, IAtomHandler, IAtomForce, IContext} from './interfaces' | ||
import type {IAtomForce, TypedPropertyDescriptor, IAtom} from './interfaces' | ||
import {ATOM_FORCE_CACHE, ATOM_FORCE_UPDATE} from './interfaces' | ||
import {defaultContext} from './Context' | ||
import {AtomWait} from './utils' | ||
import {AtomWait, getId, setFunctionName} from './utils' | ||
import Atom from './Atom' | ||
function getId(t: Object, hk: string): string { | ||
return `${t.constructor.displayName || t.constructor.name}.${hk}` | ||
} | ||
function memMethod<V, P: Object>( | ||
proto: P, | ||
name: string, | ||
descr: TypedPropertyDescriptor<*>, | ||
isComponent?: boolean | ||
): TypedPropertyDescriptor<*> { | ||
const longName = getId(proto, name) | ||
if (descr.value === undefined) { | ||
throw new TypeError(`${longName} is not an function (next?: V)`) | ||
} | ||
proto[`${name}$`] = descr.value | ||
const hostAtoms: WeakMap<Object, IAtom<V>> = new WeakMap() | ||
Object.defineProperty(proto, `${name}()`, { | ||
get() { | ||
return hostAtoms.get(this) | ||
} | ||
}) | ||
const forcedFn = function (next?: V | Error, force?: IAtomForce) { | ||
return this[name](next, force === undefined ? ATOM_FORCE_CACHE : force) | ||
} | ||
setFunctionName(forcedFn, `${longName}*`) | ||
proto[`${name}*`] = forcedFn | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value(next?: V | Error, force?: IAtomForce): V { | ||
let atom: IAtom<V> | void = hostAtoms.get(this) | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms, undefined, undefined, isComponent) | ||
hostAtoms.set(this, atom) | ||
} | ||
return (atom: IAtom<V>).value(next, force) | ||
} | ||
} | ||
} | ||
function createGetSetHandler<V>( | ||
get?: () => V, | ||
set?: (v: V | Error) => void | ||
): IAtomHandler<V, *> { | ||
return function getSetHandler(next?: V) { | ||
set?: (v: V) => void | ||
): (next?: V) => V { | ||
return function getSetHandler(next?: V): V { | ||
if (next === undefined) { | ||
@@ -59,8 +17,8 @@ return (get: any).call(this) | ||
(set: any).call(this, next) | ||
return next | ||
return (next: any) | ||
} | ||
} | ||
function createValueHandler<V>(initializer?: () => V): IAtomHandler<V, *> { | ||
return function valueHandler(next?: V | Error) { | ||
function createValueHandler<V>(initializer?: () => V): (next?: V | Error) => V { | ||
return function valueHandler(next?: V | Error): V { | ||
return next === undefined && initializer | ||
@@ -72,10 +30,3 @@ ? initializer.call(this) | ||
function setFunctionName(fn: Function, name: string) { | ||
Object.defineProperty(fn, 'name', {value: name, writable: false}) | ||
fn.displayName = name | ||
} | ||
let propForced: IAtomForce = ATOM_FORCE_NONE | ||
function memProp<V, P: Object>( | ||
function mem<V, P: Object>( | ||
proto: P, | ||
@@ -86,5 +37,25 @@ name: string, | ||
const handlerKey = `${name}$` | ||
if (proto[handlerKey] !== undefined) { | ||
return (undefined: any) | ||
if (proto[handlerKey] !== undefined) return descr | ||
const hostAtoms: WeakMap<Object, IAtom<V>> = new WeakMap() | ||
Object.defineProperty(proto, `${name}()`, { | ||
get() { | ||
return hostAtoms.get(this) | ||
} | ||
}) | ||
function value(next?: V): V { | ||
let atom: IAtom<V> | void = hostAtoms.get(this) | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms) | ||
hostAtoms.set(this, atom) | ||
} | ||
return atom.value(next) | ||
} | ||
if (descr.value !== undefined) { | ||
proto[handlerKey] = descr.value | ||
descr.value = value | ||
return descr | ||
} | ||
@@ -95,39 +66,12 @@ const longName = getId(proto, name) | ||
if (descr.set) setFunctionName(descr.set, `set#${longName}`) | ||
const handler = proto[handlerKey] = descr.get === undefined && descr.set === undefined | ||
proto[handlerKey] = descr.get === undefined && descr.set === undefined | ||
? createValueHandler(descr.initializer) | ||
: createGetSetHandler(descr.get, descr.set) | ||
setFunctionName(handler, `${longName}()`) | ||
const hostAtoms: WeakMap<Object, IAtom<V>> = new WeakMap() | ||
Object.defineProperty(proto, `${name}()`, { | ||
get() { | ||
return hostAtoms.get(this) | ||
} | ||
}) | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get() { | ||
let atom: IAtom<V> | void = hostAtoms.get(this) | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms) | ||
hostAtoms.set(this, atom) | ||
} | ||
const forced = propForced | ||
propForced = ATOM_FORCE_NONE | ||
return atom.value(undefined, forced) | ||
}, | ||
set(val: V | Error) { | ||
let atom: IAtom<V> | void = hostAtoms.get(this) | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, hostAtoms) | ||
hostAtoms.set(this, atom) | ||
} | ||
const forced = propForced | ||
propForced = ATOM_FORCE_NONE | ||
;(atom: IAtom<V>).value(val, forced) | ||
} | ||
get: value, | ||
set: (value: Function) | ||
} | ||
@@ -158,7 +102,7 @@ } | ||
function memKeyMethod<V, K, P: Object>( | ||
function memkey<V, K, P: Object>( | ||
proto: P, | ||
name: string, | ||
descr: TypedPropertyDescriptor<IAtomHandler<V, K>> | ||
): TypedPropertyDescriptor<IAtomHandler<V, K>> { | ||
descr: TypedPropertyDescriptor<(k: K, next?: V) => V> | ||
): TypedPropertyDescriptor<(k: K, next?: V) => V> { | ||
const longName = getId(proto, name) | ||
@@ -176,245 +120,62 @@ const handler = descr.value | ||
}) | ||
const forcedFn = function (rawKey: K, next?: V | Error, force?: IAtomForce) { | ||
return this[name](rawKey, next, force === undefined ? ATOM_FORCE_CACHE : force) | ||
} | ||
setFunctionName(forcedFn, `${longName}*`) | ||
proto[`${name}*`] = forcedFn | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
value(rawKey: K, next?: V | Error, force?: IAtomForce) { | ||
let atomMap: Map<string, IAtom<V>> | void = hostAtoms.get(this) | ||
if (atomMap === undefined) { | ||
atomMap = new Map() | ||
hostAtoms.set(this, atomMap) | ||
} | ||
const key = getKey(rawKey) | ||
let atom: IAtom<V> | void = atomMap.get(key) | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, atomMap, rawKey, key) | ||
atomMap.set(key, atom) | ||
} | ||
return (atom: IAtom<V>).value(next, force) | ||
function value(rawKey: K, next?: V | Error): V { | ||
let atomMap: Map<string, IAtom<V>> | void = hostAtoms.get(this) | ||
if (atomMap === undefined) { | ||
atomMap = new Map() | ||
hostAtoms.set(this, atomMap) | ||
} | ||
} | ||
} | ||
type IMemKeyMethod<V, K, P: Object> = ( | ||
proto: P, | ||
name: string, | ||
descr: TypedPropertyDescriptor<IAtomHandler<V, K>> | ||
) => TypedPropertyDescriptor<IAtomHandler<V, K>> | ||
declare function memkey<V, K, P: Object>(): () => IMemKeyMethod<V, K, P> | ||
declare function memkey<V, K, P: Object>( | ||
proto: P, | ||
name: string, | ||
descr: TypedPropertyDescriptor<IAtomHandler<V, K>> | ||
): TypedPropertyDescriptor<IAtomHandler<V, K>> | ||
export function memkey() { | ||
const args = arguments | ||
if (args.length === 3) { | ||
return memKeyMethod(args[0], args[1], args[2]) | ||
} | ||
return function ( | ||
proto: Object, | ||
name: string, | ||
descr: TypedPropertyDescriptor<IAtomHandler<*, *>> | ||
): TypedPropertyDescriptor<IAtomHandler<*, *>> { | ||
return memKeyMethod(proto, name, descr) | ||
} | ||
} | ||
const forceProxyOpts = { | ||
get(t: Object, name: string) { | ||
const forceFn = t[`${name}*`] | ||
if (forceFn === undefined) { | ||
// get/set handler | ||
propForced = ATOM_FORCE_CACHE | ||
return t[name] | ||
const key = getKey(rawKey) | ||
let atom: IAtom<V> | void = atomMap.get(key) | ||
if (atom === undefined) { | ||
atom = new Atom(name, this, defaultContext, atomMap, rawKey, key) | ||
atomMap.set(key, atom) | ||
} | ||
return forceFn.bind(t) | ||
}, | ||
set(t: Object, name: string, val: mixed) { | ||
if (t[`${name}*`] === undefined) { | ||
// get/set handler | ||
propForced = ATOM_FORCE_CACHE | ||
t[name] = val | ||
return true | ||
} | ||
return false | ||
return (atom: IAtom<V>).value(next) | ||
} | ||
} | ||
export function force<V>( | ||
proto: mixed, | ||
name: string, | ||
descr: TypedPropertyDescriptor<V> | ||
): TypedPropertyDescriptor<V> { | ||
const proxyMap: WeakMap<V, any> = new WeakMap() | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get() { | ||
let proxy: V | void = proxyMap.get(this) | ||
if (proxy === undefined) { | ||
proxy = new Proxy(this, forceProxyOpts) | ||
proxyMap.set(this, proxy) | ||
} | ||
return proxy | ||
} | ||
} | ||
} | ||
descr.value = value | ||
export function detached<P: Object, V>( | ||
proto: P, | ||
name: string, | ||
descr: TypedPropertyDescriptor<IAtomPropHandler<V>> | ||
): TypedPropertyDescriptor<IAtomPropHandler<V>> { | ||
return memMethod(proto, name, descr, true) | ||
return descr | ||
} | ||
type IMemProp<V, P: Object> = ( | ||
proto: P, | ||
name: string, | ||
descr: TypedPropertyDescriptor<IAtomHandler<V>> | ||
) => TypedPropertyDescriptor<IAtomHandler<V>> | ||
function createActionMethod(t: Object, name: string, context: IContext): (...args: any[]) => any { | ||
const longName = getId(t, name) | ||
function action() { | ||
let result: mixed | void | ||
const oldNamespace = context.beginTransaction(longName) | ||
const args = arguments | ||
try { | ||
switch (args.length) { | ||
case 0: result = t[name](); break | ||
case 1: result = t[name](args[0]); break | ||
case 2: result = t[name](args[0], args[1]); break | ||
case 3: result = t[name](args[0], args[1], args[2]); break | ||
case 4: result = t[name](args[0], args[1], args[2], args[3]); break | ||
case 5: result = t[name](args[0], args[1], args[2], args[3], args[4]); break | ||
default: result = t[name].apply(t, args) | ||
} | ||
} finally { | ||
context.endTransaction(oldNamespace) | ||
} | ||
return result | ||
const proxyHandler = { | ||
get<V: Object, T: $Keys<V>>(obj: V, key: T): IAtom<$ElementType<V, T>> { | ||
return obj[key + '()'] | ||
} | ||
setFunctionName(action, longName) | ||
return action | ||
} | ||
function createActionFn<F: Function>(fn: F, rawName?: string, context: IContext): F { | ||
const name = rawName || fn.displayName || fn.name | ||
function action(): any { | ||
let result: mixed | void | ||
const oldNamespace = context.beginTransaction(name) | ||
const args = arguments | ||
try { | ||
switch (args.length) { | ||
case 0: result = fn(); break | ||
case 1: result = fn(args[0]); break | ||
case 2: result = fn(args[0], args[1]); break | ||
case 3: result = fn(args[0], args[1], args[2]); break | ||
case 4: result = fn(args[0], args[1], args[2], args[3]); break | ||
case 5: result = fn(args[0], args[1], args[2], args[3], args[4]); break | ||
default: result = fn.apply(null, args) | ||
} | ||
} finally { | ||
context.endTransaction(oldNamespace) | ||
} | ||
return result | ||
} | ||
setFunctionName(action, name) | ||
return (action: any) | ||
function toAtom<V: Object>(obj: V): $ObjMap<V, <T>(T) => IAtom<T>> { | ||
return new Proxy(obj, proxyHandler) | ||
} | ||
function actionMethod<V, P: Object>( | ||
proto: P, | ||
name: string, | ||
descr: TypedPropertyDescriptor<*>, | ||
context: IContext | ||
): TypedPropertyDescriptor<*> { | ||
const hk = `${name}$` | ||
if (descr.value === undefined) { | ||
throw new TypeError(`${getId(proto, name)} is not an function (next?: V)`) | ||
} | ||
proto[hk] = descr.value | ||
let definingProperty = false | ||
return { | ||
enumerable: descr.enumerable, | ||
configurable: descr.configurable, | ||
get() { | ||
if (definingProperty) { | ||
return this[hk] | ||
} | ||
definingProperty = true | ||
const actionFn = createActionMethod(this, hk, context) | ||
Object.defineProperty(this, name, { | ||
configurable: true, | ||
value: actionFn | ||
}) | ||
definingProperty = false | ||
return actionFn | ||
} | ||
} | ||
function cache<V>(data: V): V { | ||
defaultContext.prevForce = defaultContext.force | ||
defaultContext.force = ATOM_FORCE_CACHE | ||
return data | ||
} | ||
declare function action<F: Function>(fn: F, name?: string): F | ||
declare function action( | ||
proto: Object, | ||
name: string, | ||
descr: TypedPropertyDescriptor<*> | ||
): TypedPropertyDescriptor<*> | ||
export function action() { | ||
const args = arguments | ||
if (args.length === 3) { | ||
return actionMethod(args[0], args[1], args[2], defaultContext) | ||
} | ||
return createActionFn(args[0], args[1], defaultContext) | ||
function force<V>(data: V): V { | ||
defaultContext.prevForce = defaultContext.force | ||
defaultContext.force = ATOM_FORCE_UPDATE | ||
return data | ||
} | ||
declare function mem<V, P: Object>(): () => IMemProp<V, P> | ||
declare function mem<V, P: Object>( | ||
proto: P, | ||
name: string, | ||
descr: TypedPropertyDescriptor<V> | ||
): TypedPropertyDescriptor<*> | ||
mem.cache = cache | ||
mem.force = force | ||
mem.key = memkey | ||
mem.Wait = AtomWait | ||
mem.toAtom = toAtom | ||
export default function mem() { | ||
const args = arguments | ||
if (args.length === 3) { | ||
return args[2].value === undefined | ||
? memProp(args[0], args[1], args[2]) | ||
: memMethod(args[0], args[1], args[2]) | ||
} | ||
return function ( | ||
proto: Object, | ||
name: string, | ||
descr: TypedPropertyDescriptor<*> | ||
): TypedPropertyDescriptor<*> { | ||
return descr.value === undefined | ||
? memProp(proto, name, descr) | ||
: memMethod(proto, name, descr) | ||
} | ||
type IMem = { | ||
<V, P: Object>(proto: P, name: string, descr: TypedPropertyDescriptor<V>): TypedPropertyDescriptor<V>; | ||
cache: typeof cache; | ||
force: typeof force; | ||
key: typeof memkey; | ||
toAtom: typeof toAtom; | ||
Wait: Class<AtomWait>; | ||
} | ||
mem.Wait = AtomWait | ||
mem.key = memkey | ||
mem.detached = detached | ||
export default (mem: IMem) |
// @flow | ||
import {catchedId, origId} from './interfaces' | ||
import {catchedId} from './interfaces' | ||
const throwOnAccess = { | ||
get<V: Object>(target: Error, key: string): V { | ||
if (key === origId) return (target: Object).valueOf() | ||
throw target.valueOf() | ||
}, | ||
ownKeys(target: Error): string[] { | ||
throw target.valueOf() | ||
} | ||
} | ||
export function createMock(error: Error): any { | ||
return new Proxy(error, throwOnAccess) | ||
} | ||
export class AtomWait extends Error { | ||
@@ -27,1 +13,10 @@ constructor(message?: string = 'Wait...') { | ||
} | ||
export function getId(t: Object, hk: string): string { | ||
return `${t.constructor.displayName || t.constructor.name}.${hk}` | ||
} | ||
export function setFunctionName(fn: Function, name: string) { | ||
Object.defineProperty(fn, 'name', {value: name, writable: false}) | ||
fn.displayName = name | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
24
319521
3312
162