Commit 53cfcd0b authored by Romain Courteaud's avatar Romain Courteaud

Reset gadget state in case of error.

In case of onStateChange cancellation/error, reset the internal gadget state.
It will simplify the code of each onStateChange function, as developpers will
not have to handle such issue.
parent fb92d31a
...@@ -453,6 +453,7 @@ ...@@ -453,6 +453,7 @@
}; };
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);
}); });
...@@ -583,7 +584,8 @@ ...@@ -583,7 +584,8 @@
.declareMethod('changeState', function (state_dict) { .declareMethod('changeState', function (state_dict) {
var key, var key,
modified = false, modified = false,
modification_dict = {}; modification_dict = {},
context = this;
for (key in state_dict) { for (key in state_dict) {
if (state_dict[key] !== this.state[key]) { if (state_dict[key] !== this.state[key]) {
this.state[key] = state_dict[key]; this.state[key] = state_dict[key];
...@@ -592,7 +594,18 @@ ...@@ -592,7 +594,18 @@
} }
} }
if (modified && this.__state_change_callback !== undefined) { if (modified && this.__state_change_callback !== undefined) {
return this.__state_change_callback(modification_dict); return new RSVP.Queue()
.push(function () {
return context.__state_change_callback(modification_dict);
})
.push(undefined, function (error) {
if (context.__json_state !== undefined) {
context.state = JSON.parse(context.__json_state);
} else {
context.state = {};
}
throw error;
});
} }
}); });
......
...@@ -1327,6 +1327,54 @@ ...@@ -1327,6 +1327,54 @@
}); });
}); });
test('reset state on onStateChange error', function () {
var gadget = new RenderJSGadget();
gadget.state = {foo: 'bar', bar: 'foo'};
gadget.__state_change_callback = function () {
throw new Error('failure in onStateChange');
};
stop();
gadget.changeState({bar: 'barbar'})
.then(function () {
ok(false, 'Expecting an error');
})
.fail(function (error) {
equal(error.message, 'failure in onStateChange');
deepEqual(gadget.state, {});
})
.always(function () {
start();
});
});
test('reset to default state on onStateChange error', function () {
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.prototype.__json_state = JSON.stringify({a: 'b'});
gadget = new Klass();
gadget.state = {foo: 'bar', bar: 'foo'};
gadget.__state_change_callback = function () {
throw new Error('failure in onStateChange');
};
stop();
gadget.changeState({bar: 'barbar'})
.then(function () {
ok(false, 'Expecting an error');
})
.fail(function (error) {
equal(error.message, 'failure in onStateChange');
deepEqual(gadget.state, {a: 'b'});
})
.always(function () {
start();
});
});
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// RenderJSGadgetKlass.declareAcquiredMethod // RenderJSGadgetKlass.declareAcquiredMethod
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -1786,8 +1834,9 @@ ...@@ -1786,8 +1834,9 @@
Klass.ready = RenderJSGadget.ready; Klass.ready = RenderJSGadget.ready;
Klass.setState = RenderJSGadget.setState; Klass.setState = RenderJSGadget.setState;
Klass.setState({}); 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