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