From d9257d3aae9c93ecfeb4cfc9c34b5e0eaa5a8e59 Mon Sep 17 00:00:00 2001 From: Lucas Perais Date: Tue, 9 Aug 2022 16:22:33 +0000 Subject: [PATCH] [FIX] web: core: domain supports domain as tuples Have a domain declared somewhere in the XML as: `("&", ("field", "=", "value"), ("field2", "=", "value2"))` Before this commit, that expression made the Domain algorithm crash, because tuples were not allowed. After this commit, only tuples containing at least one other tuple and some optional strings are accepted. closes odoo/odoo#97850 Signed-off-by: Mathieu Duckerts-Antoine --- addons/web/static/src/core/domain.js | 17 +++++++++--- addons/web/static/tests/core/domain_tests.js | 28 +++++++++++++++++--- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/addons/web/static/src/core/domain.js b/addons/web/static/src/core/domain.js index 4d7c5ba2c6c..6fac7e437e6 100644 --- a/addons/web/static/src/core/domain.js +++ b/addons/web/static/src/core/domain.js @@ -152,20 +152,31 @@ function toAST(domain) { function normalizeDomainAST(domain, op = "&") { if (domain.type !== 4 /* List */) { - throw new InvalidDomainError("Invalid domain AST"); + if (domain.type === 10 /* Tuple */) { + const value = domain.value; + /* Tuple contains at least one Tuple and optionally string */ + if ( + value.findIndex((e) => e.type === 10) === -1 || + !value.every((e) => e.type === 10 || e.type === 1) + ) { + throw new InvalidDomainError("Invalid domain AST"); + } + } else { + throw new InvalidDomainError("Invalid domain AST"); + } } if (domain.value.length === 0) { return domain; } let expected = 1; - for (let child of domain.value) { + for (const child of domain.value) { if (child.type === 1 /* String */ && (child.value === "&" || child.value === "|")) { expected++; } else if (child.type !== 1 /* String */ || child.value !== "!") { expected--; } } - let values = domain.value.slice(); + const values = domain.value.slice(); while (expected < 0) { expected++; values.unshift({ type: 1 /* String */, value: op }); diff --git a/addons/web/static/tests/core/domain_tests.js b/addons/web/static/tests/core/domain_tests.js index b8dc91de9af..3195b0cfd19 100644 --- a/addons/web/static/tests/core/domain_tests.js +++ b/addons/web/static/tests/core/domain_tests.js @@ -286,10 +286,18 @@ QUnit.module("domain", {}, () => { assert.deepEqual(new Domain(domainStr).toList(), [["date", ">=", "2013-03-25"]]); domainStr = "[('date', '>=', context_today() - relativedelta(days=30))]"; const domainList = new Domain(domainStr).toList(); // domain creation using `parseExpr` function since the parameter is a string. - assert.deepEqual(domainList[0][2], PyDate.create({ day: 25, month: 3, year: 2013 }), 'The right item in the rule in the domain should be a PyDate object'); + assert.deepEqual( + domainList[0][2], + PyDate.create({ day: 25, month: 3, year: 2013 }), + "The right item in the rule in the domain should be a PyDate object" + ); assert.deepEqual(JSON.stringify(domainList), '[["date",">=","2013-03-25"]]'); const domainList2 = new Domain(domainList).toList(); // domain creation using `toAST` function since the parameter is a list. - assert.deepEqual(domainList2[0][2], PyDate.create({ day: 25, month: 3, year: 2013 }), 'The right item in the rule in the domain should be a PyDate object'); + assert.deepEqual( + domainList2[0][2], + PyDate.create({ day: 25, month: 3, year: 2013 }), + "The right item in the rule in the domain should be a PyDate object" + ); assert.deepEqual(JSON.stringify(domainList2), '[["date",">=","2013-03-25"]]'); }); @@ -375,7 +383,7 @@ QUnit.module("domain", {}, () => { QUnit.test("return simple (normalized) domains", function (assert) { const domains = ["[]", `[("a", "=", 1)]`, `["!", ("a", "=", 1)]`]; - for (let domain of domains) { + for (const domain of domains) { assert.strictEqual(new Domain(domain).toString(), domain); } }); @@ -527,4 +535,18 @@ QUnit.module("domain", {}, () => { `["!", ("a", "=", 1)]` ); }); + + QUnit.test("tuple are supported", (assert) => { + assert.deepEqual( + new Domain(`(("field", "like", "string"), ("field", "like", "strOng"))`).toList(), + ["&", ["field", "like", "string"], ["field", "like", "strOng"]] + ); + assert.deepEqual(new Domain(`("!",("field", "like", "string"))`).toList(), [ + "!", + ["field", "like", "string"], + ]); + assert.throws(() => new Domain(`(("field", "like", "string"))`), /Invalid domain AST/); + assert.throws(() => new Domain(`("&", "&", "|")`), /Invalid domain AST/); + assert.throws(() => new Domain(`("&", "&", 3)`), /Invalid domain AST/); + }); });