Comparing version 0.1.6 to 0.1.7
@@ -1,2 +0,2 @@ | ||
var t=100,i=new Set,n=new Set,r=[],s=!1,o=function(t){Promise.resolve().then(t).catch(h)},h=function(t){console.error("Reaction exception:",t)};function u(){try{for(var o=t;r.length||n.size;){for(n.forEach(function(t){t.t(!1)}),n.clear();r.length&&--o;){var u=r;r=[],u.forEach(function(t){try{t.runManager()}catch(t){h(t)}})}if(!o)throw new Error("Infinite reactions loop")}}finally{s=!1,r=[],i.forEach(function(t){t.i()}),i.clear()}}var f=null;function e(t){var i=f;return f=t,i}var c=0;function a(t,i){void 0===i&&(i=null);var n=e(i);c+=1;try{return t()}finally{c-=1,e(n),l()}}function v(t){return function(){var i=e(null);try{return t.apply(this,arguments)}finally{e(i)}}}function l(){c||!s&&(r.length||n.size||i.size)&&(s=!0,o(u))}var p=Object.prototype.hasOwnProperty;function w(t){return t.constructor===Object||null===t.constructor}function y(t,i){if(t===i)return!0;if(Array.isArray(t)&&Array.isArray(i)){var n=t.length;if(n!==i.length)return!1;for(;n--;)if(t[n]!==i[n])return!1;return!0}if(t&&i&&"object"==typeof t&&"object"==typeof i&&w(t)&&w(i)){var r=Object.keys(t),s=r.length;if(Object.keys(i).length!==s)return!1;for(;s-- >0;){var o=r[s];if(!p.call(i,o)||t[o]!==i[o])return!1}return!0}if(t instanceof Set&&i instanceof Set){if(t.size!==i.size)return!1;var h=!0;return t.forEach(function(t){i.has(t)||(h=!1)}),h}if(t instanceof Map&&i instanceof Map){if(t.size!==i.size)return!1;var u=!0;return t.forEach(function(t,n){i.get(n)!==t&&(u=!1)}),u}return!1}var x=v(y),Revision=function(){};function d(t){var i=!1;return t.forEach(function(t,n){i||(i=n.revision()!==t)}),i}function b(t,i){t.forEach(function(t,n){n.o(i)})}function j(t,i){t.forEach(function(t,n){n.h(i)})}function S(t,i){t.forEach(function(t){t.u(i)})}var Computed=/*#__PURE__*/function(){function Computed(t,i){this.v=void 0,this.l=new Revision,this.p=new Set,this.j=new Map,this.S=0,this.M=t,this.O=i?"function"==typeof i?v(i):x:void 0}var t=Computed.prototype;return t.addSubscription=function(t){2!==this.S&&t.h(this),this.j.set(t,t.revision())},t.h=function(t){this.p.add(t),6===this.S&&this.m()},t.o=function(t){this.p.delete(t),this.p.size||6===this.S||function(t){i.add(t)}(this)},t.i=function(){this.p.size||6===this.S||this.g()},t.u=function(t){var i=this.S;i!==t&&5!==i&&(this.O?(function(t){n.add(t)}(this),3===i&&this.A(4)):this.A(t),this.S=t,5===t&&this.R())},t.t=function(t){if((6!==this.S||d(this.j))&&(4===this.S&&(this.j.forEach(function(i,n){n.t(t)}),4===this.S&&(this.S=3)),3!==this.S)){var i=this.S,n=0!==i,r=t||n&&6!==i;this.j.clear(),this.S=r?1:2;var s=e(this);try{var o=this.M();if(this.S=r?3:6,this.O&&n){if(this.O(this.v,o))return;this.A(5)}this.v=o,this.l=new Revision}catch(t){throw this.destroy(),t}finally{e(s)}}},t.revision=function(){return this.t(!1),this.l},t.destroy=function(){this.R(),this.j.clear(),this.S=0,this.v=void 0},t.get=function(t){if(void 0===t&&(t=f),1===this.S||2===this.S)throw new Error("Recursive computed call");return this.t(null!==f),t&&t.addSubscription(this),this.v},t.C=function(){j(this.j,this)},t.R=function(){b(this.j,this)},t.A=function(t){S(this.p,t)},t.g=function(){this.R(),this.S=6},t.m=function(){this.C(),this.S=3},Computed}();function M(t,i){var n=new Computed(t,i),r=n.get.bind(n);return r.instance=n,r.destroy=n.destroy.bind(n),r.revision=n.revision.bind(n),r}M.box=function(t,i){return new Computed(t,i)},M.prop=function(t,i){return new Computed(t,i)};var Observable=/*#__PURE__*/function(){function Observable(t,i){this.l=new Revision,this.p=new Set,this.v=t,this.O=i?"function"==typeof i?v(i):x:void 0}var t=Observable.prototype;return t.h=function(t){this.p.add(t)},t.o=function(t){this.p.delete(t)},t.t=function(){},t.revision=function(){return this.l},t.get=function(t){return void 0===t&&(t=f),t&&t.addSubscription(this),this.v},t.set=function(t,i){if(f&&f instanceof Computed)throw new Error("Changing observable inside of computed");if(arguments.length>0){if("function"!=typeof t||i||(t=t(this.v)),this.O&&this.O(this.v,t))return;this.v=t}this.notify()},t.notify=function(){this.l=new Revision,S(this.p,5),l()},Observable}();function O(t,i){var n=new Observable(t,i),r=n.get.bind(n),s=n.set.bind(n);return r.instance=n,r.revision=n.revision.bind(n),[r,s]}O.box=function(t,i){return new Observable(t,i)},O.prop=function(t,i){return new Observable(t,i)};var Reaction=/*#__PURE__*/function(){function Reaction(t,i){var n=this;this.M=void 0,this.I=void 0,this.shouldSubscribe=!0,this.j=new Map,this.P=null,this.S=3,this.k=function(){n.P=n.M()},this.M=t,this.I=i}var t=Reaction.prototype;return t.addSubscription=function(t){this.shouldSubscribe&&t.h(this),this.j.set(t,t.revision())},t.u=function(t){4!==t&&3===this.S&&(this.S=5,r.push(this))},t.runManager=function(){7!==this.S&&(this.I?this.I():this.run())},t.subscribe=function(){j(this.j,this)},t.unsubscribe=function(){b(this.j,this)},t.unsubscribeAndCleanup=function(){this.unsubscribe(),this.j.clear(),this.P&&this.P(),this.P=null,this.S=3},t.missedRun=function(){return d(this.j)},t.destroy=function(){this.unsubscribeAndCleanup(),this.S=7},t.run=function(){this.unsubscribeAndCleanup(),a(this.k,this)},t.updateRevisions=function(){var t=this;this.j.forEach(function(i,n){t.j.set(n,n.revision())})},Reaction}();exports.Computed=Computed,exports.Observable=Observable,exports.Reaction=Reaction,exports.Revision=Revision,exports.action=function(t){return function(){var i=e(null);c+=1;try{return t.apply(this,arguments)}finally{c-=1,e(i),l()}}},exports.computed=M,exports.configure=function(t){t.reactionScheduler&&(o=t.reactionScheduler),t.reactionExceptionHandler&&(h=t.reactionExceptionHandler)},exports.observable=O,exports.reaction=function(t,i){var n=new Reaction(t,i),r=n.destroy.bind(n);return r.run=n.run.bind(n),n.run(),r},exports.setSubscriber=e,exports.shallowEquals=y,exports.tx=function(t){c+=1;try{t()}finally{c-=1,l()}},exports.untracked=function(t){var i=e(null);try{return t()}finally{e(i)}},exports.utx=a,exports.withUntracked=v; | ||
var t=1e3,i=new Set,n=new Set,r=[],s=!1,o=function(t){Promise.resolve().then(t).catch(h)},h=function(t){console.error("Reaction exception:",t)};function u(){try{for(var o=t;(r.length||n.size)&&--o;){n.forEach(function(t){t.t(!1)}),n.clear();var u=r;r=[],u.forEach(function(t){try{t.runManager()}catch(t){h(t)}})}if(!o)throw new Error("Infinite reactions loop")}finally{s=!1,r=[],i.forEach(function(t){i.delete(t),t.i()}),i.clear()}}var f=null;function e(t){var i=f;return f=t,i}var c=0;function a(t,i){void 0===i&&(i=null);var n=e(i);c+=1;try{return t()}finally{c-=1,e(n),l()}}function v(t){return function(){var i=e(null);try{return t.apply(this,arguments)}finally{e(i)}}}function l(){c||!s&&(r.length||n.size)&&(s=!0,o(u))}var p=Object.prototype.hasOwnProperty;function w(t){return t.constructor===Object||null===t.constructor}function y(t,i){if(t===i)return!0;if(Array.isArray(t)&&Array.isArray(i)){var n=t.length;if(n!==i.length)return!1;for(;n--;)if(t[n]!==i[n])return!1;return!0}if(t&&i&&"object"==typeof t&&"object"==typeof i&&w(t)&&w(i)){var r=Object.keys(t),s=r.length;if(Object.keys(i).length!==s)return!1;for(;s-- >0;){var o=r[s];if(!p.call(i,o)||t[o]!==i[o])return!1}return!0}if(t instanceof Set&&i instanceof Set){if(t.size!==i.size)return!1;var h=!0;return t.forEach(function(t){i.has(t)||(h=!1)}),h}if(t instanceof Map&&i instanceof Map){if(t.size!==i.size)return!1;var u=!0;return t.forEach(function(t,n){i.get(n)!==t&&(u=!1)}),u}return!1}var x=v(y),Revision=function(){};function d(t){var i=!1;return t.forEach(function(t,n){i||(i=n.revision()!==t)}),i}function b(t,i){t.forEach(function(t,n){n.o(i)})}function j(t,i){t.forEach(function(t,n){n.h(i)})}function S(t,i){t.forEach(function(t){t.u(i)})}var Computed=/*#__PURE__*/function(){function Computed(t,i){this.v=void 0,this.l=new Revision,this.p=new Set,this.j=new Map,this.S=0,this.M=t,this.O=i?"function"==typeof i?v(i):x:void 0}var t=Computed.prototype;return t.addSubscription=function(t){2!==this.S&&t.h(this),this.j.set(t,t.revision())},t.h=function(t){this.p.add(t),6===this.S&&(j(this.j,this),this.S=3)},t.o=function(t){this.p.delete(t),this.p.size||6===this.S||function(t){i.add(t)}(this)},t.i=function(){this.p.size||6===this.S||(b(this.j,this),this.S=6)},t.u=function(t){var i=this.S;i!==t&&5!==i&&(this.O?(function(t){n.add(t)}(this),3===i&&S(this.p,4)):S(this.p,t),this.S=t,5===t&&b(this.j,this))},t.t=function(t){if((6!==this.S||d(this.j))&&(4===this.S&&(this.j.forEach(function(i,n){n.t(t)}),4===this.S&&(this.S=3)),3!==this.S)){var i=this.S,n=0!==i,r=t||n&&6!==i;this.S=r?1:2,this.j.clear();var s=e(this);try{var o=this.M();if(this.S=r?3:6,this.O&&n){if(this.O(this.v,o))return;S(this.p,5)}this.v=o,this.l=new Revision}catch(t){throw this.destroy(),t}finally{e(s)}}},t.revision=function(){return this.t(!1),this.l},t.destroy=function(){b(this.j,this),this.j.clear(),this.S=0,this.v=void 0},t.get=function(t){if(void 0===t&&(t=f),1===this.S||2===this.S)throw new Error("Recursive computed call");return this.t(null!==f),t&&t.addSubscription(this),this.v},Computed}();function M(t,i){var n=new Computed(t,i),r=n.get.bind(n);return r.instance=n,r.destroy=n.destroy.bind(n),r.revision=n.revision.bind(n),r}M.box=function(t,i){return new Computed(t,i)},M.prop=function(t,i){return new Computed(t,i)};var Observable=/*#__PURE__*/function(){function Observable(t,i){this.l=new Revision,this.p=new Set,this.v=t,this.O=i?"function"==typeof i?v(i):x:void 0}var t=Observable.prototype;return t.h=function(t){this.p.add(t)},t.o=function(t){this.p.delete(t)},t.t=function(){},t.revision=function(){return this.l},t.get=function(t){return void 0===t&&(t=f),t&&t.addSubscription(this),this.v},t.set=function(t,i){if(f&&f instanceof Computed)throw new Error("Changing observable inside of computed");if(arguments.length>0){if("function"!=typeof t||i||(t=t(this.v)),this.O&&this.O(this.v,t))return;this.v=t}this.notify()},t.notify=function(){this.l=new Revision,S(this.p,5),l()},Observable}();function O(t,i){var n=new Observable(t,i),r=n.get.bind(n),s=n.set.bind(n);return r.instance=n,r.revision=n.revision.bind(n),[r,s]}O.box=function(t,i){return new Observable(t,i)},O.prop=function(t,i){return new Observable(t,i)};var Reaction=/*#__PURE__*/function(){function Reaction(t,i){var n=this;this.M=void 0,this.m=void 0,this.shouldSubscribe=!0,this.j=new Map,this.g=null,this.S=3,this.A=function(){n.g=n.M()},this.M=t,this.m=i}var t=Reaction.prototype;return t.addSubscription=function(t){this.shouldSubscribe&&t.h(this),this.j.set(t,t.revision())},t.u=function(t){4!==t&&3===this.S&&(this.S=5,r.push(this))},t.runManager=function(){7!==this.S&&(this.m?this.m():this.run())},t.subscribe=function(){j(this.j,this)},t.unsubscribe=function(){b(this.j,this)},t.unsubscribeAndCleanup=function(){this.unsubscribe(),this.j.clear(),this.g&&this.g(),this.g=null,this.S=3},t.missedRun=function(){return d(this.j)},t.destroy=function(){this.unsubscribeAndCleanup(),this.S=7},t.run=function(){this.unsubscribeAndCleanup(),a(this.A,this)},t.updateRevisions=function(){var t=this;this.j.forEach(function(i,n){t.j.set(n,n.revision())})},Reaction}();exports.Computed=Computed,exports.Observable=Observable,exports.Reaction=Reaction,exports.Revision=Revision,exports.action=function(t){return function(){var i=e(null);c+=1;try{return t.apply(this,arguments)}finally{c-=1,e(i),l()}}},exports.computed=M,exports.configure=function(t){t.reactionScheduler&&(o=t.reactionScheduler),t.reactionExceptionHandler&&(h=t.reactionExceptionHandler)},exports.observable=O,exports.reaction=function(t,i){var n=new Reaction(t,i),r=n.destroy.bind(n);return r.run=n.run.bind(n),n.run(),r},exports.setSubscriber=e,exports.shallowEquals=y,exports.tx=function(t){c+=1;try{t()}finally{c-=1,l()}},exports.untracked=function(t){var i=e(null);try{return t()}finally{e(i)}},exports.utx=a,exports.withUntracked=v; | ||
//# sourceMappingURL=onek.js.map |
@@ -1,2 +0,2 @@ | ||
var t=100,n=new Set,i=new Set,r=[],s=!1,u=function(t){Promise.resolve().then(t).catch(h)},h=function(t){console.error("Reaction exception:",t)};function o(){try{for(var u=t;r.length||i.size;){for(i.forEach(function(t){t.t(!1)}),i.clear();r.length&&--u;){var o=r;r=[],o.forEach(function(t){try{t.runManager()}catch(t){h(t)}})}if(!u)throw new Error("Infinite reactions loop")}}finally{s=!1,r=[],n.forEach(function(t){t.i()}),n.clear()}}function f(t){t.reactionScheduler&&(u=t.reactionScheduler),t.reactionExceptionHandler&&(h=t.reactionExceptionHandler)}var c=null;function e(t){var n=c;return c=t,n}var a=0;function v(t){a+=1;try{t()}finally{a-=1,d()}}function l(t,n){void 0===n&&(n=null);var i=e(n);a+=1;try{return t()}finally{a-=1,e(i),d()}}function w(t){var n=e(null);try{return t()}finally{e(n)}}function y(t){return function(){var n=e(null);try{return t.apply(this,arguments)}finally{e(n)}}}function p(t){return function(){var n=e(null);a+=1;try{return t.apply(this,arguments)}finally{a-=1,e(n),d()}}}function d(){a||!s&&(r.length||i.size||n.size)&&(s=!0,u(o))}var b=Object.prototype.hasOwnProperty;function j(t){return t.constructor===Object||null===t.constructor}function S(t,n){if(t===n)return!0;if(Array.isArray(t)&&Array.isArray(n)){var i=t.length;if(i!==n.length)return!1;for(;i--;)if(t[i]!==n[i])return!1;return!0}if(t&&n&&"object"==typeof t&&"object"==typeof n&&j(t)&&j(n)){var r=Object.keys(t),s=r.length;if(Object.keys(n).length!==s)return!1;for(;s-- >0;){var u=r[s];if(!b.call(n,u)||t[u]!==n[u])return!1}return!0}if(t instanceof Set&&n instanceof Set){if(t.size!==n.size)return!1;var h=!0;return t.forEach(function(t){n.has(t)||(h=!1)}),h}if(t instanceof Map&&n instanceof Map){if(t.size!==n.size)return!1;var o=!0;return t.forEach(function(t,i){n.get(i)!==t&&(o=!1)}),o}return!1}var M=y(S),Revision=function(){};function O(t){var n=!1;return t.forEach(function(t,i){n||(n=i.revision()!==t)}),n}function m(t,n){t.forEach(function(t,i){i.u(n)})}function E(t,n){t.forEach(function(t,i){i.h(n)})}function g(t,n){t.forEach(function(t){t.o(n)})}var Computed=/*#__PURE__*/function(){function Computed(t,n){this.v=void 0,this.l=new Revision,this.p=new Set,this.j=new Map,this.S=0,this.M=t,this.O=n?"function"==typeof n?y(n):M:void 0}var t=Computed.prototype;return t.addSubscription=function(t){2!==this.S&&t.h(this),this.j.set(t,t.revision())},t.h=function(t){this.p.add(t),6===this.S&&this.m()},t.u=function(t){this.p.delete(t),this.p.size||6===this.S||function(t){n.add(t)}(this)},t.i=function(){this.p.size||6===this.S||this.g()},t.o=function(t){var n=this.S;n!==t&&5!==n&&(this.O?(function(t){i.add(t)}(this),3===n&&this.A(4)):this.A(t),this.S=t,5===t&&this.R())},t.t=function(t){if((6!==this.S||O(this.j))&&(4===this.S&&(this.j.forEach(function(n,i){i.t(t)}),4===this.S&&(this.S=3)),3!==this.S)){var n=this.S,i=0!==n,r=t||i&&6!==n;this.j.clear(),this.S=r?1:2;var s=e(this);try{var u=this.M();if(this.S=r?3:6,this.O&&i){if(this.O(this.v,u))return;this.A(5)}this.v=u,this.l=new Revision}catch(t){throw this.destroy(),t}finally{e(s)}}},t.revision=function(){return this.t(!1),this.l},t.destroy=function(){this.R(),this.j.clear(),this.S=0,this.v=void 0},t.get=function(t){if(void 0===t&&(t=c),1===this.S||2===this.S)throw new Error("Recursive computed call");return this.t(null!==c),t&&t.addSubscription(this),this.v},t.C=function(){E(this.j,this)},t.R=function(){m(this.j,this)},t.A=function(t){g(this.p,t)},t.g=function(){this.R(),this.S=6},t.m=function(){this.C(),this.S=3},Computed}();function x(t,n){var i=new Computed(t,n),r=i.get.bind(i);return r.instance=i,r.destroy=i.destroy.bind(i),r.revision=i.revision.bind(i),r}x.box=function(t,n){return new Computed(t,n)},x.prop=function(t,n){return new Computed(t,n)};var Observable=/*#__PURE__*/function(){function Observable(t,n){this.l=new Revision,this.p=new Set,this.v=t,this.O=n?"function"==typeof n?y(n):M:void 0}var t=Observable.prototype;return t.h=function(t){this.p.add(t)},t.u=function(t){this.p.delete(t)},t.t=function(){},t.revision=function(){return this.l},t.get=function(t){return void 0===t&&(t=c),t&&t.addSubscription(this),this.v},t.set=function(t,n){if(c&&c instanceof Computed)throw new Error("Changing observable inside of computed");if(arguments.length>0){if("function"!=typeof t||n||(t=t(this.v)),this.O&&this.O(this.v,t))return;this.v=t}this.notify()},t.notify=function(){this.l=new Revision,g(this.p,5),d()},Observable}();function A(t,n){var i=new Observable(t,n),r=i.get.bind(i),s=i.set.bind(i);return r.instance=i,r.revision=i.revision.bind(i),[r,s]}A.box=function(t,n){return new Observable(t,n)},A.prop=function(t,n){return new Observable(t,n)};var Reaction=/*#__PURE__*/function(){function Reaction(t,n){var i=this;this.M=void 0,this.I=void 0,this.shouldSubscribe=!0,this.j=new Map,this.P=null,this.S=3,this.k=function(){i.P=i.M()},this.M=t,this.I=n}var t=Reaction.prototype;return t.addSubscription=function(t){this.shouldSubscribe&&t.h(this),this.j.set(t,t.revision())},t.o=function(t){4!==t&&3===this.S&&(this.S=5,function(t){r.push(t)}(this))},t.runManager=function(){7!==this.S&&(this.I?this.I():this.run())},t.subscribe=function(){E(this.j,this)},t.unsubscribe=function(){m(this.j,this)},t.unsubscribeAndCleanup=function(){this.unsubscribe(),this.j.clear(),this.P&&this.P(),this.P=null,this.S=3},t.missedRun=function(){return O(this.j)},t.destroy=function(){this.unsubscribeAndCleanup(),this.S=7},t.run=function(){this.unsubscribeAndCleanup(),l(this.k,this)},t.updateRevisions=function(){var t=this;this.j.forEach(function(n,i){t.j.set(i,i.revision())})},Reaction}();function R(t,n){var i=new Reaction(t,n),r=i.destroy.bind(i);return r.run=i.run.bind(i),i.run(),r}export{Computed,Observable,Reaction,Revision,p as action,x as computed,f as configure,A as observable,R as reaction,e as setSubscriber,S as shallowEquals,v as tx,w as untracked,l as utx,y as withUntracked}; | ||
var t=1e3,i=new Set,n=new Set,r=[],s=!1,h=function(t){Promise.resolve().then(t).catch(u)},u=function(t){console.error("Reaction exception:",t)};function o(){try{for(var h=t;(r.length||n.size)&&--h;){n.forEach(function(t){t.t(!1)}),n.clear();var o=r;r=[],o.forEach(function(t){try{t.runManager()}catch(t){u(t)}})}if(!h)throw new Error("Infinite reactions loop")}finally{s=!1,r=[],i.forEach(function(t){i.delete(t),t.i()}),i.clear()}}function f(t){t.reactionScheduler&&(h=t.reactionScheduler),t.reactionExceptionHandler&&(u=t.reactionExceptionHandler)}var c=null;function e(t){var i=c;return c=t,i}var a=0;function v(t){a+=1;try{t()}finally{a-=1,d()}}function l(t,i){void 0===i&&(i=null);var n=e(i);a+=1;try{return t()}finally{a-=1,e(n),d()}}function w(t){var i=e(null);try{return t()}finally{e(i)}}function y(t){return function(){var i=e(null);try{return t.apply(this,arguments)}finally{e(i)}}}function p(t){return function(){var i=e(null);a+=1;try{return t.apply(this,arguments)}finally{a-=1,e(i),d()}}}function d(){a||!s&&(r.length||n.size)&&(s=!0,h(o))}var b=Object.prototype.hasOwnProperty;function j(t){return t.constructor===Object||null===t.constructor}function S(t,i){if(t===i)return!0;if(Array.isArray(t)&&Array.isArray(i)){var n=t.length;if(n!==i.length)return!1;for(;n--;)if(t[n]!==i[n])return!1;return!0}if(t&&i&&"object"==typeof t&&"object"==typeof i&&j(t)&&j(i)){var r=Object.keys(t),s=r.length;if(Object.keys(i).length!==s)return!1;for(;s-- >0;){var h=r[s];if(!b.call(i,h)||t[h]!==i[h])return!1}return!0}if(t instanceof Set&&i instanceof Set){if(t.size!==i.size)return!1;var u=!0;return t.forEach(function(t){i.has(t)||(u=!1)}),u}if(t instanceof Map&&i instanceof Map){if(t.size!==i.size)return!1;var o=!0;return t.forEach(function(t,n){i.get(n)!==t&&(o=!1)}),o}return!1}var M=y(S),Revision=function(){};function O(t){var i=!1;return t.forEach(function(t,n){i||(i=n.revision()!==t)}),i}function m(t,i){t.forEach(function(t,n){n.h(i)})}function E(t,i){t.forEach(function(t,n){n.u(i)})}function g(t,i){t.forEach(function(t){t.o(i)})}var Computed=/*#__PURE__*/function(){function Computed(t,i){this.v=void 0,this.l=new Revision,this.p=new Set,this.j=new Map,this.S=0,this.M=t,this.O=i?"function"==typeof i?y(i):M:void 0}var t=Computed.prototype;return t.addSubscription=function(t){2!==this.S&&t.u(this),this.j.set(t,t.revision())},t.u=function(t){this.p.add(t),6===this.S&&(E(this.j,this),this.S=3)},t.h=function(t){this.p.delete(t),this.p.size||6===this.S||function(t){i.add(t)}(this)},t.i=function(){this.p.size||6===this.S||(m(this.j,this),this.S=6)},t.o=function(t){var i=this.S;i!==t&&5!==i&&(this.O?(function(t){n.add(t)}(this),3===i&&g(this.p,4)):g(this.p,t),this.S=t,5===t&&m(this.j,this))},t.t=function(t){if((6!==this.S||O(this.j))&&(4===this.S&&(this.j.forEach(function(i,n){n.t(t)}),4===this.S&&(this.S=3)),3!==this.S)){var i=this.S,n=0!==i,r=t||n&&6!==i;this.S=r?1:2,this.j.clear();var s=e(this);try{var h=this.M();if(this.S=r?3:6,this.O&&n){if(this.O(this.v,h))return;g(this.p,5)}this.v=h,this.l=new Revision}catch(t){throw this.destroy(),t}finally{e(s)}}},t.revision=function(){return this.t(!1),this.l},t.destroy=function(){m(this.j,this),this.j.clear(),this.S=0,this.v=void 0},t.get=function(t){if(void 0===t&&(t=c),1===this.S||2===this.S)throw new Error("Recursive computed call");return this.t(null!==c),t&&t.addSubscription(this),this.v},Computed}();function x(t,i){var n=new Computed(t,i),r=n.get.bind(n);return r.instance=n,r.destroy=n.destroy.bind(n),r.revision=n.revision.bind(n),r}x.box=function(t,i){return new Computed(t,i)},x.prop=function(t,i){return new Computed(t,i)};var Observable=/*#__PURE__*/function(){function Observable(t,i){this.l=new Revision,this.p=new Set,this.v=t,this.O=i?"function"==typeof i?y(i):M:void 0}var t=Observable.prototype;return t.u=function(t){this.p.add(t)},t.h=function(t){this.p.delete(t)},t.t=function(){},t.revision=function(){return this.l},t.get=function(t){return void 0===t&&(t=c),t&&t.addSubscription(this),this.v},t.set=function(t,i){if(c&&c instanceof Computed)throw new Error("Changing observable inside of computed");if(arguments.length>0){if("function"!=typeof t||i||(t=t(this.v)),this.O&&this.O(this.v,t))return;this.v=t}this.notify()},t.notify=function(){this.l=new Revision,g(this.p,5),d()},Observable}();function A(t,i){var n=new Observable(t,i),r=n.get.bind(n),s=n.set.bind(n);return r.instance=n,r.revision=n.revision.bind(n),[r,s]}A.box=function(t,i){return new Observable(t,i)},A.prop=function(t,i){return new Observable(t,i)};var Reaction=/*#__PURE__*/function(){function Reaction(t,i){var n=this;this.M=void 0,this.m=void 0,this.shouldSubscribe=!0,this.j=new Map,this.g=null,this.S=3,this.A=function(){n.g=n.M()},this.M=t,this.m=i}var t=Reaction.prototype;return t.addSubscription=function(t){this.shouldSubscribe&&t.u(this),this.j.set(t,t.revision())},t.o=function(t){4!==t&&3===this.S&&(this.S=5,function(t){r.push(t)}(this))},t.runManager=function(){7!==this.S&&(this.m?this.m():this.run())},t.subscribe=function(){E(this.j,this)},t.unsubscribe=function(){m(this.j,this)},t.unsubscribeAndCleanup=function(){this.unsubscribe(),this.j.clear(),this.g&&this.g(),this.g=null,this.S=3},t.missedRun=function(){return O(this.j)},t.destroy=function(){this.unsubscribeAndCleanup(),this.S=7},t.run=function(){this.unsubscribeAndCleanup(),l(this.A,this)},t.updateRevisions=function(){var t=this;this.j.forEach(function(i,n){t.j.set(n,n.revision())})},Reaction}();function R(t,i){var n=new Reaction(t,i),r=n.destroy.bind(n);return r.run=n.run.bind(n),n.run(),r}export{Computed,Observable,Reaction,Revision,p as action,x as computed,f as configure,A as observable,R as reaction,e as setSubscriber,S as shallowEquals,v as tx,w as untracked,l as utx,y as withUntracked}; | ||
//# sourceMappingURL=onek.module.js.map |
@@ -1,2 +0,2 @@ | ||
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t||self).onek={})}(this,function(t){var n=100,i=new Set,r=new Set,s=[],o=!1,u=function(t){Promise.resolve().then(t).catch(f)},f=function(t){console.error("Reaction exception:",t)};function h(){try{for(var t=n;s.length||r.size;){for(r.forEach(function(t){t.t(!1)}),r.clear();s.length&&--t;){var u=s;s=[],u.forEach(function(t){try{t.runManager()}catch(t){f(t)}})}if(!t)throw new Error("Infinite reactions loop")}}finally{o=!1,s=[],i.forEach(function(t){t.i()}),i.clear()}}var e=null;function c(t){var n=e;return e=t,n}var a=0;function v(t,n){void 0===n&&(n=null);var i=c(n);a+=1;try{return t()}finally{a-=1,c(i),y()}}function l(t){return function(){var n=c(null);try{return t.apply(this,arguments)}finally{c(n)}}}function y(){a||!o&&(s.length||r.size||i.size)&&(o=!0,u(h))}var w=Object.prototype.hasOwnProperty;function d(t){return t.constructor===Object||null===t.constructor}function p(t,n){if(t===n)return!0;if(Array.isArray(t)&&Array.isArray(n)){var i=t.length;if(i!==n.length)return!1;for(;i--;)if(t[i]!==n[i])return!1;return!0}if(t&&n&&"object"==typeof t&&"object"==typeof n&&d(t)&&d(n)){var r=Object.keys(t),s=r.length;if(Object.keys(n).length!==s)return!1;for(;s-- >0;){var o=r[s];if(!w.call(n,o)||t[o]!==n[o])return!1}return!0}if(t instanceof Set&&n instanceof Set){if(t.size!==n.size)return!1;var u=!0;return t.forEach(function(t){n.has(t)||(u=!1)}),u}if(t instanceof Map&&n instanceof Map){if(t.size!==n.size)return!1;var f=!0;return t.forEach(function(t,i){n.get(i)!==t&&(f=!1)}),f}return!1}var b=l(p),Revision=function(){};function j(t){var n=!1;return t.forEach(function(t,i){n||(n=i.revision()!==t)}),n}function S(t,n){t.forEach(function(t,i){i.o(n)})}function g(t,n){t.forEach(function(t,i){i.u(n)})}function m(t,n){t.forEach(function(t){t.h(n)})}var Computed=/*#__PURE__*/function(){function Computed(t,n){this.v=void 0,this.l=new Revision,this.p=new Set,this.j=new Map,this.S=0,this.g=t,this.m=n?"function"==typeof n?l(n):b:void 0}var t=Computed.prototype;return t.addSubscription=function(t){2!==this.S&&t.u(this),this.j.set(t,t.revision())},t.u=function(t){this.p.add(t),6===this.S&&this.M()},t.o=function(t){this.p.delete(t),this.p.size||6===this.S||function(t){i.add(t)}(this)},t.i=function(){this.p.size||6===this.S||this.O()},t.h=function(t){var n=this.S;n!==t&&5!==n&&(this.m?(function(t){r.add(t)}(this),3===n&&this.A(4)):this.A(t),this.S=t,5===t&&this.R())},t.t=function(t){if((6!==this.S||j(this.j))&&(4===this.S&&(this.j.forEach(function(n,i){i.t(t)}),4===this.S&&(this.S=3)),3!==this.S)){var n=this.S,i=0!==n,r=t||i&&6!==n;this.j.clear(),this.S=r?1:2;var s=c(this);try{var o=this.g();if(this.S=r?3:6,this.m&&i){if(this.m(this.v,o))return;this.A(5)}this.v=o,this.l=new Revision}catch(t){throw this.destroy(),t}finally{c(s)}}},t.revision=function(){return this.t(!1),this.l},t.destroy=function(){this.R(),this.j.clear(),this.S=0,this.v=void 0},t.get=function(t){if(void 0===t&&(t=e),1===this.S||2===this.S)throw new Error("Recursive computed call");return this.t(null!==e),t&&t.addSubscription(this),this.v},t.T=function(){g(this.j,this)},t.R=function(){S(this.j,this)},t.A=function(t){m(this.p,t)},t.O=function(){this.R(),this.S=6},t.M=function(){this.T(),this.S=3},Computed}();function x(t,n){var i=new Computed(t,n),r=i.get.bind(i);return r.instance=i,r.destroy=i.destroy.bind(i),r.revision=i.revision.bind(i),r}x.box=function(t,n){return new Computed(t,n)},x.prop=function(t,n){return new Computed(t,n)};var Observable=/*#__PURE__*/function(){function Observable(t,n){this.l=new Revision,this.p=new Set,this.v=t,this.m=n?"function"==typeof n?l(n):b:void 0}var t=Observable.prototype;return t.u=function(t){this.p.add(t)},t.o=function(t){this.p.delete(t)},t.t=function(){},t.revision=function(){return this.l},t.get=function(t){return void 0===t&&(t=e),t&&t.addSubscription(this),this.v},t.set=function(t,n){if(e&&e instanceof Computed)throw new Error("Changing observable inside of computed");if(arguments.length>0){if("function"!=typeof t||n||(t=t(this.v)),this.m&&this.m(this.v,t))return;this.v=t}this.notify()},t.notify=function(){this.l=new Revision,m(this.p,5),y()},Observable}();function M(t,n){var i=new Observable(t,n),r=i.get.bind(i),s=i.set.bind(i);return r.instance=i,r.revision=i.revision.bind(i),[r,s]}M.box=function(t,n){return new Observable(t,n)},M.prop=function(t,n){return new Observable(t,n)};var Reaction=/*#__PURE__*/function(){function Reaction(t,n){var i=this;this.g=void 0,this.C=void 0,this.shouldSubscribe=!0,this.j=new Map,this.I=null,this.S=3,this.P=function(){i.I=i.g()},this.g=t,this.C=n}var t=Reaction.prototype;return t.addSubscription=function(t){this.shouldSubscribe&&t.u(this),this.j.set(t,t.revision())},t.h=function(t){4!==t&&3===this.S&&(this.S=5,s.push(this))},t.runManager=function(){7!==this.S&&(this.C?this.C():this.run())},t.subscribe=function(){g(this.j,this)},t.unsubscribe=function(){S(this.j,this)},t.unsubscribeAndCleanup=function(){this.unsubscribe(),this.j.clear(),this.I&&this.I(),this.I=null,this.S=3},t.missedRun=function(){return j(this.j)},t.destroy=function(){this.unsubscribeAndCleanup(),this.S=7},t.run=function(){this.unsubscribeAndCleanup(),v(this.P,this)},t.updateRevisions=function(){var t=this;this.j.forEach(function(n,i){t.j.set(i,i.revision())})},Reaction}();t.Computed=Computed,t.Observable=Observable,t.Reaction=Reaction,t.Revision=Revision,t.action=function(t){return function(){var n=c(null);a+=1;try{return t.apply(this,arguments)}finally{a-=1,c(n),y()}}},t.computed=x,t.configure=function(t){t.reactionScheduler&&(u=t.reactionScheduler),t.reactionExceptionHandler&&(f=t.reactionExceptionHandler)},t.observable=M,t.reaction=function(t,n){var i=new Reaction(t,n),r=i.destroy.bind(i);return r.run=i.run.bind(i),i.run(),r},t.setSubscriber=c,t.shallowEquals=p,t.tx=function(t){a+=1;try{t()}finally{a-=1,y()}},t.untracked=function(t){var n=c(null);try{return t()}finally{c(n)}},t.utx=v,t.withUntracked=l}); | ||
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((t||self).onek={})}(this,function(t){var i=1e3,n=new Set,r=new Set,s=[],o=!1,u=function(t){Promise.resolve().then(t).catch(h)},h=function(t){console.error("Reaction exception:",t)};function f(){try{for(var t=i;(s.length||r.size)&&--t;){r.forEach(function(t){t.t(!1)}),r.clear();var u=s;s=[],u.forEach(function(t){try{t.runManager()}catch(t){h(t)}})}if(!t)throw new Error("Infinite reactions loop")}finally{o=!1,s=[],n.forEach(function(t){n.delete(t),t.i()}),n.clear()}}var e=null;function c(t){var i=e;return e=t,i}var a=0;function v(t,i){void 0===i&&(i=null);var n=c(i);a+=1;try{return t()}finally{a-=1,c(n),y()}}function l(t){return function(){var i=c(null);try{return t.apply(this,arguments)}finally{c(i)}}}function y(){a||!o&&(s.length||r.size)&&(o=!0,u(f))}var w=Object.prototype.hasOwnProperty;function d(t){return t.constructor===Object||null===t.constructor}function p(t,i){if(t===i)return!0;if(Array.isArray(t)&&Array.isArray(i)){var n=t.length;if(n!==i.length)return!1;for(;n--;)if(t[n]!==i[n])return!1;return!0}if(t&&i&&"object"==typeof t&&"object"==typeof i&&d(t)&&d(i)){var r=Object.keys(t),s=r.length;if(Object.keys(i).length!==s)return!1;for(;s-- >0;){var o=r[s];if(!w.call(i,o)||t[o]!==i[o])return!1}return!0}if(t instanceof Set&&i instanceof Set){if(t.size!==i.size)return!1;var u=!0;return t.forEach(function(t){i.has(t)||(u=!1)}),u}if(t instanceof Map&&i instanceof Map){if(t.size!==i.size)return!1;var h=!0;return t.forEach(function(t,n){i.get(n)!==t&&(h=!1)}),h}return!1}var b=l(p),Revision=function(){};function j(t){var i=!1;return t.forEach(function(t,n){i||(i=n.revision()!==t)}),i}function S(t,i){t.forEach(function(t,n){n.o(i)})}function g(t,i){t.forEach(function(t,n){n.u(i)})}function m(t,i){t.forEach(function(t){t.h(i)})}var Computed=/*#__PURE__*/function(){function Computed(t,i){this.v=void 0,this.l=new Revision,this.p=new Set,this.j=new Map,this.S=0,this.g=t,this.m=i?"function"==typeof i?l(i):b:void 0}var t=Computed.prototype;return t.addSubscription=function(t){2!==this.S&&t.u(this),this.j.set(t,t.revision())},t.u=function(t){this.p.add(t),6===this.S&&(g(this.j,this),this.S=3)},t.o=function(t){this.p.delete(t),this.p.size||6===this.S||function(t){n.add(t)}(this)},t.i=function(){this.p.size||6===this.S||(S(this.j,this),this.S=6)},t.h=function(t){var i=this.S;i!==t&&5!==i&&(this.m?(function(t){r.add(t)}(this),3===i&&m(this.p,4)):m(this.p,t),this.S=t,5===t&&S(this.j,this))},t.t=function(t){if((6!==this.S||j(this.j))&&(4===this.S&&(this.j.forEach(function(i,n){n.t(t)}),4===this.S&&(this.S=3)),3!==this.S)){var i=this.S,n=0!==i,r=t||n&&6!==i;this.S=r?1:2,this.j.clear();var s=c(this);try{var o=this.g();if(this.S=r?3:6,this.m&&n){if(this.m(this.v,o))return;m(this.p,5)}this.v=o,this.l=new Revision}catch(t){throw this.destroy(),t}finally{c(s)}}},t.revision=function(){return this.t(!1),this.l},t.destroy=function(){S(this.j,this),this.j.clear(),this.S=0,this.v=void 0},t.get=function(t){if(void 0===t&&(t=e),1===this.S||2===this.S)throw new Error("Recursive computed call");return this.t(null!==e),t&&t.addSubscription(this),this.v},Computed}();function x(t,i){var n=new Computed(t,i),r=n.get.bind(n);return r.instance=n,r.destroy=n.destroy.bind(n),r.revision=n.revision.bind(n),r}x.box=function(t,i){return new Computed(t,i)},x.prop=function(t,i){return new Computed(t,i)};var Observable=/*#__PURE__*/function(){function Observable(t,i){this.l=new Revision,this.p=new Set,this.v=t,this.m=i?"function"==typeof i?l(i):b:void 0}var t=Observable.prototype;return t.u=function(t){this.p.add(t)},t.o=function(t){this.p.delete(t)},t.t=function(){},t.revision=function(){return this.l},t.get=function(t){return void 0===t&&(t=e),t&&t.addSubscription(this),this.v},t.set=function(t,i){if(e&&e instanceof Computed)throw new Error("Changing observable inside of computed");if(arguments.length>0){if("function"!=typeof t||i||(t=t(this.v)),this.m&&this.m(this.v,t))return;this.v=t}this.notify()},t.notify=function(){this.l=new Revision,m(this.p,5),y()},Observable}();function M(t,i){var n=new Observable(t,i),r=n.get.bind(n),s=n.set.bind(n);return r.instance=n,r.revision=n.revision.bind(n),[r,s]}M.box=function(t,i){return new Observable(t,i)},M.prop=function(t,i){return new Observable(t,i)};var Reaction=/*#__PURE__*/function(){function Reaction(t,i){var n=this;this.g=void 0,this.M=void 0,this.shouldSubscribe=!0,this.j=new Map,this.O=null,this.S=3,this.A=function(){n.O=n.g()},this.g=t,this.M=i}var t=Reaction.prototype;return t.addSubscription=function(t){this.shouldSubscribe&&t.u(this),this.j.set(t,t.revision())},t.h=function(t){4!==t&&3===this.S&&(this.S=5,s.push(this))},t.runManager=function(){7!==this.S&&(this.M?this.M():this.run())},t.subscribe=function(){g(this.j,this)},t.unsubscribe=function(){S(this.j,this)},t.unsubscribeAndCleanup=function(){this.unsubscribe(),this.j.clear(),this.O&&this.O(),this.O=null,this.S=3},t.missedRun=function(){return j(this.j)},t.destroy=function(){this.unsubscribeAndCleanup(),this.S=7},t.run=function(){this.unsubscribeAndCleanup(),v(this.A,this)},t.updateRevisions=function(){var t=this;this.j.forEach(function(i,n){t.j.set(n,n.revision())})},Reaction}();t.Computed=Computed,t.Observable=Observable,t.Reaction=Reaction,t.Revision=Revision,t.action=function(t){return function(){var i=c(null);a+=1;try{return t.apply(this,arguments)}finally{a-=1,c(i),y()}}},t.computed=x,t.configure=function(t){t.reactionScheduler&&(u=t.reactionScheduler),t.reactionExceptionHandler&&(h=t.reactionExceptionHandler)},t.observable=M,t.reaction=function(t,i){var n=new Reaction(t,i),r=n.destroy.bind(n);return r.run=n.run.bind(n),n.run(),r},t.setSubscriber=c,t.shallowEquals=p,t.tx=function(t){a+=1;try{t()}finally{a-=1,y()}},t.untracked=function(t){var i=c(null);try{return t()}finally{c(i)}},t.utx=v,t.withUntracked=l}); | ||
//# sourceMappingURL=onek.umd.js.map |
@@ -6,2 +6,2 @@ import { NotifyState, ISubscriber, ISubscription } from "../types"; | ||
export declare function subscribe(subscriptions: Map<ISubscription, Revision>, subscriber: ISubscriber): void; | ||
export declare function notifySubscribers(subscribers: Set<ISubscriber>, state: NotifyState): void; | ||
export declare function notify(subscribers: Set<ISubscriber>, state: NotifyState): void; |
@@ -20,7 +20,2 @@ import type { CheckFn, IComputed, IComputedGetter, IComputedImpl, IRevision, ISubscriber, ISubscription, NotifyState } from "../types"; | ||
get(_subscriber?: import("../types").MaybeSubscriber): T; | ||
private _subscribe; | ||
private _unsubscribe; | ||
private _notifySubscribers; | ||
private _passivate; | ||
private _resurrect; | ||
} | ||
@@ -27,0 +22,0 @@ export declare function computed<T>(fn: () => T, checkFn?: boolean | CheckFn<T>): IComputedGetter<T>; |
@@ -11,2 +11,2 @@ export declare const enum State { | ||
} | ||
export declare const MAX_REACTION_ITERATIONS = 100; | ||
export declare const MAX_REACTION_ITERATIONS = 1000; |
{ | ||
"name": "onek", | ||
"version": "0.1.6", | ||
"version": "0.1.7", | ||
"description": "⚡️1.8KB full-featured state management inspired by MobX and Solid, batteries included ⚡️", | ||
@@ -5,0 +5,0 @@ "repository": { |
196
README.md
@@ -30,3 +30,3 @@ <p align="center"> | ||
for **React** based on a solid foundation of functional reactive data structures from **MobX** and | ||
**Solid.js**, providing everything needed for managing state in complex React applications, | ||
**Solid.js**. It provides everything needed for managing state in complex React applications, | ||
all in a less than **2KB package**. | ||
@@ -36,12 +36,14 @@ | ||
- 🚀 **Reactive observable and computed values** - just like MobX, Solid.js and Preact Signals | ||
- 🎭 **Both MobX and Solid.js** flavors - choose what you like | ||
- 🤔 **Not opinionated** about the structure of your models | ||
- 👁 **Transparency** - no data glitches guaranteed | ||
- 💧 **No memory leaks** - optimal computed caching without compromises | ||
- 🧩 **Single hook** - effortless integration with React components | ||
- 🤓 **Built-in shallow equality** - easily optimize re-renders | ||
- 💾 **Compatibility** - only ES6 `Set` and `Map` are required | ||
- 💯 **100% test coverage** with complex cases | ||
- ⭐️ Written in **100% TypeScript** | ||
- 🚀 **Reactive Observable and Computed Values** - Inspired by MobX, Solid.js and Preact Signals, Onek delivers the same capabilities in a more compact package. Its goal is to provide a full-featured solution in a small size. | ||
- 🎭 **Both MobX and Solid.js Flavors** - Onek is not restricted to a single way of creating observable values and defining models. Feel free to choose and mix the styles that best fit your needs. | ||
- 🤔 **Not Opinionated** - Unlike Redux, Onek doesn't tell you how to structure your models. You can use global state, relational or object-oriented models - whatever you need to do your task. | ||
- 👁 **Transparency** - Onek guarantees no data glitches. It ensures that every computed value is up-to-date and optimally cached, so you don't have to worry about inconsistent states during complex operations. | ||
- 💧 **No Memory Leaks** - Unlike MobX, Onek doesn't need a flag for computed values to keep them alive for caching and invalidation. Onek seamlessly switches between reactive and immutable caching strategies, achieving both optimal caching and no memory leaks. | ||
- 🧩 **Single Hook** - Onek offers a simple hook for integrating with React components, making your components reactive without any hassle. | ||
- 🔀 **Concurrent React Features** - With [out-of-the-box support](#react-concurrent-rendering) for React 18 concurrent rendering, Onek allows you to optimize your app's responsiveness without any extra work. | ||
- 🤓 **Built-in Shallow Equality** - Onek includes built-in shallow equality for objects, arrays, `Map`, and `Set`, covering most use cases and allowing for easy rendering optimization. | ||
- 💾 **Compatibility** - Onek's core only needs ES6 `Set` and `Map`. This makes it a good choice for older browsers. Also, if you don't need concurrent React features, there is a compatibility package for React 16.8.0. | ||
- 💯 **100% Test Coverage** - all core functionality is fully covered by complex and exhaustive tests. | ||
- ⭐️ **Fully TypeScript** - The source code and the tests are all in TypeScript with strict rules and no hacks. This adds another proof of implementation correctness and type safety. | ||
- ☯️ **Beauty Inside** - Beyond its powerful features, Onek shines in its simplicity. The implementation of complex logic in Onek is done using simple data structures and uses minimal possible amount of class fields. The core of Onek is done in an expressive object-oriented way, enabling great extensibility. All this makes Onek source easy to read and understand. As Antoine de Saint-Exupéry said, "_Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away._" | ||
- 📦 ...and all in a less than **2KB package** | ||
@@ -53,2 +55,3 @@ | ||
- [Introduction](#introduction) | ||
- [Show me the code!](#show-me-the-code) | ||
- [Observable values](#observable-values) | ||
@@ -80,5 +83,63 @@ - [Computed values](#computed-values) | ||
## Show me the code | ||
Here's an example of a counter app that showcases all the main features of Onek with React: | ||
```jsx | ||
import { action, computed, observable } from "onek"; | ||
import { useObserver } from "onek/react"; | ||
// defined observable value | ||
const [count, setCount] = observable(0); | ||
// define computed values derived from the observable | ||
const canIncrease = computed(() => count() < 10); | ||
const canDecrease = computed(() => count() > 0); | ||
// defined actions that manipulate observable values | ||
const increase = action(() => { | ||
if (canIncrease()) { | ||
setCount((count) => count + 1); | ||
} | ||
}); | ||
const decrease = action(() => { | ||
if (canDecrease()) { | ||
setCount((count) => count - 1); | ||
} | ||
}); | ||
const Counter = () => { | ||
// get observer instance | ||
const observer = useObserver(); | ||
// wrap your render code with the observer to make it reactive | ||
return observer(() => ( | ||
<div> | ||
<p>Count: {count()}</p> | ||
<button disabled={!canDecrease()} onClick={decrease}> | ||
- | ||
</button> | ||
<button disabled={!canIncrease()} onClick={increase}> | ||
+ | ||
</button> | ||
</div> | ||
)); | ||
}; | ||
// two counters rendered in sync | ||
root.render( | ||
<> | ||
<Counter /> | ||
<Counter /> | ||
</> | ||
); | ||
``` | ||
[See it on CodeSandbox](https://codesandbox.io/s/onek-counter-example-ynilr8?file=/src/App.tsx) | ||
## Introduction | ||
**Note:** in this section Solid.js flavor will be used. If you want examples for MobX flavor, check | ||
**Note:** in this section Solid.js flavor will be used. If you want examples of MobX flavor, check | ||
out the [MobX flavor](#mobx-flavor) section. | ||
@@ -88,4 +149,3 @@ | ||
`observable` is a simple function that accepts an initial value and returns a tuple of getter and | ||
setter functions - the same convention as `useState` from React: | ||
If you're familiar with React's `useState` hook, you're already halfway to understanding Onek's `observable` function. Like the `useState` hook, it accepts an initial value and returns a tuple of value getter and setter. The difference is that the value getter is a **function** that returns the value instead of the value itself: | ||
@@ -107,7 +167,8 @@ ```js | ||
Please note that while it's similar to React's `useState`, it shouldn't be used in a React component. In this case, use the `useObservable` hook described in [Using with React](#using-with-react) section. | ||
<details> | ||
<summary><b>Extra:</b> equality check argument</summary> | ||
The second argument to `observable` might be an equality check function (or `true` for the | ||
built-in `shallowEquals` implementation): | ||
`observable` supports an equality check function as a second argument. This function can be used to prevent unnecessary updates when the value hasn't effectively changed. You can also use `true` to use the built-in `shallowEquals` implementation: | ||
@@ -117,9 +178,12 @@ ```js | ||
const [number, setNumber] = observable(1, true); | ||
const [greetings, setGreetings] = observable(["hello"], true); | ||
// or equivalently | ||
const [number, setNumber] = observable(1, shallowEquals); | ||
const [greetings, setGreetings] = observable(["hello"], shallowEquals); | ||
setNumber(1); // no updates to dependant computeds and reactions | ||
// setting an equal value doesn't trigger updates | ||
setNumber(["hello"]); | ||
``` | ||
Built-in `shallowEquals` covers plain objects, arrays, `Map` and `Set` equality, but if you need something else (like lodash `isEqual`), just pass it as the second argument. | ||
</details> | ||
@@ -130,10 +194,10 @@ | ||
In order to store a function in an observable you need to pass `true` as the second argument to the | ||
setter function. This argument means the setter should store the first argument as-is, without its | ||
interpretation as an updater function: | ||
In Onek, you can store functions directly in an observable. This is useful for cases where you need to store callback or computation functions. To do this, pass true as the second argument to the setter function: | ||
```js | ||
// create an observable for a callback function | ||
const [callback, setCallback] = observable(() => console.log("hello!")); | ||
setCallback(() => console.log("hola!"), true); // stores callback as is | ||
// stores the callback as is | ||
setCallback(() => console.log("hola!"), true); | ||
``` | ||
@@ -145,7 +209,6 @@ | ||
A computed value is like `useMemo` in React - it's cached and returns the cached value afterwards. | ||
A computed value is like `useMemo` in React - it's cached and returns the cached value afterward. | ||
All accessed `observable` or other `computed` values are automatically tracked, there is no need to | ||
specify a dependency list. | ||
Changes to these tracked values automatically invalidate the cached value, which is recalculated on | ||
next access to the `computed`: | ||
Changes to these tracked values automatically invalidate the cached value, which is recalculated on the next access to the `computed`: | ||
@@ -167,14 +230,16 @@ ```js | ||
The second argument to `computed` is also an equality check function (or `true` for the built-in | ||
implementation): | ||
Just like with `observable`, you can also provide an equality check function as a second argument to `computed` (or `true` for default `shallowEquals` implementation). This allows you to control when the `computed` value is considered to have changed and needs to notify its subscribers about it. In case the equality check function returns `true`, the output of the computed remains referentially equal to the old one: | ||
```js | ||
// create observable with an array of numbers | ||
const [numbers, setNumbers] = observable([1, 2, 3, 4]); | ||
const sortedNumbers = computed(() => numbers().slice().sort(), true); | ||
// create a computed value that returns sorted array | ||
const sortedNumbers = computed(() => [...numbers()].sort(), true); | ||
const result = sortedNumbers(); | ||
console.log(result); // [1,2,3,4] | ||
console.log(result); // output: [1,2,3,4] | ||
// the array is different, but sorted result is the same | ||
setNumbers([4, 3, 2, 1]); | ||
@@ -185,2 +250,4 @@ | ||
The primary goal of the equality check argument is to manage and limit side effects, such as updates to React components or executions of `reaction` functions. These side effects might occur due to changes in the source `observable` or `computed` values. By using an equality check, you can ensure that these side effects are triggered only when the result of the `computed` function changes substantially, rather than being activated by every minor change to the source values. This approach can be particularly useful when the source values change frequently, but the computed result does not. | ||
</details> | ||
@@ -226,3 +293,3 @@ | ||
`useObserver` hook has no arguments and returns an observer function. You can wrap your component | ||
code with it or pass it to `observable` and `computed` getters in order to get the component update | ||
code with it or pass it to `observable` and `computed` getters to get the component update | ||
on their changes. Reading observable values outside of the observer fn or without passing it to | ||
@@ -247,7 +314,6 @@ getters won't subscribe the component to changes: | ||
**Actions** automatically batch updates to observable values, and also make access to observable | ||
getters untracked - so if your action is called inside a component's render function or inside a | ||
reaction it won't make it re-render on accessed values change. | ||
getters untracked - so if your action is called inside a component's render function or a reaction it won't make it re-render on accessed values change. | ||
**Important note**: by default all changes to `observable` values are batched until the end of the | ||
current microtask. In order to run reactions synchronously on transaction end, please read | ||
**Important note**: by default, all changes to `observable` values are batched until the end of the | ||
current microtask. To run reactions synchronously on the transaction end, please read | ||
the [Changing reaction scheduler](#reaction-scheduler) section. | ||
@@ -281,3 +347,3 @@ | ||
To get the same behavior as `action` use `utx` (**U**ntracked transaction) instead: | ||
To get the same behavior as the `action` use `utx` (**U**ntracked transaction) instead: | ||
@@ -325,3 +391,3 @@ ```js | ||
[You can configure](#reaction-scheduler) Onek to use synchronous reaction scheduler that will | ||
execute side effects synchronously after each transaction end. In this case you need to use `action` | ||
execute side effects synchronously after each transaction ends. In this case, you need to use `action` | ||
for promise handlers or `utx` for code blocks in async function, i.e.: | ||
@@ -442,3 +508,3 @@ | ||
A downside of this approach is that it's required to explicitly return all model | ||
getters/setters/actions, which can be cumbersome for large models. Also it requires defining a | ||
getters/setters/actions, which can be cumbersome for large models. Also, it requires defining a | ||
convenient TypeScript type for the model: | ||
@@ -477,3 +543,3 @@ | ||
It defines observable and computed values on class and then calls `makeObservable` to create | ||
It defines observable and computed values on the class and then calls `makeObservable` to create | ||
getters/setters on the class instance. The only difference in defining the values on the class is | ||
@@ -765,2 +831,12 @@ that you need to use `.prop` modifier on observable/computed factories. Otherwise, the usage of MobX | ||
The `check` flag in `observable` and `computed` constructors can be used to optimize React re-renders. It's useful when the result of your computed changes much less frequently than the source observable values. In this case, you can use the `check` flag to prevent unnecessary re-renders: | ||
```js | ||
// todos can change frequently | ||
const [todos, setTodos] = observable([]); | ||
// but the result of this computed changes much less frequently | ||
const isEmpty = computed(() => todos().length === 0, true); | ||
``` | ||
### Reaction scheduler | ||
@@ -774,15 +850,15 @@ | ||
```js | ||
const reaction = (runner) => Promise.resolve().then(runner); | ||
const reactionScheduler = (runner) => Promise.resolve().then(runner); | ||
configure({ reaction }); | ||
configure({ reactionScheduler }); | ||
``` | ||
This is a good compromise between speed and developer experience, but sometimes you might want to | ||
run all reactions synchronously at transaction end (for example, this is done in the Onek test | ||
run all reactions synchronously at the transaction end (for example, this is done in the Onek test | ||
suite): | ||
```js | ||
const reaction = (runner) => runner(); | ||
const reactionScheduler = (runner) => runner(); | ||
configure({ reaction }); | ||
configure({ reactionScheduler }); | ||
``` | ||
@@ -793,5 +869,5 @@ | ||
```js | ||
const reaction = (runner) => setTimeout(runner, 0); | ||
const reactionScheduler = (runner) => setTimeout(runner, 0); | ||
configure({ reaction }); | ||
configure({ reactionScheduler }); | ||
``` | ||
@@ -816,11 +892,10 @@ | ||
no `keepAlive` option like in `MobX`, and here's why. When a computed value has lost its last | ||
subscriber or is being read in untracked context without existing subscribers, it enters a **passive | ||
subscriber or is being read in an untracked context without existing subscribers, it enters a **passive | ||
** state. This state means the computed is no longer referenced by any observable or other computed, | ||
but still holds references to its dependencies, so it can check later if some of them changed. | ||
How is the change detection possible without guarantees that values stored in observables and | ||
computeds are immutable? The answer is simple: along with the value, observable and computed store a | ||
How is change detection possible without guarantees that values stored in observable and computed value are immutable? The answer is simple: along with the value, observable and computed store a | ||
**revision** - an immutable plain object that is new each time an observable or computed is updated. | ||
This allows the implementation of `reselect`-like logic of checking computed dependencies with very small | ||
overhead and preserve cached values without any memory leaks. | ||
overhead and preserves cached values without any memory leaks. | ||
@@ -873,4 +948,4 @@ ## API Documentation | ||
The getter is a function that can accept a `ISubscriber` - return value of `useObserver` hook or the | ||
value of `instance`attribute of a computed getter. | ||
The getter is a function that can accept an `ISubscriber` - return value of `useObserver` hook or the | ||
value of `instance` attribute of a computed getter. | ||
@@ -896,2 +971,5 @@ The setter function can accept a `value` argument that can be of a generic type or an updater | ||
Creates a getter for a computed value. The `fn` argument is a function that returns the computed. | ||
The `checkFn` argument is a function that's used for checking if the new value from the setter is the same as the old one. It can be `true` to use the built-in `shallowEquals` implementation. | ||
### reaction | ||
@@ -907,2 +985,4 @@ | ||
Creates a reaction that runs the `fn` function and subscribes to all accessed observables and computed values. The `fn` function can return a **reaction destructor** - a function that's called before each reaction run and on the `disposer` call. If the `manager` function is specified, it's called instead of the reaction body. It should schedule the reaction to run later. | ||
## action | ||
@@ -916,2 +996,4 @@ | ||
Creates an action that runs the `fn` function and batches all updates to observables and computed. | ||
## tx | ||
@@ -923,2 +1005,4 @@ | ||
Executes the `fn` function immediately and batches all updates to observables and computed. | ||
## utx | ||
@@ -930,2 +1014,4 @@ | ||
Executes the `fn` function immediately and batches all updates to observables and computed. The difference from `tx` is that it makes all observable and computed values accessed inside the `fn` untracked, so they won't make the component rerender or reaction run. | ||
### untracked | ||
@@ -939,2 +1025,4 @@ | ||
Creates a function that runs the `fn` function and makes all observable and computed values accessed inside the `fn` untracked, so they won't make the component rerender or reaction run. | ||
### useObserver | ||
@@ -946,2 +1034,4 @@ | ||
Returns the `ISubscriber` instance that is also a function. The resulting function can be used to wrap your component code with it or be passed as an argument to `observable` and `computed` getters to make the component rerender on their changes. Also, it can be called with `observable` or `computed` as an argument, it will also make the component rerender on their changes. | ||
### shallowEquals | ||
@@ -953,2 +1043,4 @@ | ||
Returns `true` if `prev` and `next` are equal. Supports plain objects, arrays, `Map` and `Set`. | ||
## License | ||
@@ -955,0 +1047,0 @@ |
@@ -32,3 +32,3 @@ import { NotifyState, ISubscriber, ISubscription } from "../types"; | ||
export function notifySubscribers(subscribers: Set<ISubscriber>, state: NotifyState): void { | ||
export function notify(subscribers: Set<ISubscriber>, state: NotifyState): void { | ||
subscribers.forEach((subscriber) => { | ||
@@ -35,0 +35,0 @@ subscriber._notify(state); |
@@ -17,4 +17,3 @@ import type { | ||
import { Revision } from "./revision"; | ||
import { checkRevisions, notifySubscribers, subscribe, unsubscribe } from "./common"; | ||
import { invariant } from "../../utils"; | ||
import { checkRevisions, notify, subscribe, unsubscribe } from "./common"; | ||
@@ -61,3 +60,4 @@ type ComputedState = | ||
if (this._state === State.PASSIVE) { | ||
this._resurrect(); | ||
subscribe(this._subscriptions, this); | ||
this._state = State.CLEAN; | ||
} | ||
@@ -76,3 +76,4 @@ } | ||
if (!this._subscribers.size && this._state !== State.PASSIVE) { | ||
this._passivate(); | ||
unsubscribe(this._subscriptions, this); | ||
this._state = State.PASSIVE; | ||
} | ||
@@ -92,6 +93,6 @@ } | ||
if (oldState === State.CLEAN) { | ||
this._notifySubscribers(State.MAYBE_DIRTY); | ||
notify(this._subscribers, State.MAYBE_DIRTY); | ||
} | ||
} else { | ||
this._notifySubscribers(state); | ||
notify(this._subscribers, state); | ||
} | ||
@@ -102,3 +103,3 @@ | ||
if (state === State.DIRTY) { | ||
this._unsubscribe(); | ||
unsubscribe(this._subscriptions, this); | ||
} | ||
@@ -108,4 +109,6 @@ } | ||
_actualize(willHaveSubscriber: boolean): void { | ||
if (this._state === State.PASSIVE && !checkRevisions(this._subscriptions)) { | ||
return; | ||
if (this._state === State.PASSIVE) { | ||
if (!checkRevisions(this._subscriptions)) { | ||
return; | ||
} | ||
} | ||
@@ -130,6 +133,6 @@ | ||
this._state = isActive ? State.COMPUTING : State.COMPUTING_PASSIVE; | ||
this._subscriptions.clear(); | ||
this._state = isActive ? State.COMPUTING : State.COMPUTING_PASSIVE; | ||
const oldSubscriber = setSubscriber(this); | ||
@@ -146,3 +149,3 @@ | ||
} | ||
this._notifySubscribers(State.DIRTY); | ||
notify(this._subscribers, State.DIRTY); | ||
} | ||
@@ -167,3 +170,3 @@ this._value = newValue; | ||
destroy(): void { | ||
this._unsubscribe(); | ||
unsubscribe(this._subscriptions, this); | ||
this._subscriptions.clear(); | ||
@@ -187,24 +190,2 @@ this._state = State.NOT_INITIALIZED; | ||
} | ||
private _subscribe(): void { | ||
subscribe(this._subscriptions, this); | ||
} | ||
private _unsubscribe(): void { | ||
unsubscribe(this._subscriptions, this); | ||
} | ||
private _notifySubscribers(state: NotifyState): void { | ||
notifySubscribers(this._subscribers, state); | ||
} | ||
private _passivate(): void { | ||
this._unsubscribe(); | ||
this._state = State.PASSIVE; | ||
} | ||
private _resurrect(): void { | ||
this._subscribe(); | ||
this._state = State.CLEAN; | ||
} | ||
} | ||
@@ -211,0 +192,0 @@ |
@@ -17,3 +17,3 @@ import type { | ||
import { untrackedShallowEquals } from "../utils"; | ||
import { notifySubscribers } from "./common"; | ||
import { notify } from "./common"; | ||
@@ -82,3 +82,3 @@ export class Observable<T = any> implements IObservableImpl<T> { | ||
notifySubscribers(this._subscribers, State.DIRTY); | ||
notify(this._subscribers, State.DIRTY); | ||
endTx(); | ||
@@ -85,0 +85,0 @@ } |
@@ -12,2 +12,2 @@ export const enum State { | ||
export const MAX_REACTION_ITERATIONS = 100; | ||
export const MAX_REACTION_ITERATIONS = 1000; |
import { Reaction } from "../classes"; | ||
import { MAX_REACTION_ITERATIONS } from "../constants"; | ||
import { runSubscribersCheck, subscribersCheckQueue } from "./subscribersCheck"; | ||
import { runActualizations, actualizationQueue } from "./stateActualization"; | ||
import { runSubscribersCheck } from "./subscribersCheck"; | ||
import { actualizationQueue, runActualizations } from "./stateActualization"; | ||
@@ -31,20 +31,18 @@ let reactionQueue: Array<Reaction> = []; | ||
let i = MAX_REACTION_ITERATIONS; | ||
while (reactionQueue.length || actualizationQueue.size) { | ||
while ((reactionQueue.length || actualizationQueue.size) && --i) { | ||
runActualizations(); | ||
while (reactionQueue.length && --i) { | ||
const reactions = reactionQueue; | ||
reactionQueue = []; | ||
reactions.forEach((reaction) => { | ||
try { | ||
reaction.runManager(); | ||
} catch (exception: any) { | ||
reactionExceptionHandler(exception); | ||
} | ||
}); | ||
} | ||
if (!i) { | ||
throw new Error("Infinite reactions loop"); | ||
} | ||
const reactions = reactionQueue; | ||
reactionQueue = []; | ||
reactions.forEach((reaction) => { | ||
try { | ||
reaction.runManager(); | ||
} catch (exception: any) { | ||
reactionExceptionHandler(exception); | ||
} | ||
}); | ||
} | ||
if (!i) { | ||
throw new Error("Infinite reactions loop"); | ||
} | ||
} finally { | ||
@@ -59,4 +57,3 @@ isReactionRunScheduled = false; | ||
export function scheduleReactionRunner(): void { | ||
const shouldRunReactions = | ||
reactionQueue.length || actualizationQueue.size || subscribersCheckQueue.size; | ||
const shouldRunReactions = reactionQueue.length || actualizationQueue.size; | ||
@@ -63,0 +60,0 @@ if (!isReactionRunScheduled && shouldRunReactions) { |
@@ -11,2 +11,5 @@ import { Computed } from "../classes"; | ||
subscribersCheckQueue.forEach((computed) => { | ||
// the computed might be re-introduced later to the queue | ||
// when other checks will be done, so we need to delete it | ||
subscribersCheckQueue.delete(computed); | ||
computed._checkAndPassivate(); | ||
@@ -13,0 +16,0 @@ }); |
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
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
308264
1023
0
1391