From e44446f71e67396630fd73c221bee3f3f8d3b7a8 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 2 Jun 2016 17:49:27 +0200 Subject: [PATCH] proper recursive proxy initialization --- www/json/deep-proxy.js | 51 ++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/www/json/deep-proxy.js b/www/json/deep-proxy.js index ae99e2bb9..8591223d1 100644 --- a/www/json/deep-proxy.js +++ b/www/json/deep-proxy.js @@ -35,8 +35,7 @@ define([ throw new Error("'on' is a reserved attribute name for realtime lists and maps"); } - var t_value = type(value); - if (isProxyable(t_value)) { + if (isProxyable(value)) { var proxy = obj[prop] = deepProxy.create(value, cb); } else { obj[prop] = value; @@ -82,7 +81,7 @@ define([ events.change.sort(lengthDescending); break; - case 'delete': + case 'remove': pattern = type(pattern) === 'array'? pattern: [pattern]; events.remove.push({ @@ -119,6 +118,7 @@ define([ pattern(info); } }); + break; default: break; } @@ -198,7 +198,7 @@ define([ }, map)) || undefined; }; - var onRemove = function (path, key, root) { + var onRemove = function (path, key, root, old, top) { var newpath = path.concat(key); var X = find(root, newpath); @@ -209,24 +209,32 @@ define([ switch (t_X) { case 'array': + + if (top) { + // the top of an onremove should emit an onchange instead + onChange(path, key, root, old, undefined);// no newval since it's a deletion + } else { + root._events.remove.forEach(function (handler, i) { + return handler.cb(X, newpath, root); + }); + } // remove all of the array's children X.forEach(function (x, i) { onRemove(newpath, i, root); }); - root._events.remove.forEach(function (handler, i) { - return handler.cb(X, newpath, root); - }); - break; case 'object': + if (top) { + onChange(path, key, root, old, undefined);// no newval since it's a deletion + } else { + root._events.remove.forEach(function (handler, i) { + return handler.cb(X, newpath, root, old, false); + }); + } // remove all of the object's children Object.keys(X).forEach(function (key, i) { - onRemove(newpath, key, root); - }); - - root._events.remove.forEach(function (handler, i) { - return handler.cb(X, newpath, root); + onRemove(newpath, key, root, X[key], false); }); break; @@ -300,13 +308,7 @@ define([ console.log("type changed from [%s] to [%s]", t_a, t_b); switch (t_b) { case 'undefined': - // deletions are a removal - //delete A[b]; - onRemove(path, b, root); - - // this should never happen? throw new Error("first pass should never reveal undefined keys"); - //break; case 'array': A[b] = f(B[b]); // make a new proxy @@ -353,7 +355,7 @@ define([ // the key was deleted if (Bkeys.indexOf(a) === -1 || type(B[a]) === 'undefined') { - onRemove(path, a, root); + onRemove(path, a, root, old, true); delete A[a]; } }); @@ -384,6 +386,8 @@ define([ // type changes are always destructive // that's good news because destructive is easy switch (t_b) { + case 'undefined': + throw new Error('this should never happen'); case 'object': A[i] = f(b); break; @@ -424,10 +428,13 @@ define([ // A was longer than B, so there have been deletions var i = l_B; var t_a; + var old; for (; i <= l_B; i++) { // recursively delete - onRemove(path, i, root); + old = A[i]; + + onRemove(path, i, root, old, true); } // cool } @@ -447,7 +454,7 @@ define([ if (t_a !== t_b) { switch (t_b) { case 'undefined': - onRemove(path, i, root); + onRemove(path, i, root, old, true); break; // watch out for fallthrough behaviour