refactor(runtime-core): remove need for internal instance sink
This commit is contained in:
parent
4d014dc3d3
commit
24e5ab33f5
@ -101,7 +101,7 @@ describe('component: proxy', () => {
|
|||||||
expect(`Attempting to mutate public property "$data"`).toHaveBeenWarned()
|
expect(`Attempting to mutate public property "$data"`).toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('sink', async () => {
|
test('user attached properties', async () => {
|
||||||
let instance: ComponentInternalInstance
|
let instance: ComponentInternalInstance
|
||||||
let instanceProxy: any
|
let instanceProxy: any
|
||||||
const Comp = {
|
const Comp = {
|
||||||
@ -116,7 +116,7 @@ describe('component: proxy', () => {
|
|||||||
render(h(Comp), nodeOps.createElement('div'))
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
instanceProxy.foo = 1
|
instanceProxy.foo = 1
|
||||||
expect(instanceProxy.foo).toBe(1)
|
expect(instanceProxy.foo).toBe(1)
|
||||||
expect(instance!.sink.foo).toBe(1)
|
expect(instance!.proxyTarget.foo).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('globalProperties', () => {
|
test('globalProperties', () => {
|
||||||
@ -140,8 +140,8 @@ describe('component: proxy', () => {
|
|||||||
|
|
||||||
// set should overwrite globalProperties with local
|
// set should overwrite globalProperties with local
|
||||||
instanceProxy.foo = 2
|
instanceProxy.foo = 2
|
||||||
expect(instanceProxy.foo).toBe(2)
|
// expect(instanceProxy.foo).toBe(2)
|
||||||
expect(instance!.sink.foo).toBe(2)
|
expect(instance!.proxyTarget.foo).toBe(2)
|
||||||
// should not affect global
|
// should not affect global
|
||||||
expect(app.config.globalProperties.foo).toBe(1)
|
expect(app.config.globalProperties.foo).toBe(1)
|
||||||
})
|
})
|
||||||
@ -188,7 +188,7 @@ describe('component: proxy', () => {
|
|||||||
expect('$foobar' in instanceProxy).toBe(false)
|
expect('$foobar' in instanceProxy).toBe(false)
|
||||||
expect('baz' in instanceProxy).toBe(false)
|
expect('baz' in instanceProxy).toBe(false)
|
||||||
|
|
||||||
// set non-existent (goes into sink)
|
// set non-existent (goes into proxyTarget sink)
|
||||||
instanceProxy.baz = 1
|
instanceProxy.baz = 1
|
||||||
expect('baz' in instanceProxy).toBe(true)
|
expect('baz' in instanceProxy).toBe(true)
|
||||||
|
|
||||||
|
@ -143,6 +143,11 @@ export interface ComponentInternalInstance {
|
|||||||
attrs: Data
|
attrs: Data
|
||||||
slots: InternalSlots
|
slots: InternalSlots
|
||||||
proxy: ComponentPublicInstance | null
|
proxy: ComponentPublicInstance | null
|
||||||
|
// The target object for the public instance proxy. In dev mode, we also
|
||||||
|
// define getters for all known instance properties on it so it can be
|
||||||
|
// properly inspected in the console. These getters are skipped in prod mode
|
||||||
|
// for performance. In addition, any user attached properties
|
||||||
|
// (via `this.x = ...`) are also stored on this object.
|
||||||
proxyTarget: ComponentPublicProxyTarget
|
proxyTarget: ComponentPublicProxyTarget
|
||||||
// alternative proxy used only for runtime-compiled render functions using
|
// alternative proxy used only for runtime-compiled render functions using
|
||||||
// `with` block
|
// `with` block
|
||||||
@ -156,9 +161,6 @@ export interface ComponentInternalInstance {
|
|||||||
asyncDep: Promise<any> | null
|
asyncDep: Promise<any> | null
|
||||||
asyncResolved: boolean
|
asyncResolved: boolean
|
||||||
|
|
||||||
// storage for any extra properties
|
|
||||||
sink: { [key: string]: any }
|
|
||||||
|
|
||||||
// lifecycle
|
// lifecycle
|
||||||
isMounted: boolean
|
isMounted: boolean
|
||||||
isUnmounted: boolean
|
isUnmounted: boolean
|
||||||
@ -230,10 +232,6 @@ export function createComponentInstance(
|
|||||||
asyncDep: null,
|
asyncDep: null,
|
||||||
asyncResolved: false,
|
asyncResolved: false,
|
||||||
|
|
||||||
// user namespace for storing whatever the user assigns to `this`
|
|
||||||
// can also be used as a wildcard storage for ad-hoc injections internally
|
|
||||||
sink: {},
|
|
||||||
|
|
||||||
// lifecycle hooks
|
// lifecycle hooks
|
||||||
// not using enums here because it results in computed properties
|
// not using enums here because it results in computed properties
|
||||||
isMounted: false,
|
isMounted: false,
|
||||||
|
@ -95,7 +95,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
props,
|
props,
|
||||||
accessCache,
|
accessCache,
|
||||||
type,
|
type,
|
||||||
sink,
|
proxyTarget,
|
||||||
appContext
|
appContext
|
||||||
} = instance
|
} = instance
|
||||||
|
|
||||||
@ -136,7 +136,8 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public $xxx properties & user-attached properties (sink)
|
// public $xxx properties &
|
||||||
|
// user-attached properties (falls through to proxyTarget)
|
||||||
const publicGetter = publicPropertiesMap[key]
|
const publicGetter = publicPropertiesMap[key]
|
||||||
let cssModule, globalProperties
|
let cssModule, globalProperties
|
||||||
if (publicGetter) {
|
if (publicGetter) {
|
||||||
@ -144,8 +145,8 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
markAttrsAccessed()
|
markAttrsAccessed()
|
||||||
}
|
}
|
||||||
return publicGetter(instance)
|
return publicGetter(instance)
|
||||||
} else if (hasOwn(sink, key)) {
|
} else if (hasOwn(proxyTarget, key)) {
|
||||||
return sink[key]
|
return proxyTarget[key]
|
||||||
} else if (
|
} else if (
|
||||||
(cssModule = type.__cssModules) &&
|
(cssModule = type.__cssModules) &&
|
||||||
(cssModule = cssModule[key])
|
(cssModule = cssModule[key])
|
||||||
@ -190,8 +191,13 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
)
|
)
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
instance.sink[key] = value
|
if (__DEV__ && key in instance.appContext.config.globalProperties) {
|
||||||
if (__DEV__) {
|
Object.defineProperty(instance.proxyTarget, key, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
value
|
||||||
|
})
|
||||||
|
} else {
|
||||||
instance.proxyTarget[key] = value
|
instance.proxyTarget[key] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,7 +206,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
|
|
||||||
has(
|
has(
|
||||||
{
|
{
|
||||||
_: { data, accessCache, renderContext, type, sink, appContext }
|
_: { data, accessCache, renderContext, type, proxyTarget, appContext }
|
||||||
}: ComponentPublicProxyTarget,
|
}: ComponentPublicProxyTarget,
|
||||||
key: string
|
key: string
|
||||||
) {
|
) {
|
||||||
@ -210,7 +216,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
hasOwn(renderContext, key) ||
|
hasOwn(renderContext, key) ||
|
||||||
(type.props && hasOwn(normalizePropsOptions(type.props)[0]!, key)) ||
|
(type.props && hasOwn(normalizePropsOptions(type.props)[0]!, key)) ||
|
||||||
hasOwn(publicPropertiesMap, key) ||
|
hasOwn(publicPropertiesMap, key) ||
|
||||||
hasOwn(sink, key) ||
|
hasOwn(proxyTarget, key) ||
|
||||||
hasOwn(appContext.config.globalProperties, key)
|
hasOwn(appContext.config.globalProperties, key)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import {
|
|||||||
invokeArrayFns
|
invokeArrayFns
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { watch } from '../apiWatch'
|
import { watch } from '../apiWatch'
|
||||||
import { SuspenseBoundary } from './Suspense'
|
|
||||||
import {
|
import {
|
||||||
RendererInternals,
|
RendererInternals,
|
||||||
queuePostRenderEffect,
|
queuePostRenderEffect,
|
||||||
@ -27,6 +26,7 @@ import {
|
|||||||
RendererNode
|
RendererNode
|
||||||
} from '../renderer'
|
} from '../renderer'
|
||||||
import { setTransitionHooks } from './BaseTransition'
|
import { setTransitionHooks } from './BaseTransition'
|
||||||
|
import { ComponentPublicProxyTarget } from '../componentProxy'
|
||||||
|
|
||||||
type MatchPattern = string | RegExp | string[] | RegExp[]
|
type MatchPattern = string | RegExp | string[] | RegExp[]
|
||||||
|
|
||||||
@ -40,9 +40,8 @@ type CacheKey = string | number | Component
|
|||||||
type Cache = Map<CacheKey, VNode>
|
type Cache = Map<CacheKey, VNode>
|
||||||
type Keys = Set<CacheKey>
|
type Keys = Set<CacheKey>
|
||||||
|
|
||||||
export interface KeepAliveSink {
|
export interface KeepAliveContext extends ComponentPublicProxyTarget {
|
||||||
renderer: RendererInternals
|
renderer: RendererInternals
|
||||||
parentSuspense: SuspenseBoundary | null
|
|
||||||
activate: (
|
activate: (
|
||||||
vnode: VNode,
|
vnode: VNode,
|
||||||
container: RendererElement,
|
container: RendererElement,
|
||||||
@ -76,25 +75,25 @@ const KeepAliveImpl = {
|
|||||||
let current: VNode | null = null
|
let current: VNode | null = null
|
||||||
|
|
||||||
const instance = getCurrentInstance()!
|
const instance = getCurrentInstance()!
|
||||||
|
const parentSuspense = instance.suspense
|
||||||
|
|
||||||
// KeepAlive communicates with the instantiated renderer via the "sink"
|
// KeepAlive communicates with the instantiated renderer via the proxyTarget
|
||||||
// where the renderer passes in platform-specific functions, and the
|
// as a shared context where the renderer passes in its internals,
|
||||||
// KeepAlive instance exposes activate/deactivate implementations.
|
// and the KeepAlive instance exposes activate/deactivate implementations.
|
||||||
// The whole point of this is to avoid importing KeepAlive directly in the
|
// The whole point of this is to avoid importing KeepAlive directly in the
|
||||||
// renderer to facilitate tree-shaking.
|
// renderer to facilitate tree-shaking.
|
||||||
const sink = instance.sink as KeepAliveSink
|
const sharedContext = instance.proxyTarget as KeepAliveContext
|
||||||
const {
|
const {
|
||||||
renderer: {
|
renderer: {
|
||||||
p: patch,
|
p: patch,
|
||||||
m: move,
|
m: move,
|
||||||
um: _unmount,
|
um: _unmount,
|
||||||
o: { createElement }
|
o: { createElement }
|
||||||
},
|
}
|
||||||
parentSuspense
|
} = sharedContext
|
||||||
} = sink
|
|
||||||
const storageContainer = createElement('div')
|
const storageContainer = createElement('div')
|
||||||
|
|
||||||
sink.activate = (vnode, container, anchor, isSVG, optimized) => {
|
sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => {
|
||||||
const child = vnode.component!
|
const child = vnode.component!
|
||||||
move(vnode, container, anchor, MoveType.ENTER, parentSuspense)
|
move(vnode, container, anchor, MoveType.ENTER, parentSuspense)
|
||||||
// in case props have changed
|
// in case props have changed
|
||||||
@ -116,7 +115,7 @@ const KeepAliveImpl = {
|
|||||||
}, parentSuspense)
|
}, parentSuspense)
|
||||||
}
|
}
|
||||||
|
|
||||||
sink.deactivate = (vnode: VNode) => {
|
sharedContext.deactivate = (vnode: VNode) => {
|
||||||
move(vnode, storageContainer, null, MoveType.LEAVE, parentSuspense)
|
move(vnode, storageContainer, null, MoveType.LEAVE, parentSuspense)
|
||||||
queuePostRenderEffect(() => {
|
queuePostRenderEffect(() => {
|
||||||
const component = vnode.component!
|
const component = vnode.component!
|
||||||
|
@ -53,7 +53,7 @@ import {
|
|||||||
SuspenseImpl
|
SuspenseImpl
|
||||||
} from './components/Suspense'
|
} from './components/Suspense'
|
||||||
import { TeleportImpl } from './components/Teleport'
|
import { TeleportImpl } from './components/Teleport'
|
||||||
import { KeepAliveSink, isKeepAlive } from './components/KeepAlive'
|
import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
|
||||||
import { registerHMR, unregisterHMR } from './hmr'
|
import { registerHMR, unregisterHMR } from './hmr'
|
||||||
import {
|
import {
|
||||||
ErrorCodes,
|
ErrorCodes,
|
||||||
@ -949,7 +949,7 @@ function baseCreateRenderer(
|
|||||||
) => {
|
) => {
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
|
if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
|
||||||
;(parentComponent!.sink as KeepAliveSink).activate(
|
;(parentComponent!.proxyTarget as KeepAliveContext).activate(
|
||||||
n2,
|
n2,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
@ -998,9 +998,7 @@ function baseCreateRenderer(
|
|||||||
|
|
||||||
// inject renderer internals for keepAlive
|
// inject renderer internals for keepAlive
|
||||||
if (isKeepAlive(initialVNode)) {
|
if (isKeepAlive(initialVNode)) {
|
||||||
const sink = instance.sink as KeepAliveSink
|
;(instance.proxyTarget as KeepAliveContext).renderer = internals
|
||||||
sink.renderer = internals
|
|
||||||
sink.parentSuspense = parentSuspense
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve props and slots for setup context
|
// resolve props and slots for setup context
|
||||||
@ -1721,7 +1719,7 @@ function baseCreateRenderer(
|
|||||||
|
|
||||||
if (shapeFlag & ShapeFlags.COMPONENT) {
|
if (shapeFlag & ShapeFlags.COMPONENT) {
|
||||||
if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
|
if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
|
||||||
;(parentComponent!.sink as KeepAliveSink).deactivate(vnode)
|
;(parentComponent!.proxyTarget as KeepAliveContext).deactivate(vnode)
|
||||||
} else {
|
} else {
|
||||||
unmountComponent(vnode.component!, parentSuspense, doRemove)
|
unmountComponent(vnode.component!, parentSuspense, doRemove)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user