Compare commits

...

9 Commits

Author SHA1 Message Date
Géry Debongnie 83d4471048 [REL] v2.0.0-beta-9
# v2.0.0-beta-9

Fixes

- event: no crash when using t-on + modifier on slots/components
- component: fix props comparison code
- component: fix wrong behaviour when using t-on on t-component
- component: props values are own property of props object
- t-out: allow expressions evaluating as number
- compiler: add support for #{...} in string interpolation

Improvements

- slots: add support for t-props on slots props
- tooling: add another d.ts file
2022-06-09 14:32:13 +02:00
Simon Genin (ges) 8a967e5b2d [IMP] tooling: add another d.ts file 2022-06-09 14:21:34 +02:00
Géry Debongnie 385e118e58 [FIX] compiler: add support for #{...} in string interpolation 2022-06-08 10:54:30 +02:00
Géry Debongnie a3111eb9ca [FIX] t-out: allow expressions evaluating as number 2022-06-07 13:23:29 +02:00
Géry Debongnie 1fc88f626f [IMP] slots: add support for t-props on slots props 2022-06-07 09:30:45 +02:00
Géry Debongnie 5d5a530505 [FIX] component: props values are own property of props object 2022-06-03 16:41:31 +02:00
Géry Debongnie c7bd0ab85c [FIX] component: fix wrong behaviour when using t-on on t-component
Before this commit, using t-on on t-component was not correctly
implemented by owl: when more than one component shared the same
parentelement and have an handler with the same name, the second handler
would override the first (using an internal key). With this commit, we
simply recreate event handler for each instance of a catcher block. Note
that it means that using t-on on components is slightly slower now.

Also, this commit fixes an additional issue that was noticed: the
catcher block would not update its internal handler properly, so it
would not behave properly after being patched.

closes #1199
2022-06-03 16:12:56 +02:00
Géry Debongnie 31b57cbb40 [FIX] component: fix props comparison code
Before this commit, Owl had a bad interaction with the static
defaultProps code. The props comparison would be done with the new props
object (unmodified) and the current props object (with default props
applied), so the comparison would always return false, which in turn,
causes additional useless renderings.

