/** * 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`); 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 isKnownAttr = /*#__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`); function normalizeStyle(value) { if (isArray(value)) { const res = {}; for (let i = 0; i < value.length; i++) { const item = value[i]; const normalized = normalizeStyle(isString(item) ? parseStringStyle(item) : item); if (normalized) { for (const key in normalized) { res[key] = normalized[key]; } } } return res; } 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) { 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(); } // 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,hgroup,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,rtc,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'; const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS); const isSVGTag = /*#__PURE__*/ makeMap(SVG_TAGS); 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.substring(lastIndex, index); } lastIndex = index + 1; html += escaped; } return lastIndex !== index ? html + str.substring(lastIndex, index) : html; } // https://www.w3.org/TR/html52/syntax.html#comments const commentStripRE = /^-?>||--!>| looseEqual(item, val)); } /** * For converting {{ interpolation }} values to displayed strings. * @private */ const toDisplayString = (val) => { return val == null ? '' : isObject(val) ? JSON.stringify(val, replacer, 2) : String(val); }; const replacer = (_key, val) => { 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; }; /** * List of @babel/parser plugins that are used for template expression * transforms and SFC script transforms. By default we enable proposals slated * for ES2020. This will need to be updated as the spec moves forward. * Full list at https://babeljs.io/docs/en/next/babel-parser#plugins */ const babelParserDefaultPlugins = [ 'bigInt', 'optionalChaining', 'nullishCoalescingOperator' ]; 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) => val instanceof 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,' + 'onVnodeBeforeMount,onVnodeMounted,' + 'onVnodeBeforeUpdate,onVnodeUpdated,' + 'onVnodeBeforeUnmount,onVnodeUnmounted'); 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) => value !== oldValue && (value === value || oldValue === 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 : {})); }; export { EMPTY_ARR, EMPTY_OBJ, NO, NOOP, PatchFlagNames, babelParserDefaultPlugins, camelize, capitalize, def, escapeHtml, escapeHtmlComment, extend, generateCodeFrame, getGlobalThis, hasChanged, hasOwn, hyphenate, invokeArrayFns, isArray, isBooleanAttr, isDate, isFunction, isGloballyWhitelisted, isHTMLTag, isIntegerKey, isKnownAttr, isMap, isModelListener, isNoUnitNumericStyleProp, isObject, isOn, isPlainObject, isPromise, isReservedProp, isSSRSafeAttrName, isSVGTag, isSet, isSpecialBooleanAttr, isString, isSymbol, isVoidTag, looseEqual, looseIndexOf, makeMap, normalizeClass, normalizeStyle, objectToString, parseStringStyle, propsToAttrMap, remove, slotFlagsText, stringifyStyle, toDisplayString, toHandlerKey, toNumber, toRawType, toTypeString };