Commit 21e6eb76 authored by Romain Courteaud's avatar Romain Courteaud

Accumulate modification_dict on onStateChange error

Resetting the internal gadget state leads to unexpecting errors, and so,
it was a bad idea.
parent 183cb362
...@@ -453,7 +453,6 @@ ...@@ -453,7 +453,6 @@
}; };
RenderJSGadget.setState = function (state_dict) { RenderJSGadget.setState = function (state_dict) {
var json_state = JSON.stringify(state_dict); var json_state = JSON.stringify(state_dict);
this.prototype.__json_state = json_state;
return this.ready(function () { return this.ready(function () {
this.state = JSON.parse(json_state); this.state = JSON.parse(json_state);
}); });
...@@ -584,10 +583,19 @@ ...@@ -584,10 +583,19 @@
.declareMethod('changeState', function (state_dict) { .declareMethod('changeState', function (state_dict) {
var key, var key,
modified = false, modified = false,
modification_dict = {}, previous_cancelled = this.hasOwnProperty('__modification_dict'),
modification_dict,
context = this; context = this;
if (previous_cancelled) {
modification_dict = this.__modification_dict;
modified = true;
} else {
modification_dict = {};
this.__modification_dict = modification_dict;
}
for (key in state_dict) { for (key in state_dict) {
if (state_dict[key] !== this.state[key]) { if (state_dict.hasOwnProperty(key) &&
(state_dict[key] !== this.state[key])) {
this.state[key] = state_dict[key]; this.state[key] = state_dict[key];
modification_dict[key] = state_dict[key]; modification_dict[key] = state_dict[key];
modified = true; modified = true;
...@@ -598,13 +606,9 @@ ...@@ -598,13 +606,9 @@
.push(function () { .push(function () {
return context.__state_change_callback(modification_dict); return context.__state_change_callback(modification_dict);
}) })
.push(undefined, function (error) { .push(function (result) {
if (context.__json_state !== undefined) { delete context.__modification_dict;
context.state = JSON.parse(context.__json_state); return result;
} else {
context.state = {};
}
throw error;
}); });
} }
}); });
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
stop = QUnit.stop, stop = QUnit.stop,
start = QUnit.start, start = QUnit.start,
ok = QUnit.ok, ok = QUnit.ok,
expect = QUnit.expect,
equal = QUnit.equal, equal = QUnit.equal,
throws = QUnit.throws, throws = QUnit.throws,
deepEqual = QUnit.deepEqual, deepEqual = QUnit.deepEqual,
...@@ -1327,10 +1328,12 @@ ...@@ -1327,10 +1328,12 @@
}); });
}); });
test('reset state on onStateChange error', function () { test('accumulate modification_dict on onStateChange error', function () {
var gadget = new RenderJSGadget(); var gadget = new RenderJSGadget();
gadget.state = {foo: 'bar', bar: 'foo'}; expect(13);
gadget.__state_change_callback = function () { gadget.state = {a: 'b', foo: 'bar', bar: 'foo'};
gadget.__state_change_callback = function (modification_dict) {
deepEqual(modification_dict, {bar: 'barbar'});
throw new Error('failure in onStateChange'); throw new Error('failure in onStateChange');
}; };
stop(); stop();
...@@ -1340,35 +1343,44 @@ ...@@ -1340,35 +1343,44 @@
}) })
.fail(function (error) { .fail(function (error) {
equal(error.message, 'failure in onStateChange'); equal(error.message, 'failure in onStateChange');
deepEqual(gadget.state, {}); deepEqual(gadget.state, {a: 'b', foo: 'bar', bar: 'barbar'});
gadget.__state_change_callback = function (modification_dict) {
deepEqual(modification_dict, {bar: 'barbar', foo: 'foofoo'});
throw new Error('failure2 in onStateChange');
};
return gadget.changeState({foo: 'foofoo'});
}) })
.always(function () { .fail(function (error) {
start(); equal(error.message, 'failure2 in onStateChange');
}); deepEqual(gadget.state, {a: 'b', foo: 'foofoo', bar: 'barbar'});
});
test('reset to default state on onStateChange error', function () { gadget.__state_change_callback = function (modification_dict) {
// Subclass RenderJSGadget to not pollute its namespace deepEqual(modification_dict, {bar: 'barbar', foo: 'f'});
var Klass = function () { throw new Error('failure3 in onStateChange');
RenderJSGadget.call(this); };
}, gadget; return gadget.changeState({foo: 'f'});
Klass.prototype = new RenderJSGadget(); })
Klass.prototype.constructor = Klass; .fail(function (error) {
Klass.prototype.__json_state = JSON.stringify({a: 'b'}); equal(error.message, 'failure3 in onStateChange');
deepEqual(gadget.state, {a: 'b', foo: 'f', bar: 'barbar'});
gadget = new Klass(); gadget.__state_change_callback = function (modification_dict) {
gadget.state = {foo: 'bar', bar: 'foo'}; deepEqual(modification_dict, {a: 'c', bar: 'barbar', foo: 'f'});
gadget.__state_change_callback = function () {
throw new Error('failure in onStateChange');
}; };
stop(); return gadget.changeState({a: 'c'});
gadget.changeState({bar: 'barbar'}) })
.then(function () { .then(function () {
ok(false, 'Expecting an error'); deepEqual(gadget.state, {a: 'c', foo: 'f', bar: 'barbar'});
gadget.__state_change_callback = function (modification_dict) {
deepEqual(modification_dict, {a: 'd'});
};
return gadget.changeState({a: 'd'});
}) })
.fail(function (error) { .then(function () {
equal(error.message, 'failure in onStateChange'); deepEqual(gadget.state, {a: 'd', foo: 'f', bar: 'barbar'});
deepEqual(gadget.state, {a: 'b'});
}) })
.always(function () { .always(function () {
start(); start();
...@@ -1836,7 +1848,6 @@ ...@@ -1836,7 +1848,6 @@
Klass.setState({foo: 'bar'}); Klass.setState({foo: 'bar'});
equal(Klass.__ready_list.length, 1); equal(Klass.__ready_list.length, 1);
equal(Klass.prototype.__json_state, JSON.stringify({foo: 'bar'}));
}); });
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment