Skip to content

Commit 24e5ab3

Browse files
committed
refactor(runtime-core): remove need for internal instance sink
1 parent 4d014dc commit 24e5ab3

File tree

5 files changed

+39
-38
lines changed

5 files changed

+39
-38
lines changed

packages/runtime-core/__tests__/componentProxy.spec.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ describe('component: proxy', () => {
101101
expect(`Attempting to mutate public property "$data"`).toHaveBeenWarned()
102102
})
103103

104-
test('sink', async () => {
104+
test('user attached properties', async () => {
105105
let instance: ComponentInternalInstance
106106
let instanceProxy: any
107107
const Comp = {
@@ -116,7 +116,7 @@ describe('component: proxy', () => {
116116
render(h(Comp), nodeOps.createElement('div'))
117117
instanceProxy.foo = 1
118118
expect(instanceProxy.foo).toBe(1)
119-
expect(instance!.sink.foo).toBe(1)
119+
expect(instance!.proxyTarget.foo).toBe(1)
120120
})
121121

122122
test('globalProperties', () => {
@@ -140,8 +140,8 @@ describe('component: proxy', () => {
140140

141141
// set should overwrite globalProperties with local
142142
instanceProxy.foo = 2
143-
expect(instanceProxy.foo).toBe(2)
144-
expect(instance!.sink.foo).toBe(2)
143+
// expect(instanceProxy.foo).toBe(2)
144+
expect(instance!.proxyTarget.foo).toBe(2)
145145
// should not affect global
146146
expect(app.config.globalProperties.foo).toBe(1)
147147
})
@@ -188,7 +188,7 @@ describe('component: proxy', () => {
188188
expect('$foobar' in instanceProxy).toBe(false)
189189
expect('baz' in instanceProxy).toBe(false)
190190

191-
// set non-existent (goes into sink)
191+
// set non-existent (goes into proxyTarget sink)
192192
instanceProxy.baz = 1
193193
expect('baz' in instanceProxy).toBe(true)
194194

packages/runtime-core/src/component.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ export interface ComponentInternalInstance {
143143
attrs: Data
144144
slots: InternalSlots
145145
proxy: ComponentPublicInstance | null
146+
// The target object for the public instance proxy. In dev mode, we also
147+
// define getters for all known instance properties on it so it can be
148+
// properly inspected in the console. These getters are skipped in prod mode
149+
// for performance. In addition, any user attached properties
150+
// (via `this.x = ...`) are also stored on this object.
146151
proxyTarget: ComponentPublicProxyTarget
147152
// alternative proxy used only for runtime-compiled render functions using
148153
// `with` block
@@ -156,9 +161,6 @@ export interface ComponentInternalInstance {
156161
asyncDep: Promise<any> | null
157162
asyncResolved: boolean
158163

159-
// storage for any extra properties
160-
sink: { [key: string]: any }
161-
162164
// lifecycle
163165
isMounted: boolean
164166
isUnmounted: boolean
@@ -230,10 +232,6 @@ export function createComponentInstance(
230232
asyncDep: null,
231233
asyncResolved: false,
232234

233-
// user namespace for storing whatever the user assigns to `this`
234-
// can also be used as a wildcard storage for ad-hoc injections internally
235-
sink: {},
236-
237235
// lifecycle hooks
238236
// not using enums here because it results in computed properties
239237
isMounted: false,

packages/runtime-core/src/componentProxy.ts

+14-8
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
9595
props,
9696
accessCache,
9797
type,
98-
sink,
98+
proxyTarget,
9999
appContext
100100
} = instance
101101

@@ -136,16 +136,17 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
136136
}
137137
}
138138

139-
// public $xxx properties & user-attached properties (sink)
139+
// public $xxx properties &
140+
// user-attached properties (falls through to proxyTarget)
140141
const publicGetter = publicPropertiesMap[key]
141142
let cssModule, globalProperties
142143
if (publicGetter) {
143144
if (__DEV__ && key === '$attrs') {
144145
markAttrsAccessed()
145146
}
146147
return publicGetter(instance)
147-
} else if (hasOwn(sink, key)) {
148-
return sink[key]
148+
} else if (hasOwn(proxyTarget, key)) {
149+
return proxyTarget[key]
149150
} else if (
150151
(cssModule = type.__cssModules) &&
151152
(cssModule = cssModule[key])
@@ -190,8 +191,13 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
190191
)
191192
return false
192193
} else {
193-
instance.sink[key] = value
194-
if (__DEV__) {
194+
if (__DEV__ && key in instance.appContext.config.globalProperties) {
195+
Object.defineProperty(instance.proxyTarget, key, {
196+
configurable: true,
197+
enumerable: true,
198+
value
199+
})
200+
} else {
195201
instance.proxyTarget[key] = value
196202
}
197203
}
@@ -200,7 +206,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
200206

201207
has(
202208
{
203-
_: { data, accessCache, renderContext, type, sink, appContext }
209+
_: { data, accessCache, renderContext, type, proxyTarget, appContext }
204210
}: ComponentPublicProxyTarget,
205211
key: string
206212
) {
@@ -210,7 +216,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
210216
hasOwn(renderContext, key) ||
211217
(type.props && hasOwn(normalizePropsOptions(type.props)[0]!, key)) ||
212218
hasOwn(publicPropertiesMap, key) ||
213-
hasOwn(sink, key) ||
219+
hasOwn(proxyTarget, key) ||
214220
hasOwn(appContext.config.globalProperties, key)
215221
)
216222
}

packages/runtime-core/src/components/KeepAlive.ts

+11-12
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
invokeArrayFns
1919
} from '@vue/shared'
2020
import { watch } from '../apiWatch'
21-
import { SuspenseBoundary } from './Suspense'
2221
import {
2322
RendererInternals,
2423
queuePostRenderEffect,
@@ -27,6 +26,7 @@ import {
2726
RendererNode
2827
} from '../renderer'
2928
import { setTransitionHooks } from './BaseTransition'
29+
import { ComponentPublicProxyTarget } from '../componentProxy'
3030

3131
type MatchPattern = string | RegExp | string[] | RegExp[]
3232

@@ -40,9 +40,8 @@ type CacheKey = string | number | Component
4040
type Cache = Map<CacheKey, VNode>
4141
type Keys = Set<CacheKey>
4242

43-
export interface KeepAliveSink {
43+
export interface KeepAliveContext extends ComponentPublicProxyTarget {
4444
renderer: RendererInternals
45-
parentSuspense: SuspenseBoundary | null
4645
activate: (
4746
vnode: VNode,
4847
container: RendererElement,
@@ -76,25 +75,25 @@ const KeepAliveImpl = {
7675
let current: VNode | null = null
7776

7877
const instance = getCurrentInstance()!
78+
const parentSuspense = instance.suspense
7979

80-
// KeepAlive communicates with the instantiated renderer via the "sink"
81-
// where the renderer passes in platform-specific functions, and the
82-
// KeepAlive instance exposes activate/deactivate implementations.
80+
// KeepAlive communicates with the instantiated renderer via the proxyTarget
81+
// as a shared context where the renderer passes in its internals,
82+
// and the KeepAlive instance exposes activate/deactivate implementations.
8383
// The whole point of this is to avoid importing KeepAlive directly in the
8484
// renderer to facilitate tree-shaking.
85-
const sink = instance.sink as KeepAliveSink
85+
const sharedContext = instance.proxyTarget as KeepAliveContext
8686
const {
8787
renderer: {
8888
p: patch,
8989
m: move,
9090
um: _unmount,
9191
o: { createElement }
92-
},
93-
parentSuspense
94-
} = sink
92+
}
93+
} = sharedContext
9594
const storageContainer = createElement('div')
9695

97-
sink.activate = (vnode, container, anchor, isSVG, optimized) => {
96+
sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => {
9897
const child = vnode.component!
9998
move(vnode, container, anchor, MoveType.ENTER, parentSuspense)
10099
// in case props have changed
@@ -116,7 +115,7 @@ const KeepAliveImpl = {
116115
}, parentSuspense)
117116
}
118117

119-
sink.deactivate = (vnode: VNode) => {
118+
sharedContext.deactivate = (vnode: VNode) => {
120119
move(vnode, storageContainer, null, MoveType.LEAVE, parentSuspense)
121120
queuePostRenderEffect(() => {
122121
const component = vnode.component!

packages/runtime-core/src/renderer.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ import {
5353
SuspenseImpl
5454
} from './components/Suspense'
5555
import { TeleportImpl } from './components/Teleport'
56-
import { KeepAliveSink, isKeepAlive } from './components/KeepAlive'
56+
import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
5757
import { registerHMR, unregisterHMR } from './hmr'
5858
import {
5959
ErrorCodes,
@@ -949,7 +949,7 @@ function baseCreateRenderer(
949949
) => {
950950
if (n1 == null) {
951951
if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
952-
;(parentComponent!.sink as KeepAliveSink).activate(
952+
;(parentComponent!.proxyTarget as KeepAliveContext).activate(
953953
n2,
954954
container,
955955
anchor,
@@ -998,9 +998,7 @@ function baseCreateRenderer(
998998

999999
// inject renderer internals for keepAlive
10001000
if (isKeepAlive(initialVNode)) {
1001-
const sink = instance.sink as KeepAliveSink
1002-
sink.renderer = internals
1003-
sink.parentSuspense = parentSuspense
1001+
;(instance.proxyTarget as KeepAliveContext).renderer = internals
10041002
}
10051003

10061004
// resolve props and slots for setup context
@@ -1721,7 +1719,7 @@ function baseCreateRenderer(
17211719

17221720
if (shapeFlag & ShapeFlags.COMPONENT) {
17231721
if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
1724-
;(parentComponent!.sink as KeepAliveSink).deactivate(vnode)
1722+
;(parentComponent!.proxyTarget as KeepAliveContext).deactivate(vnode)
17251723
} else {
17261724
unmountComponent(vnode.component!, parentSuspense, doRemove)
17271725
}

0 commit comments

Comments
 (0)