diff --git a/lib/builtin-models.js b/lib/builtin-models.js index f9342a84..0679f670 100644 --- a/lib/builtin-models.js +++ b/lib/builtin-models.js @@ -4,6 +4,9 @@ // License text available at https://opensource.org/licenses/MIT 'use strict'; + +const assert = require('assert'); + module.exports = function(registry) { // NOTE(bajtos) we must use static require() due to browserify limitations @@ -52,8 +55,33 @@ module.exports = function(registry) { require('../common/models/checkpoint.js')); 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); customizeFn(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; +}