You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
596 lines
24 KiB
596 lines
24 KiB
/** |
|
* Make a map and return a function for checking if a key |
|
* is in that map. |
|
* IMPORTANT: all calls of this function must be prefixed with |
|
* \/\*#\_\_PURE\_\_\*\/ |
|
* So that rollup can tree-shake them if necessary. |
|
*/ |
|
function makeMap(str, expectsLowerCase) { |
|
const map = Object.create(null); |
|
const list = str.split(','); |
|
for (let i = 0; i < list.length; i++) { |
|
map[list[i]] = true; |
|
} |
|
return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val]; |
|
} |
|
|
|
/** |
|
* dev only flag -> name mapping |
|
*/ |
|
const PatchFlagNames = { |
|
[1 /* TEXT */]: `TEXT`, |
|
[2 /* CLASS */]: `CLASS`, |
|
[4 /* STYLE */]: `STYLE`, |
|
[8 /* PROPS */]: `PROPS`, |
|
[16 /* FULL_PROPS */]: `FULL_PROPS`, |
|
[32 /* HYDRATE_EVENTS */]: `HYDRATE_EVENTS`, |
|
[64 /* STABLE_FRAGMENT */]: `STABLE_FRAGMENT`, |
|
[128 /* KEYED_FRAGMENT */]: `KEYED_FRAGMENT`, |
|
[256 /* UNKEYED_FRAGMENT */]: `UNKEYED_FRAGMENT`, |
|
[512 /* NEED_PATCH */]: `NEED_PATCH`, |
|
[1024 /* DYNAMIC_SLOTS */]: `DYNAMIC_SLOTS`, |
|
[2048 /* DEV_ROOT_FRAGMENT */]: `DEV_ROOT_FRAGMENT`, |
|
[-1 /* HOISTED */]: `HOISTED`, |
|
[-2 /* BAIL */]: `BAIL` |
|
}; |
|
|
|
/** |
|
* Dev only |
|
*/ |
|
const slotFlagsText = { |
|
[1 /* STABLE */]: 'STABLE', |
|
[2 /* DYNAMIC */]: 'DYNAMIC', |
|
[3 /* FORWARDED */]: 'FORWARDED' |
|
}; |
|
|
|
const GLOBALS_WHITE_LISTED = 'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' + |
|
'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' + |
|
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt'; |
|
const isGloballyWhitelisted = /*#__PURE__*/ makeMap(GLOBALS_WHITE_LISTED); |
|
|
|
const range = 2; |
|
function generateCodeFrame(source, start = 0, end = source.length) { |
|
// Split the content into individual lines but capture the newline sequence |
|
// that separated each line. This is important because the actual sequence is |
|
// needed to properly take into account the full line length for offset |
|
// comparison |
|
let lines = source.split(/(\r?\n)/); |
|
// Separate the lines and newline sequences into separate arrays for easier referencing |
|
const newlineSequences = lines.filter((_, idx) => idx % 2 === 1); |
|
lines = lines.filter((_, idx) => idx % 2 === 0); |
|
let count = 0; |
|
const res = []; |
|
for (let i = 0; i < lines.length; i++) { |
|
count += |
|
lines[i].length + |
|
((newlineSequences[i] && newlineSequences[i].length) || 0); |
|
if (count >= start) { |
|
for (let j = i - range; j <= i + range || end > count; j++) { |
|
if (j < 0 || j >= lines.length) |
|
continue; |
|
const line = j + 1; |
|
res.push(`${line}${' '.repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`); |
|
const lineLength = lines[j].length; |
|
const newLineSeqLength = (newlineSequences[j] && newlineSequences[j].length) || 0; |
|
if (j === i) { |
|
// push underline |
|
const pad = start - (count - (lineLength + newLineSeqLength)); |
|
const length = Math.max(1, end > count ? lineLength - pad : end - start); |
|
res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length)); |
|
} |
|
else if (j > i) { |
|
if (end > count) { |
|
const length = Math.max(Math.min(end - count, lineLength), 1); |
|
res.push(` | ` + '^'.repeat(length)); |
|
} |
|
count += lineLength + newLineSeqLength; |
|
} |
|
} |
|
break; |
|
} |
|
} |
|
return res.join('\n'); |
|
} |
|
|
|
/** |
|
* On the client we only need to offer special cases for boolean attributes that |
|
* have different names from their corresponding dom properties: |
|
* - itemscope -> N/A |
|
* - allowfullscreen -> allowFullscreen |
|
* - formnovalidate -> formNoValidate |
|
* - ismap -> isMap |
|
* - nomodule -> noModule |
|
* - novalidate -> noValidate |
|
* - readonly -> readOnly |
|
*/ |
|
const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`; |
|
const isSpecialBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs); |
|
/** |
|
* The full list is needed during SSR to produce the correct initial markup. |
|
*/ |
|
const isBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs + |
|
`,async,autofocus,autoplay,controls,default,defer,disabled,hidden,` + |
|
`loop,open,required,reversed,scoped,seamless,` + |
|
`checked,muted,multiple,selected`); |
|
/** |
|
* Boolean attributes should be included if the value is truthy or ''. |
|
* e.g. `<select multiple>` compiles to `{ multiple: '' }` |
|
*/ |
|
function includeBooleanAttr(value) { |
|
return !!value || value === ''; |
|
} |
|
const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/; |
|
const attrValidationCache = {}; |
|
function isSSRSafeAttrName(name) { |
|
if (attrValidationCache.hasOwnProperty(name)) { |
|
return attrValidationCache[name]; |
|
} |
|
const isUnsafe = unsafeAttrCharRE.test(name); |
|
if (isUnsafe) { |
|
console.error(`unsafe attribute name: ${name}`); |
|
} |
|
return (attrValidationCache[name] = !isUnsafe); |
|
} |
|
const propsToAttrMap = { |
|
acceptCharset: 'accept-charset', |
|
className: 'class', |
|
htmlFor: 'for', |
|
httpEquiv: 'http-equiv' |
|
}; |
|
/** |
|
* CSS properties that accept plain numbers |
|
*/ |
|
const isNoUnitNumericStyleProp = /*#__PURE__*/ makeMap(`animation-iteration-count,border-image-outset,border-image-slice,` + |
|
`border-image-width,box-flex,box-flex-group,box-ordinal-group,column-count,` + |
|
`columns,flex,flex-grow,flex-positive,flex-shrink,flex-negative,flex-order,` + |
|
`grid-row,grid-row-end,grid-row-span,grid-row-start,grid-column,` + |
|
`grid-column-end,grid-column-span,grid-column-start,font-weight,line-clamp,` + |
|
`line-height,opacity,order,orphans,tab-size,widows,z-index,zoom,` + |
|
// SVG |
|
`fill-opacity,flood-opacity,stop-opacity,stroke-dasharray,stroke-dashoffset,` + |
|
`stroke-miterlimit,stroke-opacity,stroke-width`); |
|
/** |
|
* Known attributes, this is used for stringification of runtime static nodes |
|
* so that we don't stringify bindings that cannot be set from HTML. |
|
* Don't also forget to allow `data-*` and `aria-*`! |
|
* Generated from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes |
|
*/ |
|
const isKnownHtmlAttr = /*#__PURE__*/ makeMap(`accept,accept-charset,accesskey,action,align,allow,alt,async,` + |
|
`autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,` + |
|
`border,buffered,capture,challenge,charset,checked,cite,class,code,` + |
|
`codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,` + |
|
`coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,` + |
|
`disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,` + |
|
`formaction,formenctype,formmethod,formnovalidate,formtarget,headers,` + |
|
`height,hidden,high,href,hreflang,http-equiv,icon,id,importance,integrity,` + |
|
`ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,` + |
|
`manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,` + |
|
`open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,` + |
|
`referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,` + |
|
`selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,` + |
|
`start,step,style,summary,tabindex,target,title,translate,type,usemap,` + |
|
`value,width,wrap`); |
|
/** |
|
* Generated from https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute |
|
*/ |
|
const isKnownSvgAttr = /*#__PURE__*/ makeMap(`xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,` + |
|
`arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,` + |
|
`baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,` + |
|
`clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,` + |
|
`color-interpolation-filters,color-profile,color-rendering,` + |
|
`contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,` + |
|
`descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,` + |
|
`dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,` + |
|
`fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,` + |
|
`font-family,font-size,font-size-adjust,font-stretch,font-style,` + |
|
`font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,` + |
|
`glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,` + |
|
`gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,` + |
|
`horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,` + |
|
`k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,` + |
|
`lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,` + |
|
`marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,` + |
|
`mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,` + |
|
`name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,` + |
|
`overflow,overline-position,overline-thickness,panose-1,paint-order,path,` + |
|
`pathLength,patternContentUnits,patternTransform,patternUnits,ping,` + |
|
`pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,` + |
|
`preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,` + |
|
`rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,` + |
|
`restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,` + |
|
`specularConstant,specularExponent,speed,spreadMethod,startOffset,` + |
|
`stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,` + |
|
`strikethrough-position,strikethrough-thickness,string,stroke,` + |
|
`stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,` + |
|
`stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,` + |
|
`systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,` + |
|
`text-decoration,text-rendering,textLength,to,transform,transform-origin,` + |
|
`type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,` + |
|
`unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,` + |
|
`v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,` + |
|
`vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,` + |
|
`writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,` + |
|
`xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,` + |
|
`xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan`); |
|
|
|
function normalizeStyle(value) { |
|
if (isArray(value)) { |
|
const res = {}; |
|
for (let i = 0; i < value.length; i++) { |
|
const item = value[i]; |
|
const normalized = isString(item) |
|
? parseStringStyle(item) |
|
: normalizeStyle(item); |
|
if (normalized) { |
|
for (const key in normalized) { |
|
res[key] = normalized[key]; |
|
} |
|
} |
|
} |
|
return res; |
|
} |
|
else if (isString(value)) { |
|
return value; |
|
} |
|
else if (isObject(value)) { |
|
return value; |
|
} |
|
} |
|
const listDelimiterRE = /;(?![^(]*\))/g; |
|
const propertyDelimiterRE = /:(.+)/; |
|
function parseStringStyle(cssText) { |
|
const ret = {}; |
|
cssText.split(listDelimiterRE).forEach(item => { |
|
if (item) { |
|
const tmp = item.split(propertyDelimiterRE); |
|
tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim()); |
|
} |
|
}); |
|
return ret; |
|
} |
|
function stringifyStyle(styles) { |
|
let ret = ''; |
|
if (!styles || isString(styles)) { |
|
return ret; |
|
} |
|
for (const key in styles) { |
|
const value = styles[key]; |
|
const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key); |
|
if (isString(value) || |
|
(typeof value === 'number' && isNoUnitNumericStyleProp(normalizedKey))) { |
|
// only render valid values |
|
ret += `${normalizedKey}:${value};`; |
|
} |
|
} |
|
return ret; |
|
} |
|
function normalizeClass(value) { |
|
let res = ''; |
|
if (isString(value)) { |
|
res = value; |
|
} |
|
else if (isArray(value)) { |
|
for (let i = 0; i < value.length; i++) { |
|
const normalized = normalizeClass(value[i]); |
|
if (normalized) { |
|
res += normalized + ' '; |
|
} |
|
} |
|
} |
|
else if (isObject(value)) { |
|
for (const name in value) { |
|
if (value[name]) { |
|
res += name + ' '; |
|
} |
|
} |
|
} |
|
return res.trim(); |
|
} |
|
function normalizeProps(props) { |
|
if (!props) |
|
return null; |
|
let { class: klass, style } = props; |
|
if (klass && !isString(klass)) { |
|
props.class = normalizeClass(klass); |
|
} |
|
if (style) { |
|
props.style = normalizeStyle(style); |
|
} |
|
return props; |
|
} |
|
|
|
// These tag configs are shared between compiler-dom and runtime-dom, so they |
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element |
|
const HTML_TAGS = 'html,body,base,head,link,meta,style,title,address,article,aside,footer,' + |
|
'header,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,' + |
|
'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' + |
|
'data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,' + |
|
'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' + |
|
'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' + |
|
'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' + |
|
'option,output,progress,select,textarea,details,dialog,menu,' + |
|
'summary,template,blockquote,iframe,tfoot'; |
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element |
|
const SVG_TAGS = 'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' + |
|
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' + |
|
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' + |
|
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' + |
|
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' + |
|
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' + |
|
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' + |
|
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' + |
|
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' + |
|
'text,textPath,title,tspan,unknown,use,view'; |
|
const VOID_TAGS = 'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr'; |
|
/** |
|
* Compiler only. |
|
* Do NOT use in runtime code paths unless behind `(process.env.NODE_ENV !== 'production')` flag. |
|
*/ |
|
const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS); |
|
/** |
|
* Compiler only. |
|
* Do NOT use in runtime code paths unless behind `(process.env.NODE_ENV !== 'production')` flag. |
|
*/ |
|
const isSVGTag = /*#__PURE__*/ makeMap(SVG_TAGS); |
|
/** |
|
* Compiler only. |
|
* Do NOT use in runtime code paths unless behind `(process.env.NODE_ENV !== 'production')` flag. |
|
*/ |
|
const isVoidTag = /*#__PURE__*/ makeMap(VOID_TAGS); |
|
|
|
const escapeRE = /["'&<>]/; |
|
function escapeHtml(string) { |
|
const str = '' + string; |
|
const match = escapeRE.exec(str); |
|
if (!match) { |
|
return str; |
|
} |
|
let html = ''; |
|
let escaped; |
|
let index; |
|
let lastIndex = 0; |
|
for (index = match.index; index < str.length; index++) { |
|
switch (str.charCodeAt(index)) { |
|
case 34: // " |
|
escaped = '"'; |
|
break; |
|
case 38: // & |
|
escaped = '&'; |
|
break; |
|
case 39: // ' |
|
escaped = '''; |
|
break; |
|
case 60: // < |
|
escaped = '<'; |
|
break; |
|
case 62: // > |
|
escaped = '>'; |
|
break; |
|
default: |
|
continue; |
|
} |
|
if (lastIndex !== index) { |
|
html += str.slice(lastIndex, index); |
|
} |
|
lastIndex = index + 1; |
|
html += escaped; |
|
} |
|
return lastIndex !== index ? html + str.slice(lastIndex, index) : html; |
|
} |
|
// https://www.w3.org/TR/html52/syntax.html#comments |
|
const commentStripRE = /^-?>|<!--|-->|--!>|<!-$/g; |
|
function escapeHtmlComment(src) { |
|
return src.replace(commentStripRE, ''); |
|
} |
|
|
|
function looseCompareArrays(a, b) { |
|
if (a.length !== b.length) |
|
return false; |
|
let equal = true; |
|
for (let i = 0; equal && i < a.length; i++) { |
|
equal = looseEqual(a[i], b[i]); |
|
} |
|
return equal; |
|
} |
|
function looseEqual(a, b) { |
|
if (a === b) |
|
return true; |
|
let aValidType = isDate(a); |
|
let bValidType = isDate(b); |
|
if (aValidType || bValidType) { |
|
return aValidType && bValidType ? a.getTime() === b.getTime() : false; |
|
} |
|
aValidType = isSymbol(a); |
|
bValidType = isSymbol(b); |
|
if (aValidType || bValidType) { |
|
return a === b; |
|
} |
|
aValidType = isArray(a); |
|
bValidType = isArray(b); |
|
if (aValidType || bValidType) { |
|
return aValidType && bValidType ? looseCompareArrays(a, b) : false; |
|
} |
|
aValidType = isObject(a); |
|
bValidType = isObject(b); |
|
if (aValidType || bValidType) { |
|
/* istanbul ignore if: this if will probably never be called */ |
|
if (!aValidType || !bValidType) { |
|
return false; |
|
} |
|
const aKeysCount = Object.keys(a).length; |
|
const bKeysCount = Object.keys(b).length; |
|
if (aKeysCount !== bKeysCount) { |
|
return false; |
|
} |
|
for (const key in a) { |
|
const aHasKey = a.hasOwnProperty(key); |
|
const bHasKey = b.hasOwnProperty(key); |
|
if ((aHasKey && !bHasKey) || |
|
(!aHasKey && bHasKey) || |
|
!looseEqual(a[key], b[key])) { |
|
return false; |
|
} |
|
} |
|
} |
|
return String(a) === String(b); |
|
} |
|
function looseIndexOf(arr, val) { |
|
return arr.findIndex(item => looseEqual(item, val)); |
|
} |
|
|
|
/** |
|
* For converting {{ interpolation }} values to displayed strings. |
|
* @private |
|
*/ |
|
const toDisplayString = (val) => { |
|
return isString(val) |
|
? val |
|
: val == null |
|
? '' |
|
: isArray(val) || |
|
(isObject(val) && |
|
(val.toString === objectToString || !isFunction(val.toString))) |
|
? JSON.stringify(val, replacer, 2) |
|
: String(val); |
|
}; |
|
const replacer = (_key, val) => { |
|
// can't use isRef here since @vue/shared has no deps |
|
if (val && val.__v_isRef) { |
|
return replacer(_key, val.value); |
|
} |
|
else if (isMap(val)) { |
|
return { |
|
[`Map(${val.size})`]: [...val.entries()].reduce((entries, [key, val]) => { |
|
entries[`${key} =>`] = val; |
|
return entries; |
|
}, {}) |
|
}; |
|
} |
|
else if (isSet(val)) { |
|
return { |
|
[`Set(${val.size})`]: [...val.values()] |
|
}; |
|
} |
|
else if (isObject(val) && !isArray(val) && !isPlainObject(val)) { |
|
return String(val); |
|
} |
|
return val; |
|
}; |
|
|
|
const EMPTY_OBJ = (process.env.NODE_ENV !== 'production') |
|
? Object.freeze({}) |
|
: {}; |
|
const EMPTY_ARR = (process.env.NODE_ENV !== 'production') ? Object.freeze([]) : []; |
|
const NOOP = () => { }; |
|
/** |
|
* Always return false. |
|
*/ |
|
const NO = () => false; |
|
const onRE = /^on[^a-z]/; |
|
const isOn = (key) => onRE.test(key); |
|
const isModelListener = (key) => key.startsWith('onUpdate:'); |
|
const extend = Object.assign; |
|
const remove = (arr, el) => { |
|
const i = arr.indexOf(el); |
|
if (i > -1) { |
|
arr.splice(i, 1); |
|
} |
|
}; |
|
const hasOwnProperty = Object.prototype.hasOwnProperty; |
|
const hasOwn = (val, key) => hasOwnProperty.call(val, key); |
|
const isArray = Array.isArray; |
|
const isMap = (val) => toTypeString(val) === '[object Map]'; |
|
const isSet = (val) => toTypeString(val) === '[object Set]'; |
|
const isDate = (val) => toTypeString(val) === '[object Date]'; |
|
const isFunction = (val) => typeof val === 'function'; |
|
const isString = (val) => typeof val === 'string'; |
|
const isSymbol = (val) => typeof val === 'symbol'; |
|
const isObject = (val) => val !== null && typeof val === 'object'; |
|
const isPromise = (val) => { |
|
return isObject(val) && isFunction(val.then) && isFunction(val.catch); |
|
}; |
|
const objectToString = Object.prototype.toString; |
|
const toTypeString = (value) => objectToString.call(value); |
|
const toRawType = (value) => { |
|
// extract "RawType" from strings like "[object RawType]" |
|
return toTypeString(value).slice(8, -1); |
|
}; |
|
const isPlainObject = (val) => toTypeString(val) === '[object Object]'; |
|
const isIntegerKey = (key) => isString(key) && |
|
key !== 'NaN' && |
|
key[0] !== '-' && |
|
'' + parseInt(key, 10) === key; |
|
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'); |
|
const isBuiltInDirective = /*#__PURE__*/ makeMap('bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo'); |
|
const cacheStringFunction = (fn) => { |
|
const cache = Object.create(null); |
|
return ((str) => { |
|
const hit = cache[str]; |
|
return hit || (cache[str] = fn(str)); |
|
}); |
|
}; |
|
const camelizeRE = /-(\w)/g; |
|
/** |
|
* @private |
|
*/ |
|
const camelize = cacheStringFunction((str) => { |
|
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : '')); |
|
}); |
|
const hyphenateRE = /\B([A-Z])/g; |
|
/** |
|
* @private |
|
*/ |
|
const hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, '-$1').toLowerCase()); |
|
/** |
|
* @private |
|
*/ |
|
const capitalize = cacheStringFunction((str) => str.charAt(0).toUpperCase() + str.slice(1)); |
|
/** |
|
* @private |
|
*/ |
|
const toHandlerKey = cacheStringFunction((str) => str ? `on${capitalize(str)}` : ``); |
|
// compare whether a value has changed, accounting for NaN. |
|
const hasChanged = (value, oldValue) => !Object.is(value, oldValue); |
|
const invokeArrayFns = (fns, arg) => { |
|
for (let i = 0; i < fns.length; i++) { |
|
fns[i](arg); |
|
} |
|
}; |
|
const def = (obj, key, value) => { |
|
Object.defineProperty(obj, key, { |
|
configurable: true, |
|
enumerable: false, |
|
value |
|
}); |
|
}; |
|
const toNumber = (val) => { |
|
const n = parseFloat(val); |
|
return isNaN(n) ? val : n; |
|
}; |
|
let _globalThis; |
|
const getGlobalThis = () => { |
|
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]*$/; |
|
function genPropsAccessExp(name) { |
|
return identRE.test(name) |
|
? `__props.${name}` |
|
: `__props[${JSON.stringify(name)}]`; |
|
} |
|
|
|
export { EMPTY_ARR, EMPTY_OBJ, NO, NOOP, PatchFlagNames, camelize, capitalize, def, escapeHtml, escapeHtmlComment, extend, genPropsAccessExp, generateCodeFrame, getGlobalThis, hasChanged, hasOwn, hyphenate, includeBooleanAttr, invokeArrayFns, isArray, isBooleanAttr, isBuiltInDirective, isDate, isFunction, isGloballyWhitelisted, isHTMLTag, isIntegerKey, isKnownHtmlAttr, isKnownSvgAttr, isMap, isModelListener, isNoUnitNumericStyleProp, isObject, isOn, isPlainObject, isPromise, isReservedProp, isSSRSafeAttrName, isSVGTag, isSet, isSpecialBooleanAttr, isString, isSymbol, isVoidTag, looseEqual, looseIndexOf, makeMap, normalizeClass, normalizeProps, normalizeStyle, objectToString, parseStringStyle, propsToAttrMap, remove, slotFlagsText, stringifyStyle, toDisplayString, toHandlerKey, toNumber, toRawType, toTypeString };
|
|
|