Deep-clone model settings in lib/builtin-models

Fix the code loading builtin models to always clone the JSON object
used as model settings/definition. This is needed to allow applications
to modify model settings while not affecting settings of new models
created in the local registry of another app.
This commit is contained in:
Miroslav Bajtoš 2017-02-24 15:11:06 +01:00
parent c45954cdaa
commit f0c9700e1d
No known key found for this signature in database
GPG Key ID: 797723F23CE0A94A
1 changed files with 28 additions and 0 deletions

View File

@ -4,6 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
const assert = require('assert');
module.exports = function(registry) { module.exports = function(registry) {
// NOTE(bajtos) we must use static require() due to browserify limitations // NOTE(bajtos) we must use static require() due to browserify limitations
@ -52,8 +55,33 @@ module.exports = function(registry) {
require('../common/models/checkpoint.js')); require('../common/models/checkpoint.js'));
function createModel(definitionJson, customizeFn) { function createModel(definitionJson, customizeFn) {
// Clone the JSON definition to allow applications
// to modify model settings while not affecting
// settings of new models created in the local registry
// of another app.
// This is needed because require() always returns the same
// object instance it loaded during the first call.
definitionJson = cloneDeepJson(definitionJson);
var Model = registry.createModel(definitionJson); var Model = registry.createModel(definitionJson);
customizeFn(Model); customizeFn(Model);
return Model; return Model;
} }
}; };
// Because we are cloning objects created by JSON.parse,
// the cloning algorithm can stay much simpler than a general-purpose
// "cloneDeep" e.g. from lodash.
function cloneDeepJson(obj) {
const result = Array.isArray(obj) ? [] : {};
assert.equal(Object.getPrototypeOf(result), Object.getPrototypeOf(obj));
for (const key in obj) {
const value = obj[key];
if (typeof value === 'object') {
result[key] = cloneDeepJson(value);
} else {
result[key] = value;
}
}
return result;
}