Skip to content

Commit

Permalink
feat: remove component proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbinBaauw committed Jul 11, 2020
1 parent 36acc2b commit 373decb
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 53 deletions.
4 changes: 4 additions & 0 deletions packages/compiler-core/src/runtimeHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ export const PUSH_SCOPE_ID = Symbol(__DEV__ ? `pushScopeId` : ``)
export const POP_SCOPE_ID = Symbol(__DEV__ ? `popScopeId` : ``)
export const WITH_SCOPE_ID = Symbol(__DEV__ ? `withScopeId` : ``)
export const WITH_CTX = Symbol(__DEV__ ? `withCtx` : ``)
export const PUBLIC_INSTANCE_HANDLERS = Symbol(
__DEV__ ? `PublicInstanceHandlers` : ``
)

// Name mapping for runtime helpers that need to be imported from 'vue' in
// generated code. Make sure these are correctly exported in the runtime!
// Using `any` here because TS doesn't allow symbols as index type.
export const helperNameMap: any = {
[PUBLIC_INSTANCE_HANDLERS]: `PublicInstanceHandlers`,
[FRAGMENT]: `Fragment`,
[TELEPORT]: `Teleport`,
[SUSPENSE]: `Suspense`,
Expand Down
10 changes: 6 additions & 4 deletions packages/compiler-core/src/transforms/transformExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
import { createCompilerError, ErrorCodes } from '../errors'
import { Node, Function, Identifier, ObjectProperty } from '@babel/types'
import { validateBrowserExpression } from '../validateExpression'
import { PUBLIC_INSTANCE_HANDLERS } from '@vue/compiler-core'

const isLiteralWhitelisted = /*#__PURE__*/ makeMap('true,false,null,this')

Expand Down Expand Up @@ -102,10 +103,9 @@ export function processExpression(

const { bindingMetadata } = context
const prefix = (raw: string) => {
const source = hasOwn(bindingMetadata, raw)
? `$` + bindingMetadata[raw]
: `_ctx`
return `${source}.${raw}`
return hasOwn(bindingMetadata, raw)
? `${bindingMetadata[raw]}.${raw}`
: `_PublicInstanceHandlers.get(_ctx, "${raw}")`
}

// fast path if expression is a simple identifier.
Expand All @@ -119,6 +119,7 @@ export function processExpression(
!isGloballyWhitelisted(rawExp) &&
!isLiteralWhitelisted(rawExp)
) {
context.helper(PUBLIC_INSTANCE_HANDLERS)
node.content = prefix(rawExp)
} else if (!context.identifiers[rawExp] && !bailConstant) {
// mark node constant for hoisting unless it's referring a scope variable
Expand Down Expand Up @@ -169,6 +170,7 @@ export function processExpression(
// rewrite the value
node.prefix = `${node.name}: `
}
context.helper(PUBLIC_INSTANCE_HANDLERS)
node.name = prefix(node.name)
ids.push(node)
} else if (!isStaticPropertyKey(node, parent)) {
Expand Down
12 changes: 3 additions & 9 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { VNode, VNodeChild, isVNode } from './vnode'
import {
reactive,
ReactiveEffect,
pauseTracking,
resetTracking,
Expand All @@ -9,8 +8,6 @@ import {
import {
CreateComponentPublicInstance,
ComponentPublicInstance,
PublicInstanceProxyHandlers,
RuntimeCompiledPublicInstanceProxyHandlers,
createRenderContext,
exposePropsOnRenderContext,
exposeSetupStateOnRenderContext
Expand Down Expand Up @@ -473,7 +470,7 @@ function setupStatefulComponent(
instance.accessCache = {}
// 1. create public instance / render proxy
// also mark it raw so it's never observed
instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers)
instance.proxy = instance.ctx as any
if (__DEV__) {
exposePropsOnRenderContext(instance)
}
Expand Down Expand Up @@ -535,7 +532,7 @@ export function handleSetupResult(
}
// setup returned bindings.
// assuming a render function compiled from template is present.
instance.setupState = reactive(setupResult)
instance.setupState = setupResult
if (__DEV__) {
exposeSetupStateOnRenderContext(instance)
}
Expand Down Expand Up @@ -615,10 +612,7 @@ function finishComponentSetup(
// proxy used needs a different `has` handler which is more performant and
// also only allows a whitelist of globals to fallthrough.
if (instance.render._rc) {
instance.withProxy = new Proxy(
instance.ctx,
RuntimeCompiledPublicInstanceProxyHandlers
)
instance.withProxy = instance.ctx as any
}
}

Expand Down
74 changes: 35 additions & 39 deletions packages/runtime-core/src/componentProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
shallowReadonly,
ReactiveFlags,
track,
TrackOpTypes
TrackOpTypes,
unref
} from '@vue/reactivity'
import {
ExtractComputedReturns,
Expand Down Expand Up @@ -198,8 +199,8 @@ export interface ComponentRenderContext {
_: ComponentInternalInstance
}

export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
get({ _: instance }: ComponentRenderContext, key: string) {
export class PublicInstanceHandlers {
static get({ _: instance }: ComponentRenderContext, key: string) {
const {
ctx,
setupState,
Expand Down Expand Up @@ -227,7 +228,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
if (n !== undefined) {
switch (n) {
case AccessTypes.SETUP:
return setupState[key]
return unref(setupState[key])
case AccessTypes.DATA:
return data[key]
case AccessTypes.CONTEXT:
Expand All @@ -238,7 +239,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
}
} else if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
accessCache![key] = AccessTypes.SETUP
return setupState[key]
return unref(setupState[key])
} else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
accessCache![key] = AccessTypes.DATA
return data[key]
Expand Down Expand Up @@ -304,9 +305,9 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
)
}
}
},
}

set(
static set(
{ _: instance }: ComponentRenderContext,
key: string,
value: any
Expand Down Expand Up @@ -344,9 +345,9 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
}
}
return true
},
}

has(
static has(
{
_: { data, setupState, accessCache, ctx, type, appContext }
}: ComponentRenderContext,
Expand All @@ -366,40 +367,35 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
}
}

if (__DEV__ && !__TEST__) {
PublicInstanceProxyHandlers.ownKeys = (target: ComponentRenderContext) => {
warn(
`Avoid app logic that relies on enumerating keys on a component instance. ` +
`The keys will be empty in production mode to avoid performance overhead.`
)
return Reflect.ownKeys(target)
export class RuntimeCompiledPublicInstanceHandlers {
static set(
instance: ComponentRenderContext,
key: string,
value: any
): boolean {
return PublicInstanceHandlers.set(instance, key, value)
}
}

export const RuntimeCompiledPublicInstanceProxyHandlers = extend(
{},
PublicInstanceProxyHandlers,
{
get(target: ComponentRenderContext, key: string) {
// fast path for unscopables when using `with` block
if ((key as any) === Symbol.unscopables) {
return
}
return PublicInstanceProxyHandlers.get!(target, key, target)
},
has(_: ComponentRenderContext, key: string) {
const has = key[0] !== '_' && !isGloballyWhitelisted(key)
if (__DEV__ && !has && PublicInstanceProxyHandlers.has!(_, key)) {
warn(
`Property ${JSON.stringify(
key
)} should not start with _ which is a reserved prefix for Vue internals.`
)
}
return has
static get(target: ComponentRenderContext, key: string) {
// fast path for unscopables when using `with` block
if ((key as any) === Symbol.unscopables) {
return
}
return PublicInstanceHandlers.get(target, key)
}
)

static has(_: ComponentRenderContext, key: string) {
const has = key[0] !== '_' && !isGloballyWhitelisted(key)
if (__DEV__ && !has && PublicInstanceHandlers.has(_, key)) {
warn(
`Property ${JSON.stringify(
key
)} should not start with _ which is a reserved prefix for Vue internals.`
)
}
return has
}
}

// In dev mode, the proxy target exposes the same properties as seen on `this`
// for easier console inspection. In prod mode it will be an empty object so
Expand Down
1 change: 1 addition & 0 deletions packages/runtime-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export {
RenderFunction
} from './componentOptions'
export {
PublicInstanceHandlers,
ComponentPublicInstance,
ComponentCustomProperties
} from './componentProxy'
Expand Down
5 changes: 4 additions & 1 deletion packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,10 @@ export const setRef = (
refs[ref] = value
if (hasOwn(setupState, ref)) {
queuePostRenderEffect(() => {
setupState[ref] = value
const setupStateRef = setupState[ref]
if (isRef(setupStateRef)) {
setupStateRef.value = value
}
}, parentSuspense)
}
} else if (isRef(ref)) {
Expand Down

0 comments on commit 373decb

Please sign in to comment.