This commit modifies component node to keep a reference to the
(unmodified) props object so we can compare it as expected.
2022-06-03 15:51:58 +02:00
Géry Debongnie 31fce0926c [FIX] event: no crash when using t-on + modifier on slots/components
closes #1185
2022-06-01 09:58:49 +02:00
35 changed files with 742 additions and 205 deletions
+6
View File
@@ -239,6 +239,12 @@ And the child component that includes the slot can provide values like this:
<t t-slot="foo" bool="other_var" num="5">
```
or this:
```xml
<t t-slot="foo" t-props="someObject">
```
In the case of the default slot, you may declare the slot scope directly on the
component itself:
+3 -2
View File
@@ -290,10 +290,11 @@ If an expression evaluates to a falsy value, it will not be set at all:
It is sometimes convenient to format an attribute with string interpolation. In
that case, the `t-attf-` directive can be used. It is useful when we need to mix
literal and dynamic elements, such as css classes.
literal and dynamic elements, such as css classes. The dynamic elements can be
specified with either `{{...}}` or `#{...}`:
```xml
<div t-attf-foo="a {{value1}} is {{value2}} of {{value3}} ]"/>
<div t-attf-foo="a {{value1}} is #{value2} of {{value3}} ]"/>
<!-- result if values are set to 1,2 and 3: <div foo="a 0 is 1 of 2 ]"></div> -->
```
+3 -2
View File
@@ -1,11 +1,11 @@
{
"name": "@odoo/owl",
"version": "2.0.0-beta-8",
"version": "2.0.0-beta-9",
"description": "Odoo Web Library (OWL)",
"main": "dist/owl.cjs.js",
"browser": "dist/owl.iife.js",
"module": "dist/owl.es.js",
"types": "dist/types/index.d.ts",
"types": "dist/types/owl.d.ts",
"files": [
"dist"
],
@@ -55,6 +55,7 @@
"npm-run-all": "^4.1.5",
"prettier": "2.4.1",
"rollup": "^2.56.3",
"rollup-plugin-dts": "^4.2.2",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.31.1",
"sass": "^1.16.1",
+17 -10
View File
@@ -2,7 +2,7 @@ import pkg from "./package.json";
import git from "git-rev-sync";
import typescript from 'rollup-plugin-typescript2';
import { terser } from "rollup-plugin-terser";
import dts from "rollup-plugin-dts";
let input, output;
@@ -68,12 +68,19 @@ function getConfigForFormat(format, generatedFileName, outro, minified = false)
};
}
export default {
input,
output,
plugins: [
typescript({
useTsconfigDeclarationDir: true
}),
]
};
export default [
{
input,
output,
plugins: [
typescript({
useTsconfigDeclarationDir: true
}),
]
},
{
input: "dist/types/index.d.ts",
output: [{ file: "dist/types/owl.d.ts", format: "es" }],
plugins: [dts()],
},
];
+29 -27
View File
@@ -1,4 +1,10 @@
import { compileExpr, compileExprToArray, interpolate, INTERP_REGEXP } from "./inline_expressions";
import {
compileExpr,
compileExprToArray,
interpolate,
INTERP_REGEXP,
replaceDynamicParts,
} from "./inline_expressions";
import {
AST,
ASTComment,
@@ -606,11 +612,8 @@ export class CodeGenerator {
this.target.hasRef = true;
const isDynamic = INTERP_REGEXP.test(ast.ref);
if (isDynamic) {
const str = ast.ref.replace(
INTERP_REGEXP,
(expr) => "${" + this.captureExpression(expr.slice(2, -2), true) + "}"
);
const idx = block!.insertData(`(el) => refs[\`${str}\`] = el`, "ref");
const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
const idx = block!.insertData(`(el) => refs[${str}] = el`, "ref");
attrs["block-ref"] = String(idx);
} else {
let name = ast.ref;
@@ -1083,23 +1086,25 @@ export class CodeGenerator {
return `${name}: ${value || undefined}`;
}
formatPropObject(obj: { [prop: string]: any }): string {
const params = [];
for (const [n, v] of Object.entries(obj)) {
params.push(this.formatProp(n, v));
formatPropObject(obj: { [prop: string]: any }): string[] {
return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
}
getPropString(props: string[], dynProps: string | null): string {
let propString = `{${props.join(",")}}`;
if (dynProps) {
propString = `Object.assign({}, ${compileExpr(dynProps)}${
props.length ? ", " + propString : ""
})`;
}
return params.join(", ");
return propString;
}
compileComponent(ast: ASTComponent, ctx: Context) {
let { block } = ctx;
// props
const hasSlotsProp = "slots" in (ast.props || {});
const props: string[] = [];
const propExpr = this.formatPropObject(ast.props || {});
if (propExpr) {
props.push(propExpr);
}
const props: string[] = ast.props ? this.formatPropObject(ast.props) : [];
// slots
let slotDef: string = "";
@@ -1123,7 +1128,7 @@ export class CodeGenerator {
params.push(`__scope: "${scope}"`);
}
if (ast.slots[slotName].attrs) {
params.push(this.formatPropObject(ast.slots[slotName].attrs!));
params.push(...this.formatPropObject(ast.slots[slotName].attrs!));
}
const slotInfo = `{${params.join(", ")}}`;
slotStr.push(`'${slotName}': ${slotInfo}`);
@@ -1136,14 +1141,7 @@ export class CodeGenerator {
props.push(`slots: markRaw(${slotDef})`);
}
const propStr = `{${props.join(",")}}`;
let propString = propStr;
if (ast.dynamicProps) {
propString = `Object.assign({}, ${compileExpr(ast.dynamicProps)}${
props.length ? ", " + propStr : ""
})`;
}
let propString = this.getPropString(props, ast.dynamicProps);
let propVar: string;
if ((slotDef && (ast.dynamicProps || hasSlotsProp)) || this.dev) {
@@ -1223,8 +1221,12 @@ export class CodeGenerator {
} else {
slotName = "'" + ast.name + "'";
}
const scope = ast.attrs ? `{${this.formatPropObject(ast.attrs)}}` : null;
const dynProps = ast.attrs ? ast.attrs["t-props"] : null;
if (ast.attrs) {
delete ast.attrs["t-props"];
}
const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
const scope = this.getPropString(props, dynProps);
if (ast.defaultContent) {
const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope}, ${name})`;
+10 -5
View File
@@ -355,15 +355,20 @@ export function compileExpr(expr: string): string {
.join("");
}
export const INTERP_REGEXP = /\{\{.*?\}\}/g;
const INTERP_GROUP_REGEXP = /\{\{.*?\}\}/g;
export const INTERP_REGEXP = /\{\{.*?\}\}|\#\{.*?\}/g;
export function interpolate(s: string): string {
export function replaceDynamicParts(s: string, replacer: (s: string) => string) {
let matches = s.match(INTERP_REGEXP);
if (matches && matches[0].length === s.length) {
return `(${compileExpr(s.slice(2, -2))})`;
return `(${replacer(s.slice(2, matches[0][0] === "{" ? -2 : -1))})`;
}
let r = s.replace(INTERP_GROUP_REGEXP, (s) => "${" + compileExpr(s.slice(2, -2)) + "}");
let r = s.replace(
INTERP_REGEXP,
(s) => "${" + replacer(s.slice(2, s[0] === "{" ? -2 : -1)) + "}"
);
return "`" + r + "`";
}
export function interpolate(s: string): string {
return replaceDynamicParts(s, compileExpr);
}
+31 -19
View File
@@ -6,36 +6,43 @@ type EventsSpec = { [name: string]: number };
type Catcher = (child: VNode, handlers: any[]) => VNode;
export function createCatcher(eventsSpec: EventsSpec): Catcher {
let setupFns: any[] = [];
let removeFns: any[] = [];
for (let name in eventsSpec) {
let index = eventsSpec[name];
let { setup, remove } = createEventHandler(name);
setupFns[index] = setup;
removeFns[index] = remove;
}
let n = setupFns.length;
const n = Object.keys(eventsSpec).length;
class VCatcher {
child: VNode;
handlers: any[];
handlerData: any[];
handlerFns: any[] = [];
parentEl?: HTMLElement | undefined;
afterNode: Node | null = null;
afterNode: Text | null = null;
constructor(child: VNode, handlers: any[]) {
this.child = child;
this.handlers = handlers;
this.handlerData = handlers;
}
mount(parent: HTMLElement, afterNode: Node | null) {
this.parentEl = parent;
this.afterNode = afterNode;
this.child.mount(parent, afterNode);
this.afterNode = document.createTextNode("");
parent.insertBefore(this.afterNode, afterNode);
this.wrapHandlerData();
for (let name in eventsSpec) {
const index = eventsSpec[name];
const handler = createEventHandler(name);
this.handlerFns[index] = handler;
handler.setup.call(parent, this.handlerData[index]);
}
}
wrapHandlerData() {
for (let i = 0; i < n; i++) {
let origFn = this.handlers[i][0];
let handler = this.handlerData[i];
// handler = [...mods, fn, comp], so we need to replace second to last elem
let idx = handler.length - 2;
let origFn = handler[idx];
const self = this;
this.handlers[i][0] = function (ev: any) {
handler[idx] = function (ev: any) {
const target = ev.target;
let currentNode: any = self.child.firstNode();
const afterNode = self.afterNode;
@@ -46,20 +53,24 @@ export function createCatcher(eventsSpec: EventsSpec): Catcher {
currentNode = currentNode.nextSibling;
}
};
setupFns[i].call(parent, this.handlers[i]);
}
}
moveBefore(other: VCatcher | null, afterNode: Node | null) {
this.afterNode = null;
this.child.moveBefore(other ? other.child : null, afterNode);
this.parentEl!.insertBefore(this.afterNode!, afterNode);
}
patch(other: VCatcher, withBeforeRemove: boolean) {
if (this === other) {
return;
}
this.handlers = other.handlers;
this.handlerData = other.handlerData;
this.wrapHandlerData();
for (let i = 0; i < n; i++) {
this.handlerFns[i].update.call(this.parentEl!, this.handlerData[i]);
}
this.child.patch(other.child, withBeforeRemove);
}
@@ -69,9 +80,10 @@ export function createCatcher(eventsSpec: EventsSpec): Catcher {
remove() {
for (let i = 0; i < n; i++) {
removeFns[i].call(this.parentEl!);
this.handlerFns[i].remove.call(this.parentEl!);
}
this.child.remove();
this.afterNode!.remove();
}
firstNode(): Node | undefined {
+12 -8
View File
@@ -30,15 +30,15 @@ export function useComponent(): Component {
/**
* Apply default props (only top level).
*
* Note that this method does modify in place the props
*/
function applyDefaultProps<P>(props: P, defaultProps: Partial<P>) {
function applyDefaultProps<P extends object>(props: P, defaultProps: Partial<P>): P {
const result = Object.assign({} as any, props);
for (let propName in defaultProps) {
if ((props as any)[propName] === undefined) {
(props as any)[propName] = defaultProps[propName];
if (props[propName] === undefined) {
result[propName] = defaultProps[propName];
}
}
return result;
}
// -----------------------------------------------------------------------------
// Integration with reactivity system (useState)
@@ -106,7 +106,7 @@ export function component<P extends Props>(
if (shouldRender) {
node.forceNextRender = false;
} else {
const currentProps = node.component.props;
const currentProps = node.props;
shouldRender = parentFiber.deep || arePropsDifferent(currentProps, props);
}
if (shouldRender) {
@@ -148,6 +148,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
status: STATUS = STATUS.NEW;
forceNextRender: boolean = false;
parentKey: string | null;
props: P;
renderFn: Function;
parent: ComponentNode | null;
@@ -174,11 +175,12 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
currentNode = this;
this.app = app;
this.parent = parent;
this.props = props;
this.parentKey = parentKey;
this.level = parent ? parent.level + 1 : 0;
const defaultProps = C.defaultProps;
if (defaultProps) {
applyDefaultProps(props, defaultProps);
props = applyDefaultProps(props, defaultProps);
}
const env = (parent && parent.childEnv) || app.env;
this.childEnv = env;
@@ -294,13 +296,14 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
}
async updateAndRender(props: P, parentFiber: Fiber) {
const rawProps = props;
// update
const fiber = makeChildFiber(this, parentFiber);
this.fiber = fiber;
const component = this.component;
const defaultProps = (component.constructor as any).defaultProps;
if (defaultProps) {
applyDefaultProps(props, defaultProps);
props = applyDefaultProps(props, defaultProps);
}
currentNode = this;
@@ -317,6 +320,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
return;
}
component.props = props;
this.props = rawProps;
fiber.render();
const parentRoot = parentFiber.root!;
if (this.willPatch.length) {
+24 -13
View File
@@ -132,19 +132,30 @@ export function safeOutput(value: any): ReturnType<typeof toggler> {
}
let safeKey;
let block;
if (value instanceof Markup) {
safeKey = `string_safe`;
block = html(value as string);
} else if (value instanceof LazyValue) {
safeKey = `lazy_value`;
block = value.evaluate();
} else if (value instanceof String || typeof value === "string") {
safeKey = "string_unsafe";
block = text(value);
} else {
// Assuming it is a block
safeKey = "block_safe";
block = value;
switch (typeof value) {
case "object":
if (value instanceof Markup) {
safeKey = `string_safe`;
block = html(value as string);
} else if (value instanceof LazyValue) {
safeKey = `lazy_value`;
block = value.evaluate();
} else if (value instanceof String) {
safeKey = "string_unsafe";
block = text(value);
} else {
// Assuming it is a block
safeKey = "block_safe";
block = value;
}
break;
case "string":
safeKey = "string_unsafe";
block = text(value);
break;
default:
safeKey = "string_unsafe";
block = text(String(value));
}
return toggler(safeKey, block);
}
@@ -387,6 +387,20 @@ exports[`attributes static attributes with dashes 1`] = `
}"
`;
exports[`attributes string interpolation, alternate syntax 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = \`b\${ctx['value']}r\`;
return block1([attr1]);
}
}"
`;
exports[`attributes t-att-class and class should combine together 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -34,7 +34,7 @@ exports[`misc complex template 1`] = `
for (let i1 = 0; i1 < l_block4; i1++) {
ctx[\`slot\`] = v_block4[i1];
const key1 = ctx['slot'].id;
c_block4[i1] = withKey(component(\`SlotButton\`, {class: ctx['slot_container'], slot: ctx['slot']}, key + \`__1__\${key1}\`, node, ctx), key1);
c_block4[i1] = withKey(component(\`SlotButton\`, {class: ctx['slot_container'],slot: ctx['slot']}, key + \`__1__\${key1}\`, node, ctx), key1);
}
ctx = ctx.__proto__;
b4 = list(c_block4);
@@ -316,8 +316,8 @@ exports[`misc other complex template 1`] = `
if (!ctx['project']) {
b24 = block24();
} else {
const b26 = component(\`BundlesList\`, {bundles: ctx['bundles'].sticky, category_custom_views: ctx['category_custom_views'], search: ctx['search']}, key + \`__2\`, node, ctx);
const b27 = component(\`BundlesList\`, {bundles: ctx['bundles'].dev, search: ctx['search']}, key + \`__3\`, node, ctx);
const b26 = component(\`BundlesList\`, {bundles: ctx['bundles'].sticky,category_custom_views: ctx['category_custom_views'],search: ctx['search']}, key + \`__2\`, node, ctx);
const b27 = component(\`BundlesList\`, {bundles: ctx['bundles'].dev,search: ctx['search']}, key + \`__3\`, node, ctx);
b25 = block25([], [b26, b27]);
}
return block1([attr1, txt1, hdlr2, hdlr3, attr8, hdlr4, hdlr5, ref1, hdlr6, ref2], [b2, b4, b14, b17, b22, b23, b24, b25]);
@@ -79,6 +79,21 @@ exports[`t-out not escaping 1`] = `
}"
`;
exports[`t-out number literal 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = safeOutput(1);
return block1([], [b2]);
}
}"
`;
exports[`t-out t-out 0 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -16,6 +16,22 @@ exports[`t-ref can get a dynamic ref on a node 1`] = `
}"
`;
exports[`t-ref can get a dynamic ref on a node, alternate syntax 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><span block-ref=\\"0\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs;
const v1 = ctx['id'];
let ref1 = (el) => refs[\`myspan\${v1}\`] = el;
return block1([ref1]);
}
}"
`;
exports[`t-ref can get a ref on a node 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -99,7 +115,7 @@ exports[`t-ref refs in a loop 1`] = `
const key1 = ctx['item'];
const tKey_1 = ctx['item'];
const v1 = ctx['item'];
let ref1 = (el) => refs[\`\${v1}\`] = el;
let ref1 = (el) => refs[(v1)] = el;
let txt1 = ctx['item'];
c_block2[i1] = withKey(block3([ref1, txt1]), tKey_1 + key1);
}
+6
View File
@@ -131,6 +131,12 @@ describe("attributes", () => {
expect(result).toBe(`<div foo="bar"></div>`);
});
test("string interpolation, alternate syntax", () => {
const template = `<div t-attf-foo="b#{value}r"/>`;
const result = renderToString(template, { value: "a" });
expect(result).toBe(`<div foo="bar"></div>`);
});
test("t-attf-class", () => {
const template = `<div t-attf-class="hello"/>`;
const result = renderToString(template);
+5
View File
@@ -27,6 +27,11 @@ describe("t-out", () => {
expect(renderToString(template)).toBe("<span>ok</span>");
});
test("number literal", () => {
const template = `<span><t t-out="1"/></span>`;
expect(renderToString(template)).toBe("<span>1</span>");
});
test("literal, no outside html element", () => {
const template = `<t t-out="'ok'"/>`;
expect(renderToString(template)).toBe("ok");
+9
View File
@@ -27,6 +27,15 @@ describe("t-ref", () => {
expect(refs.myspan3.tagName).toBe("SPAN");
});
test("can get a dynamic ref on a node, alternate syntax", () => {
const template = `<div><span t-ref="myspan#{id}"/></div>`;
const refs: any = {};
const bdom = renderToBdom(template, { id: 3, __owl__: { refs } });
expect(refs).toEqual({});
mount(bdom, document.createElement("div"));
expect(refs.myspan3.tagName).toBe("SPAN");
});
test("refs in a loop", () => {
const template = `<div>
<t t-foreach="items" t-as="item" t-key="item">
@@ -551,6 +551,32 @@ exports[`basics props is set on root component 1`] = `
}"
`;
exports[`basics props value are own property of props object 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<span>simple vnode</span>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`basics props value are own property of props object, even with default values 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<span>simple vnode</span>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`basics reconciliation alg is not confused in some specific situation 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -993,7 +1019,7 @@ exports[`basics update props of component without concrete own node 2`] = `
return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['props'].subKey;
return toggler(tKey_1, component(\`Custom\`, {key: ctx['props'].key, subKey: ctx['props'].subKey}, tKey_1 + key + \`__1\`, node, ctx));
return toggler(tKey_1, component(\`Custom\`, {key: ctx['props'].key,subKey: ctx['props'].subKey}, tKey_1 + key + \`__1\`, node, ctx));
}
}"
`;
@@ -227,7 +227,7 @@ exports[`concurrent renderings scenario 1 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`ComponentC\`, {fromA: ctx['props'].fromA, fromB: ctx['state'].fromB}, key + \`__1\`, node, ctx);
const b2 = component(\`ComponentC\`, {fromA: ctx['props'].fromA,fromB: ctx['state'].fromB}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
@@ -271,7 +271,7 @@ exports[`concurrent renderings scenario 2 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`ComponentC\`, {fromA: ctx['props'].fromA, fromB: ctx['state'].fromB}, key + \`__1\`, node, ctx);
const b2 = component(\`ComponentC\`, {fromA: ctx['props'].fromA,fromB: ctx['state'].fromB}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
@@ -314,7 +314,7 @@ exports[`concurrent renderings scenario 2bis 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`ComponentC\`, {fromA: ctx['props'].fromA, fromB: ctx['state'].fromB}, key + \`__1\`, node, ctx);
const b2 = component(\`ComponentC\`, {fromA: ctx['props'].fromA,fromB: ctx['state'].fromB}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
@@ -371,7 +371,7 @@ exports[`concurrent renderings scenario 3 3`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`ComponentD\`, {fromA: ctx['props'].fromA, fromC: ctx['state'].fromC}, key + \`__1\`, node, ctx);
const b2 = component(\`ComponentD\`, {fromA: ctx['props'].fromA,fromC: ctx['state'].fromC}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
@@ -428,7 +428,7 @@ exports[`concurrent renderings scenario 4 3`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`ComponentD\`, {fromA: ctx['props'].fromA, fromC: ctx['state'].fromC}, key + \`__1\`, node, ctx);
const b2 = component(\`ComponentD\`, {fromA: ctx['props'].fromA,fromC: ctx['state'].fromC}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
@@ -601,7 +601,7 @@ exports[`concurrent renderings scenario 9 3`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`ComponentD\`, {fromA: ctx['props'].fromA, fromC: ctx['state'].fromC}, key + \`__1\`, node, ctx);
const b2 = component(\`ComponentD\`, {fromA: ctx['props'].fromA,fromC: ctx['state'].fromC}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
@@ -778,7 +778,7 @@ exports[`concurrent renderings scenario 14 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`C\`, {fromB: ctx['state'].fromB, fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx);
const b2 = component(\`C\`, {fromB: ctx['state'].fromB,fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
@@ -822,7 +822,7 @@ exports[`concurrent renderings scenario 15 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`C\`, {fromB: ctx['state'].fromB, fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx);
const b2 = component(\`C\`, {fromB: ctx['state'].fromB,fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
@@ -861,7 +861,7 @@ exports[`concurrent renderings scenario 16 2`] = `
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`C\`, {fromB: ctx['state'].fromB, fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx);
return component(\`C\`, {fromB: ctx['state'].fromB,fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx);
}
}"
`;
@@ -197,7 +197,7 @@ exports[`can catch errors can catch an error in a component render function 2`]
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -250,7 +250,7 @@ exports[`can catch errors can catch an error in the constructor call of a compon
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -291,7 +291,7 @@ exports[`can catch errors can catch an error in the constructor call of a compon
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -369,7 +369,7 @@ exports[`can catch errors can catch an error in the initial call of a component
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -425,7 +425,7 @@ exports[`can catch errors can catch an error in the initial call of a component
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -567,7 +567,7 @@ exports[`can catch errors can catch an error in the mounted call 2`] = `
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -620,7 +620,7 @@ exports[`can catch errors can catch an error in the willPatch call 2`] = `
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -673,7 +673,7 @@ exports[`can catch errors can catch an error in the willStart call 2`] = `
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -727,7 +727,7 @@ exports[`can catch errors can catch an error origination from a child's willStar
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -840,7 +840,7 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -915,7 +915,7 @@ exports[`can catch errors catching in child makes parent render 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -991,7 +991,7 @@ exports[`can catch errors error in mounted on a component with a sibling (proper
if (ctx['state'].error) {
b2 = text(\`Error handled\`);
} else {
b3 = callSlot(ctx, node, key, 'default', false, null);
b3 = callSlot(ctx, node, key, 'default', false, {});
}
return block1([], [b2, b3]);
}
@@ -273,7 +273,7 @@ exports[`bound functions is referentially equal after update 1`] = `
let { bind } = helpers;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {val: ctx['state'].val, fn: bind(ctx, ctx['someFunction'])}, key + \`__1\`, node, ctx);
return component(\`Child\`, {val: ctx['state'].val,fn: bind(ctx, ctx['someFunction'])}, key + \`__1\`, node, ctx);
}
}"
`;
@@ -115,7 +115,7 @@ exports[`props validation can specify that additional props are allowed (array)
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const props1 = {message: 'm', otherProp: 'o'};
const props1 = {message: 'm',otherProp: 'o'};
helpers.validateProps(\`Child\`, props1, ctx);
return component(\`Child\`, props1, key + \`__1\`, node, ctx);
}
@@ -141,7 +141,7 @@ exports[`props validation can specify that additional props are allowed (object)
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const props1 = {message: 'm', otherProp: 'o'};
const props1 = {message: 'm',otherProp: 'o'};
helpers.validateProps(\`Child\`, props1, ctx);
return component(\`Child\`, props1, key + \`__1\`, node, ctx);
}
@@ -32,7 +32,7 @@ exports[`reactivity in lifecycle Component is automatically subscribed to reacti
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {obj: ctx['obj'], reactiveObj: ctx['reactiveObj']}, key + \`__1\`, node, ctx);
return component(\`Child\`, {obj: ctx['obj'],reactiveObj: ctx['reactiveObj']}, key + \`__1\`, node, ctx);
}
}"
`;
@@ -92,7 +92,7 @@ exports[`refs refs are properly bound in slots 2`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'footer', false, null);
const b2 = callSlot(ctx, node, key, 'footer', false, {});
return block1([], [b2]);
}
}"
@@ -1,5 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`children, default props and renderings 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['state'].value);
const b3 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
return multi([b2, b3]);
}
}"
`;
exports[`children, default props and renderings 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`child\`);
}
}"
`;
exports[`force render in case of existing render 1`] = `
"function anonymous(app, bdom, helpers
) {
+114 -78
View File
@@ -27,7 +27,7 @@ exports[`slots can define a default content 2`] = `
}
return function template(ctx, node, key = \\"\\") {
const b3 = callSlot(ctx, node, key, 'default', false, null, defaultContent1);
const b3 = callSlot(ctx, node, key, 'default', false, {}, defaultContent1);
return block1([], [b3]);
}
}"
@@ -68,8 +68,8 @@ exports[`slots can define and call slots 2`] = `
let block1 = createBlock(\`<div><div><block-child-0/></div><div><block-child-1/></div></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'header', false, null);
const b3 = callSlot(ctx, node, key, 'footer', false, null);
const b2 = callSlot(ctx, node, key, 'header', false, {});
const b3 = callSlot(ctx, node, key, 'footer', false, {});
return block1([], [b2, b3]);
}
}"
@@ -99,7 +99,7 @@ exports[`slots can define and call slots with bound params 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'abc', false, null);
const b2 = callSlot(ctx, node, key, 'abc', false, {});
const b3 = text(ctx['props'].slots['abc'].getValue());
return multi([b2, b3]);
}
@@ -142,9 +142,9 @@ exports[`slots can define and call slots with params 2`] = `
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].slots['header'].param;
const b2 = callSlot(ctx, node, key, 'header', false, null);
const b2 = callSlot(ctx, node, key, 'header', false, {});
let txt2 = ctx['props'].slots['footer'].param;
const b3 = callSlot(ctx, node, key, 'footer', false, null);
const b3 = callSlot(ctx, node, key, 'footer', false, {});
return block1([txt1, txt2], [b2, b3]);
}
}"
@@ -179,7 +179,7 @@ exports[`slots can render node with t-ref and Component in same slot 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -191,7 +191,7 @@ exports[`slots can render only empty slot 1`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -218,7 +218,7 @@ exports[`slots can use component in default-content of t-slot 2`] = `
}
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null, defaultContent1);
return callSlot(ctx, node, key, 'default', false, {}, defaultContent1);
}
}"
`;
@@ -257,7 +257,7 @@ exports[`slots can use t-call in default-content of t-slot 2`] = `
}
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null, defaultContent1);
return callSlot(ctx, node, key, 'default', false, {}, defaultContent1);
}
}"
`;
@@ -298,7 +298,7 @@ exports[`slots content is the default slot (variation) 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -332,7 +332,7 @@ exports[`slots content is the default slot 2`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -371,7 +371,7 @@ exports[`slots default content is not rendered if named slot is provided 2`] = `
}
return function template(ctx, node, key = \\"\\") {
const b3 = callSlot(ctx, node, key, 'header', false, null, defaultContent1);
const b3 = callSlot(ctx, node, key, 'header', false, {}, defaultContent1);
return block1([], [b3]);
}
}"
@@ -409,7 +409,7 @@ exports[`slots default content is not rendered if slot is provided 2`] = `
}
return function template(ctx, node, key = \\"\\") {
const b3 = callSlot(ctx, node, key, 'default', false, null, defaultContent1);
const b3 = callSlot(ctx, node, key, 'default', false, {}, defaultContent1);
return block1([], [b3]);
}
}"
@@ -452,8 +452,8 @@ exports[`slots default slot next to named slot, with default content 2`] = `
}
return function template(ctx, node, key = \\"\\") {
const b3 = callSlot(ctx, node, key, 'default', false, null, defaultContent1);
const b5 = callSlot(ctx, node, key, 'footer', false, null, defaultContent2);
const b3 = callSlot(ctx, node, key, 'default', false, {}, defaultContent1);
const b5 = callSlot(ctx, node, key, 'footer', false, {}, defaultContent2);
return block1([], [b3, b5]);
}
}"
@@ -547,7 +547,7 @@ exports[`slots default slot work with text nodes (variation) 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -580,7 +580,7 @@ exports[`slots default slot work with text nodes 2`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -626,7 +626,7 @@ exports[`slots dynamic t-slot call 2`] = `
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['toggle'], ctx];
const slot1 = (ctx['current'].slot);
const b2 = toggler(slot1, callSlot(ctx, node, key, slot1, true, null));
const b2 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {}));
return block1([hdlr1], [b2]);
}
}"
@@ -675,7 +675,7 @@ exports[`slots dynamic t-slot call with default 2`] = `
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['toggle'], ctx];
const b3 = callSlot(ctx, node, key, (ctx['current'].slot), true, null, defaultContent1);
const b3 = callSlot(ctx, node, key, (ctx['current'].slot), true, {}, defaultContent1);
return block1([hdlr1], [b3]);
}
}"
@@ -704,8 +704,8 @@ exports[`slots fun: two calls to the same slot 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b3 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
const b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]);
}
}"
@@ -734,8 +734,8 @@ exports[`slots missing slots are ignored 2`] = `
let block1 = createBlock(\`<span><block-child-0/><span>some content</span><block-child-1/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b3 = callSlot(ctx, node, key, 'footer', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
const b3 = callSlot(ctx, node, key, 'footer', false, {});
return block1([], [b2, b3]);
}
}"
@@ -844,7 +844,7 @@ exports[`slots mix of slots, t-call, t-call with body, and giving own props chil
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`[C]\`);
const b3 = callSlot(ctx, node, key, 'default', false, null);
const b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]);
}
}"
@@ -882,7 +882,7 @@ exports[`slots multiple roots are allowed in a default slot 2`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -921,7 +921,7 @@ exports[`slots multiple roots are allowed in a named slot 2`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'content', false, null);
const b2 = callSlot(ctx, node, key, 'content', false, {});
return block1([], [b2]);
}
}"
@@ -957,8 +957,8 @@ exports[`slots multiple slots containing components 2`] = `
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 's1', false, null);
const b3 = callSlot(ctx, node, key, 's2', false, null);
const b2 = callSlot(ctx, node, key, 's1', false, {});
const b3 = callSlot(ctx, node, key, 's2', false, {});
return block1([], [b2, b3]);
}
}"
@@ -1020,8 +1020,8 @@ exports[`slots named slot inside slot 2`] = `
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'brol', false, null);
const b3 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'brol', false, {});
const b3 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2, b3]);
}
}"
@@ -1069,8 +1069,8 @@ exports[`slots named slot inside slot, part 3 2`] = `
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'brol', false, null);
const b3 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'brol', false, {});
const b3 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2, b3]);
}
}"
@@ -1103,7 +1103,7 @@ exports[`slots named slots can define a default content 2`] = `
}
return function template(ctx, node, key = \\"\\") {
const b3 = callSlot(ctx, node, key, 'header', false, null, defaultContent1);
const b3 = callSlot(ctx, node, key, 'header', false, {}, defaultContent1);
return block1([], [b3]);
}
}"
@@ -1159,9 +1159,9 @@ exports[`slots named slots inside slot, again 2`] = `
}
return function template(ctx, node, key = \\"\\") {
const b3 = callSlot(ctx, node, key, 'brol1', false, null, defaultContent1);
const b5 = callSlot(ctx, node, key, 'brol2', false, null, defaultContent2);
const b6 = callSlot(ctx, node, key, 'default', false, null);
const b3 = callSlot(ctx, node, key, 'brol1', false, {}, defaultContent1);
const b5 = callSlot(ctx, node, key, 'brol2', false, {}, defaultContent2);
const b6 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b3, b5, b6]);
}
}"
@@ -1199,7 +1199,7 @@ exports[`slots nested slots in same template 2`] = `
let block1 = createBlock(\`<span id=\\"c1\\"><div><block-child-0/></div></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1214,7 +1214,7 @@ exports[`slots nested slots in same template 3`] = `
let block1 = createBlock(\`<span id=\\"c2\\"><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1256,7 +1256,7 @@ exports[`slots nested slots: evaluation context and parented relationship 2`] =
let { callSlot, markRaw } = helpers;
function slot1(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
return function template(ctx, node, key = \\"\\") {
@@ -1274,7 +1274,7 @@ exports[`slots nested slots: evaluation context and parented relationship 3`] =
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1314,7 +1314,7 @@ exports[`slots no named slot content => just no children 2`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'header', false, null);
const b2 = callSlot(ctx, node, key, 'header', false, {});
return block1([], [b2]);
}
}"
@@ -1345,7 +1345,7 @@ exports[`slots simple default slot 2`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1439,7 +1439,7 @@ exports[`slots simple default slot, variation 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -1509,7 +1509,7 @@ exports[`slots simple named and empty slot -- 2 2`] = `
}
return function template(ctx, node, key = \\"\\") {
const b3 = callSlot(ctx, node, key, 'myEmptySlot', false, null, defaultContent1);
const b3 = callSlot(ctx, node, key, 'myEmptySlot', false, {}, defaultContent1);
return block1([], [b3]);
}
}"
@@ -1541,8 +1541,8 @@ exports[`slots simple named and empty slot 2`] = `
let block1 = createBlock(\`<span><block-child-0/><block-child-1/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b3 = callSlot(ctx, node, key, 'myEmptySlot', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
const b3 = callSlot(ctx, node, key, 'myEmptySlot', false, {});
return block1([], [b2, b3]);
}
}"
@@ -1629,7 +1629,7 @@ exports[`slots slot and (inline) t-call 3`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1678,7 +1678,7 @@ exports[`slots slot and t-call 3`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1712,7 +1712,7 @@ exports[`slots slot and t-esc 2`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1748,7 +1748,7 @@ exports[`slots slot are properly rendered if inner props are changed 2`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1793,7 +1793,7 @@ exports[`slots slot content has different key from other content -- dynamic slot
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`Child\`, {parent: 'SlotDisplay'}, key + \`__1\`, node, ctx);
const slot1 = (ctx['slotName']);
const b3 = toggler(slot1, callSlot(ctx, node, key, slot1, true, null));
const b3 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {}));
return multi([b2, b3]);
}
}"
@@ -1837,7 +1837,7 @@ exports[`slots slot content has different key from other content -- static slot
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`Child\`, {parent: 'SlotDisplay'}, key + \`__1\`, node, ctx);
const b3 = callSlot(ctx, node, key, 'default', false, null);
const b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]);
}
}"
@@ -1889,7 +1889,7 @@ exports[`slots slot content is bound to caller (variation) 2`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1923,7 +1923,7 @@ exports[`slots slot content is bound to caller 2`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -1955,7 +1955,7 @@ exports[`slots slot preserves properly parented relationship 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -2010,7 +2010,7 @@ exports[`slots slot preserves properly parented relationship, even through t-cal
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -2026,6 +2026,42 @@ exports[`slots slot preserves properly parented relationship, even through t-cal
}"
`;
exports[`slots slot with slot scope and t-props 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { capture, markRaw } = helpers;
let block2 = createBlock(\`<p><block-text-0/></p>\`);
let block3 = createBlock(\`<p><block-text-0/></p>\`);
function slot1(ctx, node, key = \\"\\") {
let txt1 = ctx['info'].a;
const b2 = block2([txt1]);
let txt2 = ctx['info'].b;
const b3 = block3([txt2]);
return multi([b2, b3]);
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
return component(\`Child\`, {slots: markRaw({'slotName': {__render: slot1, __ctx: ctx1, __scope: \\"info\\"}})}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`slots slot with slot scope and t-props 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'slotName', false, Object.assign({}, ctx['info']));
}
}"
`;
exports[`slots slots and wrapper components 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -2051,7 +2087,7 @@ exports[`slots slots and wrapper components 2`] = `
let block1 = createBlock(\`<a href=\\"abc\\"><block-child-0/></a>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -2086,7 +2122,7 @@ exports[`slots slots are properly bound to correct component 2`] = `
}
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null, defaultContent1);
return callSlot(ctx, node, key, 'default', false, {}, defaultContent1);
}
}"
`;
@@ -2123,7 +2159,7 @@ exports[`slots slots are rendered with proper context 2`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'footer', false, null);
const b2 = callSlot(ctx, node, key, 'footer', false, {});
return block1([], [b2]);
}
}"
@@ -2170,7 +2206,7 @@ exports[`slots slots are rendered with proper context, part 2 2`] = `
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['props'].to;
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([attr1], [b2]);
}
}"
@@ -2218,7 +2254,7 @@ exports[`slots slots are rendered with proper context, part 3 2`] = `
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['props'].to;
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([attr1], [b2]);
}
}"
@@ -2257,7 +2293,7 @@ exports[`slots slots are rendered with proper context, part 4 2`] = `
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['props'].to;
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([attr1], [b2]);
}
}"
@@ -2297,7 +2333,7 @@ exports[`slots slots in slots, with vars 2`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
return function template(ctx, node, key = \\"\\") {
@@ -2316,7 +2352,7 @@ exports[`slots slots in slots, with vars 3`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -2360,7 +2396,7 @@ exports[`slots slots in t-foreach and re-rendering 2`] = `
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].val;
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([txt1], [b2]);
}
}"
@@ -2418,7 +2454,7 @@ exports[`slots slots in t-foreach in t-foreach 2`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -2465,7 +2501,7 @@ exports[`slots slots in t-foreach with t-set and re-rendering 2`] = `
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].val;
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([txt1], [b2]);
}
}"
@@ -2501,7 +2537,7 @@ exports[`slots t-debug on a t-set-slot (defining a slot) 2`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'content', false, null);
const b2 = callSlot(ctx, node, key, 'content', false, {});
return block1([], [b2]);
}
}"
@@ -2539,7 +2575,7 @@ exports[`slots t-set t-value in a slot 2`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -2599,7 +2635,7 @@ exports[`slots t-slot in recursive templates 2`] = `
let block1 = createBlock(\`<wrapper><block-child-0/></wrapper>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -2637,7 +2673,7 @@ exports[`slots t-slot nested within another slot 2`] = `
}
function slot2(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
return function template(ctx, node, key = \\"\\") {
@@ -2656,7 +2692,7 @@ exports[`slots t-slot nested within another slot 3`] = `
let block1 = createBlock(\`<span id=\\"modal\\"><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -2671,7 +2707,7 @@ exports[`slots t-slot nested within another slot 4`] = `
let block1 = createBlock(\`<span id=\\"portal\\"><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -2718,7 +2754,7 @@ exports[`slots t-slot scope context 2`] = `
function slot1(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['onClick'], ctx];
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([hdlr1], [b2]);
}
@@ -2735,7 +2771,7 @@ exports[`slots t-slot scope context 3`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -2771,7 +2807,7 @@ exports[`slots t-slot within dynamic t-call 2`] = `
let block1 = createBlock(\`<div class=\\"slotted\\"><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, null);
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([], [b2]);
}
}"
@@ -2830,7 +2866,7 @@ exports[`slots template can just return a slot 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
@@ -147,7 +147,7 @@ exports[`style and class handling class on sub component, which is switched to a
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'someclass', child: ctx['state'].child}, key + \`__1\`, node, ctx);
return component(\`Child\`, {class: 'someclass',child: ctx['state'].child}, key + \`__1\`, node, ctx);
}
}"
`;
@@ -177,7 +177,7 @@ exports[`list of components reconciliation alg works for t-foreach in t-foreach,
for (let i2 = 0; i2 < l_block4; i2++) {
ctx[\`col\`] = v_block4[i2];
const key2 = ctx['col'];
const b6 = component(\`Child\`, {row: ctx['row'], col: ctx['col']}, key + \`__1__\${key1}__\${key2}\`, node, ctx);
const b6 = component(\`Child\`, {row: ctx['row'],col: ctx['col']}, key + \`__1__\${key1}__\${key2}\`, node, ctx);
c_block4[i2] = withKey(block5([], [b6]), key2);
}
ctx = ctx.__proto__;
@@ -181,6 +181,42 @@ exports[`t-on t-on on components 2`] = `
}"
`;
exports[`t-on t-on on components and t-foreach 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { prepareList, createCatcher, withKey } = helpers;
const catcher1 = createCatcher({\\"click\\":0});
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block1, v_block1, l_block1, c_block1] = prepareList(['John','Raoul','Gérald']);;
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`name\`] = v_block1[i1];
const key1 = ctx['name'];
const v1 = ctx['name'];
const hdlr1 = [()=>this.log(v1), ctx];
c_block1[i1] = withKey(catcher1(component(\`Child\`, {value: ctx['name']}, key + \`__1__\${key1}\`, node, ctx), [hdlr1]), key1);
}
return list(c_block1);
}
}"
`;
exports[`t-on t-on on components and t-foreach 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].value;
return block1([txt1]);
}
}"
`;
exports[`t-on t-on on components, variation 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -212,6 +248,66 @@ exports[`t-on t-on on components, variation 2`] = `
}"
`;
exports[`t-on t-on on components, with 'prevent' modifier 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { createCatcher } = helpers;
const catcher1 = createCatcher({\\"click.prevent\\":0});
return function template(ctx, node, key = \\"\\") {
const hdlr1 = [\\"prevent\\", ctx['increment'], ctx];
return catcher1(component(\`Child\`, {value: ctx['state'].value}, key + \`__1\`, node, ctx), [hdlr1]);
}
}"
`;
exports[`t-on t-on on components, with 'prevent' modifier 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<button><block-text-0/></button>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].value;
return block1([txt1]);
}
}"
`;
exports[`t-on t-on on components, with a handler update 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { isBoundary, withDefault, setContextValue, createCatcher } = helpers;
const catcher1 = createCatcher({\\"click\\":0});
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"name\\", ctx['state'].name);
const v1 = ctx['name'];
const hdlr1 = [()=>this.log(v1), ctx];
return catcher1(component(\`Child\`, {value: ctx['name']}, key + \`__1\`, node, ctx), [hdlr1]);
}
}"
`;
exports[`t-on t-on on components, with a handler update 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].value;
return block1([txt1]);
}
}"
`;
exports[`t-on t-on on destroyed components 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -243,6 +339,38 @@ exports[`t-on t-on on destroyed components 2`] = `
}"
`;
exports[`t-on t-on on slot, with 'prevent' modifier 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<button>button</button>\`);
function slot1(ctx, node, key = \\"\\") {
return block1();
}
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`t-on t-on on slot, with 'prevent' modifier 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { callSlot, createCatcher } = helpers;
const catcher1 = createCatcher({\\"click.prevent\\":0});
return function template(ctx, node, key = \\"\\") {
const hdlr1 = [\\"prevent\\", ctx['doSomething'], ctx];
return catcher1(callSlot(ctx, node, key, 'default', false, {}), [hdlr1]);
}
}"
`;
exports[`t-on t-on on t-set-slots 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -278,7 +406,7 @@ exports[`t-on t-on on t-set-slots 2`] = `
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'myslot', false, null);
return callSlot(ctx, node, key, 'myslot', false, {});
}
}"
`;
@@ -313,7 +441,7 @@ exports[`t-on t-on on t-slots 2`] = `
const b3 = text(ctx['state'].count);
const b4 = text(\`] \`);
const hdlr1 = [()=>this.state.count++, ctx];
const b5 = catcher1(callSlot(ctx, node, key, 'default', false, null), [hdlr1]);
const b5 = catcher1(callSlot(ctx, node, key, 'default', false, {}), [hdlr1]);
return multi([b2, b3, b4, b5]);
}
}"
@@ -117,7 +117,7 @@ exports[`t-props t-props with props 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = component(\`Child\`, Object.assign({}, ctx['childProps'], {a: 1, b: 2}), key + \`__1\`, node, ctx);
const b2 = component(\`Child\`, Object.assign({}, ctx['childProps'], {a: 1,b: 2}), key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
@@ -81,7 +81,7 @@ exports[`t-set slots with a t-set with a component in body 2`] = `
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`Child \`);
const b3 = callSlot(ctx, node, key, 'default', false, null);
const b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]);
}
}"
@@ -136,7 +136,7 @@ exports[`t-set slots with an t-set with a component in body 2`] = `
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`Blorg \`);
const b3 = callSlot(ctx, node, key, 'default', false, null);
const b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]);
}
}"
@@ -185,7 +185,7 @@ exports[`t-set slots with an unused t-set with a component in body 2`] = `
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`Child \`);
const b3 = callSlot(ctx, node, key, 'default', false, null);
const b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]);
}
}"
+30
View File
@@ -129,6 +129,36 @@ describe("basics", () => {
await app.mount(fixture);
});
test("props value are own property of props object", async () => {
expect.assertions(2);
const p = { a: 1 };
class Test extends Component {
static template = xml`<span>simple vnode</span>`;
setup() {
expect(Object.prototype.hasOwnProperty.call(this.props, "a")).toBe(true);
}
}
const app = new App(Test, { props: p });
await app.mount(fixture);
});
test("props value are own property of props object, even with default values", async () => {
expect.assertions(3);
const p = { a: 1 };
class Test extends Component {
static template = xml`<span>simple vnode</span>`;
static defaultProps = { b: 1 };
setup() {
expect(Object.prototype.hasOwnProperty.call(this.props, "a")).toBe(true);
expect(Object.prototype.hasOwnProperty.call(this.props, "b")).toBe(true);
}
}
const app = new App(Test, { props: p });
await app.mount(fixture);
});
test("some simple sanity checks (el/status)", async () => {
expect.assertions(3);
class Test extends Component {
+49
View File
@@ -477,3 +477,52 @@ test("force render in case of existing render", async () => {
"A:patched",
]).toBeLogged();
});
test("children, default props and renderings", async () => {
class Child extends Component {
static template = xml`child`;
static defaultProps = { value: 1 };
setup() {
useLogLifecycle();
}
}
class Parent extends Component {
static template = xml`
<t t-esc="state.value"/>
<Child />
`;
static components = { Child };
state = useState({ value: "A" });
setup() {
useLogLifecycle();
}
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("Achild");
expect([
"Parent:setup",
"Parent:willStart",
"Parent:willRender",
"Child:setup",
"Child:willStart",
"Parent:rendered",
"Child:willRender",
"Child:rendered",
"Child:mounted",
"Parent:mounted",
]).toBeLogged();
parent.state.value = "B";
await nextTick();
expect(fixture.innerHTML).toBe("Bchild");
expect([
"Parent:willRender",
"Parent:rendered",
"Parent:willPatch",
"Parent:patched",
]).toBeLogged();
});
+22
View File
@@ -74,6 +74,28 @@ describe("slots", () => {
expect(fixture.innerHTML).toBe("<span>other text</span>");
});
test("slot with slot scope and t-props", async () => {
class Child extends Component {
static template = xml`
<t t-slot="slotName" t-props="info"/>`;
info = { a: 1, b: 2 };
}
class Parent extends Component {
static template = xml`
<Child>
<t t-set-slot="slotName" t-slot-scope="info">
<p t-esc="info.a"/>
<p t-esc="info.b"/>
</t>
</Child>`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("<p>1</p><p>2</p>");
});
test("simple dynamic slot with slot scope", async () => {
let child: any;
class Child extends Component {
+109 -1
View File
@@ -1,5 +1,5 @@
import { Component, mount, onMounted, useState, xml } from "../../src/index";
import { elem, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
import { elem, logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
import { status } from "../../src/runtime/status";
snapshotEverything();
@@ -275,4 +275,112 @@ describe("t-on", () => {
await nextTick();
expect(fixture.innerHTML).toBe(" [1] <p>something</p><p>paragraph</p>");
});
test("t-on on components, with 'prevent' modifier", async () => {
expect.assertions(4); // 2 snaps and 2 expects
class Child extends Component {
static template = xml`<button t-esc="props.value"/>`;
}
class Parent extends Component {
static template = xml`<Child t-on-click.prevent="increment" value="state.value"/>`;
static components = { Child };
state = useState({ value: 1 });
increment(ev: MouseEvent) {
expect(ev.defaultPrevented).toBe(true);
this.state.value++;
}
}
await mount(Parent, fixture);
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.innerHTML).toBe("<button>2</button>");
});
test("t-on on slot, with 'prevent' modifier", async () => {
class Child extends Component {
static template = xml`<t t-slot="default" t-on-click.prevent="doSomething"/>`;
doSomething(ev: MouseEvent) {
expect(ev.defaultPrevented).toBe(true);
logStep("hey");
}
}
class Parent extends Component {
static template = xml`
<Child>
<button>button</button>
</Child>`;
static components = { Child };
}
await mount(Parent, fixture);
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.innerHTML).toBe("<button>button</button>");
expect(["hey"]).toBeLogged();
});
test("t-on on components and t-foreach", async () => {
class Child extends Component {
static template = xml`<div t-esc="props.value"/>`;
}
class Parent extends Component {
static template = xml`
<t t-foreach="['John', 'Raoul', 'Gérald']" t-as="name" t-key="name">
<Child t-on-click="() => this.log(name)" value="name"/>
</t>`;
static components = { Child };
log(name: string) {
logStep(name);
}
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("<div>John</div><div>Raoul</div><div>Gérald</div>");
expect([]).toBeLogged();
fixture.querySelectorAll("div")[0].click();
await nextTick();
expect(["John"]).toBeLogged();
fixture.querySelectorAll("div")[1].click();
await nextTick();
expect(["Raoul"]).toBeLogged();
fixture.querySelectorAll("div")[2].click();
await nextTick();
expect(["Gérald"]).toBeLogged();
});
test("t-on on components, with a handler update", async () => {
class Child extends Component {
static template = xml`<div t-esc="props.value"/>`;
}
class Parent extends Component {
static template = xml`
<t t-set="name" t-value="state.name"/>
<Child value="name" t-on-click="() => this.log(name)"
/>`;
static components = { Child };
state = useState({ name: "aaron" });
log(name: string) {
logStep(name);
}
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("<div>aaron</div>");
expect([]).toBeLogged();
fixture.querySelectorAll("div")[0].click();
await nextTick();
expect(["aaron"]).toBeLogged();
parent.state.name = "lucas";
await nextTick();
expect(fixture.innerHTML).toBe("<div>lucas</div>");
fixture.querySelectorAll("div")[0].click();
await nextTick();
expect(["lucas"]).toBeLogged();
});
});
+1 -1
View File
@@ -177,7 +177,7 @@ exports[`Portal Portal composed with t-slot 2`] = `
const Portal = app.Portal;
function slot1(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, null);
return callSlot(ctx, node, key, 'default', false, {});
}
return function template(ctx, node, key = \\"\\") {