From 1698024293c900483970418e5d79f0c6c1d471eb Mon Sep 17 00:00:00 2001 From: Javier Marquez Date: Mon, 19 Feb 2018 20:17:08 +0100 Subject: [PATCH] Bumps to version 0.14.0 --- CHANGELOG.md | 3 +++ README.md | 1 + build/freezer.js | 8 ++++++-- build/freezer.min.js | 4 ++-- package.json | 2 +- src/frozen.js | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fdcaa9..68a3e86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Freezer Changelog +###v0.14.0 +* Adds a new flag `singleParent` that prevents the same node to be added twice into the the state tree. Thanks to @nathanial. + ###v0.13.0 * Fixes bug making apps unresponsive in FF when an error happens in a listener. diff --git a/README.md b/README.md index a25aae7..e2d45b9 100644 --- a/README.md +++ b/README.md @@ -197,6 +197,7 @@ var freezer = new Freezer({hi: 'hello'}, {mutable: true, live:true}); | **mutable** | boolean | `false` | Once you get used to freezer, you can see that immutability is not necessary if you learn that you shouldn't update the data directly. In that case, disable immutability in the case that you need a small performance boost. | | **live** | boolean | `false` | With live mode on, freezer emits the update events just when the changes happen, instead of batching all the changes and emiting the event on the next tick. This is useful if you want freezer to store input field values. | | **freezeInstances** | boolean | `false` | It's possible to store class instances in freezer. They are handled like strings or numbers, added to the state like non-frozen leaves. Keep in mind that if their internal state changes, freezer won't `emit` any update event. If you want freezer to handle them as freezer nodes, set 'freezerInstances: true'. They will be frozen and you will be able to update their attributes using freezer methods, but remember that any instance method that update its internal state may fail (the instance is frozen) and wouldn't emit any `update` event. | +| **singleParent** | boolean | `false` | Freezer allows to add the same node to different parts of the state tree. Updating that node will update all its references that the current state contains. This is a nice feature but it's not ideal if you don't want circular dependencies in your state, in that case set it to `true`. | And then, Freezer's API is really simple and only has 2 methods: `get` and `set`. A freezer object also implements the [listener API](#listener-api). diff --git a/build/freezer.js b/build/freezer.js index 9d57733..df8d126 100644 --- a/build/freezer.js +++ b/build/freezer.js @@ -1,4 +1,4 @@ -/* freezer-js v0.13.0 (3-7-2017) +/* freezer-js v0.14.0 (19-2-2018) * https://github.com/arqex/freezer * By arqex * License: MIT @@ -880,6 +880,9 @@ var Frozen = { ; if( index === -1 ){ + if(node.__.store.singleParent && parents.length >= 1){ + throw new Error("Freezer: Can't add node to the tree. It's already added and freezer is configured to `singleParent: true`."); + } parents[ parents.length ] = parent; } }, @@ -945,7 +948,8 @@ var Freezer = function( initialValue, options ) { ops = options || {}, store = { live: ops.live || false, - freezeInstances: ops.freezeInstances || false + freezeInstances: ops.freezeInstances || false, + singleParent: ops.singleParent || false } ; diff --git a/build/freezer.min.js b/build/freezer.min.js index 20f96ba..e93a65e 100644 --- a/build/freezer.min.js +++ b/build/freezer.min.js @@ -1,6 +1,6 @@ /* -freezer-js v0.13.0 +freezer-js v0.14.0 https://github.com/arqex/freezer MIT: https://github.com/arqex/freezer/raw/master/LICENSE */ -!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.Freezer=t()}(this,function(){"use strict";function e(e){n.warn(!1,"Method "+e.name+" called on a detached node.",e.node,e.options)}var t="undefined"!=typeof t?t:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},n={extend:function(e,t){for(var n in t)e[n]=t[n];return e},createNonEnumerable:function(e,t){var n={};for(var r in e)n[r]={value:e[r]};return Object.create(t||{},n)},error:function(e){var t=new Error(e);if(console)return console.error(t);throw t},each:function(e,t){var n,r,i;if(e&&e.constructor===Array)for(n=0,r=e.length;n=0;n--)r[n].callback===t&&r.splice(n,1)}return this},emit:function(e){var t,n,r,a,f=[].slice.call(arguments,1),c=this._events[e]||[],u=[],h=s.indexOf(e)!==-1;for(h||this.emit.apply(this,[i,e].concat(f)),t=0;t=0;t--)c.splice(u[t],1);return h||this.emit.apply(this,[o,e].concat(f)),r},trigger:function(){return n.warn(!1,"Method `trigger` is deprecated and will be removed from freezer in upcoming releases. Please use `emit`."),this.emit.apply(this,arguments)}},f=n.createNonEnumerable(a),c={freeze:function(e,t){if(e&&e.__)return e;var i=this,o=r.clone(e);return n.addNE(o,{__:{listener:!1,parents:[],store:t}}),n.each(e,function(e,r){n.isLeaf(e,t.freezeInstances)||(e=i.freeze(e,t)),e&&e.__&&i.addParent(e,o),o[r]=e}),t.freezeFn(o),o},merge:function(e,t){var r=e.__,i=r.trans,t=n.extend({},t);if(i){for(var o in t)i[o]=t[o];return e}var s,a,f,c=this,u=this.copyMeta(e),h=r.store;n.each(e,function(r,i){return f=r&&r.__,f&&c.removeParent(r,e),(s=t[i])?(n.isLeaf(s,h.freezeInstances)||(s=c.freeze(s,h)),s&&s.__&&c.addParent(s,u),delete t[i],void(u[i]=s)):(f&&c.addParent(r,u),u[i]=r)});for(a in t)s=t[a],n.isLeaf(s,h.freezeInstances)||(s=c.freeze(s,h)),s&&s.__&&c.addParent(s,u),u[a]=s;return r.store.freezeFn(u),this.refreshParents(e,u),u},replace:function(e,t){var r=this,i=e.__,o=t;return n.isLeaf(t,i.store.freezeInstances)||(o=r.freeze(t,i.store),o.__.parents=i.parents,o.__.updateRoot=i.updateRoot,i.listener&&(o.__.listener=i.listener)),o&&this.fixChildren(o,e),this.refreshParents(e,o),o},remove:function(e,t){var r=e.__.trans;if(r){for(var i=t.length-1;i>=0;i--)delete r[t[i]];return e}var o,s=this,a=this.copyMeta(e);return n.each(e,function(n,r){o=n&&n.__,o&&s.removeParent(n,e),t.indexOf(r)===-1&&(o&&s.addParent(n,a),a[r]=n)}),e.__.store.freezeFn(a),this.refreshParents(e,a),a},splice:function(e,t){var r=e.__,i=r.trans;if(i)return i.splice.apply(i,t),e;var o,s=this,a=this.copyMeta(e),f=t[0],c=f+t[1];if(n.each(e,function(t,n){t&&t.__&&(s.removeParent(t,e),(n=c)&&s.addParent(t,a)),a[n]=t}),t.length>1)for(var u=t.length-1;u>=2;u--)o=t[u],n.isLeaf(o,r.store.freezeInstances)||(o=this.freeze(o,r.store)),o&&o.__&&this.addParent(o,a),t[u]=o;return Array.prototype.splice.apply(a,t),r.store.freezeFn(a),this.refreshParents(e,a),a},transact:function(e){var t,r=this,i=e.__.trans;return i?i:(t=e.constructor===Array?[]:{},n.each(e,function(e,n){t[n]=e}),e.__.trans=t,n.nextTick(function(){e.__.trans&&r.run(e)}),t)},run:function(e){var t=this,r=e.__.trans;if(!r)return e;n.each(r,function(n,r){n&&n.__&&t.removeParent(n,e)}),delete e.__.trans;var i=this.replace(e,r);return i},pivot:function(e){return e.__.pivot=1,this.unpivot(e),e},unpivot:function(e){n.nextTick(function(){e.__.pivot=0})},refresh:function(e,t,r){var i=this,o=e.__.trans,s=0;if(o)return n.each(o,function(n,a){s||n===t&&(o[a]=r,s=1,r&&r.__&&i.addParent(r,e))}),e;var a,f=this.copyMeta(e);n.each(e,function(n,o){n===t&&(n=r),n&&(a=n.__)&&(i.removeParent(n,e),i.addParent(n,f)),f[o]=n}),e.__.store.freezeFn(f),this.refreshParents(e,f)},fixChildren:function(e,t){var r=this;n.each(e,function(n){if(n&&n.__){if(r.fixChildren(n),1===n.__.parents.length)return n.__.parents=[e];t&&r.removeParent(n,t),r.addParent(n,e)}})},copyMeta:function(e){var t=r.clone(e),i=e.__;return n.addNE(t,{__:{store:i.store,updateRoot:i.updateRoot,listener:i.listener,parents:i.parents.slice(0),trans:i.trans,pivot:i.pivot}}),i.pivot&&this.unpivot(t),t},refreshParents:function(e,t){var n,r=e.__,i=r.parents.length;if(e.__.updateRoot&&e.__.updateRoot(e,t),t&&this.emit(e,"update",t,r.store.live),i)for(n=i-1;n>=0;n--)this.refresh(r.parents[n],e,t)},removeParent:function(e,t){var n=e.__.parents,r=n.indexOf(t);r!==-1&&n.splice(r,1)},addParent:function(e,t){var n=e.__.parents,r=n.indexOf(t);r===-1&&(n[n.length]=t)},emit:function(e,t,r,i){var o=e.__.listener;if(o){var s=o.ticking;if(i)return void((s||r)&&(o.ticking=0,o.emit(t,s||r,e)));o.ticking=r,o.prevState||(o.prevState=e),s||n.nextTick(function(){if(o.ticking){var n=o.ticking;o.prevState;o.ticking=0,o.prevState=0,o.emit(t,n,e)}})}},createListener:function(e){var t=e.__.listener;return t||(t=Object.create(f,{_events:{value:{},writable:!0}}),e.__.listener=t),t}};r.init(c);var u=function(t,r){var i,o,s=this,a=r||{},f={live:a.live||!1,freezeInstances:a.freezeInstances||!1},u=[],h=0,p=function(e){var t,n=e.__;if(n.listener){var r=n.listener.prevState||e;n.listener.prevState=0,c.emit(r,"update",e,!0)}for(t=0;t=0;n--)r[n].callback===t&&r.splice(n,1)}return this},emit:function(e){var t,n,r,a,f=[].slice.call(arguments,1),c=this._events[e]||[],u=[],h=s.indexOf(e)!==-1;for(h||this.emit.apply(this,[i,e].concat(f)),t=0;t=0;t--)c.splice(u[t],1);return h||this.emit.apply(this,[o,e].concat(f)),r},trigger:function(){return n.warn(!1,"Method `trigger` is deprecated and will be removed from freezer in upcoming releases. Please use `emit`."),this.emit.apply(this,arguments)}},f=n.createNonEnumerable(a),c={freeze:function(e,t){if(e&&e.__)return e;var i=this,o=r.clone(e);return n.addNE(o,{__:{listener:!1,parents:[],store:t}}),n.each(e,function(e,r){n.isLeaf(e,t.freezeInstances)||(e=i.freeze(e,t)),e&&e.__&&i.addParent(e,o),o[r]=e}),t.freezeFn(o),o},merge:function(e,t){var r=e.__,i=r.trans,t=n.extend({},t);if(i){for(var o in t)i[o]=t[o];return e}var s,a,f,c=this,u=this.copyMeta(e),h=r.store;n.each(e,function(r,i){return f=r&&r.__,f&&c.removeParent(r,e),(s=t[i])?(n.isLeaf(s,h.freezeInstances)||(s=c.freeze(s,h)),s&&s.__&&c.addParent(s,u),delete t[i],void(u[i]=s)):(f&&c.addParent(r,u),u[i]=r)});for(a in t)s=t[a],n.isLeaf(s,h.freezeInstances)||(s=c.freeze(s,h)),s&&s.__&&c.addParent(s,u),u[a]=s;return r.store.freezeFn(u),this.refreshParents(e,u),u},replace:function(e,t){var r=this,i=e.__,o=t;return n.isLeaf(t,i.store.freezeInstances)||(o=r.freeze(t,i.store),o.__.parents=i.parents,o.__.updateRoot=i.updateRoot,i.listener&&(o.__.listener=i.listener)),o&&this.fixChildren(o,e),this.refreshParents(e,o),o},remove:function(e,t){var r=e.__.trans;if(r){for(var i=t.length-1;i>=0;i--)delete r[t[i]];return e}var o,s=this,a=this.copyMeta(e);return n.each(e,function(n,r){o=n&&n.__,o&&s.removeParent(n,e),t.indexOf(r)===-1&&(o&&s.addParent(n,a),a[r]=n)}),e.__.store.freezeFn(a),this.refreshParents(e,a),a},splice:function(e,t){var r=e.__,i=r.trans;if(i)return i.splice.apply(i,t),e;var o,s=this,a=this.copyMeta(e),f=t[0],c=f+t[1];if(n.each(e,function(t,n){t&&t.__&&(s.removeParent(t,e),(n=c)&&s.addParent(t,a)),a[n]=t}),t.length>1)for(var u=t.length-1;u>=2;u--)o=t[u],n.isLeaf(o,r.store.freezeInstances)||(o=this.freeze(o,r.store)),o&&o.__&&this.addParent(o,a),t[u]=o;return Array.prototype.splice.apply(a,t),r.store.freezeFn(a),this.refreshParents(e,a),a},transact:function(e){var t,r=this,i=e.__.trans;return i?i:(t=e.constructor===Array?[]:{},n.each(e,function(e,n){t[n]=e}),e.__.trans=t,n.nextTick(function(){e.__.trans&&r.run(e)}),t)},run:function(e){var t=this,r=e.__.trans;if(!r)return e;n.each(r,function(n,r){n&&n.__&&t.removeParent(n,e)}),delete e.__.trans;var i=this.replace(e,r);return i},pivot:function(e){return e.__.pivot=1,this.unpivot(e),e},unpivot:function(e){n.nextTick(function(){e.__.pivot=0})},refresh:function(e,t,r){var i=this,o=e.__.trans,s=0;if(o)return n.each(o,function(n,a){s||n===t&&(o[a]=r,s=1,r&&r.__&&i.addParent(r,e))}),e;var a,f=this.copyMeta(e);n.each(e,function(n,o){n===t&&(n=r),n&&(a=n.__)&&(i.removeParent(n,e),i.addParent(n,f)),f[o]=n}),e.__.store.freezeFn(f),this.refreshParents(e,f)},fixChildren:function(e,t){var r=this;n.each(e,function(n){if(n&&n.__){if(r.fixChildren(n),1===n.__.parents.length)return n.__.parents=[e];t&&r.removeParent(n,t),r.addParent(n,e)}})},copyMeta:function(e){var t=r.clone(e),i=e.__;return n.addNE(t,{__:{store:i.store,updateRoot:i.updateRoot,listener:i.listener,parents:i.parents.slice(0),trans:i.trans,pivot:i.pivot}}),i.pivot&&this.unpivot(t),t},refreshParents:function(e,t){var n,r=e.__,i=r.parents.length;if(e.__.updateRoot&&e.__.updateRoot(e,t),t&&this.emit(e,"update",t,r.store.live),i)for(n=i-1;n>=0;n--)this.refresh(r.parents[n],e,t)},removeParent:function(e,t){var n=e.__.parents,r=n.indexOf(t);r!==-1&&n.splice(r,1)},addParent:function(e,t){var n=e.__.parents,r=n.indexOf(t);if(r===-1){if(e.__.store.singleParent&&n.length>=1)throw new Error("Freezer: Can't add node to the tree. It's already added and freezer is configured to `singleParent: true`.");n[n.length]=t}},emit:function(e,t,r,i){var o=e.__.listener;if(o){var s=o.ticking;if(i)return void((s||r)&&(o.ticking=0,o.emit(t,s||r,e)));o.ticking=r,o.prevState||(o.prevState=e),s||n.nextTick(function(){if(o.ticking){var n=o.ticking;o.prevState;o.ticking=0,o.prevState=0,o.emit(t,n,e)}})}},createListener:function(e){var t=e.__.listener;return t||(t=Object.create(f,{_events:{value:{},writable:!0}}),e.__.listener=t),t}};r.init(c);var u=function(t,r){var i,o,s=this,a=r||{},f={live:a.live||!1,freezeInstances:a.freezeInstances||!1,singleParent:a.singleParent||!1},u=[],h=0,p=function(e){var t,n=e.__;if(n.listener){var r=n.listener.prevState||e;n.listener.prevState=0,c.emit(r,"update",e,!0)}for(t=0;t= 1){ - throw new Error('Node already has a parent'); + throw new Error("Freezer: Can't add node to the tree. It's already added and freezer is configured to `singleParent: true`."); } parents[ parents.length ] = parent; }