]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: remove circular dependencies in compiler
authorEvan You <yyx990803@gmail.com>
Thu, 23 Mar 2023 08:30:42 +0000 (16:30 +0800)
committerEvan You <yyx990803@gmail.com>
Thu, 23 Mar 2023 08:30:42 +0000 (16:30 +0800)
14 files changed:
packages/compiler-core/src/ast.ts
packages/compiler-core/src/codegen.ts
packages/compiler-core/src/compat/transformFilter.ts
packages/compiler-core/src/transform.ts
packages/compiler-core/src/transforms/hoistStatic.ts
packages/compiler-core/src/transforms/vFor.ts
packages/compiler-core/src/transforms/vIf.ts
packages/compiler-core/src/transforms/vMemo.ts
packages/compiler-core/src/utils.ts
packages/shared/src/general.ts [new file with mode: 0644]
packages/shared/src/index.ts
packages/shared/src/looseEqual.ts
packages/shared/src/normalizeProp.ts
packages/shared/src/toDisplayString.ts

index 457a9057633948cd963c2226271859603f2c2af5..515083c336ad130c12932e2f224d8d361151ded5 100644 (file)
@@ -7,11 +7,14 @@ import {
   OPEN_BLOCK,
   FRAGMENT,
   WITH_DIRECTIVES,
-  WITH_MEMO
+  WITH_MEMO,
+  CREATE_VNODE,
+  CREATE_ELEMENT_VNODE,
+  CREATE_BLOCK,
+  CREATE_ELEMENT_BLOCK
 } from './runtimeHelpers'
 import { PropsExpression } from './transforms/transformElement'
 import { ImportItem, TransformContext } from './transform'
-import { getVNodeBlockHelper, getVNodeHelper } from './utils'
 
 // Vue template is a platform-agnostic superset of HTML (syntax only).
 // More namespaces like SVG and MathML are declared by platform specific
@@ -810,3 +813,23 @@ export function createReturnStatement(
     loc: locStub
   }
 }
+
+export function getVNodeHelper(ssr: boolean, isComponent: boolean) {
+  return ssr || isComponent ? CREATE_VNODE : CREATE_ELEMENT_VNODE
+}
+
+export function getVNodeBlockHelper(ssr: boolean, isComponent: boolean) {
+  return ssr || isComponent ? CREATE_BLOCK : CREATE_ELEMENT_BLOCK
+}
+
+export function convertToBlock(
+  node: VNodeCall,
+  { helper, removeHelper, inSSR }: TransformContext
+) {
+  if (!node.isBlock) {
+    node.isBlock = true
+    removeHelper(getVNodeHelper(inSSR, node.isComponent))
+    helper(OPEN_BLOCK)
+    helper(getVNodeBlockHelper(inSSR, node.isComponent))
+  }
+}
index dce58737735cc89a797ba18b79294d402990b76b..e8da0a4cb41752357513c3f15c208d825a5b2414 100644 (file)
@@ -24,14 +24,14 @@ import {
   AssignmentExpression,
   ReturnStatement,
   VNodeCall,
-  SequenceExpression
+  SequenceExpression,
+  getVNodeBlockHelper,
+  getVNodeHelper
 } from './ast'
 import { SourceMapGenerator, RawSourceMap } from 'source-map'
 import {
   advancePositionWithMutation,
   assert,
-  getVNodeBlockHelper,
-  getVNodeHelper,
   isSimpleIdentifier,
   toValidAssetId
 } from './utils'
index 8eaa81eb3f17dc35fbc4867ff0968644679d4315..77331db4d806015759ec0c9b0b51d8b7e1328aef 100644 (file)
@@ -1,19 +1,18 @@
 import { RESOLVE_FILTER } from '../runtimeHelpers'
 import {
+  ExpressionNode,
   AttributeNode,
   DirectiveNode,
-  NodeTransform,
   NodeTypes,
-  SimpleExpressionNode,
-  toValidAssetId,
-  TransformContext
-} from '@vue/compiler-core'
+  SimpleExpressionNode
+} from '../ast'
 import {
   CompilerDeprecationTypes,
   isCompatEnabled,
   warnDeprecation
 } from './compatConfig'
