[IMP] component: use reactivity to allow shallow renderings

With this commit, component only render child
components if they have different props (shallow
equality). Otherwise, we trust the reactivity
system to make sure that all impacted components
are updated
This commit is contained in:
Géry Debongnie
2022-01-10 14:35:57 +01:00
committed by Samuel Degueldre
parent 592d9a458e
commit 1ae9d514b9
26 changed files with 1177 additions and 189 deletions
@@ -1067,6 +1067,33 @@ exports[`delay willUpdateProps with rendering grandchild 4`] = `
}"
`;
exports[`destroying/recreating a subcomponent, other scenario 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2,b3;
b2 = text(\`parent\`);
if (ctx['state'].hasChild) {
b3 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
}
return multi([b2, b3]);
}
}"
`;
exports[`destroying/recreating a subcomponent, other scenario 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`child\`);
}
}"
`;
exports[`destroying/recreating a subwidget with different props (if start is not over) 1`] = `
"function anonymous(bdom, helpers
) {
@@ -1145,7 +1172,7 @@ exports[`properly behave when destroyed/unmounted while rendering 2`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`);
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]);
}
}"
@@ -100,6 +100,7 @@ exports[`can catch errors can catch an error in a component render function 1`]
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -108,7 +109,7 @@ exports[`can catch errors can catch an error in a component render function 1`]
}
return function template(ctx, node, key = \\"\\") {
let b3 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__2\`, node, ctx);
let b3 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx);
return block1([], [b3]);
}
}"
@@ -152,6 +153,7 @@ exports[`can catch errors can catch an error in the constructor call of a compon
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -160,7 +162,7 @@ exports[`can catch errors can catch an error in the constructor call of a compon
}
return function template(ctx, node, key = \\"\\") {
let b3 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__2\`, node, ctx);
let b3 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx);
return block1([], [b3]);
}
}"
@@ -190,6 +192,7 @@ exports[`can catch errors can catch an error in the constructor call of a compon
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -200,7 +203,7 @@ exports[`can catch errors can catch an error in the constructor call of a compon
}
return function template(ctx, node, key = \\"\\") {
let b5 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__3\`, node, ctx);
let b5 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, ctx);
return block1([], [b5]);
}
}"
@@ -269,6 +272,7 @@ exports[`can catch errors can catch an error in the initial call of a component
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -277,7 +281,7 @@ exports[`can catch errors can catch an error in the initial call of a component
}
return function template(ctx, node, key = \\"\\") {
let b3 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__2\`, node, ctx);
let b3 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx);
return block1([], [b3]);
}
}"
@@ -321,6 +325,7 @@ exports[`can catch errors can catch an error in the initial call of a component
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -331,7 +336,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 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__2\`, node, ctx);
b3 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx);
}
return block1([], [b3]);
}
@@ -465,6 +470,7 @@ exports[`can catch errors can catch an error in the mounted call 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -473,7 +479,7 @@ exports[`can catch errors can catch an error in the mounted call 1`] = `
}
return function template(ctx, node, key = \\"\\") {
let b3 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__2\`, node, ctx);
let b3 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx);
return block1([], [b3]);
}
}"
@@ -516,6 +522,7 @@ exports[`can catch errors can catch an error in the willPatch call 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><span><block-text-0/></span><block-child-0/></div>\`);
@@ -525,7 +532,7 @@ exports[`can catch errors can catch an error in the willPatch call 1`] = `
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].message;
let b3 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__2\`, node, ctx);
let b3 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx);
return block1([txt1], [b3]);
}
}"
@@ -569,6 +576,7 @@ exports[`can catch errors can catch an error in the willStart call 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -577,7 +585,7 @@ exports[`can catch errors can catch an error in the willStart call 1`] = `
}
return function template(ctx, node, key = \\"\\") {
let b3 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__2\`, node, ctx);
let b3 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx);
return block1([], [b3]);
}
}"
@@ -620,6 +628,7 @@ exports[`can catch errors can catch an error origination from a child's willStar
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -630,7 +639,7 @@ exports[`can catch errors can catch an error origination from a child's willStar
}
return function template(ctx, node, key = \\"\\") {
let b5 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__3\`, node, ctx);
let b5 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, ctx);
return block1([], [b5]);
}
}"
@@ -733,7 +742,7 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { prepareList, capture, withKey } = helpers;
let { prepareList, capture, markRaw, withKey } = helpers;
function slot1(ctx, node, key = \\"\\") {
let Comp1 = ctx['cp'].Comp;
@@ -748,7 +757,7 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
let key1 = ctx['cp'].id;
const v1 = ctx['cp'];
const ctx1 = capture(ctx);
c_block1[i1] = withKey(component(\`ErrorHandler\`, {onError: ()=>this.cleanUp(v1.id),slots: {'default': {__render: slot1, __ctx: ctx1}}}, key + \`__2__\${key1}\`, node, ctx), key1);
c_block1[i1] = withKey(component(\`ErrorHandler\`, {onError: ()=>this.cleanUp(v1.id),slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, ctx), key1);
}
return list(c_block1);
}
@@ -808,7 +817,7 @@ exports[`can catch errors catching in child makes parent render 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { prepareList, capture, withKey } = helpers;
let { prepareList, capture, markRaw, withKey } = helpers;
function slot1(ctx, node, key = \\"\\") {
let Comp1 = ctx['elem'][1];
@@ -823,7 +832,7 @@ exports[`can catch errors catching in child makes parent render 1`] = `
let key1 = ctx['elem'][0];
const v1 = ctx['elem'];
const ctx1 = capture(ctx);
c_block1[i1] = withKey(component(\`Catch\`, {onError: (_error)=>this.onError(v1[0],_error),slots: {'default': {__render: slot1, __ctx: ctx1}}}, key + \`__2__\${key1}\`, node, ctx), key1);
c_block1[i1] = withKey(component(\`Catch\`, {onError: (_error)=>this.onError(v1[0],_error),slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, ctx), key1);
}
return list(c_block1);
}
@@ -873,6 +882,7 @@ exports[`can catch errors error in mounted on a component with a sibling (proper
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { markRaw } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
@@ -882,7 +892,7 @@ exports[`can catch errors error in mounted on a component with a sibling (proper
return function template(ctx, node, key = \\"\\") {
let b2 = component(\`OK\`, {}, key + \`__1\`, node, ctx);
let b4 = component(\`ErrorBoundary\`, {slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__3\`, node, ctx);
let b4 = component(\`ErrorBoundary\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, ctx);
return block1([], [b2, b4]);
}
}"
@@ -527,7 +527,7 @@ exports[`lifecycle hooks onWillRender 1`] = `
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {}, key + \`__1\`, node, ctx);
return component(\`Child\`, {someValue: ctx['state'].value}, key + \`__1\`, node, ctx);
}
}"
`;
@@ -62,7 +62,7 @@ exports[`refs refs are properly bound in slots 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { capture } = helpers;
let { capture, markRaw } = helpers;
let block1 = createBlock(\`<div><span class=\\"counter\\"><block-text-0/></span><block-child-0/></div>\`);
let block2 = createBlock(\`<button block-handler-0=\\"click\\" block-ref=\\"1\\">do something</button>\`);
@@ -77,7 +77,7 @@ exports[`refs refs are properly bound in slots 1`] = `
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].val;
const ctx1 = capture(ctx);
let b3 = component(\`Dialog\`, {slots: {'footer': {__render: slot1, __ctx: ctx1}}}, key + \`__1\`, node, ctx);
let b3 = component(\`Dialog\`, {slots: markRaw({'footer': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx);
return block1([txt1], [b3]);
}
}"
@@ -0,0 +1,212 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`force render in case of existing render 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`B\`, {val: ctx['state'].val}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`force render in case of existing render 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2 = component(\`C\`, {}, key + \`__1\`, node, ctx);
let b3 = text(ctx['props'].val);
return multi([b2, b3]);
}
}"
`;
exports[`force render in case of existing render 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`C\`);
}
}"
`;
exports[`rendering semantics can force a render to update sub tree 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2 = text(ctx['state'].value);
let b3 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
return multi([b2, b3]);
}
}"
`;
exports[`rendering semantics can force a render to update sub tree 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`child\`);
}
}"
`;
exports[`rendering semantics can render a parent without rendering child 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2 = text(ctx['state'].value);
let b3 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
return multi([b2, b3]);
}
}"
`;
exports[`rendering semantics can render a parent without rendering child 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`child\`);
}
}"
`;
exports[`rendering semantics props are reactive (nested prop) 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {a: ctx['state']}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`rendering semantics props are reactive (nested prop) 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['props'].a.b.c);
}
}"
`;
exports[`rendering semantics props are reactive 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {a: ctx['state']}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`rendering semantics props are reactive 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['props'].a.b);
}
}"
`;
exports[`rendering semantics render with deep=true followed by render with deep=false work as expected 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2 = text(\`parent\`);
let b3 = text(ctx['state'].value);
let b4 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
return multi([b2, b3, b4]);
}
}"
`;
exports[`rendering semantics render with deep=true followed by render with deep=false work as expected 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2 = text(\`child\`);
let b3 = text(ctx['env'].getValue());
return multi([b2, b3]);
}
}"
`;
exports[`rendering semantics rendering is atomic (for one subtree) 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2 = text(ctx['state'].obj.val);
let b3 = component(\`B\`, {obj: ctx['state'].obj}, key + \`__1\`, node, ctx);
return multi([b2, b3]);
}
}"
`;
exports[`rendering semantics rendering is atomic (for one subtree) 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`C\`, {obj: ctx['props'].obj}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`rendering semantics rendering is atomic (for one subtree) 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['props'].obj.val);
}
}"
`;
exports[`rendering semantics works as expected for dynamic number of props 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, Object.assign({}, ctx['state']), key + \`__1\`, node, ctx);
}
}"
`;
exports[`rendering semantics works as expected for dynamic number of props 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(Object.keys(ctx['props']).length);
}
}"
`;
File diff suppressed because it is too large Load Diff
@@ -4,7 +4,7 @@ exports[`t-set slot setted value (with t-set) not accessible with t-esc 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { isBoundary, withDefault, setContextValue, capture } = helpers;
let { isBoundary, withDefault, setContextValue, capture, markRaw } = helpers;
let block1 = createBlock(\`<div><p><block-text-0/></p><block-child-0/><p><block-text-1/></p></div>\`);
@@ -21,7 +21,7 @@ exports[`t-set slot setted value (with t-set) not accessible with t-esc 1`] = `
setContextValue(ctx, \\"iter\\", 'source');
let txt1 = ctx['iter'];
const ctx1 = capture(ctx);
let b2 = component(\`Childcomp\`, {slots: {'default': {__render: slot1, __ctx: ctx1}}}, key + \`__1\`, node, ctx);
let b2 = component(\`Childcomp\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx);
let txt2 = ctx['iter'];
return block1([txt1, txt2], [b2]);
}
@@ -51,7 +51,7 @@ exports[`t-set slots with a t-set with a component in body 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { capture, isBoundary, withDefault, LazyValue, safeOutput } = helpers;
let { capture, isBoundary, withDefault, LazyValue, safeOutput, markRaw } = helpers;
function slot1(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
@@ -68,7 +68,7 @@ exports[`t-set slots with a t-set with a component in body 1`] = `
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
return component(\`Child\`, {slots: {'default': {__render: slot1, __ctx: ctx1}}}, key + \`__2\`, node, ctx);
return component(\`Child\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx);
}
}"
`;
@@ -102,7 +102,7 @@ exports[`t-set slots with an t-set with a component in body 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { capture, isBoundary, withDefault, LazyValue, safeOutput } = helpers;
let { capture, isBoundary, withDefault, LazyValue, safeOutput, markRaw } = helpers;
let block4 = createBlock(\`<div>coffee</div>\`);
@@ -123,7 +123,7 @@ exports[`t-set slots with an t-set with a component in body 1`] = `
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
return component(\`Blorg\`, {slots: {'default': {__render: slot1, __ctx: ctx1}}}, key + \`__2\`, node, ctx);
return component(\`Blorg\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx);
}
}"
`;
@@ -157,7 +157,7 @@ exports[`t-set slots with an unused t-set with a component in body 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { capture, isBoundary, withDefault, LazyValue } = helpers;
let { capture, isBoundary, withDefault, LazyValue, markRaw } = helpers;
function slot1(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
@@ -172,7 +172,7 @@ exports[`t-set slots with an unused t-set with a component in body 1`] = `
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
return component(\`Child\`, {slots: {'default': {__render: slot1, __ctx: ctx1}}}, key + \`__2\`, node, ctx);
return component(\`Child\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx);
}
}"
`;