]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: use symbol for private properties (#8681)
author丶远方 <yangpanteng@gmail.com>
Tue, 22 Aug 2023 08:57:15 +0000 (16:57 +0800)
committerGitHub <noreply@github.com>
Tue, 22 Aug 2023 08:57:15 +0000 (16:57 +0800)
packages/runtime-core/src/components/BaseTransition.ts
packages/runtime-dom/__tests__/patchClass.spec.ts
packages/runtime-dom/src/components/Transition.ts
packages/runtime-dom/src/components/TransitionGroup.ts
packages/runtime-dom/src/directives/vModel.ts
packages/runtime-dom/src/directives/vShow.ts
packages/runtime-dom/src/modules/class.ts
packages/runtime-dom/src/modules/events.ts
packages/runtime-dom/src/modules/style.ts
packages/vue/__tests__/svgNamespace.spec.ts

index a4e862335eb2bc2f3b6a6a22284311925e49f5cd..9cb80b94ef0146c4fd806a6dc91c8e424cc299a2 100644 (file)
@@ -22,6 +22,9 @@ import { RendererElement } from '../renderer'
 
 type Hook<T = () => void> = T | T[]
 
+const leaveCbKey = Symbol('_leaveCb')
+const enterCbKey = Symbol('_enterCb')
+
 export interface BaseTransitionProps<HostElement = RendererElement> {
   mode?: 'in-out' | 'out-in' | 'default'
   appear?: boolean
@@ -89,8 +92,8 @@ export interface TransitionElement {
   // in persisted mode (e.g. v-show), the same element is toggled, so the
   // pending enter/leave callbacks may need to be cancelled if the state is toggled
   // before it finishes.
-  _enterCb?: PendingCallback
-  _leaveCb?: PendingCallback
+  [enterCbKey]?: PendingCallback
+  [leaveCbKey]?: PendingCallback
 }
 
 export function useTransitionState(): TransitionState {
@@ -259,9 +262,9 @@ const BaseTransitionImpl: ComponentOptions = {
             )
             leavingVNodesCache[String(oldInnerChild.key)] = oldInnerChild
             // early removal callback
-            el._leaveCb = () => {
+            el[leaveCbKey] = () => {
               earlyRemove()
-              el._leaveCb = undefined
+              el[leaveCbKey] = undefined
               delete enterHooks.delayedLeave
             }
             enterHooks.delayedLeave = delayedLeave
@@ -366,18 +369,18 @@ export function resolveTransitionHooks(
         }
       }
       // for same element (v-show)
-      if (el._leaveCb) {
-        el._leaveCb(true /* cancelled */)
+      if (el[leaveCbKey]) {
+        el[leaveCbKey](true /* cancelled */)
       }
       // for toggled element with same key (v-if)
       const leavingVNode = leavingVNodesCache[key]
       if (
         leavingVNode &&
         isSameVNodeType(vnode, leavingVNode) &&
-        leavingVNode.el!._leaveCb
+        (leavingVNode.el as TransitionElement)[leaveCbKey]
       ) {
         // force early removal (not cancelled)
-        leavingVNode.el!._leaveCb()
+        ;(leavingVNode.el as TransitionElement)[leaveCbKey]!()
       }
       callHook(hook, [el])
     },
@@ -396,7 +399,7 @@ export function resolveTransitionHooks(
         }
       }
       let called = false
-      const done = (el._enterCb = (cancelled?) => {
+      const done = (el[enterCbKey] = (cancelled?) => {
         if (called) return
         called = true
         if (cancelled) {
@@ -407,7 +410,7 @@ export function resolveTransitionHooks(
         if (hooks.delayedLeave) {
           hooks.delayedLeave()
         }
-        el._enterCb = undefined
+        el[enterCbKey] = undefined
       })
       if (hook) {
         callAsyncHook(hook, [el, done])
@@ -418,15 +421,15 @@ export function resolveTransitionHooks(
 
     leave(el, remove) {
       const key = String(vnode.key)
-      if (el._enterCb) {
-        el._enterCb(true /* cancelled */)
+      if (el[enterCbKey]) {
+        el[enterCbKey](true /* cancelled */)
       }
       if (state.isUnmounting) {
         return remove()
       }
       callHook(onBeforeLeave, [el])
       let called = false
-      const done = (el._leaveCb = (cancelled?) => {
+      const done = (el[leaveCbKey] = (cancelled?) => {
         if (called) return
         called = true
         remove()
@@ -435,7 +438,7 @@ export function resolveTransitionHooks(
         } else {
           callHook(onAfterLeave, [el])
         }
-        el._leaveCb = undefined
+        el[leaveCbKey] = undefined
         if (leavingVNodesCache[key] === vnode) {
           delete leavingVNodesCache[key]
         }
index a784c7d543f35dc8c7feba8f8c943d9f5f76aa83..c8da741677a25e6d8bcebe7e445b1e63b2c2fb69 100644 (file)
@@ -1,5 +1,5 @@
 import { patchProp } from '../src/patchProp'
-import { ElementWithTransition } from '../src/components/Transition'
+import { ElementWithTransition, vtcKey } from '../src/components/Transition'
 import { svgNS } from '../src/nodeOps'
 
 describe('runtime-dom: class patching', () => {
@@ -13,12 +13,12 @@ describe('runtime-dom: class patching', () => {
 
   test('transition class', () => {
     const el = document.createElement('div') as ElementWithTransition
-    el._vtc = new Set(['bar', 'baz'])
+    el[vtcKey] = new Set(['bar', 'baz'])
     patchProp(el, 'class', null, 'foo')
     expect(el.className).toBe('foo bar baz')
     patchProp(el, 'class', null, null)
     expect(el.className).toBe('bar baz')
-    delete el._vtc
+    delete el[vtcKey]
     patchProp(el, 'class', null, 'foo')
     expect(el.className).toBe('foo')
   })
index eebfdccca352621bd993692f589c10d393b5f5b6..b06752132980b1687ff0b8676161da8ff404a175 100644 (file)
@@ -32,12 +32,14 @@ export interface TransitionProps extends BaseTransitionProps<Element> {
   leaveToClass?: string
 }
 
+export const vtcKey = Symbol('_vtc')
+
 export interface ElementWithTransition extends HTMLElement {
   // _vtc = Vue Transition Classes.
   // Store the temporarily-added transition classes on the element
   // so that we can avoid overwriting them if the element's class is patched
   // during the transition.
-  _vtc?: Set<string>
+  [vtcKey]?: Set<string>
 }
 
 // DOM Transition is a higher-order-component based on the platform-agnostic
@@ -295,18 +297,18 @@ function NumberOf(val: unknown): number {
 export function addTransitionClass(el: Element, cls: string) {
   cls.split(/\s+/).forEach(c => c && el.classList.add(c))
   ;(
-    (el as ElementWithTransition)._vtc ||
-    ((el as ElementWithTransition)._vtc = new Set())
+    (el as ElementWithTransition)[vtcKey] ||
+    ((el as ElementWithTransition)[vtcKey] = new Set())
   ).add(cls)
 }
 
 export function removeTransitionClass(el: Element, cls: string) {
   cls.split(/\s+/).forEach(c => c && el.classList.remove(c))
-  const { _vtc } = el as ElementWithTransition
+  const _vtc = (el as ElementWithTransition)[vtcKey]
   if (_vtc) {
     _vtc.delete(cls)
     if (!_vtc!.size) {
-      ;(el as ElementWithTransition)._vtc = undefined
+      ;(el as ElementWithTransition)[vtcKey] = undefined
     }
   }
 }
index 5c78be26d72486fa1c2f1c272e0260a1d81ec6cf..fc5d260b91ef81121b7e0f156245fc9d676808b9 100644 (file)
@@ -6,7 +6,8 @@ import {
   getTransitionInfo,
   resolveTransitionProps,
   TransitionPropsValidators,
-  forceReflow
+  forceReflow,
+  vtcKey
 } from './Transition'
 import {
   Fragment,
@@ -29,7 +30,8 @@ import { extend } from '@vue/shared'
 
 const positionMap = new WeakMap<VNode, DOMRect>()
 const newPositionMap = new WeakMap<VNode, DOMRect>()
-
+const moveCbKey = Symbol('_moveCb')
+const enterCbKey = Symbol('_enterCb')
 export type TransitionGroupProps = Omit<TransitionProps, 'mode'> & {
   tag?: string
   moveClass?: string
@@ -80,13 +82,13 @@ const TransitionGroupImpl: ComponentOptions = {
         const style = el.style
         addTransitionClass(el, moveClass)
         style.transform = style.webkitTransform = style.transitionDuration = ''
-        const cb = ((el as any)._moveCb = (e: TransitionEvent) => {
+        const cb = ((el as any)[moveCbKey] = (e: TransitionEvent) => {
           if (e && e.target !== el) {
             return
           }
           if (!e || /transform$/.test(e.propertyName)) {
             el.removeEventListener('transitionend', cb)
-            ;(el as any)._moveCb = null
+            ;(el as any)[moveCbKey] = null
             removeTransitionClass(el, moveClass)
           }
         })
@@ -162,11 +164,11 @@ export const TransitionGroup = TransitionGroupImpl as unknown as {
 
 function callPendingCbs(c: VNode) {
   const el = c.el as any
-  if (el._moveCb) {
-    el._moveCb()
+  if (el[moveCbKey]) {
+    el[moveCbKey]()
   }
-  if (el._enterCb) {
-    el._enterCb()
+  if (el[enterCbKey]) {
+    el[enterCbKey]()
   }
 }
 
@@ -198,8 +200,9 @@ function hasCSSTransform(
   // all other transition classes applied to ensure only the move class
   // is applied.
   const clone = el.cloneNode() as HTMLElement
-  if (el._vtc) {
-    el._vtc.forEach(cls => {
+  const _vtc = el[vtcKey]
+  if (_vtc) {
+    _vtc.forEach(cls => {
       cls.split(/\s+/).forEach(c => c && clone.classList.remove(c))
     })
   }
index 2cf5f4cfc16a0eb013c9b634f7f246be64bfa7ca..89cd5f9d49f1bd72a090abbdee7822313f1304f0 100644 (file)
@@ -36,7 +36,9 @@ function onCompositionEnd(e: Event) {
   }
 }
 
-type ModelDirective<T> = ObjectDirective<T & { _assign: AssignerFn }>
+const assignKey = Symbol('_assign')
+
+type ModelDirective<T> = ObjectDirective<T & { [assignKey]: AssignerFn }>
 
 // We are exporting the v-model runtime directly as vnode hooks so that it can
 // be tree-shaken in case v-model is never used.
@@ -44,7 +46,7 @@ export const vModelText: ModelDirective<
   HTMLInputElement | HTMLTextAreaElement
 > = {
   created(el, { modifiers: { lazy, trim, number } }, vnode) {
-    el._assign = getModelAssigner(vnode)
+    el[assignKey] = getModelAssigner(vnode)
     const castToNumber =
       number || (vnode.props && vnode.props.type === 'number')
     addEventListener(el, lazy ? 'change' : 'input', e => {
@@ -56,7 +58,7 @@ export const vModelText: ModelDirective<
       if (castToNumber) {
         domValue = looseToNumber(domValue)
       }
-      el._assign(domValue)
+      el[assignKey](domValue)
     })
     if (trim) {
       addEventListener(el, 'change', () => {
@@ -78,7 +80,7 @@ export const vModelText: ModelDirective<
     el.value = value == null ? '' : value
   },
   beforeUpdate(el, { value, modifiers: { lazy, trim, number } }, vnode) {
-    el._assign = getModelAssigner(vnode)
+    el[assignKey] = getModelAssigner(vnode)
     // avoid clearing unresolved text. #2302
     if ((el as any).composing) return
     if (document.activeElement === el && el.type !== 'range') {
@@ -106,12 +108,12 @@ export const vModelCheckbox: ModelDirective<HTMLInputElement> = {
   // #4096 array checkboxes need to be deep traversed
   deep: true,
   created(el, _, vnode) {
-    el._assign = getModelAssigner(vnode)
+    el[assignKey] = getModelAssigner(vnode)
     addEventListener(el, 'change', () => {
       const modelValue = (el as any)._modelValue
       const elementValue = getValue(el)
       const checked = el.checked
-      const assign = el._assign
+      const assign = el[assignKey]
       if (isArray(modelValue)) {
         const index = looseIndexOf(modelValue, elementValue)
         const found = index !== -1
@@ -138,7 +140,7 @@ export const vModelCheckbox: ModelDirective<HTMLInputElement> = {
   // set initial checked on mount to wait for true-value/false-value
   mounted: setChecked,
   beforeUpdate(el, binding, vnode) {
-    el._assign = getModelAssigner(vnode)
+    el[assignKey] = getModelAssigner(vnode)
     setChecked(el, binding, vnode)
   }
 }
@@ -163,13 +165,13 @@ function setChecked(
 export const vModelRadio: ModelDirective<HTMLInputElement> = {
   created(el, { value }, vnode) {
     el.checked = looseEqual(value, vnode.props!.value)
-    el._assign = getModelAssigner(vnode)
+    el[assignKey] = getModelAssigner(vnode)
     addEventListener(el, 'change', () => {
-      el._assign(getValue(el))
+      el[assignKey](getValue(el))
     })
   },
   beforeUpdate(el, { value, oldValue }, vnode) {
-    el._assign = getModelAssigner(vnode)
+    el[assignKey] = getModelAssigner(vnode)
     if (value !== oldValue) {
       el.checked = looseEqual(value, vnode.props!.value)
     }
@@ -187,7 +189,7 @@ export const vModelSelect: ModelDirective<HTMLSelectElement> = {
         .map((o: HTMLOptionElement) =>
           number ? looseToNumber(getValue(o)) : getValue(o)
         )
-      el._assign(
+      el[assignKey](
         el.multiple
           ? isSetModel
             ? new Set(selectedVal)
@@ -195,7 +197,7 @@ export const vModelSelect: ModelDirective<HTMLSelectElement> = {
           : selectedVal[0]
       )
     })
-    el._assign = getModelAssigner(vnode)
+    el[assignKey] = getModelAssigner(vnode)
   },
   // set value in mounted & updated because <select> relies on its children
   // <option>s.
@@ -203,7 +205,7 @@ export const vModelSelect: ModelDirective<HTMLSelectElement> = {
     setSelected(el, value)
   },
   beforeUpdate(el, _binding, vnode) {
-    el._assign = getModelAssigner(vnode)
+    el[assignKey] = getModelAssigner(vnode)
   },
   updated(el, { value }) {
     setSelected(el, value)
index ee2aff0b8561c5f4030e2cb31b3fd880447ab8f1..b848ec9980f4c565daade1be40ce196d28cf7483 100644 (file)
@@ -1,13 +1,15 @@
 import { ObjectDirective } from '@vue/runtime-core'
 
+export const vShowOldKey = Symbol('_vod')
+
 interface VShowElement extends HTMLElement {
   // _vod = vue original display
-  _vod: string
+  [vShowOldKey]: string
 }
 
 export const vShow: ObjectDirective<VShowElement> = {
   beforeMount(el, { value }, { transition }) {
-    el._vod = el.style.display === 'none' ? '' : el.style.display
+    el[vShowOldKey] = el.style.display === 'none' ? '' : el.style.display
     if (transition && value) {
       transition.beforeEnter(el)
     } else {
@@ -41,7 +43,7 @@ export const vShow: ObjectDirective<VShowElement> = {
 }
 
 function setDisplay(el: VShowElement, value: unknown): void {
-  el.style.display = value ? el._vod : 'none'
+  el.style.display = value ? el[vShowOldKey] : 'none'
 }
 
 // SSR vnode transforms, only used when user includes client-oriented render
index 0be26ef8682602e9930b310f085a691aa7b7c0a3..bf2c6280c7754ed86b5ef16b952c1e1978455ca5 100644 (file)
@@ -1,4 +1,4 @@
-import { ElementWithTransition } from '../components/Transition'
+import { ElementWithTransition, vtcKey } from '../components/Transition'
 
 // compiler should normalize class + :class bindings on the same element
 // into a single binding ['staticClass', dynamic]
@@ -6,7 +6,7 @@ export function patchClass(el: Element, value: string | null, isSVG: boolean) {
   // directly setting className should be faster than setAttribute in theory
   // if this is an element during a transition, take the temporary transition
   // classes into account.
-  const transitionClasses = (el as ElementWithTransition)._vtc
+  const transitionClasses = (el as ElementWithTransition)[vtcKey]
   if (transitionClasses) {
     value = (
       value ? [value, ...transitionClasses] : [...transitionClasses]
index 272cededcf454c0756dd2d747b3f170480443f9e..884c55c92322b965982d0dd3eb77ec53e1f404ab 100644 (file)
@@ -30,15 +30,17 @@ export function removeEventListener(
   el.removeEventListener(event, handler, options)
 }
 
+const veiKey = Symbol('_vei')
+
 export function patchEvent(
-  el: Element & { _vei?: Record<string, Invoker | undefined> },
+  el: Element & { [veiKey]?: Record<string, Invoker | undefined> },
   rawName: string,
   prevValue: EventValue | null,
   nextValue: EventValue | null,
   instance: ComponentInternalInstance | null = null
 ) {
   // vei = vue event invokers
-  const invokers = el._vei || (el._vei = {})
+  const invokers = el[veiKey] || (el[veiKey] = {})
   const existingInvoker = invokers[rawName]
   if (nextValue && existingInvoker) {
     // patch
index 4eeeffe96b941f348d50e588b9517eb99c5a43e2..c18fd8aa9d50ce43d3672cb80ad601bfc44494c2 100644 (file)
@@ -1,5 +1,6 @@
 import { isString, hyphenate, capitalize, isArray } from '@vue/shared'
 import { camelize, warn } from '@vue/runtime-core'
+import { vShowOldKey } from '../directives/vShow'
 
 type Style = string | Record<string, string | string[]> | null
 
@@ -29,7 +30,7 @@ export function patchStyle(el: Element, prev: Style, next: Style) {
     // indicates that the `display` of the element is controlled by `v-show`,
     // so we always keep the current `display` value regardless of the `style`
     // value, thus handing over control to `v-show`.
-    if ('_vod' in el) {
+    if (vShowOldKey in el) {
       style.display = currentDisplay
     }
   }
index 433e8d36d4ce18a843adff993b1c1e44fdc66fa4..e944e7d8663b08a20d6760b0e5390d5a576d3772 100644 (file)
@@ -5,6 +5,7 @@
 // - runtime-core/src/renderer.ts
 // - compiler-core/src/transforms/transformElement.ts
 
+import { vtcKey } from '../../runtime-dom/src/components/Transition'
 import { render, h, ref, nextTick } from '../src'
 
 describe('SVG support', () => {
@@ -54,7 +55,7 @@ describe('SVG support', () => {
 
     // set a transition class on the <div> - which is only respected on non-svg
     // patches
-    ;(f2 as any)._vtc = ['baz']
+    ;(f2 as any)[vtcKey] = ['baz']
     cls.value = 'bar'
     await nextTick()
     expect(f1.getAttribute('class')).toBe('bar')