-import { ExpressionNode } from '../ast'
+import { NodeTransform, TransformContext } from '../transform'
+import { toValidAssetId } from '../utils'
 
 const validDivisionCharRE = /[\w).+\-_$\]]/
 
index 3cb3e6bf01f47be068ab547ef23cea114722442a..4d9e8c6ed49d57102b3140abe59d6b207dd4f387 100644 (file)
@@ -17,7 +17,8 @@ import {
   TemplateLiteral,
   createVNodeCall,
   ConstantTypes,
-  ArrayExpression
+  ArrayExpression,
+  convertToBlock
 } from './ast'
 import {
   isString,
@@ -36,7 +37,7 @@ import {
   helperNameMap,
   CREATE_COMMENT
 } from './runtimeHelpers'
-import { isVSlot, makeBlock } from './utils'
+import { isVSlot } from './utils'
 import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
 import { CompilerCompatOptions } from './compat/compatConfig'
 
@@ -348,7 +349,7 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
       // SimpleExpressionNode
       const codegenNode = child.codegenNode
       if (codegenNode.type === NodeTypes.VNODE_CALL) {
-        makeBlock(codegenNode, context)
+        convertToBlock(codegenNode, context)
       }
       root.codegenNode = codegenNode
     } else {
index b2b7f871c0a1cba707947ec549267ddb2e8eaabe..5526163c6f95774f6c0135365218d3cb10a1c0d9 100644 (file)
@@ -12,11 +12,13 @@ import {
   ParentNode,
   JSChildNode,
   CallExpression,
-  createArrayExpression
+  createArrayExpression,
+  getVNodeBlockHelper,
+  getVNodeHelper
 } from '../ast'
 import { TransformContext } from '../transform'
 import { PatchFlags, isString, isSymbol, isArray } from '@vue/shared'
-import { getVNodeBlockHelper, getVNodeHelper, isSlotOutlet } from '../utils'
+import { isSlotOutlet } from '../utils'
 import {
   OPEN_BLOCK,
   GUARD_REACTIVE_PROPS,
index e72c64c1a58cfb05fe3dcee790f6ed2b0442c408..a44532c0d58b582712a14eb27a26b138c9211397 100644 (file)
@@ -26,7 +26,9 @@ import {
   ForIteratorExpression,
   ConstantTypes,
   createBlockStatement,
-  createCompoundExpression
+  createCompoundExpression,
+  getVNodeBlockHelper,
+  getVNodeHelper
 } from '../ast'
 import { createCompilerError, ErrorCodes } from '../errors'
 import {
@@ -35,8 +37,6 @@ import {
   isTemplateNode,
   isSlotOutlet,
   injectProp,
-  getVNodeBlockHelper,
-  getVNodeHelper,
   findDir
 } from '../utils'
 import {
index 636d9dff67320f36dd8e91e7a1ad90d5c12ec502..4e1673561c522fe809af5a33ac535bcbdf1d5072 100644 (file)
@@ -23,7 +23,8 @@ import {
   locStub,
   CacheExpression,
   ConstantTypes,
-  MemoExpression
+  MemoExpression,
+  convertToBlock
 } from '../ast'
 import { createCompilerError, ErrorCodes } from '../errors'
 import { processExpression } from './transformExpression'
@@ -34,10 +35,9 @@ import {
   findDir,
   findProp,
   isBuiltInType,
-  makeBlock
+  getMemoedVNodeCall
 } from '../utils'
 import { PatchFlags, PatchFlagNames } from '@vue/shared'
-import { getMemoedVNodeCall } from '..'
 
 export const transformIf = createStructuralDirectiveTransform(
   /^(if|else|else-if)$/,
@@ -301,7 +301,7 @@ function createChildrenCodegenNode(
     const vnodeCall = getMemoedVNodeCall(ret)
     // Change createVNode to createBlock.
     if (vnodeCall.type === NodeTypes.VNODE_CALL) {
-      makeBlock(vnodeCall, context)
+      convertToBlock(vnodeCall, context)
     }
     // inject branch key
     injectProp(vnodeCall, keyProperty, context)
index 4e150875d98fe25f5aa36dc4c12a9dd6000c2341..c14f6ceb860841c132caa8579772551aea9107b1 100644 (file)
@@ -1,6 +1,7 @@
 import { NodeTransform } from '../transform'
-import { findDir, makeBlock } from '../utils'
+import { findDir } from '../utils'
 import {
+  convertToBlock,
   createCallExpression,
   createFunctionExpression,
   ElementTypes,
@@ -26,7 +27,7 @@ export const transformMemo: NodeTransform = (node, context) => {
       if (codegenNode && codegenNode.type === NodeTypes.VNODE_CALL) {
         // non-component sub tree should be turned into a block
         if (node.tagType !== ElementTypes.COMPONENT) {
-          makeBlock(codegenNode, context)
+          convertToBlock(codegenNode, context)
         }
         node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [
           dir.exp!,
index 6a6b03a2ead991ca30f21dbc4c94e79b7e6d6fe1..bd2882b09e22a5bd39531c0b724511230acf410c 100644 (file)
@@ -35,12 +35,7 @@ import {
   TO_HANDLERS,
   NORMALIZE_PROPS,
   GUARD_REACTIVE_PROPS,
-  CREATE_BLOCK,
-  CREATE_ELEMENT_BLOCK,
-  CREATE_VNODE,
-  CREATE_ELEMENT_VNODE,
-  WITH_MEMO,
-  OPEN_BLOCK
+  WITH_MEMO
 } from './runtimeHelpers'
 import { isString, isObject, hyphenate, extend, NOOP } from '@vue/shared'
 import { PropsExpression } from './transforms/transformElement'
@@ -331,14 +326,6 @@ export function isSlotOutlet(
   return node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
 }
 
-export function getVNodeHelper(ssr: boolean, isComponent: boolean) {
-  return ssr || isComponent ? CREATE_VNODE : CREATE_ELEMENT_VNODE
-}
-
-export function getVNodeBlockHelper(ssr: boolean, isComponent: boolean) {
-  return ssr || isComponent ? CREATE_BLOCK : CREATE_ELEMENT_BLOCK
-}
-
 const propsHelperSet = new Set([NORMALIZE_PROPS, GUARD_REACTIVE_PROPS])
 
 function getUnnormalizedProps(
@@ -532,15 +519,3 @@ export function getMemoedVNodeCall(node: BlockCodegenNode | MemoExpression) {
     return node
   }
 }
-
-export function makeBlock(
-  node: VNodeCall,
-  { helper, removeHelper, inSSR }: TransformContext
-) {
-  if (!node.isBlock) {
-    node.isBlock = true
-    removeHelper(getVNodeHelper(inSSR, node.isComponent))
-    helper(OPEN_BLOCK)
-    helper(getVNodeBlockHelper(inSSR, node.isComponent))
-  }
-}
diff --git a/packages/shared/src/general.ts b/packages/shared/src/general.ts
new file mode 100644 (file)
index 0000000..6efaf52
--- /dev/null
@@ -0,0 +1,183 @@
+import { makeMap } from './makeMap'
+
+export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
+  ? Object.freeze({})
+  : {}
+export const EMPTY_ARR = __DEV__ ? Object.freeze([]) : []
+
+export const NOOP = () => {}
+
+/**
+ * Always return false.
+ */
+export const NO = () => false
+
+const onRE = /^on[^a-z]/
+export const isOn = (key: string) => onRE.test(key)
+
+export const isModelListener = (key: string) => key.startsWith('onUpdate:')
+
+export const extend = Object.assign
+
+export const remove = <T>(arr: T[], el: T) => {
+  const i = arr.indexOf(el)
+  if (i > -1) {
+    arr.splice(i, 1)
+  }
+}
+
+const hasOwnProperty = Object.prototype.hasOwnProperty
+export const hasOwn = (
+  val: object,
+  key: string | symbol
+): key is keyof typeof val => hasOwnProperty.call(val, key)
+
+export const isArray = Array.isArray
+export const isMap = (val: unknown): val is Map<any, any> =>
+  toTypeString(val) === '[object Map]'
+export const isSet = (val: unknown): val is Set<any> =>
+  toTypeString(val) === '[object Set]'
+
+export const isDate = (val: unknown): val is Date =>
+  toTypeString(val) === '[object Date]'
+export const isRegExp = (val: unknown): val is RegExp =>
+  toTypeString(val) === '[object RegExp]'
+export const isFunction = (val: unknown): val is Function =>
+  typeof val === 'function'
+export const isString = (val: unknown): val is string => typeof val === 'string'
+export const isSymbol = (val: unknown): val is symbol => typeof val === 'symbol'
+export const isObject = (val: unknown): val is Record<any, any> =>
+  val !== null && typeof val === 'object'
+
+export const isPromise = <T = any>(val: unknown): val is Promise<T> => {
+  return isObject(val) && isFunction(val.then) && isFunction(val.catch)
+}
+
+export const objectToString = Object.prototype.toString
+export const toTypeString = (value: unknown): string =>
+  objectToString.call(value)
+
+export const toRawType = (value: unknown): string => {
+  // extract "RawType" from strings like "[object RawType]"
+  return toTypeString(value).slice(8, -1)
+}
+
+export const isPlainObject = (val: unknown): val is object =>
+  toTypeString(val) === '[object Object]'
+
+export const isIntegerKey = (key: unknown) =>
+  isString(key) &&
+  key !== 'NaN' &&
+  key[0] !== '-' &&
+  '' + parseInt(key, 10) === key
+
+export const isReservedProp = /*#__PURE__*/ makeMap(
+  // the leading comma is intentional so empty string "" is also included
+  ',key,ref,ref_for,ref_key,' +
+    'onVnodeBeforeMount,onVnodeMounted,' +
+    'onVnodeBeforeUpdate,onVnodeUpdated,' +
+    'onVnodeBeforeUnmount,onVnodeUnmounted'
+)
+
+export const isBuiltInDirective = /*#__PURE__*/ makeMap(
+  'bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo'
+)
+
+const cacheStringFunction = <T extends (str: string) => string>(fn: T): T => {
+  const cache: Record<string, string> = Object.create(null)
+  return ((str: string) => {
+    const hit = cache[str]
+    return hit || (cache[str] = fn(str))
+  }) as T
+}
+
+const camelizeRE = /-(\w)/g
+/**
+ * @private
+ */
+export const camelize = cacheStringFunction((str: string): string => {
+  return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
+})
+
+const hyphenateRE = /\B([A-Z])/g
+/**
+ * @private
+ */
+export const hyphenate = cacheStringFunction((str: string) =>
+  str.replace(hyphenateRE, '-$1').toLowerCase()
+)
+
+/**
+ * @private
+ */
+export const capitalize = cacheStringFunction(
+  (str: string) => str.charAt(0).toUpperCase() + str.slice(1)
+)
+
+/**
+ * @private
+ */
+export const toHandlerKey = cacheStringFunction((str: string) =>
+  str ? `on${capitalize(str)}` : ``
+)
+
+// compare whether a value has changed, accounting for NaN.
+export const hasChanged = (value: any, oldValue: any): boolean =>
+  !Object.is(value, oldValue)
+
+export const invokeArrayFns = (fns: Function[], arg?: any) => {
+  for (let i = 0; i < fns.length; i++) {
+    fns[i](arg)
+  }
+}
+
+export const def = (obj: object, key: string | symbol, value: any) => {
+  Object.defineProperty(obj, key, {
+    configurable: true,
+    enumerable: false,
+    value
+  })
+}
+
+/**
+ * "123-foo" will be parsed to 123
+ * This is used for the .number modifier in v-model
+ */
+export const looseToNumber = (val: any): any => {
+  const n = parseFloat(val)
+  return isNaN(n) ? val : n
+}
+
+/**
+ * Only conerces number-like strings
+ * "123-foo" will be returned as-is
+ */
+export const toNumber = (val: any): any => {
+  const n = isString(val) ? Number(val) : NaN
+  return isNaN(n) ? val : n
+}
+
+let _globalThis: any
+export const getGlobalThis = (): any => {
+  return (
+    _globalThis ||
+    (_globalThis =
+      typeof globalThis !== 'undefined'
+        ? globalThis
+        : typeof self !== 'undefined'
+        ? self
+        : typeof window !== 'undefined'
+        ? window
+        : typeof global !== 'undefined'
+        ? global
+        : {})
+  )
+}
+
+const identRE = /^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/
+
+export function genPropsAccessExp(name: string) {
+  return identRE.test(name)
+    ? `__props.${name}`
+    : `__props[${JSON.stringify(name)}]`
+}
index e3fcd86627ba0ee4832baade5adb5206e22759f8..2e7292f0eac8943ae00aaf6190c59a70e9d6923a 100644 (file)
@@ -1,6 +1,5 @@
-import { makeMap } from './makeMap'
-
-export { makeMap }
+export { makeMap } from './makeMap'
+export * from './general'
 export * from './patchFlags'
 export * from './shapeFlags'
 export * from './slotFlags'
@@ -13,185 +12,3 @@ export * from './escapeHtml'
 export * from './looseEqual'
 export * from './toDisplayString'
 export * from './typeUtils'
-
-export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
-  ? Object.freeze({})
-  : {}
-export const EMPTY_ARR = __DEV__ ? Object.freeze([]) : []
-
-export const NOOP = () => {}
-
-/**
- * Always return false.
- */
-export const NO = () => false
-
-const onRE = /^on[^a-z]/
-export const isOn = (key: string) => onRE.test(key)
-
-export const isModelListener = (key: string) => key.startsWith('onUpdate:')
-
-export const extend = Object.assign
-
-export const remove = <T>(arr: T[], el: T) => {
-  const i = arr.indexOf(el)
-  if (i > -1) {
-    arr.splice(i, 1)
-  }
-}
-
-const hasOwnProperty = Object.prototype.hasOwnProperty
-export const hasOwn = (
-  val: object,
-  key: string | symbol
-): key is keyof typeof val => hasOwnProperty.call(val, key)
-
-export const isArray = Array.isArray
-export const isMap = (val: unknown): val is Map<any, any> =>
-  toTypeString(val) === '[object Map]'
-export const isSet = (val: unknown): val is Set<any> =>
-  toTypeString(val) === '[object Set]'
-
-export const isDate = (val: unknown): val is Date =>
-  toTypeString(val) === '[object Date]'
-export const isRegExp = (val: unknown): val is RegExp =>
-  toTypeString(val) === '[object RegExp]'
-export const isFunction = (val: unknown): val is Function =>
-  typeof val === 'function'
-export const isString = (val: unknown): val is string => typeof val === 'string'
-export const isSymbol = (val: unknown): val is symbol => typeof val === 'symbol'
-export const isObject = (val: unknown): val is Record<any, any> =>
-  val !== null && typeof val === 'object'
-
-export const isPromise = <T = any>(val: unknown): val is Promise<T> => {
-  return isObject(val) && isFunction(val.then) && isFunction(val.catch)
-}
-
-export const objectToString = Object.prototype.toString
-export const toTypeString = (value: unknown): string =>
-  objectToString.call(value)
-
-export const toRawType = (value: unknown): string => {
-  // extract "RawType" from strings like "[object RawType]"
-  return toTypeString(value).slice(8, -1)
-}
-
-export const isPlainObject = (val: unknown): val is object =>
-  toTypeString(val) === '[object Object]'
-
-export const isIntegerKey = (key: unknown) =>
-  isString(key) &&
-  key !== 'NaN' &&
-  key[0] !== '-' &&
-  '' + parseInt(key, 10) === key
-
-export const isReservedProp = /*#__PURE__*/ makeMap(
-  // the leading comma is intentional so empty string "" is also included
-  ',key,ref,ref_for,ref_key,' +
-    'onVnodeBeforeMount,onVnodeMounted,' +
-    'onVnodeBeforeUpdate,onVnodeUpdated,' +
-    'onVnodeBeforeUnmount,onVnodeUnmounted'
-)
-
-export const isBuiltInDirective = /*#__PURE__*/ makeMap(
-  'bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo'
-)
-
-const cacheStringFunction = <T extends (str: string) => string>(fn: T): T => {
-  const cache: Record<string, string> = Object.create(null)
-  return ((str: string) => {
-    const hit = cache[str]
-    return hit || (cache[str] = fn(str))
-  }) as T
-}
-
-const camelizeRE = /-(\w)/g
-/**
- * @private
- */
-export const camelize = cacheStringFunction((str: string): string => {
-  return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
-})
-
-const hyphenateRE = /\B([A-Z])/g
-/**
- * @private
- */
-export const hyphenate = cacheStringFunction((str: string) =>
-  str.replace(hyphenateRE, '-$1').toLowerCase()
-)
-
-/**
- * @private
- */
-export const capitalize = cacheStringFunction(
-  (str: string) => str.charAt(0).toUpperCase() + str.slice(1)
-)
-
-/**
- * @private
- */
-export const toHandlerKey = cacheStringFunction((str: string) =>
-  str ? `on${capitalize(str)}` : ``
-)
-
-// compare whether a value has changed, accounting for NaN.
-export const hasChanged = (value: any, oldValue: any): boolean =>
-  !Object.is(value, oldValue)
-
-export const invokeArrayFns = (fns: Function[], arg?: any) => {
-  for (let i = 0; i < fns.length; i++) {
-    fns[i](arg)
-  }
-}
-
-export const def = (obj: object, key: string | symbol, value: any) => {
-  Object.defineProperty(obj, key, {
-    configurable: true,
-    enumerable: false,
-    value
-  })
-}
-
-/**
- * "123-foo" will be parsed to 123
- * This is used for the .number modifier in v-model
- */
-export const looseToNumber = (val: any): any => {
-  const n = parseFloat(val)
-  return isNaN(n) ? val : n
-}
-
-/**
- * Only conerces number-like strings
- * "123-foo" will be returned as-is
- */
-export const toNumber = (val: any): any => {
-  const n = isString(val) ? Number(val) : NaN
-  return isNaN(n) ? val : n
-}
-
-let _globalThis: any
-export const getGlobalThis = (): any => {
-  return (
-    _globalThis ||
-    (_globalThis =
-      typeof globalThis !== 'undefined'
-        ? globalThis
-        : typeof self !== 'undefined'
-        ? self
-        : typeof window !== 'undefined'
-        ? window
-        : typeof global !== 'undefined'
-        ? global
-        : {})
-  )
-}
-
-const identRE = /^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/
-
-export function genPropsAccessExp(name: string) {
-  return identRE.test(name)
-    ? `__props.${name}`
-    : `__props[${JSON.stringify(name)}]`
-}
index 387150535c7484163519136dc919a4150929d22a..db869922fc15e6cf426888e037cc9bde14a484e9 100644 (file)
@@ -1,4 +1,4 @@
-import { isArray, isDate, isObject, isSymbol } from './'
+import { isArray, isDate, isObject, isSymbol } from './general'
 
 function looseCompareArrays(a: any[], b: any[]) {
   if (a.length !== b.length) return false
index b6f822670fe055933806eb153773d9cf01d227a5..e6ef62a5c80401cd8aa70ca719a32987941ec535 100644 (file)
@@ -1,4 +1,4 @@
-import { isArray, isString, isObject, hyphenate } from './'
+import { isArray, isString, isObject, hyphenate } from './general'
 
 export type NormalizedStyle = Record<string, string | number>
 
index efe3b7cc0e88eecbd581da9d7af0e6ad219dccb1..7f5818d94915ded5db50e1738ff182b662362c29 100644 (file)
@@ -7,7 +7,7 @@ import {
   isSet,
   objectToString,
   isString
-} from './index'
+} from './general'
 
 /**
  * For converting {{ interpolation }} values to displayed strings.