[IMP] web: add Registry predicate

Before this commit, any value could be added to registries and the class
needed to be overridden to assert that added values would answer to a
certain predicate.

Now, the registry can be instantiated with a given predicate function
that all added value must pass to be registered (default: all values
are accepted).

Existing implentations have been adapted:
- FieldRegistry
- FieldRegistryOwl.
This commit is contained in:
Julien Mougenot
2020-07-23 08:21:09 +00:00
committed by Mathieu Duckerts-Antoine
parent ea1741bc74
commit 5698d1fab9
4 changed files with 38 additions and 24 deletions
+13 -2
View File
@@ -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;
@@ -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) {
@@ -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) {
@@ -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"]);
});
});
});