Terser will aggressively inline hot functions in renderer.ts in order
to reduce "function" declarations, but the inlining leads to performance
overhead (small, but noticeable in benchmarks).
Since we cannot control user's minifier options, we have to avoid the
deopt in the source code by using arrow functions in hot paths.
Previously codegen node for elements and components used raw expressions,
which leads to multiple permutations of AST shapes based on whether the
node is a block or has directives. The complexity is spread across the
entire compiler and occurs whenever a transform needs to deal with
element codegen nodes.
This refactor centralizes the handling of all possible permutations
into the codegen phase, so that all elements/components will have a
consistent node type throughout the transform phase.
The refactor is split into two commits (with test updates in a separate
one) so changes can be easier to inspect.
reference: https://github.com/vuejs/rfcs/issues/121
BREAKING CHANGE: object returned from `setup()` are no longer implicitly
passed to `reactive()`.
The renderContext is the object returned by `setup()` (or a new object
if no setup() is present). Before this change, it was implicitly passed
to `reactive()` for ref unwrapping. But this has the side effect of
unnecessary deep reactive conversion on properties that should not be
made reactive (e.g. computed return values and injected non-reactive
objects), and can lead to performance issues.
This change removes the `reactive()` call and instead performs a
shallow ref unwrapping at the render proxy level. The breaking part is
when the user returns an object with a plain property from `setup()`,
e.g. `return { count: 0 }`, this property will no longer trigger
updates when mutated by a in-template event handler. Instead, explicit
refs are required.
This also means that any objects not explicitly made reactive in
`setup()` will remain non-reactive. This can be desirable when
exposing heavy external stateful objects on `this`.