Skip to content

Commit

Permalink
fix(runtime-core): use same internal object mechanism for slots
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 authored and lynxlangya committed May 30, 2024
1 parent 3081008 commit 785876b
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 15 deletions.
10 changes: 2 additions & 8 deletions packages/runtime-core/src/componentProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { createPropsDefaultThis } from './compat/props'
import { isCompatEnabled, softAssertCompatEnabled } from './compat/compatConfig'
import { DeprecationTypes } from './compat/compatConfig'
import { shouldSkipAttr } from './compat/attrsFallthrough'
import { createInternalObject } from './internalObject'

export type ComponentPropsOptions<P = Data> =
| ComponentObjectPropsOptions<P>
Expand Down Expand Up @@ -185,21 +186,14 @@ type NormalizedProp =
export type NormalizedProps = Record<string, NormalizedProp>
export type NormalizedPropsOptions = [NormalizedProps, string[]] | []

/**
* Used during vnode props normalization to check if the vnode props is the
* attrs object of a component via `Object.getPrototypeOf`. This is more
* performant than defining a non-enumerable property.
*/
export const attrsProto = {}

export function initProps(
instance: ComponentInternalInstance,
rawProps: Data | null,
isStateful: number, // result of bitwise flag comparison
isSSR = false,
) {
const props: Data = {}
const attrs: Data = Object.create(attrsProto)
const attrs: Data = createInternalObject()

instance.propsDefaults = Object.create(null)

Expand Down
5 changes: 3 additions & 2 deletions packages/runtime-core/src/componentSlots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'
import { toRaw } from '@vue/reactivity'
import { trigger } from '@vue/reactivity'
import { TriggerOpTypes } from '@vue/reactivity'
import { createInternalObject } from './internalObject'

export type Slot<T extends any = any> = (
...args: IfAny<T, any[], [T] | (T extends undefined ? [] : never)>
Expand Down Expand Up @@ -177,12 +178,12 @@ export const initSlots = (
} else {
normalizeObjectSlots(
children as RawSlots,
(instance.slots = {}),
(instance.slots = createInternalObject()),
instance,
)
}
} else {
instance.slots = {}
instance.slots = createInternalObject()
if (children) {
normalizeVNodeSlots(instance, children)
}
Expand Down
12 changes: 12 additions & 0 deletions packages/runtime-core/src/internalObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Used during vnode props/slots normalization to check if the vnode props/slots
* are the internal attrs / slots object of a component via
* `Object.getPrototypeOf`. This is more performant than defining a
* non-enumerable property. (one of the optimizations done for ssr-benchmark)
*/
const internalObjectProto = Object.create(null)

export const createInternalObject = () => Object.create(internalObjectProto)

export const isInternalObject = (obj: object) =>
Object.getPrototypeOf(obj) === internalObjectProto
8 changes: 3 additions & 5 deletions packages/runtime-core/src/vnode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import { convertLegacyVModelProps } from './compat/componentVModel'
import { defineLegacyVNodeProperties } from './compat/renderFn'
import { ErrorCodes, callWithAsyncErrorHandling } from './errorHandling'
import type { ComponentPublicInstance } from './componentPublicInstance'
import { attrsProto } from './componentProps'
import { isInternalObject } from './internalObject'

export const Fragment = Symbol.for('v-fgt') as any as {
__isFragment: true
Expand Down Expand Up @@ -617,9 +617,7 @@ function _createVNode(

export function guardReactiveProps(props: (Data & VNodeProps) | null) {
if (!props) return null
return isProxy(props) || Object.getPrototypeOf(props) === attrsProto
? extend({}, props)
: props
return isProxy(props) || isInternalObject(props) ? extend({}, props) : props
}

export function cloneVNode<T, U>(
Expand Down Expand Up @@ -791,7 +789,7 @@ export function normalizeChildren(vnode: VNode, children: unknown) {
} else {
type = ShapeFlags.SLOTS_CHILDREN
const slotFlag = (children as RawSlots)._
if (!slotFlag) {
if (!slotFlag && !isInternalObject(children)) {
// if slots are not normalized, attach context instance
// (compiled / normalized slots already have context)
;(children as RawSlots)._ctx = currentRenderingInstance
Expand Down

0 comments on commit 785876b

Please sign in to comment.