Bug 1370752: Part 2 - Allow fallback serializer when JSON.serialize fails. r?aswan
Currently, we need to be able to handle serializing non-JSON-compatible
objects without catastrophically failing to save the storage file. Ideally, we
would ensure this in the ordinary toJSON method. However, that would require
a unnecessary extra calls to JSON.stringify for each object that needs to be
sanitized before returning a JSON-safe value, which is more expensive than we
can afford.
The fallback toJSONSafe method allows us to do this only when necessary, due
to an initial failed JSON serialization.
MozReview-Commit-ID: JXQ001dOGtW
--- a/toolkit/modules/JSONFile.jsm
+++ b/toolkit/modules/JSONFile.jsm
@@ -281,18 +281,30 @@ JSONFile.prototype = {
*
* If an error occurs, the previous file is not deleted.
*
* @return {Promise}
* @resolves When the operation finished successfully.
* @rejects JavaScript exception.
*/
async _save() {
+ let json;
+ try {
+ json = JSON.stringify(this._data);
+ } catch (e) {
+ // If serialization fails, try fallback safe JSON converter.
+ if (typeof this._data.toJSONSafe == "function") {
+ json = JSON.stringify(this._data.toJSONSafe());
+ } else {
+ throw e;
+ }
+ }
+
// Create or overwrite the file.
- let bytes = gTextEncoder.encode(JSON.stringify(this._data));
+ let bytes = gTextEncoder.encode(json);
if (this._beforeSave) {
await Promise.resolve(this._beforeSave());
}
await OS.File.writeAtomic(this.path, bytes,
Object.assign(
{ tmpPath: this.path + ".tmp" },
this._options));
},