You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are two separate issues relating to the way that Compiler.aggregate works, one related to oneTime bindings and the other to SSR OpCode cache-clearing.
Compiler.aggregate stores a reference to the last binding in a set of strings and bindings. It then mutates that binding and uses it as the binding provided to the constructor of a new HTMLBindingDirective.
SSR OpCode Cache Issue:
In SSR, if the ViewTemplate -> OpCode cache is cleared, a template will be re-parsed for op codes. Because Compiler.aggregate mutates the binding reference, this leads to a different output than the first parsing of the template by the Template Parser, causing an inconsistent SSR result.
Attribute binding Issue:
When oneTime is used in conjunction with a regular binding in an element's attribute, there is inconsistent behavior with how the bindings update due to how Compiler.aggregate re-uses the last binding in the set of bindings. If the last binding in the attribute is a oneTime binding, the oneTime binding is used by Compiler.aggregate and changes to observable properties fail to update the attribute value. If the oneTime binding is not last, changes to observable properties update the attribute value, but also re-evaluate the oneTime binding unexpectedly. See https://stackblitz.com/edit/typescript-t71pfv?file=index.ts,index.html for a min-repro.
Proposed Fix
I think two changes need to be made:
Update OneTimeBinding.evaluate to only invoke the binding expression once, during bind(). All other invocations of OneTimeBinding.evaluate would return the previously returned value. Uppon re-binding of the OneTimeBinding, the binding expression would be re-invoked for the provided target. This change is necessary because code created in Compiler.aggregate manually calls the binding expression from dataBinding.evaluate().
Update Compiler.aggregate to provide a new binding to the returned HTMLBindingDirective instead of re-using the last binding. Doing so will prevent the binding from not updating when the last binding is a OneTimeBinding. This prevents mutation of the existing bindings and fixes SSR cache issue, and also prevents OneTimeBinding from preventing updates of other bindings when it is the last binding in the set of bindings.
Actually fast-ssr also manually calls dataBinding.evaluate() from the same binding reference, so overriding evaluate() is probably not a good idea. We might need a different solution to fix the oneTime re-evaluation problem.
🐛 Bug Report
There are two separate issues relating to the way that
Compiler.aggregate
works, one related tooneTime
bindings and the other to SSR OpCode cache-clearing.Compiler.aggregate
stores a reference to the last binding in a set of strings and bindings. It then mutates that binding and uses it as the binding provided to the constructor of a newHTMLBindingDirective
.SSR OpCode Cache Issue:
In SSR, if the
ViewTemplate
->OpCode
cache is cleared, a template will be re-parsed for op codes. BecauseCompiler.aggregate
mutates the binding reference, this leads to a different output than the first parsing of the template by the Template Parser, causing an inconsistent SSR result.Attribute binding Issue:
When
oneTime
is used in conjunction with a regular binding in an element's attribute, there is inconsistent behavior with how the bindings update due to howCompiler.aggregate
re-uses the last binding in the set of bindings. If the last binding in the attribute is aoneTime
binding, theoneTime
binding is used byCompiler.aggregate
and changes to observable properties fail to update the attribute value. If theoneTime
binding is not last, changes to observable properties update the attribute value, but also re-evaluate theoneTime
binding unexpectedly. See https://stackblitz.com/edit/typescript-t71pfv?file=index.ts,index.html for a min-repro.Proposed Fix
I think two changes need to be made:
OneTimeBinding.evaluate
to only invoke the binding expression once, duringbind()
. All other invocations ofOneTimeBinding.evaluate
would return the previously returned value. Uppon re-binding of the OneTimeBinding, the binding expression would be re-invoked for the provided target. This change is necessary because code created inCompiler.aggregate
manually calls the binding expression fromdataBinding.evaluate()
.Compiler.aggregate
to provide a new binding to the returnedHTMLBindingDirective
instead of re-using the last binding. Doing so will prevent the binding from not updating when the last binding is aOneTimeBinding
. This prevents mutation of the existing bindings and fixes SSR cache issue, and also prevents OneTimeBinding from preventing updates of other bindings when it is the last binding in the set of bindings.The text was updated successfully, but these errors were encountered: