@@ -1,6 +1,6 @@
|
||||
import { isFunction } from '@vue/shared'
|
||||
import { currentInstance } from './component'
|
||||
import { currentRenderingInstance } from './componentRenderUtils'
|
||||
import { currentRenderingInstance } from './componentRenderContext'
|
||||
import { warn } from './warning'
|
||||
|
||||
export interface InjectionKey<T> extends Symbol {}
|
||||
|
||||
@@ -51,10 +51,8 @@ import {
|
||||
} from '@vue/shared'
|
||||
import { SuspenseBoundary } from './components/Suspense'
|
||||
import { CompilerOptions } from '@vue/compiler-core'
|
||||
import {
|
||||
currentRenderingInstance,
|
||||
markAttrsAccessed
|
||||
} from './componentRenderUtils'
|
||||
import { markAttrsAccessed } from './componentRenderUtils'
|
||||
import { currentRenderingInstance } from './componentRenderContext'
|
||||
import { startMeasure, endMeasure } from './profiling'
|
||||
|
||||
export type Data = Record<string, unknown>
|
||||
|
||||
@@ -35,10 +35,8 @@ import {
|
||||
} from './componentOptions'
|
||||
import { EmitsOptions, EmitFn } from './componentEmits'
|
||||
import { Slots } from './componentSlots'
|
||||
import {
|
||||
currentRenderingInstance,
|
||||
markAttrsAccessed
|
||||
} from './componentRenderUtils'
|
||||
import { markAttrsAccessed } from './componentRenderUtils'
|
||||
import { currentRenderingInstance } from './componentRenderContext'
|
||||
import { warn } from './warning'
|
||||
import { UnionToIntersection } from './helpers/typeUtils'
|
||||
|
||||
|
||||
57
packages/runtime-core/src/componentRenderContext.ts
Normal file
57
packages/runtime-core/src/componentRenderContext.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { ComponentInternalInstance } from './component'
|
||||
import { isRenderingCompiledSlot } from './helpers/renderSlot'
|
||||
import { closeBlock, openBlock } from './vnode'
|
||||
|
||||
/**
|
||||
* mark the current rendering instance for asset resolution (e.g.
|
||||
* resolveComponent, resolveDirective) during render
|
||||
*/
|
||||
export let currentRenderingInstance: ComponentInternalInstance | null = null
|
||||
export let currentScopeId: string | null = null
|
||||
|
||||
export function setCurrentRenderingInstance(
|
||||
instance: ComponentInternalInstance | null
|
||||
) {
|
||||
currentRenderingInstance = instance
|
||||
currentScopeId = (instance && instance.type.__scopeId) || null
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scope id when creating hoisted vnodes.
|
||||
* @private compiler helper
|
||||
*/
|
||||
export function setScopeId(id: string | null) {
|
||||
currentScopeId = id
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a slot function to memoize current rendering instance
|
||||
* @private compiler helper
|
||||
*/
|
||||
export function withCtx(
|
||||
fn: Function,
|
||||
ctx: ComponentInternalInstance | null = currentRenderingInstance
|
||||
) {
|
||||
if (!ctx) return fn
|
||||
const renderFnWithContext = (...args: any[]) => {
|
||||
// If a user calls a compiled slot inside a template expression (#1745), it
|
||||
// can mess up block tracking, so by default we need to push a null block to
|
||||
// avoid that. This isn't necessary if rendering a compiled `<slot>`.
|
||||
if (!isRenderingCompiledSlot) {
|
||||
openBlock(true /* null block that disables tracking */)
|
||||
}
|
||||
const prevInstance = currentRenderingInstance
|
||||
setCurrentRenderingInstance(ctx)
|
||||
const res = fn(...args)
|
||||
setCurrentRenderingInstance(prevInstance)
|
||||
if (!isRenderingCompiledSlot) {
|
||||
closeBlock()
|
||||
}
|
||||
return res
|
||||
}
|
||||
// mark this as a compiled slot function.
|
||||
// this is used in vnode.ts -> normalizeChildren() to set the slot
|
||||
// rendering flag.
|
||||
renderFnWithContext._c = true
|
||||
return renderFnWithContext
|
||||
}
|
||||
@@ -18,18 +18,7 @@ import { warn } from './warning'
|
||||
import { isHmrUpdating } from './hmr'
|
||||
import { NormalizedProps } from './componentProps'
|
||||
import { isEmitListener } from './componentEmits'
|
||||
|
||||
/**
|
||||
* mark the current rendering instance for asset resolution (e.g.
|
||||
* resolveComponent, resolveDirective) during render
|
||||
*/
|
||||
export let currentRenderingInstance: ComponentInternalInstance | null = null
|
||||
|
||||
export function setCurrentRenderingInstance(
|
||||
instance: ComponentInternalInstance | null
|
||||
) {
|
||||
currentRenderingInstance = instance
|
||||
}
|
||||
import { setCurrentRenderingInstance } from './componentRenderContext'
|
||||
|
||||
/**
|
||||
* dev only flag to track whether $attrs was used during render.
|
||||
@@ -63,7 +52,7 @@ export function renderComponentRoot(
|
||||
} = instance
|
||||
|
||||
let result
|
||||
currentRenderingInstance = instance
|
||||
setCurrentRenderingInstance(instance)
|
||||
if (__DEV__) {
|
||||
accessedAttrs = false
|
||||
}
|
||||
@@ -215,8 +204,8 @@ export function renderComponentRoot(
|
||||
handleError(err, instance, ErrorCodes.RENDER_FUNCTION)
|
||||
result = createVNode(Comment)
|
||||
}
|
||||
currentRenderingInstance = null
|
||||
|
||||
setCurrentRenderingInstance(null)
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from '@vue/shared'
|
||||
import { warn } from './warning'
|
||||
import { isKeepAlive } from './components/KeepAlive'
|
||||
import { withCtx } from './helpers/withRenderContext'
|
||||
import { withCtx } from './componentRenderContext'
|
||||
import { isHmrUpdating } from './hmr'
|
||||
|
||||
export type Slot = (...args: any[]) => VNode[]
|
||||
|
||||
@@ -112,6 +112,7 @@ const KeepAliveImpl = {
|
||||
instance,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
vnode.slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
queuePostRenderEffect(() => {
|
||||
|
||||
@@ -46,6 +46,7 @@ export const SuspenseImpl = {
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean,
|
||||
// platform-specific impl passed from renderer
|
||||
rendererInternals: RendererInternals
|
||||
@@ -58,6 +59,7 @@ export const SuspenseImpl = {
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized,
|
||||
rendererInternals
|
||||
)
|
||||
@@ -69,6 +71,8 @@ export const SuspenseImpl = {
|
||||
anchor,
|
||||
parentComponent,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized,
|
||||
rendererInternals
|
||||
)
|
||||
}
|
||||
@@ -92,6 +96,7 @@ function mountSuspense(
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean,
|
||||
rendererInternals: RendererInternals
|
||||
) {
|
||||
@@ -108,6 +113,7 @@ function mountSuspense(
|
||||
hiddenContainer,
|
||||
anchor,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized,
|
||||
rendererInternals
|
||||
))
|
||||
@@ -120,7 +126,8 @@ function mountSuspense(
|
||||
null,
|
||||
parentComponent,
|
||||
suspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds
|
||||
)
|
||||
// now check if we have encountered any async deps
|
||||
if (suspense.deps > 0) {
|
||||
@@ -133,7 +140,8 @@ function mountSuspense(
|
||||
anchor,
|
||||
parentComponent,
|
||||
null, // fallback tree will not have suspense context
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds
|
||||
)
|
||||
setActiveBranch(suspense, vnode.ssFallback!)
|
||||
} else {
|
||||
@@ -149,6 +157,8 @@ function patchSuspense(
|
||||
anchor: RendererNode | null,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean,
|
||||
{ p: patch, um: unmount, o: { createElement } }: RendererInternals
|
||||
) {
|
||||
const suspense = (n2.suspense = n1.suspense)!
|
||||
@@ -169,7 +179,9 @@ function patchSuspense(
|
||||
null,
|
||||
parentComponent,
|
||||
suspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
if (suspense.deps <= 0) {
|
||||
suspense.resolve()
|
||||
@@ -181,7 +193,9 @@ function patchSuspense(
|
||||
anchor,
|
||||
parentComponent,
|
||||
null, // fallback tree will not have suspense context
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
setActiveBranch(suspense, newFallback)
|
||||
}
|
||||
@@ -214,7 +228,9 @@ function patchSuspense(
|
||||
null,
|
||||
parentComponent,
|
||||
suspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
if (suspense.deps <= 0) {
|
||||
suspense.resolve()
|
||||
@@ -226,7 +242,9 @@ function patchSuspense(
|
||||
anchor,
|
||||
parentComponent,
|
||||
null, // fallback tree will not have suspense context
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
setActiveBranch(suspense, newFallback)
|
||||
}
|
||||
@@ -239,7 +257,9 @@ function patchSuspense(
|
||||
anchor,
|
||||
parentComponent,
|
||||
suspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
// force resolve
|
||||
suspense.resolve(true)
|
||||
@@ -252,7 +272,9 @@ function patchSuspense(
|
||||
null,
|
||||
parentComponent,
|
||||
suspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
if (suspense.deps <= 0) {
|
||||
suspense.resolve()
|
||||
@@ -269,7 +291,9 @@ function patchSuspense(
|
||||
anchor,
|
||||
parentComponent,
|
||||
suspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
setActiveBranch(suspense, newBranch)
|
||||
} else {
|
||||
@@ -289,7 +313,9 @@ function patchSuspense(
|
||||
null,
|
||||
parentComponent,
|
||||
suspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
if (suspense.deps <= 0) {
|
||||
// incoming branch has no async deps, resolve now.
|
||||
@@ -352,6 +378,7 @@ function createSuspenseBoundary(
|
||||
hiddenContainer: RendererElement,
|
||||
anchor: RendererNode | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean,
|
||||
rendererInternals: RendererInternals,
|
||||
isHydrating = false
|
||||
@@ -507,7 +534,9 @@ function createSuspenseBoundary(
|
||||
anchor,
|
||||
parentComponent,
|
||||
null, // fallback tree will not have suspense context
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
setActiveBranch(suspense, fallbackVNode)
|
||||
}
|
||||
@@ -632,6 +661,7 @@ function hydrateSuspense(
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean,
|
||||
rendererInternals: RendererInternals,
|
||||
hydrateNode: (
|
||||
@@ -639,6 +669,7 @@ function hydrateSuspense(
|
||||
vnode: VNode,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => Node | null
|
||||
): Node | null {
|
||||
@@ -651,6 +682,7 @@ function hydrateSuspense(
|
||||
document.createElement('div'),
|
||||
null,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized,
|
||||
rendererInternals,
|
||||
true /* hydrating */
|
||||
@@ -666,6 +698,7 @@ function hydrateSuspense(
|
||||
(suspense.pendingBranch = vnode.ssContent!),
|
||||
parentComponent,
|
||||
suspense,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
if (suspense.deps === 0) {
|
||||
|
||||
@@ -71,6 +71,7 @@ export const TeleportImpl = {
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean,
|
||||
internals: RendererInternals
|
||||
) {
|
||||
@@ -115,6 +116,7 @@ export const TeleportImpl = {
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
}
|
||||
@@ -144,7 +146,8 @@ export const TeleportImpl = {
|
||||
currentContainer,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds
|
||||
)
|
||||
// even in block tree mode we need to make sure all root-level nodes
|
||||
// in the teleport inherit previous DOM references so that they can
|
||||
@@ -158,7 +161,9 @@ export const TeleportImpl = {
|
||||
currentAnchor,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -283,6 +288,7 @@ function hydrateTeleport(
|
||||
vnode: TeleportVNode,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean,
|
||||
{
|
||||
o: { nextSibling, parentNode, querySelector }
|
||||
@@ -293,6 +299,7 @@ function hydrateTeleport(
|
||||
container: Element,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => Node | null
|
||||
): Node | null {
|
||||
@@ -313,6 +320,7 @@ function hydrateTeleport(
|
||||
parentNode(node)!,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
vnode.targetAnchor = targetNode
|
||||
@@ -324,6 +332,7 @@ function hydrateTeleport(
|
||||
target,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { VNode } from './vnode'
|
||||
import { isFunction, EMPTY_OBJ, makeMap } from '@vue/shared'
|
||||
import { warn } from './warning'
|
||||
import { ComponentInternalInstance, Data } from './component'
|
||||
import { currentRenderingInstance } from './componentRenderUtils'
|
||||
import { currentRenderingInstance } from './componentRenderContext'
|
||||
import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
|
||||
import { ComponentPublicInstance } from './componentPublicInstance'
|
||||
|
||||
|
||||
@@ -53,6 +53,10 @@ export function renderSlot(
|
||||
? PatchFlags.STABLE_FRAGMENT
|
||||
: PatchFlags.BAIL
|
||||
)
|
||||
// TODO (optimization) only add slot scope id if :slotted is used
|
||||
if (rendered.scopeId) {
|
||||
rendered.slotScopeIds = [rendered.scopeId + '-s']
|
||||
}
|
||||
isRenderingCompiledSlot--
|
||||
return rendered
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { currentRenderingInstance } from '../componentRenderUtils'
|
||||
import {
|
||||
currentInstance,
|
||||
ConcreteComponent,
|
||||
ComponentOptions,
|
||||
getComponentName
|
||||
} from '../component'
|
||||
import { currentRenderingInstance } from '../componentRenderContext'
|
||||
import { Directive } from '../directives'
|
||||
import { camelize, capitalize, isString } from '@vue/shared'
|
||||
import { warn } from '../warning'
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
// SFC scoped style ID management.
|
||||
// These are only used in esm-bundler builds, but since exports cannot be
|
||||
// conditional, we can only drop inner implementations in non-bundler builds.
|
||||
|
||||
import { withCtx } from './withRenderContext'
|
||||
|
||||
export let currentScopeId: string | null = null
|
||||
const scopeIdStack: string[] = []
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function pushScopeId(id: string) {
|
||||
scopeIdStack.push((currentScopeId = id))
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function popScopeId() {
|
||||
scopeIdStack.pop()
|
||||
currentScopeId = scopeIdStack[scopeIdStack.length - 1] || null
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function withScopeId(id: string): <T extends Function>(fn: T) => T {
|
||||
return ((fn: Function) =>
|
||||
withCtx(function(this: any) {
|
||||
pushScopeId(id)
|
||||
const res = fn.apply(this, arguments)
|
||||
popScopeId()
|
||||
return res
|
||||
})) as any
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import { Slot } from '../componentSlots'
|
||||
import {
|
||||
setCurrentRenderingInstance,
|
||||
currentRenderingInstance
|
||||
} from '../componentRenderUtils'
|
||||
import { ComponentInternalInstance } from '../component'
|
||||
import { isRenderingCompiledSlot } from './renderSlot'
|
||||
import { closeBlock, openBlock } from '../vnode'
|
||||
|
||||
/**
|
||||
* Wrap a slot function to memoize current rendering instance
|
||||
* @private
|
||||
*/
|
||||
export function withCtx(
|
||||
fn: Slot,
|
||||
ctx: ComponentInternalInstance | null = currentRenderingInstance
|
||||
) {
|
||||
if (!ctx) return fn
|
||||
const renderFnWithContext = (...args: any[]) => {
|
||||
// If a user calls a compiled slot inside a template expression (#1745), it
|
||||
// can mess up block tracking, so by default we need to push a null block to
|
||||
// avoid that. This isn't necessary if rendering a compiled `<slot>`.
|
||||
if (!isRenderingCompiledSlot) {
|
||||
openBlock(true /* null block that disables tracking */)
|
||||
}
|
||||
const owner = currentRenderingInstance
|
||||
setCurrentRenderingInstance(ctx)
|
||||
const res = fn(...args)
|
||||
setCurrentRenderingInstance(owner)
|
||||
if (!isRenderingCompiledSlot) {
|
||||
closeBlock()
|
||||
}
|
||||
return res
|
||||
}
|
||||
renderFnWithContext._c = true
|
||||
return renderFnWithContext
|
||||
}
|
||||
@@ -63,7 +63,7 @@ export function createHydrationFunctions(
|
||||
return
|
||||
}
|
||||
hasMismatch = false
|
||||
hydrateNode(container.firstChild!, vnode, null, null)
|
||||
hydrateNode(container.firstChild!, vnode, null, null, null)
|
||||
flushPostFlushCbs()
|
||||
if (hasMismatch && !__TEST__) {
|
||||
// this error should show up in production
|
||||
@@ -76,6 +76,7 @@ export function createHydrationFunctions(
|
||||
vnode: VNode,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized = false
|
||||
): Node | null => {
|
||||
const isFragmentStart = isComment(node) && node.data === '['
|
||||
@@ -85,6 +86,7 @@ export function createHydrationFunctions(
|
||||
vnode,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
slotScopeIds,
|
||||
isFragmentStart
|
||||
)
|
||||
|
||||
@@ -147,6 +149,7 @@ export function createHydrationFunctions(
|
||||
vnode,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
}
|
||||
@@ -164,6 +167,7 @@ export function createHydrationFunctions(
|
||||
vnode,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
}
|
||||
@@ -171,6 +175,7 @@ export function createHydrationFunctions(
|
||||
// when setting up the render effect, if the initial vnode already
|
||||
// has .el set, the component will perform hydration instead of mount
|
||||
// on its sub-tree.
|
||||
vnode.slotScopeIds = slotScopeIds
|
||||
const container = parentNode(node)!
|
||||
const hydrateComponent = () => {
|
||||
mountComponent(
|
||||
@@ -205,6 +210,7 @@ export function createHydrationFunctions(
|
||||
vnode as TeleportVNode,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
slotScopeIds,
|
||||
optimized,
|
||||
rendererInternals,
|
||||
hydrateChildren
|
||||
@@ -217,6 +223,7 @@ export function createHydrationFunctions(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVGContainer(parentNode(node)!),
|
||||
slotScopeIds,
|
||||
optimized,
|
||||
rendererInternals,
|
||||
hydrateNode
|
||||
@@ -238,6 +245,7 @@ export function createHydrationFunctions(
|
||||
vnode: VNode,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => {
|
||||
optimized = optimized || !!vnode.dynamicChildren
|
||||
@@ -291,6 +299,7 @@ export function createHydrationFunctions(
|
||||
el,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
let hasWarned = false
|
||||
@@ -330,6 +339,7 @@ export function createHydrationFunctions(
|
||||
container: Element,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
): Node | null => {
|
||||
optimized = optimized || !!parentVNode.dynamicChildren
|
||||
@@ -346,6 +356,7 @@ export function createHydrationFunctions(
|
||||
vnode,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
} else {
|
||||
@@ -365,7 +376,8 @@ export function createHydrationFunctions(
|
||||
null,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVGContainer(container)
|
||||
isSVGContainer(container),
|
||||
slotScopeIds
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -377,8 +389,16 @@ export function createHydrationFunctions(
|
||||
vnode: VNode,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => {
|
||||
const { slotScopeIds: fragmentSlotScopeIds } = vnode
|
||||
if (fragmentSlotScopeIds) {
|
||||
slotScopeIds = slotScopeIds
|
||||
? slotScopeIds.concat(fragmentSlotScopeIds)
|
||||
: fragmentSlotScopeIds
|
||||
}
|
||||
|
||||
const container = parentNode(node)!
|
||||
const next = hydrateChildren(
|
||||
nextSibling(node)!,
|
||||
@@ -386,6 +406,7 @@ export function createHydrationFunctions(
|
||||
container,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
if (next && isComment(next) && next.data === ']') {
|
||||
@@ -405,6 +426,7 @@ export function createHydrationFunctions(
|
||||
vnode: VNode,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
slotScopeIds: string[] | null,
|
||||
isFragment: boolean
|
||||
): Node | null => {
|
||||
hasMismatch = true
|
||||
@@ -446,7 +468,8 @@ export function createHydrationFunctions(
|
||||
next,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVGContainer(container)
|
||||
isSVGContainer(container),
|
||||
slotScopeIds
|
||||
)
|
||||
return next
|
||||
}
|
||||
|
||||
@@ -227,12 +227,11 @@ export { HMRRuntime } from './hmr'
|
||||
|
||||
// For compiler generated code
|
||||
// should sync with '@vue/compiler-core/src/runtimeConstants.ts'
|
||||
export { withCtx } from './helpers/withRenderContext'
|
||||
export { withCtx, setScopeId } from './componentRenderContext'
|
||||
export { renderList } from './helpers/renderList'
|
||||
export { toHandlers } from './helpers/toHandlers'
|
||||
export { renderSlot } from './helpers/renderSlot'
|
||||
export { createSlots } from './helpers/createSlots'
|
||||
export { pushScopeId, popScopeId, withScopeId } from './helpers/scopeId'
|
||||
export {
|
||||
openBlock,
|
||||
createBlock,
|
||||
@@ -257,10 +256,8 @@ export { transformVNodeArgs } from './vnode'
|
||||
// change without notice between versions. User code should never rely on them.
|
||||
|
||||
import { createComponentInstance, setupComponent } from './component'
|
||||
import {
|
||||
renderComponentRoot,
|
||||
setCurrentRenderingInstance
|
||||
} from './componentRenderUtils'
|
||||
import { renderComponentRoot } from './componentRenderUtils'
|
||||
import { setCurrentRenderingInstance } from './componentRenderContext'
|
||||
import { isVNode, normalizeVNode } from './vnode'
|
||||
|
||||
const _ssrUtils = {
|
||||
|
||||
@@ -177,6 +177,7 @@ type PatchFn = (
|
||||
parentComponent?: ComponentInternalInstance | null,
|
||||
parentSuspense?: SuspenseBoundary | null,
|
||||
isSVG?: boolean,
|
||||
slotScopeIds?: string[] | null,
|
||||
optimized?: boolean
|
||||
) => void
|
||||
|
||||
@@ -187,6 +188,7 @@ type MountChildrenFn = (
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean,
|
||||
start?: number
|
||||
) => void
|
||||
@@ -199,7 +201,8 @@ type PatchChildrenFn = (
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
optimized?: boolean
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => void
|
||||
|
||||
type PatchBlockChildrenFn = (
|
||||
@@ -208,7 +211,8 @@ type PatchBlockChildrenFn = (
|
||||
fallbackContainer: RendererElement,
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null
|
||||
) => void
|
||||
|
||||
type MoveFn = (
|
||||
@@ -469,6 +473,7 @@ function baseCreateRenderer(
|
||||
parentComponent = null,
|
||||
parentSuspense = null,
|
||||
isSVG = false,
|
||||
slotScopeIds = null,
|
||||
optimized = false
|
||||
) => {
|
||||
// patching & not same type, unmount old tree
|
||||
@@ -507,6 +512,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
break
|
||||
@@ -520,6 +526,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
} else if (shapeFlag & ShapeFlags.COMPONENT) {
|
||||
@@ -531,6 +538,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
} else if (shapeFlag & ShapeFlags.TELEPORT) {
|
||||
@@ -542,6 +550,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized,
|
||||
internals
|
||||
)
|
||||
@@ -554,6 +563,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized,
|
||||
internals
|
||||
)
|
||||
@@ -676,6 +686,7 @@ function baseCreateRenderer(
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => {
|
||||
isSVG = isSVG || (n2.type as string) === 'svg'
|
||||
@@ -687,10 +698,19 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
} else {
|
||||
patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized)
|
||||
patchElement(
|
||||
n1,
|
||||
n2,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,19 +721,12 @@ function baseCreateRenderer(
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => {
|
||||
let el: RendererElement
|
||||
let vnodeHook: VNodeHook | undefined | null
|
||||
const {
|
||||
type,
|
||||
props,
|
||||
shapeFlag,
|
||||
transition,
|
||||
scopeId,
|
||||
patchFlag,
|
||||
dirs
|
||||
} = vnode
|
||||
const { type, props, shapeFlag, transition, patchFlag, dirs } = vnode
|
||||
if (
|
||||
!__DEV__ &&
|
||||
vnode.el &&
|
||||
@@ -744,6 +757,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG && type !== 'foreignObject',
|
||||
slotScopeIds,
|
||||
optimized || !!vnode.dynamicChildren
|
||||
)
|
||||
}
|
||||
@@ -773,7 +787,7 @@ function baseCreateRenderer(
|
||||
}
|
||||
}
|
||||
// scopeId
|
||||
setScopeId(el, scopeId, vnode, parentComponent)
|
||||
setScopeId(el, vnode, vnode.scopeId, slotScopeIds, parentComponent)
|
||||
}
|
||||
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
|
||||
Object.defineProperty(el, '__vnode', {
|
||||
@@ -813,30 +827,32 @@ function baseCreateRenderer(
|
||||
|
||||
const setScopeId = (
|
||||
el: RendererElement,
|
||||
scopeId: string | false | null,
|
||||
vnode: VNode,
|
||||
scopeId: string | null,
|
||||
slotScopeIds: string[] | null,
|
||||
parentComponent: ComponentInternalInstance | null
|
||||
) => {
|
||||
if (scopeId) {
|
||||
hostSetScopeId(el, scopeId)
|
||||
}
|
||||
if (parentComponent) {
|
||||
const treeOwnerId = parentComponent.type.__scopeId
|
||||
// vnode's own scopeId and the current patched component's scopeId is
|
||||
// different - this is a slot content node.
|
||||
if (treeOwnerId && treeOwnerId !== scopeId) {
|
||||
hostSetScopeId(el, treeOwnerId + '-s')
|
||||
if (slotScopeIds) {
|
||||
for (let i = 0; i < slotScopeIds.length; i++) {
|
||||
hostSetScopeId(el, slotScopeIds[i])
|
||||
}
|
||||
}
|
||||
if (parentComponent) {
|
||||
let subTree = parentComponent.subTree
|
||||
if (__DEV__ && subTree.type === Fragment) {
|
||||
if (__DEV__ && subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT) {
|
||||
subTree =
|
||||
filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
|
||||
}
|
||||
if (vnode === subTree) {
|
||||
const parentVNode = parentComponent.vnode
|
||||
setScopeId(
|
||||
el,
|
||||
parentComponent.vnode.scopeId,
|
||||
parentComponent.vnode,
|
||||
parentVNode,
|
||||
parentVNode.scopeId,
|
||||
parentVNode.slotScopeIds,
|
||||
parentComponent.parent
|
||||
)
|
||||
}
|
||||
@@ -851,6 +867,7 @@ function baseCreateRenderer(
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
optimized,
|
||||
slotScopeIds,
|
||||
start = 0
|
||||
) => {
|
||||
for (let i = start; i < children.length; i++) {
|
||||
@@ -865,7 +882,8 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
optimized
|
||||
optimized,
|
||||
slotScopeIds
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -876,6 +894,7 @@ function baseCreateRenderer(
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => {
|
||||
const el = (n2.el = n1.el!)
|
||||
@@ -993,7 +1012,8 @@ function baseCreateRenderer(
|
||||
el,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
areChildrenSVG
|
||||
areChildrenSVG,
|
||||
slotScopeIds
|
||||
)
|
||||
if (__DEV__ && parentComponent && parentComponent.type.__hmrId) {
|
||||
traverseStaticChildren(n1, n2)
|
||||
@@ -1007,7 +1027,9 @@ function baseCreateRenderer(
|
||||
null,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
areChildrenSVG
|
||||
areChildrenSVG,
|
||||
slotScopeIds,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1026,7 +1048,8 @@ function baseCreateRenderer(
|
||||
fallbackContainer,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds
|
||||
) => {
|
||||
for (let i = 0; i < newChildren.length; i++) {
|
||||
const oldVNode = oldChildren[i]
|
||||
@@ -1054,6 +1077,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
true
|
||||
)
|
||||
}
|
||||
@@ -1119,16 +1143,24 @@ function baseCreateRenderer(
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => {
|
||||
const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateText(''))!
|
||||
const fragmentEndAnchor = (n2.anchor = n1 ? n1.anchor : hostCreateText(''))!
|
||||
|
||||
let { patchFlag, dynamicChildren } = n2
|
||||
let { patchFlag, dynamicChildren, slotScopeIds: fragmentSlotScopeIds } = n2
|
||||
if (patchFlag > 0) {
|
||||
optimized = true
|
||||
}
|
||||
|
||||
// check if this is a slot fragment with :slotted scope ids
|
||||
if (fragmentSlotScopeIds) {
|
||||
slotScopeIds = slotScopeIds
|
||||
? slotScopeIds.concat(fragmentSlotScopeIds)
|
||||
: fragmentSlotScopeIds
|
||||
}
|
||||
|
||||
if (__DEV__ && isHmrUpdating) {
|
||||
// HMR updated, force full diff
|
||||
patchFlag = 0
|
||||
@@ -1149,6 +1181,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
} else {
|
||||
@@ -1168,7 +1201,8 @@ function baseCreateRenderer(
|
||||
container,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds
|
||||
)
|
||||
if (__DEV__ && parentComponent && parentComponent.type.__hmrId) {
|
||||
traverseStaticChildren(n1, n2)
|
||||
@@ -1195,6 +1229,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
}
|
||||
@@ -1209,8 +1244,10 @@ function baseCreateRenderer(
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => {
|
||||
n2.slotScopeIds = slotScopeIds
|
||||
if (n1 == null) {
|
||||
if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
|
||||
;(parentComponent!.ctx as KeepAliveContext).activate(
|
||||
@@ -1382,7 +1419,8 @@ function baseCreateRenderer(
|
||||
initialVNode.el as Node,
|
||||
subTree,
|
||||
instance,
|
||||
parentSuspense
|
||||
parentSuspense,
|
||||
null
|
||||
)
|
||||
if (__DEV__) {
|
||||
endMeasure(instance, `hydrate`)
|
||||
@@ -1543,6 +1581,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized = false
|
||||
) => {
|
||||
const c1 = n1 && n1.children
|
||||
@@ -1563,6 +1602,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
return
|
||||
@@ -1576,6 +1616,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
return
|
||||
@@ -1604,6 +1645,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
} else {
|
||||
@@ -1625,6 +1667,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
}
|
||||
@@ -1640,6 +1683,7 @@ function baseCreateRenderer(
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => {
|
||||
c1 = c1 || EMPTY_ARR
|
||||
@@ -1660,6 +1704,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
}
|
||||
@@ -1682,6 +1727,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized,
|
||||
commonLength
|
||||
)
|
||||
@@ -1697,6 +1743,7 @@ function baseCreateRenderer(
|
||||
parentComponent: ComponentInternalInstance | null,
|
||||
parentSuspense: SuspenseBoundary | null,
|
||||
isSVG: boolean,
|
||||
slotScopeIds: string[] | null,
|
||||
optimized: boolean
|
||||
) => {
|
||||
let i = 0
|
||||
@@ -1721,6 +1768,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
} else {
|
||||
@@ -1746,6 +1794,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
} else {
|
||||
@@ -1776,7 +1825,9 @@ function baseCreateRenderer(
|
||||
anchor,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
i++
|
||||
}
|
||||
@@ -1878,6 +1929,7 @@ function baseCreateRenderer(
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
patched++
|
||||
@@ -1905,7 +1957,9 @@ function baseCreateRenderer(
|
||||
anchor,
|
||||
parentComponent,
|
||||
parentSuspense,
|
||||
isSVG
|
||||
isSVG,
|
||||
slotScopeIds,
|
||||
optimized
|
||||
)
|
||||
} else if (moved) {
|
||||
// move if:
|
||||
|
||||
@@ -32,9 +32,11 @@ import {
|
||||
import { DirectiveBinding } from './directives'
|
||||
import { TransitionHooks } from './components/BaseTransition'
|
||||
import { warn } from './warning'
|
||||
import { currentScopeId } from './helpers/scopeId'
|
||||
import { TeleportImpl, isTeleport } from './components/Teleport'
|
||||
import { currentRenderingInstance } from './componentRenderUtils'
|
||||
import {
|
||||
currentRenderingInstance,
|
||||
currentScopeId
|
||||
} from './componentRenderContext'
|
||||
import { RendererNode, RendererElement } from './renderer'
|
||||
import { NULL_DYNAMIC_COMPONENT } from './helpers/resolveAssets'
|
||||
import { hmrDirtyComponents } from './hmr'
|
||||
@@ -133,7 +135,18 @@ export interface VNode<
|
||||
props: (VNodeProps & ExtraProps) | null
|
||||
key: string | number | null
|
||||
ref: VNodeNormalizedRef | null
|
||||
scopeId: string | null // SFC only
|
||||
/**
|
||||
* SFC only. This is assigned on vnode creation using currentScopeId
|
||||
* which is set alongside currentRenderingInstance.
|
||||
*/
|
||||
scopeId: string | null
|
||||
/**
|
||||
* SFC only. This is assigned to:
|
||||
* - Slot fragment vnodes with :slotted SFC styles.
|
||||
* - Component vnodes (during patch/hydration) so that its root node can
|
||||
* inherit the component's slotScopeIds
|
||||
*/
|
||||
slotScopeIds: string[] | null
|
||||
children: VNodeNormalizedChildren
|
||||
component: ComponentInternalInstance | null
|
||||
dirs: DirectiveBinding[] | null
|
||||
@@ -398,6 +411,7 @@ function _createVNode(
|
||||
key: props && normalizeKey(props),
|
||||
ref: props && normalizeRef(props),
|
||||
scopeId: currentScopeId,
|
||||
slotScopeIds: null,
|
||||
children: null,
|
||||
component: null,
|
||||
suspense: null,
|
||||
@@ -479,6 +493,7 @@ export function cloneVNode<T, U>(
|
||||
: normalizeRef(extraProps)
|
||||
: ref,
|
||||
scopeId: vnode.scopeId,
|
||||
slotScopeIds: vnode.slotScopeIds,
|
||||
children:
|
||||
__DEV__ && patchFlag === PatchFlags.HOISTED && isArray(children)
|
||||
? (children as VNode[]).map(deepCloneVNode)
|
||||
|
||||
Reference in New Issue
Block a user