wip(ssr): basic element hydration
This commit is contained in:
@@ -5,8 +5,8 @@ exports[`scopeId compiler support should push scopeId for hoisted nodes 1`] = `
|
||||
const _withId = _withScopeId(\\"test\\")
|
||||
|
||||
_pushScopeId(\\"test\\")
|
||||
const _hoisted_1 = _createVNode(\\"div\\", null, \\"hello\\", -1)
|
||||
const _hoisted_2 = _createVNode(\\"div\\", null, \\"world\\", -1)
|
||||
const _hoisted_1 = _createVNode(\\"div\\", null, \\"hello\\", -2 /* HOISTED */)
|
||||
const _hoisted_2 = _createVNode(\\"div\\", null, \\"world\\", -2 /* HOISTED */)
|
||||
_popScopeId()
|
||||
|
||||
export const render = _withId(function render(_ctx, _cache) {
|
||||
|
||||
@@ -4,6 +4,8 @@ import {
|
||||
PUSH_SCOPE_ID,
|
||||
POP_SCOPE_ID
|
||||
} from '../src/runtimeHelpers'
|
||||
import { PatchFlags } from '@vue/shared'
|
||||
import { genFlagText } from './testUtils'
|
||||
|
||||
describe('scopeId compiler support', () => {
|
||||
test('should only work in module mode', () => {
|
||||
@@ -81,8 +83,12 @@ describe('scopeId compiler support', () => {
|
||||
expect(code).toMatch(
|
||||
[
|
||||
`_pushScopeId("test")`,
|
||||
`const _hoisted_1 = _createVNode("div", null, "hello", -1)`,
|
||||
`const _hoisted_2 = _createVNode("div", null, "world", -1)`,
|
||||
`const _hoisted_1 = _createVNode("div", null, "hello", ${genFlagText(
|
||||
PatchFlags.HOISTED
|
||||
)})`,
|
||||
`const _hoisted_2 = _createVNode("div", null, "world", ${genFlagText(
|
||||
PatchFlags.HOISTED
|
||||
)})`,
|
||||
`_popScopeId()`
|
||||
].join('\n')
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ exports[`compiler: hoistStatic transform hoist element with static key 1`] = `
|
||||
"const _Vue = Vue
|
||||
const { createVNode: _createVNode } = _Vue
|
||||
|
||||
const _hoisted_1 = _createVNode(\\"div\\", { key: \\"foo\\" }, null, -1)
|
||||
const _hoisted_1 = _createVNode(\\"div\\", { key: \\"foo\\" }, null, -2 /* HOISTED */)
|
||||
|
||||
return function render(_ctx, _cache) {
|
||||
with (this) {
|
||||
@@ -24,7 +24,7 @@ const { createVNode: _createVNode } = _Vue
|
||||
const _hoisted_1 = _createVNode(\\"p\\", null, [
|
||||
_createVNode(\\"span\\"),
|
||||
_createVNode(\\"span\\")
|
||||
], -1)
|
||||
], -2 /* HOISTED */)
|
||||
|
||||
return function render(_ctx, _cache) {
|
||||
with (this) {
|
||||
@@ -43,7 +43,7 @@ const { createVNode: _createVNode, createCommentVNode: _createCommentVNode } = _
|
||||
|
||||
const _hoisted_1 = _createVNode(\\"div\\", null, [
|
||||
_createCommentVNode(\\"comment\\")
|
||||
], -1)
|
||||
], -2 /* HOISTED */)
|
||||
|
||||
return function render(_ctx, _cache) {
|
||||
with (this) {
|
||||
@@ -60,8 +60,8 @@ exports[`compiler: hoistStatic transform hoist siblings with common non-hoistabl
|
||||
"const _Vue = Vue
|
||||
const { createVNode: _createVNode } = _Vue
|
||||
|
||||
const _hoisted_1 = _createVNode(\\"span\\", null, null, -1)
|
||||
const _hoisted_2 = _createVNode(\\"div\\", null, null, -1)
|
||||
const _hoisted_1 = _createVNode(\\"span\\", null, null, -2 /* HOISTED */)
|
||||
const _hoisted_2 = _createVNode(\\"div\\", null, null, -2 /* HOISTED */)
|
||||
|
||||
return function render(_ctx, _cache) {
|
||||
with (this) {
|
||||
@@ -79,7 +79,7 @@ exports[`compiler: hoistStatic transform hoist simple element 1`] = `
|
||||
"const _Vue = Vue
|
||||
const { createVNode: _createVNode } = _Vue
|
||||
|
||||
const _hoisted_1 = _createVNode(\\"span\\", { class: \\"inline\\" }, \\"hello\\", -1)
|
||||
const _hoisted_1 = _createVNode(\\"span\\", { class: \\"inline\\" }, \\"hello\\", -2 /* HOISTED */)
|
||||
|
||||
return function render(_ctx, _cache) {
|
||||
with (this) {
|
||||
@@ -105,7 +105,7 @@ return function render(_ctx, _cache) {
|
||||
const _directive_foo = _resolveDirective(\\"foo\\")
|
||||
|
||||
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||
_withDirectives(_createVNode(\\"div\\", _hoisted_1, null, 32 /* NEED_PATCH */), [
|
||||
_withDirectives(_createVNode(\\"div\\", _hoisted_1, null, -1 /* NEED_PATCH */), [
|
||||
[_directive_foo]
|
||||
])
|
||||
]))
|
||||
@@ -172,7 +172,7 @@ exports[`compiler: hoistStatic transform prefixIdentifiers hoist nested static t
|
||||
"const _Vue = Vue
|
||||
const { createVNode: _createVNode } = _Vue
|
||||
|
||||
const _hoisted_1 = _createVNode(\\"span\\", null, \\"foo \\" + _toDisplayString(1) + \\" \\" + _toDisplayString(true), -1)
|
||||
const _hoisted_1 = _createVNode(\\"span\\", null, \\"foo \\" + _toDisplayString(1) + \\" \\" + _toDisplayString(true), -2 /* HOISTED */)
|
||||
|
||||
return function render(_ctx, _cache) {
|
||||
with (this) {
|
||||
@@ -189,7 +189,7 @@ exports[`compiler: hoistStatic transform prefixIdentifiers hoist nested static t
|
||||
"const _Vue = Vue
|
||||
const { createVNode: _createVNode } = _Vue
|
||||
|
||||
const _hoisted_1 = _createVNode(\\"span\\", { foo: 0 }, _toDisplayString(1), -1)
|
||||
const _hoisted_1 = _createVNode(\\"span\\", { foo: 0 }, _toDisplayString(1), -2 /* HOISTED */)
|
||||
|
||||
return function render(_ctx, _cache) {
|
||||
with (this) {
|
||||
@@ -323,7 +323,7 @@ return function render(_ctx, _cache) {
|
||||
const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
||||
|
||||
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||
_createVNode(\\"div\\", { ref: foo }, null, 32 /* NEED_PATCH */)
|
||||
_createVNode(\\"div\\", { ref: foo }, null, -1 /* NEED_PATCH */)
|
||||
]))
|
||||
}
|
||||
}"
|
||||
@@ -346,7 +346,7 @@ exports[`compiler: hoistStatic transform should hoist v-for children if static 1
|
||||
const { createVNode: _createVNode } = _Vue
|
||||
|
||||
const _hoisted_1 = { id: \\"foo\\" }
|
||||
const _hoisted_2 = _createVNode(\\"span\\", null, null, -1)
|
||||
const _hoisted_2 = _createVNode(\\"span\\", null, null, -2 /* HOISTED */)
|
||||
|
||||
return function render(_ctx, _cache) {
|
||||
with (this) {
|
||||
@@ -371,7 +371,7 @@ const _hoisted_1 = {
|
||||
key: 0,
|
||||
id: \\"foo\\"
|
||||
}
|
||||
const _hoisted_2 = _createVNode(\\"span\\", null, null, -1)
|
||||
const _hoisted_2 = _createVNode(\\"span\\", null, null, -2 /* HOISTED */)
|
||||
|
||||
return function render(_ctx, _cache) {
|
||||
with (this) {
|
||||
|
||||
@@ -142,7 +142,7 @@ return function render(_ctx, _cache) {
|
||||
const _directive_foo = _resolveDirective(\\"foo\\")
|
||||
|
||||
return (_openBlock(true), _createBlock(_Fragment, null, _renderList(list, (i) => {
|
||||
return _withDirectives((_openBlock(), _createBlock(\\"div\\", null, null, 32 /* NEED_PATCH */)), [
|
||||
return _withDirectives((_openBlock(), _createBlock(\\"div\\", null, null, -1 /* NEED_PATCH */)), [
|
||||
[_directive_foo]
|
||||
])
|
||||
}), 256 /* UNKEYED_FRAGMENT */))
|
||||
|
||||
@@ -52,7 +52,8 @@ function walk(
|
||||
) {
|
||||
if (!doNotHoistNode && isStaticNode(child, resultCache)) {
|
||||
// whole tree is static
|
||||
;(child.codegenNode as VNodeCall).patchFlag = PatchFlags.HOISTED + ``
|
||||
;(child.codegenNode as VNodeCall).patchFlag =
|
||||
PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``)
|
||||
const hoisted = context.transformHoist
|
||||
? context.transformHoist(child, context)
|
||||
: child.codegenNode!
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
DirectiveArguments,
|
||||
createVNodeCall
|
||||
} from '../ast'
|
||||
import { PatchFlags, PatchFlagNames, isSymbol } from '@vue/shared'
|
||||
import { PatchFlags, PatchFlagNames, isSymbol, isOn } from '@vue/shared'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import {
|
||||
RESOLVE_DIRECTIVE,
|
||||
@@ -159,12 +159,18 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||
// patchFlag & dynamicPropNames
|
||||
if (patchFlag !== 0) {
|
||||
if (__DEV__) {
|
||||
const flagNames = Object.keys(PatchFlagNames)
|
||||
.map(Number)
|
||||
.filter(n => n > 0 && patchFlag & n)
|
||||
.map(n => PatchFlagNames[n])
|
||||
.join(`, `)
|
||||
vnodePatchFlag = patchFlag + ` /* ${flagNames} */`
|
||||
if (patchFlag < 0) {
|
||||
// special flags (negative and mutually exclusive)
|
||||
vnodePatchFlag = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`
|
||||
} else {
|
||||
// bitwise flags
|
||||
const flagNames = Object.keys(PatchFlagNames)
|
||||
.map(Number)
|
||||
.filter(n => n > 0 && patchFlag & n)
|
||||
.map(n => PatchFlagNames[n])
|
||||
.join(`, `)
|
||||
vnodePatchFlag = patchFlag + ` /* ${flagNames} */`
|
||||
}
|
||||
} else {
|
||||
vnodePatchFlag = String(patchFlag)
|
||||
}
|
||||
@@ -256,20 +262,27 @@ export function buildProps(
|
||||
let hasRef = false
|
||||
let hasClassBinding = false
|
||||
let hasStyleBinding = false
|
||||
let hasHydrationEventBinding = false
|
||||
let hasDynamicKeys = false
|
||||
const dynamicPropNames: string[] = []
|
||||
|
||||
const analyzePatchFlag = ({ key, value }: Property) => {
|
||||
if (key.type === NodeTypes.SIMPLE_EXPRESSION && key.isStatic) {
|
||||
const name = key.content
|
||||
if (!isComponent && isOn(name) && name.toLowerCase() !== 'onclick') {
|
||||
// This flag is for hydrating event handlers only. We omit the flag for
|
||||
// click handlers becaues hydration gives click dedicated fast path.
|
||||
hasHydrationEventBinding = true
|
||||
}
|
||||
if (
|
||||
value.type === NodeTypes.JS_CACHE_EXPRESSION ||
|
||||
((value.type === NodeTypes.SIMPLE_EXPRESSION ||
|
||||
value.type === NodeTypes.COMPOUND_EXPRESSION) &&
|
||||
isStaticNode(value))
|
||||
) {
|
||||
// skip if the prop is a cached handler or has constant value
|
||||
return
|
||||
}
|
||||
const name = key.content
|
||||
if (name === 'ref') {
|
||||
hasRef = true
|
||||
} else if (name === 'class') {
|
||||
@@ -430,9 +443,12 @@ export function buildProps(
|
||||
if (dynamicPropNames.length) {
|
||||
patchFlag |= PatchFlags.PROPS
|
||||
}
|
||||
if (hasHydrationEventBinding) {
|
||||
patchFlag |= PatchFlags.HYDRATE_EVENTS
|
||||
}
|
||||
}
|
||||
if (patchFlag === 0 && (hasRef || runtimeDirectives.length > 0)) {
|
||||
patchFlag |= PatchFlags.NEED_PATCH
|
||||
patchFlag = PatchFlags.NEED_PATCH
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user