refactor: remove circular dependencies in compiler
This commit is contained in:
parent
650f5c26f4
commit
aac163110f
|
@ -7,11 +7,14 @@ import {
|
||||||
OPEN_BLOCK,
|
OPEN_BLOCK,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
WITH_DIRECTIVES,
|
WITH_DIRECTIVES,
|
||||||
WITH_MEMO
|
WITH_MEMO,
|
||||||
|
CREATE_VNODE,
|
||||||
|
CREATE_ELEMENT_VNODE,
|
||||||
|
CREATE_BLOCK,
|
||||||
|
CREATE_ELEMENT_BLOCK
|
||||||
} from './runtimeHelpers'
|
} from './runtimeHelpers'
|
||||||
import { PropsExpression } from './transforms/transformElement'
|
import { PropsExpression } from './transforms/transformElement'
|
||||||
import { ImportItem, TransformContext } from './transform'
|
import { ImportItem, TransformContext } from './transform'
|
||||||
import { getVNodeBlockHelper, getVNodeHelper } from './utils'
|
|
||||||
|
|
||||||
// Vue template is a platform-agnostic superset of HTML (syntax only).
|
// Vue template is a platform-agnostic superset of HTML (syntax only).
|
||||||
// More namespaces like SVG and MathML are declared by platform specific
|
// More namespaces like SVG and MathML are declared by platform specific
|
||||||
|
@ -810,3 +813,23 @@ export function createReturnStatement(
|
||||||
loc: locStub
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,14 +24,14 @@ import {
|
||||||
AssignmentExpression,
|
AssignmentExpression,
|
||||||
ReturnStatement,
|
ReturnStatement,
|
||||||
VNodeCall,
|
VNodeCall,
|
||||||
SequenceExpression
|
SequenceExpression,
|
||||||
|
getVNodeBlockHelper,
|
||||||
|
getVNodeHelper
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import { SourceMapGenerator, RawSourceMap } from 'source-map'
|
import { SourceMapGenerator, RawSourceMap } from 'source-map'
|
||||||
import {
|
import {
|
||||||
advancePositionWithMutation,
|
advancePositionWithMutation,
|
||||||
assert,
|
assert,
|
||||||
getVNodeBlockHelper,
|
|
||||||
getVNodeHelper,
|
|
||||||
isSimpleIdentifier,
|
isSimpleIdentifier,
|
||||||
toValidAssetId
|
toValidAssetId
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
import { RESOLVE_FILTER } from '../runtimeHelpers'
|
import { RESOLVE_FILTER } from '../runtimeHelpers'
|
||||||
import {
|
import {
|
||||||
|
ExpressionNode,
|
||||||
AttributeNode,
|
AttributeNode,
|
||||||
DirectiveNode,
|
DirectiveNode,
|
||||||
NodeTransform,
|
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
SimpleExpressionNode,
|
SimpleExpressionNode
|
||||||
toValidAssetId,
|
} from '../ast'
|
||||||
TransformContext
|
|
||||||
} from '@vue/compiler-core'
|
|
||||||
import {
|
import {
|
||||||
CompilerDeprecationTypes,
|
CompilerDeprecationTypes,
|
||||||
isCompatEnabled,
|
isCompatEnabled,
|
||||||
warnDeprecation
|
warnDeprecation
|
||||||
} from './compatConfig'
|
} from './compatConfig'
|
||||||
import { ExpressionNode } from '../ast'
|
import { NodeTransform, TransformContext } from '../transform'
|
||||||
|
import { toValidAssetId } from '../utils'
|
||||||
|
|
||||||
const validDivisionCharRE = /[\w).+\-_$\]]/
|
const validDivisionCharRE = /[\w).+\-_$\]]/
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@ import {
|
||||||
TemplateLiteral,
|
TemplateLiteral,
|
||||||
createVNodeCall,
|
createVNodeCall,
|
||||||
ConstantTypes,
|
ConstantTypes,
|
||||||
ArrayExpression
|
ArrayExpression,
|
||||||
|
convertToBlock
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import {
|
import {
|
||||||
isString,
|
isString,
|
||||||
|
@ -36,7 +37,7 @@ import {
|
||||||
helperNameMap,
|
helperNameMap,
|
||||||
CREATE_COMMENT
|
CREATE_COMMENT
|
||||||
} from './runtimeHelpers'
|
} from './runtimeHelpers'
|
||||||
import { isVSlot, makeBlock } from './utils'
|
import { isVSlot } from './utils'
|
||||||
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
|
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
|
||||||
import { CompilerCompatOptions } from './compat/compatConfig'
|
import { CompilerCompatOptions } from './compat/compatConfig'
|
||||||
|
|
||||||
|
@ -348,7 +349,7 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
|
||||||
// SimpleExpressionNode
|
// SimpleExpressionNode
|
||||||
const codegenNode = child.codegenNode
|
const codegenNode = child.codegenNode
|
||||||
if (codegenNode.type === NodeTypes.VNODE_CALL) {
|
if (codegenNode.type === NodeTypes.VNODE_CALL) {
|
||||||
makeBlock(codegenNode, context)
|
convertToBlock(codegenNode, context)
|
||||||
}
|
}
|
||||||
root.codegenNode = codegenNode
|
root.codegenNode = codegenNode
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -12,11 +12,13 @@ import {
|
||||||
ParentNode,
|
ParentNode,
|
||||||
JSChildNode,
|
JSChildNode,
|
||||||
CallExpression,
|
CallExpression,
|
||||||
createArrayExpression
|
createArrayExpression,
|
||||||
|
getVNodeBlockHelper,
|
||||||
|
getVNodeHelper
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { TransformContext } from '../transform'
|
import { TransformContext } from '../transform'
|
||||||
import { PatchFlags, isString, isSymbol, isArray } from '@vue/shared'
|
import { PatchFlags, isString, isSymbol, isArray } from '@vue/shared'
|
||||||
import { getVNodeBlockHelper, getVNodeHelper, isSlotOutlet } from '../utils'
|
import { isSlotOutlet } from '../utils'
|
||||||
import {
|
import {
|
||||||
OPEN_BLOCK,
|
OPEN_BLOCK,
|
||||||
GUARD_REACTIVE_PROPS,
|
GUARD_REACTIVE_PROPS,
|
||||||
|
|
|
@ -26,7 +26,9 @@ import {
|
||||||
ForIteratorExpression,
|
ForIteratorExpression,
|
||||||
ConstantTypes,
|
ConstantTypes,
|
||||||
createBlockStatement,
|
createBlockStatement,
|
||||||
createCompoundExpression
|
createCompoundExpression,
|
||||||
|
getVNodeBlockHelper,
|
||||||
|
getVNodeHelper
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
import {
|
import {
|
||||||
|
@ -35,8 +37,6 @@ import {
|
||||||
isTemplateNode,
|
isTemplateNode,
|
||||||
isSlotOutlet,
|
isSlotOutlet,
|
||||||
injectProp,
|
injectProp,
|
||||||
getVNodeBlockHelper,
|
|
||||||
getVNodeHelper,
|
|
||||||
findDir
|
findDir
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import {
|
import {
|
||||||
|
|
|
@ -23,7 +23,8 @@ import {
|
||||||
locStub,
|
locStub,
|
||||||
CacheExpression,
|
CacheExpression,
|
||||||
ConstantTypes,
|
ConstantTypes,
|
||||||
MemoExpression
|
MemoExpression,
|
||||||
|
convertToBlock
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
import { processExpression } from './transformExpression'
|
import { processExpression } from './transformExpression'
|
||||||
|
@ -34,10 +35,9 @@ import {
|
||||||
findDir,
|
findDir,
|
||||||
findProp,
|
findProp,
|
||||||
isBuiltInType,
|
isBuiltInType,
|
||||||
makeBlock
|
getMemoedVNodeCall
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||||
import { getMemoedVNodeCall } from '..'
|
|
||||||
|
|
||||||
export const transformIf = createStructuralDirectiveTransform(
|
export const transformIf = createStructuralDirectiveTransform(
|
||||||
/^(if|else|else-if)$/,
|
/^(if|else|else-if)$/,
|
||||||
|
@ -301,7 +301,7 @@ function createChildrenCodegenNode(
|
||||||
const vnodeCall = getMemoedVNodeCall(ret)
|
const vnodeCall = getMemoedVNodeCall(ret)
|
||||||
// Change createVNode to createBlock.
|
// Change createVNode to createBlock.
|
||||||
if (vnodeCall.type === NodeTypes.VNODE_CALL) {
|
if (vnodeCall.type === NodeTypes.VNODE_CALL) {
|
||||||
makeBlock(vnodeCall, context)
|
convertToBlock(vnodeCall, context)
|
||||||
}
|
}
|
||||||
// inject branch key
|
// inject branch key
|
||||||
injectProp(vnodeCall, keyProperty, context)
|
injectProp(vnodeCall, keyProperty, context)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { NodeTransform } from '../transform'
|
import { NodeTransform } from '../transform'
|
||||||
import { findDir, makeBlock } from '../utils'
|
import { findDir } from '../utils'
|
||||||
import {
|
import {
|
||||||
|
convertToBlock,
|
||||||
createCallExpression,
|
createCallExpression,
|
||||||
createFunctionExpression,
|
createFunctionExpression,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
|
@ -26,7 +27,7 @@ export const transformMemo: NodeTransform = (node, context) => {
|
||||||
if (codegenNode && codegenNode.type === NodeTypes.VNODE_CALL) {
|
if (codegenNode && codegenNode.type === NodeTypes.VNODE_CALL) {
|
||||||
// non-component sub tree should be turned into a block
|
// non-component sub tree should be turned into a block
|
||||||
if (node.tagType !== ElementTypes.COMPONENT) {
|
if (node.tagType !== ElementTypes.COMPONENT) {
|
||||||
makeBlock(codegenNode, context)
|
convertToBlock(codegenNode, context)
|
||||||
}
|
}
|
||||||
node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [
|
node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [
|
||||||
dir.exp!,
|
dir.exp!,
|
||||||
|
|
|
@ -35,12 +35,7 @@ import {
|
||||||
TO_HANDLERS,
|
TO_HANDLERS,
|
||||||
NORMALIZE_PROPS,
|
NORMALIZE_PROPS,
|
||||||
GUARD_REACTIVE_PROPS,
|
GUARD_REACTIVE_PROPS,
|
||||||
CREATE_BLOCK,
|
WITH_MEMO
|
||||||
CREATE_ELEMENT_BLOCK,
|
|
||||||
CREATE_VNODE,
|
|
||||||
CREATE_ELEMENT_VNODE,
|
|
||||||
WITH_MEMO,
|
|
||||||
OPEN_BLOCK
|
|
||||||
} from './runtimeHelpers'
|
} from './runtimeHelpers'
|
||||||
import { isString, isObject, hyphenate, extend, NOOP } from '@vue/shared'
|
import { isString, isObject, hyphenate, extend, NOOP } from '@vue/shared'
|
||||||
import { PropsExpression } from './transforms/transformElement'
|
import { PropsExpression } from './transforms/transformElement'
|
||||||
|
@ -331,14 +326,6 @@ export function isSlotOutlet(
|
||||||
return node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
|
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])
|
const propsHelperSet = new Set([NORMALIZE_PROPS, GUARD_REACTIVE_PROPS])
|
||||||
|
|
||||||
function getUnnormalizedProps(
|
function getUnnormalizedProps(
|
||||||
|
@ -532,15 +519,3 @@ export function getMemoedVNodeCall(node: BlockCodegenNode | MemoExpression) {
|
||||||
return node
|
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)}]`
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
import { makeMap } from './makeMap'
|
export { makeMap } from './makeMap'
|
||||||
|
export * from './general'
|
||||||
export { makeMap }
|
|
||||||
export * from './patchFlags'
|
export * from './patchFlags'
|
||||||
export * from './shapeFlags'
|
export * from './shapeFlags'
|
||||||
export * from './slotFlags'
|
export * from './slotFlags'
|
||||||
|
@ -13,185 +12,3 @@ export * from './escapeHtml'
|
||||||
export * from './looseEqual'
|
export * from './looseEqual'
|
||||||
export * from './toDisplayString'
|
export * from './toDisplayString'
|
||||||
export * from './typeUtils'
|
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)}]`
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isArray, isDate, isObject, isSymbol } from './'
|
import { isArray, isDate, isObject, isSymbol } from './general'
|
||||||
|
|
||||||
function looseCompareArrays(a: any[], b: any[]) {
|
function looseCompareArrays(a: any[], b: any[]) {
|
||||||
if (a.length !== b.length) return false
|
if (a.length !== b.length) return false
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isArray, isString, isObject, hyphenate } from './'
|
import { isArray, isString, isObject, hyphenate } from './general'
|
||||||
|
|
||||||
export type NormalizedStyle = Record<string, string | number>
|
export type NormalizedStyle = Record<string, string | number>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
isSet,
|
isSet,
|
||||||
objectToString,
|
objectToString,
|
||||||
isString
|
isString
|
||||||
} from './index'
|
} from './general'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For converting {{ interpolation }} values to displayed strings.
|
* For converting {{ interpolation }} values to displayed strings.
|
||||||
|
|
Loading…
Reference in New Issue