Compare commits

..

2 Commits

Author SHA1 Message Date
Géry Debongnie 875ebdcfb0 [REL] v2.2.1
# v2.2.1

 - [FIX] compiler: allow t-out on component tag
2023-07-19 15:22:35 +02:00
Géry Debongnie 2e07799250 [FIX] compiler: allow t-out on component tag
Before this commit, the template parser would allow using t-esc on a
component tag (<MyComponent t-esc="expr"/>) but would incorrectly ignore
the component when parsing a t-out: <MyComponent t-out="expr"/> would be
parsed as <t t-out="expr"/>

This commit solves the issue, and also, moves the `t-out` parsing code
next to `t-esc` so they have the same priority relatively to other
directives.

closes #1483
2023-07-19 15:16:26 +02:00
6 changed files with 46 additions and 42 deletions
+19 -20
View File
@@ -4839,10 +4839,10 @@ function parseNode(node, ctx) {
parseTCall(node, ctx) || parseTCall(node, ctx) ||
parseTCallBlock(node) || parseTCallBlock(node) ||
parseTEscNode(node, ctx) || parseTEscNode(node, ctx) ||
parseTOutNode(node, ctx) ||
parseTKey(node, ctx) || parseTKey(node, ctx) ||
parseTTranslation(node, ctx) || parseTTranslation(node, ctx) ||
parseTSlot(node, ctx) || parseTSlot(node, ctx) ||
parseTOutNode(node, ctx) ||
parseComponent(node, ctx) || parseComponent(node, ctx) ||
parseDOMNode(node, ctx) || parseDOMNode(node, ctx) ||
parseTSetNode(node, ctx) || parseTSetNode(node, ctx) ||
@@ -5032,9 +5032,6 @@ function parseTEscNode(node, ctx) {
content: [tesc], content: [tesc],
}; };
} }
if (ast.type === 11 /* TComponent */) {
throw new OwlError("t-esc is not supported on Component nodes");
}
return tesc; return tesc;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -5476,19 +5473,21 @@ function normalizeTIf(el) {
* *
* @param el the element containing the tree that should be normalized * @param el the element containing the tree that should be normalized
*/ */
function normalizeTEsc(el) { function normalizeTEscTOut(el) {
const elements = [...el.querySelectorAll("[t-esc]")].filter((el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component")); for (const d of ["t-esc", "t-out"]) {
for (const el of elements) { const elements = [...el.querySelectorAll(`[${d}]`)].filter((el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component"));
if (el.childNodes.length) { for (const el of elements) {
throw new OwlError("Cannot have t-esc on a component that already has content"); if (el.childNodes.length) {
throw new OwlError(`Cannot have ${d} on a component that already has content`);
}
const value = el.getAttribute(d);
el.removeAttribute(d);
const t = el.ownerDocument.createElement("t");
if (value != null) {
t.setAttribute(d, value);
}
el.appendChild(t);
} }
const value = el.getAttribute("t-esc");
el.removeAttribute("t-esc");
const t = el.ownerDocument.createElement("t");
if (value != null) {
t.setAttribute("t-esc", value);
}
el.appendChild(t);
} }
} }
/** /**
@@ -5499,7 +5498,7 @@ function normalizeTEsc(el) {
*/ */
function normalizeXML(el) { function normalizeXML(el) {
normalizeTIf(el); normalizeTIf(el);
normalizeTEsc(el); normalizeTEscTOut(el);
} }
/** /**
* Parses an XML string into an XML document, throwing errors on parser errors * Parses an XML string into an XML document, throwing errors on parser errors
@@ -5552,7 +5551,7 @@ function compile(template, options = {}) {
} }
// do not modify manually. This file is generated by the release script. // do not modify manually. This file is generated by the release script.
const version = "2.1.4"; const version = "2.2";
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Scheduler // Scheduler
@@ -5985,6 +5984,6 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
export { App, Component, EventBus, OwlError, __info__, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml }; export { App, Component, EventBus, OwlError, __info__, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml };
__info__.date = '2023-07-18T14:07:26.565Z'; __info__.date = '2023-07-19T13:22:24.480Z';
__info__.hash = '836e12b'; __info__.hash = '2e07799';
__info__.url = 'https://github.com/odoo/owl'; __info__.url = 'https://github.com/odoo/owl';
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@odoo/owl", "name": "@odoo/owl",
"version": "2.2", "version": "2.2.1",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@odoo/owl", "name": "@odoo/owl",
"version": "2.2", "version": "2.2.1",
"description": "Odoo Web Library (OWL)", "description": "Odoo Web Library (OWL)",
"main": "dist/owl.cjs.js", "main": "dist/owl.cjs.js",
"module": "dist/owl.es.js", "module": "dist/owl.es.js",
+18 -19
View File
@@ -235,10 +235,10 @@ function parseNode(node: Node, ctx: ParsingContext): AST | null {
parseTCall(node, ctx) || parseTCall(node, ctx) ||
parseTCallBlock(node, ctx) || parseTCallBlock(node, ctx) ||
parseTEscNode(node, ctx) || parseTEscNode(node, ctx) ||
parseTOutNode(node, ctx) ||
parseTKey(node, ctx) || parseTKey(node, ctx) ||
parseTTranslation(node, ctx) || parseTTranslation(node, ctx) ||
parseTSlot(node, ctx) || parseTSlot(node, ctx) ||
parseTOutNode(node, ctx) ||
parseComponent(node, ctx) || parseComponent(node, ctx) ||
parseDOMNode(node, ctx) || parseDOMNode(node, ctx) ||
parseTSetNode(node, ctx) || parseTSetNode(node, ctx) ||
@@ -444,9 +444,6 @@ function parseTEscNode(node: Element, ctx: ParsingContext): AST | null {
content: [tesc], content: [tesc],
}; };
} }
if (ast.type === ASTType.TComponent) {
throw new OwlError("t-esc is not supported on Component nodes");
}
return tesc; return tesc;
} }
@@ -941,21 +938,23 @@ function normalizeTIf(el: Element) {
* *
* @param el the element containing the tree that should be normalized * @param el the element containing the tree that should be normalized
*/ */
function normalizeTEsc(el: Element) { function normalizeTEscTOut(el: Element) {
const elements = [...el.querySelectorAll("[t-esc]")].filter( for (const d of ["t-esc", "t-out"]) {
(el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component") const elements = [...el.querySelectorAll(`[${d}]`)].filter(
); (el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component")
for (const el of elements) { );
if (el.childNodes.length) { for (const el of elements) {
throw new OwlError("Cannot have t-esc on a component that already has content"); if (el.childNodes.length) {
throw new OwlError(`Cannot have ${d} on a component that already has content`);
}
const value = el.getAttribute(d);
el.removeAttribute(d);
const t = el.ownerDocument.createElement("t");
if (value != null) {
t.setAttribute(d, value);
}
el.appendChild(t);
} }
const value = el.getAttribute("t-esc");
el.removeAttribute("t-esc");
const t = el.ownerDocument.createElement("t");
if (value != null) {
t.setAttribute("t-esc", value);
}
el.appendChild(t);
} }
} }
@@ -967,7 +966,7 @@ function normalizeTEsc(el: Element) {
*/ */
function normalizeXML(el: Element) { function normalizeXML(el: Element) {
normalizeTIf(el); normalizeTIf(el);
normalizeTEsc(el); normalizeTEscTOut(el);
} }
/** /**
+1 -1
View File
@@ -1,2 +1,2 @@
// do not modify manually. This file is generated by the release script. // do not modify manually. This file is generated by the release script.
export const version = "2.2"; export const version = "2.2.1";
+6
View File
@@ -1569,6 +1569,12 @@ describe("qweb parser", () => {
); );
}); });
test("component with t-out", async () => {
expect(parse(`<MyComponent t-out="someValue"/>`)).toEqual(
parse(`<MyComponent><t t-out="someValue"/></MyComponent>`)
);
});
test("component with t-esc and content", async () => { test("component with t-esc and content", async () => {
expect(() => parse(`<MyComponent t-esc="someValue">Some content</MyComponent>`)).toThrow( expect(() => parse(`<MyComponent t-esc="someValue">Some content</MyComponent>`)).toThrow(
"Cannot have t-esc on a component that already has content" "Cannot have t-esc on a component that already has content"