mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5efc9ad462 |
@@ -124,7 +124,7 @@ npm install @odoo/owl
|
|||||||
|
|
||||||
If you want to use a simple `<script>` tag, the last release can be downloaded here:
|
If you want to use a simple `<script>` tag, the last release can be downloaded here:
|
||||||
|
|
||||||
- [owl-1.4.8](https://github.com/odoo/owl/releases/tag/v1.4.8)
|
- [owl-1.4.5](https://github.com/odoo/owl/releases/tag/v1.4.5)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odoo/owl",
|
"name": "@odoo/owl",
|
||||||
"version": "1.4.8",
|
"version": "1.4.5",
|
||||||
"description": "Odoo Web Library (OWL)",
|
"description": "Odoo Web Library (OWL)",
|
||||||
"main": "dist/owl.cjs.js",
|
"main": "dist/owl.cjs.js",
|
||||||
"browser": "dist/owl.iife.js",
|
"browser": "dist/owl.iife.js",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# 🦉 OWL Roadmap 🦉
|
# 🦉 OWL Roadmap 🦉
|
||||||
|
|
||||||
- Current version: 1.4.8
|
- Current version: 1.4.5
|
||||||
- Status: stable
|
- Status: stable
|
||||||
|
|
||||||
This roadmap is only an attempt at predicting Owl's future. Everything may
|
This roadmap is only an attempt at predicting Owl's future. Everything may
|
||||||
|
|||||||
@@ -400,7 +400,6 @@ export class Component<Props extends {} = any, T extends Env = Env> {
|
|||||||
if (currentFiber && !currentFiber.isRendered && !currentFiber.isCompleted) {
|
if (currentFiber && !currentFiber.isRendered && !currentFiber.isCompleted) {
|
||||||
return scheduler.addFiber(currentFiber.root);
|
return scheduler.addFiber(currentFiber.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we aren't mounted at this point, it implies that there is a
|
// if we aren't mounted at this point, it implies that there is a
|
||||||
// currentFiber that is already rendered (isRendered is true), so we are
|
// currentFiber that is already rendered (isRendered is true), so we are
|
||||||
// about to be mounted
|
// about to be mounted
|
||||||
@@ -506,6 +505,7 @@ export class Component<Props extends {} = any, T extends Env = Env> {
|
|||||||
const __owl__ = this.__owl__;
|
const __owl__ = this.__owl__;
|
||||||
|
|
||||||
__owl__.status = STATUS.MOUNTED;
|
__owl__.status = STATUS.MOUNTED;
|
||||||
|
__owl__.currentFiber = null;
|
||||||
this.mounted();
|
this.mounted();
|
||||||
if (__owl__.mountedCB) {
|
if (__owl__.mountedCB) {
|
||||||
__owl__.mountedCB();
|
__owl__.mountedCB();
|
||||||
|
|||||||
@@ -198,7 +198,6 @@ export class Fiber {
|
|||||||
// build patchQueue
|
// build patchQueue
|
||||||
const patchQueue: Fiber[] = [];
|
const patchQueue: Fiber[] = [];
|
||||||
const doWork: (Fiber) => Fiber | null = function (f) {
|
const doWork: (Fiber) => Fiber | null = function (f) {
|
||||||
f.component.__owl__.currentFiber = null;
|
|
||||||
patchQueue.push(f);
|
patchQueue.push(f);
|
||||||
return f.child;
|
return f.child;
|
||||||
};
|
};
|
||||||
@@ -243,9 +242,8 @@ export class Fiber {
|
|||||||
}
|
}
|
||||||
component.__patch(target!, fiber.vnode!);
|
component.__patch(target!, fiber.vnode!);
|
||||||
} else {
|
} else {
|
||||||
const vnode = component.__owl__.vnode;
|
if (fiber.shouldPatch) {
|
||||||
if (fiber.shouldPatch && vnode) {
|
component.__patch(component.__owl__.vnode!, fiber.vnode!);
|
||||||
component.__patch(vnode, fiber.vnode!);
|
|
||||||
// When updating a Component's props (in directive),
|
// When updating a Component's props (in directive),
|
||||||
// the component has a pvnode AND should be patched.
|
// the component has a pvnode AND should be patched.
|
||||||
// However, its pvnode.elm may have changed if it is a High Order Component
|
// However, its pvnode.elm may have changed if it is a High Order Component
|
||||||
@@ -257,6 +255,10 @@ export class Fiber {
|
|||||||
component.__owl__.pvnode!.elm = component.__owl__.vnode!.elm;
|
component.__owl__.pvnode!.elm = component.__owl__.vnode!.elm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const compOwl = component.__owl__;
|
||||||
|
if (fiber === compOwl.currentFiber) {
|
||||||
|
compOwl.currentFiber = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert into the DOM (mount case)
|
// insert into the DOM (mount case)
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ Object.defineProperty(config, "mode", {
|
|||||||
|
|
||||||
This is not suitable for production use.
|
This is not suitable for production use.
|
||||||
See https://github.com/odoo/owl/blob/master/doc/reference/config.md#mode for more information.`);
|
See https://github.com/odoo/owl/blob/master/doc/reference/config.md#mode for more information.`);
|
||||||
|
} else {
|
||||||
|
console.log(`Owl is now running in 'prod' mode.`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -326,8 +326,7 @@ QWeb.addDirective({
|
|||||||
ctx.addLine(`if (!_${arrayID}) { throw new Error('QWeb error: Invalid loop expression')}`);
|
ctx.addLine(`if (!_${arrayID}) { throw new Error('QWeb error: Invalid loop expression')}`);
|
||||||
let keysID = ctx.generateID();
|
let keysID = ctx.generateID();
|
||||||
let valuesID = ctx.generateID();
|
let valuesID = ctx.generateID();
|
||||||
ctx.addLine(`let _${keysID} = _${arrayID};`);
|
ctx.addLine(`let _${keysID} = _${valuesID} = _${arrayID};`);
|
||||||
ctx.addLine(`let _${valuesID} = _${arrayID};`);
|
|
||||||
ctx.addIf(`!(_${arrayID} instanceof Array)`);
|
ctx.addIf(`!(_${arrayID} instanceof Array)`);
|
||||||
ctx.addLine(`_${keysID} = Object.keys(_${arrayID});`);
|
ctx.addLine(`_${keysID} = Object.keys(_${arrayID});`);
|
||||||
ctx.addLine(`_${valuesID} = Object.values(_${arrayID});`);
|
ctx.addLine(`_${valuesID} = Object.values(_${arrayID});`);
|
||||||
|
|||||||
@@ -420,29 +420,29 @@ describe("animations", () => {
|
|||||||
|
|
||||||
widget.state.flag = true;
|
widget.state.flag = true;
|
||||||
|
|
||||||
await nextFrame();
|
await nextFrame(3);
|
||||||
widget.el!.querySelector("span")!.dispatchEvent(new Event("transitionend"));
|
widget.el!.querySelector("span")!.dispatchEvent(new Event("transitionend"));
|
||||||
expect(fixture.innerHTML).toBe('<div><span class="">blue</span></div>');
|
expect(fixture.innerHTML).toBe('<div><span class="">blue</span></div>');
|
||||||
expect(QWeb.utils.transitionInsert).toBeCalledTimes(1);
|
expect(QWeb.utils.transitionInsert).toBeCalledTimes(1);
|
||||||
|
|
||||||
widget.state.flag = false;
|
widget.state.flag = false;
|
||||||
await nextFrame();
|
await nextFrame(3);
|
||||||
expect(fixture.innerHTML).toBe(
|
expect(fixture.innerHTML).toBe(
|
||||||
'<div><span class="chimay-leave-active chimay-leave-to" data-owl-key="__3__">blue</span></div>'
|
'<div><span class="chimay-leave-active chimay-leave-to" data-owl-key="__3__">blue</span></div>'
|
||||||
);
|
);
|
||||||
expect(QWeb.utils.transitionInsert).toBeCalledTimes(1);
|
expect(QWeb.utils.transitionInsert).toBeCalledTimes(1);
|
||||||
|
|
||||||
widget.state.flag = true;
|
widget.state.flag = true;
|
||||||
await nextFrame();
|
await nextFrame(3);
|
||||||
expect(fixture.innerHTML).toBe(
|
expect(fixture.innerHTML).toBe(
|
||||||
'<div><span class="chimay-enter-active chimay-enter-to" data-owl-key="__3__">blue</span></div>'
|
'<div><span class="chimay-enter-active chimay-enter-to" data-owl-key="__3__">blue</span></div>'
|
||||||
);
|
);
|
||||||
expect(QWeb.utils.transitionInsert).toBeCalledTimes(2);
|
expect(QWeb.utils.transitionInsert).toBeCalledTimes(2);
|
||||||
|
|
||||||
widget.state.flag = false;
|
widget.state.flag = false;
|
||||||
await nextFrame();
|
await nextFrame(3);
|
||||||
widget.state.flag = true;
|
widget.state.flag = true;
|
||||||
await nextFrame();
|
await nextFrame(3);
|
||||||
|
|
||||||
expect(QWeb.utils.transitionInsert).toBeCalledTimes(3);
|
expect(QWeb.utils.transitionInsert).toBeCalledTimes(3);
|
||||||
widget.el!.querySelector("span")!.dispatchEvent(new Event("transitionend"));
|
widget.el!.querySelector("span")!.dispatchEvent(new Event("transitionend"));
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['state'].s;
|
let _2 = scope['state'].s;
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -69,8 +68,7 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for
|
|||||||
let key1 = i1;
|
let key1 = i1;
|
||||||
let _6 = scope['section'].blips;
|
let _6 = scope['section'].blips;
|
||||||
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _7 = _6;
|
let _7 = _8 = _6;
|
||||||
let _8 = _6;
|
|
||||||
if (!(_6 instanceof Array)) {
|
if (!(_6 instanceof Array)) {
|
||||||
_7 = Object.keys(_6);
|
_7 = Object.keys(_6);
|
||||||
_8 = Object.values(_6);
|
_8 = Object.values(_6);
|
||||||
@@ -311,8 +309,7 @@ exports[`composition sub components with some state rendered in a loop 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['state'].numbers;
|
let _2 = scope['state'].numbers;
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -600,8 +597,7 @@ exports[`other directives with t-component t-on expression captured in t-foreach
|
|||||||
scope.iter = 0;
|
scope.iter = 0;
|
||||||
let _2 = scope['arr'];
|
let _2 = scope['arr'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -643,8 +639,7 @@ exports[`other directives with t-component t-on expression in t-foreach 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['state'].values;
|
let _2 = scope['state'].values;
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -696,8 +691,7 @@ exports[`other directives with t-component t-on expression in t-foreach with t-s
|
|||||||
scope.bossa = 'nova';
|
scope.bossa = 'nova';
|
||||||
let _2 = scope['state'].values;
|
let _2 = scope['state'].values;
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -750,8 +744,7 @@ exports[`other directives with t-component t-on method call in t-foreach 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['state'].values;
|
let _2 = scope['state'].values;
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -1417,8 +1410,7 @@ exports[`other directives with t-component t-set outside modified in t-foreach 1
|
|||||||
scope.iter = 0;
|
scope.iter = 0;
|
||||||
let _2 = scope['state'].values;
|
let _2 = scope['state'].values;
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -1568,8 +1560,7 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['items'];
|
let _2 = scope['items'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -1847,8 +1838,7 @@ exports[`t-model directive in a t-foreach 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['state'];
|
let _2 = scope['state'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -1888,8 +1878,7 @@ exports[`t-model directive in a t-foreach, part 2 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['state'];
|
let _2 = scope['state'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
|
|||||||
@@ -414,8 +414,7 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = `
|
|||||||
c1.push(vn2);
|
c1.push(vn2);
|
||||||
let _3 = scope['state'].users;
|
let _3 = scope['state'].users;
|
||||||
if (!_3) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_3) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _4 = _3;
|
let _4 = _5 = _3;
|
||||||
let _5 = _3;
|
|
||||||
if (!(_3 instanceof Array)) {
|
if (!(_3 instanceof Array)) {
|
||||||
_4 = Object.keys(_3);
|
_4 = Object.keys(_3);
|
||||||
_5 = Object.values(_3);
|
_5 = Object.values(_3);
|
||||||
@@ -513,8 +512,7 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = `
|
|||||||
c1.push(vn2);
|
c1.push(vn2);
|
||||||
let _3 = scope['state'].users;
|
let _3 = scope['state'].users;
|
||||||
if (!_3) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_3) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _4 = _3;
|
let _4 = _5 = _3;
|
||||||
let _5 = _3;
|
|
||||||
if (!(_3 instanceof Array)) {
|
if (!(_3 instanceof Array)) {
|
||||||
_4 = Object.keys(_3);
|
_4 = Object.keys(_3);
|
||||||
_5 = Object.values(_3);
|
_5 = Object.values(_3);
|
||||||
@@ -647,8 +645,7 @@ exports[`t-slot directive slots in t-foreach in t-foreach 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['tree'];
|
let _2 = scope['tree'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -675,8 +672,7 @@ exports[`t-slot directive slots in t-foreach in t-foreach 1`] = `
|
|||||||
c1.push(vn8);
|
c1.push(vn8);
|
||||||
let _9 = scope['node1'].nodes;
|
let _9 = scope['node1'].nodes;
|
||||||
if (!_9) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_9) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _10 = _9;
|
let _10 = _11 = _9;
|
||||||
let _11 = _9;
|
|
||||||
if (!(_9 instanceof Array)) {
|
if (!(_9 instanceof Array)) {
|
||||||
_10 = Object.keys(_9);
|
_10 = Object.keys(_9);
|
||||||
_11 = Object.values(_9);
|
_11 = Object.values(_9);
|
||||||
|
|||||||
@@ -1388,62 +1388,6 @@ describe("async rendering", () => {
|
|||||||
expect(fixture.innerHTML).toBe("<span>4</span>");
|
expect(fixture.innerHTML).toBe("<span>4</span>");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("calling render in destroy", async () => {
|
|
||||||
let a: any = null;
|
|
||||||
let c: any = null;
|
|
||||||
|
|
||||||
class C extends Component {
|
|
||||||
static template = xml`
|
|
||||||
<div>
|
|
||||||
<t t-esc="props.fromA"/>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
let flag = false;
|
|
||||||
class B extends Component {
|
|
||||||
static template = xml`<C fromA="props.fromA"/>`;
|
|
||||||
static components = { C };
|
|
||||||
|
|
||||||
setup() {
|
|
||||||
c = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
if (flag) {
|
|
||||||
this.render();
|
|
||||||
} else {
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
willUnmount() {
|
|
||||||
c.render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class A extends Component {
|
|
||||||
static template = xml`<B t-key="key" fromA="state"/>`;
|
|
||||||
static components = { B };
|
|
||||||
state = "a";
|
|
||||||
key = 1;
|
|
||||||
|
|
||||||
setup() {
|
|
||||||
a = this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const parent = new A();
|
|
||||||
await parent.mount(fixture);
|
|
||||||
expect(fixture.innerHTML).toBe("<div>a</div>");
|
|
||||||
|
|
||||||
a.state = "A";
|
|
||||||
a.key = 2;
|
|
||||||
await a.render();
|
|
||||||
// this nextTick is critical, otherwise jest may silently swallow errors
|
|
||||||
await nextTick();
|
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe("<div>A</div>");
|
|
||||||
});
|
|
||||||
|
|
||||||
test("change state and call manually render: no unnecessary rendering", async () => {
|
test("change state and call manually render: no unnecessary rendering", async () => {
|
||||||
class Widget extends Component {
|
class Widget extends Component {
|
||||||
static template = xml`<div><t t-esc="state.val"/></div>`;
|
static template = xml`<div><t t-esc="state.val"/></div>`;
|
||||||
|
|||||||
+4
-3
@@ -41,9 +41,10 @@ export async function nextTick(): Promise<void> {
|
|||||||
await new Promise((resolve) => scheduler.requestAnimationFrame(resolve));
|
await new Promise((resolve) => scheduler.requestAnimationFrame(resolve));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function nextFrame(): Promise<void> {
|
export async function nextFrame(numberOfAnimationFrames: number = 2): Promise<void> {
|
||||||
await new Promise((resolve) => scheduler.requestAnimationFrame(resolve));
|
for (let i = 0; i < numberOfAnimationFrames; i++) {
|
||||||
await new Promise((resolve) => scheduler.requestAnimationFrame(resolve));
|
await new Promise((resolve) => scheduler.requestAnimationFrame(resolve));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeTestFixture() {
|
export function makeTestFixture() {
|
||||||
|
|||||||
@@ -429,8 +429,7 @@ exports[`foreach does not pollute the rendering context 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = [1];
|
let _2 = [1];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -465,8 +464,7 @@ exports[`foreach iterate on items (on a element node) 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = [1,2];
|
let _2 = [1,2];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -504,8 +502,7 @@ exports[`foreach iterate on items 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = [3,2,1];
|
let _2 = [3,2,1];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -552,8 +549,7 @@ exports[`foreach iterate, dict param 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['value'];
|
let _2 = scope['value'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -600,8 +596,7 @@ exports[`foreach iterate, position 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = Array(5);
|
let _2 = Array(5);
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -646,8 +641,7 @@ exports[`foreach t-call with body in t-foreach in t-foreach 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['numbers'];
|
let _2 = scope['numbers'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -664,8 +658,7 @@ exports[`foreach t-call with body in t-foreach in t-foreach 1`] = `
|
|||||||
let key1 = i1;
|
let key1 = i1;
|
||||||
let _6 = scope['letters'];
|
let _6 = scope['letters'];
|
||||||
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _7 = _6;
|
let _7 = _8 = _6;
|
||||||
let _8 = _6;
|
|
||||||
if (!(_6 instanceof Array)) {
|
if (!(_6 instanceof Array)) {
|
||||||
_7 = Object.keys(_6);
|
_7 = Object.keys(_6);
|
||||||
_8 = Object.values(_6);
|
_8 = Object.values(_6);
|
||||||
@@ -736,8 +729,7 @@ exports[`foreach t-call without body in t-foreach in t-foreach 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['numbers'];
|
let _2 = scope['numbers'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -754,8 +746,7 @@ exports[`foreach t-call without body in t-foreach in t-foreach 1`] = `
|
|||||||
let key1 = i1;
|
let key1 = i1;
|
||||||
let _6 = scope['letters'];
|
let _6 = scope['letters'];
|
||||||
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _7 = _6;
|
let _7 = _8 = _6;
|
||||||
let _8 = _6;
|
|
||||||
if (!(_6 instanceof Array)) {
|
if (!(_6 instanceof Array)) {
|
||||||
_7 = Object.keys(_6);
|
_7 = Object.keys(_6);
|
||||||
_8 = Object.values(_6);
|
_8 = Object.values(_6);
|
||||||
@@ -820,8 +811,7 @@ exports[`foreach t-foreach in t-forach 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['numbers'];
|
let _2 = scope['numbers'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -838,8 +828,7 @@ exports[`foreach t-foreach in t-forach 1`] = `
|
|||||||
let key1 = i1;
|
let key1 = i1;
|
||||||
let _6 = scope['letters'];
|
let _6 = scope['letters'];
|
||||||
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _7 = _6;
|
let _7 = _8 = _6;
|
||||||
let _8 = _6;
|
|
||||||
if (!(_6 instanceof Array)) {
|
if (!(_6 instanceof Array)) {
|
||||||
_7 = Object.keys(_6);
|
_7 = Object.keys(_6);
|
||||||
_8 = Object.values(_6);
|
_8 = Object.values(_6);
|
||||||
@@ -882,8 +871,7 @@ exports[`foreach warn if no key in some case 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = [1,2];
|
let _2 = [1,2];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -952,8 +940,7 @@ exports[`misc global 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = [4,5,6];
|
let _2 = [4,5,6];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -1679,8 +1666,7 @@ exports[`t-call (template calling recursive template, part 2 2`] = `
|
|||||||
}
|
}
|
||||||
let _6 = scope['node'].children||[];
|
let _6 = scope['node'].children||[];
|
||||||
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _7 = _6;
|
let _7 = _8 = _6;
|
||||||
let _8 = _6;
|
|
||||||
if (!(_6 instanceof Array)) {
|
if (!(_6 instanceof Array)) {
|
||||||
_7 = Object.keys(_6);
|
_7 = Object.keys(_6);
|
||||||
_8 = Object.values(_6);
|
_8 = Object.values(_6);
|
||||||
@@ -1760,8 +1746,7 @@ exports[`t-call (template calling recursive template, part 3 2`] = `
|
|||||||
}
|
}
|
||||||
let _6 = scope['node'].children||[];
|
let _6 = scope['node'].children||[];
|
||||||
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _7 = _6;
|
let _7 = _8 = _6;
|
||||||
let _8 = _6;
|
|
||||||
if (!(_6 instanceof Array)) {
|
if (!(_6 instanceof Array)) {
|
||||||
_7 = Object.keys(_6);
|
_7 = Object.keys(_6);
|
||||||
_8 = Object.values(_6);
|
_8 = Object.values(_6);
|
||||||
@@ -1847,8 +1832,7 @@ exports[`t-call (template calling recursive template, part 4: with t-set recursi
|
|||||||
}
|
}
|
||||||
let _6 = scope['node'].children||[];
|
let _6 = scope['node'].children||[];
|
||||||
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_6) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _7 = _6;
|
let _7 = _8 = _6;
|
||||||
let _8 = _6;
|
|
||||||
if (!(_6 instanceof Array)) {
|
if (!(_6 instanceof Array)) {
|
||||||
_7 = Object.keys(_6);
|
_7 = Object.keys(_6);
|
||||||
_8 = Object.values(_6);
|
_8 = Object.values(_6);
|
||||||
@@ -2014,8 +1998,7 @@ exports[`t-call (template calling t-call with t-set inside and outside 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['list'];
|
let _2 = scope['list'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -2792,8 +2775,7 @@ exports[`t-key t-key directive in a list 1`] = `
|
|||||||
let vn1 = h('ul', p1, c1);
|
let vn1 = h('ul', p1, c1);
|
||||||
let _2 = scope['beers'];
|
let _2 = scope['beers'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -2897,8 +2879,7 @@ exports[`t-on can bind handlers with loop variable as argument 1`] = `
|
|||||||
let vn1 = h('ul', p1, c1);
|
let vn1 = h('ul', p1, c1);
|
||||||
let _2 = ['someval'];
|
let _2 = ['someval'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -3180,8 +3161,7 @@ exports[`t-on t-on with prevent modifier in t-foreach 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['projects'];
|
let _2 = scope['projects'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -3452,8 +3432,7 @@ exports[`t-ref refs in a loop 1`] = `
|
|||||||
let vn1 = h('div', p1, c1);
|
let vn1 = h('div', p1, c1);
|
||||||
let _2 = scope['items'];
|
let _2 = scope['items'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
@@ -3697,8 +3676,7 @@ exports[`t-set t-set should reuse variable if possible 1`] = `
|
|||||||
scope.v = 1;
|
scope.v = 1;
|
||||||
let _2 = scope['list'];
|
let _2 = scope['list'];
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||||
let _3 = _2;
|
let _3 = _4 = _2;
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
if (!(_2 instanceof Array)) {
|
||||||
_3 = Object.keys(_2);
|
_3 = Object.keys(_2);
|
||||||
_4 = Object.values(_2);
|
_4 = Object.values(_2);
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`memory t-foreach does not leak stuff in global scope 1`] = `
|
|
||||||
"function anonymous(context, extra
|
|
||||||
) {
|
|
||||||
// Template name: \\"test\\"
|
|
||||||
let scope = Object.create(context);
|
|
||||||
let h = this.h;
|
|
||||||
let c1 = [], p1 = {key:1};
|
|
||||||
let vn1 = h('p', p1, c1);
|
|
||||||
let _2 = [3,2,1];
|
|
||||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
|
||||||
let _3 = _2;
|
|
||||||
let _4 = _2;
|
|
||||||
if (!(_2 instanceof Array)) {
|
|
||||||
_3 = Object.keys(_2);
|
|
||||||
_4 = Object.values(_2);
|
|
||||||
}
|
|
||||||
let _length3 = _3.length;
|
|
||||||
let _origScope5 = scope;
|
|
||||||
scope = Object.create(scope);
|
|
||||||
for (let i1 = 0; i1 < _length3; i1++) {
|
|
||||||
scope.item_first = i1 === 0
|
|
||||||
scope.item_last = i1 === _length3 - 1
|
|
||||||
scope.item_index = i1
|
|
||||||
scope.item = _3[i1]
|
|
||||||
scope.item_value = _4[i1]
|
|
||||||
let key1 = i1;
|
|
||||||
let _6 = scope['item'];
|
|
||||||
if (_6 != null) {
|
|
||||||
c1.push({text: _6});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scope = _origScope5;
|
|
||||||
return vn1;
|
|
||||||
}"
|
|
||||||
`;
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import { QWeb } from "../../src/qweb/index";
|
|
||||||
import { renderToString } from "../helpers";
|
|
||||||
|
|
||||||
describe("memory", () => {
|
|
||||||
test("t-foreach does not leak stuff in global scope", () => {
|
|
||||||
let qweb = new QWeb();
|
|
||||||
const initialNumberOfGlobals = Object.keys(window).length;
|
|
||||||
qweb.addTemplate("test", `<p><t t-foreach="[3, 2, 1]" t-as="item"><t t-esc="item"/></t></p>`);
|
|
||||||
const result = renderToString(qweb, "test");
|
|
||||||
const expected = `<p>321</p>`;
|
|
||||||
expect(result).toBe(expected);
|
|
||||||
expect(Object.keys(window).length).toBe(initialNumberOfGlobals);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
+2
-2
@@ -13,8 +13,8 @@
|
|||||||
// "compileOnSave": false, // Signals to the IDE to generate all files for a given tsconfig.json upon saving.
|
// "compileOnSave": false, // Signals to the IDE to generate all files for a given tsconfig.json upon saving.
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
// Main options
|
// Main options
|
||||||
"target": "es2017", // Specify ECMAScript target version: 'es3' (default), 'es5', 'es2015', 'es2016', 'es2017','es2018' or 'esnext'.
|
"target": "esnext", // Specify ECMAScript target version: 'es3' (default), 'es5', 'es2015', 'es2016', 'es2017','es2018' or 'esnext'.
|
||||||
"module": "es6", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
|
"module": "esnext", // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
|
||||||
// "lib": ["esnext", "dom"], // Specify library files to be included in the compilation.
|
// "lib": ["esnext", "dom"], // Specify library files to be included in the compilation.
|
||||||
// "allowJs": false, // Allow javascript files to be compiled.
|
// "allowJs": false, // Allow javascript files to be compiled.
|
||||||
// "checkJs": false, // Report errors in .js files.
|
// "checkJs": false, // Report errors in .js files.
|
||||||
|
|||||||
Reference in New Issue
Block a user