[REF] *: reformat with prettier and printWidth=100

closes #214
This commit is contained in:
Géry Debongnie
2019-06-28 10:32:03 +02:00
parent 0095bfa61f
commit af7520d869
28 changed files with 268 additions and 948 deletions
+3
View File
@@ -60,5 +60,8 @@
"json",
"node"
]
},
"prettier": {
"printWidth": 100
}
}
+8 -33
View File
@@ -437,10 +437,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
__owl__.renderPromise = null;
const target = __owl__.vnode || document.createElement(vnode.sel!);
if (this.__owl__.classObj) {
(<any>vnode).data.class = Object.assign(
(<any>vnode).data.class || {},
this.__owl__.classObj
);
(<any>vnode).data.class = Object.assign((<any>vnode).data.class || {}, this.__owl__.classObj);
}
__owl__.vnode = patch(target, vnode);
}
@@ -471,17 +468,11 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
if (template) {
this.template = template;
} else {
while (
(template = p.name) &&
!(template in qweb.templates) &&
p !== Component
) {
while ((template = p.name) && !(template in qweb.templates) && p !== Component) {
p = p.__proto__;
}
if (p === Component) {
throw new Error(
`Could not find template for component "${this.constructor.name}"`
);
throw new Error(`Could not find template for component "${this.constructor.name}"`);
} else {
tmap[name] = template;
this.template = template;
@@ -493,10 +484,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
return this.__render();
}
async __render(
force: boolean = false,
patchQueue: any[] = []
): Promise<VNode> {
async __render(force: boolean = false, patchQueue: any[] = []): Promise<VNode> {
const __owl__ = this.__owl__;
__owl__.renderId++;
const promises: Promise<void>[] = [];
@@ -536,10 +524,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
__mount(vnode: VNode, elm: HTMLElement): VNode {
const __owl__ = this.__owl__;
if (__owl__.classObj) {
(<any>vnode).data.class = Object.assign(
(<any>vnode).data.class || {},
__owl__.classObj
);
(<any>vnode).data.class = Object.assign((<any>vnode).data.class || {}, __owl__.classObj);
}
__owl__.vnode = patch(elm, vnode);
if (__owl__.parent!.__owl__.isMounted && !__owl__.isMounted) {
@@ -619,11 +604,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
// list of strings (prop names)
for (let i = 0, l = propsDef.length; i < l; i++) {
if (!(propsDef[i] in props)) {
throw new Error(
`Missing props '${propsDef[i]}' (component '${
this.constructor.name
}')`
);
throw new Error(`Missing props '${propsDef[i]}' (component '${this.constructor.name}')`);
}
}
} else if (propsDef) {
@@ -631,11 +612,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
for (let propName in propsDef) {
if (!(propName in props)) {
if (propsDef[propName] && !propsDef[propName].optional) {
throw new Error(
`Missing props '${propName}' (component '${
this.constructor.name
}')`
);
throw new Error(`Missing props '${propName}' (component '${this.constructor.name}')`);
} else {
break;
}
@@ -643,9 +620,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
let isValid = isValidProp(props[propName], propsDef[propName]);
if (!isValid) {
throw new Error(
`Props '${propName}' of invalid type in component '${
this.constructor.name
}'`
`Props '${propName}' of invalid type in component '${this.constructor.name}'`
);
}
}
+1 -1
View File
@@ -32,7 +32,7 @@ Object.defineProperty(__info__, "mode", {
`Owl is running in 'dev' mode. This is not suitable for production use. See ${url} for more information.`
);
} else {
console.log(`Owl is now running in 'prod' mode.`)
console.log(`Owl is now running in 'prod' mode.`);
}
}
});
+5 -22
View File
@@ -21,15 +21,7 @@
// we define here a new modified Array prototype, which basically override all
// Array methods that change some state to be able to track their changes
const methodsToPatch = [
"push",
"pop",
"shift",
"unshift",
"splice",
"sort",
"reverse"
];
const methodsToPatch = ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"];
const methodLen = methodsToPatch.length;
const ArrayProto = Array.prototype;
@@ -78,18 +70,14 @@ export class Observer {
static set(target: any, key: number | string, value: any) {
if (!target.__owl__) {
throw Error(
"`Observer.set()` can only be called with observed Objects or Arrays"
);
throw Error("`Observer.set()` can only be called with observed Objects or Arrays");
}
target.__owl__.observer.set(target, key, value);
}
static delete(target: any, key: number | string) {
if (!target.__owl__) {
throw Error(
"`Observer.delete()` can only be called with observed Objects"
);
throw Error("`Observer.delete()` can only be called with observed Objects");
}
target.__owl__.observer.delete(target, key);
}
@@ -127,8 +115,7 @@ export class Observer {
set(target: any, key: number | string, value: any) {
let alreadyDefined =
key in target &&
Object.getOwnPropertyDescriptor(target, key)!.configurable === false;
key in target && Object.getOwnPropertyDescriptor(target, key)!.configurable === false;
if (alreadyDefined) {
target[key] = value;
} else {
@@ -172,11 +159,7 @@ export class Observer {
}
}
_addProp<T extends { __owl__?: any }>(
obj: T,
key: string | number,
value: any
) {
_addProp<T extends { __owl__?: any }>(obj: T, key: string | number, value: any) {
var self = this;
Object.defineProperty(obj, key, {
configurable: true,
+11 -45
View File
@@ -59,14 +59,7 @@ export interface Directive {
// Const/global stuff/helpers
//------------------------------------------------------------------------------
const DISABLED_TAGS = [
"input",
"textarea",
"button",
"select",
"option",
"optgroup"
];
const DISABLED_TAGS = ["input", "textarea", "button", "select", "option", "optgroup"];
const lineBreakRE = /[\r\n]/;
const whitespaceRE = /\s+/g;
@@ -245,9 +238,7 @@ export class QWeb extends EventBus {
return a + b;
}) > 1
) {
throw new Error(
"Only one conditional branching directive is allowed per node"
);
throw new Error("Only one conditional branching directive is allowed per node");
}
// All text nodes between branch nodes are removed
let textNode;
@@ -311,28 +302,20 @@ export class QWeb extends EventBus {
}
let template;
try {
template = new Function(
"context",
"extra",
ctx.code.join("\n")
) as CompiledTemplate;
template = new Function("context", "extra", ctx.code.join("\n")) as CompiledTemplate;
} catch (e) {
const templateName = ctx.templateName.replace(/`/g, "'");
console.groupCollapsed(`Invalid Code generated by ${templateName}`);
console.warn(ctx.code.join("\n"));
console.groupEnd();
throw new Error(
`Invalid generated code while compiling template '${templateName}': ${
e.message
}`
`Invalid generated code while compiling template '${templateName}': ${e.message}`
);
}
if (isDebug) {
const tpl = this.templates[name];
if (tpl) {
const msg = `Template: ${
tpl.elem.outerHTML
}\nCompiled code:\n${template.toString()}`;
const msg = `Template: ${tpl.elem.outerHTML}\nCompiled code:\n${template.toString()}`;
console.log(msg);
}
}
@@ -481,11 +464,7 @@ export class QWeb extends EventBus {
}
}
_compileGenericNode(
node: ChildNode,
ctx: Context,
withHandlers: boolean = true
): number {
_compileGenericNode(node: ChildNode, ctx: Context, withHandlers: boolean = true): number {
// nodeType 1 is generic tag
if (node.nodeType !== 1) {
throw new Error("unsupported node type");
@@ -509,10 +488,7 @@ export class QWeb extends EventBus {
if (key === "disabled" && DISABLED_TAGS.indexOf(node.nodeName) > -1) {
isProp = true;
}
if (
(key === "readonly" && node.nodeName === "input") ||
node.nodeName === "textarea"
) {
if ((key === "readonly" && node.nodeName === "input") || node.nodeName === "textarea") {
isProp = true;
}
if (isProp) {
@@ -526,10 +502,7 @@ export class QWeb extends EventBus {
const value = attributes[i].textContent!;
// regular attributes
if (
!name.startsWith("t-") &&
!(<Element>node).getAttribute("t-attf-" + name)
) {
if (!name.startsWith("t-") && !(<Element>node).getAttribute("t-attf-" + name)) {
const attID = ctx.generateID();
if (name === "class") {
let classDef = value
@@ -577,9 +550,7 @@ export class QWeb extends EventBus {
const attValueID = ctx.generateID();
ctx.addLine(`var _${attValueID} = ${formattedValue};`);
formattedValue = `'${attValue}' + (_${attValueID} ? ' ' + _${attValueID} : '')`;
const attrIndex = attrs.findIndex(att =>
att.startsWith(attName + ":")
);
const attrIndex = attrs.findIndex(att => att.startsWith(attName + ":"));
attrs.splice(attrIndex, 1);
}
ctx.addLine(`var _${attID} = ${formattedValue};`);
@@ -645,9 +616,7 @@ export class QWeb extends EventBus {
ctx.addLine(`}`);
ctx.closeIf();
}
ctx.addLine(
`var vn${nodeID} = h('${node.nodeName}', p${nodeID}, c${nodeID});`
);
ctx.addLine(`var vn${nodeID} = h('${node.nodeName}', p${nodeID}, c${nodeID});`);
if (ctx.parentNode) {
ctx.addLine(`c${ctx.parentNode}.push(vn${nodeID});`);
}
@@ -776,10 +745,7 @@ export class Context {
return `(${this.formatExpression(s.slice(2, -2))})`;
}
let r = s.replace(
/\{\{.*?\}\}/g,
s => "${" + this.formatExpression(s.slice(2, -2)) + "}"
);
let r = s.replace(/\{\{.*?\}\}/g, s => "${" + this.formatExpression(s.slice(2, -2)) + "}");
return "`" + r + "`";
}
}
+5 -14
View File
@@ -60,9 +60,7 @@ function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: Context) {
ctx.addLine(`var frag${fragID} = this.utils.getFragment(${exprID})`);
let tempNodeID = ctx.generateID();
ctx.addLine(`var p${tempNodeID} = {hook: {`);
ctx.addLine(
` insert: n => n.elm.parentNode.replaceChild(frag${fragID}, n.elm),`
);
ctx.addLine(` insert: n => n.elm.parentNode.replaceChild(frag${fragID}, n.elm),`);
ctx.addLine(`}};`);
ctx.addLine(`var vn${tempNodeID} = h('div', p${tempNodeID})`);
ctx.addLine(`c${ctx.parentNode}.push(vn${tempNodeID});`);
@@ -116,9 +114,7 @@ QWeb.addDirective({
if (value) {
const formattedValue = ctx.formatExpression(value);
if (ctx.variables.hasOwnProperty(variable)) {
ctx.addLine(
`${(<QWebExprVar>ctx.variables[variable]).id} = ${formattedValue}`
);
ctx.addLine(`${(<QWebExprVar>ctx.variables[variable]).id} = ${formattedValue}`);
} else {
const varName = `_${ctx.generateID()}`;
ctx.addLine(`var ${varName} = ${formattedValue};`);
@@ -220,9 +216,7 @@ QWeb.addDirective({
}
// compile sub template
const subCtx = ctx
.subContext("caller", nodeCopy)
.subContext("variables", Object.create(vars));
const subCtx = ctx.subContext("caller", nodeCopy).subContext("variables", Object.create(vars));
qweb._compileNode(nodeTemplate.elem, subCtx);
@@ -250,9 +244,7 @@ QWeb.addDirective({
const name = node.getAttribute("t-as")!;
let arrayID = ctx.generateID();
ctx.addLine(`var _${arrayID} = ${ctx.formatExpression(elems)};`);
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 valuesID = ctx.generateID();
ctx.addLine(`var _${keysID} = _${valuesID} = _${arrayID};`);
@@ -269,8 +261,7 @@ QWeb.addDirective({
ctx.addLine(`context.${name} = _${keysID}[i];`);
ctx.addLine(`context.${name}_value = _${valuesID}[i];`);
const nodeCopy = <Element>node.cloneNode(true);
let shouldWarn =
nodeCopy.tagName !== "t" && !nodeCopy.hasAttribute("t-key");
let shouldWarn = nodeCopy.tagName !== "t" && !nodeCopy.hasAttribute("t-key");
if (!shouldWarn && node.tagName === "t") {
if (node.hasAttribute("t-component") && !node.hasAttribute("t-key")) {
shouldWarn = true;
+3 -9
View File
@@ -82,7 +82,7 @@ const STATIC_TOKEN_MAP: { [key: string]: TKind } = {
")": "RIGHT_PAREN"
};
const OPERATORS = ".,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%".split(',');
const OPERATORS = ".,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%".split(",");
type Tokenizer = (expr: string) => Token | false;
@@ -231,10 +231,7 @@ export function tokenize(expr: string): Token[] {
* - or if the previous token is a left brace or a comma, and the next token is
* a colon (in that case, this is an object key: `{a: b}`)
*/
export function compileExpr(
expr: string,
vars: { [key: string]: QWebVar }
): string {
export function compileExpr(expr: string, vars: { [key: string]: QWebVar }): string {
const tokens = tokenize(expr);
let result = "";
for (let i = 0; i < tokens.length; i++) {
@@ -246,10 +243,7 @@ export function compileExpr(
if (prevToken) {
if (prevToken.type === "OPERATOR" && prevToken.value === ".") {
isVar = false;
} else if (
prevToken.type === "LEFT_BRACE" ||
prevToken.type === "COMMA"
) {
} else if (prevToken.type === "LEFT_BRACE" || prevToken.type === "COMMA") {
let nextToken = tokens[i + 1];
if (nextToken && nextToken.type === "COLON") {
isVar = false;
+19 -64
View File
@@ -49,9 +49,7 @@ QWeb.addDirective({
)}'\`)`
);
ctx.closeIf();
let params = extraArgs
? `owner, ${ctx.formatExpression(extraArgs)}`
: "owner";
let params = extraArgs ? `owner, ${ctx.formatExpression(extraArgs)}` : "owner";
let handler;
if (mods.length > 0) {
handler = `function (e) {`;
@@ -70,9 +68,7 @@ QWeb.addDirective({
ctx.addLine(
`extra.handlers['${eventName}' + ${nodeID}] = extra.handlers['${eventName}' + ${nodeID}] || ${handler};`
);
ctx.addLine(
`p${nodeID}.on['${eventName}'] = extra.handlers['${eventName}' + ${nodeID}];`
);
ctx.addLine(`p${nodeID}.on['${eventName}'] = extra.handlers['${eventName}' + ${nodeID}];`);
}
}
});
@@ -101,9 +97,7 @@ UTILS.transitionInsert = function(vn: VNode, name: string) {
const elm = <HTMLElement>vn.elm;
// remove potential duplicated vnode that is currently being removed, to
// prevent from having twice the same node in the DOM during an animation
const dup =
elm.parentElement &&
elm.parentElement!.querySelector(`*[data-owl-key='${vn.key}']`);
const dup = elm.parentElement && elm.parentElement!.querySelector(`*[data-owl-key='${vn.key}']`);
if (dup) {
dup.remove();
}
@@ -164,9 +158,7 @@ function toMs(s: string): number {
function whenTransitionEnd(elm: HTMLElement, cb) {
const styles = window.getComputedStyle(elm);
const delays: Array<string> = (styles.transitionDelay || "").split(", ");
const durations: Array<string> = (styles.transitionDuration || "").split(
", "
);
const durations: Array<string> = (styles.transitionDuration || "").split(", ");
const timeout: number = getTimeout(delays, durations);
if (timeout > 0) {
elm.addEventListener("transitionend", cb, { once: true });
@@ -425,9 +417,7 @@ QWeb.addDirective({
// necessary to prevent collisions
if (!key && ctx.inLoop) {
let id = ctx.generateID();
ctx.addLine(
`let template${id} = "_slot_" + String(-${componentID} - i)`
);
ctx.addLine(`let template${id} = "_slot_" + String(-${componentID} - i)`);
templateID = `template${id}`;
} else {
templateID = `"_slot_${templateID}"`;
@@ -446,9 +436,7 @@ QWeb.addDirective({
if (transition) {
transitionsInsertCode = `utils.transitionInsert(vn, '${transition}');`;
}
let finalizeComponentCode = `w${componentID}.${
keepAlive ? "unmount" : "destroy"
}();`;
let finalizeComponentCode = `w${componentID}.${keepAlive ? "unmount" : "destroy"}();`;
if (ref && !keepAlive) {
finalizeComponentCode += `delete context.refs[${refKey}];`;
}
@@ -501,9 +489,7 @@ QWeb.addDirective({
// we need to evaluate the arguments now, because the handler will
// be set asynchronously later when the widget is ready, and the
// context might be different.
ctx.addLine(
`let arg${argId} = ${ctx.formatExpression(extraArgs)};`
);
ctx.addLine(`let arg${argId} = ${ctx.formatExpression(extraArgs)};`);
params = `owner, arg${argId}`;
} else {
params = `owner, ${ctx.formatExpression(extraArgs)}`;
@@ -536,9 +522,7 @@ QWeb.addDirective({
if (async) {
ctx.addLine(`const patchQueue${componentID} = [];`);
ctx.addLine(
`c${
ctx.parentNode
}.push(w${componentID} && w${componentID}.__owl__.pvnode || null);`
`c${ctx.parentNode}.push(w${componentID} && w${componentID}.__owl__.pvnode || null);`
);
} else {
ctx.addLine(`c${ctx.parentNode}.push(null);`);
@@ -547,9 +531,7 @@ QWeb.addDirective({
ctx.addIf(
`w${componentID} && w${componentID}.__owl__.renderPromise && !w${componentID}.__owl__.vnode`
);
ctx.addIf(
`utils.shallowEqual(props${componentID}, w${componentID}.__owl__.renderProps)`
);
ctx.addIf(`utils.shallowEqual(props${componentID}, w${componentID}.__owl__.renderProps)`);
ctx.addLine(`def${defID} = w${componentID}.__owl__.renderPromise;`);
ctx.addElse();
ctx.addLine(`w${componentID}.destroy();`);
@@ -568,12 +550,8 @@ QWeb.addDirective({
ctx.addLine(
`if (!W${componentID}) {throw new Error('Cannot find the definition of component "' + componentKey${componentID} + '"')}`
);
ctx.addLine(
`w${componentID} = new W${componentID}(owner, props${componentID});`
);
ctx.addLine(
`context.__owl__.cmap[${templateID}] = w${componentID}.__owl__.id;`
);
ctx.addLine(`w${componentID} = new W${componentID}(owner, props${componentID});`);
ctx.addLine(`context.__owl__.cmap[${templateID}] = w${componentID}.__owl__.id;`);
// SLOTS
if (node.childNodes.length) {
@@ -587,11 +565,7 @@ QWeb.addDirective({
slotNode.parentElement!.removeChild(slotNode);
const key = slotNode.getAttribute("t-set")!;
slotNode.removeAttribute("t-set");
const slotFn = qweb._compile(
`slot_${key}_template`,
slotNode,
ctx.parentNode!
);
const slotFn = qweb._compile(`slot_${key}_template`, slotNode, ctx.parentNode!);
qweb.slots[`${slotId}_${key}`] = slotFn.bind(qweb);
}
}
@@ -600,11 +574,7 @@ QWeb.addDirective({
for (let child of Object.values(clone.childNodes)) {
t.appendChild(child);
}
const slotFn = qweb._compile(
`slot_default_template`,
t,
ctx.parentNode!
);
const slotFn = qweb._compile(`slot_default_template`, t, ctx.parentNode!);
qweb.slots[`${slotId}_default`] = slotFn.bind(qweb);
}
}
@@ -619,9 +589,7 @@ QWeb.addDirective({
ctx.addElse();
// need to update component
const patchQueueCode = async
? `patchQueue${componentID}`
: "extra.patchQueue";
const patchQueueCode = async ? `patchQueue${componentID}` : "extra.patchQueue";
ctx.addLine(
`def${defID} = def${defID} || w${componentID}.__updateProps(props${componentID}, extra.forceUpdate, ${patchQueueCode});`
);
@@ -650,11 +618,7 @@ QWeb.addDirective({
ctx.addLine(`extra.promises.push(def${defID});`);
}
if (
node.hasAttribute("t-if") ||
node.hasAttribute("t-else") ||
node.hasAttribute("t-elif")
) {
if (node.hasAttribute("t-if") || node.hasAttribute("t-else") || node.hasAttribute("t-elif")) {
ctx.closeIf();
}
@@ -694,10 +658,7 @@ QWeb.addDirective({
`extra.mountedHandlers[${nodeID}] = extra.mountedHandlers[${nodeID}] || (context['${handler}'] || ${error}).bind(owner);`
);
}
addNodeHook(
"insert",
`if (context.__owl__.isMounted) { extra.mountedHandlers[${nodeID}](); }`
);
addNodeHook("insert", `if (context.__owl__.isMounted) { extra.mountedHandlers[${nodeID}](); }`);
}
});
@@ -709,9 +670,7 @@ QWeb.addDirective({
priority: 80,
atNodeEncounter({ ctx, value }): boolean {
const slotKey = ctx.generateID();
ctx.addLine(
`const slot${slotKey} = this.slots[context.__owl__.slotId + '_' + '${value}'];`
);
ctx.addLine(`const slot${slotKey} = this.slots[context.__owl__.slotId + '_' + '${value}'];`);
ctx.addIf(`slot${slotKey}`);
ctx.addLine(
`slot${slotKey}(context.__owl__.parent, Object.assign({}, extra, {parentNode: c${
@@ -747,9 +706,7 @@ QWeb.addDirective({
handler = `(ev) => {context.state['${value}'] = ev.target.checked}`;
} else if (type === "radio") {
const nodeValue = node.getAttribute("value")!;
ctx.addLine(
`p${nodeID}.props = {checked:context.state['${value}'] === '${nodeValue}'};`
);
ctx.addLine(`p${nodeID}.props = {checked:context.state['${value}'] === '${nodeValue}'};`);
handler = `(ev) => {context.state['${value}'] = ev.target.value}`;
event = "click";
} else {
@@ -765,8 +722,6 @@ QWeb.addDirective({
ctx.addLine(
`extra.handlers['${event}' + ${nodeID}] = extra.handlers['${event}' + ${nodeID}] || (${handler});`
);
ctx.addLine(
`p${nodeID}.on['${event}'] = extra.handlers['${event}' + ${nodeID}];`
);
ctx.addLine(`p${nodeID}.on['${event}'] = extra.handlers['${event}' + ${nodeID}];`);
}
});
+1 -5
View File
@@ -308,11 +308,7 @@ export function connect<E extends EnvWithStore, P, S>(
);
}
__owl__.ownProps = nextProps;
const mergedProps = Object.assign(
{},
nextProps,
__owl__.currentStoreProps
);
const mergedProps = Object.assign({}, nextProps, __owl__.currentStoreProps);
return super.__updateProps(mergedProps, forceUpdate, patchQueue);
}
};
+2 -6
View File
@@ -17,7 +17,7 @@ export function whenReady(fn) {
} else {
document.addEventListener("DOMContentLoaded", resolve, false);
}
}).then(fn || function () {});
}).then(fn || function() {});
}
const loadedScripts: { [key: string]: Promise<void> } = {};
@@ -76,11 +76,7 @@ export function escape(str: string | number | undefined): string {
*
* Inspired by https://davidwalsh.name/javascript-debounce-function
*/
export function debounce(
func: Function,
wait: number,
immediate?: boolean
): Function {
export function debounce(func: Function, wait: number, immediate?: boolean): Function {
let timeout;
return function(this: any) {
const context = this;
+25 -118
View File
@@ -109,14 +109,7 @@ function createKeyToOldIdx(
return map;
}
const hooks: (keyof Module)[] = [
"create",
"update",
"remove",
"destroy",
"pre",
"post"
];
const hooks: (keyof Module)[] = ["create", "update", "remove", "destroy", "pre", "post"];
export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
let i: number,
@@ -138,13 +131,7 @@ export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
function emptyNodeAt(elm: Element) {
const id = elm.id ? "#" + elm.id : "";
const c = elm.className ? "." + elm.className.split(" ").join(".") : "";
return vnode(
api.tagName(elm).toLowerCase() + id + c,
{},
[],
undefined,
elm
);
return vnode(api.tagName(elm).toLowerCase() + id + c, {}, [], undefined, elm);
}
function createRmCb(childElm: Node, listeners: number) {
@@ -179,19 +166,14 @@ export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
const dotIdx = sel.indexOf(".", hashIdx);
const hash = hashIdx > 0 ? hashIdx : sel.length;
const dot = dotIdx > 0 ? dotIdx : sel.length;
const tag =
hashIdx !== -1 || dotIdx !== -1
? sel.slice(0, Math.min(hash, dot))
: sel;
const tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
const elm = (vnode.elm =
isDef(data) && isDef((i = (data as VNodeData).ns))
? api.createElementNS(i, tag)
: api.createElement(tag));
if (hash < dot) elm.setAttribute("id", sel.slice(hash + 1, dot));
if (dotIdx > 0)
elm.setAttribute("class", sel.slice(dot + 1).replace(/\./g, " "));
for (i = 0, iLen = cbs.create.length; i < iLen; ++i)
cbs.create[i](emptyNode, vnode);
if (dotIdx > 0) elm.setAttribute("class", sel.slice(dot + 1).replace(/\./g, " "));
for (i = 0, iLen = cbs.create.length; i < iLen; ++i) cbs.create[i](emptyNode, vnode);
if (array(children)) {
for (i = 0, iLen = children.length; i < iLen; ++i) {
const ch = children[i];
@@ -237,8 +219,7 @@ export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
data = vnode.data;
if (data !== undefined) {
if (isDef((i = data.hook)) && isDef((i = i.destroy))) i(vnode);
for (i = 0, iLen = cbs.destroy.length; i < iLen; ++i)
cbs.destroy[i](vnode);
for (i = 0, iLen = cbs.destroy.length; i < iLen; ++i) cbs.destroy[i](vnode);
if (vnode.children !== undefined) {
for (j = 0, jLen = vnode.children.length; j < jLen; ++j) {
i = vnode.children[j];
@@ -267,13 +248,8 @@ export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
invokeDestroyHook(ch);
listeners = cbs.remove.length + 1;
rm = createRmCb(ch.elm as Node, listeners);
for (i = 0, iLen = cbs.remove.length; i < iLen; ++i)
cbs.remove[i](ch, rm);
if (
isDef((i = ch.data)) &&
isDef((i = i.hook)) &&
isDef((i = i.remove))
) {
for (i = 0, iLen = cbs.remove.length; i < iLen; ++i) cbs.remove[i](ch, rm);
if (isDef((i = ch.data)) && isDef((i = i.hook)) && isDef((i = i.remove))) {
i(ch, rm);
} else {
rm();
@@ -335,11 +311,7 @@ export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
} else if (sameVnode(oldEndVnode, newStartVnode)) {
// Vnode moved left
patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);
api.insertBefore(
parentElm,
oldEndVnode.elm as Node,
oldStartVnode.elm as Node
);
api.insertBefore(parentElm, oldEndVnode.elm as Node, oldStartVnode.elm as Node);
oldEndVnode = oldCh[--oldEndIdx];
newStartVnode = newCh[++newStartIdx];
} else {
@@ -366,11 +338,7 @@ export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
} else {
patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);
oldCh[idxInOld] = undefined as any;
api.insertBefore(
parentElm,
elmToMove.elm as Node,
oldStartVnode.elm as Node
);
api.insertBefore(parentElm, elmToMove.elm as Node, oldStartVnode.elm as Node);
}
newStartVnode = newCh[++newStartIdx];
}
@@ -379,31 +347,16 @@ export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) {
if (oldStartIdx > oldEndIdx) {
before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm;
addVnodes(
parentElm,
before,
newCh,
newStartIdx,
newEndIdx,
insertedVnodeQueue
);
addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
} else {
removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
}
}
}
function patchVnode(
oldVnode: VNode,
vnode: VNode,
insertedVnodeQueue: VNodeQueue
) {
function patchVnode(oldVnode: VNode, vnode: VNode, insertedVnodeQueue: VNodeQueue) {
let i: any, iLen: number, hook: any;
if (
isDef((i = vnode.data)) &&
isDef((hook = i.hook)) &&
isDef((i = hook.prepatch))
) {
if (isDef((i = vnode.data)) && isDef((hook = i.hook)) && isDef((i = hook.prepatch))) {
i(oldVnode, vnode);
}
const elm = (vnode.elm = oldVnode.elm as Node);
@@ -411,20 +364,14 @@ export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
let ch = vnode.children;
if (oldVnode === vnode) return;
if (vnode.data !== undefined) {
for (i = 0, iLen = cbs.update.length; i < iLen; ++i)
cbs.update[i](oldVnode, vnode);
for (i = 0, iLen = cbs.update.length; i < iLen; ++i) cbs.update[i](oldVnode, vnode);
i = vnode.data.hook;
if (isDef(i) && isDef((i = i.update))) i(oldVnode, vnode);
}
if (isUndef(vnode.text)) {
if (isDef(oldCh) && isDef(ch)) {
if (oldCh !== ch)
updateChildren(
elm,
oldCh as Array<VNode>,
ch as Array<VNode>,
insertedVnodeQueue
);
updateChildren(elm, oldCh as Array<VNode>, ch as Array<VNode>, insertedVnodeQueue);
} else if (isDef(ch)) {
if (isDef(oldVnode.text)) api.setTextContent(elm, "");
addVnodes(
@@ -436,23 +383,13 @@ export function init(modules: Array<Partial<Module>>, domApi?: DOMAPI) {
insertedVnodeQueue
);
} else if (isDef(oldCh)) {
removeVnodes(
elm,
oldCh as Array<VNode>,
0,
(oldCh as Array<VNode>).length - 1
);
removeVnodes(elm, oldCh as Array<VNode>, 0, (oldCh as Array<VNode>).length - 1);
} else if (isDef(oldVnode.text)) {
api.setTextContent(elm, "");
}
} else if (oldVnode.text !== vnode.text) {
if (isDef(oldCh)) {
removeVnodes(
elm,
oldCh as Array<VNode>,
0,
(oldCh as Array<VNode>).length - 1
);
removeVnodes(elm, oldCh as Array<VNode>, 0, (oldCh as Array<VNode>).length - 1);
}
api.setTextContent(elm, vnode.text as string);
}
@@ -510,11 +447,7 @@ interface DOMAPI {
createElementNS: (namespaceURI: string, qualifiedName: string) => Element;
createTextNode: (text: string) => Text;
createComment: (text: string) => Comment;
insertBefore: (
parentNode: Node,
newNode: Node,
referenceNode: Node | null
) => void;
insertBefore: (parentNode: Node, newNode: Node, referenceNode: Node | null) => void;
removeChild: (node: Node, child: Node) => void;
appendChild: (node: Node, child: Node) => void;
parentNode: (node: Node) => Node;
@@ -543,11 +476,7 @@ function createComment(text: string): Comment {
return document.createComment(text);
}
function insertBefore(
parentNode: Node,
newNode: Node,
referenceNode: Node | null
): void {
function insertBefore(parentNode: Node, newNode: Node, referenceNode: Node | null): void {
parentNode.insertBefore(newNode, referenceNode);
}
@@ -644,21 +573,13 @@ type VNodeChildElement = VNode | string | number | undefined | null;
type ArrayOrElement<T> = T | T[];
type VNodeChildren = ArrayOrElement<VNodeChildElement>;
function addNS(
data: any,
children: VNodes | undefined,
sel: string | undefined
): void {
function addNS(data: any, children: VNodes | undefined, sel: string | undefined): void {
data.ns = "http://www.w3.org/2000/svg";
if (sel !== "foreignObject" && children !== undefined) {
for (let i = 0, iLen = children.length; i < iLen; ++i) {
let childData = children[i].data;
if (childData !== undefined) {
addNS(
childData,
(children[i] as VNode).children as VNodes,
children[i].sel
);
addNS(childData, (children[i] as VNode).children as VNodes, children[i].sel);
}
}
}
@@ -697,13 +618,7 @@ export function h(sel: any, b?: any, c?: any): VNode {
if (children !== undefined) {
for (i = 0, iLen = children.length; i < iLen; ++i) {
if (primitive(children[i]))
children[i] = vnode(
undefined,
undefined,
undefined,
children[i],
undefined
);
children[i] = vnode(undefined, undefined, undefined, children[i], undefined);
}
}
if (
@@ -769,9 +684,7 @@ interface Module {
//------------------------------------------------------------------------------
// module/eventlisteners.ts
//------------------------------------------------------------------------------
type On = {
[N in keyof HTMLElementEventMap]?: (ev: HTMLElementEventMap[N]) => void
} & {
type On = { [N in keyof HTMLElementEventMap]?: (ev: HTMLElementEventMap[N]) => void } & {
[event: string]: EventListener;
};
@@ -850,8 +763,7 @@ function updateEventListeners(oldVnode: VNode, vnode?: VNode): void {
// add new listeners which has not already attached
if (on) {
// reuse existing listener or create new
var listener = ((vnode as any).listener =
(oldVnode as any).listener || createListener());
var listener = ((vnode as any).listener = (oldVnode as any).listener || createListener());
// update vnode for listener
listener.vnode = vnode;
@@ -973,9 +885,4 @@ const classModule = { create: updateClass, update: updateClass } as Module;
//------------------------------------------------------------------------------
// patch
//------------------------------------------------------------------------------
export const patch = init([
eventListenersModule,
attrsModule,
propsModule,
classModule
]);
export const patch = init([eventListenersModule, attrsModule, propsModule, classModule]);
+7 -22
View File
@@ -173,10 +173,7 @@ describe("animations", () => {
test("t-transition combined with component", async () => {
expect.assertions(5);
env.qweb.addTemplate(
"Parent",
`<div><Child t-transition="chimay"/></div>`
);
env.qweb.addTemplate("Parent", `<div><Child t-transition="chimay"/></div>`);
env.qweb.addTemplate("Child", `<span>blue</span>`);
class Parent extends Widget {
components = { Child: Child };
@@ -320,9 +317,7 @@ describe("animations", () => {
expect(spans.length).toBe(1);
expect(spans[0].className).toBe(`chimay-${phase} chimay-${phase}-active`);
cb();
expect(spans[0].className).toBe(
`chimay-${phase}-active chimay-${phase}-to`
);
expect(spans[0].className).toBe(`chimay-${phase}-active chimay-${phase}-to`);
def.resolve();
});
@@ -330,9 +325,7 @@ describe("animations", () => {
button!.click();
await def; // wait for the mocked repaint to be done
widget.el!.querySelector("span")!.dispatchEvent(new Event("transitionend")); // mock end of css transition
expect(fixture.innerHTML).toBe(
'<div><button>Toggle</button><span class="">blue</span></div>'
);
expect(fixture.innerHTML).toBe('<div><button>Toggle</button><span class="">blue</span></div>');
// click to remove the span, and click again to re-add it before transitionend
def = makeDeferred();
@@ -346,9 +339,7 @@ describe("animations", () => {
await def; // wait for the mocked repaint to be done
widget.el!.querySelector("span")!.dispatchEvent(new Event("transitionend")); // mock end of css transition
expect(fixture.innerHTML).toBe(
'<div><button>Toggle</button><span class="">blue</span></div>'
);
expect(fixture.innerHTML).toBe('<div><button>Toggle</button><span class="">blue</span></div>');
});
test("t-transition combined with t-component, remove and re-add before transitionend", async () => {
@@ -386,9 +377,7 @@ describe("animations", () => {
expect(spans.length).toBe(1);
expect(spans[0].className).toBe(`chimay-${phase} chimay-${phase}-active`);
cb();
expect(spans[0].className).toBe(
`chimay-${phase}-active chimay-${phase}-to`
);
expect(spans[0].className).toBe(`chimay-${phase}-active chimay-${phase}-to`);
def.resolve();
});
@@ -396,9 +385,7 @@ describe("animations", () => {
button!.click();
await def; // wait for the mocked repaint to be done
widget.el!.querySelector("span")!.dispatchEvent(new Event("transitionend")); // mock end of css transition
expect(fixture.innerHTML).toBe(
'<div><button>Toggle</button><span class="">blue</span></div>'
);
expect(fixture.innerHTML).toBe('<div><button>Toggle</button><span class="">blue</span></div>');
// click to remove the span, and click again to re-add it before transitionend
def = makeDeferred();
@@ -412,8 +399,6 @@ describe("animations", () => {
await def; // wait for the mocked repaint to be done
widget.el!.querySelector("span")!.dispatchEvent(new Event("transitionend")); // mock end of css transition
expect(fixture.innerHTML).toBe(
'<div><button>Toggle</button><span class="">blue</span></div>'
);
expect(fixture.innerHTML).toBe('<div><button>Toggle</button><span class="">blue</span></div>');
});
});
+60 -202
View File
@@ -92,9 +92,7 @@ describe("basic widget properties", () => {
try {
await widget.mount(fixture);
} catch (e) {
expect(e.message).toBe(
'Could not find template for component "SomeWidget"'
);
expect(e.message).toBe('Could not find template for component "SomeWidget"');
}
});
@@ -128,9 +126,7 @@ describe("basic widget properties", () => {
class StyledWidget extends Widget {}
const widget = new StyledWidget(env);
await widget.mount(fixture);
expect(fixture.innerHTML).toBe(
`<div style="font-weight:bold;" class="some-class">world</div>`
);
expect(fixture.innerHTML).toBe(`<div style="font-weight:bold;" class="some-class">world</div>`);
});
test("changing state before first render does not trigger a render", async () => {
@@ -249,10 +245,7 @@ describe("lifecycle hooks", () => {
"ParentWidget",
`<div><t t-if="state.flag"><t t-component="child"/></t></div>`
);
env.qweb.addTemplate(
"ChildWidget",
`<div><t t-component="childchild"/></div>`
);
env.qweb.addTemplate("ChildWidget", `<div><t t-component="childchild"/></div>`);
class ParentWidget extends Widget {
components = { child: ChildWidget };
@@ -300,10 +293,7 @@ describe("lifecycle hooks", () => {
test("willPatch, patched hook are called on subsubcomponents, in proper order", async () => {
const steps: any[] = [];
env.qweb.addTemplate(
"ParentWidget",
`<div><t t-component="child" n="state.n"/></div>`
);
env.qweb.addTemplate("ParentWidget", `<div><t t-component="child" n="state.n"/></div>`);
class ParentWidget extends Widget {
components = { child: ChildWidget };
state = { n: 1 };
@@ -314,10 +304,7 @@ describe("lifecycle hooks", () => {
steps.push("parent:patched");
}
}
env.qweb.addTemplate(
"ChildWidget",
`<div><t t-component="childchild" n="props.n"/></div>`
);
env.qweb.addTemplate("ChildWidget", `<div><t t-component="childchild" n="props.n"/></div>`);
class ChildWidget extends Widget {
components = { childchild: ChildChildWidget };
willPatch() {
@@ -780,11 +767,7 @@ describe("lifecycle hooks", () => {
expect(steps).toEqual(["child:mounted", "child:willUnmount"]);
widget.state.flag = true;
await nextTick();
expect(steps).toEqual([
"child:mounted",
"child:willUnmount",
"child:mounted"
]);
expect(steps).toEqual(["child:mounted", "child:willUnmount", "child:mounted"]);
});
});
@@ -859,10 +842,7 @@ describe("composition", () => {
test("can use components from the global registry", async () => {
QWeb.register("WidgetB", WidgetB);
env.qweb.addTemplate(
"ParentWidget",
`<div><t t-component="WidgetB"/></div>`
);
env.qweb.addTemplate("ParentWidget", `<div><t t-component="WidgetB"/></div>`);
class ParentWidget extends Widget {}
const widget = new ParentWidget(env);
await widget.mount(fixture);
@@ -872,10 +852,7 @@ describe("composition", () => {
test("don't fallback to global registry if widget defined locally", async () => {
QWeb.register("WidgetB", WidgetB); // should not use this widget
env.qweb.addTemplate(
"ParentWidget",
`<div><t t-component="WidgetB"/></div>`
);
env.qweb.addTemplate("ParentWidget", `<div><t t-component="WidgetB"/></div>`);
env.qweb.addTemplate("AnotherWidgetB", `<span>Belgium</span>`);
class AnotherWidgetB extends Widget {}
class ParentWidget extends Widget {
@@ -912,17 +889,12 @@ describe("composition", () => {
try {
await parent.mount(fixture);
} catch (e) {
expect(e.message).toBe(
'Cannot find the definition of component "SomeMispelledWidget"'
);
expect(e.message).toBe('Cannot find the definition of component "SomeMispelledWidget"');
}
});
test("t-refs on widget are components", async () => {
env.qweb.addTemplate(
"WidgetC",
`<div>Hello<t t-ref="mywidgetb" t-component="b"/></div>`
);
env.qweb.addTemplate("WidgetC", `<div>Hello<t t-ref="mywidgetb" t-component="b"/></div>`);
class WidgetC extends Widget {
components = { b: WidgetB };
}
@@ -1007,24 +979,17 @@ describe("composition", () => {
});
test("modifying a sub widget", async () => {
env.qweb.addTemplate(
"ParentWidget",
`<div><t t-component="Counter"/></div>`
);
env.qweb.addTemplate("ParentWidget", `<div><t t-component="Counter"/></div>`);
class ParentWidget extends Widget {
components = { Counter };
}
const widget = new ParentWidget(env);
await widget.mount(fixture);
expect(fixture.innerHTML).toBe(
"<div><div>0<button>Inc</button></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div>0<button>Inc</button></div></div>");
const button = fixture.getElementsByTagName("button")[0];
await button.click();
await nextTick();
expect(fixture.innerHTML).toBe(
"<div><div>1<button>Inc</button></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div>1<button>Inc</button></div></div>");
});
test("refs in a loop", async () => {
@@ -1066,10 +1031,7 @@ describe("composition", () => {
});
test("rerendering a widget with a sub widget", async () => {
env.qweb.addTemplate(
"ParentWidget",
`<div><t t-component="Counter"/></div>`
);
env.qweb.addTemplate("ParentWidget", `<div><t t-component="Counter"/></div>`);
class ParentWidget extends Widget {
components = { Counter };
}
@@ -1078,20 +1040,13 @@ describe("composition", () => {
const button = fixture.getElementsByTagName("button")[0];
await button.click();
await nextTick();
expect(fixture.innerHTML).toBe(
"<div><div>1<button>Inc</button></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div>1<button>Inc</button></div></div>");
await widget.render();
expect(fixture.innerHTML).toBe(
"<div><div>1<button>Inc</button></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div>1<button>Inc</button></div></div>");
});
test("sub components are destroyed if no longer in dom, then recreated", async () => {
env.qweb.addTemplate(
"ParentWidget",
`<div><t t-if="state.ok"><Counter /></t></div>`
);
env.qweb.addTemplate("ParentWidget", `<div><t t-if="state.ok"><Counter /></t></div>`);
class ParentWidget extends Widget {
state = { ok: true };
components = { Counter };
@@ -1101,18 +1056,14 @@ describe("composition", () => {
const button = fixture.getElementsByTagName("button")[0];
await button.click();
await nextTick();
expect(fixture.innerHTML).toBe(
"<div><div>1<button>Inc</button></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div>1<button>Inc</button></div></div>");
widget.state.ok = false;
await nextTick();
expect(fixture.innerHTML).toBe("<div></div>");
widget.state.ok = true;
await nextTick();
expect(fixture.innerHTML).toBe(
"<div><div>0<button>Inc</button></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div>0<button>Inc</button></div></div>");
});
test("sub components with t-keepalive are not destroyed if no longer in dom", async () => {
@@ -1129,9 +1080,7 @@ describe("composition", () => {
const button = fixture.getElementsByTagName("button")[0];
await button.click();
await nextTick();
expect(fixture.innerHTML).toBe(
"<div><div>1<button>Inc</button></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div>1<button>Inc</button></div></div>");
const counter = children(widget)[0];
expect(counter.__owl__.isMounted).toBe(true);
@@ -1143,9 +1092,7 @@ describe("composition", () => {
widget.state.ok = true;
await nextTick();
expect(counter.__owl__.isMounted).toBe(true);
expect(fixture.innerHTML).toBe(
"<div><div>1<button>Inc</button></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div>1<button>Inc</button></div></div>");
});
test("sub components dom state with t-keepalive is preserved", async () => {
@@ -1320,10 +1267,7 @@ describe("composition", () => {
});
test("t-component with dynamic value", async () => {
env.qweb.addTemplate(
"ParentWidget",
`<div><t t-component="{{state.widget}}"/></div>`
);
env.qweb.addTemplate("ParentWidget", `<div><t t-component="{{state.widget}}"/></div>`);
class ParentWidget extends Widget {
components = { WidgetB };
state = { widget: "WidgetB" };
@@ -1335,10 +1279,7 @@ describe("composition", () => {
});
test("t-component with dynamic value 2", async () => {
env.qweb.addTemplate(
"ParentWidget",
`<div><t t-component="Widget{{state.widget}}"/></div>`
);
env.qweb.addTemplate("ParentWidget", `<div><t t-component="Widget{{state.widget}}"/></div>`);
class ParentWidget extends Widget {
components = { WidgetB };
state = { widget: "B" };
@@ -1352,10 +1293,7 @@ describe("composition", () => {
describe("props evaluation ", () => {
test("explicit object prop", async () => {
env.qweb.addTemplate(
"Parent",
`<div><t t-component="child" value="state.val"/></div>`
);
env.qweb.addTemplate("Parent", `<div><t t-component="child" value="state.val"/></div>`);
class Parent extends Widget {
components = { child: Child };
state = { val: 42 };
@@ -1379,10 +1317,7 @@ describe("props evaluation ", () => {
env.qweb.addTemplate("Child", `<span><t t-esc="props.greetings"/></span>`);
class Child extends Widget {}
env.qweb.addTemplate(
"Parent",
`<div><t t-component="child" greetings="greetings"/></div>`
);
env.qweb.addTemplate("Parent", `<div><t t-component="child" greetings="greetings"/></div>`);
class Parent extends Widget {
components = { child: Child };
get greetings() {
@@ -1600,9 +1535,7 @@ describe("class and style attributes with t-component", () => {
}
const widget = new ParentWidget(env);
await widget.mount(fixture);
expect(fixture.innerHTML).toBe(
`<div><div style="font-weight: bold;"></div></div>`
);
expect(fixture.innerHTML).toBe(`<div><div style="font-weight: bold;"></div></div>`);
});
test("dynamic t-att-style is properly added and updated on widget root el", async () => {
@@ -1622,16 +1555,12 @@ describe("class and style attributes with t-component", () => {
expect(env.qweb.templates.ParentWidget.fn.toString()).toMatchSnapshot();
expect(fixture.innerHTML).toBe(
`<div><div style="font-size: 20px;"></div></div>`
);
expect(fixture.innerHTML).toBe(`<div><div style="font-size: 20px;"></div></div>`);
widget.state.style = "font-size: 30px";
await nextTick();
expect(fixture.innerHTML).toBe(
`<div><div style="font-size: 30px;"></div></div>`
);
expect(fixture.innerHTML).toBe(`<div><div style="font-size: 30px;"></div></div>`);
});
});
@@ -1891,10 +1820,7 @@ describe("other directives with t-component", () => {
});
test("t-if works with t-component", async () => {
env.qweb.addTemplate(
"ParentWidget",
`<div><t t-component="child" t-if="state.flag"/></div>`
);
env.qweb.addTemplate("ParentWidget", `<div><t t-component="child" t-if="state.flag"/></div>`);
class ParentWidget extends Widget {
components = { child: Child };
state = { flag: true };
@@ -2044,19 +1970,13 @@ describe("random stuff/miscellaneous", () => {
// in this situation, we protect against a bug that occurred: because of the
// interplay between components and vnodes, a sub widget vnode was patched
// twice.
env.qweb.addTemplate(
"Parent",
`<div><t t-component="child" flag="state.flag"/></div>`
);
env.qweb.addTemplate("Parent", `<div><t t-component="child" flag="state.flag"/></div>`);
class Parent extends Widget {
components = { child: Child };
state = { flag: false };
}
env.qweb.addTemplate(
"Child",
`<span>abc<t t-if="props.flag">def</t></span>`
);
env.qweb.addTemplate("Child", `<span>abc<t t-if="props.flag">def</t></span>`);
class Child extends Widget {}
const widget = new Parent(env);
@@ -2077,10 +1997,7 @@ describe("random stuff/miscellaneous", () => {
state = { flag: false };
}
env.qweb.addTemplate(
"Child",
`<span>abc<t t-if="props.flag">def</t></span>`
);
env.qweb.addTemplate("Child", `<span>abc<t t-if="props.flag">def</t></span>`);
class Child extends Widget {}
const widget = new Parent(env);
@@ -2190,9 +2107,7 @@ describe("random stuff/miscellaneous", () => {
const a = new A(env);
await a.mount(fixture);
expect(fixture.innerHTML).toBe(
`<div>A<div>B</div><div>C<div>D</div><div>E</div></div></div>`
);
expect(fixture.innerHTML).toBe(`<div>A<div>B</div><div>C<div>D</div><div>E</div></div></div>`);
expect(steps).toEqual([
"A:willStart",
"A:render",
@@ -2267,10 +2182,7 @@ describe("async rendering", () => {
test("destroying/recreating a subwidget with different props (if start is not over)", async () => {
let def = makeDeferred();
let n = 0;
env.qweb.addTemplate(
"W",
`<div><t t-if="state.val > 1"><Child val="state.val"/></t></div>`
);
env.qweb.addTemplate("W", `<div><t t-if="state.val > 1"><Child val="state.val"/></t></div>`);
class W extends Widget {
components = { Child };
state = { val: 1 };
@@ -2380,23 +2292,15 @@ describe("async rendering", () => {
}
const parent = new Parent(env);
await parent.mount(fixture);
expect(fixture.innerHTML.replace(/\r?\n|\r|\s+/g, "")).toBe(
"<div><span>a1</span></div>"
);
expect(fixture.innerHTML.replace(/\r?\n|\r|\s+/g, "")).toBe("<div><span>a1</span></div>");
parent.state.valA = 2;
await nextTick();
expect(fixture.innerHTML.replace(/\r?\n|\r|\s+/g, "")).toBe(
"<div><span>a1</span></div>"
);
expect(fixture.innerHTML.replace(/\r?\n|\r|\s+/g, "")).toBe("<div><span>a1</span></div>");
parent.state.flagB = true;
await nextTick();
expect(fixture.innerHTML.replace(/\r?\n|\r|\s+/g, "")).toBe(
"<div><span>a1</span></div>"
);
expect(fixture.innerHTML.replace(/\r?\n|\r|\s+/g, "")).toBe("<div><span>a1</span></div>");
defB.resolve();
expect(fixture.innerHTML.replace(/\r?\n|\r|\s+/g, "")).toBe(
"<div><span>a1</span></div>"
);
expect(fixture.innerHTML.replace(/\r?\n|\r|\s+/g, "")).toBe("<div><span>a1</span></div>");
defA.resolve();
await nextTick();
expect(fixture.innerHTML.replace(/\r?\n|\r|\s+/g, "")).toBe(
@@ -2569,25 +2473,19 @@ describe("async rendering", () => {
await parent.mount(fixture);
expect(env.qweb.templates.Parent.fn.toString()).toMatchSnapshot();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>0</span><span>0</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>0</span><span>0</span>");
// click on button to increment Parent counter
def = makeDeferred();
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>1</span><span>0</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>1</span><span>0</span>");
def.resolve();
await nextTick();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>1</span><span>1</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>1</span><span>1</span>");
});
test("fast component with t-asyncroot directive", async () => {
@@ -2624,25 +2522,19 @@ describe("async rendering", () => {
await parent.mount(fixture);
expect(env.qweb.templates.Parent.fn.toString()).toMatchSnapshot();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>0</span><span>0</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>0</span><span>0</span>");
// click on button to increment Parent counter
def = makeDeferred();
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>1</span><span>0</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>1</span><span>0</span>");
def.resolve();
await nextTick();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>1</span><span>1</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>1</span><span>1</span>");
});
test("t-component with t-asyncroot directive: mixed re-renderings", async () => {
@@ -2687,40 +2579,30 @@ describe("async rendering", () => {
await parent.mount(fixture);
expect(env.qweb.templates.Parent.fn.toString()).toMatchSnapshot();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>0/0</span><span>0/0</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>0/0</span><span>0/0</span>");
// click on button to increment Parent counter
def = makeDeferred();
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>0/1</span><span>0/0</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>0/1</span><span>0/0</span>");
// click on each Child to increment their local counter
const children = parent.el!.querySelectorAll("span");
children[0]!.click();
await nextTick();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>1/1</span><span>0/0</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>1/1</span><span>0/0</span>");
children[1]!.click();
await nextTick();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>1/1</span><span>1/0</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>1/1</span><span>1/0</span>");
// finalize first re-rendering (coming from the props update)
def.resolve();
await nextTick();
expect(fixture.querySelector(".children")!.innerHTML).toBe(
"<span>1/1</span><span>1/1</span>"
);
expect(fixture.querySelector(".children")!.innerHTML).toBe("<span>1/1</span><span>1/1</span>");
});
});
@@ -2860,9 +2742,7 @@ describe("widget and observable state", () => {
try {
await parent.mount(fixture);
} catch (e) {
expect(e.message).toBe(
'Observed state cannot be changed here! (key: "coffee", val: "2")'
);
expect(e.message).toBe('Observed state cannot be changed here! (key: "coffee", val: "2")');
}
});
});
@@ -2903,10 +2783,7 @@ describe("t-mounted directive", () => {
});
test("combined with a t-if", async () => {
env.qweb.addTemplate(
"TestWidget",
`<div><input t-if="state.flag" t-mounted="f"/></div>`
);
env.qweb.addTemplate("TestWidget", `<div><input t-if="state.flag" t-mounted="f"/></div>`);
class TestWidget extends Widget {
state = { flag: false };
f() {}
@@ -2922,10 +2799,7 @@ describe("t-mounted directive", () => {
});
test("combined with a t-ref", async () => {
env.qweb.addTemplate(
"TestWidget",
`<div><input t-ref="input" t-mounted="f"/></div>`
);
env.qweb.addTemplate("TestWidget", `<div><input t-ref="input" t-mounted="f"/></div>`);
class TestWidget extends Widget {
f() {}
}
@@ -3099,9 +2973,7 @@ describe("t-slot directive", () => {
const parent = new Parent(env);
await parent.mount(fixture);
expect(fixture.innerHTML).toBe(
"<div><div><span>sts rocks</span></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div><span>sts rocks</span></div></div>");
});
test("default slot work with text nodes", async () => {
@@ -3144,9 +3016,7 @@ describe("t-slot directive", () => {
const parent = new Parent(env);
await parent.mount(fixture);
expect(fixture.innerHTML).toBe(
"<div><div><span>sts</span><span>rocks</span></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div><span>sts</span><span>rocks</span></div></div>");
});
test("multiple roots are allowed in a default slot", async () => {
@@ -3168,9 +3038,7 @@ describe("t-slot directive", () => {
const parent = new Parent(env);
await parent.mount(fixture);
expect(fixture.innerHTML).toBe(
"<div><div><span>sts</span><span>rocks</span></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div><span>sts</span><span>rocks</span></div></div>");
});
test("missing slots are ignored", async () => {
@@ -3193,9 +3061,7 @@ describe("t-slot directive", () => {
const parent = new Parent(env);
await parent.mount(fixture);
expect(fixture.innerHTML).toBe(
"<div><span><span>some content</span></span></div>"
);
expect(fixture.innerHTML).toBe("<div><span><span>some content</span></span></div>");
});
test("t-debug on a t-set (defining a slot)", async () => {
@@ -3264,16 +3130,12 @@ describe("t-model directive", () => {
const comp = new SomeComponent(env);
await comp.mount(fixture);
expect(fixture.innerHTML).toBe(
'<div><input type="checkbox"><span>no</span></div>'
);
expect(fixture.innerHTML).toBe('<div><input type="checkbox"><span>no</span></div>');
let input = fixture.querySelector("input")!;
input.click();
await nextTick();
expect(fixture.innerHTML).toBe(
'<div><input type="checkbox"><span>yes</span></div>'
);
expect(fixture.innerHTML).toBe('<div><input type="checkbox"><span>yes</span></div>');
expect(comp.state.flag).toBe(true);
expect(env.qweb.templates.SomeComponent.fn.toString()).toMatchSnapshot();
@@ -3296,16 +3158,12 @@ describe("t-model directive", () => {
const comp = new SomeComponent(env);
await comp.mount(fixture);
expect(fixture.innerHTML).toBe(
"<div><textarea></textarea><span></span></div>"
);
expect(fixture.innerHTML).toBe("<div><textarea></textarea><span></span></div>");
const textarea = fixture.querySelector("textarea")!;
await editInput(textarea, "test");
expect(comp.state.text).toBe("test");
expect(fixture.innerHTML).toBe(
"<div><textarea></textarea><span>test</span></div>"
);
expect(fixture.innerHTML).toBe("<div><textarea></textarea><span>test</span></div>");
});
test("on an input type=radio", async () => {
+3 -8
View File
@@ -52,14 +52,10 @@ interface FileData {
sections: MarkDownSection[];
}
function isLinkValid(
link: MarkDownLink,
current: FileData,
files: FileData[]
): boolean {
function isLinkValid(link: MarkDownLink, current: FileData, files: FileData[]): boolean {
const parts = link.link.split("#");
const currentParts = current.name.split("/");
const path = currentParts.length > 1 ? currentParts[0] + '/' : "";
const path = currentParts.length > 1 ? currentParts[0] + "/" : "";
const fullName = path + parts[0];
if (parts.length === 1) {
// no # in url
@@ -70,8 +66,7 @@ function isLinkValid(
}
}
} else {
const file =
parts[0] === "" ? current : files.find(f => f.name === fullName);
const file = parts[0] === "" ? current : files.find(f => f.name === fullName);
if (!file) {
return false;
}
+1 -3
View File
@@ -23,9 +23,7 @@ describe("event bus behaviour", () => {
test("throw error if callback is undefined", () => {
expect.assertions(1);
const bus = new EventBus();
expect(() => bus.on("event", {}, <any>undefined)).toThrow(
`Missing callback`
);
expect(() => bus.on("event", {}, <any>undefined)).toThrow(`Missing callback`);
});
test("can unsubscribe", () => {
+2 -9
View File
@@ -68,11 +68,7 @@ export function renderToDOM(
return result.elm as HTMLElement;
}
export function renderToString(
qweb: QWeb,
t: string,
context: EvalContext = {}
): string {
export function renderToString(qweb: QWeb, t: string, context: EvalContext = {}): string {
const node = renderToDOM(qweb, t, context);
return node instanceof Text ? node.textContent! : node.outerHTML;
}
@@ -92,10 +88,7 @@ export function unpatchNextFrame() {
UTILS.nextFrame = nextFrame;
}
export async function editInput(
input: HTMLInputElement | HTMLTextAreaElement,
value: string
) {
export async function editInput(input: HTMLInputElement | HTMLTextAreaElement, value: string) {
input.value = value;
input.dispatchEvent(new Event("input"));
input.dispatchEvent(new Event("change"));
+7 -12
View File
@@ -126,7 +126,6 @@ describe("props validation", () => {
}
});
test("can validate a prop with multiple types", async () => {
let TestWidget = class extends Widget {
static props = { p: [String, Boolean] };
@@ -149,16 +148,14 @@ describe("props validation", () => {
expect(() => {
new TestWidget(env, { p: "hey" });
new TestWidget(env, { });
new TestWidget(env, {});
}).not.toThrow();
expect(() => {
new TestWidget(env, { p: 1 });
}).toThrow();
});
test("can validate an array with given primitive type", async () => {
let TestWidget = class extends Widget {
static props = { p: { type: Array, element: String } };
@@ -222,7 +219,7 @@ describe("props validation", () => {
type: Object,
shape: {
id: Number,
url: [Boolean, {type: Array, element: Number}],
url: [Boolean, { type: Array, element: Number }]
}
}
};
@@ -230,21 +227,19 @@ describe("props validation", () => {
expect(() => {
new TestWidget(env, { p: { id: 1, url: true } });
new TestWidget(env, { p: { id: 1, url: [12]} });
new TestWidget(env, { p: { id: 1, url: [12] } });
}).not.toThrow();
expect(() => {
new TestWidget(env, { p: { id: 1, url: [12, true]} });
new TestWidget(env, { p: { id: 1, url: [12, true] } });
}).toThrow();
});
});
describe("default props", () => {
test("can set default values", async () => {
class TestWidget extends Widget {
static defaultProps = {p: 4}
static defaultProps = { p: 4 };
}
const w = new TestWidget(env, {});
@@ -253,10 +248,10 @@ describe("default props", () => {
test("default values are also set whenever component is updated", async () => {
class TestWidget extends Widget {
static defaultProps = {p: 4}
static defaultProps = { p: 4 };
}
const w = new TestWidget(env, {p: 1});
const w = new TestWidget(env, { p: 1 });
await w.__updateProps({});
expect(w.props.p).toBe(4);
});
+35 -111
View File
@@ -26,9 +26,7 @@ describe("static templates", () => {
test("simple dynamic value", () => {
qweb.addTemplate("test", '<t><t t-esc="text"/></t>');
expect(renderToString(qweb, "test", { text: "hello vdom" })).toBe(
"hello vdom"
);
expect(renderToString(qweb, "test", { text: "hello vdom" })).toBe("hello vdom");
});
test("simple string, with some dynamic value", () => {
@@ -54,9 +52,7 @@ describe("static templates", () => {
describe("error handling", () => {
test("invalid xml", () => {
expect(() => qweb.addTemplate("test", "<div>")).toThrow(
"Invalid XML in template"
);
expect(() => qweb.addTemplate("test", "<div>")).toThrow("Invalid XML in template");
});
test("template with text node and tag", () => {
@@ -73,9 +69,7 @@ describe("error handling", () => {
test("cannot add twice the same template", () => {
qweb.addTemplate("test", `<t></t>`);
expect(() => qweb.addTemplate("test", "<div/>", true)).not.toThrow(
"already defined"
);
expect(() => qweb.addTemplate("test", "<div/>", true)).not.toThrow("already defined");
expect(() => qweb.addTemplate("test", "<div/>")).toThrow("already defined");
});
@@ -94,19 +88,14 @@ describe("error handling", () => {
test("nice error when t-on is evaluated with a missing event", () => {
qweb.addTemplate("templatename", `<div t-on="somemethod"></div>`);
expect(() =>
qweb.render("templatename", { someMethod() {} }, { handlers: [] })
).toThrow("Missing event name with t-on directive");
expect(() => qweb.render("templatename", { someMethod() {} }, { handlers: [] })).toThrow(
"Missing event name with t-on directive"
);
});
test("error when unknown directive", () => {
qweb.addTemplate(
"templatename",
`<div t-best-beer="rochefort 10">test</div>`
);
expect(() => qweb.render("templatename")).toThrow(
"Unknown QWeb directive: 't-best-beer'"
);
qweb.addTemplate("templatename", `<div t-best-beer="rochefort 10">test</div>`);
expect(() => qweb.render("templatename")).toThrow("Unknown QWeb directive: 't-best-beer'");
});
});
@@ -123,9 +112,7 @@ describe("t-esc", () => {
test.skip("escaping", () => {
qweb.addTemplate("test", `<span><t t-esc="var"/></span>`);
expect(renderToString(qweb, "test", { var: "<ok>" })).toBe(
"<span>&lt;ok&gt;</span>"
);
expect(renderToString(qweb, "test", { var: "<ok>" })).toBe("<span>&lt;ok&gt;</span>");
});
test("escaping on a node", () => {
@@ -157,9 +144,7 @@ describe("t-raw", () => {
test("not escaping", () => {
qweb.addTemplate("test", `<div><t t-raw="var"/></div>`);
expect(renderToString(qweb, "test", { var: "<ok></ok>" })).toBe(
"<div><ok></ok></div>"
);
expect(renderToString(qweb, "test", { var: "<ok></ok>" })).toBe("<div><ok></ok></div>");
});
test("t-raw and another sibling node", () => {
@@ -172,10 +157,7 @@ describe("t-raw", () => {
describe("t-set", () => {
test("set from attribute literal", () => {
qweb.addTemplate(
"test",
`<div><t t-set="value" t-value="'ok'"/><t t-esc="value"/></div>`
);
qweb.addTemplate("test", `<div><t t-set="value" t-value="'ok'"/><t t-esc="value"/></div>`);
expect(renderToString(qweb, "test")).toBe("<div>ok</div>");
});
@@ -187,24 +169,16 @@ describe("t-set", () => {
<t t-if="v === 'ok'">grimbergen</t>
</div>`
);
expect(renderToString(qweb, "test", { value: "ok" })).toBe(
"<div>grimbergen</div>"
);
expect(renderToString(qweb, "test", { value: "ok" })).toBe("<div>grimbergen</div>");
});
test("set from body literal", () => {
qweb.addTemplate(
"test",
`<t><t t-set="value">ok</t><t t-esc="value"/></t>`
);
qweb.addTemplate("test", `<t><t t-set="value">ok</t><t t-esc="value"/></t>`);
expect(renderToString(qweb, "test")).toBe("ok");
});
test("set from attribute lookup", () => {
qweb.addTemplate(
"test",
`<div><t t-set="stuff" t-value="value"/><t t-esc="stuff"/></div>`
);
qweb.addTemplate("test", `<div><t t-set="stuff" t-value="value"/><t t-esc="stuff"/></div>`);
expect(renderToString(qweb, "test", { value: "ok" })).toBe("<div>ok</div>");
});
@@ -236,18 +210,12 @@ describe("t-set", () => {
});
test("value priority", () => {
qweb.addTemplate(
"test",
`<div><t t-set="value" t-value="1">2</t><t t-esc="value"/></div>`
);
qweb.addTemplate("test", `<div><t t-set="value" t-value="1">2</t><t t-esc="value"/></div>`);
expect(renderToString(qweb, "test")).toBe("<div>1</div>");
});
test("evaluate value expression", () => {
qweb.addTemplate(
"test",
`<div><t t-set="value" t-value="1 + 2"/><t t-esc="value"/></div>`
);
qweb.addTemplate("test", `<div><t t-set="value" t-value="1 + 2"/><t t-esc="value"/></div>`);
expect(renderToString(qweb, "test")).toBe("<div>3</div>");
});
@@ -272,25 +240,19 @@ describe("t-set", () => {
"test",
`<div><t t-set="value" t-value="somevariable + 2"/><t t-esc="value"/></div>`
);
expect(renderToString(qweb, "test", { somevariable: 43 })).toBe(
"<div>45</div>"
);
expect(renderToString(qweb, "test", { somevariable: 43 })).toBe("<div>45</div>");
});
});
describe("t-if", () => {
test("boolean value true condition", () => {
qweb.addTemplate("test", `<div><t t-if="condition">ok</t></div>`);
expect(renderToString(qweb, "test", { condition: true })).toBe(
"<div>ok</div>"
);
expect(renderToString(qweb, "test", { condition: true })).toBe("<div>ok</div>");
});
test("boolean value false condition", () => {
qweb.addTemplate("test", `<div><t t-if="condition">ok</t></div>`);
expect(renderToString(qweb, "test", { condition: false })).toBe(
"<div></div>"
);
expect(renderToString(qweb, "test", { condition: false })).toBe("<div></div>");
});
test("boolean value condition missing", () => {
@@ -307,9 +269,7 @@ describe("t-if", () => {
<t t-else="">beer</t></div>
`
);
expect(renderToString(qweb, "test", { color: "red" })).toBe(
"<div>red is dead</div>"
);
expect(renderToString(qweb, "test", { color: "red" })).toBe("<div>red is dead</div>");
});
test("boolean value condition else", () => {
@@ -335,9 +295,7 @@ describe("t-if", () => {
`
);
const result = trim(renderToString(qweb, "test", { condition: false }));
expect(result).toBe(
"<div><span>begin</span>fail-else<span>end</span></div>"
);
expect(result).toBe("<div><span>begin</span>fail-else<span>end</span></div>");
});
test("can use some boolean operators in expressions", () => {
@@ -362,9 +320,7 @@ describe("t-if", () => {
m: 5,
n: 2
};
expect(normalize(renderToString(qweb, "test", context))).toBe(
"<div>andormgtnlt</div>"
);
expect(normalize(renderToString(qweb, "test", context))).toBe("<div>andormgtnlt</div>");
});
});
@@ -489,10 +445,7 @@ describe("attributes", () => {
});
test("format multiple", () => {
qweb.addTemplate(
"test",
`<div t-attf-foo="a {{value1}} is {{value2}} of {{value3}} ]"/>`
);
qweb.addTemplate("test", `<div t-attf-foo="a {{value1}} is {{value2}} of {{value3}} ]"/>`);
const result = renderToString(qweb, "test", {
value1: 0,
value2: 1,
@@ -528,19 +481,13 @@ describe("attributes", () => {
});
test("class and t-attf-class with ternary operation", () => {
qweb.addTemplate(
"test",
`<div class="hello" t-attf-class="{{value ? 'world' : ''}}"/>`
);
qweb.addTemplate("test", `<div class="hello" t-attf-class="{{value ? 'world' : ''}}"/>`);
const result = renderToString(qweb, "test", { value: true });
expect(result).toBe(`<div class="hello world"></div>`);
});
test("t-att-class with object", () => {
qweb.addTemplate(
"test",
`<div class="static" t-att-class="{a: b, c: d, e: f}"/>`
);
qweb.addTemplate("test", `<div class="static" t-att-class="{a: b, c: d, e: f}"/>`);
const result = renderToString(qweb, "test", { b: true, d: false, f: true });
expect(result).toBe(`<div class="static a e"></div>`);
});
@@ -569,10 +516,7 @@ describe("t-call (template calling", () => {
test("with unused setbody", () => {
qweb.addTemplate("_basic-callee", "<div>ok</div>");
qweb.addTemplate(
"caller",
'<t t-call="_basic-callee"><t t-set="qux" t-value="3"/></t>'
);
qweb.addTemplate("caller", '<t t-call="_basic-callee"><t t-set="qux" t-value="3"/></t>');
const expected = "<div>ok</div>";
expect(renderToString(qweb, "caller")).toBe(expected);
});
@@ -678,9 +622,7 @@ describe("foreach", () => {
</t>
</div>`
);
const result = trim(
renderToString(qweb, "test", { value: { a: 1, b: 2, c: 3 } })
);
const result = trim(renderToString(qweb, "test", { value: { a: 1, b: 2, c: 3 } }));
const expected = `<div>[0:a1][1:b2][2:c3]</div>`;
expect(result).toBe(expected);
});
@@ -727,14 +669,8 @@ describe("foreach", () => {
describe("misc", () => {
test("global", () => {
qweb.addTemplate("_callee-asc", `<Año t-att-falló="'agüero'" t-raw="0"/>`);
qweb.addTemplate(
"_callee-uses-foo",
`<span t-esc="foo">foo default</span>`
);
qweb.addTemplate(
"_callee-asc-toto",
`<div t-raw="toto">toto default</div>`
);
qweb.addTemplate("_callee-uses-foo", `<span t-esc="foo">foo default</span>`);
qweb.addTemplate("_callee-asc-toto", `<div t-raw="toto">toto default</div>`);
qweb.addTemplate(
"caller",
`
@@ -847,10 +783,7 @@ describe("t-on", () => {
});
test("can bind handlers with object arguments", () => {
qweb.addTemplate(
"test",
`<button t-on-click="add({val: 5})">Click</button>`
);
qweb.addTemplate("test", `<button t-on-click="add({val: 5})">Click</button>`);
let a = 1;
const node = renderToDOM(
qweb,
@@ -868,10 +801,7 @@ describe("t-on", () => {
test("can bind handlers with empty object", () => {
expect.assertions(2);
qweb.addTemplate(
"test",
`<button t-on-click="doSomething({})">Click</button>`
);
qweb.addTemplate("test", `<button t-on-click="doSomething({})">Click</button>`);
const node = renderToDOM(
qweb,
"test",
@@ -887,10 +817,7 @@ describe("t-on", () => {
test("can bind handlers with empty object (with non empty inner string)", () => {
expect.assertions(2);
qweb.addTemplate(
"test",
`<button t-on-click="doSomething({ })">Click</button>`
);
qweb.addTemplate("test", `<button t-on-click="doSomething({ })">Click</button>`);
const node = renderToDOM(
qweb,
"test",
@@ -1190,13 +1117,10 @@ describe("whitespace handling", () => {
describe("t-key", () => {
test("can use t-key directive on a node", () => {
qweb.addTemplate(
"test",
`<div t-key="beer.id"><t t-esc="beer.name"/></div>`
qweb.addTemplate("test", `<div t-key="beer.id"><t t-esc="beer.name"/></div>`);
expect(renderToString(qweb, "test", { beer: { id: 12, name: "Chimay Rouge" } })).toBe(
"<div>Chimay Rouge</div>"
);
expect(
renderToString(qweb, "test", { beer: { id: 12, name: "Chimay Rouge" } })
).toBe("<div>Chimay Rouge</div>");
});
test("t-key directive in a list", () => {
+17 -40
View File
@@ -2,9 +2,7 @@ import { compileExpr, tokenize } from "../src/qweb_expressions";
describe("tokenizer", () => {
test("simple tokens", () => {
expect(tokenize("1.3")).toEqual([
{ type: "VALUE", value: "1.3" }
]);
expect(tokenize("1.3")).toEqual([{ type: "VALUE", value: "1.3" }]);
expect(tokenize("{}")).toEqual([
{ type: "LEFT_BRACE", value: "{" },
@@ -29,10 +27,7 @@ describe("tokenizer", () => {
{ type: "VALUE", value: "2" },
{ type: "RIGHT_BRACE", value: "}" }
]);
expect(tokenize("a,")).toEqual([
{ type: "SYMBOL", value: "a" },
{ type: "COMMA", value: "," }
]);
expect(tokenize("a,")).toEqual([{ type: "SYMBOL", value: "a" }, { type: "COMMA", value: "," }]);
expect(tokenize("][")).toEqual([
{ type: "RIGHT_BRACKET", value: "]" },
{ type: "LEFT_BRACKET", value: "[" }
@@ -46,7 +41,7 @@ describe("tokenizer", () => {
{ type: "OPERATOR", value: "<" },
{ type: "OPERATOR", value: ">" },
{ type: "OPERATOR", value: "!==" },
{ type: "OPERATOR", value: "!=" },
{ type: "OPERATOR", value: "!=" }
]);
});
@@ -54,25 +49,17 @@ describe("tokenizer", () => {
expect(() => tokenize("'")).toThrow("Invalid expression");
expect(() => tokenize("'\\")).toThrow("Invalid expression");
expect(() => tokenize("'\\'")).toThrow("Invalid expression");
expect(tokenize("'hello ged'")).toEqual([
{ type: "VALUE", value: "'hello ged'" }
]);
expect(tokenize("'hello \\'ged\\''")).toEqual([
{ type: "VALUE", value: "'hello \\'ged\\''" }
]);
expect(tokenize("'hello ged'")).toEqual([{ type: "VALUE", value: "'hello ged'" }]);
expect(tokenize("'hello \\'ged\\''")).toEqual([{ type: "VALUE", value: "'hello \\'ged\\''" }]);
expect(() => tokenize('"')).toThrow("Invalid expression");
expect(() => tokenize('"\\"')).toThrow("Invalid expression");
expect(tokenize('"hello ged"')).toEqual([
{ type: "VALUE", value: '"hello ged"' }
]);
expect(tokenize('"hello ged"')).toEqual([{ type: "VALUE", value: '"hello ged"' }]);
expect(tokenize('"hello ged"}')).toEqual([
{ type: "VALUE", value: '"hello ged"' },
{ type: "RIGHT_BRACE", value: "}" }
]);
expect(tokenize('"hello \\"ged\\""')).toEqual([
{ type: "VALUE", value: '"hello \\"ged\\""' }
]);
expect(tokenize('"hello \\"ged\\""')).toEqual([{ type: "VALUE", value: '"hello \\"ged\\""' }]);
});
});
@@ -113,9 +100,7 @@ describe("expression evaluation", () => {
test("arrays and objects", () => {
expect(compileExpr("[{b:1}] ", {})).toBe("[{b:1}]");
expect(compileExpr("{a: []} ", {})).toBe("{a:[]}");
expect(compileExpr("[{b:1, c: [1, {d: {e: 3}} ]}] ", {})).toBe(
"[{b:1,c:[1,{d:{e:3}}]}]"
);
expect(compileExpr("[{b:1, c: [1, {d: {e: 3}} ]}] ", {})).toBe("[{b:1,c:[1,{d:{e:3}}]}]");
});
test("dot operator", () => {
@@ -130,13 +115,9 @@ describe("expression evaluation", () => {
});
test("various binary operators", () => {
expect(compileExpr("color == 'black'", {})).toBe(
"context['color']=='black'"
);
expect(compileExpr("color == 'black'", {})).toBe("context['color']=='black'");
expect(compileExpr("a || b", {})).toBe("context['a']||context['b']");
expect(compileExpr("color === 'black'", {})).toBe(
"context['color']==='black'"
);
expect(compileExpr("color === 'black'", {})).toBe("context['color']==='black'");
expect(compileExpr("'li_'+item", {})).toBe("'li_'+context['item']");
expect(compileExpr("state.val > 1", {})).toBe("context['state'].val>1");
});
@@ -164,18 +145,14 @@ describe("expression evaluation", () => {
expect(compileExpr("a()", {})).toBe("context['a']()");
expect(compileExpr("a(1)", {})).toBe("context['a'](1)");
expect(compileExpr("a(1,2)", {})).toBe("context['a'](1,2)");
expect(compileExpr("a(1,2,{a:[a]})", {})).toBe(
"context['a'](1,2,{a:[context['a']]})"
);
expect(compileExpr("a(1,2,{a:[a]})", {})).toBe("context['a'](1,2,{a:[context['a']]})");
expect(compileExpr("'x'.toUpperCase()", {})).toBe("'x'.toUpperCase()");
expect(compileExpr("'x'.toUpperCase({a: 3})", {})).toBe(
"'x'.toUpperCase({a:3})"
expect(compileExpr("'x'.toUpperCase({a: 3})", {})).toBe("'x'.toUpperCase({a:3})");
expect(compileExpr("'x'.toUpperCase(a)", { a: { id: "_v5", expr: "" } })).toBe(
"'x'.toUpperCase(_v5)"
);
expect(compileExpr("'x'.toUpperCase({b: a})", { a: { id: "_v5", expr: "" } })).toBe(
"'x'.toUpperCase({b:_v5})"
);
expect(
compileExpr("'x'.toUpperCase(a)", { a: { id: "_v5", expr: "" } })
).toBe("'x'.toUpperCase(_v5)");
expect(
compileExpr("'x'.toUpperCase({b: a})", { a: { id: "_v5", expr: "" } })
).toBe("'x'.toUpperCase({b:_v5})");
});
});
+6 -21
View File
@@ -1,11 +1,6 @@
import { Component, Env } from "../src/component";
import { connect, Store } from "../src/store";
import {
makeTestFixture,
makeTestEnv,
nextMicroTick,
nextTick
} from "./helpers";
import { makeTestFixture, makeTestEnv, nextMicroTick, nextTick } from "./helpers";
import { Observer } from "../src";
describe("basic use", () => {
@@ -794,9 +789,7 @@ describe("connecting a component to store", () => {
store.commit("addTodo", "hoegaarden");
await nextTick();
expect(fixture.innerHTML).toBe(
"<div><span>jupiler</span><span>hoegaarden</span></div>"
);
expect(fixture.innerHTML).toBe("<div><span>jupiler</span><span>hoegaarden</span></div>");
});
test("connect receives store getters as third argument", async () => {
@@ -930,9 +923,7 @@ describe("connecting a component to store", () => {
store.commit("addBeer", "kwak");
await nextTick();
expect(fixture.innerHTML).toBe(
"<div><span>jupiler</span><span>kwak</span></div>"
);
expect(fixture.innerHTML).toBe("<div><span>jupiler</span><span>kwak</span></div>");
});
test("connected component with undefined, null and string props", async () => {
@@ -984,9 +975,7 @@ describe("connecting a component to store", () => {
const app = new App(env);
await app.mount(fixture);
expect(fixture.innerHTML).toBe(
"<div><div><span>taster:aaron</span></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div><span>taster:aaron</span></div></div>");
app.state.beerId = 1;
await nextTick();
@@ -1062,9 +1051,7 @@ describe("connecting a component to store", () => {
const app = new App(env);
await app.mount(fixture);
expect(fixture.innerHTML).toBe(
"<div><div><span>taster:aaron</span></div></div>"
);
expect(fixture.innerHTML).toBe("<div><div><span>taster:aaron</span></div></div>");
app.state.beerId = 1;
await nextTick();
@@ -1334,9 +1321,7 @@ describe("connecting a component to store", () => {
await nextTick();
expect(renderCount).toBe(1);
expect(fCount).toBe(1);
expect(fixture.innerHTML).toBe(
'<div class="todoapp"></div>'
);
expect(fixture.innerHTML).toBe('<div class="todoapp"></div>');
});
test("connected component willpatch/patch hooks are called on store updates", async () => {
+28 -143
View File
@@ -59,9 +59,7 @@ describe("attributes", function() {
test("are set correctly when namespaced", function() {
const vnode1 = h("div", { attrs: { "xlink:href": "#foo" } });
elm = patch(vnode0, vnode1).elm;
expect(elm.getAttributeNS("http://www.w3.org/1999/xlink", "href")).toBe(
"#foo"
);
expect(elm.getAttributeNS("http://www.w3.org/1999/xlink", "href")).toBe("#foo");
});
test("should not touch class nor id fields", function() {
@@ -207,12 +205,8 @@ describe("snabbdom", function() {
expect(elm.firstChild.namespaceURI).toBe(SVGNamespace);
// verify that svg tag automatically gets svg namespace
elm = patch(
vnode0,
h("svg", [
h("foreignObject", [h("div", ["I am HTML embedded in SVG"])])
])
).elm;
elm = patch(vnode0, h("svg", [h("foreignObject", [h("div", ["I am HTML embedded in SVG"])])]))
.elm;
expect(elm.namespaceURI).toBe(SVGNamespace);
expect(elm.firstChild.namespaceURI).toBe(SVGNamespace);
expect(elm.firstChild.firstChild.namespaceURI).toBe(XHTMLNamespace);
@@ -352,13 +346,7 @@ describe("snabbdom", function() {
elm = patch(vnode0, vnode1).elm;
expect(elm.children.length).toBe(2);
elm = patch(vnode1, vnode2).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual([
"1",
"2",
"3",
"4",
"5"
]);
expect(map(elm.children, c => c.innerHTML)).toEqual(["1", "2", "3", "4", "5"]);
});
test("add elements in the middle", function() {
@@ -368,13 +356,7 @@ describe("snabbdom", function() {
expect(elm.children.length).toBe(4);
expect(elm.children.length).toBe(4);
elm = patch(vnode1, vnode2).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual([
"1",
"2",
"3",
"4",
"5"
]);
expect(map(elm.children, c => c.innerHTML)).toEqual(["1", "2", "3", "4", "5"]);
});
test("add elements at beginning and end", function() {
@@ -383,13 +365,7 @@ describe("snabbdom", function() {
elm = patch(vnode0, vnode1).elm;
expect(elm.children.length).toBe(3);
elm = patch(vnode1, vnode2).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual([
"1",
"2",
"3",
"4",
"5"
]);
expect(map(elm.children, c => c.innerHTML)).toEqual(["1", "2", "3", "4", "5"]);
});
test("adds children to parent with no children", function() {
@@ -588,35 +564,19 @@ describe("snabbdom", function() {
elm = patch(vnode0, vnode1).elm;
expect(elm.children.length).toBe(6);
elm = patch(vnode1, vnode2).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual([
"4",
"3",
"2",
"1",
"5",
"0"
]);
expect(map(elm.children, c => c.innerHTML)).toEqual(["4", "3", "2", "1", "5", "0"]);
});
test("supports null/undefined children", function() {
const vnode1 = h("i", [0, 1, 2, 3, 4, 5].map(spanNum));
const vnode2 = h(
"i",
[null, 2, undefined, null, 1, 0, null, 5, 4, null, 3, undefined].map(
spanNum
)
[null, 2, undefined, null, 1, 0, null, 5, 4, null, 3, undefined].map(spanNum)
);
elm = patch(vnode0, vnode1).elm;
expect(elm.children.length).toBe(6);
elm = patch(vnode1, vnode2).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual([
"2",
"1",
"0",
"5",
"4",
"3"
]);
expect(map(elm.children, c => c.innerHTML)).toEqual(["2", "1", "0", "5", "4", "3"]);
});
test("supports all null/undefined children", function() {
@@ -627,14 +587,7 @@ describe("snabbdom", function() {
elm = patch(vnode1, vnode2).elm;
expect(elm.children.length).toBe(0);
elm = patch(vnode2, vnode3).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual([
"5",
"4",
"3",
"2",
"1",
"0"
]);
expect(map(elm.children, c => c.innerHTML)).toEqual(["5", "4", "3", "2", "1", "0"]);
});
});
});
@@ -714,18 +667,10 @@ describe("snabbdom", function() {
});
test("removes elements", function() {
const vnode1 = h("div", [
h("span", "One"),
h("span", "Two"),
h("span", "Three")
]);
const vnode1 = h("div", [h("span", "One"), h("span", "Two"), h("span", "Three")]);
const vnode2 = h("div", [h("span", "One"), h("span", "Three")]);
elm = patch(vnode0, vnode1).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual([
"One",
"Two",
"Three"
]);
expect(map(elm.children, c => c.innerHTML)).toEqual(["One", "Two", "Three"]);
elm = patch(vnode1, vnode2).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual(["One", "Three"]);
});
@@ -760,49 +705,19 @@ describe("snabbdom", function() {
});
test("reorders elements", function() {
const vnode1 = h("div", [
h("span", "One"),
h("div", "Two"),
h("b", "Three")
]);
const vnode2 = h("div", [
h("b", "Three"),
h("span", "One"),
h("div", "Two")
]);
const vnode1 = h("div", [h("span", "One"), h("div", "Two"), h("b", "Three")]);
const vnode2 = h("div", [h("b", "Three"), h("span", "One"), h("div", "Two")]);
elm = patch(vnode0, vnode1).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual([
"One",
"Two",
"Three"
]);
expect(map(elm.children, c => c.innerHTML)).toEqual(["One", "Two", "Three"]);
elm = patch(vnode1, vnode2).elm;
expect(map(elm.children, c => c.tagName)).toEqual(["B", "SPAN", "DIV"]);
expect(map(elm.children, c => c.innerHTML)).toEqual([
"Three",
"One",
"Two"
]);
expect(map(elm.children, c => c.innerHTML)).toEqual(["Three", "One", "Two"]);
});
test("supports null/undefined children", function() {
const vnode1 = h("i", [null, h("i", "1"), h("i", "2"), null]);
const vnode2 = h("i", [
h("i", "2"),
undefined,
undefined,
h("i", "1"),
undefined
]);
const vnode3 = h("i", [
null,
h("i", "1"),
undefined,
null,
h("i", "2"),
undefined,
null
]);
const vnode2 = h("i", [h("i", "2"), undefined, undefined, h("i", "1"), undefined]);
const vnode3 = h("i", [null, h("i", "1"), undefined, null, h("i", "2"), undefined, null]);
elm = patch(vnode0, vnode1).elm;
expect(map(elm.children, c => c.innerHTML)).toEqual(["1", "2"]);
elm = patch(vnode1, vnode2).elm;
@@ -835,10 +750,7 @@ describe("snabbdom", function() {
}
const vnode1 = h("div", [
h("span", "First sibling"),
h("div", { hook: { create: cb } }, [
h("span", "Child 1"),
h("span", "Child 2")
]),
h("div", { hook: { create: cb } }, [h("span", "Child 1"), h("span", "Child 2")]),
h("span", "Can't touch me")
]);
patch(vnode0, vnode1);
@@ -855,10 +767,7 @@ describe("snabbdom", function() {
}
const vnode1 = h("div", [
h("span", "First sibling"),
h("div", { hook: { insert: cb } }, [
h("span", "Child 1"),
h("span", "Child 2")
]),
h("div", { hook: { insert: cb } }, [h("span", "Child 1"), h("span", "Child 2")]),
h("span", "Can touch me")
]);
patch(vnode0, vnode1);
@@ -874,17 +783,11 @@ describe("snabbdom", function() {
}
const vnode1 = h("div", [
h("span", "First sibling"),
h("div", { hook: { prepatch: cb } }, [
h("span", "Child 1"),
h("span", "Child 2")
])
h("div", { hook: { prepatch: cb } }, [h("span", "Child 1"), h("span", "Child 2")])
]);
const vnode2 = h("div", [
h("span", "First sibling"),
h("div", { hook: { prepatch: cb } }, [
h("span", "Child 1"),
h("span", "Child 2")
])
h("div", { hook: { prepatch: cb } }, [h("span", "Child 1"), h("span", "Child 2")])
]);
patch(vnode0, vnode1);
patch(vnode1, vnode2);
@@ -965,10 +868,7 @@ describe("snabbdom", function() {
}
const vnode1 = h("div", [
h("span", "First sibling"),
h("div", { hook: { remove: cb } }, [
h("span", "Child 1"),
h("span", "Child 2")
])
h("div", { hook: { remove: cb } }, [h("span", "Child 1"), h("span", "Child 2")])
]);
const vnode2 = h("div", [h("span", "First sibling")]);
patch(vnode0, vnode1);
@@ -981,9 +881,7 @@ describe("snabbdom", function() {
function cb(vnode) {
calls++;
}
const vnode1 = h("div", [
h("div", { hook: { destroy: cb } }, [h("span", "Child 1")])
]);
const vnode1 = h("div", [h("div", { hook: { destroy: cb } }, [h("span", "Child 1")])]);
const vnode2 = h("div", "Text node");
patch(vnode0, vnode1);
patch(vnode1, vnode2);
@@ -1053,10 +951,7 @@ describe("snabbdom", function() {
result.push(vnode);
rm();
}
const vnode1 = h("div", { hook: { remove: cb } }, [
h("b", "Child 1"),
h("i", "Child 2")
]);
const vnode1 = h("div", { hook: { remove: cb } }, [h("b", "Child 1"), h("i", "Child 2")]);
const vnode2 = h("span", [h("b", "Child 1"), h("i", "Child 2")]);
patch(vnode0, vnode1);
patch(vnode1, vnode2);
@@ -1091,10 +986,7 @@ describe("snabbdom", function() {
}
const vnode1 = h("div", [
h("span", "First sibling"),
h("div", [
h("span", { hook: { destroy: cb } }, "Child 1"),
h("span", "Child 2")
])
h("div", [h("span", { hook: { destroy: cb } }, "Child 1"), h("span", "Child 2")])
]);
const vnode2 = h("div");
patch(vnode0, vnode1);
@@ -1150,11 +1042,7 @@ describe("snabbdom", function() {
}
}
]);
const vnode1 = h("div", [
h("span", "First child"),
"",
h("span", "Third child")
]);
const vnode1 = h("div", [h("span", "First child"), "", h("span", "Third child")]);
const vnode2 = h("div");
patch(vnode0, vnode1);
patch(vnode1, vnode2);
@@ -1196,10 +1084,7 @@ describe("snabbdom", function() {
function cb(vnode) {
result.push(vnode);
}
const vnode1 = h("div", [
h("span", { hook: { update: cb } }, "Hello"),
h("span", "there")
]);
const vnode1 = h("div", [h("span", { hook: { update: cb } }, "Hello"), h("span", "there")]);
patch(vnode0, vnode1);
patch(vnode1, vnode1);
expect(result).toHaveLength(0);
+2 -11
View File
@@ -1,9 +1,4 @@
import {
buildData,
startMeasure,
stopMeasure,
formatNumber
} from "../shared/utils.js";
import { buildData, startMeasure, stopMeasure, formatNumber } from "../shared/utils.js";
//------------------------------------------------------------------------------
// Likes Counter Widget
@@ -40,11 +35,7 @@ class App extends owl.Component {
state = { messages: [], multipleFlag: false, clearAfterFlag: false };
mounted() {
this.log(
`Benchmarking Owl v${owl.__info__.version} (build date: ${
owl.__info__.date
})`
);
this.log(`Benchmarking Owl v${owl.__info__.version} (build date: ${owl.__info__.date})`);
}
benchmark(message, fn, callback) {
+2 -11
View File
@@ -1,9 +1,4 @@
import {
buildData,
startMeasure,
stopMeasure,
formatNumber
} from "../shared/utils.js";
import { buildData, startMeasure, stopMeasure, formatNumber } from "../shared/utils.js";
//------------------------------------------------------------------------------
// Likes Counter Widget
@@ -40,11 +35,7 @@ class App extends owl.Component {
state = { messages: [], multipleFlag: false, clearAfterFlag: false };
mounted() {
this.log(
`Benchmarking Owl v${owl.__info__.version} (build date: ${
owl.__info__.date
})`
);
this.log(`Benchmarking Owl v${owl.__info__.version} (build date: ${owl.__info__.date})`);
}
benchmark(message, fn, callback) {
+2 -11
View File
@@ -1,9 +1,4 @@
import {
buildData,
startMeasure,
stopMeasure,
formatNumber
} from "../shared/utils.js";
import { buildData, startMeasure, stopMeasure, formatNumber } from "../shared/utils.js";
//------------------------------------------------------------------------------
// Likes Counter Widget
@@ -40,11 +35,7 @@ class App extends owl.Component {
state = { messages: [], multipleFlag: false, clearAfterFlag: false };
mounted() {
this.log(
`Benchmarking Owl v${owl.__info__.version} (build date: ${
owl.__info__.date
})`
);
this.log(`Benchmarking Owl v${owl.__info__.version} (build date: ${owl.__info__.date})`);
}
benchmark(message, fn, callback) {
+3 -14
View File
@@ -1,9 +1,4 @@
import {
buildData,
startMeasure,
stopMeasure,
formatNumber
} from "../shared/utils.js";
import { buildData, startMeasure, stopMeasure, formatNumber } from "../shared/utils.js";
//------------------------------------------------------------------------------
// Likes Counter Widget
@@ -40,11 +35,7 @@ class App extends owl.Component {
state = { messages: [], multipleFlag: false, clearAfterFlag: false };
mounted() {
this.log(
`Benchmarking Owl v${owl.__info__.version} (build date: ${
owl.__info__.date
})`
);
this.log(`Benchmarking Owl v${owl.__info__.version} (build date: ${owl.__info__.date})`);
}
benchmark(message, fn, callback) {
@@ -128,9 +119,7 @@ class App extends owl.Component {
removeMessage(event) {
this.benchmark("remove message", () => {
const index = this.state.messages.findIndex(
m => m.id === event.detail.id
);
const index = this.state.messages.findIndex(m => m.id === event.detail.id);
this.state.messages.splice(index, 1);
});
}
+1 -1
View File
@@ -51,7 +51,7 @@ export function stopMeasure(cb) {
const msg = `[${last}] took ${formatNumber(delta)}ms`;
console.log(msg);
if (cb) {
cb({msg, delta});
cb({ msg, delta });
}
}, 0);
}
+1 -4
View File
@@ -97,10 +97,7 @@ function makeCodeIframe(js, css, xml, errorHandler) {
setTimeout(function() {
if (iframe.contentWindow) {
iframe.contentWindow.removeEventListener("error", errorHandler);
iframe.contentWindow.removeEventListener(
"unhandledrejection",
errorHandler
);
iframe.contentWindow.removeEventListener("unhandledrejection", errorHandler);
}
}, 200);
doc.body.appendChild(script);
+1 -1
View File
@@ -1351,7 +1351,7 @@ export const SAMPLES = [
description: "Lifecycle demo",
code: LIFECYCLE_DEMO,
xml: LIFECYCLE_DEMO_XML,
css: LIFECYCLE_CSS,
css: LIFECYCLE_CSS
},
{
description: "Todo List App (with store)",