mirror of https://github.com/vuejs/core.git
fix(runtime-vapor): reset insertion state to avoid duplicate block inserts during non-hydration (#13220)
This commit is contained in:
parent
99482a4ddf
commit
99a8c6d34b
|
@ -211,38 +211,42 @@ color: red
|
||||||
expect(
|
expect(
|
||||||
compileScoped(`.div { color: red; } .div:where(:hover) { color: blue; }`),
|
compileScoped(`.div { color: red; } .div:where(:hover) { color: blue; }`),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
".div[data-v-test] { color: red;
|
".div[data-v-test] { color: red;
|
||||||
}
|
}
|
||||||
.div[data-v-test]:where(:hover) { color: blue;
|
.div[data-v-test]:where(:hover) { color: blue;
|
||||||
}"`)
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
compileScoped(`.div { color: red; } .div:is(:hover) { color: blue; }`),
|
compileScoped(`.div { color: red; } .div:is(:hover) { color: blue; }`),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
".div[data-v-test] { color: red;
|
".div[data-v-test] { color: red;
|
||||||
}
|
}
|
||||||
.div[data-v-test]:is(:hover) { color: blue;
|
.div[data-v-test]:is(:hover) { color: blue;
|
||||||
}"`)
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
compileScoped(
|
compileScoped(
|
||||||
`.div { color: red; } .div:where(.foo:hover) { color: blue; }`,
|
`.div { color: red; } .div:where(.foo:hover) { color: blue; }`,
|
||||||
),
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
".div[data-v-test] { color: red;
|
".div[data-v-test] { color: red;
|
||||||
}
|
}
|
||||||
.div[data-v-test]:where(.foo:hover) { color: blue;
|
.div[data-v-test]:where(.foo:hover) { color: blue;
|
||||||
}"`)
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
compileScoped(
|
compileScoped(
|
||||||
`.div { color: red; } .div:is(.foo:hover) { color: blue; }`,
|
`.div { color: red; } .div:is(.foo:hover) { color: blue; }`,
|
||||||
),
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
".div[data-v-test] { color: red;
|
".div[data-v-test] { color: red;
|
||||||
}
|
}
|
||||||
.div[data-v-test]:is(.foo:hover) { color: blue;
|
.div[data-v-test]:is(.foo:hover) { color: blue;
|
||||||
}"`)
|
}"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('media query', () => {
|
test('media query', () => {
|
||||||
|
|
|
@ -44,7 +44,7 @@ export function genOperationWithInsertionState(
|
||||||
): CodeFragment[] {
|
): CodeFragment[] {
|
||||||
const [frag, push] = buildCodeFragment()
|
const [frag, push] = buildCodeFragment()
|
||||||
if (isBlockOperation(oper) && oper.parent) {
|
if (isBlockOperation(oper) && oper.parent) {
|
||||||
push(...genInsertionstate(oper, context))
|
push(...genInsertionState(oper, context))
|
||||||
}
|
}
|
||||||
push(...genOperation(oper, context))
|
push(...genOperation(oper, context))
|
||||||
return frag
|
return frag
|
||||||
|
@ -152,7 +152,7 @@ export function genEffect(
|
||||||
return frag
|
return frag
|
||||||
}
|
}
|
||||||
|
|
||||||
function genInsertionstate(
|
function genInsertionState(
|
||||||
operation: InsertionStateTypes,
|
operation: InsertionStateTypes,
|
||||||
context: CodegenContext,
|
context: CodegenContext,
|
||||||
): CodeFragment[] {
|
): CodeFragment[] {
|
||||||
|
|
|
@ -23,7 +23,11 @@ import type { DynamicSlot } from './componentSlots'
|
||||||
import { renderEffect } from './renderEffect'
|
import { renderEffect } from './renderEffect'
|
||||||
import { VaporVForFlags } from '../../shared/src/vaporFlags'
|
import { VaporVForFlags } from '../../shared/src/vaporFlags'
|
||||||
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
||||||
import { insertionAnchor, insertionParent } from './insertionState'
|
import {
|
||||||
|
insertionAnchor,
|
||||||
|
insertionParent,
|
||||||
|
resetInsertionState,
|
||||||
|
} from './insertionState'
|
||||||
|
|
||||||
class ForBlock extends VaporFragment {
|
class ForBlock extends VaporFragment {
|
||||||
scope: EffectScope | undefined
|
scope: EffectScope | undefined
|
||||||
|
@ -72,6 +76,8 @@ export const createFor = (
|
||||||
const _insertionAnchor = insertionAnchor
|
const _insertionAnchor = insertionAnchor
|
||||||
if (isHydrating) {
|
if (isHydrating) {
|
||||||
locateHydrationNode()
|
locateHydrationNode()
|
||||||
|
} else {
|
||||||
|
resetInsertionState()
|
||||||
}
|
}
|
||||||
|
|
||||||
let isMounted = false
|
let isMounted = false
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import { type Block, type BlockFn, DynamicFragment, insert } from './block'
|
import { type Block, type BlockFn, DynamicFragment, insert } from './block'
|
||||||
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
||||||
import { insertionAnchor, insertionParent } from './insertionState'
|
import {
|
||||||
|
insertionAnchor,
|
||||||
|
insertionParent,
|
||||||
|
resetInsertionState,
|
||||||
|
} from './insertionState'
|
||||||
import { renderEffect } from './renderEffect'
|
import { renderEffect } from './renderEffect'
|
||||||
|
|
||||||
export function createIf(
|
export function createIf(
|
||||||
|
@ -13,6 +17,8 @@ export function createIf(
|
||||||
const _insertionAnchor = insertionAnchor
|
const _insertionAnchor = insertionAnchor
|
||||||
if (isHydrating) {
|
if (isHydrating) {
|
||||||
locateHydrationNode()
|
locateHydrationNode()
|
||||||
|
} else {
|
||||||
|
resetInsertionState()
|
||||||
}
|
}
|
||||||
|
|
||||||
let frag: Block
|
let frag: Block
|
||||||
|
|
|
@ -59,7 +59,11 @@ import {
|
||||||
} from './componentSlots'
|
} from './componentSlots'
|
||||||
import { hmrReload, hmrRerender } from './hmr'
|
import { hmrReload, hmrRerender } from './hmr'
|
||||||
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
||||||
import { insertionAnchor, insertionParent } from './insertionState'
|
import {
|
||||||
|
insertionAnchor,
|
||||||
|
insertionParent,
|
||||||
|
resetInsertionState,
|
||||||
|
} from './insertionState'
|
||||||
|
|
||||||
export { currentInstance } from '@vue/runtime-dom'
|
export { currentInstance } from '@vue/runtime-dom'
|
||||||
|
|
||||||
|
@ -142,6 +146,8 @@ export function createComponent(
|
||||||
const _insertionAnchor = insertionAnchor
|
const _insertionAnchor = insertionAnchor
|
||||||
if (isHydrating) {
|
if (isHydrating) {
|
||||||
locateHydrationNode()
|
locateHydrationNode()
|
||||||
|
} else {
|
||||||
|
resetInsertionState()
|
||||||
}
|
}
|
||||||
|
|
||||||
// vdom interop enabled and component is not an explicit vapor component
|
// vdom interop enabled and component is not an explicit vapor component
|
||||||
|
|
|
@ -4,7 +4,11 @@ import { rawPropsProxyHandlers } from './componentProps'
|
||||||
import { currentInstance, isRef } from '@vue/runtime-dom'
|
import { currentInstance, isRef } from '@vue/runtime-dom'
|
||||||
import type { LooseRawProps, VaporComponentInstance } from './component'
|
import type { LooseRawProps, VaporComponentInstance } from './component'
|
||||||
import { renderEffect } from './renderEffect'
|
import { renderEffect } from './renderEffect'
|
||||||
import { insertionAnchor, insertionParent } from './insertionState'
|
import {
|
||||||
|
insertionAnchor,
|
||||||
|
insertionParent,
|
||||||
|
resetInsertionState,
|
||||||
|
} from './insertionState'
|
||||||
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
||||||
|
|
||||||
export type RawSlots = Record<string, VaporSlot> & {
|
export type RawSlots = Record<string, VaporSlot> & {
|
||||||
|
@ -96,6 +100,8 @@ export function createSlot(
|
||||||
const _insertionAnchor = insertionAnchor
|
const _insertionAnchor = insertionAnchor
|
||||||
if (isHydrating) {
|
if (isHydrating) {
|
||||||
locateHydrationNode()
|
locateHydrationNode()
|
||||||
|
} else {
|
||||||
|
resetInsertionState()
|
||||||
}
|
}
|
||||||
|
|
||||||
const instance = currentInstance as VaporComponentInstance
|
const instance = currentInstance as VaporComponentInstance
|
||||||
|
|
|
@ -49,7 +49,7 @@ test('pipeToWebWritable', async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { readable, writable } = new TransformStream()
|
const { readable, writable } = new TransformStream()
|
||||||
pipeToWebWritable(createApp(App), {}, writable)
|
pipeToWebWritable(createApp(App), {}, writable as any)
|
||||||
|
|
||||||
const reader = readable.getReader()
|
const reader = readable.getReader()
|
||||||
const decoder = new TextDecoder()
|
const decoder = new TextDecoder()
|
||||||
|
|
3050
pnpm-lock.yaml
3050
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue