diff --git a/src/compiler/code_generator.ts b/src/compiler/code_generator.ts index 11251e0b..9fb24181 100644 --- a/src/compiler/code_generator.ts +++ b/src/compiler/code_generator.ts @@ -948,7 +948,7 @@ export class CodeGenerator { let propString = propStr; if (ast.dynamicProps) { if (!props.length) { - propString = `${compileExpr(ast.dynamicProps)}`; + propString = `Object.assign({}, ${compileExpr(ast.dynamicProps)})`; } else { propString = `Object.assign({}, ${compileExpr(ast.dynamicProps)}, ${propStr})`; } @@ -1012,7 +1012,7 @@ export class CodeGenerator { keyArg = `${ctx.tKeyExpr} + ${keyArg}`; } const blockArgs = `${expr}, ${propString}, ${keyArg}, node, ctx`; - let blockExpr = `component(${blockArgs})`; + let blockExpr = `component(${blockArgs}${hasSlot ? ", true" : ""})`; if (Object.keys(extraArgs).length) { this.shouldDefineAssign = true; const content = Object.keys(extraArgs).map((k) => `${k}: ${extraArgs[k]}`); diff --git a/src/component/component.ts b/src/component/component.ts index b3c48f3a..cec032a6 100644 --- a/src/component/component.ts +++ b/src/component/component.ts @@ -1,6 +1,8 @@ import type { Env } from "../app/app"; import type { ComponentNode } from "./component_node"; +export type Props = { [key: string]: any }; + // ----------------------------------------------------------------------------- // Component Class // ----------------------------------------------------------------------------- diff --git a/src/component/component_node.ts b/src/component/component_node.ts index 897b4c4d..c65809aa 100644 --- a/src/component/component_node.ts +++ b/src/component/component_node.ts @@ -1,6 +1,6 @@ import type { App, Env } from "../app/app"; import { BDom, VNode } from "../blockdom"; -import { Component } from "./component"; +import { Component, Props } from "./component"; import { Fiber, makeChildFiber, @@ -15,12 +15,21 @@ import { applyDefaultProps } from "./props_validation"; import { STATUS } from "./status"; import { applyStyles } from "./style"; +function arePropsDifferent(props1: Props, props2: Props): boolean { + for (let k in props1) { + if (props1[k] !== props2[k]) { + return true; + } + } + return false; +} export function component( name: string | typeof Component, props: any, key: string, ctx: ComponentNode, - parent: any + parent: any, + hasSlots: boolean = false ): ComponentNode { let node: any = ctx.children[key]; let isDynamic = typeof name !== "string"; @@ -39,7 +48,9 @@ export function component( const parentFiber = ctx.fiber!; if (node) { - node.updateAndRender(props, parentFiber); + if (hasSlots || arePropsDifferent(node.component.props, props)) { + node.updateAndRender(props, parentFiber); + } } else { // new component let C; @@ -241,6 +252,10 @@ export class ComponentNode } patch() { + if (!this.fiber) { + // component was not rendered => no need to do anything + return; + } this.bdom!.patch(this!.fiber!.bdom!, false); this.fiber!.appliedToDom = true; this.fiber = null; diff --git a/tests/components/__snapshots__/basics.test.ts.snap b/tests/components/__snapshots__/basics.test.ts.snap index 41d5ff4b..12e71c65 100644 --- a/tests/components/__snapshots__/basics.test.ts.snap +++ b/tests/components/__snapshots__/basics.test.ts.snap @@ -1020,7 +1020,7 @@ exports[`basics update props of component without concrete own node 3`] = ` return function template(ctx, node, key = \\"\\") { const tKey_1 = ctx['childProps'].key; - let b2 = toggler(tKey_1, component(\`Child\`, ctx['childProps'], tKey_1 + key + \`__2\`, node, ctx)); + let b2 = toggler(tKey_1, component(\`Child\`, Object.assign({}, ctx['childProps']), tKey_1 + key + \`__2\`, node, ctx)); return block1([], [b2]); } }" diff --git a/tests/components/__snapshots__/concurrency.test.ts.snap b/tests/components/__snapshots__/concurrency.test.ts.snap index 53704e5e..aa22e42d 100644 --- a/tests/components/__snapshots__/concurrency.test.ts.snap +++ b/tests/components/__snapshots__/concurrency.test.ts.snap @@ -1067,7 +1067,7 @@ exports[`properly behave when destroyed/unmounted while rendering 2`] = ` let block1 = createBlock(\`
\`); return function template(ctx, node, key = \\"\\") { - let b2 = component(\`SubChild\`, {}, key + \`__1\`, node, ctx); + let b2 = component(\`SubChild\`, {val: ctx['props'].val}, key + \`__1\`, node, ctx); return block1([], [b2]); } }" diff --git a/tests/components/__snapshots__/error_handling.test.ts.snap b/tests/components/__snapshots__/error_handling.test.ts.snap index 30916e66..870cd689 100644 --- a/tests/components/__snapshots__/error_handling.test.ts.snap +++ b/tests/components/__snapshots__/error_handling.test.ts.snap @@ -126,7 +126,7 @@ exports[`can catch errors can catch an error in a component render function 3`] } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -230,7 +230,7 @@ exports[`can catch errors can catch an error in the constructor call of a compon } return function template(ctx, node, key = \\"\\") { - let b5 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b5 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b5]); } }" @@ -250,7 +250,7 @@ exports[`can catch errors can catch an error in the constructor call of a compon } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -305,7 +305,7 @@ exports[`can catch errors can catch an error in the initial call of a component } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -362,7 +362,7 @@ exports[`can catch errors can catch an error in the initial call of a component return function template(ctx, node, key = \\"\\") { let b3; if (ctx['state'].flag) { - b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } return block1([], [b3]); } @@ -417,7 +417,7 @@ exports[`can catch errors can catch an error in the mounted call 3`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -473,7 +473,7 @@ exports[`can catch errors can catch an error in the willPatch call 3`] = ` return function template(ctx, node, key = \\"\\") { let d1 = ctx['state'].message; - let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([d1], [b3]); } }" @@ -527,7 +527,7 @@ exports[`can catch errors can catch an error in the willStart call 3`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -597,7 +597,7 @@ exports[`can catch errors can catch an error origination from a child's willStar } return function template(ctx, node, key = \\"\\") { - let b5 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b5 = assign(component(\`ErrorBoundary\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b5]); } }" diff --git a/tests/components/__snapshots__/lifecycle.test.ts.snap b/tests/components/__snapshots__/lifecycle.test.ts.snap index b6a6c446..bffaee04 100644 --- a/tests/components/__snapshots__/lifecycle.test.ts.snap +++ b/tests/components/__snapshots__/lifecycle.test.ts.snap @@ -555,7 +555,7 @@ exports[`lifecycle hooks onWillRender 2`] = ` let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; return function template(ctx, node, key = \\"\\") { - return component(\`Child\`, {}, key + \`__1\`, node, ctx); + return component(\`Child\`, {someValue: ctx['state'].value}, key + \`__1\`, node, ctx); } }" `; diff --git a/tests/components/__snapshots__/refs.test.ts.snap b/tests/components/__snapshots__/refs.test.ts.snap index 661bde6d..88c9c823 100644 --- a/tests/components/__snapshots__/refs.test.ts.snap +++ b/tests/components/__snapshots__/refs.test.ts.snap @@ -53,7 +53,7 @@ exports[`refs refs are properly bound in slots 2`] = ` const refs = ctx.__owl__.refs; let d1 = ctx['state'].val; const ctx2 = capture(ctx); - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'footer': slot3(ctx2)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'footer': slot3(ctx2)}}); return block1([d1], [b3]); } }" diff --git a/tests/components/__snapshots__/rendering.test.ts.snap b/tests/components/__snapshots__/rendering.test.ts.snap new file mode 100644 index 00000000..24686781 --- /dev/null +++ b/tests/components/__snapshots__/rendering.test.ts.snap @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`rendering semantics can render a parent without rendering child 1`] = ` +"function anonymous(bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, component } = bdom; + let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; + + return function template(ctx, node, key = \\"\\") { + return text(\`child\`); + } +}" +`; + +exports[`rendering semantics can render a parent without rendering child 2`] = ` +"function anonymous(bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, component } = bdom; + let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; + + return function template(ctx, node, key = \\"\\") { + let b2 = text(ctx['state'].value); + let b3 = component(\`Child\`, {}, key + \`__1\`, node, ctx); + return multi([b2, b3]); + } +}" +`; diff --git a/tests/components/__snapshots__/slots.test.ts.snap b/tests/components/__snapshots__/slots.test.ts.snap index 67d22566..ee54cbb9 100644 --- a/tests/components/__snapshots__/slots.test.ts.snap +++ b/tests/components/__snapshots__/slots.test.ts.snap @@ -37,7 +37,7 @@ exports[`slots can define and call slots 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b4 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'header': slot3(ctx2), 'footer': slot4(ctx2)}}); + let b4 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'header': slot3(ctx2), 'footer': slot4(ctx2)}}); return block1([], [b4]); } }" @@ -74,7 +74,7 @@ exports[`slots can render node with t-ref and Component in same slot 2`] = ` return function template(ctx, node, key = \\"\\") { const refs = ctx.__owl__.refs; - return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -117,7 +117,7 @@ exports[`slots content is the default slot (variation) 2`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -152,7 +152,7 @@ exports[`slots content is the default slot 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -226,7 +226,7 @@ exports[`slots default content is not rendered if named slot is provided 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'header': slot3(ctx2)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'header': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -265,7 +265,7 @@ exports[`slots default content is not rendered if slot is provided 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -310,7 +310,7 @@ exports[`slots default slot next to named slot, with default content 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'footer': slot3(ctx2)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'footer': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -340,7 +340,7 @@ exports[`slots default slot work with text nodes (variation) 2`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -374,7 +374,7 @@ exports[`slots default slot work with text nodes 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -422,7 +422,7 @@ exports[`slots dynamic t-slot call 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b6 = assign(component(\`Toggler\`, {}, key + \`__1\`, node, ctx), {slots: {'slot1': slot3(ctx2), 'slot2': slot4(ctx2)}}); + let b6 = assign(component(\`Toggler\`, {}, key + \`__1\`, node, ctx, true), {slots: {'slot1': slot3(ctx2), 'slot2': slot4(ctx2)}}); return block1([], [b6]); } }" @@ -473,7 +473,7 @@ exports[`slots dynamic t-slot call with default 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b6 = assign(component(\`Toggler\`, {}, key + \`__1\`, node, ctx), {slots: {'slot1': slot3(ctx2), 'slot2': slot4(ctx2)}}); + let b6 = assign(component(\`Toggler\`, {}, key + \`__1\`, node, ctx, true), {slots: {'slot1': slot3(ctx2), 'slot2': slot4(ctx2)}}); return block1([], [b6]); } }" @@ -505,7 +505,7 @@ exports[`slots fun: two calls to the same slot 2`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -574,7 +574,7 @@ exports[`slots multiple roots are allowed in a default slot 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b5 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b5 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b5]); } }" @@ -614,7 +614,7 @@ exports[`slots multiple roots are allowed in a named slot 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b5 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'content': slot3(ctx2)}}); + let b5 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'content': slot3(ctx2)}}); return block1([], [b5]); } }" @@ -668,7 +668,7 @@ exports[`slots multiple slots containing components 3`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - return assign(component(\`B\`, {}, key + \`__1\`, node, ctx), {slots: {'s1': slot3(ctx2), 's2': slot5(ctx2)}}); + return assign(component(\`B\`, {}, key + \`__1\`, node, ctx, true), {slots: {'s1': slot3(ctx2), 's2': slot5(ctx2)}}); } }" `; @@ -707,7 +707,7 @@ exports[`slots named slot inside slot 2`] = ` const slot4 = ctx => (node, key) => { const ctx6 = capture(ctx); - return assign(component(\`Child\`, {}, key + \`__5\`, node, ctx), {slots: {'brol': slot7(ctx6)}}); + return assign(component(\`Child\`, {}, key + \`__5\`, node, ctx, true), {slots: {'brol': slot7(ctx6)}}); } const slot7 = ctx => (node, key) => { @@ -717,7 +717,7 @@ exports[`slots named slot inside slot 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b5 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'brol': slot3(ctx2), 'default': slot4(ctx2)}}); + let b5 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'brol': slot3(ctx2), 'default': slot4(ctx2)}}); return block1([], [b5]); } }" @@ -757,7 +757,7 @@ exports[`slots named slot inside slot, part 3 2`] = ` const slot4 = ctx => (node, key) => { const ctx6 = capture(ctx); - return assign(component(\`Child\`, {}, key + \`__5\`, node, ctx), {slots: {'brol': slot7(ctx6)}}); + return assign(component(\`Child\`, {}, key + \`__5\`, node, ctx, true), {slots: {'brol': slot7(ctx6)}}); } const slot7 = ctx => (node, key) => { @@ -767,7 +767,7 @@ exports[`slots named slot inside slot, part 3 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b5 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'brol': slot3(ctx2), 'default': slot4(ctx2)}}); + let b5 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'brol': slot3(ctx2), 'default': slot4(ctx2)}}); return block1([], [b5]); } }" @@ -850,7 +850,7 @@ exports[`slots named slots inside slot, again 2`] = ` const slot4 = ctx => (node, key) => { const ctx6 = capture(ctx); - return assign(component(\`Child\`, {}, key + \`__5\`, node, ctx), {slots: {'brol2': slot7(ctx6)}}); + return assign(component(\`Child\`, {}, key + \`__5\`, node, ctx, true), {slots: {'brol2': slot7(ctx6)}}); } const slot7 = ctx => (node, key) => { @@ -860,7 +860,7 @@ exports[`slots named slots inside slot, again 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b5 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'brol1': slot3(ctx2), 'default': slot4(ctx2)}}); + let b5 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'brol1': slot3(ctx2), 'default': slot4(ctx2)}}); return block1([], [b5]); } }" @@ -920,7 +920,7 @@ exports[`slots nested slots in same template 4`] = ` let block1 = createBlock(\`\`); const slot2 = ctx => (node, key) => { - return assign(component(\`Child2\`, {}, key + \`__3\`, node, ctx), {slots: {'default': slot4(ctx)}}); + return assign(component(\`Child2\`, {}, key + \`__3\`, node, ctx, true), {slots: {'default': slot4(ctx)}}); } const slot4 = ctx => (node, key) => { @@ -928,7 +928,7 @@ exports[`slots nested slots in same template 4`] = ` } return function template(ctx, node, key = \\"\\") { - let b4 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b4 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b4]); } }" @@ -976,7 +976,7 @@ exports[`slots nested slots: evaluation context and parented relationship 3`] = } return function template(ctx, node, key = \\"\\") { - return assign(component(\`GrandChild\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`GrandChild\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -993,7 +993,7 @@ exports[`slots nested slots: evaluation context and parented relationship 4`] = } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -1052,7 +1052,7 @@ exports[`slots simple default slot 2`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -1081,7 +1081,7 @@ exports[`slots simple default slot, variation 2`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -1131,7 +1131,7 @@ exports[`slots slot and (inline) t-call 3`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -1182,7 +1182,7 @@ exports[`slots slot and t-call 3`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -1217,7 +1217,7 @@ exports[`slots slot and t-esc 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -1270,7 +1270,7 @@ exports[`slots slot are properly rendered if inner props are changed 3`] = ` const v1 = ctx['inc']; let d1 = [v1, ctx]; let d2 = ctx['state'].val; - let b3 = assign(component(\`GenericComponent\`, {}, key + \`__2\`, node, ctx), {slots: {'default': slot3(ctx)}}); + let b3 = assign(component(\`GenericComponent\`, {}, key + \`__2\`, node, ctx, true), {slots: {'default': slot3(ctx)}}); return block1([d1, d2], [b3]); } }" @@ -1307,7 +1307,7 @@ exports[`slots slot content is bound to caller 2`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -1350,7 +1350,7 @@ exports[`slots slot preserves properly parented relationship 3`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -1408,7 +1408,7 @@ exports[`slots slot preserves properly parented relationship, even through t-cal return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b3 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b3 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -1441,7 +1441,7 @@ exports[`slots slots and wrapper components 2`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Link\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Link\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -1480,7 +1480,7 @@ exports[`slots slots are rendered with proper context 2`] = ` return function template(ctx, node, key = \\"\\") { let d1 = ctx['state'].val; const ctx2 = capture(ctx); - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'footer': slot3(ctx2)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'footer': slot3(ctx2)}}); return block1([d1], [b3]); } }" @@ -1525,7 +1525,7 @@ exports[`slots slots are rendered with proper context, part 2 2`] = ` ctx[\`user\`] = v_block2[i1]; let key1 = ctx['user'].id; const ctx2 = capture(ctx); - let b7 = assign(component(\`Link\`, {to: '/user/'+ctx['user'].id}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b7 = assign(component(\`Link\`, {to: '/user/'+ctx['user'].id}, key + \`__1__\${key1}\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); c_block2[i1] = withKey(block3([], [b7]), key1); } let b2 = list(c_block2); @@ -1574,7 +1574,7 @@ exports[`slots slots are rendered with proper context, part 3 2`] = ` let key1 = ctx['user'].id; setContextValue(ctx, \\"userdescr\\", 'User '+ctx['user'].name); const ctx2 = capture(ctx); - let b5 = assign(component(\`Link\`, {to: '/user/'+ctx['user'].id}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b5 = assign(component(\`Link\`, {to: '/user/'+ctx['user'].id}, key + \`__1__\${key1}\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); c_block2[i1] = withKey(block3([], [b5]), key1); } let b2 = list(c_block2); @@ -1617,7 +1617,7 @@ exports[`slots slots are rendered with proper context, part 4 2`] = ` ctx[isBoundary] = 1 setContextValue(ctx, \\"userdescr\\", 'User '+ctx['state'].user.name); const ctx2 = capture(ctx); - let b3 = assign(component(\`Link\`, {to: '/user/'+ctx['state'].user.id}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b3 = assign(component(\`Link\`, {to: '/user/'+ctx['state'].user.id}, key + \`__1\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -1652,7 +1652,7 @@ exports[`slots slots in slots, with vars 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`B\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`B\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -1678,7 +1678,7 @@ exports[`slots slots in slots, with vars 3`] = ` ctx[isBoundary] = 1 setContextValue(ctx, \\"test\\", ctx['state'].name); const ctx2 = capture(ctx); - let b3 = assign(component(\`A\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b3 = assign(component(\`A\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -1721,7 +1721,7 @@ exports[`slots slots in t-foreach and re-rendering 2`] = ` ctx[\`n_index\`] = i1; let key1 = ctx['n_index']; const ctx2 = capture(ctx); - c_block2[i1] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}}), key1); + c_block2[i1] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}), key1); } let b2 = list(c_block2); return block1([], [b2]); @@ -1775,7 +1775,7 @@ exports[`slots slots in t-foreach in t-foreach 2`] = ` ctx[\`node2\`] = v_block6[i2]; let key2 = ctx['node2'].key; const ctx2 = capture(ctx); - c_block6[i2] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}__\${key2}\`, node, ctx), {slots: {'default': slot3(ctx2)}}), key2); + c_block6[i2] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}__\${key2}\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}), key2); } ctx = ctx.__proto__; let b6 = list(c_block6); @@ -1828,7 +1828,7 @@ exports[`slots slots in t-foreach with t-set and re-rendering 2`] = ` let key1 = ctx['n_index']; setContextValue(ctx, \\"dummy\\", ctx['n_index']); const ctx2 = capture(ctx); - c_block2[i1] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}}), key1); + c_block2[i1] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}), key1); } let b2 = list(c_block2); return block1([], [b2]); @@ -1867,7 +1867,7 @@ exports[`slots t-debug on a t-set-slot (defining a slot) 2`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'content': slot3(ctx2)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'content': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -1906,7 +1906,7 @@ exports[`slots t-set t-value in a slot 2`] = ` ctx = Object.create(ctx); ctx[isBoundary] = 1 const ctx2 = capture(ctx); - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -1968,7 +1968,7 @@ exports[`slots t-slot in recursive templates 2`] = ` ctx = Object.create(ctx); ctx[isBoundary] = 1 const ctx2 = capture(ctx); - return assign(component(\`Wrapper\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + return assign(component(\`Wrapper\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); } }" `; @@ -2027,7 +2027,7 @@ exports[`slots t-slot nested within another slot 4`] = ` let block1 = createBlock(\`\`); const slot2 = ctx => (node, key) => { - return assign(component(\`Portal\`, {}, key + \`__3\`, node, ctx), {slots: {'default': slot4(ctx)}}); + return assign(component(\`Portal\`, {}, key + \`__3\`, node, ctx, true), {slots: {'default': slot4(ctx)}}); } const slot4 = ctx => (node, key) => { @@ -2035,7 +2035,7 @@ exports[`slots t-slot nested within another slot 4`] = ` } return function template(ctx, node, key = \\"\\") { - let b4 = assign(component(\`Modal\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b4 = assign(component(\`Modal\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b4]); } }" @@ -2055,7 +2055,7 @@ exports[`slots t-slot nested within another slot 5`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -2090,7 +2090,7 @@ exports[`slots t-slot scope context 2`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Wrapper\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Wrapper\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -2109,7 +2109,7 @@ exports[`slots t-slot scope context 3`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -2174,7 +2174,7 @@ exports[`slots t-slot within dynamic t-call 4`] = ` return function template(ctx, node, key = \\"\\") { const ctx2 = capture(ctx); - let b3 = assign(component(\`Slotted\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b3 = assign(component(\`Slotted\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); return block1([], [b3]); } }" @@ -2221,7 +2221,7 @@ exports[`slots template can just return a slot 3`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`SlotComponent\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`SlotComponent\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" diff --git a/tests/components/__snapshots__/t_props.test.ts.snap b/tests/components/__snapshots__/t_props.test.ts.snap index 2c353109..d3116a06 100644 --- a/tests/components/__snapshots__/t_props.test.ts.snap +++ b/tests/components/__snapshots__/t_props.test.ts.snap @@ -24,7 +24,7 @@ exports[`t-props basic use 2`] = ` let block1 = createBlock(\`
\`); return function template(ctx, node, key = \\"\\") { - let b2 = component(\`Child\`, ctx['some'].obj, key + \`__1\`, node, ctx); + let b2 = component(\`Child\`, Object.assign({}, ctx['some'].obj), key + \`__1\`, node, ctx); return block1([], [b2]); } }" @@ -85,7 +85,7 @@ exports[`t-props t-props only 2`] = ` let block1 = createBlock(\`
\`); return function template(ctx, node, key = \\"\\") { - let b2 = component(\`Comp\`, ctx['state'], key + \`__1\`, node, ctx); + let b2 = component(\`Comp\`, Object.assign({}, ctx['state']), key + \`__1\`, node, ctx); return block1([], [b2]); } }" diff --git a/tests/components/__snapshots__/t_set.test.ts.snap b/tests/components/__snapshots__/t_set.test.ts.snap index 1c5d699a..60022fb8 100644 --- a/tests/components/__snapshots__/t_set.test.ts.snap +++ b/tests/components/__snapshots__/t_set.test.ts.snap @@ -38,7 +38,7 @@ exports[`t-set slot setted value (with t-set) not accessible with t-esc 2`] = ` setContextValue(ctx, \\"iter\\", 'source'); let d1 = ctx['iter']; const ctx2 = capture(ctx); - let b2 = assign(component(\`Childcomp\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); + let b2 = assign(component(\`Childcomp\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot3(ctx2)}}); let d2 = ctx['iter']; return block1([d1, d2], [b2]); } diff --git a/tests/components/concurrency.test.ts b/tests/components/concurrency.test.ts index 3f8a2743..6bfe85fb 100644 --- a/tests/components/concurrency.test.ts +++ b/tests/components/concurrency.test.ts @@ -543,7 +543,7 @@ test("properly behave when destroyed/unmounted while rendering ", async () => { } class Child extends Component { - static template = xml`
`; + static template = xml`
`; static components = { SubChild }; setup() { useLogLifecycle(steps); @@ -1900,18 +1900,13 @@ test("concurrent renderings scenario 13", async () => { "Child:willPatch", "Child:patched", "Parent:willRender", - "Child:willUpdateProps", "Child:setup", "Child:willStart", "Parent:rendered", "Child:willRender", "Child:rendered", - "Child:willRender", - "Child:rendered", "Parent:willPatch", - "Child:willPatch", "Child:mounted", - "Child:patched", "Parent:patched", "Child:willRender", "Child:rendered", diff --git a/tests/components/lifecycle.test.ts b/tests/components/lifecycle.test.ts index 4b877991..8f79ec87 100644 --- a/tests/components/lifecycle.test.ts +++ b/tests/components/lifecycle.test.ts @@ -899,8 +899,9 @@ describe("lifecycle hooks", () => { class Parent extends Component { static template = xml` - `; + `; static components = { Child }; + state = useState({ value: 1 }); setup() { useLogLifecycle(steps); } @@ -910,7 +911,7 @@ describe("lifecycle hooks", () => { expect(fixture.innerHTML).toBe(""); - parent.render(); // to block child render + parent.state.value++; // to block child render await nextTick(); fixture.querySelector("button")!.click(); @@ -1063,22 +1064,18 @@ describe("lifecycle hooks", () => { steps.splice(0); c!.state.flag = false; await nextTick(); + expect(fixture.innerHTML).toBe(`
A
B
C
D
F
`); expect(steps).toEqual([ "C:willRender", - "D:willUpdateProps", "F:setup", "F:willStart", "C:rendered", - "D:willRender", - "D:rendered", "F:willRender", "F:rendered", "C:willPatch", - "D:willPatch", "E:willUnmount", "E:destroyed", "F:mounted", - "D:patched", "C:patched", ]); }); diff --git a/tests/components/rendering.test.ts b/tests/components/rendering.test.ts new file mode 100644 index 00000000..8350822e --- /dev/null +++ b/tests/components/rendering.test.ts @@ -0,0 +1,49 @@ +import { Component, mount, onRendered, useState } from "../../src"; +import { xml } from "../../src/tags"; +import { makeTestFixture, snapshotEverything, nextTick } from "../helpers"; + +let fixture: HTMLElement; + +snapshotEverything(); + +beforeEach(() => { + fixture = makeTestFixture(); +}); + +describe("rendering semantics", () => { + test("can render a parent without rendering child", async () => { + let childN = 0; + let parentN = 0; + class Child extends Component { + static template = xml`child`; + setup() { + onRendered(() => childN++); + } + } + + class Parent extends Component { + static template = xml` + + + `; + static components = { Child }; + + state = useState({ value: "A" }); + setup() { + onRendered(() => parentN++); + } + } + + const parent = await mount(Parent, fixture); + + expect(fixture.innerHTML).toBe("Achild"); + expect(parentN).toBe(1); + expect(childN).toBe(1); + + parent.state.value = "B"; + await nextTick(); + expect(fixture.innerHTML).toBe("Bchild"); + expect(parentN).toBe(2); + expect(childN).toBe(1); + }); +}); diff --git a/tests/components/t_props.test.ts b/tests/components/t_props.test.ts index ce78d09b..6d7bfc2a 100644 --- a/tests/components/t_props.test.ts +++ b/tests/components/t_props.test.ts @@ -65,7 +65,7 @@ describe("t-props", () => { `; setup() { expect(this.props).toEqual({ a: 1, b: 2 }); - expect(this.props).toBe(props); + expect(this.props).not.toBe(props); } } class Parent extends Component { diff --git a/tests/misc/__snapshots__/memo.test.ts.snap b/tests/misc/__snapshots__/memo.test.ts.snap index 1422ec5d..4e3487cf 100644 --- a/tests/misc/__snapshots__/memo.test.ts.snap +++ b/tests/misc/__snapshots__/memo.test.ts.snap @@ -30,7 +30,7 @@ exports[`Memo if no prop change, prevent renderings from above 2`] = ` let b2 = text(ctx['state'].a); let b3 = text(ctx['state'].b); let b4 = text(ctx['state'].c); - let b9 = assign(component(\`Memo\`, {a: ctx['state'].a,b: ctx['state'].b}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b9 = assign(component(\`Memo\`, {a: ctx['state'].a,b: ctx['state'].b}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return multi([b2, b3, b4, b9]); } }" @@ -61,7 +61,7 @@ exports[`Memo if no props, prevent renderings from above 2`] = ` return function template(ctx, node, key = \\"\\") { let b2 = component(\`Child\`, {value: ctx['state'].value}, key + \`__1\`, node, ctx); - let b4 = assign(component(\`Memo\`, {}, key + \`__2\`, node, ctx), {slots: {'default': slot3(ctx)}}); + let b4 = assign(component(\`Memo\`, {}, key + \`__2\`, node, ctx, true), {slots: {'default': slot3(ctx)}}); return multi([b2, b4]); } }" @@ -80,7 +80,7 @@ exports[`Memo if no props, prevent renderings from above (work with simple html) return function template(ctx, node, key = \\"\\") { let b2 = text(ctx['state'].value); - let b4 = assign(component(\`Memo\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b4 = assign(component(\`Memo\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return multi([b2, b4]); } }" diff --git a/tests/misc/__snapshots__/portal.test.ts.snap b/tests/misc/__snapshots__/portal.test.ts.snap index 3e9f4561..7eac3a3c 100644 --- a/tests/misc/__snapshots__/portal.test.ts.snap +++ b/tests/misc/__snapshots__/portal.test.ts.snap @@ -28,7 +28,7 @@ exports[`Portal Portal composed with t-slot 2`] = ` } return function template(ctx, node, key = \\"\\") { - return assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + return assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } }" `; @@ -47,7 +47,7 @@ exports[`Portal Portal composed with t-slot 3`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Child\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -68,7 +68,7 @@ exports[`Portal basic use of portal 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -106,7 +106,7 @@ exports[`Portal conditional use of Portal (with sub Component) 2`] = ` let b2,b4; b2 = block2(); if (ctx['state'].hasPortal) { - b4 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + b4 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } return multi([b2, b4]); } @@ -131,7 +131,7 @@ exports[`Portal conditional use of Portal 1`] = ` let b2,b4; b2 = block2(); if (ctx['state'].hasPortal) { - b4 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + b4 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } return multi([b2, b4]); } @@ -169,7 +169,7 @@ exports[`Portal lifecycle hooks of portal sub component are properly called 2`] return function template(ctx, node, key = \\"\\") { let b3; if (ctx['state'].hasChild) { - b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); } return block1([], [b3]); } @@ -196,7 +196,7 @@ exports[`Portal portal could have dynamically no content 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b4 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b4 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b4]); } }" @@ -231,7 +231,7 @@ exports[`Portal portal destroys on crash 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -266,7 +266,7 @@ exports[`Portal portal with child and props 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -295,7 +295,7 @@ exports[`Portal portal with dynamic body 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b5 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b5 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b5]); } }" @@ -319,7 +319,7 @@ exports[`Portal portal with many children 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b5 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b5 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b5]); } }" @@ -343,7 +343,7 @@ exports[`Portal portal with no content 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b4 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b4 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b4]); } }" @@ -363,7 +363,7 @@ exports[`Portal portal with only text as content 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -384,7 +384,7 @@ exports[`Portal portal with target not in dom 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: '#does-not-exist'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: '#does-not-exist'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -418,7 +418,7 @@ exports[`Portal portal's parent's env is not polluted 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -439,7 +439,7 @@ exports[`Portal with target in template (after portal) 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: '#local-target'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: '#local-target'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -460,7 +460,7 @@ exports[`Portal with target in template (before portal) 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: '#local-target'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: '#local-target'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -481,7 +481,7 @@ exports[`Portal: Props validation target is mandatory 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -502,7 +502,7 @@ exports[`Portal: Props validation target is not list 1`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: ['body']}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: ['body']}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" @@ -537,7 +537,7 @@ exports[`Portal: UI/UX focus is kept across re-renders 2`] = ` } return function template(ctx, node, key = \\"\\") { - let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx), {slots: {'default': slot2(ctx)}}); + let b3 = assign(component(\`Portal\`, {target: '#outside'}, key + \`__1\`, node, ctx, true), {slots: {'default': slot2(ctx)}}); return block1([], [b3]); } }" diff --git a/tests/reactivity.test.ts b/tests/reactivity.test.ts index e74c0e46..3f0f4ad8 100644 --- a/tests/reactivity.test.ts +++ b/tests/reactivity.test.ts @@ -1510,7 +1510,7 @@ describe("Reactivity: useState", () => { expect([...steps]).toEqual(["list"]); await nextTick(); expect(fixture.innerHTML).toBe("
3
Total: 3 Count: 1
"); - expect([...steps]).toEqual(["list", "quantity1"]); + expect([...steps]).toEqual(["list"]); steps.clear(); secondQuantity.quantity = 2;