mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7bc9d34a64 | |||
| b1a3b322ee | |||
| ca688d8640 | |||
| ea9f533536 | |||
| 875ebdcfb0 | |||
| 2e07799250 |
+20
-21
@@ -4839,10 +4839,10 @@ function parseNode(node, ctx) {
|
||||
parseTCall(node, ctx) ||
|
||||
parseTCallBlock(node) ||
|
||||
parseTEscNode(node, ctx) ||
|
||||
parseTOutNode(node, ctx) ||
|
||||
parseTKey(node, ctx) ||
|
||||
parseTTranslation(node, ctx) ||
|
||||
parseTSlot(node, ctx) ||
|
||||
parseTOutNode(node, ctx) ||
|
||||
parseComponent(node, ctx) ||
|
||||
parseDOMNode(node, ctx) ||
|
||||
parseTSetNode(node, ctx) ||
|
||||
@@ -5032,9 +5032,6 @@ function parseTEscNode(node, ctx) {
|
||||
content: [tesc],
|
||||
};
|
||||
}
|
||||
if (ast.type === 11 /* TComponent */) {
|
||||
throw new OwlError("t-esc is not supported on Component nodes");
|
||||
}
|
||||
return tesc;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -5476,19 +5473,21 @@ function normalizeTIf(el) {
|
||||
*
|
||||
* @param el the element containing the tree that should be normalized
|
||||
*/
|
||||
function normalizeTEsc(el) {
|
||||
const elements = [...el.querySelectorAll("[t-esc]")].filter((el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component"));
|
||||
for (const el of elements) {
|
||||
if (el.childNodes.length) {
|
||||
throw new OwlError("Cannot have t-esc on a component that already has content");
|
||||
function normalizeTEscTOut(el) {
|
||||
for (const d of ["t-esc", "t-out"]) {
|
||||
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) {
|
||||
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) {
|
||||
normalizeTIf(el);
|
||||
normalizeTEsc(el);
|
||||
normalizeTEscTOut(el);
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
const version = "2.1.4";
|
||||
const version = "2.2.3";
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Scheduler
|
||||
@@ -5709,8 +5708,8 @@ class App extends TemplateSet {
|
||||
}
|
||||
destroy() {
|
||||
if (this.root) {
|
||||
this.scheduler.flush();
|
||||
this.root.destroy();
|
||||
this.scheduler.processTasks();
|
||||
}
|
||||
window.__OWL_DEVTOOLS__.apps.delete(this);
|
||||
}
|
||||
@@ -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 };
|
||||
|
||||
|
||||
__info__.date = '2023-07-18T14:07:26.565Z';
|
||||
__info__.hash = '836e12b';
|
||||
__info__.date = '2023-07-20T06:05:29.796Z';
|
||||
__info__.hash = 'b1a3b32';
|
||||
__info__.url = 'https://github.com/odoo/owl';
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@odoo/owl",
|
||||
"version": "2.2",
|
||||
"version": "2.2.3",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@odoo/owl",
|
||||
"version": "2.2",
|
||||
"version": "2.2.3",
|
||||
"description": "Odoo Web Library (OWL)",
|
||||
"main": "dist/owl.cjs.js",
|
||||
"module": "dist/owl.es.js",
|
||||
|
||||
+18
-19
@@ -235,10 +235,10 @@ function parseNode(node: Node, ctx: ParsingContext): AST | null {
|
||||
parseTCall(node, ctx) ||
|
||||
parseTCallBlock(node, ctx) ||
|
||||
parseTEscNode(node, ctx) ||
|
||||
parseTOutNode(node, ctx) ||
|
||||
parseTKey(node, ctx) ||
|
||||
parseTTranslation(node, ctx) ||
|
||||
parseTSlot(node, ctx) ||
|
||||
parseTOutNode(node, ctx) ||
|
||||
parseComponent(node, ctx) ||
|
||||
parseDOMNode(node, ctx) ||
|
||||
parseTSetNode(node, ctx) ||
|
||||
@@ -444,9 +444,6 @@ function parseTEscNode(node: Element, ctx: ParsingContext): AST | null {
|
||||
content: [tesc],
|
||||
};
|
||||
}
|
||||
if (ast.type === ASTType.TComponent) {
|
||||
throw new OwlError("t-esc is not supported on Component nodes");
|
||||
}
|
||||
return tesc;
|
||||
}
|
||||
|
||||
@@ -941,21 +938,23 @@ function normalizeTIf(el: Element) {
|
||||
*
|
||||
* @param el the element containing the tree that should be normalized
|
||||
*/
|
||||
function normalizeTEsc(el: Element) {
|
||||
const elements = [...el.querySelectorAll("[t-esc]")].filter(
|
||||
(el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component")
|
||||
);
|
||||
for (const el of elements) {
|
||||
if (el.childNodes.length) {
|
||||
throw new OwlError("Cannot have t-esc on a component that already has content");
|
||||
function normalizeTEscTOut(el: Element) {
|
||||
for (const d of ["t-esc", "t-out"]) {
|
||||
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) {
|
||||
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) {
|
||||
normalizeTIf(el);
|
||||
normalizeTEsc(el);
|
||||
normalizeTEscTOut(el);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -136,8 +136,8 @@ export class App<
|
||||
|
||||
destroy() {
|
||||
if (this.root) {
|
||||
this.scheduler.flush();
|
||||
this.root.destroy();
|
||||
this.scheduler.processTasks();
|
||||
}
|
||||
window.__OWL_DEVTOOLS__.apps.delete(this);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
// do not modify manually. This file is generated by the release script.
|
||||
export const version = "2.2";
|
||||
export const version = "2.2.3";
|
||||
|
||||
@@ -15,6 +15,34 @@ exports[`app App supports env with getters/setters 1`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`app app: clear scheduler tasks and destroy cancelled nodes immediately on destroy 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
const comp1 = app.createComponent(\`B\`, true, false, false, []);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let b2,b3;
|
||||
b2 = text(\`A\`);
|
||||
if (ctx['state'].value) {
|
||||
b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||
}
|
||||
return multi([b2, b3]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`app app: clear scheduler tasks and destroy cancelled nodes immediately on destroy 2`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return text(\`B\`);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`app can configure an app with props 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
|
||||
+50
-2
@@ -1,6 +1,14 @@
|
||||
import { App, Component, mount, xml } from "../../src";
|
||||
import { App, Component, mount, onWillStart, useState, xml } from "../../src";
|
||||
import { status } from "../../src/runtime/status";
|
||||
import { makeTestFixture, snapshotEverything, nextTick, elem } from "../helpers";
|
||||
import {
|
||||
makeTestFixture,
|
||||
snapshotEverything,
|
||||
nextTick,
|
||||
elem,
|
||||
useLogLifecycle,
|
||||
makeDeferred,
|
||||
nextMicroTick,
|
||||
} from "../helpers";
|
||||
|
||||
let fixture: HTMLElement;
|
||||
|
||||
@@ -94,4 +102,44 @@ describe("app", () => {
|
||||
expect(iframeDoc.contains(div)).toBe(false);
|
||||
expect(status(comp)).toBe("destroyed");
|
||||
});
|
||||
|
||||
test("app: clear scheduler tasks and destroy cancelled nodes immediately on destroy", async () => {
|
||||
let def = makeDeferred();
|
||||
class B extends Component {
|
||||
static template = xml`B`;
|
||||
setup() {
|
||||
useLogLifecycle();
|
||||
onWillStart(() => def);
|
||||
}
|
||||
}
|
||||
class A extends Component {
|
||||
static template = xml`A<t t-if="state.value"><B/></t>`;
|
||||
static components = { B };
|
||||
state = useState({ value: false });
|
||||
setup() {
|
||||
useLogLifecycle();
|
||||
}
|
||||
}
|
||||
|
||||
const app = new App(A);
|
||||
const comp = await app.mount(fixture);
|
||||
expect(["A:setup", "A:willStart", "A:willRender", "A:rendered", "A:mounted"]).toBeLogged();
|
||||
|
||||
comp.state.value = true;
|
||||
await nextTick();
|
||||
expect(["A:willRender", "B:setup", "B:willStart", "A:rendered"]).toBeLogged();
|
||||
|
||||
// rerender to force the instantiation of a new B component (and cancelling the first)
|
||||
comp.render();
|
||||
await nextMicroTick();
|
||||
expect(["A:willRender", "B:setup", "B:willStart", "A:rendered"]).toBeLogged();
|
||||
|
||||
app.destroy();
|
||||
expect([
|
||||
"A:willUnmount",
|
||||
"B:willDestroy",
|
||||
"A:willDestroy",
|
||||
"B:willDestroy", // make sure the 2 B instances have been destroyed synchronously
|
||||
]).toBeLogged();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 () => {
|
||||
expect(() => parse(`<MyComponent t-esc="someValue">Some content</MyComponent>`)).toThrow(
|
||||
"Cannot have t-esc on a component that already has content"
|
||||
|
||||
+6
-7
@@ -82,6 +82,12 @@ async function startRelease() {
|
||||
return;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
log(`Step ${step++}/${STEPS}: updating package.json...`);
|
||||
await writeFile("package.json", JSON.stringify({...package, version: next}, null, 2) + "\n");
|
||||
await writeFile("package-lock.json", JSON.stringify({...packageLock, version: next}, null, 2) + "\n");
|
||||
await writeFile("./src/version.ts", `// do not modify manually. This file is generated by the release script.\nexport const version = "${next}";\n`);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
log(`Step ${step++}/${STEPS}: building owl...`);
|
||||
await execCommand("rm -rf dist/");
|
||||
@@ -108,13 +114,6 @@ async function startRelease() {
|
||||
await execCommand("cd dist && zip -r owl-devtools.zip devtools-chrome devtools-firefox && cd ..");
|
||||
await execCommand("rm -r dist/devtools-chrome dist/devtools-firefox && rm dist/compiler.js");
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
log(`Step ${step++}/${STEPS}: updating package.json...`);
|
||||
await writeFile("package.json", JSON.stringify({...package, version: next}, null, 2) + "\n");
|
||||
await writeFile("package-lock.json", JSON.stringify({...packageLock, version: next}, null, 2) + "\n");
|
||||
await writeFile("./src/version.ts", `// do not modify manually. This file is generated by the release script.\nexport const version = "${next}";\n`);
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
log(`Step ${step++}/${STEPS}: updating owl on github page...`);
|
||||
await fs.copyFileSync("dist/owl.es.js", "docs/owl.js");
|
||||
|
||||
Reference in New Issue
Block a user