diff --git a/addons/web/static/src/js/core/registry.js b/addons/web/static/src/js/core/registry.js index 7b2c69db180..1ab16236e59 100644 --- a/addons/web/static/src/js/core/registry.js +++ b/addons/web/static/src/js/core/registry.js @@ -20,13 +20,21 @@ odoo.define("web.Registry", function (require) { */ class Registry { /** - * @param {Object} [mapping] the initial data in the registry + * @function predicate + * @param {any} value + * @returns {boolean} */ - constructor(mapping) { + /** + * @param {Object} [mapping] the initial data in the registry + * @param {predicate} [predicate=(() => true)] predicate that each + * added value must pass to be registered. + */ + constructor(mapping, predicate = () => true) { this.map = Object.create(mapping || null); this._scoreMapping = Object.create(null); this._sortedKeys = null; this.listeners = []; // listening callbacks on newly added items. + this.predicate = predicate; } //-------------------------------------------------------------------------- @@ -42,6 +50,9 @@ odoo.define("web.Registry", function (require) { * @returns {Registry} can be used to chain add calls. */ add(key, value, score) { + if (!this.predicate(value)) { + throw new Error(`Value of key "${key}" does not pass the addition predicate.`); + } this._scoreMapping[key] = score === undefined ? key : score; this._sortedKeys = null; this.map[key] = value; diff --git a/addons/web/static/src/js/fields/field_registry.js b/addons/web/static/src/js/fields/field_registry.js index 925b405051e..ef174702579 100644 --- a/addons/web/static/src/js/fields/field_registry.js +++ b/addons/web/static/src/js/fields/field_registry.js @@ -1,18 +1,12 @@ odoo.define('web.field_registry', function (require) { -"use strict"; + "use strict"; -var Registry = require('web.Registry'); + const Registry = require('web.Registry'); -var FieldRegistry = Registry.extend({ - add: function (key, value, score) { - if (value.prototype instanceof owl.Component) { - throw new Error("This registry should not contain any Component. Use 'web.field_registry_owl' instead."); - } - return this._super(...arguments); - }, -}); - -return new FieldRegistry(); + return new Registry( + null, + (value) => !(value.prototype instanceof owl.Component) + ); }); odoo.define('web._field_registry', function (require) { diff --git a/addons/web/static/src/js/fields/field_registry_owl.js b/addons/web/static/src/js/fields/field_registry_owl.js index 907ea38a9d7..635db621829 100644 --- a/addons/web/static/src/js/fields/field_registry_owl.js +++ b/addons/web/static/src/js/fields/field_registry_owl.js @@ -3,16 +3,10 @@ odoo.define('web.field_registry_owl', function (require) { const Registry = require('web.Registry'); - const FieldRegistry = Registry.extend({ - add: function (key, value, score) { - if (!(value.prototype instanceof owl.Component)) { - throw new Error("This registry should only contain subclasses of Component"); - } - return this._super(...arguments); - }, - }); - - return new FieldRegistry(); + return new Registry( + null, + (value) => value.prototype instanceof owl.Component + ); }); odoo.define('web._field_registry_owl', function (require) { diff --git a/addons/web/static/tests/core/registry_tests.js b/addons/web/static/tests/core/registry_tests.js index 9f9f7b467cb..eb3389a4383 100644 --- a/addons/web/static/tests/core/registry_tests.js +++ b/addons/web/static/tests/core/registry_tests.js @@ -70,6 +70,21 @@ QUnit.module('core', {}, function () { assert.deepEqual(registry.values(), ['bar', 'foo', 'qux']); }); + QUnit.test("predicate prevents invalid values", function (assert) { + assert.expect(5); + + const predicate = value => typeof value === "number"; + const registry = new Registry(null, predicate); + registry.onAdd((key) => assert.step(key)); + + assert.ok(registry.add("age", 23)); + assert.throws( + () => registry.add("name", "Fred"), + new Error(`Value of key "name" does not pass the addition predicate.`) + ); + assert.deepEqual(registry.entries(), { age: 23 }); + assert.verifySteps(["age"]); + }); }); });