mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[REF] blockdom,compiler: implement properties
Before this commit, properties were just handled as a special case of attributes. But it does not make that much sense, since they are different. For example, the `readOnly` property does not have the same name as the `readonly` attribute. The confusion probably comes from the fact that QWeb does not distinguish between property and attributes, so Owl has to infer which one is which. With this commit, we introduce a `block-property` directive in blockdom, and change the compiler to use it in emitted code. It has the additional benefits of slightly shrinking the runtime code, since the `isProp` function can now be located in the compiler.
This commit is contained in:
committed by
Sam Degueldre
parent
f0fb3ab64e
commit
f892929c80
@@ -140,33 +140,3 @@ export function updateClass(this: HTMLElement, val: any, oldVal: any) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function makePropSetter(name: string): Setter<HTMLElement> {
|
||||
return function setProp(this: HTMLElement, value: any) {
|
||||
// support 0, fallback to empty string for other falsy values
|
||||
(this as any)[name] = value === 0 ? 0 : value ? value.valueOf() : "";
|
||||
};
|
||||
}
|
||||
|
||||
export function isProp(tag: string, key: string): boolean {
|
||||
switch (tag) {
|
||||
case "input":
|
||||
return (
|
||||
key === "checked" ||
|
||||
key === "indeterminate" ||
|
||||
key === "value" ||
|
||||
key === "readonly" ||
|
||||
key === "disabled"
|
||||
);
|
||||
case "option":
|
||||
return key === "selected" || key === "disabled";
|
||||
case "textarea":
|
||||
return key === "value" || key === "readonly" || key === "disabled";
|
||||
case "select":
|
||||
return key === "value" || key === "disabled";
|
||||
case "button":
|
||||
case "optgroup":
|
||||
return key === "disabled";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
import { OwlError } from "../error_handling";
|
||||
import {
|
||||
attrsSetter,
|
||||
attrsUpdater,
|
||||
createAttrUpdater,
|
||||
isProp,
|
||||
makePropSetter,
|
||||
setClass,
|
||||
updateClass,
|
||||
} from "./attributes";
|
||||
import { attrsSetter, attrsUpdater, createAttrUpdater, setClass, updateClass } from "./attributes";
|
||||
import { config } from "./config";
|
||||
import { createEventHandler } from "./events";
|
||||
import type { VNode } from "./index";
|
||||
@@ -25,6 +17,13 @@ const nodeGetNextSibling = getDescriptor(nodeProto, "nextSibling").get!;
|
||||
|
||||
const NO_OP = () => {};
|
||||
|
||||
function makePropSetter(name: string): Setter<HTMLElement> {
|
||||
return function setProp(this: HTMLElement, value: any) {
|
||||
// support 0, fallback to empty string for other falsy values
|
||||
(this as any)[name] = value === 0 ? 0 : value ? value.valueOf() : "";
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Main compiler code
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -101,7 +100,7 @@ function normalizeNode(node: HTMLElement | Text) {
|
||||
interface DynamicInfo {
|
||||
idx: number;
|
||||
refIdx?: number;
|
||||
type: "text" | "child" | "handler" | "attribute" | "attributes" | "ref";
|
||||
type: "text" | "child" | "handler" | "attribute" | "attributes" | "property" | "ref";
|
||||
isOnlyChild?: boolean;
|
||||
name?: string;
|
||||
tag?: string;
|
||||
@@ -184,6 +183,14 @@ function buildTree(
|
||||
name: attrValue,
|
||||
tag: tagName,
|
||||
});
|
||||
} else if (attrName.startsWith("block-property-")) {
|
||||
const idx = parseInt(attrName.slice(15), 10);
|
||||
info.push({
|
||||
type: "property",
|
||||
idx,
|
||||
name: attrValue,
|
||||
tag: tagName,
|
||||
});
|
||||
} else if (attrName === "block-attributes") {
|
||||
info.push({
|
||||
type: "attributes",
|
||||
@@ -377,15 +384,22 @@ function updateCtx(ctx: BlockCtx, tree: IntermediateTree) {
|
||||
};
|
||||
}
|
||||
break;
|
||||
case "property": {
|
||||
const refIdx = info.refIdx!;
|
||||
const setProp = makePropSetter(info.name!);
|
||||
ctx.locations.push({
|
||||
idx: info.idx,
|
||||
refIdx,
|
||||
setData: setProp,
|
||||
updateData: setProp,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "attribute": {
|
||||
const refIdx = info.refIdx!;
|
||||
let updater: any;
|
||||
let setter: any;
|
||||
if (isProp(info.tag!, info.name!)) {
|
||||
const setProp = makePropSetter(info.name!);
|
||||
setter = setProp;
|
||||
updater = setProp;
|
||||
} else if (info.name === "class") {
|
||||
if (info.name === "class") {
|
||||
setter = setClass;
|
||||
updater = updateClass;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user