diff --git a/Dockerfile.embedded b/Dockerfile.embedded index 378b2f9..4a3e612 100644 --- a/Dockerfile.embedded +++ b/Dockerfile.embedded @@ -6,6 +6,7 @@ COPY webui webui ### Build Vue.js into plain HTML/CSS/JS WORKDIR /app/webui +RUN npm i RUN npm run build-embed FROM golang:1.19.1 AS builder @@ -30,4 +31,4 @@ WORKDIR /app/ COPY --from=builder /app/webapi ./ ### Executable command -CMD ["/app/webapi", "--db-filename", "/data/wasaphoto.db", "--data-path", "/data/data"] \ No newline at end of file +CMD ["/app/webapi", "--db-filename", "/data/wasaphoto.db", "--data-path", "/data/data"] diff --git a/webui/node_modules/vite/dist/node/chunks/dep-94c1417a.js b/webui/node_modules/vite/dist/node/chunks/dep-94c1417a.js index 94eabfb..f04be91 100644 --- a/webui/node_modules/vite/dist/node/chunks/dep-94c1417a.js +++ b/webui/node_modules/vite/dist/node/chunks/dep-94c1417a.js @@ -159,83 +159,83 @@ var pify$1 = pify$2.exports = function (obj, P, opts) { pify$1.all = pify$1; -var fs = require$$0__default; -var path$2 = require$$0; -var pify = pify$2.exports; - -var stat = pify(fs.stat); -var readFile = pify(fs.readFile); -var resolve = path$2.resolve; - -var cache = Object.create(null); - -function convert(content, encoding) { - if (Buffer.isEncoding(encoding)) { - return content.toString(encoding); - } - return content; -} - -readCache$1.exports = function (path, encoding) { - path = resolve(path); - - return stat(path).then(function (stats) { - var item = cache[path]; - - if (item && item.mtime.getTime() === stats.mtime.getTime()) { - return convert(item.content, encoding); - } - - return readFile(path).then(function (data) { - cache[path] = { - mtime: stats.mtime, - content: data - }; - - return convert(data, encoding); - }); - }).catch(function (err) { - cache[path] = null; - return Promise.reject(err); - }); -}; - -readCache$1.exports.sync = function (path, encoding) { - path = resolve(path); - - try { - var stats = fs.statSync(path); - var item = cache[path]; - - if (item && item.mtime.getTime() === stats.mtime.getTime()) { - return convert(item.content, encoding); - } - - var data = fs.readFileSync(path); - - cache[path] = { - mtime: stats.mtime, - content: data - }; - - return convert(data, encoding); - } catch (err) { - cache[path] = null; - throw err; - } - -}; - -readCache$1.exports.get = function (path, encoding) { - path = resolve(path); - if (cache[path]) { - return convert(cache[path].content, encoding); - } - return null; -}; - -readCache$1.exports.clear = function () { - cache = Object.create(null); +var fs = require$$0__default; +var path$2 = require$$0; +var pify = pify$2.exports; + +var stat = pify(fs.stat); +var readFile = pify(fs.readFile); +var resolve = path$2.resolve; + +var cache = Object.create(null); + +function convert(content, encoding) { + if (Buffer.isEncoding(encoding)) { + return content.toString(encoding); + } + return content; +} + +readCache$1.exports = function (path, encoding) { + path = resolve(path); + + return stat(path).then(function (stats) { + var item = cache[path]; + + if (item && item.mtime.getTime() === stats.mtime.getTime()) { + return convert(item.content, encoding); + } + + return readFile(path).then(function (data) { + cache[path] = { + mtime: stats.mtime, + content: data + }; + + return convert(data, encoding); + }); + }).catch(function (err) { + cache[path] = null; + return Promise.reject(err); + }); +}; + +readCache$1.exports.sync = function (path, encoding) { + path = resolve(path); + + try { + var stats = fs.statSync(path); + var item = cache[path]; + + if (item && item.mtime.getTime() === stats.mtime.getTime()) { + return convert(item.content, encoding); + } + + var data = fs.readFileSync(path); + + cache[path] = { + mtime: stats.mtime, + content: data + }; + + return convert(data, encoding); + } catch (err) { + cache[path] = null; + throw err; + } + +}; + +readCache$1.exports.get = function (path, encoding) { + path = resolve(path); + if (cache[path]) { + return convert(cache[path].content, encoding); + } + return null; +}; + +readCache$1.exports.clear = function () { + cache = Object.create(null); }; const readCache = readCache$1.exports; diff --git a/webui/node_modules/vite/dist/node/chunks/dep-9d3f225a.js b/webui/node_modules/vite/dist/node/chunks/dep-9d3f225a.js index 9b3ae72..415fb80 100644 --- a/webui/node_modules/vite/dist/node/chunks/dep-9d3f225a.js +++ b/webui/node_modules/vite/dist/node/chunks/dep-9d3f225a.js @@ -22,599 +22,599 @@ function _mergeNamespaces(n, m) { var compilerDom_cjs$2 = {}; -/** - * 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]; +/** + * 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 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' +/** + * 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 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'); +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,` + +/** + * 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; +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. - */ +// 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, ''); +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)); +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; +/** + * 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$1 = (fn) => { - const cache = Object.create(null); - return ((str) => { - const hit = cache[str]; - return hit || (cache[str] = fn(str)); - }); -}; -const camelizeRE$1 = /-(\w)/g; -/** - * @private - */ -const camelize$1 = cacheStringFunction$1((str) => { - return str.replace(camelizeRE$1, (_, c) => (c ? c.toUpperCase() : '')); -}); -const hyphenateRE = /\B([A-Z])/g; -/** - * @private - */ -const hyphenate = cacheStringFunction$1((str) => str.replace(hyphenateRE, '-$1').toLowerCase()); -/** - * @private - */ -const capitalize = cacheStringFunction$1((str) => str.charAt(0).toUpperCase() + str.slice(1)); -/** - * @private - */ -const toHandlerKey = cacheStringFunction$1((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)}]`; +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$1 = (fn) => { + const cache = Object.create(null); + return ((str) => { + const hit = cache[str]; + return hit || (cache[str] = fn(str)); + }); +}; +const camelizeRE$1 = /-(\w)/g; +/** + * @private + */ +const camelize$1 = cacheStringFunction$1((str) => { + return str.replace(camelizeRE$1, (_, c) => (c ? c.toUpperCase() : '')); +}); +const hyphenateRE = /\B([A-Z])/g; +/** + * @private + */ +const hyphenate = cacheStringFunction$1((str) => str.replace(hyphenateRE, '-$1').toLowerCase()); +/** + * @private + */ +const capitalize = cacheStringFunction$1((str) => str.charAt(0).toUpperCase() + str.slice(1)); +/** + * @private + */ +const toHandlerKey = cacheStringFunction$1((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)}]`; } var shared_esmBundler = { @@ -682,4855 +682,4855 @@ var shared_esmBundler = { toTypeString: toTypeString }; -function defaultOnError(error) { - throw error; -} -function defaultOnWarn(msg) { - (process.env.NODE_ENV !== 'production') && console.warn(`[Vue warn] ${msg.message}`); -} -function createCompilerError(code, loc, messages, additionalMessage) { - const msg = (process.env.NODE_ENV !== 'production') || !true - ? (messages || errorMessages)[code] + (additionalMessage || ``) - : code; - const error = new SyntaxError(String(msg)); - error.code = code; - error.loc = loc; - return error; -} -const errorMessages = { - // parse errors - [0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */]: 'Illegal comment.', - [1 /* CDATA_IN_HTML_CONTENT */]: 'CDATA section is allowed only in XML context.', - [2 /* DUPLICATE_ATTRIBUTE */]: 'Duplicate attribute.', - [3 /* END_TAG_WITH_ATTRIBUTES */]: 'End tag cannot have attributes.', - [4 /* END_TAG_WITH_TRAILING_SOLIDUS */]: "Illegal '/' in tags.", - [5 /* EOF_BEFORE_TAG_NAME */]: 'Unexpected EOF in tag.', - [6 /* EOF_IN_CDATA */]: 'Unexpected EOF in CDATA section.', - [7 /* EOF_IN_COMMENT */]: 'Unexpected EOF in comment.', - [8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */]: 'Unexpected EOF in script.', - [9 /* EOF_IN_TAG */]: 'Unexpected EOF in tag.', - [10 /* INCORRECTLY_CLOSED_COMMENT */]: 'Incorrectly closed comment.', - [11 /* INCORRECTLY_OPENED_COMMENT */]: 'Incorrectly opened comment.', - [12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */]: "Illegal tag name. Use '<' to print '<'.", - [13 /* MISSING_ATTRIBUTE_VALUE */]: 'Attribute value was expected.', - [14 /* MISSING_END_TAG_NAME */]: 'End tag name was expected.', - [15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */]: 'Whitespace was expected.', - [16 /* NESTED_COMMENT */]: "Unexpected '<!--' in comment.", - [17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */]: 'Attribute name cannot contain U+0022 ("), U+0027 (\'), and U+003C (<).', - [18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */]: 'Unquoted attribute value cannot contain U+0022 ("), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).', - [19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */]: "Attribute name cannot start with '='.", - [21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */]: "'<?' is allowed only in XML context.", - [20 /* UNEXPECTED_NULL_CHARACTER */]: `Unexpected null character.`, - [22 /* UNEXPECTED_SOLIDUS_IN_TAG */]: "Illegal '/' in tags.", - // Vue-specific parse errors - [23 /* X_INVALID_END_TAG */]: 'Invalid end tag.', - [24 /* X_MISSING_END_TAG */]: 'Element is missing end tag.', - [25 /* X_MISSING_INTERPOLATION_END */]: 'Interpolation end sign was not found.', - [27 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */]: 'End bracket for dynamic directive argument was not found. ' + - 'Note that dynamic directive argument cannot contain spaces.', - [26 /* X_MISSING_DIRECTIVE_NAME */]: 'Legal directive name was expected.', - // transform errors - [28 /* X_V_IF_NO_EXPRESSION */]: `v-if/v-else-if is missing expression.`, - [29 /* X_V_IF_SAME_KEY */]: `v-if/else branches must use unique keys.`, - [30 /* X_V_ELSE_NO_ADJACENT_IF */]: `v-else/v-else-if has no adjacent v-if or v-else-if.`, - [31 /* X_V_FOR_NO_EXPRESSION */]: `v-for is missing expression.`, - [32 /* X_V_FOR_MALFORMED_EXPRESSION */]: `v-for has invalid expression.`, - [33 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */]: `<template v-for> key should be placed on the <template> tag.`, - [34 /* X_V_BIND_NO_EXPRESSION */]: `v-bind is missing expression.`, - [35 /* X_V_ON_NO_EXPRESSION */]: `v-on is missing expression.`, - [36 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */]: `Unexpected custom directive on <slot> outlet.`, - [37 /* X_V_SLOT_MIXED_SLOT_USAGE */]: `Mixed v-slot usage on both the component and nested <template>.` + - `When there are multiple named slots, all slots should use <template> ` + - `syntax to avoid scope ambiguity.`, - [38 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */]: `Duplicate slot names found. `, - [39 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */]: `Extraneous children found when component already has explicitly named ` + - `default slot. These children will be ignored.`, - [40 /* X_V_SLOT_MISPLACED */]: `v-slot can only be used on components or <template> tags.`, - [41 /* X_V_MODEL_NO_EXPRESSION */]: `v-model is missing expression.`, - [42 /* X_V_MODEL_MALFORMED_EXPRESSION */]: `v-model value must be a valid JavaScript member expression.`, - [43 /* X_V_MODEL_ON_SCOPE_VARIABLE */]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`, - [44 /* X_INVALID_EXPRESSION */]: `Error parsing JavaScript expression: `, - [45 /* X_KEEP_ALIVE_INVALID_CHILDREN */]: `<KeepAlive> expects exactly one child component.`, - // generic errors - [46 /* X_PREFIX_ID_NOT_SUPPORTED */]: `"prefixIdentifiers" option is not supported in this build of compiler.`, - [47 /* X_MODULE_MODE_NOT_SUPPORTED */]: `ES module mode is not supported in this build of compiler.`, - [48 /* X_CACHE_HANDLER_NOT_SUPPORTED */]: `"cacheHandlers" option is only supported when the "prefixIdentifiers" option is enabled.`, - [49 /* X_SCOPE_ID_NOT_SUPPORTED */]: `"scopeId" option is only supported in module mode.`, - // just to fulfill types - [50 /* __EXTEND_POINT__ */]: `` +function defaultOnError(error) { + throw error; +} +function defaultOnWarn(msg) { + (process.env.NODE_ENV !== 'production') && console.warn(`[Vue warn] ${msg.message}`); +} +function createCompilerError(code, loc, messages, additionalMessage) { + const msg = (process.env.NODE_ENV !== 'production') || !true + ? (messages || errorMessages)[code] + (additionalMessage || ``) + : code; + const error = new SyntaxError(String(msg)); + error.code = code; + error.loc = loc; + return error; +} +const errorMessages = { + // parse errors + [0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */]: 'Illegal comment.', + [1 /* CDATA_IN_HTML_CONTENT */]: 'CDATA section is allowed only in XML context.', + [2 /* DUPLICATE_ATTRIBUTE */]: 'Duplicate attribute.', + [3 /* END_TAG_WITH_ATTRIBUTES */]: 'End tag cannot have attributes.', + [4 /* END_TAG_WITH_TRAILING_SOLIDUS */]: "Illegal '/' in tags.", + [5 /* EOF_BEFORE_TAG_NAME */]: 'Unexpected EOF in tag.', + [6 /* EOF_IN_CDATA */]: 'Unexpected EOF in CDATA section.', + [7 /* EOF_IN_COMMENT */]: 'Unexpected EOF in comment.', + [8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */]: 'Unexpected EOF in script.', + [9 /* EOF_IN_TAG */]: 'Unexpected EOF in tag.', + [10 /* INCORRECTLY_CLOSED_COMMENT */]: 'Incorrectly closed comment.', + [11 /* INCORRECTLY_OPENED_COMMENT */]: 'Incorrectly opened comment.', + [12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */]: "Illegal tag name. Use '<' to print '<'.", + [13 /* MISSING_ATTRIBUTE_VALUE */]: 'Attribute value was expected.', + [14 /* MISSING_END_TAG_NAME */]: 'End tag name was expected.', + [15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */]: 'Whitespace was expected.', + [16 /* NESTED_COMMENT */]: "Unexpected '<!--' in comment.", + [17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */]: 'Attribute name cannot contain U+0022 ("), U+0027 (\'), and U+003C (<).', + [18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */]: 'Unquoted attribute value cannot contain U+0022 ("), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).', + [19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */]: "Attribute name cannot start with '='.", + [21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */]: "'<?' is allowed only in XML context.", + [20 /* UNEXPECTED_NULL_CHARACTER */]: `Unexpected null character.`, + [22 /* UNEXPECTED_SOLIDUS_IN_TAG */]: "Illegal '/' in tags.", + // Vue-specific parse errors + [23 /* X_INVALID_END_TAG */]: 'Invalid end tag.', + [24 /* X_MISSING_END_TAG */]: 'Element is missing end tag.', + [25 /* X_MISSING_INTERPOLATION_END */]: 'Interpolation end sign was not found.', + [27 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */]: 'End bracket for dynamic directive argument was not found. ' + + 'Note that dynamic directive argument cannot contain spaces.', + [26 /* X_MISSING_DIRECTIVE_NAME */]: 'Legal directive name was expected.', + // transform errors + [28 /* X_V_IF_NO_EXPRESSION */]: `v-if/v-else-if is missing expression.`, + [29 /* X_V_IF_SAME_KEY */]: `v-if/else branches must use unique keys.`, + [30 /* X_V_ELSE_NO_ADJACENT_IF */]: `v-else/v-else-if has no adjacent v-if or v-else-if.`, + [31 /* X_V_FOR_NO_EXPRESSION */]: `v-for is missing expression.`, + [32 /* X_V_FOR_MALFORMED_EXPRESSION */]: `v-for has invalid expression.`, + [33 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */]: `<template v-for> key should be placed on the <template> tag.`, + [34 /* X_V_BIND_NO_EXPRESSION */]: `v-bind is missing expression.`, + [35 /* X_V_ON_NO_EXPRESSION */]: `v-on is missing expression.`, + [36 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */]: `Unexpected custom directive on <slot> outlet.`, + [37 /* X_V_SLOT_MIXED_SLOT_USAGE */]: `Mixed v-slot usage on both the component and nested <template>.` + + `When there are multiple named slots, all slots should use <template> ` + + `syntax to avoid scope ambiguity.`, + [38 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */]: `Duplicate slot names found. `, + [39 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */]: `Extraneous children found when component already has explicitly named ` + + `default slot. These children will be ignored.`, + [40 /* X_V_SLOT_MISPLACED */]: `v-slot can only be used on components or <template> tags.`, + [41 /* X_V_MODEL_NO_EXPRESSION */]: `v-model is missing expression.`, + [42 /* X_V_MODEL_MALFORMED_EXPRESSION */]: `v-model value must be a valid JavaScript member expression.`, + [43 /* X_V_MODEL_ON_SCOPE_VARIABLE */]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`, + [44 /* X_INVALID_EXPRESSION */]: `Error parsing JavaScript expression: `, + [45 /* X_KEEP_ALIVE_INVALID_CHILDREN */]: `<KeepAlive> expects exactly one child component.`, + // generic errors + [46 /* X_PREFIX_ID_NOT_SUPPORTED */]: `"prefixIdentifiers" option is not supported in this build of compiler.`, + [47 /* X_MODULE_MODE_NOT_SUPPORTED */]: `ES module mode is not supported in this build of compiler.`, + [48 /* X_CACHE_HANDLER_NOT_SUPPORTED */]: `"cacheHandlers" option is only supported when the "prefixIdentifiers" option is enabled.`, + [49 /* X_SCOPE_ID_NOT_SUPPORTED */]: `"scopeId" option is only supported in module mode.`, + // just to fulfill types + [50 /* __EXTEND_POINT__ */]: `` }; -const FRAGMENT = Symbol((process.env.NODE_ENV !== 'production') ? `Fragment` : ``); -const TELEPORT = Symbol((process.env.NODE_ENV !== 'production') ? `Teleport` : ``); -const SUSPENSE = Symbol((process.env.NODE_ENV !== 'production') ? `Suspense` : ``); -const KEEP_ALIVE = Symbol((process.env.NODE_ENV !== 'production') ? `KeepAlive` : ``); -const BASE_TRANSITION = Symbol((process.env.NODE_ENV !== 'production') ? `BaseTransition` : ``); -const OPEN_BLOCK = Symbol((process.env.NODE_ENV !== 'production') ? `openBlock` : ``); -const CREATE_BLOCK = Symbol((process.env.NODE_ENV !== 'production') ? `createBlock` : ``); -const CREATE_ELEMENT_BLOCK = Symbol((process.env.NODE_ENV !== 'production') ? `createElementBlock` : ``); -const CREATE_VNODE = Symbol((process.env.NODE_ENV !== 'production') ? `createVNode` : ``); -const CREATE_ELEMENT_VNODE = Symbol((process.env.NODE_ENV !== 'production') ? `createElementVNode` : ``); -const CREATE_COMMENT = Symbol((process.env.NODE_ENV !== 'production') ? `createCommentVNode` : ``); -const CREATE_TEXT = Symbol((process.env.NODE_ENV !== 'production') ? `createTextVNode` : ``); -const CREATE_STATIC = Symbol((process.env.NODE_ENV !== 'production') ? `createStaticVNode` : ``); -const RESOLVE_COMPONENT = Symbol((process.env.NODE_ENV !== 'production') ? `resolveComponent` : ``); -const RESOLVE_DYNAMIC_COMPONENT = Symbol((process.env.NODE_ENV !== 'production') ? `resolveDynamicComponent` : ``); -const RESOLVE_DIRECTIVE = Symbol((process.env.NODE_ENV !== 'production') ? `resolveDirective` : ``); -const RESOLVE_FILTER = Symbol((process.env.NODE_ENV !== 'production') ? `resolveFilter` : ``); -const WITH_DIRECTIVES = Symbol((process.env.NODE_ENV !== 'production') ? `withDirectives` : ``); -const RENDER_LIST = Symbol((process.env.NODE_ENV !== 'production') ? `renderList` : ``); -const RENDER_SLOT = Symbol((process.env.NODE_ENV !== 'production') ? `renderSlot` : ``); -const CREATE_SLOTS = Symbol((process.env.NODE_ENV !== 'production') ? `createSlots` : ``); -const TO_DISPLAY_STRING = Symbol((process.env.NODE_ENV !== 'production') ? `toDisplayString` : ``); -const MERGE_PROPS = Symbol((process.env.NODE_ENV !== 'production') ? `mergeProps` : ``); -const NORMALIZE_CLASS = Symbol((process.env.NODE_ENV !== 'production') ? `normalizeClass` : ``); -const NORMALIZE_STYLE = Symbol((process.env.NODE_ENV !== 'production') ? `normalizeStyle` : ``); -const NORMALIZE_PROPS = Symbol((process.env.NODE_ENV !== 'production') ? `normalizeProps` : ``); -const GUARD_REACTIVE_PROPS = Symbol((process.env.NODE_ENV !== 'production') ? `guardReactiveProps` : ``); -const TO_HANDLERS = Symbol((process.env.NODE_ENV !== 'production') ? `toHandlers` : ``); -const CAMELIZE = Symbol((process.env.NODE_ENV !== 'production') ? `camelize` : ``); -const CAPITALIZE = Symbol((process.env.NODE_ENV !== 'production') ? `capitalize` : ``); -const TO_HANDLER_KEY = Symbol((process.env.NODE_ENV !== 'production') ? `toHandlerKey` : ``); -const SET_BLOCK_TRACKING = Symbol((process.env.NODE_ENV !== 'production') ? `setBlockTracking` : ``); -const PUSH_SCOPE_ID = Symbol((process.env.NODE_ENV !== 'production') ? `pushScopeId` : ``); -const POP_SCOPE_ID = Symbol((process.env.NODE_ENV !== 'production') ? `popScopeId` : ``); -const WITH_CTX = Symbol((process.env.NODE_ENV !== 'production') ? `withCtx` : ``); -const UNREF = Symbol((process.env.NODE_ENV !== 'production') ? `unref` : ``); -const IS_REF = Symbol((process.env.NODE_ENV !== 'production') ? `isRef` : ``); -const WITH_MEMO = Symbol((process.env.NODE_ENV !== 'production') ? `withMemo` : ``); -const IS_MEMO_SAME = Symbol((process.env.NODE_ENV !== 'production') ? `isMemoSame` : ``); -// Name mapping for runtime helpers that need to be imported from 'vue' in -// generated code. Make sure these are correctly exported in the runtime! -// Using `any` here because TS doesn't allow symbols as index type. -const helperNameMap = { - [FRAGMENT]: `Fragment`, - [TELEPORT]: `Teleport`, - [SUSPENSE]: `Suspense`, - [KEEP_ALIVE]: `KeepAlive`, - [BASE_TRANSITION]: `BaseTransition`, - [OPEN_BLOCK]: `openBlock`, - [CREATE_BLOCK]: `createBlock`, - [CREATE_ELEMENT_BLOCK]: `createElementBlock`, - [CREATE_VNODE]: `createVNode`, - [CREATE_ELEMENT_VNODE]: `createElementVNode`, - [CREATE_COMMENT]: `createCommentVNode`, - [CREATE_TEXT]: `createTextVNode`, - [CREATE_STATIC]: `createStaticVNode`, - [RESOLVE_COMPONENT]: `resolveComponent`, - [RESOLVE_DYNAMIC_COMPONENT]: `resolveDynamicComponent`, - [RESOLVE_DIRECTIVE]: `resolveDirective`, - [RESOLVE_FILTER]: `resolveFilter`, - [WITH_DIRECTIVES]: `withDirectives`, - [RENDER_LIST]: `renderList`, - [RENDER_SLOT]: `renderSlot`, - [CREATE_SLOTS]: `createSlots`, - [TO_DISPLAY_STRING]: `toDisplayString`, - [MERGE_PROPS]: `mergeProps`, - [NORMALIZE_CLASS]: `normalizeClass`, - [NORMALIZE_STYLE]: `normalizeStyle`, - [NORMALIZE_PROPS]: `normalizeProps`, - [GUARD_REACTIVE_PROPS]: `guardReactiveProps`, - [TO_HANDLERS]: `toHandlers`, - [CAMELIZE]: `camelize`, - [CAPITALIZE]: `capitalize`, - [TO_HANDLER_KEY]: `toHandlerKey`, - [SET_BLOCK_TRACKING]: `setBlockTracking`, - [PUSH_SCOPE_ID]: `pushScopeId`, - [POP_SCOPE_ID]: `popScopeId`, - [WITH_CTX]: `withCtx`, - [UNREF]: `unref`, - [IS_REF]: `isRef`, - [WITH_MEMO]: `withMemo`, - [IS_MEMO_SAME]: `isMemoSame` -}; -function registerRuntimeHelpers(helpers) { - Object.getOwnPropertySymbols(helpers).forEach(s => { - helperNameMap[s] = helpers[s]; - }); +const FRAGMENT = Symbol((process.env.NODE_ENV !== 'production') ? `Fragment` : ``); +const TELEPORT = Symbol((process.env.NODE_ENV !== 'production') ? `Teleport` : ``); +const SUSPENSE = Symbol((process.env.NODE_ENV !== 'production') ? `Suspense` : ``); +const KEEP_ALIVE = Symbol((process.env.NODE_ENV !== 'production') ? `KeepAlive` : ``); +const BASE_TRANSITION = Symbol((process.env.NODE_ENV !== 'production') ? `BaseTransition` : ``); +const OPEN_BLOCK = Symbol((process.env.NODE_ENV !== 'production') ? `openBlock` : ``); +const CREATE_BLOCK = Symbol((process.env.NODE_ENV !== 'production') ? `createBlock` : ``); +const CREATE_ELEMENT_BLOCK = Symbol((process.env.NODE_ENV !== 'production') ? `createElementBlock` : ``); +const CREATE_VNODE = Symbol((process.env.NODE_ENV !== 'production') ? `createVNode` : ``); +const CREATE_ELEMENT_VNODE = Symbol((process.env.NODE_ENV !== 'production') ? `createElementVNode` : ``); +const CREATE_COMMENT = Symbol((process.env.NODE_ENV !== 'production') ? `createCommentVNode` : ``); +const CREATE_TEXT = Symbol((process.env.NODE_ENV !== 'production') ? `createTextVNode` : ``); +const CREATE_STATIC = Symbol((process.env.NODE_ENV !== 'production') ? `createStaticVNode` : ``); +const RESOLVE_COMPONENT = Symbol((process.env.NODE_ENV !== 'production') ? `resolveComponent` : ``); +const RESOLVE_DYNAMIC_COMPONENT = Symbol((process.env.NODE_ENV !== 'production') ? `resolveDynamicComponent` : ``); +const RESOLVE_DIRECTIVE = Symbol((process.env.NODE_ENV !== 'production') ? `resolveDirective` : ``); +const RESOLVE_FILTER = Symbol((process.env.NODE_ENV !== 'production') ? `resolveFilter` : ``); +const WITH_DIRECTIVES = Symbol((process.env.NODE_ENV !== 'production') ? `withDirectives` : ``); +const RENDER_LIST = Symbol((process.env.NODE_ENV !== 'production') ? `renderList` : ``); +const RENDER_SLOT = Symbol((process.env.NODE_ENV !== 'production') ? `renderSlot` : ``); +const CREATE_SLOTS = Symbol((process.env.NODE_ENV !== 'production') ? `createSlots` : ``); +const TO_DISPLAY_STRING = Symbol((process.env.NODE_ENV !== 'production') ? `toDisplayString` : ``); +const MERGE_PROPS = Symbol((process.env.NODE_ENV !== 'production') ? `mergeProps` : ``); +const NORMALIZE_CLASS = Symbol((process.env.NODE_ENV !== 'production') ? `normalizeClass` : ``); +const NORMALIZE_STYLE = Symbol((process.env.NODE_ENV !== 'production') ? `normalizeStyle` : ``); +const NORMALIZE_PROPS = Symbol((process.env.NODE_ENV !== 'production') ? `normalizeProps` : ``); +const GUARD_REACTIVE_PROPS = Symbol((process.env.NODE_ENV !== 'production') ? `guardReactiveProps` : ``); +const TO_HANDLERS = Symbol((process.env.NODE_ENV !== 'production') ? `toHandlers` : ``); +const CAMELIZE = Symbol((process.env.NODE_ENV !== 'production') ? `camelize` : ``); +const CAPITALIZE = Symbol((process.env.NODE_ENV !== 'production') ? `capitalize` : ``); +const TO_HANDLER_KEY = Symbol((process.env.NODE_ENV !== 'production') ? `toHandlerKey` : ``); +const SET_BLOCK_TRACKING = Symbol((process.env.NODE_ENV !== 'production') ? `setBlockTracking` : ``); +const PUSH_SCOPE_ID = Symbol((process.env.NODE_ENV !== 'production') ? `pushScopeId` : ``); +const POP_SCOPE_ID = Symbol((process.env.NODE_ENV !== 'production') ? `popScopeId` : ``); +const WITH_CTX = Symbol((process.env.NODE_ENV !== 'production') ? `withCtx` : ``); +const UNREF = Symbol((process.env.NODE_ENV !== 'production') ? `unref` : ``); +const IS_REF = Symbol((process.env.NODE_ENV !== 'production') ? `isRef` : ``); +const WITH_MEMO = Symbol((process.env.NODE_ENV !== 'production') ? `withMemo` : ``); +const IS_MEMO_SAME = Symbol((process.env.NODE_ENV !== 'production') ? `isMemoSame` : ``); +// Name mapping for runtime helpers that need to be imported from 'vue' in +// generated code. Make sure these are correctly exported in the runtime! +// Using `any` here because TS doesn't allow symbols as index type. +const helperNameMap = { + [FRAGMENT]: `Fragment`, + [TELEPORT]: `Teleport`, + [SUSPENSE]: `Suspense`, + [KEEP_ALIVE]: `KeepAlive`, + [BASE_TRANSITION]: `BaseTransition`, + [OPEN_BLOCK]: `openBlock`, + [CREATE_BLOCK]: `createBlock`, + [CREATE_ELEMENT_BLOCK]: `createElementBlock`, + [CREATE_VNODE]: `createVNode`, + [CREATE_ELEMENT_VNODE]: `createElementVNode`, + [CREATE_COMMENT]: `createCommentVNode`, + [CREATE_TEXT]: `createTextVNode`, + [CREATE_STATIC]: `createStaticVNode`, + [RESOLVE_COMPONENT]: `resolveComponent`, + [RESOLVE_DYNAMIC_COMPONENT]: `resolveDynamicComponent`, + [RESOLVE_DIRECTIVE]: `resolveDirective`, + [RESOLVE_FILTER]: `resolveFilter`, + [WITH_DIRECTIVES]: `withDirectives`, + [RENDER_LIST]: `renderList`, + [RENDER_SLOT]: `renderSlot`, + [CREATE_SLOTS]: `createSlots`, + [TO_DISPLAY_STRING]: `toDisplayString`, + [MERGE_PROPS]: `mergeProps`, + [NORMALIZE_CLASS]: `normalizeClass`, + [NORMALIZE_STYLE]: `normalizeStyle`, + [NORMALIZE_PROPS]: `normalizeProps`, + [GUARD_REACTIVE_PROPS]: `guardReactiveProps`, + [TO_HANDLERS]: `toHandlers`, + [CAMELIZE]: `camelize`, + [CAPITALIZE]: `capitalize`, + [TO_HANDLER_KEY]: `toHandlerKey`, + [SET_BLOCK_TRACKING]: `setBlockTracking`, + [PUSH_SCOPE_ID]: `pushScopeId`, + [POP_SCOPE_ID]: `popScopeId`, + [WITH_CTX]: `withCtx`, + [UNREF]: `unref`, + [IS_REF]: `isRef`, + [WITH_MEMO]: `withMemo`, + [IS_MEMO_SAME]: `isMemoSame` +}; +function registerRuntimeHelpers(helpers) { + Object.getOwnPropertySymbols(helpers).forEach(s => { + helperNameMap[s] = helpers[s]; + }); } -// AST Utilities --------------------------------------------------------------- -// Some expressions, e.g. sequence and conditional expressions, are never -// associated with template nodes, so their source locations are just a stub. -// Container types like CompoundExpression also don't need a real location. -const locStub = { - source: '', - start: { line: 1, column: 1, offset: 0 }, - end: { line: 1, column: 1, offset: 0 } -}; -function createRoot(children, loc = locStub) { - return { - type: 0 /* ROOT */, - children, - helpers: [], - components: [], - directives: [], - hoists: [], - imports: [], - cached: 0, - temps: 0, - codegenNode: undefined, - loc - }; -} -function createVNodeCall(context, tag, props, children, patchFlag, dynamicProps, directives, isBlock = false, disableTracking = false, isComponent = false, loc = locStub) { - if (context) { - if (isBlock) { - context.helper(OPEN_BLOCK); - context.helper(getVNodeBlockHelper(context.inSSR, isComponent)); - } - else { - context.helper(getVNodeHelper(context.inSSR, isComponent)); - } - if (directives) { - context.helper(WITH_DIRECTIVES); - } - } - return { - type: 13 /* VNODE_CALL */, - tag, - props, - children, - patchFlag, - dynamicProps, - directives, - isBlock, - disableTracking, - isComponent, - loc - }; -} -function createArrayExpression(elements, loc = locStub) { - return { - type: 17 /* JS_ARRAY_EXPRESSION */, - loc, - elements - }; -} -function createObjectExpression(properties, loc = locStub) { - return { - type: 15 /* JS_OBJECT_EXPRESSION */, - loc, - properties - }; -} -function createObjectProperty(key, value) { - return { - type: 16 /* JS_PROPERTY */, - loc: locStub, - key: isString(key) ? createSimpleExpression(key, true) : key, - value - }; -} -function createSimpleExpression(content, isStatic = false, loc = locStub, constType = 0 /* NOT_CONSTANT */) { - return { - type: 4 /* SIMPLE_EXPRESSION */, - loc, - content, - isStatic, - constType: isStatic ? 3 /* CAN_STRINGIFY */ : constType - }; -} -function createInterpolation(content, loc) { - return { - type: 5 /* INTERPOLATION */, - loc, - content: isString(content) - ? createSimpleExpression(content, false, loc) - : content - }; -} -function createCompoundExpression(children, loc = locStub) { - return { - type: 8 /* COMPOUND_EXPRESSION */, - loc, - children - }; -} -function createCallExpression(callee, args = [], loc = locStub) { - return { - type: 14 /* JS_CALL_EXPRESSION */, - loc, - callee, - arguments: args - }; -} -function createFunctionExpression(params, returns = undefined, newline = false, isSlot = false, loc = locStub) { - return { - type: 18 /* JS_FUNCTION_EXPRESSION */, - params, - returns, - newline, - isSlot, - loc - }; -} -function createConditionalExpression(test, consequent, alternate, newline = true) { - return { - type: 19 /* JS_CONDITIONAL_EXPRESSION */, - test, - consequent, - alternate, - newline, - loc: locStub - }; -} -function createCacheExpression(index, value, isVNode = false) { - return { - type: 20 /* JS_CACHE_EXPRESSION */, - index, - value, - isVNode, - loc: locStub - }; -} -function createBlockStatement(body) { - return { - type: 21 /* JS_BLOCK_STATEMENT */, - body, - loc: locStub - }; -} -function createTemplateLiteral(elements) { - return { - type: 22 /* JS_TEMPLATE_LITERAL */, - elements, - loc: locStub - }; -} -function createIfStatement(test, consequent, alternate) { - return { - type: 23 /* JS_IF_STATEMENT */, - test, - consequent, - alternate, - loc: locStub - }; -} -function createAssignmentExpression(left, right) { - return { - type: 24 /* JS_ASSIGNMENT_EXPRESSION */, - left, - right, - loc: locStub - }; -} -function createSequenceExpression(expressions) { - return { - type: 25 /* JS_SEQUENCE_EXPRESSION */, - expressions, - loc: locStub - }; -} -function createReturnStatement(returns) { - return { - type: 26 /* JS_RETURN_STATEMENT */, - returns, - loc: locStub - }; +// AST Utilities --------------------------------------------------------------- +// Some expressions, e.g. sequence and conditional expressions, are never +// associated with template nodes, so their source locations are just a stub. +// Container types like CompoundExpression also don't need a real location. +const locStub = { + source: '', + start: { line: 1, column: 1, offset: 0 }, + end: { line: 1, column: 1, offset: 0 } +}; +function createRoot(children, loc = locStub) { + return { + type: 0 /* ROOT */, + children, + helpers: [], + components: [], + directives: [], + hoists: [], + imports: [], + cached: 0, + temps: 0, + codegenNode: undefined, + loc + }; +} +function createVNodeCall(context, tag, props, children, patchFlag, dynamicProps, directives, isBlock = false, disableTracking = false, isComponent = false, loc = locStub) { + if (context) { + if (isBlock) { + context.helper(OPEN_BLOCK); + context.helper(getVNodeBlockHelper(context.inSSR, isComponent)); + } + else { + context.helper(getVNodeHelper(context.inSSR, isComponent)); + } + if (directives) { + context.helper(WITH_DIRECTIVES); + } + } + return { + type: 13 /* VNODE_CALL */, + tag, + props, + children, + patchFlag, + dynamicProps, + directives, + isBlock, + disableTracking, + isComponent, + loc + }; +} +function createArrayExpression(elements, loc = locStub) { + return { + type: 17 /* JS_ARRAY_EXPRESSION */, + loc, + elements + }; +} +function createObjectExpression(properties, loc = locStub) { + return { + type: 15 /* JS_OBJECT_EXPRESSION */, + loc, + properties + }; +} +function createObjectProperty(key, value) { + return { + type: 16 /* JS_PROPERTY */, + loc: locStub, + key: isString(key) ? createSimpleExpression(key, true) : key, + value + }; +} +function createSimpleExpression(content, isStatic = false, loc = locStub, constType = 0 /* NOT_CONSTANT */) { + return { + type: 4 /* SIMPLE_EXPRESSION */, + loc, + content, + isStatic, + constType: isStatic ? 3 /* CAN_STRINGIFY */ : constType + }; +} +function createInterpolation(content, loc) { + return { + type: 5 /* INTERPOLATION */, + loc, + content: isString(content) + ? createSimpleExpression(content, false, loc) + : content + }; +} +function createCompoundExpression(children, loc = locStub) { + return { + type: 8 /* COMPOUND_EXPRESSION */, + loc, + children + }; +} +function createCallExpression(callee, args = [], loc = locStub) { + return { + type: 14 /* JS_CALL_EXPRESSION */, + loc, + callee, + arguments: args + }; +} +function createFunctionExpression(params, returns = undefined, newline = false, isSlot = false, loc = locStub) { + return { + type: 18 /* JS_FUNCTION_EXPRESSION */, + params, + returns, + newline, + isSlot, + loc + }; +} +function createConditionalExpression(test, consequent, alternate, newline = true) { + return { + type: 19 /* JS_CONDITIONAL_EXPRESSION */, + test, + consequent, + alternate, + newline, + loc: locStub + }; +} +function createCacheExpression(index, value, isVNode = false) { + return { + type: 20 /* JS_CACHE_EXPRESSION */, + index, + value, + isVNode, + loc: locStub + }; +} +function createBlockStatement(body) { + return { + type: 21 /* JS_BLOCK_STATEMENT */, + body, + loc: locStub + }; +} +function createTemplateLiteral(elements) { + return { + type: 22 /* JS_TEMPLATE_LITERAL */, + elements, + loc: locStub + }; +} +function createIfStatement(test, consequent, alternate) { + return { + type: 23 /* JS_IF_STATEMENT */, + test, + consequent, + alternate, + loc: locStub + }; +} +function createAssignmentExpression(left, right) { + return { + type: 24 /* JS_ASSIGNMENT_EXPRESSION */, + left, + right, + loc: locStub + }; +} +function createSequenceExpression(expressions) { + return { + type: 25 /* JS_SEQUENCE_EXPRESSION */, + expressions, + loc: locStub + }; +} +function createReturnStatement(returns) { + return { + type: 26 /* JS_RETURN_STATEMENT */, + returns, + loc: locStub + }; } -const isStaticExp = (p) => p.type === 4 /* SIMPLE_EXPRESSION */ && p.isStatic; -const isBuiltInType = (tag, expected) => tag === expected || tag === hyphenate(expected); -function isCoreComponent(tag) { - if (isBuiltInType(tag, 'Teleport')) { - return TELEPORT; - } - else if (isBuiltInType(tag, 'Suspense')) { - return SUSPENSE; - } - else if (isBuiltInType(tag, 'KeepAlive')) { - return KEEP_ALIVE; - } - else if (isBuiltInType(tag, 'BaseTransition')) { - return BASE_TRANSITION; - } -} -const nonIdentifierRE = /^\d|[^\$\w]/; -const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name); -const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/; -const validIdentCharRE = /[\.\?\w$\xA0-\uFFFF]/; -const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g; -/** - * Simple lexer to check if an expression is a member expression. This is - * lax and only checks validity at the root level (i.e. does not validate exps - * inside square brackets), but it's ok since these are only used on template - * expressions and false positives are invalid expressions in the first place. - */ -const isMemberExpressionBrowser = (path) => { - // remove whitespaces around . or [ first - path = path.trim().replace(whitespaceRE, s => s.trim()); - let state = 0 /* inMemberExp */; - let stateStack = []; - let currentOpenBracketCount = 0; - let currentOpenParensCount = 0; - let currentStringType = null; - for (let i = 0; i < path.length; i++) { - const char = path.charAt(i); - switch (state) { - case 0 /* inMemberExp */: - if (char === '[') { - stateStack.push(state); - state = 1 /* inBrackets */; - currentOpenBracketCount++; - } - else if (char === '(') { - stateStack.push(state); - state = 2 /* inParens */; - currentOpenParensCount++; - } - else if (!(i === 0 ? validFirstIdentCharRE : validIdentCharRE).test(char)) { - return false; - } - break; - case 1 /* inBrackets */: - if (char === `'` || char === `"` || char === '`') { - stateStack.push(state); - state = 3 /* inString */; - currentStringType = char; - } - else if (char === `[`) { - currentOpenBracketCount++; - } - else if (char === `]`) { - if (!--currentOpenBracketCount) { - state = stateStack.pop(); - } - } - break; - case 2 /* inParens */: - if (char === `'` || char === `"` || char === '`') { - stateStack.push(state); - state = 3 /* inString */; - currentStringType = char; - } - else if (char === `(`) { - currentOpenParensCount++; - } - else if (char === `)`) { - // if the exp ends as a call then it should not be considered valid - if (i === path.length - 1) { - return false; - } - if (!--currentOpenParensCount) { - state = stateStack.pop(); - } - } - break; - case 3 /* inString */: - if (char === currentStringType) { - state = stateStack.pop(); - currentStringType = null; - } - break; - } - } - return !currentOpenBracketCount && !currentOpenParensCount; -}; -const isMemberExpressionNode = NOOP - ; -const isMemberExpression = isMemberExpressionBrowser - ; -function getInnerRange(loc, offset, length) { - const source = loc.source.slice(offset, offset + length); - const newLoc = { - source, - start: advancePositionWithClone(loc.start, loc.source, offset), - end: loc.end - }; - if (length != null) { - newLoc.end = advancePositionWithClone(loc.start, loc.source, offset + length); - } - return newLoc; -} -function advancePositionWithClone(pos, source, numberOfCharacters = source.length) { - return advancePositionWithMutation(extend({}, pos), source, numberOfCharacters); -} -// advance by mutation without cloning (for performance reasons), since this -// gets called a lot in the parser -function advancePositionWithMutation(pos, source, numberOfCharacters = source.length) { - let linesCount = 0; - let lastNewLinePos = -1; - for (let i = 0; i < numberOfCharacters; i++) { - if (source.charCodeAt(i) === 10 /* newline char code */) { - linesCount++; - lastNewLinePos = i; - } - } - pos.offset += numberOfCharacters; - pos.line += linesCount; - pos.column = - lastNewLinePos === -1 - ? pos.column + numberOfCharacters - : numberOfCharacters - lastNewLinePos; - return pos; -} -function assert(condition, msg) { - /* istanbul ignore if */ - if (!condition) { - throw new Error(msg || `unexpected compiler condition`); - } -} -function findDir(node, name, allowEmpty = false) { - for (let i = 0; i < node.props.length; i++) { - const p = node.props[i]; - if (p.type === 7 /* DIRECTIVE */ && - (allowEmpty || p.exp) && - (isString(name) ? p.name === name : name.test(p.name))) { - return p; - } - } -} -function findProp(node, name, dynamicOnly = false, allowEmpty = false) { - for (let i = 0; i < node.props.length; i++) { - const p = node.props[i]; - if (p.type === 6 /* ATTRIBUTE */) { - if (dynamicOnly) - continue; - if (p.name === name && (p.value || allowEmpty)) { - return p; - } - } - else if (p.name === 'bind' && - (p.exp || allowEmpty) && - isStaticArgOf(p.arg, name)) { - return p; - } - } -} -function isStaticArgOf(arg, name) { - return !!(arg && isStaticExp(arg) && arg.content === name); -} -function hasDynamicKeyVBind(node) { - return node.props.some(p => p.type === 7 /* DIRECTIVE */ && - p.name === 'bind' && - (!p.arg || // v-bind="obj" - p.arg.type !== 4 /* SIMPLE_EXPRESSION */ || // v-bind:[_ctx.foo] - !p.arg.isStatic) // v-bind:[foo] - ); -} -function isText(node) { - return node.type === 5 /* INTERPOLATION */ || node.type === 2 /* TEXT */; -} -function isVSlot(p) { - return p.type === 7 /* DIRECTIVE */ && p.name === 'slot'; -} -function isTemplateNode(node) { - return (node.type === 1 /* ELEMENT */ && node.tagType === 3 /* TEMPLATE */); -} -function isSlotOutlet(node) { - return node.type === 1 /* ELEMENT */ && node.tagType === 2 /* SLOT */; -} -function getVNodeHelper(ssr, isComponent) { - return ssr || isComponent ? CREATE_VNODE : CREATE_ELEMENT_VNODE; -} -function getVNodeBlockHelper(ssr, isComponent) { - return ssr || isComponent ? CREATE_BLOCK : CREATE_ELEMENT_BLOCK; -} -const propsHelperSet = new Set([NORMALIZE_PROPS, GUARD_REACTIVE_PROPS]); -function getUnnormalizedProps(props, callPath = []) { - if (props && - !isString(props) && - props.type === 14 /* JS_CALL_EXPRESSION */) { - const callee = props.callee; - if (!isString(callee) && propsHelperSet.has(callee)) { - return getUnnormalizedProps(props.arguments[0], callPath.concat(props)); - } - } - return [props, callPath]; -} -function injectProp(node, prop, context) { - let propsWithInjection; - /** - * 1. mergeProps(...) - * 2. toHandlers(...) - * 3. normalizeProps(...) - * 4. normalizeProps(guardReactiveProps(...)) - * - * we need to get the real props before normalization - */ - let props = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2]; - let callPath = []; - let parentCall; - if (props && - !isString(props) && - props.type === 14 /* JS_CALL_EXPRESSION */) { - const ret = getUnnormalizedProps(props); - props = ret[0]; - callPath = ret[1]; - parentCall = callPath[callPath.length - 1]; - } - if (props == null || isString(props)) { - propsWithInjection = createObjectExpression([prop]); - } - else if (props.type === 14 /* JS_CALL_EXPRESSION */) { - // merged props... add ours - // only inject key to object literal if it's the first argument so that - // if doesn't override user provided keys - const first = props.arguments[0]; - if (!isString(first) && first.type === 15 /* JS_OBJECT_EXPRESSION */) { - first.properties.unshift(prop); - } - else { - if (props.callee === TO_HANDLERS) { - // #2366 - propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [ - createObjectExpression([prop]), - props - ]); - } - else { - props.arguments.unshift(createObjectExpression([prop])); - } - } - !propsWithInjection && (propsWithInjection = props); - } - else if (props.type === 15 /* JS_OBJECT_EXPRESSION */) { - let alreadyExists = false; - // check existing key to avoid overriding user provided keys - if (prop.key.type === 4 /* SIMPLE_EXPRESSION */) { - const propKeyName = prop.key.content; - alreadyExists = props.properties.some(p => p.key.type === 4 /* SIMPLE_EXPRESSION */ && - p.key.content === propKeyName); - } - if (!alreadyExists) { - props.properties.unshift(prop); - } - propsWithInjection = props; - } - else { - // single v-bind with expression, return a merged replacement - propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [ - createObjectExpression([prop]), - props - ]); - // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(props))`, - // it will be rewritten as `normalizeProps(mergeProps({ key: 0 }, props))`, - // the `guardReactiveProps` will no longer be needed - if (parentCall && parentCall.callee === GUARD_REACTIVE_PROPS) { - parentCall = callPath[callPath.length - 2]; - } - } - if (node.type === 13 /* VNODE_CALL */) { - if (parentCall) { - parentCall.arguments[0] = propsWithInjection; - } - else { - node.props = propsWithInjection; - } - } - else { - if (parentCall) { - parentCall.arguments[0] = propsWithInjection; - } - else { - node.arguments[2] = propsWithInjection; - } - } -} -function toValidAssetId(name, type) { - // see issue#4422, we need adding identifier on validAssetId if variable `name` has specific character - return `_${type}_${name.replace(/[^\w]/g, (searchValue, replaceValue) => { - return searchValue === '-' ? '_' : name.charCodeAt(replaceValue).toString(); - })}`; -} -// Check if a node contains expressions that reference current context scope ids -function hasScopeRef(node, ids) { - if (!node || Object.keys(ids).length === 0) { - return false; - } - switch (node.type) { - case 1 /* ELEMENT */: - for (let i = 0; i < node.props.length; i++) { - const p = node.props[i]; - if (p.type === 7 /* DIRECTIVE */ && - (hasScopeRef(p.arg, ids) || hasScopeRef(p.exp, ids))) { - return true; - } - } - return node.children.some(c => hasScopeRef(c, ids)); - case 11 /* FOR */: - if (hasScopeRef(node.source, ids)) { - return true; - } - return node.children.some(c => hasScopeRef(c, ids)); - case 9 /* IF */: - return node.branches.some(b => hasScopeRef(b, ids)); - case 10 /* IF_BRANCH */: - if (hasScopeRef(node.condition, ids)) { - return true; - } - return node.children.some(c => hasScopeRef(c, ids)); - case 4 /* SIMPLE_EXPRESSION */: - return (!node.isStatic && - isSimpleIdentifier(node.content) && - !!ids[node.content]); - case 8 /* COMPOUND_EXPRESSION */: - return node.children.some(c => isObject(c) && hasScopeRef(c, ids)); - case 5 /* INTERPOLATION */: - case 12 /* TEXT_CALL */: - return hasScopeRef(node.content, ids); - case 2 /* TEXT */: - case 3 /* COMMENT */: - return false; - default: - if ((process.env.NODE_ENV !== 'production')) ; - return false; - } -} -function getMemoedVNodeCall(node) { - if (node.type === 14 /* JS_CALL_EXPRESSION */ && node.callee === WITH_MEMO) { - return node.arguments[1].returns; - } - else { - return node; - } -} -function makeBlock(node, { helper, removeHelper, inSSR }) { - if (!node.isBlock) { - node.isBlock = true; - removeHelper(getVNodeHelper(inSSR, node.isComponent)); - helper(OPEN_BLOCK); - helper(getVNodeBlockHelper(inSSR, node.isComponent)); - } +const isStaticExp = (p) => p.type === 4 /* SIMPLE_EXPRESSION */ && p.isStatic; +const isBuiltInType = (tag, expected) => tag === expected || tag === hyphenate(expected); +function isCoreComponent(tag) { + if (isBuiltInType(tag, 'Teleport')) { + return TELEPORT; + } + else if (isBuiltInType(tag, 'Suspense')) { + return SUSPENSE; + } + else if (isBuiltInType(tag, 'KeepAlive')) { + return KEEP_ALIVE; + } + else if (isBuiltInType(tag, 'BaseTransition')) { + return BASE_TRANSITION; + } +} +const nonIdentifierRE = /^\d|[^\$\w]/; +const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name); +const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/; +const validIdentCharRE = /[\.\?\w$\xA0-\uFFFF]/; +const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g; +/** + * Simple lexer to check if an expression is a member expression. This is + * lax and only checks validity at the root level (i.e. does not validate exps + * inside square brackets), but it's ok since these are only used on template + * expressions and false positives are invalid expressions in the first place. + */ +const isMemberExpressionBrowser = (path) => { + // remove whitespaces around . or [ first + path = path.trim().replace(whitespaceRE, s => s.trim()); + let state = 0 /* inMemberExp */; + let stateStack = []; + let currentOpenBracketCount = 0; + let currentOpenParensCount = 0; + let currentStringType = null; + for (let i = 0; i < path.length; i++) { + const char = path.charAt(i); + switch (state) { + case 0 /* inMemberExp */: + if (char === '[') { + stateStack.push(state); + state = 1 /* inBrackets */; + currentOpenBracketCount++; + } + else if (char === '(') { + stateStack.push(state); + state = 2 /* inParens */; + currentOpenParensCount++; + } + else if (!(i === 0 ? validFirstIdentCharRE : validIdentCharRE).test(char)) { + return false; + } + break; + case 1 /* inBrackets */: + if (char === `'` || char === `"` || char === '`') { + stateStack.push(state); + state = 3 /* inString */; + currentStringType = char; + } + else if (char === `[`) { + currentOpenBracketCount++; + } + else if (char === `]`) { + if (!--currentOpenBracketCount) { + state = stateStack.pop(); + } + } + break; + case 2 /* inParens */: + if (char === `'` || char === `"` || char === '`') { + stateStack.push(state); + state = 3 /* inString */; + currentStringType = char; + } + else if (char === `(`) { + currentOpenParensCount++; + } + else if (char === `)`) { + // if the exp ends as a call then it should not be considered valid + if (i === path.length - 1) { + return false; + } + if (!--currentOpenParensCount) { + state = stateStack.pop(); + } + } + break; + case 3 /* inString */: + if (char === currentStringType) { + state = stateStack.pop(); + currentStringType = null; + } + break; + } + } + return !currentOpenBracketCount && !currentOpenParensCount; +}; +const isMemberExpressionNode = NOOP + ; +const isMemberExpression = isMemberExpressionBrowser + ; +function getInnerRange(loc, offset, length) { + const source = loc.source.slice(offset, offset + length); + const newLoc = { + source, + start: advancePositionWithClone(loc.start, loc.source, offset), + end: loc.end + }; + if (length != null) { + newLoc.end = advancePositionWithClone(loc.start, loc.source, offset + length); + } + return newLoc; +} +function advancePositionWithClone(pos, source, numberOfCharacters = source.length) { + return advancePositionWithMutation(extend({}, pos), source, numberOfCharacters); +} +// advance by mutation without cloning (for performance reasons), since this +// gets called a lot in the parser +function advancePositionWithMutation(pos, source, numberOfCharacters = source.length) { + let linesCount = 0; + let lastNewLinePos = -1; + for (let i = 0; i < numberOfCharacters; i++) { + if (source.charCodeAt(i) === 10 /* newline char code */) { + linesCount++; + lastNewLinePos = i; + } + } + pos.offset += numberOfCharacters; + pos.line += linesCount; + pos.column = + lastNewLinePos === -1 + ? pos.column + numberOfCharacters + : numberOfCharacters - lastNewLinePos; + return pos; +} +function assert(condition, msg) { + /* istanbul ignore if */ + if (!condition) { + throw new Error(msg || `unexpected compiler condition`); + } +} +function findDir(node, name, allowEmpty = false) { + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i]; + if (p.type === 7 /* DIRECTIVE */ && + (allowEmpty || p.exp) && + (isString(name) ? p.name === name : name.test(p.name))) { + return p; + } + } +} +function findProp(node, name, dynamicOnly = false, allowEmpty = false) { + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i]; + if (p.type === 6 /* ATTRIBUTE */) { + if (dynamicOnly) + continue; + if (p.name === name && (p.value || allowEmpty)) { + return p; + } + } + else if (p.name === 'bind' && + (p.exp || allowEmpty) && + isStaticArgOf(p.arg, name)) { + return p; + } + } +} +function isStaticArgOf(arg, name) { + return !!(arg && isStaticExp(arg) && arg.content === name); +} +function hasDynamicKeyVBind(node) { + return node.props.some(p => p.type === 7 /* DIRECTIVE */ && + p.name === 'bind' && + (!p.arg || // v-bind="obj" + p.arg.type !== 4 /* SIMPLE_EXPRESSION */ || // v-bind:[_ctx.foo] + !p.arg.isStatic) // v-bind:[foo] + ); +} +function isText(node) { + return node.type === 5 /* INTERPOLATION */ || node.type === 2 /* TEXT */; +} +function isVSlot(p) { + return p.type === 7 /* DIRECTIVE */ && p.name === 'slot'; +} +function isTemplateNode(node) { + return (node.type === 1 /* ELEMENT */ && node.tagType === 3 /* TEMPLATE */); +} +function isSlotOutlet(node) { + return node.type === 1 /* ELEMENT */ && node.tagType === 2 /* SLOT */; +} +function getVNodeHelper(ssr, isComponent) { + return ssr || isComponent ? CREATE_VNODE : CREATE_ELEMENT_VNODE; +} +function getVNodeBlockHelper(ssr, isComponent) { + return ssr || isComponent ? CREATE_BLOCK : CREATE_ELEMENT_BLOCK; +} +const propsHelperSet = new Set([NORMALIZE_PROPS, GUARD_REACTIVE_PROPS]); +function getUnnormalizedProps(props, callPath = []) { + if (props && + !isString(props) && + props.type === 14 /* JS_CALL_EXPRESSION */) { + const callee = props.callee; + if (!isString(callee) && propsHelperSet.has(callee)) { + return getUnnormalizedProps(props.arguments[0], callPath.concat(props)); + } + } + return [props, callPath]; +} +function injectProp(node, prop, context) { + let propsWithInjection; + /** + * 1. mergeProps(...) + * 2. toHandlers(...) + * 3. normalizeProps(...) + * 4. normalizeProps(guardReactiveProps(...)) + * + * we need to get the real props before normalization + */ + let props = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2]; + let callPath = []; + let parentCall; + if (props && + !isString(props) && + props.type === 14 /* JS_CALL_EXPRESSION */) { + const ret = getUnnormalizedProps(props); + props = ret[0]; + callPath = ret[1]; + parentCall = callPath[callPath.length - 1]; + } + if (props == null || isString(props)) { + propsWithInjection = createObjectExpression([prop]); + } + else if (props.type === 14 /* JS_CALL_EXPRESSION */) { + // merged props... add ours + // only inject key to object literal if it's the first argument so that + // if doesn't override user provided keys + const first = props.arguments[0]; + if (!isString(first) && first.type === 15 /* JS_OBJECT_EXPRESSION */) { + first.properties.unshift(prop); + } + else { + if (props.callee === TO_HANDLERS) { + // #2366 + propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [ + createObjectExpression([prop]), + props + ]); + } + else { + props.arguments.unshift(createObjectExpression([prop])); + } + } + !propsWithInjection && (propsWithInjection = props); + } + else if (props.type === 15 /* JS_OBJECT_EXPRESSION */) { + let alreadyExists = false; + // check existing key to avoid overriding user provided keys + if (prop.key.type === 4 /* SIMPLE_EXPRESSION */) { + const propKeyName = prop.key.content; + alreadyExists = props.properties.some(p => p.key.type === 4 /* SIMPLE_EXPRESSION */ && + p.key.content === propKeyName); + } + if (!alreadyExists) { + props.properties.unshift(prop); + } + propsWithInjection = props; + } + else { + // single v-bind with expression, return a merged replacement + propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [ + createObjectExpression([prop]), + props + ]); + // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(props))`, + // it will be rewritten as `normalizeProps(mergeProps({ key: 0 }, props))`, + // the `guardReactiveProps` will no longer be needed + if (parentCall && parentCall.callee === GUARD_REACTIVE_PROPS) { + parentCall = callPath[callPath.length - 2]; + } + } + if (node.type === 13 /* VNODE_CALL */) { + if (parentCall) { + parentCall.arguments[0] = propsWithInjection; + } + else { + node.props = propsWithInjection; + } + } + else { + if (parentCall) { + parentCall.arguments[0] = propsWithInjection; + } + else { + node.arguments[2] = propsWithInjection; + } + } +} +function toValidAssetId(name, type) { + // see issue#4422, we need adding identifier on validAssetId if variable `name` has specific character + return `_${type}_${name.replace(/[^\w]/g, (searchValue, replaceValue) => { + return searchValue === '-' ? '_' : name.charCodeAt(replaceValue).toString(); + })}`; +} +// Check if a node contains expressions that reference current context scope ids +function hasScopeRef(node, ids) { + if (!node || Object.keys(ids).length === 0) { + return false; + } + switch (node.type) { + case 1 /* ELEMENT */: + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i]; + if (p.type === 7 /* DIRECTIVE */ && + (hasScopeRef(p.arg, ids) || hasScopeRef(p.exp, ids))) { + return true; + } + } + return node.children.some(c => hasScopeRef(c, ids)); + case 11 /* FOR */: + if (hasScopeRef(node.source, ids)) { + return true; + } + return node.children.some(c => hasScopeRef(c, ids)); + case 9 /* IF */: + return node.branches.some(b => hasScopeRef(b, ids)); + case 10 /* IF_BRANCH */: + if (hasScopeRef(node.condition, ids)) { + return true; + } + return node.children.some(c => hasScopeRef(c, ids)); + case 4 /* SIMPLE_EXPRESSION */: + return (!node.isStatic && + isSimpleIdentifier(node.content) && + !!ids[node.content]); + case 8 /* COMPOUND_EXPRESSION */: + return node.children.some(c => isObject(c) && hasScopeRef(c, ids)); + case 5 /* INTERPOLATION */: + case 12 /* TEXT_CALL */: + return hasScopeRef(node.content, ids); + case 2 /* TEXT */: + case 3 /* COMMENT */: + return false; + default: + if ((process.env.NODE_ENV !== 'production')) ; + return false; + } +} +function getMemoedVNodeCall(node) { + if (node.type === 14 /* JS_CALL_EXPRESSION */ && node.callee === WITH_MEMO) { + return node.arguments[1].returns; + } + else { + return node; + } +} +function makeBlock(node, { helper, removeHelper, inSSR }) { + if (!node.isBlock) { + node.isBlock = true; + removeHelper(getVNodeHelper(inSSR, node.isComponent)); + helper(OPEN_BLOCK); + helper(getVNodeBlockHelper(inSSR, node.isComponent)); + } } -const deprecationData = { - ["COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */]: { - message: `Platform-native elements with "is" prop will no longer be ` + - `treated as components in Vue 3 unless the "is" value is explicitly ` + - `prefixed with "vue:".`, - link: `https://v3-migration.vuejs.org/breaking-changes/custom-elements-interop.html` - }, - ["COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */]: { - message: key => `.sync modifier for v-bind has been removed. Use v-model with ` + - `argument instead. \`v-bind:${key}.sync\` should be changed to ` + - `\`v-model:${key}\`.`, - link: `https://v3-migration.vuejs.org/breaking-changes/v-model.html` - }, - ["COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */]: { - message: `.prop modifier for v-bind has been removed and no longer necessary. ` + - `Vue 3 will automatically set a binding as DOM property when appropriate.` - }, - ["COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */]: { - message: `v-bind="obj" usage is now order sensitive and behaves like JavaScript ` + - `object spread: it will now overwrite an existing non-mergeable attribute ` + - `that appears before v-bind in the case of conflict. ` + - `To retain 2.x behavior, move v-bind to make it the first attribute. ` + - `You can also suppress this warning if the usage is intended.`, - link: `https://v3-migration.vuejs.org/breaking-changes/v-bind.html` - }, - ["COMPILER_V_ON_NATIVE" /* COMPILER_V_ON_NATIVE */]: { - message: `.native modifier for v-on has been removed as is no longer necessary.`, - link: `https://v3-migration.vuejs.org/breaking-changes/v-on-native-modifier-removed.html` - }, - ["COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */]: { - message: `v-if / v-for precedence when used on the same element has changed ` + - `in Vue 3: v-if now takes higher precedence and will no longer have ` + - `access to v-for scope variables. It is best to avoid the ambiguity ` + - `with <template> tags or use a computed property that filters v-for ` + - `data source.`, - link: `https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html` - }, - ["COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */]: { - message: `<template> with no special directives will render as a native template ` + - `element instead of its inner content in Vue 3.` - }, - ["COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */]: { - message: `"inline-template" has been removed in Vue 3.`, - link: `https://v3-migration.vuejs.org/breaking-changes/inline-template-attribute.html` - }, - ["COMPILER_FILTER" /* COMPILER_FILTERS */]: { - message: `filters have been removed in Vue 3. ` + - `The "|" symbol will be treated as native JavaScript bitwise OR operator. ` + - `Use method calls or computed properties instead.`, - link: `https://v3-migration.vuejs.org/breaking-changes/filters.html` - } -}; -function getCompatValue(key, context) { - const config = context.options - ? context.options.compatConfig - : context.compatConfig; - const value = config && config[key]; - if (key === 'MODE') { - return value || 3; // compiler defaults to v3 behavior - } - else { - return value; - } -} -function isCompatEnabled(key, context) { - const mode = getCompatValue('MODE', context); - const value = getCompatValue(key, context); - // in v3 mode, only enable if explicitly set to true - // otherwise enable for any non-false value - return mode === 3 ? value === true : value !== false; -} -function checkCompatEnabled(key, context, loc, ...args) { - const enabled = isCompatEnabled(key, context); - if ((process.env.NODE_ENV !== 'production') && enabled) { - warnDeprecation(key, context, loc, ...args); - } - return enabled; -} -function warnDeprecation(key, context, loc, ...args) { - const val = getCompatValue(key, context); - if (val === 'suppress-warning') { - return; - } - const { message, link } = deprecationData[key]; - const msg = `(deprecation ${key}) ${typeof message === 'function' ? message(...args) : message}${link ? `\n Details: ${link}` : ``}`; - const err = new SyntaxError(msg); - err.code = key; - if (loc) - err.loc = loc; - context.onWarn(err); +const deprecationData = { + ["COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */]: { + message: `Platform-native elements with "is" prop will no longer be ` + + `treated as components in Vue 3 unless the "is" value is explicitly ` + + `prefixed with "vue:".`, + link: `https://v3-migration.vuejs.org/breaking-changes/custom-elements-interop.html` + }, + ["COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */]: { + message: key => `.sync modifier for v-bind has been removed. Use v-model with ` + + `argument instead. \`v-bind:${key}.sync\` should be changed to ` + + `\`v-model:${key}\`.`, + link: `https://v3-migration.vuejs.org/breaking-changes/v-model.html` + }, + ["COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */]: { + message: `.prop modifier for v-bind has been removed and no longer necessary. ` + + `Vue 3 will automatically set a binding as DOM property when appropriate.` + }, + ["COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */]: { + message: `v-bind="obj" usage is now order sensitive and behaves like JavaScript ` + + `object spread: it will now overwrite an existing non-mergeable attribute ` + + `that appears before v-bind in the case of conflict. ` + + `To retain 2.x behavior, move v-bind to make it the first attribute. ` + + `You can also suppress this warning if the usage is intended.`, + link: `https://v3-migration.vuejs.org/breaking-changes/v-bind.html` + }, + ["COMPILER_V_ON_NATIVE" /* COMPILER_V_ON_NATIVE */]: { + message: `.native modifier for v-on has been removed as is no longer necessary.`, + link: `https://v3-migration.vuejs.org/breaking-changes/v-on-native-modifier-removed.html` + }, + ["COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */]: { + message: `v-if / v-for precedence when used on the same element has changed ` + + `in Vue 3: v-if now takes higher precedence and will no longer have ` + + `access to v-for scope variables. It is best to avoid the ambiguity ` + + `with <template> tags or use a computed property that filters v-for ` + + `data source.`, + link: `https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html` + }, + ["COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */]: { + message: `<template> with no special directives will render as a native template ` + + `element instead of its inner content in Vue 3.` + }, + ["COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */]: { + message: `"inline-template" has been removed in Vue 3.`, + link: `https://v3-migration.vuejs.org/breaking-changes/inline-template-attribute.html` + }, + ["COMPILER_FILTER" /* COMPILER_FILTERS */]: { + message: `filters have been removed in Vue 3. ` + + `The "|" symbol will be treated as native JavaScript bitwise OR operator. ` + + `Use method calls or computed properties instead.`, + link: `https://v3-migration.vuejs.org/breaking-changes/filters.html` + } +}; +function getCompatValue(key, context) { + const config = context.options + ? context.options.compatConfig + : context.compatConfig; + const value = config && config[key]; + if (key === 'MODE') { + return value || 3; // compiler defaults to v3 behavior + } + else { + return value; + } +} +function isCompatEnabled(key, context) { + const mode = getCompatValue('MODE', context); + const value = getCompatValue(key, context); + // in v3 mode, only enable if explicitly set to true + // otherwise enable for any non-false value + return mode === 3 ? value === true : value !== false; +} +function checkCompatEnabled(key, context, loc, ...args) { + const enabled = isCompatEnabled(key, context); + if ((process.env.NODE_ENV !== 'production') && enabled) { + warnDeprecation(key, context, loc, ...args); + } + return enabled; +} +function warnDeprecation(key, context, loc, ...args) { + const val = getCompatValue(key, context); + if (val === 'suppress-warning') { + return; + } + const { message, link } = deprecationData[key]; + const msg = `(deprecation ${key}) ${typeof message === 'function' ? message(...args) : message}${link ? `\n Details: ${link}` : ``}`; + const err = new SyntaxError(msg); + err.code = key; + if (loc) + err.loc = loc; + context.onWarn(err); } -// The default decoder only provides escapes for characters reserved as part of -// the template syntax, and is only used if the custom renderer did not provide -// a platform-specific decoder. -const decodeRE = /&(gt|lt|amp|apos|quot);/g; -const decodeMap = { - gt: '>', - lt: '<', - amp: '&', - apos: "'", - quot: '"' -}; -const defaultParserOptions = { - delimiters: [`{{`, `}}`], - getNamespace: () => 0 /* HTML */, - getTextMode: () => 0 /* DATA */, - isVoidTag: NO, - isPreTag: NO, - isCustomElement: NO, - decodeEntities: (rawText) => rawText.replace(decodeRE, (_, p1) => decodeMap[p1]), - onError: defaultOnError, - onWarn: defaultOnWarn, - comments: (process.env.NODE_ENV !== 'production') -}; -function baseParse(content, options = {}) { - const context = createParserContext(content, options); - const start = getCursor(context); - return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start)); -} -function createParserContext(content, rawOptions) { - const options = extend({}, defaultParserOptions); - let key; - for (key in rawOptions) { - // @ts-ignore - options[key] = - rawOptions[key] === undefined - ? defaultParserOptions[key] - : rawOptions[key]; - } - return { - options, - column: 1, - line: 1, - offset: 0, - originalSource: content, - source: content, - inPre: false, - inVPre: false, - onWarn: options.onWarn - }; -} -function parseChildren(context, mode, ancestors) { - const parent = last(ancestors); - const ns = parent ? parent.ns : 0 /* HTML */; - const nodes = []; - while (!isEnd(context, mode, ancestors)) { - const s = context.source; - let node = undefined; - if (mode === 0 /* DATA */ || mode === 1 /* RCDATA */) { - if (!context.inVPre && startsWith(s, context.options.delimiters[0])) { - // '{{' - node = parseInterpolation(context, mode); - } - else if (mode === 0 /* DATA */ && s[0] === '<') { - // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state - if (s.length === 1) { - emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 1); - } - else if (s[1] === '!') { - // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state - if (startsWith(s, '<!--')) { - node = parseComment(context); - } - else if (startsWith(s, '<!DOCTYPE')) { - // Ignore DOCTYPE by a limitation. - node = parseBogusComment(context); - } - else if (startsWith(s, '<![CDATA[')) { - if (ns !== 0 /* HTML */) { - node = parseCDATA(context, ancestors); - } - else { - emitError(context, 1 /* CDATA_IN_HTML_CONTENT */); - node = parseBogusComment(context); - } - } - else { - emitError(context, 11 /* INCORRECTLY_OPENED_COMMENT */); - node = parseBogusComment(context); - } - } - else if (s[1] === '/') { - // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state - if (s.length === 2) { - emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 2); - } - else if (s[2] === '>') { - emitError(context, 14 /* MISSING_END_TAG_NAME */, 2); - advanceBy(context, 3); - continue; - } - else if (/[a-z]/i.test(s[2])) { - emitError(context, 23 /* X_INVALID_END_TAG */); - parseTag(context, 1 /* End */, parent); - continue; - } - else { - emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2); - node = parseBogusComment(context); - } - } - else if (/[a-z]/i.test(s[1])) { - node = parseElement(context, ancestors); - // 2.x <template> with no directive compat - if (isCompatEnabled("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context) && - node && - node.tag === 'template' && - !node.props.some(p => p.type === 7 /* DIRECTIVE */ && - isSpecialTemplateDirective(p.name))) { - (process.env.NODE_ENV !== 'production') && - warnDeprecation("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context, node.loc); - node = node.children; - } - } - else if (s[1] === '?') { - emitError(context, 21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1); - node = parseBogusComment(context); - } - else { - emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1); - } - } - } - if (!node) { - node = parseText(context, mode); - } - if (isArray(node)) { - for (let i = 0; i < node.length; i++) { - pushNode(nodes, node[i]); - } - } - else { - pushNode(nodes, node); - } - } - // Whitespace handling strategy like v2 - let removedWhitespace = false; - if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) { - const shouldCondense = context.options.whitespace !== 'preserve'; - for (let i = 0; i < nodes.length; i++) { - const node = nodes[i]; - if (!context.inPre && node.type === 2 /* TEXT */) { - if (!/[^\t\r\n\f ]/.test(node.content)) { - const prev = nodes[i - 1]; - const next = nodes[i + 1]; - // Remove if: - // - the whitespace is the first or last node, or: - // - (condense mode) the whitespace is adjacent to a comment, or: - // - (condense mode) the whitespace is between two elements AND contains newline - if (!prev || - !next || - (shouldCondense && - (prev.type === 3 /* COMMENT */ || - next.type === 3 /* COMMENT */ || - (prev.type === 1 /* ELEMENT */ && - next.type === 1 /* ELEMENT */ && - /[\r\n]/.test(node.content))))) { - removedWhitespace = true; - nodes[i] = null; - } - else { - // Otherwise, the whitespace is condensed into a single space - node.content = ' '; - } - } - else if (shouldCondense) { - // in condense mode, consecutive whitespaces in text are condensed - // down to a single space. - node.content = node.content.replace(/[\t\r\n\f ]+/g, ' '); - } - } - // Remove comment nodes if desired by configuration. - else if (node.type === 3 /* COMMENT */ && !context.options.comments) { - removedWhitespace = true; - nodes[i] = null; - } - } - if (context.inPre && parent && context.options.isPreTag(parent.tag)) { - // remove leading newline per html spec - // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element - const first = nodes[0]; - if (first && first.type === 2 /* TEXT */) { - first.content = first.content.replace(/^\r?\n/, ''); - } - } - } - return removedWhitespace ? nodes.filter(Boolean) : nodes; -} -function pushNode(nodes, node) { - if (node.type === 2 /* TEXT */) { - const prev = last(nodes); - // Merge if both this and the previous node are text and those are - // consecutive. This happens for cases like "a < b". - if (prev && - prev.type === 2 /* TEXT */ && - prev.loc.end.offset === node.loc.start.offset) { - prev.content += node.content; - prev.loc.end = node.loc.end; - prev.loc.source += node.loc.source; - return; - } - } - nodes.push(node); -} -function parseCDATA(context, ancestors) { - advanceBy(context, 9); - const nodes = parseChildren(context, 3 /* CDATA */, ancestors); - if (context.source.length === 0) { - emitError(context, 6 /* EOF_IN_CDATA */); - } - else { - advanceBy(context, 3); - } - return nodes; -} -function parseComment(context) { - const start = getCursor(context); - let content; - // Regular comment. - const match = /--(\!)?>/.exec(context.source); - if (!match) { - content = context.source.slice(4); - advanceBy(context, context.source.length); - emitError(context, 7 /* EOF_IN_COMMENT */); - } - else { - if (match.index <= 3) { - emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */); - } - if (match[1]) { - emitError(context, 10 /* INCORRECTLY_CLOSED_COMMENT */); - } - content = context.source.slice(4, match.index); - // Advancing with reporting nested comments. - const s = context.source.slice(0, match.index); - let prevIndex = 1, nestedIndex = 0; - while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) { - advanceBy(context, nestedIndex - prevIndex + 1); - if (nestedIndex + 4 < s.length) { - emitError(context, 16 /* NESTED_COMMENT */); - } - prevIndex = nestedIndex + 1; - } - advanceBy(context, match.index + match[0].length - prevIndex + 1); - } - return { - type: 3 /* COMMENT */, - content, - loc: getSelection(context, start) - }; -} -function parseBogusComment(context) { - const start = getCursor(context); - const contentStart = context.source[1] === '?' ? 1 : 2; - let content; - const closeIndex = context.source.indexOf('>'); - if (closeIndex === -1) { - content = context.source.slice(contentStart); - advanceBy(context, context.source.length); - } - else { - content = context.source.slice(contentStart, closeIndex); - advanceBy(context, closeIndex + 1); - } - return { - type: 3 /* COMMENT */, - content, - loc: getSelection(context, start) - }; -} -function parseElement(context, ancestors) { - // Start tag. - const wasInPre = context.inPre; - const wasInVPre = context.inVPre; - const parent = last(ancestors); - const element = parseTag(context, 0 /* Start */, parent); - const isPreBoundary = context.inPre && !wasInPre; - const isVPreBoundary = context.inVPre && !wasInVPre; - if (element.isSelfClosing || context.options.isVoidTag(element.tag)) { - // #4030 self-closing <pre> tag - if (isPreBoundary) { - context.inPre = false; - } - if (isVPreBoundary) { - context.inVPre = false; - } - return element; - } - // Children. - ancestors.push(element); - const mode = context.options.getTextMode(element, parent); - const children = parseChildren(context, mode, ancestors); - ancestors.pop(); - // 2.x inline-template compat - { - const inlineTemplateProp = element.props.find(p => p.type === 6 /* ATTRIBUTE */ && p.name === 'inline-template'); - if (inlineTemplateProp && - checkCompatEnabled("COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */, context, inlineTemplateProp.loc)) { - const loc = getSelection(context, element.loc.end); - inlineTemplateProp.value = { - type: 2 /* TEXT */, - content: loc.source, - loc - }; - } - } - element.children = children; - // End tag. - if (startsWithEndTagOpen(context.source, element.tag)) { - parseTag(context, 1 /* End */, parent); - } - else { - emitError(context, 24 /* X_MISSING_END_TAG */, 0, element.loc.start); - if (context.source.length === 0 && element.tag.toLowerCase() === 'script') { - const first = children[0]; - if (first && startsWith(first.loc.source, '<!--')) { - emitError(context, 8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */); - } - } - } - element.loc = getSelection(context, element.loc.start); - if (isPreBoundary) { - context.inPre = false; - } - if (isVPreBoundary) { - context.inVPre = false; - } - return element; -} -const isSpecialTemplateDirective = /*#__PURE__*/ makeMap(`if,else,else-if,for,slot`); -function parseTag(context, type, parent) { - // Tag open. - const start = getCursor(context); - const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source); - const tag = match[1]; - const ns = context.options.getNamespace(tag, parent); - advanceBy(context, match[0].length); - advanceSpaces(context); - // save current state in case we need to re-parse attributes with v-pre - const cursor = getCursor(context); - const currentSource = context.source; - // check <pre> tag - if (context.options.isPreTag(tag)) { - context.inPre = true; - } - // Attributes. - let props = parseAttributes(context, type); - // check v-pre - if (type === 0 /* Start */ && - !context.inVPre && - props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) { - context.inVPre = true; - // reset context - extend(context, cursor); - context.source = currentSource; - // re-parse attrs and filter out v-pre itself - props = parseAttributes(context, type).filter(p => p.name !== 'v-pre'); - } - // Tag close. - let isSelfClosing = false; - if (context.source.length === 0) { - emitError(context, 9 /* EOF_IN_TAG */); - } - else { - isSelfClosing = startsWith(context.source, '/>'); - if (type === 1 /* End */ && isSelfClosing) { - emitError(context, 4 /* END_TAG_WITH_TRAILING_SOLIDUS */); - } - advanceBy(context, isSelfClosing ? 2 : 1); - } - if (type === 1 /* End */) { - return; - } - // 2.x deprecation checks - if ((process.env.NODE_ENV !== 'production') && - isCompatEnabled("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context)) { - let hasIf = false; - let hasFor = false; - for (let i = 0; i < props.length; i++) { - const p = props[i]; - if (p.type === 7 /* DIRECTIVE */) { - if (p.name === 'if') { - hasIf = true; - } - else if (p.name === 'for') { - hasFor = true; - } - } - if (hasIf && hasFor) { - warnDeprecation("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context, getSelection(context, start)); - break; - } - } - } - let tagType = 0 /* ELEMENT */; - if (!context.inVPre) { - if (tag === 'slot') { - tagType = 2 /* SLOT */; - } - else if (tag === 'template') { - if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) { - tagType = 3 /* TEMPLATE */; - } - } - else if (isComponent(tag, props, context)) { - tagType = 1 /* COMPONENT */; - } - } - return { - type: 1 /* ELEMENT */, - ns, - tag, - tagType, - props, - isSelfClosing, - children: [], - loc: getSelection(context, start), - codegenNode: undefined // to be created during transform phase - }; -} -function isComponent(tag, props, context) { - const options = context.options; - if (options.isCustomElement(tag)) { - return false; - } - if (tag === 'component' || - /^[A-Z]/.test(tag) || - isCoreComponent(tag) || - (options.isBuiltInComponent && options.isBuiltInComponent(tag)) || - (options.isNativeTag && !options.isNativeTag(tag))) { - return true; - } - // at this point the tag should be a native tag, but check for potential "is" - // casting - for (let i = 0; i < props.length; i++) { - const p = props[i]; - if (p.type === 6 /* ATTRIBUTE */) { - if (p.name === 'is' && p.value) { - if (p.value.content.startsWith('vue:')) { - return true; - } - else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) { - return true; - } - } - } - else { - // directive - // v-is (TODO Deprecate) - if (p.name === 'is') { - return true; - } - else if ( - // :is on plain element - only treat as component in compat mode - p.name === 'bind' && - isStaticArgOf(p.arg, 'is') && - true && - checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) { - return true; - } - } - } -} -function parseAttributes(context, type) { - const props = []; - const attributeNames = new Set(); - while (context.source.length > 0 && - !startsWith(context.source, '>') && - !startsWith(context.source, '/>')) { - if (startsWith(context.source, '/')) { - emitError(context, 22 /* UNEXPECTED_SOLIDUS_IN_TAG */); - advanceBy(context, 1); - advanceSpaces(context); - continue; - } - if (type === 1 /* End */) { - emitError(context, 3 /* END_TAG_WITH_ATTRIBUTES */); - } - const attr = parseAttribute(context, attributeNames); - // Trim whitespace between class - // https://github.com/vuejs/core/issues/4251 - if (attr.type === 6 /* ATTRIBUTE */ && - attr.value && - attr.name === 'class') { - attr.value.content = attr.value.content.replace(/\s+/g, ' ').trim(); - } - if (type === 0 /* Start */) { - props.push(attr); - } - if (/^[^\t\r\n\f />]/.test(context.source)) { - emitError(context, 15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */); - } - advanceSpaces(context); - } - return props; -} -function parseAttribute(context, nameSet) { - // Name. - const start = getCursor(context); - const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source); - const name = match[0]; - if (nameSet.has(name)) { - emitError(context, 2 /* DUPLICATE_ATTRIBUTE */); - } - nameSet.add(name); - if (name[0] === '=') { - emitError(context, 19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */); - } - { - const pattern = /["'<]/g; - let m; - while ((m = pattern.exec(name))) { - emitError(context, 17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index); - } - } - advanceBy(context, name.length); - // Value - let value = undefined; - if (/^[\t\r\n\f ]*=/.test(context.source)) { - advanceSpaces(context); - advanceBy(context, 1); - advanceSpaces(context); - value = parseAttributeValue(context); - if (!value) { - emitError(context, 13 /* MISSING_ATTRIBUTE_VALUE */); - } - } - const loc = getSelection(context, start); - if (!context.inVPre && /^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) { - const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name); - let isPropShorthand = startsWith(name, '.'); - let dirName = match[1] || - (isPropShorthand || startsWith(name, ':') - ? 'bind' - : startsWith(name, '@') - ? 'on' - : 'slot'); - let arg; - if (match[2]) { - const isSlot = dirName === 'slot'; - const startOffset = name.lastIndexOf(match[2]); - const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length)); - let content = match[2]; - let isStatic = true; - if (content.startsWith('[')) { - isStatic = false; - if (!content.endsWith(']')) { - emitError(context, 27 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */); - content = content.slice(1); - } - else { - content = content.slice(1, content.length - 1); - } - } - else if (isSlot) { - // #1241 special case for v-slot: vuetify relies extensively on slot - // names containing dots. v-slot doesn't have any modifiers and Vue 2.x - // supports such usage so we are keeping it consistent with 2.x. - content += match[3] || ''; - } - arg = { - type: 4 /* SIMPLE_EXPRESSION */, - content, - isStatic, - constType: isStatic - ? 3 /* CAN_STRINGIFY */ - : 0 /* NOT_CONSTANT */, - loc - }; - } - if (value && value.isQuoted) { - const valueLoc = value.loc; - valueLoc.start.offset++; - valueLoc.start.column++; - valueLoc.end = advancePositionWithClone(valueLoc.start, value.content); - valueLoc.source = valueLoc.source.slice(1, -1); - } - const modifiers = match[3] ? match[3].slice(1).split('.') : []; - if (isPropShorthand) - modifiers.push('prop'); - // 2.x compat v-bind:foo.sync -> v-model:foo - if (dirName === 'bind' && arg) { - if (modifiers.includes('sync') && - checkCompatEnabled("COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */, context, loc, arg.loc.source)) { - dirName = 'model'; - modifiers.splice(modifiers.indexOf('sync'), 1); - } - if ((process.env.NODE_ENV !== 'production') && modifiers.includes('prop')) { - checkCompatEnabled("COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */, context, loc); - } - } - return { - type: 7 /* DIRECTIVE */, - name: dirName, - exp: value && { - type: 4 /* SIMPLE_EXPRESSION */, - content: value.content, - isStatic: false, - // Treat as non-constant by default. This can be potentially set to - // other values by `transformExpression` to make it eligible for hoisting. - constType: 0 /* NOT_CONSTANT */, - loc: value.loc - }, - arg, - modifiers, - loc - }; - } - // missing directive name or illegal directive name - if (!context.inVPre && startsWith(name, 'v-')) { - emitError(context, 26 /* X_MISSING_DIRECTIVE_NAME */); - } - return { - type: 6 /* ATTRIBUTE */, - name, - value: value && { - type: 2 /* TEXT */, - content: value.content, - loc: value.loc - }, - loc - }; -} -function parseAttributeValue(context) { - const start = getCursor(context); - let content; - const quote = context.source[0]; - const isQuoted = quote === `"` || quote === `'`; - if (isQuoted) { - // Quoted value. - advanceBy(context, 1); - const endIndex = context.source.indexOf(quote); - if (endIndex === -1) { - content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */); - } - else { - content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */); - advanceBy(context, 1); - } - } - else { - // Unquoted - const match = /^[^\t\r\n\f >]+/.exec(context.source); - if (!match) { - return undefined; - } - const unexpectedChars = /["'<=`]/g; - let m; - while ((m = unexpectedChars.exec(match[0]))) { - emitError(context, 18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index); - } - content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */); - } - return { content, isQuoted, loc: getSelection(context, start) }; -} -function parseInterpolation(context, mode) { - const [open, close] = context.options.delimiters; - const closeIndex = context.source.indexOf(close, open.length); - if (closeIndex === -1) { - emitError(context, 25 /* X_MISSING_INTERPOLATION_END */); - return undefined; - } - const start = getCursor(context); - advanceBy(context, open.length); - const innerStart = getCursor(context); - const innerEnd = getCursor(context); - const rawContentLength = closeIndex - open.length; - const rawContent = context.source.slice(0, rawContentLength); - const preTrimContent = parseTextData(context, rawContentLength, mode); - const content = preTrimContent.trim(); - const startOffset = preTrimContent.indexOf(content); - if (startOffset > 0) { - advancePositionWithMutation(innerStart, rawContent, startOffset); - } - const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset); - advancePositionWithMutation(innerEnd, rawContent, endOffset); - advanceBy(context, close.length); - return { - type: 5 /* INTERPOLATION */, - content: { - type: 4 /* SIMPLE_EXPRESSION */, - isStatic: false, - // Set `isConstant` to false by default and will decide in transformExpression - constType: 0 /* NOT_CONSTANT */, - content, - loc: getSelection(context, innerStart, innerEnd) - }, - loc: getSelection(context, start) - }; -} -function parseText(context, mode) { - const endTokens = mode === 3 /* CDATA */ ? [']]>'] : ['<', context.options.delimiters[0]]; - let endIndex = context.source.length; - for (let i = 0; i < endTokens.length; i++) { - const index = context.source.indexOf(endTokens[i], 1); - if (index !== -1 && endIndex > index) { - endIndex = index; - } - } - const start = getCursor(context); - const content = parseTextData(context, endIndex, mode); - return { - type: 2 /* TEXT */, - content, - loc: getSelection(context, start) - }; -} -/** - * Get text data with a given length from the current location. - * This translates HTML entities in the text data. - */ -function parseTextData(context, length, mode) { - const rawText = context.source.slice(0, length); - advanceBy(context, length); - if (mode === 2 /* RAWTEXT */ || - mode === 3 /* CDATA */ || - !rawText.includes('&')) { - return rawText; - } - else { - // DATA or RCDATA containing "&"". Entity decoding required. - return context.options.decodeEntities(rawText, mode === 4 /* ATTRIBUTE_VALUE */); - } -} -function getCursor(context) { - const { column, line, offset } = context; - return { column, line, offset }; -} -function getSelection(context, start, end) { - end = end || getCursor(context); - return { - start, - end, - source: context.originalSource.slice(start.offset, end.offset) - }; -} -function last(xs) { - return xs[xs.length - 1]; -} -function startsWith(source, searchString) { - return source.startsWith(searchString); -} -function advanceBy(context, numberOfCharacters) { - const { source } = context; - advancePositionWithMutation(context, source, numberOfCharacters); - context.source = source.slice(numberOfCharacters); -} -function advanceSpaces(context) { - const match = /^[\t\r\n\f ]+/.exec(context.source); - if (match) { - advanceBy(context, match[0].length); - } -} -function getNewPosition(context, start, numberOfCharacters) { - return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters); -} -function emitError(context, code, offset, loc = getCursor(context)) { - if (offset) { - loc.offset += offset; - loc.column += offset; - } - context.options.onError(createCompilerError(code, { - start: loc, - end: loc, - source: '' - })); -} -function isEnd(context, mode, ancestors) { - const s = context.source; - switch (mode) { - case 0 /* DATA */: - if (startsWith(s, '</')) { - // TODO: probably bad performance - for (let i = ancestors.length - 1; i >= 0; --i) { - if (startsWithEndTagOpen(s, ancestors[i].tag)) { - return true; - } - } - } - break; - case 1 /* RCDATA */: - case 2 /* RAWTEXT */: { - const parent = last(ancestors); - if (parent && startsWithEndTagOpen(s, parent.tag)) { - return true; - } - break; - } - case 3 /* CDATA */: - if (startsWith(s, ']]>')) { - return true; - } - break; - } - return !s; -} -function startsWithEndTagOpen(source, tag) { - return (startsWith(source, '</') && - source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase() && - /[\t\r\n\f />]/.test(source[2 + tag.length] || '>')); +// The default decoder only provides escapes for characters reserved as part of +// the template syntax, and is only used if the custom renderer did not provide +// a platform-specific decoder. +const decodeRE = /&(gt|lt|amp|apos|quot);/g; +const decodeMap = { + gt: '>', + lt: '<', + amp: '&', + apos: "'", + quot: '"' +}; +const defaultParserOptions = { + delimiters: [`{{`, `}}`], + getNamespace: () => 0 /* HTML */, + getTextMode: () => 0 /* DATA */, + isVoidTag: NO, + isPreTag: NO, + isCustomElement: NO, + decodeEntities: (rawText) => rawText.replace(decodeRE, (_, p1) => decodeMap[p1]), + onError: defaultOnError, + onWarn: defaultOnWarn, + comments: (process.env.NODE_ENV !== 'production') +}; +function baseParse(content, options = {}) { + const context = createParserContext(content, options); + const start = getCursor(context); + return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start)); +} +function createParserContext(content, rawOptions) { + const options = extend({}, defaultParserOptions); + let key; + for (key in rawOptions) { + // @ts-ignore + options[key] = + rawOptions[key] === undefined + ? defaultParserOptions[key] + : rawOptions[key]; + } + return { + options, + column: 1, + line: 1, + offset: 0, + originalSource: content, + source: content, + inPre: false, + inVPre: false, + onWarn: options.onWarn + }; +} +function parseChildren(context, mode, ancestors) { + const parent = last(ancestors); + const ns = parent ? parent.ns : 0 /* HTML */; + const nodes = []; + while (!isEnd(context, mode, ancestors)) { + const s = context.source; + let node = undefined; + if (mode === 0 /* DATA */ || mode === 1 /* RCDATA */) { + if (!context.inVPre && startsWith(s, context.options.delimiters[0])) { + // '{{' + node = parseInterpolation(context, mode); + } + else if (mode === 0 /* DATA */ && s[0] === '<') { + // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state + if (s.length === 1) { + emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 1); + } + else if (s[1] === '!') { + // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state + if (startsWith(s, '<!--')) { + node = parseComment(context); + } + else if (startsWith(s, '<!DOCTYPE')) { + // Ignore DOCTYPE by a limitation. + node = parseBogusComment(context); + } + else if (startsWith(s, '<![CDATA[')) { + if (ns !== 0 /* HTML */) { + node = parseCDATA(context, ancestors); + } + else { + emitError(context, 1 /* CDATA_IN_HTML_CONTENT */); + node = parseBogusComment(context); + } + } + else { + emitError(context, 11 /* INCORRECTLY_OPENED_COMMENT */); + node = parseBogusComment(context); + } + } + else if (s[1] === '/') { + // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state + if (s.length === 2) { + emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 2); + } + else if (s[2] === '>') { + emitError(context, 14 /* MISSING_END_TAG_NAME */, 2); + advanceBy(context, 3); + continue; + } + else if (/[a-z]/i.test(s[2])) { + emitError(context, 23 /* X_INVALID_END_TAG */); + parseTag(context, 1 /* End */, parent); + continue; + } + else { + emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2); + node = parseBogusComment(context); + } + } + else if (/[a-z]/i.test(s[1])) { + node = parseElement(context, ancestors); + // 2.x <template> with no directive compat + if (isCompatEnabled("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context) && + node && + node.tag === 'template' && + !node.props.some(p => p.type === 7 /* DIRECTIVE */ && + isSpecialTemplateDirective(p.name))) { + (process.env.NODE_ENV !== 'production') && + warnDeprecation("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context, node.loc); + node = node.children; + } + } + else if (s[1] === '?') { + emitError(context, 21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1); + node = parseBogusComment(context); + } + else { + emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1); + } + } + } + if (!node) { + node = parseText(context, mode); + } + if (isArray(node)) { + for (let i = 0; i < node.length; i++) { + pushNode(nodes, node[i]); + } + } + else { + pushNode(nodes, node); + } + } + // Whitespace handling strategy like v2 + let removedWhitespace = false; + if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) { + const shouldCondense = context.options.whitespace !== 'preserve'; + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + if (!context.inPre && node.type === 2 /* TEXT */) { + if (!/[^\t\r\n\f ]/.test(node.content)) { + const prev = nodes[i - 1]; + const next = nodes[i + 1]; + // Remove if: + // - the whitespace is the first or last node, or: + // - (condense mode) the whitespace is adjacent to a comment, or: + // - (condense mode) the whitespace is between two elements AND contains newline + if (!prev || + !next || + (shouldCondense && + (prev.type === 3 /* COMMENT */ || + next.type === 3 /* COMMENT */ || + (prev.type === 1 /* ELEMENT */ && + next.type === 1 /* ELEMENT */ && + /[\r\n]/.test(node.content))))) { + removedWhitespace = true; + nodes[i] = null; + } + else { + // Otherwise, the whitespace is condensed into a single space + node.content = ' '; + } + } + else if (shouldCondense) { + // in condense mode, consecutive whitespaces in text are condensed + // down to a single space. + node.content = node.content.replace(/[\t\r\n\f ]+/g, ' '); + } + } + // Remove comment nodes if desired by configuration. + else if (node.type === 3 /* COMMENT */ && !context.options.comments) { + removedWhitespace = true; + nodes[i] = null; + } + } + if (context.inPre && parent && context.options.isPreTag(parent.tag)) { + // remove leading newline per html spec + // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element + const first = nodes[0]; + if (first && first.type === 2 /* TEXT */) { + first.content = first.content.replace(/^\r?\n/, ''); + } + } + } + return removedWhitespace ? nodes.filter(Boolean) : nodes; +} +function pushNode(nodes, node) { + if (node.type === 2 /* TEXT */) { + const prev = last(nodes); + // Merge if both this and the previous node are text and those are + // consecutive. This happens for cases like "a < b". + if (prev && + prev.type === 2 /* TEXT */ && + prev.loc.end.offset === node.loc.start.offset) { + prev.content += node.content; + prev.loc.end = node.loc.end; + prev.loc.source += node.loc.source; + return; + } + } + nodes.push(node); +} +function parseCDATA(context, ancestors) { + advanceBy(context, 9); + const nodes = parseChildren(context, 3 /* CDATA */, ancestors); + if (context.source.length === 0) { + emitError(context, 6 /* EOF_IN_CDATA */); + } + else { + advanceBy(context, 3); + } + return nodes; +} +function parseComment(context) { + const start = getCursor(context); + let content; + // Regular comment. + const match = /--(\!)?>/.exec(context.source); + if (!match) { + content = context.source.slice(4); + advanceBy(context, context.source.length); + emitError(context, 7 /* EOF_IN_COMMENT */); + } + else { + if (match.index <= 3) { + emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */); + } + if (match[1]) { + emitError(context, 10 /* INCORRECTLY_CLOSED_COMMENT */); + } + content = context.source.slice(4, match.index); + // Advancing with reporting nested comments. + const s = context.source.slice(0, match.index); + let prevIndex = 1, nestedIndex = 0; + while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) { + advanceBy(context, nestedIndex - prevIndex + 1); + if (nestedIndex + 4 < s.length) { + emitError(context, 16 /* NESTED_COMMENT */); + } + prevIndex = nestedIndex + 1; + } + advanceBy(context, match.index + match[0].length - prevIndex + 1); + } + return { + type: 3 /* COMMENT */, + content, + loc: getSelection(context, start) + }; +} +function parseBogusComment(context) { + const start = getCursor(context); + const contentStart = context.source[1] === '?' ? 1 : 2; + let content; + const closeIndex = context.source.indexOf('>'); + if (closeIndex === -1) { + content = context.source.slice(contentStart); + advanceBy(context, context.source.length); + } + else { + content = context.source.slice(contentStart, closeIndex); + advanceBy(context, closeIndex + 1); + } + return { + type: 3 /* COMMENT */, + content, + loc: getSelection(context, start) + }; +} +function parseElement(context, ancestors) { + // Start tag. + const wasInPre = context.inPre; + const wasInVPre = context.inVPre; + const parent = last(ancestors); + const element = parseTag(context, 0 /* Start */, parent); + const isPreBoundary = context.inPre && !wasInPre; + const isVPreBoundary = context.inVPre && !wasInVPre; + if (element.isSelfClosing || context.options.isVoidTag(element.tag)) { + // #4030 self-closing <pre> tag + if (isPreBoundary) { + context.inPre = false; + } + if (isVPreBoundary) { + context.inVPre = false; + } + return element; + } + // Children. + ancestors.push(element); + const mode = context.options.getTextMode(element, parent); + const children = parseChildren(context, mode, ancestors); + ancestors.pop(); + // 2.x inline-template compat + { + const inlineTemplateProp = element.props.find(p => p.type === 6 /* ATTRIBUTE */ && p.name === 'inline-template'); + if (inlineTemplateProp && + checkCompatEnabled("COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */, context, inlineTemplateProp.loc)) { + const loc = getSelection(context, element.loc.end); + inlineTemplateProp.value = { + type: 2 /* TEXT */, + content: loc.source, + loc + }; + } + } + element.children = children; + // End tag. + if (startsWithEndTagOpen(context.source, element.tag)) { + parseTag(context, 1 /* End */, parent); + } + else { + emitError(context, 24 /* X_MISSING_END_TAG */, 0, element.loc.start); + if (context.source.length === 0 && element.tag.toLowerCase() === 'script') { + const first = children[0]; + if (first && startsWith(first.loc.source, '<!--')) { + emitError(context, 8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */); + } + } + } + element.loc = getSelection(context, element.loc.start); + if (isPreBoundary) { + context.inPre = false; + } + if (isVPreBoundary) { + context.inVPre = false; + } + return element; +} +const isSpecialTemplateDirective = /*#__PURE__*/ makeMap(`if,else,else-if,for,slot`); +function parseTag(context, type, parent) { + // Tag open. + const start = getCursor(context); + const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source); + const tag = match[1]; + const ns = context.options.getNamespace(tag, parent); + advanceBy(context, match[0].length); + advanceSpaces(context); + // save current state in case we need to re-parse attributes with v-pre + const cursor = getCursor(context); + const currentSource = context.source; + // check <pre> tag + if (context.options.isPreTag(tag)) { + context.inPre = true; + } + // Attributes. + let props = parseAttributes(context, type); + // check v-pre + if (type === 0 /* Start */ && + !context.inVPre && + props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) { + context.inVPre = true; + // reset context + extend(context, cursor); + context.source = currentSource; + // re-parse attrs and filter out v-pre itself + props = parseAttributes(context, type).filter(p => p.name !== 'v-pre'); + } + // Tag close. + let isSelfClosing = false; + if (context.source.length === 0) { + emitError(context, 9 /* EOF_IN_TAG */); + } + else { + isSelfClosing = startsWith(context.source, '/>'); + if (type === 1 /* End */ && isSelfClosing) { + emitError(context, 4 /* END_TAG_WITH_TRAILING_SOLIDUS */); + } + advanceBy(context, isSelfClosing ? 2 : 1); + } + if (type === 1 /* End */) { + return; + } + // 2.x deprecation checks + if ((process.env.NODE_ENV !== 'production') && + isCompatEnabled("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context)) { + let hasIf = false; + let hasFor = false; + for (let i = 0; i < props.length; i++) { + const p = props[i]; + if (p.type === 7 /* DIRECTIVE */) { + if (p.name === 'if') { + hasIf = true; + } + else if (p.name === 'for') { + hasFor = true; + } + } + if (hasIf && hasFor) { + warnDeprecation("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context, getSelection(context, start)); + break; + } + } + } + let tagType = 0 /* ELEMENT */; + if (!context.inVPre) { + if (tag === 'slot') { + tagType = 2 /* SLOT */; + } + else if (tag === 'template') { + if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) { + tagType = 3 /* TEMPLATE */; + } + } + else if (isComponent(tag, props, context)) { + tagType = 1 /* COMPONENT */; + } + } + return { + type: 1 /* ELEMENT */, + ns, + tag, + tagType, + props, + isSelfClosing, + children: [], + loc: getSelection(context, start), + codegenNode: undefined // to be created during transform phase + }; +} +function isComponent(tag, props, context) { + const options = context.options; + if (options.isCustomElement(tag)) { + return false; + } + if (tag === 'component' || + /^[A-Z]/.test(tag) || + isCoreComponent(tag) || + (options.isBuiltInComponent && options.isBuiltInComponent(tag)) || + (options.isNativeTag && !options.isNativeTag(tag))) { + return true; + } + // at this point the tag should be a native tag, but check for potential "is" + // casting + for (let i = 0; i < props.length; i++) { + const p = props[i]; + if (p.type === 6 /* ATTRIBUTE */) { + if (p.name === 'is' && p.value) { + if (p.value.content.startsWith('vue:')) { + return true; + } + else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) { + return true; + } + } + } + else { + // directive + // v-is (TODO Deprecate) + if (p.name === 'is') { + return true; + } + else if ( + // :is on plain element - only treat as component in compat mode + p.name === 'bind' && + isStaticArgOf(p.arg, 'is') && + true && + checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) { + return true; + } + } + } +} +function parseAttributes(context, type) { + const props = []; + const attributeNames = new Set(); + while (context.source.length > 0 && + !startsWith(context.source, '>') && + !startsWith(context.source, '/>')) { + if (startsWith(context.source, '/')) { + emitError(context, 22 /* UNEXPECTED_SOLIDUS_IN_TAG */); + advanceBy(context, 1); + advanceSpaces(context); + continue; + } + if (type === 1 /* End */) { + emitError(context, 3 /* END_TAG_WITH_ATTRIBUTES */); + } + const attr = parseAttribute(context, attributeNames); + // Trim whitespace between class + // https://github.com/vuejs/core/issues/4251 + if (attr.type === 6 /* ATTRIBUTE */ && + attr.value && + attr.name === 'class') { + attr.value.content = attr.value.content.replace(/\s+/g, ' ').trim(); + } + if (type === 0 /* Start */) { + props.push(attr); + } + if (/^[^\t\r\n\f />]/.test(context.source)) { + emitError(context, 15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */); + } + advanceSpaces(context); + } + return props; +} +function parseAttribute(context, nameSet) { + // Name. + const start = getCursor(context); + const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source); + const name = match[0]; + if (nameSet.has(name)) { + emitError(context, 2 /* DUPLICATE_ATTRIBUTE */); + } + nameSet.add(name); + if (name[0] === '=') { + emitError(context, 19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */); + } + { + const pattern = /["'<]/g; + let m; + while ((m = pattern.exec(name))) { + emitError(context, 17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index); + } + } + advanceBy(context, name.length); + // Value + let value = undefined; + if (/^[\t\r\n\f ]*=/.test(context.source)) { + advanceSpaces(context); + advanceBy(context, 1); + advanceSpaces(context); + value = parseAttributeValue(context); + if (!value) { + emitError(context, 13 /* MISSING_ATTRIBUTE_VALUE */); + } + } + const loc = getSelection(context, start); + if (!context.inVPre && /^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) { + const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name); + let isPropShorthand = startsWith(name, '.'); + let dirName = match[1] || + (isPropShorthand || startsWith(name, ':') + ? 'bind' + : startsWith(name, '@') + ? 'on' + : 'slot'); + let arg; + if (match[2]) { + const isSlot = dirName === 'slot'; + const startOffset = name.lastIndexOf(match[2]); + const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length)); + let content = match[2]; + let isStatic = true; + if (content.startsWith('[')) { + isStatic = false; + if (!content.endsWith(']')) { + emitError(context, 27 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */); + content = content.slice(1); + } + else { + content = content.slice(1, content.length - 1); + } + } + else if (isSlot) { + // #1241 special case for v-slot: vuetify relies extensively on slot + // names containing dots. v-slot doesn't have any modifiers and Vue 2.x + // supports such usage so we are keeping it consistent with 2.x. + content += match[3] || ''; + } + arg = { + type: 4 /* SIMPLE_EXPRESSION */, + content, + isStatic, + constType: isStatic + ? 3 /* CAN_STRINGIFY */ + : 0 /* NOT_CONSTANT */, + loc + }; + } + if (value && value.isQuoted) { + const valueLoc = value.loc; + valueLoc.start.offset++; + valueLoc.start.column++; + valueLoc.end = advancePositionWithClone(valueLoc.start, value.content); + valueLoc.source = valueLoc.source.slice(1, -1); + } + const modifiers = match[3] ? match[3].slice(1).split('.') : []; + if (isPropShorthand) + modifiers.push('prop'); + // 2.x compat v-bind:foo.sync -> v-model:foo + if (dirName === 'bind' && arg) { + if (modifiers.includes('sync') && + checkCompatEnabled("COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */, context, loc, arg.loc.source)) { + dirName = 'model'; + modifiers.splice(modifiers.indexOf('sync'), 1); + } + if ((process.env.NODE_ENV !== 'production') && modifiers.includes('prop')) { + checkCompatEnabled("COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */, context, loc); + } + } + return { + type: 7 /* DIRECTIVE */, + name: dirName, + exp: value && { + type: 4 /* SIMPLE_EXPRESSION */, + content: value.content, + isStatic: false, + // Treat as non-constant by default. This can be potentially set to + // other values by `transformExpression` to make it eligible for hoisting. + constType: 0 /* NOT_CONSTANT */, + loc: value.loc + }, + arg, + modifiers, + loc + }; + } + // missing directive name or illegal directive name + if (!context.inVPre && startsWith(name, 'v-')) { + emitError(context, 26 /* X_MISSING_DIRECTIVE_NAME */); + } + return { + type: 6 /* ATTRIBUTE */, + name, + value: value && { + type: 2 /* TEXT */, + content: value.content, + loc: value.loc + }, + loc + }; +} +function parseAttributeValue(context) { + const start = getCursor(context); + let content; + const quote = context.source[0]; + const isQuoted = quote === `"` || quote === `'`; + if (isQuoted) { + // Quoted value. + advanceBy(context, 1); + const endIndex = context.source.indexOf(quote); + if (endIndex === -1) { + content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */); + } + else { + content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */); + advanceBy(context, 1); + } + } + else { + // Unquoted + const match = /^[^\t\r\n\f >]+/.exec(context.source); + if (!match) { + return undefined; + } + const unexpectedChars = /["'<=`]/g; + let m; + while ((m = unexpectedChars.exec(match[0]))) { + emitError(context, 18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index); + } + content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */); + } + return { content, isQuoted, loc: getSelection(context, start) }; +} +function parseInterpolation(context, mode) { + const [open, close] = context.options.delimiters; + const closeIndex = context.source.indexOf(close, open.length); + if (closeIndex === -1) { + emitError(context, 25 /* X_MISSING_INTERPOLATION_END */); + return undefined; + } + const start = getCursor(context); + advanceBy(context, open.length); + const innerStart = getCursor(context); + const innerEnd = getCursor(context); + const rawContentLength = closeIndex - open.length; + const rawContent = context.source.slice(0, rawContentLength); + const preTrimContent = parseTextData(context, rawContentLength, mode); + const content = preTrimContent.trim(); + const startOffset = preTrimContent.indexOf(content); + if (startOffset > 0) { + advancePositionWithMutation(innerStart, rawContent, startOffset); + } + const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset); + advancePositionWithMutation(innerEnd, rawContent, endOffset); + advanceBy(context, close.length); + return { + type: 5 /* INTERPOLATION */, + content: { + type: 4 /* SIMPLE_EXPRESSION */, + isStatic: false, + // Set `isConstant` to false by default and will decide in transformExpression + constType: 0 /* NOT_CONSTANT */, + content, + loc: getSelection(context, innerStart, innerEnd) + }, + loc: getSelection(context, start) + }; +} +function parseText(context, mode) { + const endTokens = mode === 3 /* CDATA */ ? [']]>'] : ['<', context.options.delimiters[0]]; + let endIndex = context.source.length; + for (let i = 0; i < endTokens.length; i++) { + const index = context.source.indexOf(endTokens[i], 1); + if (index !== -1 && endIndex > index) { + endIndex = index; + } + } + const start = getCursor(context); + const content = parseTextData(context, endIndex, mode); + return { + type: 2 /* TEXT */, + content, + loc: getSelection(context, start) + }; +} +/** + * Get text data with a given length from the current location. + * This translates HTML entities in the text data. + */ +function parseTextData(context, length, mode) { + const rawText = context.source.slice(0, length); + advanceBy(context, length); + if (mode === 2 /* RAWTEXT */ || + mode === 3 /* CDATA */ || + !rawText.includes('&')) { + return rawText; + } + else { + // DATA or RCDATA containing "&"". Entity decoding required. + return context.options.decodeEntities(rawText, mode === 4 /* ATTRIBUTE_VALUE */); + } +} +function getCursor(context) { + const { column, line, offset } = context; + return { column, line, offset }; +} +function getSelection(context, start, end) { + end = end || getCursor(context); + return { + start, + end, + source: context.originalSource.slice(start.offset, end.offset) + }; +} +function last(xs) { + return xs[xs.length - 1]; +} +function startsWith(source, searchString) { + return source.startsWith(searchString); +} +function advanceBy(context, numberOfCharacters) { + const { source } = context; + advancePositionWithMutation(context, source, numberOfCharacters); + context.source = source.slice(numberOfCharacters); +} +function advanceSpaces(context) { + const match = /^[\t\r\n\f ]+/.exec(context.source); + if (match) { + advanceBy(context, match[0].length); + } +} +function getNewPosition(context, start, numberOfCharacters) { + return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters); +} +function emitError(context, code, offset, loc = getCursor(context)) { + if (offset) { + loc.offset += offset; + loc.column += offset; + } + context.options.onError(createCompilerError(code, { + start: loc, + end: loc, + source: '' + })); +} +function isEnd(context, mode, ancestors) { + const s = context.source; + switch (mode) { + case 0 /* DATA */: + if (startsWith(s, '</')) { + // TODO: probably bad performance + for (let i = ancestors.length - 1; i >= 0; --i) { + if (startsWithEndTagOpen(s, ancestors[i].tag)) { + return true; + } + } + } + break; + case 1 /* RCDATA */: + case 2 /* RAWTEXT */: { + const parent = last(ancestors); + if (parent && startsWithEndTagOpen(s, parent.tag)) { + return true; + } + break; + } + case 3 /* CDATA */: + if (startsWith(s, ']]>')) { + return true; + } + break; + } + return !s; +} +function startsWithEndTagOpen(source, tag) { + return (startsWith(source, '</') && + source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase() && + /[\t\r\n\f />]/.test(source[2 + tag.length] || '>')); } -function hoistStatic(root, context) { - walk(root, context, - // Root node is unfortunately non-hoistable due to potential parent - // fallthrough attributes. - isSingleElementRoot(root, root.children[0])); -} -function isSingleElementRoot(root, child) { - const { children } = root; - return (children.length === 1 && - child.type === 1 /* ELEMENT */ && - !isSlotOutlet(child)); -} -function walk(node, context, doNotHoistNode = false) { - const { children } = node; - const originalCount = children.length; - let hoistedCount = 0; - for (let i = 0; i < children.length; i++) { - const child = children[i]; - // only plain elements & text calls are eligible for hoisting. - if (child.type === 1 /* ELEMENT */ && - child.tagType === 0 /* ELEMENT */) { - const constantType = doNotHoistNode - ? 0 /* NOT_CONSTANT */ - : getConstantType(child, context); - if (constantType > 0 /* NOT_CONSTANT */) { - if (constantType >= 2 /* CAN_HOIST */) { - child.codegenNode.patchFlag = - -1 /* HOISTED */ + ((process.env.NODE_ENV !== 'production') ? ` /* HOISTED */` : ``); - child.codegenNode = context.hoist(child.codegenNode); - hoistedCount++; - continue; - } - } - else { - // node may contain dynamic children, but its props may be eligible for - // hoisting. - const codegenNode = child.codegenNode; - if (codegenNode.type === 13 /* VNODE_CALL */) { - const flag = getPatchFlag(codegenNode); - if ((!flag || - flag === 512 /* NEED_PATCH */ || - flag === 1 /* TEXT */) && - getGeneratedPropsConstantType(child, context) >= - 2 /* CAN_HOIST */) { - const props = getNodeProps(child); - if (props) { - codegenNode.props = context.hoist(props); - } - } - if (codegenNode.dynamicProps) { - codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps); - } - } - } - } - else if (child.type === 12 /* TEXT_CALL */ && - getConstantType(child.content, context) >= 2 /* CAN_HOIST */) { - child.codegenNode = context.hoist(child.codegenNode); - hoistedCount++; - } - // walk further - if (child.type === 1 /* ELEMENT */) { - const isComponent = child.tagType === 1 /* COMPONENT */; - if (isComponent) { - context.scopes.vSlot++; - } - walk(child, context); - if (isComponent) { - context.scopes.vSlot--; - } - } - else if (child.type === 11 /* FOR */) { - // Do not hoist v-for single child because it has to be a block - walk(child, context, child.children.length === 1); - } - else if (child.type === 9 /* IF */) { - for (let i = 0; i < child.branches.length; i++) { - // Do not hoist v-if single child because it has to be a block - walk(child.branches[i], context, child.branches[i].children.length === 1); - } - } - } - if (hoistedCount && context.transformHoist) { - context.transformHoist(children, context, node); - } - // all children were hoisted - the entire children array is hoistable. - if (hoistedCount && - hoistedCount === originalCount && - node.type === 1 /* ELEMENT */ && - node.tagType === 0 /* ELEMENT */ && - node.codegenNode && - node.codegenNode.type === 13 /* VNODE_CALL */ && - isArray(node.codegenNode.children)) { - node.codegenNode.children = context.hoist(createArrayExpression(node.codegenNode.children)); - } -} -function getConstantType(node, context) { - const { constantCache } = context; - switch (node.type) { - case 1 /* ELEMENT */: - if (node.tagType !== 0 /* ELEMENT */) { - return 0 /* NOT_CONSTANT */; - } - const cached = constantCache.get(node); - if (cached !== undefined) { - return cached; - } - const codegenNode = node.codegenNode; - if (codegenNode.type !== 13 /* VNODE_CALL */) { - return 0 /* NOT_CONSTANT */; - } - if (codegenNode.isBlock && - node.tag !== 'svg' && - node.tag !== 'foreignObject') { - return 0 /* NOT_CONSTANT */; - } - const flag = getPatchFlag(codegenNode); - if (!flag) { - let returnType = 3 /* CAN_STRINGIFY */; - // Element itself has no patch flag. However we still need to check: - // 1. Even for a node with no patch flag, it is possible for it to contain - // non-hoistable expressions that refers to scope variables, e.g. compiler - // injected keys or cached event handlers. Therefore we need to always - // check the codegenNode's props to be sure. - const generatedPropsType = getGeneratedPropsConstantType(node, context); - if (generatedPropsType === 0 /* NOT_CONSTANT */) { - constantCache.set(node, 0 /* NOT_CONSTANT */); - return 0 /* NOT_CONSTANT */; - } - if (generatedPropsType < returnType) { - returnType = generatedPropsType; - } - // 2. its children. - for (let i = 0; i < node.children.length; i++) { - const childType = getConstantType(node.children[i], context); - if (childType === 0 /* NOT_CONSTANT */) { - constantCache.set(node, 0 /* NOT_CONSTANT */); - return 0 /* NOT_CONSTANT */; - } - if (childType < returnType) { - returnType = childType; - } - } - // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-0 - // type, check if any of the props can cause the type to be lowered - // we can skip can_patch because it's guaranteed by the absence of a - // patchFlag. - if (returnType > 1 /* CAN_SKIP_PATCH */) { - for (let i = 0; i < node.props.length; i++) { - const p = node.props[i]; - if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind' && p.exp) { - const expType = getConstantType(p.exp, context); - if (expType === 0 /* NOT_CONSTANT */) { - constantCache.set(node, 0 /* NOT_CONSTANT */); - return 0 /* NOT_CONSTANT */; - } - if (expType < returnType) { - returnType = expType; - } - } - } - } - // only svg/foreignObject could be block here, however if they are - // static then they don't need to be blocks since there will be no - // nested updates. - if (codegenNode.isBlock) { - // except set custom directives. - for (let i = 0; i < node.props.length; i++) { - const p = node.props[i]; - if (p.type === 7 /* DIRECTIVE */) { - constantCache.set(node, 0 /* NOT_CONSTANT */); - return 0 /* NOT_CONSTANT */; - } - } - context.removeHelper(OPEN_BLOCK); - context.removeHelper(getVNodeBlockHelper(context.inSSR, codegenNode.isComponent)); - codegenNode.isBlock = false; - context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent)); - } - constantCache.set(node, returnType); - return returnType; - } - else { - constantCache.set(node, 0 /* NOT_CONSTANT */); - return 0 /* NOT_CONSTANT */; - } - case 2 /* TEXT */: - case 3 /* COMMENT */: - return 3 /* CAN_STRINGIFY */; - case 9 /* IF */: - case 11 /* FOR */: - case 10 /* IF_BRANCH */: - return 0 /* NOT_CONSTANT */; - case 5 /* INTERPOLATION */: - case 12 /* TEXT_CALL */: - return getConstantType(node.content, context); - case 4 /* SIMPLE_EXPRESSION */: - return node.constType; - case 8 /* COMPOUND_EXPRESSION */: - let returnType = 3 /* CAN_STRINGIFY */; - for (let i = 0; i < node.children.length; i++) { - const child = node.children[i]; - if (isString(child) || isSymbol(child)) { - continue; - } - const childType = getConstantType(child, context); - if (childType === 0 /* NOT_CONSTANT */) { - return 0 /* NOT_CONSTANT */; - } - else if (childType < returnType) { - returnType = childType; - } - } - return returnType; - default: - if ((process.env.NODE_ENV !== 'production')) ; - return 0 /* NOT_CONSTANT */; - } -} -const allowHoistedHelperSet = new Set([ - NORMALIZE_CLASS, - NORMALIZE_STYLE, - NORMALIZE_PROPS, - GUARD_REACTIVE_PROPS -]); -function getConstantTypeOfHelperCall(value, context) { - if (value.type === 14 /* JS_CALL_EXPRESSION */ && - !isString(value.callee) && - allowHoistedHelperSet.has(value.callee)) { - const arg = value.arguments[0]; - if (arg.type === 4 /* SIMPLE_EXPRESSION */) { - return getConstantType(arg, context); - } - else if (arg.type === 14 /* JS_CALL_EXPRESSION */) { - // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))` - return getConstantTypeOfHelperCall(arg, context); - } - } - return 0 /* NOT_CONSTANT */; -} -function getGeneratedPropsConstantType(node, context) { - let returnType = 3 /* CAN_STRINGIFY */; - const props = getNodeProps(node); - if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) { - const { properties } = props; - for (let i = 0; i < properties.length; i++) { - const { key, value } = properties[i]; - const keyType = getConstantType(key, context); - if (keyType === 0 /* NOT_CONSTANT */) { - return keyType; - } - if (keyType < returnType) { - returnType = keyType; - } - let valueType; - if (value.type === 4 /* SIMPLE_EXPRESSION */) { - valueType = getConstantType(value, context); - } - else if (value.type === 14 /* JS_CALL_EXPRESSION */) { - // some helper calls can be hoisted, - // such as the `normalizeProps` generated by the compiler for pre-normalize class, - // in this case we need to respect the ConstantType of the helper's arguments - valueType = getConstantTypeOfHelperCall(value, context); - } - else { - valueType = 0 /* NOT_CONSTANT */; - } - if (valueType === 0 /* NOT_CONSTANT */) { - return valueType; - } - if (valueType < returnType) { - returnType = valueType; - } - } - } - return returnType; -} -function getNodeProps(node) { - const codegenNode = node.codegenNode; - if (codegenNode.type === 13 /* VNODE_CALL */) { - return codegenNode.props; - } -} -function getPatchFlag(node) { - const flag = node.patchFlag; - return flag ? parseInt(flag, 10) : undefined; +function hoistStatic(root, context) { + walk(root, context, + // Root node is unfortunately non-hoistable due to potential parent + // fallthrough attributes. + isSingleElementRoot(root, root.children[0])); +} +function isSingleElementRoot(root, child) { + const { children } = root; + return (children.length === 1 && + child.type === 1 /* ELEMENT */ && + !isSlotOutlet(child)); +} +function walk(node, context, doNotHoistNode = false) { + const { children } = node; + const originalCount = children.length; + let hoistedCount = 0; + for (let i = 0; i < children.length; i++) { + const child = children[i]; + // only plain elements & text calls are eligible for hoisting. + if (child.type === 1 /* ELEMENT */ && + child.tagType === 0 /* ELEMENT */) { + const constantType = doNotHoistNode + ? 0 /* NOT_CONSTANT */ + : getConstantType(child, context); + if (constantType > 0 /* NOT_CONSTANT */) { + if (constantType >= 2 /* CAN_HOIST */) { + child.codegenNode.patchFlag = + -1 /* HOISTED */ + ((process.env.NODE_ENV !== 'production') ? ` /* HOISTED */` : ``); + child.codegenNode = context.hoist(child.codegenNode); + hoistedCount++; + continue; + } + } + else { + // node may contain dynamic children, but its props may be eligible for + // hoisting. + const codegenNode = child.codegenNode; + if (codegenNode.type === 13 /* VNODE_CALL */) { + const flag = getPatchFlag(codegenNode); + if ((!flag || + flag === 512 /* NEED_PATCH */ || + flag === 1 /* TEXT */) && + getGeneratedPropsConstantType(child, context) >= + 2 /* CAN_HOIST */) { + const props = getNodeProps(child); + if (props) { + codegenNode.props = context.hoist(props); + } + } + if (codegenNode.dynamicProps) { + codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps); + } + } + } + } + else if (child.type === 12 /* TEXT_CALL */ && + getConstantType(child.content, context) >= 2 /* CAN_HOIST */) { + child.codegenNode = context.hoist(child.codegenNode); + hoistedCount++; + } + // walk further + if (child.type === 1 /* ELEMENT */) { + const isComponent = child.tagType === 1 /* COMPONENT */; + if (isComponent) { + context.scopes.vSlot++; + } + walk(child, context); + if (isComponent) { + context.scopes.vSlot--; + } + } + else if (child.type === 11 /* FOR */) { + // Do not hoist v-for single child because it has to be a block + walk(child, context, child.children.length === 1); + } + else if (child.type === 9 /* IF */) { + for (let i = 0; i < child.branches.length; i++) { + // Do not hoist v-if single child because it has to be a block + walk(child.branches[i], context, child.branches[i].children.length === 1); + } + } + } + if (hoistedCount && context.transformHoist) { + context.transformHoist(children, context, node); + } + // all children were hoisted - the entire children array is hoistable. + if (hoistedCount && + hoistedCount === originalCount && + node.type === 1 /* ELEMENT */ && + node.tagType === 0 /* ELEMENT */ && + node.codegenNode && + node.codegenNode.type === 13 /* VNODE_CALL */ && + isArray(node.codegenNode.children)) { + node.codegenNode.children = context.hoist(createArrayExpression(node.codegenNode.children)); + } +} +function getConstantType(node, context) { + const { constantCache } = context; + switch (node.type) { + case 1 /* ELEMENT */: + if (node.tagType !== 0 /* ELEMENT */) { + return 0 /* NOT_CONSTANT */; + } + const cached = constantCache.get(node); + if (cached !== undefined) { + return cached; + } + const codegenNode = node.codegenNode; + if (codegenNode.type !== 13 /* VNODE_CALL */) { + return 0 /* NOT_CONSTANT */; + } + if (codegenNode.isBlock && + node.tag !== 'svg' && + node.tag !== 'foreignObject') { + return 0 /* NOT_CONSTANT */; + } + const flag = getPatchFlag(codegenNode); + if (!flag) { + let returnType = 3 /* CAN_STRINGIFY */; + // Element itself has no patch flag. However we still need to check: + // 1. Even for a node with no patch flag, it is possible for it to contain + // non-hoistable expressions that refers to scope variables, e.g. compiler + // injected keys or cached event handlers. Therefore we need to always + // check the codegenNode's props to be sure. + const generatedPropsType = getGeneratedPropsConstantType(node, context); + if (generatedPropsType === 0 /* NOT_CONSTANT */) { + constantCache.set(node, 0 /* NOT_CONSTANT */); + return 0 /* NOT_CONSTANT */; + } + if (generatedPropsType < returnType) { + returnType = generatedPropsType; + } + // 2. its children. + for (let i = 0; i < node.children.length; i++) { + const childType = getConstantType(node.children[i], context); + if (childType === 0 /* NOT_CONSTANT */) { + constantCache.set(node, 0 /* NOT_CONSTANT */); + return 0 /* NOT_CONSTANT */; + } + if (childType < returnType) { + returnType = childType; + } + } + // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-0 + // type, check if any of the props can cause the type to be lowered + // we can skip can_patch because it's guaranteed by the absence of a + // patchFlag. + if (returnType > 1 /* CAN_SKIP_PATCH */) { + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i]; + if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind' && p.exp) { + const expType = getConstantType(p.exp, context); + if (expType === 0 /* NOT_CONSTANT */) { + constantCache.set(node, 0 /* NOT_CONSTANT */); + return 0 /* NOT_CONSTANT */; + } + if (expType < returnType) { + returnType = expType; + } + } + } + } + // only svg/foreignObject could be block here, however if they are + // static then they don't need to be blocks since there will be no + // nested updates. + if (codegenNode.isBlock) { + // except set custom directives. + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i]; + if (p.type === 7 /* DIRECTIVE */) { + constantCache.set(node, 0 /* NOT_CONSTANT */); + return 0 /* NOT_CONSTANT */; + } + } + context.removeHelper(OPEN_BLOCK); + context.removeHelper(getVNodeBlockHelper(context.inSSR, codegenNode.isComponent)); + codegenNode.isBlock = false; + context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent)); + } + constantCache.set(node, returnType); + return returnType; + } + else { + constantCache.set(node, 0 /* NOT_CONSTANT */); + return 0 /* NOT_CONSTANT */; + } + case 2 /* TEXT */: + case 3 /* COMMENT */: + return 3 /* CAN_STRINGIFY */; + case 9 /* IF */: + case 11 /* FOR */: + case 10 /* IF_BRANCH */: + return 0 /* NOT_CONSTANT */; + case 5 /* INTERPOLATION */: + case 12 /* TEXT_CALL */: + return getConstantType(node.content, context); + case 4 /* SIMPLE_EXPRESSION */: + return node.constType; + case 8 /* COMPOUND_EXPRESSION */: + let returnType = 3 /* CAN_STRINGIFY */; + for (let i = 0; i < node.children.length; i++) { + const child = node.children[i]; + if (isString(child) || isSymbol(child)) { + continue; + } + const childType = getConstantType(child, context); + if (childType === 0 /* NOT_CONSTANT */) { + return 0 /* NOT_CONSTANT */; + } + else if (childType < returnType) { + returnType = childType; + } + } + return returnType; + default: + if ((process.env.NODE_ENV !== 'production')) ; + return 0 /* NOT_CONSTANT */; + } +} +const allowHoistedHelperSet = new Set([ + NORMALIZE_CLASS, + NORMALIZE_STYLE, + NORMALIZE_PROPS, + GUARD_REACTIVE_PROPS +]); +function getConstantTypeOfHelperCall(value, context) { + if (value.type === 14 /* JS_CALL_EXPRESSION */ && + !isString(value.callee) && + allowHoistedHelperSet.has(value.callee)) { + const arg = value.arguments[0]; + if (arg.type === 4 /* SIMPLE_EXPRESSION */) { + return getConstantType(arg, context); + } + else if (arg.type === 14 /* JS_CALL_EXPRESSION */) { + // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))` + return getConstantTypeOfHelperCall(arg, context); + } + } + return 0 /* NOT_CONSTANT */; +} +function getGeneratedPropsConstantType(node, context) { + let returnType = 3 /* CAN_STRINGIFY */; + const props = getNodeProps(node); + if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) { + const { properties } = props; + for (let i = 0; i < properties.length; i++) { + const { key, value } = properties[i]; + const keyType = getConstantType(key, context); + if (keyType === 0 /* NOT_CONSTANT */) { + return keyType; + } + if (keyType < returnType) { + returnType = keyType; + } + let valueType; + if (value.type === 4 /* SIMPLE_EXPRESSION */) { + valueType = getConstantType(value, context); + } + else if (value.type === 14 /* JS_CALL_EXPRESSION */) { + // some helper calls can be hoisted, + // such as the `normalizeProps` generated by the compiler for pre-normalize class, + // in this case we need to respect the ConstantType of the helper's arguments + valueType = getConstantTypeOfHelperCall(value, context); + } + else { + valueType = 0 /* NOT_CONSTANT */; + } + if (valueType === 0 /* NOT_CONSTANT */) { + return valueType; + } + if (valueType < returnType) { + returnType = valueType; + } + } + } + return returnType; +} +function getNodeProps(node) { + const codegenNode = node.codegenNode; + if (codegenNode.type === 13 /* VNODE_CALL */) { + return codegenNode.props; + } +} +function getPatchFlag(node) { + const flag = node.patchFlag; + return flag ? parseInt(flag, 10) : undefined; } -function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, isCustomElement = NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, inSSR = false, ssrCssVars = ``, bindingMetadata = EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError, onWarn = defaultOnWarn, compatConfig }) { - const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/); - const context = { - // options - selfName: nameMatch && capitalize(camelize$1(nameMatch[1])), - prefixIdentifiers, - hoistStatic, - cacheHandlers, - nodeTransforms, - directiveTransforms, - transformHoist, - isBuiltInComponent, - isCustomElement, - expressionPlugins, - scopeId, - slotted, - ssr, - inSSR, - ssrCssVars, - bindingMetadata, - inline, - isTS, - onError, - onWarn, - compatConfig, - // state - root, - helpers: new Map(), - components: new Set(), - directives: new Set(), - hoists: [], - imports: [], - constantCache: new Map(), - temps: 0, - cached: 0, - identifiers: Object.create(null), - scopes: { - vFor: 0, - vSlot: 0, - vPre: 0, - vOnce: 0 - }, - parent: null, - currentNode: root, - childIndex: 0, - inVOnce: false, - // methods - helper(name) { - const count = context.helpers.get(name) || 0; - context.helpers.set(name, count + 1); - return name; - }, - removeHelper(name) { - const count = context.helpers.get(name); - if (count) { - const currentCount = count - 1; - if (!currentCount) { - context.helpers.delete(name); - } - else { - context.helpers.set(name, currentCount); - } - } - }, - helperString(name) { - return `_${helperNameMap[context.helper(name)]}`; - }, - replaceNode(node) { - /* istanbul ignore if */ - if ((process.env.NODE_ENV !== 'production')) { - if (!context.currentNode) { - throw new Error(`Node being replaced is already removed.`); - } - if (!context.parent) { - throw new Error(`Cannot replace root node.`); - } - } - context.parent.children[context.childIndex] = context.currentNode = node; - }, - removeNode(node) { - if ((process.env.NODE_ENV !== 'production') && !context.parent) { - throw new Error(`Cannot remove root node.`); - } - const list = context.parent.children; - const removalIndex = node - ? list.indexOf(node) - : context.currentNode - ? context.childIndex - : -1; - /* istanbul ignore if */ - if ((process.env.NODE_ENV !== 'production') && removalIndex < 0) { - throw new Error(`node being removed is not a child of current parent`); - } - if (!node || node === context.currentNode) { - // current node removed - context.currentNode = null; - context.onNodeRemoved(); - } - else { - // sibling node removed - if (context.childIndex > removalIndex) { - context.childIndex--; - context.onNodeRemoved(); - } - } - context.parent.children.splice(removalIndex, 1); - }, - onNodeRemoved: () => { }, - addIdentifiers(exp) { - }, - removeIdentifiers(exp) { - }, - hoist(exp) { - if (isString(exp)) - exp = createSimpleExpression(exp); - context.hoists.push(exp); - const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, 2 /* CAN_HOIST */); - identifier.hoisted = exp; - return identifier; - }, - cache(exp, isVNode = false) { - return createCacheExpression(context.cached++, exp, isVNode); - } - }; - { - context.filters = new Set(); - } - return context; -} -function transform(root, options) { - const context = createTransformContext(root, options); - traverseNode(root, context); - if (options.hoistStatic) { - hoistStatic(root, context); - } - if (!options.ssr) { - createRootCodegen(root, context); - } - // finalize meta information - root.helpers = [...context.helpers.keys()]; - root.components = [...context.components]; - root.directives = [...context.directives]; - root.imports = context.imports; - root.hoists = context.hoists; - root.temps = context.temps; - root.cached = context.cached; - { - root.filters = [...context.filters]; - } -} -function createRootCodegen(root, context) { - const { helper } = context; - const { children } = root; - if (children.length === 1) { - const child = children[0]; - // if the single child is an element, turn it into a block. - if (isSingleElementRoot(root, child) && child.codegenNode) { - // single element root is never hoisted so codegenNode will never be - // SimpleExpressionNode - const codegenNode = child.codegenNode; - if (codegenNode.type === 13 /* VNODE_CALL */) { - makeBlock(codegenNode, context); - } - root.codegenNode = codegenNode; - } - else { - // - single <slot/>, IfNode, ForNode: already blocks. - // - single text node: always patched. - // root codegen falls through via genNode() - root.codegenNode = child; - } - } - else if (children.length > 1) { - // root has multiple nodes - return a fragment block. - let patchFlag = 64 /* STABLE_FRAGMENT */; - let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */]; - // check if the fragment actually contains a single valid child with - // the rest being comments - if ((process.env.NODE_ENV !== 'production') && - children.filter(c => c.type !== 3 /* COMMENT */).length === 1) { - patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */; - patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`; - } - root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, patchFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${patchFlagText} */` : ``), undefined, undefined, true, undefined, false /* isComponent */); - } - else ; -} -function traverseChildren(parent, context) { - let i = 0; - const nodeRemoved = () => { - i--; - }; - for (; i < parent.children.length; i++) { - const child = parent.children[i]; - if (isString(child)) - continue; - context.parent = parent; - context.childIndex = i; - context.onNodeRemoved = nodeRemoved; - traverseNode(child, context); - } -} -function traverseNode(node, context) { - context.currentNode = node; - // apply transform plugins - const { nodeTransforms } = context; - const exitFns = []; - for (let i = 0; i < nodeTransforms.length; i++) { - const onExit = nodeTransforms[i](node, context); - if (onExit) { - if (isArray(onExit)) { - exitFns.push(...onExit); - } - else { - exitFns.push(onExit); - } - } - if (!context.currentNode) { - // node was removed - return; - } - else { - // node may have been replaced - node = context.currentNode; - } - } - switch (node.type) { - case 3 /* COMMENT */: - if (!context.ssr) { - // inject import for the Comment symbol, which is needed for creating - // comment nodes with `createVNode` - context.helper(CREATE_COMMENT); - } - break; - case 5 /* INTERPOLATION */: - // no need to traverse, but we need to inject toString helper - if (!context.ssr) { - context.helper(TO_DISPLAY_STRING); - } - break; - // for container types, further traverse downwards - case 9 /* IF */: - for (let i = 0; i < node.branches.length; i++) { - traverseNode(node.branches[i], context); - } - break; - case 10 /* IF_BRANCH */: - case 11 /* FOR */: - case 1 /* ELEMENT */: - case 0 /* ROOT */: - traverseChildren(node, context); - break; - } - // exit transforms - context.currentNode = node; - let i = exitFns.length; - while (i--) { - exitFns[i](); - } -} -function createStructuralDirectiveTransform(name, fn) { - const matches = isString(name) - ? (n) => n === name - : (n) => name.test(n); - return (node, context) => { - if (node.type === 1 /* ELEMENT */) { - const { props } = node; - // structural directive transforms are not concerned with slots - // as they are handled separately in vSlot.ts - if (node.tagType === 3 /* TEMPLATE */ && props.some(isVSlot)) { - return; - } - const exitFns = []; - for (let i = 0; i < props.length; i++) { - const prop = props[i]; - if (prop.type === 7 /* DIRECTIVE */ && matches(prop.name)) { - // structural directives are removed to avoid infinite recursion - // also we remove them *before* applying so that it can further - // traverse itself in case it moves the node around - props.splice(i, 1); - i--; - const onExit = fn(node, prop, context); - if (onExit) - exitFns.push(onExit); - } - } - return exitFns; - } - }; +function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, isCustomElement = NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, inSSR = false, ssrCssVars = ``, bindingMetadata = EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError, onWarn = defaultOnWarn, compatConfig }) { + const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/); + const context = { + // options + selfName: nameMatch && capitalize(camelize$1(nameMatch[1])), + prefixIdentifiers, + hoistStatic, + cacheHandlers, + nodeTransforms, + directiveTransforms, + transformHoist, + isBuiltInComponent, + isCustomElement, + expressionPlugins, + scopeId, + slotted, + ssr, + inSSR, + ssrCssVars, + bindingMetadata, + inline, + isTS, + onError, + onWarn, + compatConfig, + // state + root, + helpers: new Map(), + components: new Set(), + directives: new Set(), + hoists: [], + imports: [], + constantCache: new Map(), + temps: 0, + cached: 0, + identifiers: Object.create(null), + scopes: { + vFor: 0, + vSlot: 0, + vPre: 0, + vOnce: 0 + }, + parent: null, + currentNode: root, + childIndex: 0, + inVOnce: false, + // methods + helper(name) { + const count = context.helpers.get(name) || 0; + context.helpers.set(name, count + 1); + return name; + }, + removeHelper(name) { + const count = context.helpers.get(name); + if (count) { + const currentCount = count - 1; + if (!currentCount) { + context.helpers.delete(name); + } + else { + context.helpers.set(name, currentCount); + } + } + }, + helperString(name) { + return `_${helperNameMap[context.helper(name)]}`; + }, + replaceNode(node) { + /* istanbul ignore if */ + if ((process.env.NODE_ENV !== 'production')) { + if (!context.currentNode) { + throw new Error(`Node being replaced is already removed.`); + } + if (!context.parent) { + throw new Error(`Cannot replace root node.`); + } + } + context.parent.children[context.childIndex] = context.currentNode = node; + }, + removeNode(node) { + if ((process.env.NODE_ENV !== 'production') && !context.parent) { + throw new Error(`Cannot remove root node.`); + } + const list = context.parent.children; + const removalIndex = node + ? list.indexOf(node) + : context.currentNode + ? context.childIndex + : -1; + /* istanbul ignore if */ + if ((process.env.NODE_ENV !== 'production') && removalIndex < 0) { + throw new Error(`node being removed is not a child of current parent`); + } + if (!node || node === context.currentNode) { + // current node removed + context.currentNode = null; + context.onNodeRemoved(); + } + else { + // sibling node removed + if (context.childIndex > removalIndex) { + context.childIndex--; + context.onNodeRemoved(); + } + } + context.parent.children.splice(removalIndex, 1); + }, + onNodeRemoved: () => { }, + addIdentifiers(exp) { + }, + removeIdentifiers(exp) { + }, + hoist(exp) { + if (isString(exp)) + exp = createSimpleExpression(exp); + context.hoists.push(exp); + const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, 2 /* CAN_HOIST */); + identifier.hoisted = exp; + return identifier; + }, + cache(exp, isVNode = false) { + return createCacheExpression(context.cached++, exp, isVNode); + } + }; + { + context.filters = new Set(); + } + return context; +} +function transform(root, options) { + const context = createTransformContext(root, options); + traverseNode(root, context); + if (options.hoistStatic) { + hoistStatic(root, context); + } + if (!options.ssr) { + createRootCodegen(root, context); + } + // finalize meta information + root.helpers = [...context.helpers.keys()]; + root.components = [...context.components]; + root.directives = [...context.directives]; + root.imports = context.imports; + root.hoists = context.hoists; + root.temps = context.temps; + root.cached = context.cached; + { + root.filters = [...context.filters]; + } +} +function createRootCodegen(root, context) { + const { helper } = context; + const { children } = root; + if (children.length === 1) { + const child = children[0]; + // if the single child is an element, turn it into a block. + if (isSingleElementRoot(root, child) && child.codegenNode) { + // single element root is never hoisted so codegenNode will never be + // SimpleExpressionNode + const codegenNode = child.codegenNode; + if (codegenNode.type === 13 /* VNODE_CALL */) { + makeBlock(codegenNode, context); + } + root.codegenNode = codegenNode; + } + else { + // - single <slot/>, IfNode, ForNode: already blocks. + // - single text node: always patched. + // root codegen falls through via genNode() + root.codegenNode = child; + } + } + else if (children.length > 1) { + // root has multiple nodes - return a fragment block. + let patchFlag = 64 /* STABLE_FRAGMENT */; + let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */]; + // check if the fragment actually contains a single valid child with + // the rest being comments + if ((process.env.NODE_ENV !== 'production') && + children.filter(c => c.type !== 3 /* COMMENT */).length === 1) { + patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */; + patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`; + } + root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, patchFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${patchFlagText} */` : ``), undefined, undefined, true, undefined, false /* isComponent */); + } + else ; +} +function traverseChildren(parent, context) { + let i = 0; + const nodeRemoved = () => { + i--; + }; + for (; i < parent.children.length; i++) { + const child = parent.children[i]; + if (isString(child)) + continue; + context.parent = parent; + context.childIndex = i; + context.onNodeRemoved = nodeRemoved; + traverseNode(child, context); + } +} +function traverseNode(node, context) { + context.currentNode = node; + // apply transform plugins + const { nodeTransforms } = context; + const exitFns = []; + for (let i = 0; i < nodeTransforms.length; i++) { + const onExit = nodeTransforms[i](node, context); + if (onExit) { + if (isArray(onExit)) { + exitFns.push(...onExit); + } + else { + exitFns.push(onExit); + } + } + if (!context.currentNode) { + // node was removed + return; + } + else { + // node may have been replaced + node = context.currentNode; + } + } + switch (node.type) { + case 3 /* COMMENT */: + if (!context.ssr) { + // inject import for the Comment symbol, which is needed for creating + // comment nodes with `createVNode` + context.helper(CREATE_COMMENT); + } + break; + case 5 /* INTERPOLATION */: + // no need to traverse, but we need to inject toString helper + if (!context.ssr) { + context.helper(TO_DISPLAY_STRING); + } + break; + // for container types, further traverse downwards + case 9 /* IF */: + for (let i = 0; i < node.branches.length; i++) { + traverseNode(node.branches[i], context); + } + break; + case 10 /* IF_BRANCH */: + case 11 /* FOR */: + case 1 /* ELEMENT */: + case 0 /* ROOT */: + traverseChildren(node, context); + break; + } + // exit transforms + context.currentNode = node; + let i = exitFns.length; + while (i--) { + exitFns[i](); + } +} +function createStructuralDirectiveTransform(name, fn) { + const matches = isString(name) + ? (n) => n === name + : (n) => name.test(n); + return (node, context) => { + if (node.type === 1 /* ELEMENT */) { + const { props } = node; + // structural directive transforms are not concerned with slots + // as they are handled separately in vSlot.ts + if (node.tagType === 3 /* TEMPLATE */ && props.some(isVSlot)) { + return; + } + const exitFns = []; + for (let i = 0; i < props.length; i++) { + const prop = props[i]; + if (prop.type === 7 /* DIRECTIVE */ && matches(prop.name)) { + // structural directives are removed to avoid infinite recursion + // also we remove them *before* applying so that it can further + // traverse itself in case it moves the node around + props.splice(i, 1); + i--; + const onExit = fn(node, prop, context); + if (onExit) + exitFns.push(onExit); + } + } + return exitFns; + } + }; } -const PURE_ANNOTATION = `/*#__PURE__*/`; -const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`; -function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssrRuntimeModuleName = 'vue/server-renderer', ssr = false, isTS = false, inSSR = false }) { - const context = { - mode, - prefixIdentifiers, - sourceMap, - filename, - scopeId, - optimizeImports, - runtimeGlobalName, - runtimeModuleName, - ssrRuntimeModuleName, - ssr, - isTS, - inSSR, - source: ast.loc.source, - code: ``, - column: 1, - line: 1, - offset: 0, - indentLevel: 0, - pure: false, - map: undefined, - helper(key) { - return `_${helperNameMap[key]}`; - }, - push(code, node) { - context.code += code; - }, - indent() { - newline(++context.indentLevel); - }, - deindent(withoutNewLine = false) { - if (withoutNewLine) { - --context.indentLevel; - } - else { - newline(--context.indentLevel); - } - }, - newline() { - newline(context.indentLevel); - } - }; - function newline(n) { - context.push('\n' + ` `.repeat(n)); - } - return context; -} -function generate(ast, options = {}) { - const context = createCodegenContext(ast, options); - if (options.onContextCreated) - options.onContextCreated(context); - const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context; - const hasHelpers = ast.helpers.length > 0; - const useWithBlock = !prefixIdentifiers && mode !== 'module'; - // preambles - // in setup() inline mode, the preamble is generated in a sub context - // and returned separately. - const preambleContext = context; - { - genFunctionPreamble(ast, preambleContext); - } - // enter render function - const functionName = ssr ? `ssrRender` : `render`; - const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache']; - const signature = args.join(', '); - { - push(`function ${functionName}(${signature}) {`); - } - indent(); - if (useWithBlock) { - push(`with (_ctx) {`); - indent(); - // function mode const declarations should be inside with block - // also they should be renamed to avoid collision with user properties - if (hasHelpers) { - push(`const { ${ast.helpers.map(aliasHelper).join(', ')} } = _Vue`); - push(`\n`); - newline(); - } - } - // generate asset resolution statements - if (ast.components.length) { - genAssets(ast.components, 'component', context); - if (ast.directives.length || ast.temps > 0) { - newline(); - } - } - if (ast.directives.length) { - genAssets(ast.directives, 'directive', context); - if (ast.temps > 0) { - newline(); - } - } - if (ast.filters && ast.filters.length) { - newline(); - genAssets(ast.filters, 'filter', context); - newline(); - } - if (ast.temps > 0) { - push(`let `); - for (let i = 0; i < ast.temps; i++) { - push(`${i > 0 ? `, ` : ``}_temp${i}`); - } - } - if (ast.components.length || ast.directives.length || ast.temps) { - push(`\n`); - newline(); - } - // generate the VNode tree expression - if (!ssr) { - push(`return `); - } - if (ast.codegenNode) { - genNode(ast.codegenNode, context); - } - else { - push(`null`); - } - if (useWithBlock) { - deindent(); - push(`}`); - } - deindent(); - push(`}`); - return { - ast, - code: context.code, - preamble: ``, - // SourceMapGenerator does have toJSON() method but it's not in the types - map: context.map ? context.map.toJSON() : undefined - }; -} -function genFunctionPreamble(ast, context) { - const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName, ssrRuntimeModuleName } = context; - const VueBinding = runtimeGlobalName; - // Generate const declaration for helpers - // In prefix mode, we place the const declaration at top so it's done - // only once; But if we not prefixing, we place the declaration inside the - // with block so it doesn't incur the `in` check cost for every helper access. - if (ast.helpers.length > 0) { - { - // "with" mode. - // save Vue in a separate variable to avoid collision - push(`const _Vue = ${VueBinding}\n`); - // in "with" mode, helpers are declared inside the with block to avoid - // has check cost, but hoists are lifted out of the function - we need - // to provide the helper here. - if (ast.hoists.length) { - const staticHelpers = [ - CREATE_VNODE, - CREATE_ELEMENT_VNODE, - CREATE_COMMENT, - CREATE_TEXT, - CREATE_STATIC - ] - .filter(helper => ast.helpers.includes(helper)) - .map(aliasHelper) - .join(', '); - push(`const { ${staticHelpers} } = _Vue\n`); - } - } - } - genHoists(ast.hoists, context); - newline(); - push(`return `); -} -function genAssets(assets, type, { helper, push, newline, isTS }) { - const resolver = helper(type === 'filter' - ? RESOLVE_FILTER - : type === 'component' - ? RESOLVE_COMPONENT - : RESOLVE_DIRECTIVE); - for (let i = 0; i < assets.length; i++) { - let id = assets[i]; - // potential component implicit self-reference inferred from SFC filename - const maybeSelfReference = id.endsWith('__self'); - if (maybeSelfReference) { - id = id.slice(0, -6); - } - push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`); - if (i < assets.length - 1) { - newline(); - } - } -} -function genHoists(hoists, context) { - if (!hoists.length) { - return; - } - context.pure = true; - const { push, newline, helper, scopeId, mode } = context; - newline(); - for (let i = 0; i < hoists.length; i++) { - const exp = hoists[i]; - if (exp) { - push(`const _hoisted_${i + 1} = ${``}`); - genNode(exp, context); - newline(); - } - } - context.pure = false; -} -function isText$1(n) { - return (isString(n) || - n.type === 4 /* SIMPLE_EXPRESSION */ || - n.type === 2 /* TEXT */ || - n.type === 5 /* INTERPOLATION */ || - n.type === 8 /* COMPOUND_EXPRESSION */); -} -function genNodeListAsArray(nodes, context) { - const multilines = nodes.length > 3 || - (((process.env.NODE_ENV !== 'production')) && nodes.some(n => isArray(n) || !isText$1(n))); - context.push(`[`); - multilines && context.indent(); - genNodeList(nodes, context, multilines); - multilines && context.deindent(); - context.push(`]`); -} -function genNodeList(nodes, context, multilines = false, comma = true) { - const { push, newline } = context; - for (let i = 0; i < nodes.length; i++) { - const node = nodes[i]; - if (isString(node)) { - push(node); - } - else if (isArray(node)) { - genNodeListAsArray(node, context); - } - else { - genNode(node, context); - } - if (i < nodes.length - 1) { - if (multilines) { - comma && push(','); - newline(); - } - else { - comma && push(', '); - } - } - } -} -function genNode(node, context) { - if (isString(node)) { - context.push(node); - return; - } - if (isSymbol(node)) { - context.push(context.helper(node)); - return; - } - switch (node.type) { - case 1 /* ELEMENT */: - case 9 /* IF */: - case 11 /* FOR */: - (process.env.NODE_ENV !== 'production') && - assert(node.codegenNode != null, `Codegen node is missing for element/if/for node. ` + - `Apply appropriate transforms first.`); - genNode(node.codegenNode, context); - break; - case 2 /* TEXT */: - genText(node, context); - break; - case 4 /* SIMPLE_EXPRESSION */: - genExpression(node, context); - break; - case 5 /* INTERPOLATION */: - genInterpolation(node, context); - break; - case 12 /* TEXT_CALL */: - genNode(node.codegenNode, context); - break; - case 8 /* COMPOUND_EXPRESSION */: - genCompoundExpression(node, context); - break; - case 3 /* COMMENT */: - genComment(node, context); - break; - case 13 /* VNODE_CALL */: - genVNodeCall(node, context); - break; - case 14 /* JS_CALL_EXPRESSION */: - genCallExpression(node, context); - break; - case 15 /* JS_OBJECT_EXPRESSION */: - genObjectExpression(node, context); - break; - case 17 /* JS_ARRAY_EXPRESSION */: - genArrayExpression(node, context); - break; - case 18 /* JS_FUNCTION_EXPRESSION */: - genFunctionExpression(node, context); - break; - case 19 /* JS_CONDITIONAL_EXPRESSION */: - genConditionalExpression(node, context); - break; - case 20 /* JS_CACHE_EXPRESSION */: - genCacheExpression(node, context); - break; - case 21 /* JS_BLOCK_STATEMENT */: - genNodeList(node.body, context, true, false); - break; - // SSR only types - case 22 /* JS_TEMPLATE_LITERAL */: - break; - case 23 /* JS_IF_STATEMENT */: - break; - case 24 /* JS_ASSIGNMENT_EXPRESSION */: - break; - case 25 /* JS_SEQUENCE_EXPRESSION */: - break; - case 26 /* JS_RETURN_STATEMENT */: - break; - /* istanbul ignore next */ - case 10 /* IF_BRANCH */: - // noop - break; - default: - if ((process.env.NODE_ENV !== 'production')) { - assert(false, `unhandled codegen node type: ${node.type}`); - // make sure we exhaust all possible types - const exhaustiveCheck = node; - return exhaustiveCheck; - } - } -} -function genText(node, context) { - context.push(JSON.stringify(node.content), node); -} -function genExpression(node, context) { - const { content, isStatic } = node; - context.push(isStatic ? JSON.stringify(content) : content, node); -} -function genInterpolation(node, context) { - const { push, helper, pure } = context; - if (pure) - push(PURE_ANNOTATION); - push(`${helper(TO_DISPLAY_STRING)}(`); - genNode(node.content, context); - push(`)`); -} -function genCompoundExpression(node, context) { - for (let i = 0; i < node.children.length; i++) { - const child = node.children[i]; - if (isString(child)) { - context.push(child); - } - else { - genNode(child, context); - } - } -} -function genExpressionAsPropertyKey(node, context) { - const { push } = context; - if (node.type === 8 /* COMPOUND_EXPRESSION */) { - push(`[`); - genCompoundExpression(node, context); - push(`]`); - } - else if (node.isStatic) { - // only quote keys if necessary - const text = isSimpleIdentifier(node.content) - ? node.content - : JSON.stringify(node.content); - push(text, node); - } - else { - push(`[${node.content}]`, node); - } -} -function genComment(node, context) { - const { push, helper, pure } = context; - if (pure) { - push(PURE_ANNOTATION); - } - push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node); -} -function genVNodeCall(node, context) { - const { push, helper, pure } = context; - const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking, isComponent } = node; - if (directives) { - push(helper(WITH_DIRECTIVES) + `(`); - } - if (isBlock) { - push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `); - } - if (pure) { - push(PURE_ANNOTATION); - } - const callHelper = isBlock - ? getVNodeBlockHelper(context.inSSR, isComponent) - : getVNodeHelper(context.inSSR, isComponent); - push(helper(callHelper) + `(`, node); - genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context); - push(`)`); - if (isBlock) { - push(`)`); - } - if (directives) { - push(`, `); - genNode(directives, context); - push(`)`); - } -} -function genNullableArgs(args) { - let i = args.length; - while (i--) { - if (args[i] != null) - break; - } - return args.slice(0, i + 1).map(arg => arg || `null`); -} -// JavaScript -function genCallExpression(node, context) { - const { push, helper, pure } = context; - const callee = isString(node.callee) ? node.callee : helper(node.callee); - if (pure) { - push(PURE_ANNOTATION); - } - push(callee + `(`, node); - genNodeList(node.arguments, context); - push(`)`); -} -function genObjectExpression(node, context) { - const { push, indent, deindent, newline } = context; - const { properties } = node; - if (!properties.length) { - push(`{}`, node); - return; - } - const multilines = properties.length > 1 || - (((process.env.NODE_ENV !== 'production')) && - properties.some(p => p.value.type !== 4 /* SIMPLE_EXPRESSION */)); - push(multilines ? `{` : `{ `); - multilines && indent(); - for (let i = 0; i < properties.length; i++) { - const { key, value } = properties[i]; - // key - genExpressionAsPropertyKey(key, context); - push(`: `); - // value - genNode(value, context); - if (i < properties.length - 1) { - // will only reach this if it's multilines - push(`,`); - newline(); - } - } - multilines && deindent(); - push(multilines ? `}` : ` }`); -} -function genArrayExpression(node, context) { - genNodeListAsArray(node.elements, context); -} -function genFunctionExpression(node, context) { - const { push, indent, deindent } = context; - const { params, returns, body, newline, isSlot } = node; - if (isSlot) { - // wrap slot functions with owner context - push(`_${helperNameMap[WITH_CTX]}(`); - } - push(`(`, node); - if (isArray(params)) { - genNodeList(params, context); - } - else if (params) { - genNode(params, context); - } - push(`) => `); - if (newline || body) { - push(`{`); - indent(); - } - if (returns) { - if (newline) { - push(`return `); - } - if (isArray(returns)) { - genNodeListAsArray(returns, context); - } - else { - genNode(returns, context); - } - } - else if (body) { - genNode(body, context); - } - if (newline || body) { - deindent(); - push(`}`); - } - if (isSlot) { - if (node.isNonScopedSlot) { - push(`, undefined, true`); - } - push(`)`); - } -} -function genConditionalExpression(node, context) { - const { test, consequent, alternate, newline: needNewline } = node; - const { push, indent, deindent, newline } = context; - if (test.type === 4 /* SIMPLE_EXPRESSION */) { - const needsParens = !isSimpleIdentifier(test.content); - needsParens && push(`(`); - genExpression(test, context); - needsParens && push(`)`); - } - else { - push(`(`); - genNode(test, context); - push(`)`); - } - needNewline && indent(); - context.indentLevel++; - needNewline || push(` `); - push(`? `); - genNode(consequent, context); - context.indentLevel--; - needNewline && newline(); - needNewline || push(` `); - push(`: `); - const isNested = alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */; - if (!isNested) { - context.indentLevel++; - } - genNode(alternate, context); - if (!isNested) { - context.indentLevel--; - } - needNewline && deindent(true /* without newline */); -} -function genCacheExpression(node, context) { - const { push, helper, indent, deindent, newline } = context; - push(`_cache[${node.index}] || (`); - if (node.isVNode) { - indent(); - push(`${helper(SET_BLOCK_TRACKING)}(-1),`); - newline(); - } - push(`_cache[${node.index}] = `); - genNode(node.value, context); - if (node.isVNode) { - push(`,`); - newline(); - push(`${helper(SET_BLOCK_TRACKING)}(1),`); - newline(); - push(`_cache[${node.index}]`); - deindent(); - } - push(`)`); +const PURE_ANNOTATION = `/*#__PURE__*/`; +const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`; +function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssrRuntimeModuleName = 'vue/server-renderer', ssr = false, isTS = false, inSSR = false }) { + const context = { + mode, + prefixIdentifiers, + sourceMap, + filename, + scopeId, + optimizeImports, + runtimeGlobalName, + runtimeModuleName, + ssrRuntimeModuleName, + ssr, + isTS, + inSSR, + source: ast.loc.source, + code: ``, + column: 1, + line: 1, + offset: 0, + indentLevel: 0, + pure: false, + map: undefined, + helper(key) { + return `_${helperNameMap[key]}`; + }, + push(code, node) { + context.code += code; + }, + indent() { + newline(++context.indentLevel); + }, + deindent(withoutNewLine = false) { + if (withoutNewLine) { + --context.indentLevel; + } + else { + newline(--context.indentLevel); + } + }, + newline() { + newline(context.indentLevel); + } + }; + function newline(n) { + context.push('\n' + ` `.repeat(n)); + } + return context; +} +function generate(ast, options = {}) { + const context = createCodegenContext(ast, options); + if (options.onContextCreated) + options.onContextCreated(context); + const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context; + const hasHelpers = ast.helpers.length > 0; + const useWithBlock = !prefixIdentifiers && mode !== 'module'; + // preambles + // in setup() inline mode, the preamble is generated in a sub context + // and returned separately. + const preambleContext = context; + { + genFunctionPreamble(ast, preambleContext); + } + // enter render function + const functionName = ssr ? `ssrRender` : `render`; + const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache']; + const signature = args.join(', '); + { + push(`function ${functionName}(${signature}) {`); + } + indent(); + if (useWithBlock) { + push(`with (_ctx) {`); + indent(); + // function mode const declarations should be inside with block + // also they should be renamed to avoid collision with user properties + if (hasHelpers) { + push(`const { ${ast.helpers.map(aliasHelper).join(', ')} } = _Vue`); + push(`\n`); + newline(); + } + } + // generate asset resolution statements + if (ast.components.length) { + genAssets(ast.components, 'component', context); + if (ast.directives.length || ast.temps > 0) { + newline(); + } + } + if (ast.directives.length) { + genAssets(ast.directives, 'directive', context); + if (ast.temps > 0) { + newline(); + } + } + if (ast.filters && ast.filters.length) { + newline(); + genAssets(ast.filters, 'filter', context); + newline(); + } + if (ast.temps > 0) { + push(`let `); + for (let i = 0; i < ast.temps; i++) { + push(`${i > 0 ? `, ` : ``}_temp${i}`); + } + } + if (ast.components.length || ast.directives.length || ast.temps) { + push(`\n`); + newline(); + } + // generate the VNode tree expression + if (!ssr) { + push(`return `); + } + if (ast.codegenNode) { + genNode(ast.codegenNode, context); + } + else { + push(`null`); + } + if (useWithBlock) { + deindent(); + push(`}`); + } + deindent(); + push(`}`); + return { + ast, + code: context.code, + preamble: ``, + // SourceMapGenerator does have toJSON() method but it's not in the types + map: context.map ? context.map.toJSON() : undefined + }; +} +function genFunctionPreamble(ast, context) { + const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName, ssrRuntimeModuleName } = context; + const VueBinding = runtimeGlobalName; + // Generate const declaration for helpers + // In prefix mode, we place the const declaration at top so it's done + // only once; But if we not prefixing, we place the declaration inside the + // with block so it doesn't incur the `in` check cost for every helper access. + if (ast.helpers.length > 0) { + { + // "with" mode. + // save Vue in a separate variable to avoid collision + push(`const _Vue = ${VueBinding}\n`); + // in "with" mode, helpers are declared inside the with block to avoid + // has check cost, but hoists are lifted out of the function - we need + // to provide the helper here. + if (ast.hoists.length) { + const staticHelpers = [ + CREATE_VNODE, + CREATE_ELEMENT_VNODE, + CREATE_COMMENT, + CREATE_TEXT, + CREATE_STATIC + ] + .filter(helper => ast.helpers.includes(helper)) + .map(aliasHelper) + .join(', '); + push(`const { ${staticHelpers} } = _Vue\n`); + } + } + } + genHoists(ast.hoists, context); + newline(); + push(`return `); +} +function genAssets(assets, type, { helper, push, newline, isTS }) { + const resolver = helper(type === 'filter' + ? RESOLVE_FILTER + : type === 'component' + ? RESOLVE_COMPONENT + : RESOLVE_DIRECTIVE); + for (let i = 0; i < assets.length; i++) { + let id = assets[i]; + // potential component implicit self-reference inferred from SFC filename + const maybeSelfReference = id.endsWith('__self'); + if (maybeSelfReference) { + id = id.slice(0, -6); + } + push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`); + if (i < assets.length - 1) { + newline(); + } + } +} +function genHoists(hoists, context) { + if (!hoists.length) { + return; + } + context.pure = true; + const { push, newline, helper, scopeId, mode } = context; + newline(); + for (let i = 0; i < hoists.length; i++) { + const exp = hoists[i]; + if (exp) { + push(`const _hoisted_${i + 1} = ${``}`); + genNode(exp, context); + newline(); + } + } + context.pure = false; +} +function isText$1(n) { + return (isString(n) || + n.type === 4 /* SIMPLE_EXPRESSION */ || + n.type === 2 /* TEXT */ || + n.type === 5 /* INTERPOLATION */ || + n.type === 8 /* COMPOUND_EXPRESSION */); +} +function genNodeListAsArray(nodes, context) { + const multilines = nodes.length > 3 || + (((process.env.NODE_ENV !== 'production')) && nodes.some(n => isArray(n) || !isText$1(n))); + context.push(`[`); + multilines && context.indent(); + genNodeList(nodes, context, multilines); + multilines && context.deindent(); + context.push(`]`); +} +function genNodeList(nodes, context, multilines = false, comma = true) { + const { push, newline } = context; + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + if (isString(node)) { + push(node); + } + else if (isArray(node)) { + genNodeListAsArray(node, context); + } + else { + genNode(node, context); + } + if (i < nodes.length - 1) { + if (multilines) { + comma && push(','); + newline(); + } + else { + comma && push(', '); + } + } + } +} +function genNode(node, context) { + if (isString(node)) { + context.push(node); + return; + } + if (isSymbol(node)) { + context.push(context.helper(node)); + return; + } + switch (node.type) { + case 1 /* ELEMENT */: + case 9 /* IF */: + case 11 /* FOR */: + (process.env.NODE_ENV !== 'production') && + assert(node.codegenNode != null, `Codegen node is missing for element/if/for node. ` + + `Apply appropriate transforms first.`); + genNode(node.codegenNode, context); + break; + case 2 /* TEXT */: + genText(node, context); + break; + case 4 /* SIMPLE_EXPRESSION */: + genExpression(node, context); + break; + case 5 /* INTERPOLATION */: + genInterpolation(node, context); + break; + case 12 /* TEXT_CALL */: + genNode(node.codegenNode, context); + break; + case 8 /* COMPOUND_EXPRESSION */: + genCompoundExpression(node, context); + break; + case 3 /* COMMENT */: + genComment(node, context); + break; + case 13 /* VNODE_CALL */: + genVNodeCall(node, context); + break; + case 14 /* JS_CALL_EXPRESSION */: + genCallExpression(node, context); + break; + case 15 /* JS_OBJECT_EXPRESSION */: + genObjectExpression(node, context); + break; + case 17 /* JS_ARRAY_EXPRESSION */: + genArrayExpression(node, context); + break; + case 18 /* JS_FUNCTION_EXPRESSION */: + genFunctionExpression(node, context); + break; + case 19 /* JS_CONDITIONAL_EXPRESSION */: + genConditionalExpression(node, context); + break; + case 20 /* JS_CACHE_EXPRESSION */: + genCacheExpression(node, context); + break; + case 21 /* JS_BLOCK_STATEMENT */: + genNodeList(node.body, context, true, false); + break; + // SSR only types + case 22 /* JS_TEMPLATE_LITERAL */: + break; + case 23 /* JS_IF_STATEMENT */: + break; + case 24 /* JS_ASSIGNMENT_EXPRESSION */: + break; + case 25 /* JS_SEQUENCE_EXPRESSION */: + break; + case 26 /* JS_RETURN_STATEMENT */: + break; + /* istanbul ignore next */ + case 10 /* IF_BRANCH */: + // noop + break; + default: + if ((process.env.NODE_ENV !== 'production')) { + assert(false, `unhandled codegen node type: ${node.type}`); + // make sure we exhaust all possible types + const exhaustiveCheck = node; + return exhaustiveCheck; + } + } +} +function genText(node, context) { + context.push(JSON.stringify(node.content), node); +} +function genExpression(node, context) { + const { content, isStatic } = node; + context.push(isStatic ? JSON.stringify(content) : content, node); +} +function genInterpolation(node, context) { + const { push, helper, pure } = context; + if (pure) + push(PURE_ANNOTATION); + push(`${helper(TO_DISPLAY_STRING)}(`); + genNode(node.content, context); + push(`)`); +} +function genCompoundExpression(node, context) { + for (let i = 0; i < node.children.length; i++) { + const child = node.children[i]; + if (isString(child)) { + context.push(child); + } + else { + genNode(child, context); + } + } +} +function genExpressionAsPropertyKey(node, context) { + const { push } = context; + if (node.type === 8 /* COMPOUND_EXPRESSION */) { + push(`[`); + genCompoundExpression(node, context); + push(`]`); + } + else if (node.isStatic) { + // only quote keys if necessary + const text = isSimpleIdentifier(node.content) + ? node.content + : JSON.stringify(node.content); + push(text, node); + } + else { + push(`[${node.content}]`, node); + } +} +function genComment(node, context) { + const { push, helper, pure } = context; + if (pure) { + push(PURE_ANNOTATION); + } + push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node); +} +function genVNodeCall(node, context) { + const { push, helper, pure } = context; + const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking, isComponent } = node; + if (directives) { + push(helper(WITH_DIRECTIVES) + `(`); + } + if (isBlock) { + push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `); + } + if (pure) { + push(PURE_ANNOTATION); + } + const callHelper = isBlock + ? getVNodeBlockHelper(context.inSSR, isComponent) + : getVNodeHelper(context.inSSR, isComponent); + push(helper(callHelper) + `(`, node); + genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context); + push(`)`); + if (isBlock) { + push(`)`); + } + if (directives) { + push(`, `); + genNode(directives, context); + push(`)`); + } +} +function genNullableArgs(args) { + let i = args.length; + while (i--) { + if (args[i] != null) + break; + } + return args.slice(0, i + 1).map(arg => arg || `null`); +} +// JavaScript +function genCallExpression(node, context) { + const { push, helper, pure } = context; + const callee = isString(node.callee) ? node.callee : helper(node.callee); + if (pure) { + push(PURE_ANNOTATION); + } + push(callee + `(`, node); + genNodeList(node.arguments, context); + push(`)`); +} +function genObjectExpression(node, context) { + const { push, indent, deindent, newline } = context; + const { properties } = node; + if (!properties.length) { + push(`{}`, node); + return; + } + const multilines = properties.length > 1 || + (((process.env.NODE_ENV !== 'production')) && + properties.some(p => p.value.type !== 4 /* SIMPLE_EXPRESSION */)); + push(multilines ? `{` : `{ `); + multilines && indent(); + for (let i = 0; i < properties.length; i++) { + const { key, value } = properties[i]; + // key + genExpressionAsPropertyKey(key, context); + push(`: `); + // value + genNode(value, context); + if (i < properties.length - 1) { + // will only reach this if it's multilines + push(`,`); + newline(); + } + } + multilines && deindent(); + push(multilines ? `}` : ` }`); +} +function genArrayExpression(node, context) { + genNodeListAsArray(node.elements, context); +} +function genFunctionExpression(node, context) { + const { push, indent, deindent } = context; + const { params, returns, body, newline, isSlot } = node; + if (isSlot) { + // wrap slot functions with owner context + push(`_${helperNameMap[WITH_CTX]}(`); + } + push(`(`, node); + if (isArray(params)) { + genNodeList(params, context); + } + else if (params) { + genNode(params, context); + } + push(`) => `); + if (newline || body) { + push(`{`); + indent(); + } + if (returns) { + if (newline) { + push(`return `); + } + if (isArray(returns)) { + genNodeListAsArray(returns, context); + } + else { + genNode(returns, context); + } + } + else if (body) { + genNode(body, context); + } + if (newline || body) { + deindent(); + push(`}`); + } + if (isSlot) { + if (node.isNonScopedSlot) { + push(`, undefined, true`); + } + push(`)`); + } +} +function genConditionalExpression(node, context) { + const { test, consequent, alternate, newline: needNewline } = node; + const { push, indent, deindent, newline } = context; + if (test.type === 4 /* SIMPLE_EXPRESSION */) { + const needsParens = !isSimpleIdentifier(test.content); + needsParens && push(`(`); + genExpression(test, context); + needsParens && push(`)`); + } + else { + push(`(`); + genNode(test, context); + push(`)`); + } + needNewline && indent(); + context.indentLevel++; + needNewline || push(` `); + push(`? `); + genNode(consequent, context); + context.indentLevel--; + needNewline && newline(); + needNewline || push(` `); + push(`: `); + const isNested = alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */; + if (!isNested) { + context.indentLevel++; + } + genNode(alternate, context); + if (!isNested) { + context.indentLevel--; + } + needNewline && deindent(true /* without newline */); +} +function genCacheExpression(node, context) { + const { push, helper, indent, deindent, newline } = context; + push(`_cache[${node.index}] || (`); + if (node.isVNode) { + indent(); + push(`${helper(SET_BLOCK_TRACKING)}(-1),`); + newline(); + } + push(`_cache[${node.index}] = `); + genNode(node.value, context); + if (node.isVNode) { + push(`,`); + newline(); + push(`${helper(SET_BLOCK_TRACKING)}(1),`); + newline(); + push(`_cache[${node.index}]`); + deindent(); + } + push(`)`); } -function walkIdentifiers(root, onIdentifier, includeAll = false, parentStack = [], knownIds = Object.create(null)) { - { - return; - } -} -function isReferencedIdentifier(id, parent, parentStack) { - { - return false; - } -} -function isInDestructureAssignment(parent, parentStack) { - if (parent && - (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')) { - let i = parentStack.length; - while (i--) { - const p = parentStack[i]; - if (p.type === 'AssignmentExpression') { - return true; - } - else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) { - break; - } - } - } - return false; -} -function walkFunctionParams(node, onIdent) { - for (const p of node.params) { - for (const id of extractIdentifiers(p)) { - onIdent(id); - } - } -} -function walkBlockDeclarations(block, onIdent) { - for (const stmt of block.body) { - if (stmt.type === 'VariableDeclaration') { - if (stmt.declare) - continue; - for (const decl of stmt.declarations) { - for (const id of extractIdentifiers(decl.id)) { - onIdent(id); - } - } - } - else if (stmt.type === 'FunctionDeclaration' || - stmt.type === 'ClassDeclaration') { - if (stmt.declare || !stmt.id) - continue; - onIdent(stmt.id); - } - } -} -function extractIdentifiers(param, nodes = []) { - switch (param.type) { - case 'Identifier': - nodes.push(param); - break; - case 'MemberExpression': - let object = param; - while (object.type === 'MemberExpression') { - object = object.object; - } - nodes.push(object); - break; - case 'ObjectPattern': - for (const prop of param.properties) { - if (prop.type === 'RestElement') { - extractIdentifiers(prop.argument, nodes); - } - else { - extractIdentifiers(prop.value, nodes); - } - } - break; - case 'ArrayPattern': - param.elements.forEach(element => { - if (element) - extractIdentifiers(element, nodes); - }); - break; - case 'RestElement': - extractIdentifiers(param.argument, nodes); - break; - case 'AssignmentPattern': - extractIdentifiers(param.left, nodes); - break; - } - return nodes; -} -const isFunctionType = (node) => { - return /Function(?:Expression|Declaration)$|Method$/.test(node.type); -}; -const isStaticProperty = (node) => node && - (node.type === 'ObjectProperty' || node.type === 'ObjectMethod') && - !node.computed; +function walkIdentifiers(root, onIdentifier, includeAll = false, parentStack = [], knownIds = Object.create(null)) { + { + return; + } +} +function isReferencedIdentifier(id, parent, parentStack) { + { + return false; + } +} +function isInDestructureAssignment(parent, parentStack) { + if (parent && + (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')) { + let i = parentStack.length; + while (i--) { + const p = parentStack[i]; + if (p.type === 'AssignmentExpression') { + return true; + } + else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) { + break; + } + } + } + return false; +} +function walkFunctionParams(node, onIdent) { + for (const p of node.params) { + for (const id of extractIdentifiers(p)) { + onIdent(id); + } + } +} +function walkBlockDeclarations(block, onIdent) { + for (const stmt of block.body) { + if (stmt.type === 'VariableDeclaration') { + if (stmt.declare) + continue; + for (const decl of stmt.declarations) { + for (const id of extractIdentifiers(decl.id)) { + onIdent(id); + } + } + } + else if (stmt.type === 'FunctionDeclaration' || + stmt.type === 'ClassDeclaration') { + if (stmt.declare || !stmt.id) + continue; + onIdent(stmt.id); + } + } +} +function extractIdentifiers(param, nodes = []) { + switch (param.type) { + case 'Identifier': + nodes.push(param); + break; + case 'MemberExpression': + let object = param; + while (object.type === 'MemberExpression') { + object = object.object; + } + nodes.push(object); + break; + case 'ObjectPattern': + for (const prop of param.properties) { + if (prop.type === 'RestElement') { + extractIdentifiers(prop.argument, nodes); + } + else { + extractIdentifiers(prop.value, nodes); + } + } + break; + case 'ArrayPattern': + param.elements.forEach(element => { + if (element) + extractIdentifiers(element, nodes); + }); + break; + case 'RestElement': + extractIdentifiers(param.argument, nodes); + break; + case 'AssignmentPattern': + extractIdentifiers(param.left, nodes); + break; + } + return nodes; +} +const isFunctionType = (node) => { + return /Function(?:Expression|Declaration)$|Method$/.test(node.type); +}; +const isStaticProperty = (node) => node && + (node.type === 'ObjectProperty' || node.type === 'ObjectMethod') && + !node.computed; const isStaticPropertyKey = (node, parent) => isStaticProperty(parent) && parent.key === node; -// these keywords should not appear inside expressions, but operators like -// typeof, instanceof and in are allowed -const prohibitedKeywordRE = new RegExp('\\b' + - ('do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' + - 'super,throw,while,yield,delete,export,import,return,switch,default,' + - 'extends,finally,continue,debugger,function,arguments,typeof,void') - .split(',') - .join('\\b|\\b') + - '\\b'); -// strip strings in expressions -const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g; -/** - * Validate a non-prefixed expression. - * This is only called when using the in-browser runtime compiler since it - * doesn't prefix expressions. - */ -function validateBrowserExpression(node, context, asParams = false, asRawStatements = false) { - const exp = node.content; - // empty expressions are validated per-directive since some directives - // do allow empty expressions. - if (!exp.trim()) { - return; - } - try { - new Function(asRawStatements - ? ` ${exp} ` - : `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`); - } - catch (e) { - let message = e.message; - const keywordMatch = exp - .replace(stripStringRE, '') - .match(prohibitedKeywordRE); - if (keywordMatch) { - message = `avoid using JavaScript keyword as property name: "${keywordMatch[0]}"`; - } - context.onError(createCompilerError(44 /* X_INVALID_EXPRESSION */, node.loc, undefined, message)); - } +// these keywords should not appear inside expressions, but operators like +// typeof, instanceof and in are allowed +const prohibitedKeywordRE = new RegExp('\\b' + + ('do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' + + 'super,throw,while,yield,delete,export,import,return,switch,default,' + + 'extends,finally,continue,debugger,function,arguments,typeof,void') + .split(',') + .join('\\b|\\b') + + '\\b'); +// strip strings in expressions +const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g; +/** + * Validate a non-prefixed expression. + * This is only called when using the in-browser runtime compiler since it + * doesn't prefix expressions. + */ +function validateBrowserExpression(node, context, asParams = false, asRawStatements = false) { + const exp = node.content; + // empty expressions are validated per-directive since some directives + // do allow empty expressions. + if (!exp.trim()) { + return; + } + try { + new Function(asRawStatements + ? ` ${exp} ` + : `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`); + } + catch (e) { + let message = e.message; + const keywordMatch = exp + .replace(stripStringRE, '') + .match(prohibitedKeywordRE); + if (keywordMatch) { + message = `avoid using JavaScript keyword as property name: "${keywordMatch[0]}"`; + } + context.onError(createCompilerError(44 /* X_INVALID_EXPRESSION */, node.loc, undefined, message)); + } } -const transformExpression = (node, context) => { - if (node.type === 5 /* INTERPOLATION */) { - node.content = processExpression(node.content, context); - } - else if (node.type === 1 /* ELEMENT */) { - // handle directives on element - for (let i = 0; i < node.props.length; i++) { - const dir = node.props[i]; - // do not process for v-on & v-for since they are special handled - if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') { - const exp = dir.exp; - const arg = dir.arg; - // do not process exp if this is v-on:arg - we need special handling - // for wrapping inline statements. - if (exp && - exp.type === 4 /* SIMPLE_EXPRESSION */ && - !(dir.name === 'on' && arg)) { - dir.exp = processExpression(exp, context, - // slot args must be processed as function params - dir.name === 'slot'); - } - if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) { - dir.arg = processExpression(arg, context); - } - } - } - } -}; -// Important: since this function uses Node.js only dependencies, it should -// always be used with a leading !true check so that it can be -// tree-shaken from the browser build. -function processExpression(node, context, -// some expressions like v-slot props & v-for aliases should be parsed as -// function params -asParams = false, -// v-on handler values may contain multiple statements -asRawStatements = false, localVars = Object.create(context.identifiers)) { - { - if ((process.env.NODE_ENV !== 'production')) { - // simple in-browser validation (same logic in 2.x) - validateBrowserExpression(node, context, asParams, asRawStatements); - } - return node; - } +const transformExpression = (node, context) => { + if (node.type === 5 /* INTERPOLATION */) { + node.content = processExpression(node.content, context); + } + else if (node.type === 1 /* ELEMENT */) { + // handle directives on element + for (let i = 0; i < node.props.length; i++) { + const dir = node.props[i]; + // do not process for v-on & v-for since they are special handled + if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') { + const exp = dir.exp; + const arg = dir.arg; + // do not process exp if this is v-on:arg - we need special handling + // for wrapping inline statements. + if (exp && + exp.type === 4 /* SIMPLE_EXPRESSION */ && + !(dir.name === 'on' && arg)) { + dir.exp = processExpression(exp, context, + // slot args must be processed as function params + dir.name === 'slot'); + } + if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) { + dir.arg = processExpression(arg, context); + } + } + } + } +}; +// Important: since this function uses Node.js only dependencies, it should +// always be used with a leading !true check so that it can be +// tree-shaken from the browser build. +function processExpression(node, context, +// some expressions like v-slot props & v-for aliases should be parsed as +// function params +asParams = false, +// v-on handler values may contain multiple statements +asRawStatements = false, localVars = Object.create(context.identifiers)) { + { + if ((process.env.NODE_ENV !== 'production')) { + // simple in-browser validation (same logic in 2.x) + validateBrowserExpression(node, context, asParams, asRawStatements); + } + return node; + } } -const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => { - return processIf(node, dir, context, (ifNode, branch, isRoot) => { - // #1587: We need to dynamically increment the key based on the current - // node's sibling nodes, since chained v-if/else branches are - // rendered at the same depth - const siblings = context.parent.children; - let i = siblings.indexOf(ifNode); - let key = 0; - while (i-- >= 0) { - const sibling = siblings[i]; - if (sibling && sibling.type === 9 /* IF */) { - key += sibling.branches.length; - } - } - // Exit callback. Complete the codegenNode when all children have been - // transformed. - return () => { - if (isRoot) { - ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context); - } - else { - // attach this branch's codegen node to the v-if root. - const parentCondition = getParentCondition(ifNode.codegenNode); - parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context); - } - }; - }); -}); -// target-agnostic transform used for both Client and SSR -function processIf(node, dir, context, processCodegen) { - if (dir.name !== 'else' && - (!dir.exp || !dir.exp.content.trim())) { - const loc = dir.exp ? dir.exp.loc : node.loc; - context.onError(createCompilerError(28 /* X_V_IF_NO_EXPRESSION */, dir.loc)); - dir.exp = createSimpleExpression(`true`, false, loc); - } - if ((process.env.NODE_ENV !== 'production') && true && dir.exp) { - validateBrowserExpression(dir.exp, context); - } - if (dir.name === 'if') { - const branch = createIfBranch(node, dir); - const ifNode = { - type: 9 /* IF */, - loc: node.loc, - branches: [branch] - }; - context.replaceNode(ifNode); - if (processCodegen) { - return processCodegen(ifNode, branch, true); - } - } - else { - // locate the adjacent v-if - const siblings = context.parent.children; - const comments = []; - let i = siblings.indexOf(node); - while (i-- >= -1) { - const sibling = siblings[i]; - if ((process.env.NODE_ENV !== 'production') && sibling && sibling.type === 3 /* COMMENT */) { - context.removeNode(sibling); - comments.unshift(sibling); - continue; - } - if (sibling && - sibling.type === 2 /* TEXT */ && - !sibling.content.trim().length) { - context.removeNode(sibling); - continue; - } - if (sibling && sibling.type === 9 /* IF */) { - // Check if v-else was followed by v-else-if - if (dir.name === 'else-if' && - sibling.branches[sibling.branches.length - 1].condition === undefined) { - context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc)); - } - // move the node to the if node's branches - context.removeNode(); - const branch = createIfBranch(node, dir); - if ((process.env.NODE_ENV !== 'production') && - comments.length && - // #3619 ignore comments if the v-if is direct child of <transition> - !(context.parent && - context.parent.type === 1 /* ELEMENT */ && - isBuiltInType(context.parent.tag, 'transition'))) { - branch.children = [...comments, ...branch.children]; - } - // check if user is forcing same key on different branches - if ((process.env.NODE_ENV !== 'production') || !true) { - const key = branch.userKey; - if (key) { - sibling.branches.forEach(({ userKey }) => { - if (isSameKey(userKey, key)) { - context.onError(createCompilerError(29 /* X_V_IF_SAME_KEY */, branch.userKey.loc)); - } - }); - } - } - sibling.branches.push(branch); - const onExit = processCodegen && processCodegen(sibling, branch, false); - // since the branch was removed, it will not be traversed. - // make sure to traverse here. - traverseNode(branch, context); - // call on exit - if (onExit) - onExit(); - // make sure to reset currentNode after traversal to indicate this - // node has been removed. - context.currentNode = null; - } - else { - context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc)); - } - break; - } - } -} -function createIfBranch(node, dir) { - const isTemplateIf = node.tagType === 3 /* TEMPLATE */; - return { - type: 10 /* IF_BRANCH */, - loc: node.loc, - condition: dir.name === 'else' ? undefined : dir.exp, - children: isTemplateIf && !findDir(node, 'for') ? node.children : [node], - userKey: findProp(node, `key`), - isTemplateIf - }; -} -function createCodegenNodeForBranch(branch, keyIndex, context) { - if (branch.condition) { - return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, keyIndex, context), - // make sure to pass in asBlock: true so that the comment node call - // closes the current block. - createCallExpression(context.helper(CREATE_COMMENT), [ - (process.env.NODE_ENV !== 'production') ? '"v-if"' : '""', - 'true' - ])); - } - else { - return createChildrenCodegenNode(branch, keyIndex, context); - } -} -function createChildrenCodegenNode(branch, keyIndex, context) { - const { helper } = context; - const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */)); - const { children } = branch; - const firstChild = children[0]; - const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* ELEMENT */; - if (needFragmentWrapper) { - if (children.length === 1 && firstChild.type === 11 /* FOR */) { - // optimize away nested fragments when child is a ForNode - const vnodeCall = firstChild.codegenNode; - injectProp(vnodeCall, keyProperty, context); - return vnodeCall; - } - else { - let patchFlag = 64 /* STABLE_FRAGMENT */; - let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */]; - // check if the fragment actually contains a single valid child with - // the rest being comments - if ((process.env.NODE_ENV !== 'production') && - !branch.isTemplateIf && - children.filter(c => c.type !== 3 /* COMMENT */).length === 1) { - patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */; - patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`; - } - return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${patchFlagText} */` : ``), undefined, undefined, true, false, false /* isComponent */, branch.loc); - } - } - else { - const ret = firstChild.codegenNode; - const vnodeCall = getMemoedVNodeCall(ret); - // Change createVNode to createBlock. - if (vnodeCall.type === 13 /* VNODE_CALL */) { - makeBlock(vnodeCall, context); - } - // inject branch key - injectProp(vnodeCall, keyProperty, context); - return ret; - } -} -function isSameKey(a, b) { - if (!a || a.type !== b.type) { - return false; - } - if (a.type === 6 /* ATTRIBUTE */) { - if (a.value.content !== b.value.content) { - return false; - } - } - else { - // directive - const exp = a.exp; - const branchExp = b.exp; - if (exp.type !== branchExp.type) { - return false; - } - if (exp.type !== 4 /* SIMPLE_EXPRESSION */ || - exp.isStatic !== branchExp.isStatic || - exp.content !== branchExp.content) { - return false; - } - } - return true; -} -function getParentCondition(node) { - while (true) { - if (node.type === 19 /* JS_CONDITIONAL_EXPRESSION */) { - if (node.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) { - node = node.alternate; - } - else { - return node; - } - } - else if (node.type === 20 /* JS_CACHE_EXPRESSION */) { - node = node.value; - } - } +const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => { + return processIf(node, dir, context, (ifNode, branch, isRoot) => { + // #1587: We need to dynamically increment the key based on the current + // node's sibling nodes, since chained v-if/else branches are + // rendered at the same depth + const siblings = context.parent.children; + let i = siblings.indexOf(ifNode); + let key = 0; + while (i-- >= 0) { + const sibling = siblings[i]; + if (sibling && sibling.type === 9 /* IF */) { + key += sibling.branches.length; + } + } + // Exit callback. Complete the codegenNode when all children have been + // transformed. + return () => { + if (isRoot) { + ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context); + } + else { + // attach this branch's codegen node to the v-if root. + const parentCondition = getParentCondition(ifNode.codegenNode); + parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context); + } + }; + }); +}); +// target-agnostic transform used for both Client and SSR +function processIf(node, dir, context, processCodegen) { + if (dir.name !== 'else' && + (!dir.exp || !dir.exp.content.trim())) { + const loc = dir.exp ? dir.exp.loc : node.loc; + context.onError(createCompilerError(28 /* X_V_IF_NO_EXPRESSION */, dir.loc)); + dir.exp = createSimpleExpression(`true`, false, loc); + } + if ((process.env.NODE_ENV !== 'production') && true && dir.exp) { + validateBrowserExpression(dir.exp, context); + } + if (dir.name === 'if') { + const branch = createIfBranch(node, dir); + const ifNode = { + type: 9 /* IF */, + loc: node.loc, + branches: [branch] + }; + context.replaceNode(ifNode); + if (processCodegen) { + return processCodegen(ifNode, branch, true); + } + } + else { + // locate the adjacent v-if + const siblings = context.parent.children; + const comments = []; + let i = siblings.indexOf(node); + while (i-- >= -1) { + const sibling = siblings[i]; + if ((process.env.NODE_ENV !== 'production') && sibling && sibling.type === 3 /* COMMENT */) { + context.removeNode(sibling); + comments.unshift(sibling); + continue; + } + if (sibling && + sibling.type === 2 /* TEXT */ && + !sibling.content.trim().length) { + context.removeNode(sibling); + continue; + } + if (sibling && sibling.type === 9 /* IF */) { + // Check if v-else was followed by v-else-if + if (dir.name === 'else-if' && + sibling.branches[sibling.branches.length - 1].condition === undefined) { + context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc)); + } + // move the node to the if node's branches + context.removeNode(); + const branch = createIfBranch(node, dir); + if ((process.env.NODE_ENV !== 'production') && + comments.length && + // #3619 ignore comments if the v-if is direct child of <transition> + !(context.parent && + context.parent.type === 1 /* ELEMENT */ && + isBuiltInType(context.parent.tag, 'transition'))) { + branch.children = [...comments, ...branch.children]; + } + // check if user is forcing same key on different branches + if ((process.env.NODE_ENV !== 'production') || !true) { + const key = branch.userKey; + if (key) { + sibling.branches.forEach(({ userKey }) => { + if (isSameKey(userKey, key)) { + context.onError(createCompilerError(29 /* X_V_IF_SAME_KEY */, branch.userKey.loc)); + } + }); + } + } + sibling.branches.push(branch); + const onExit = processCodegen && processCodegen(sibling, branch, false); + // since the branch was removed, it will not be traversed. + // make sure to traverse here. + traverseNode(branch, context); + // call on exit + if (onExit) + onExit(); + // make sure to reset currentNode after traversal to indicate this + // node has been removed. + context.currentNode = null; + } + else { + context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc)); + } + break; + } + } +} +function createIfBranch(node, dir) { + const isTemplateIf = node.tagType === 3 /* TEMPLATE */; + return { + type: 10 /* IF_BRANCH */, + loc: node.loc, + condition: dir.name === 'else' ? undefined : dir.exp, + children: isTemplateIf && !findDir(node, 'for') ? node.children : [node], + userKey: findProp(node, `key`), + isTemplateIf + }; +} +function createCodegenNodeForBranch(branch, keyIndex, context) { + if (branch.condition) { + return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, keyIndex, context), + // make sure to pass in asBlock: true so that the comment node call + // closes the current block. + createCallExpression(context.helper(CREATE_COMMENT), [ + (process.env.NODE_ENV !== 'production') ? '"v-if"' : '""', + 'true' + ])); + } + else { + return createChildrenCodegenNode(branch, keyIndex, context); + } +} +function createChildrenCodegenNode(branch, keyIndex, context) { + const { helper } = context; + const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */)); + const { children } = branch; + const firstChild = children[0]; + const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* ELEMENT */; + if (needFragmentWrapper) { + if (children.length === 1 && firstChild.type === 11 /* FOR */) { + // optimize away nested fragments when child is a ForNode + const vnodeCall = firstChild.codegenNode; + injectProp(vnodeCall, keyProperty, context); + return vnodeCall; + } + else { + let patchFlag = 64 /* STABLE_FRAGMENT */; + let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */]; + // check if the fragment actually contains a single valid child with + // the rest being comments + if ((process.env.NODE_ENV !== 'production') && + !branch.isTemplateIf && + children.filter(c => c.type !== 3 /* COMMENT */).length === 1) { + patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */; + patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`; + } + return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${patchFlagText} */` : ``), undefined, undefined, true, false, false /* isComponent */, branch.loc); + } + } + else { + const ret = firstChild.codegenNode; + const vnodeCall = getMemoedVNodeCall(ret); + // Change createVNode to createBlock. + if (vnodeCall.type === 13 /* VNODE_CALL */) { + makeBlock(vnodeCall, context); + } + // inject branch key + injectProp(vnodeCall, keyProperty, context); + return ret; + } +} +function isSameKey(a, b) { + if (!a || a.type !== b.type) { + return false; + } + if (a.type === 6 /* ATTRIBUTE */) { + if (a.value.content !== b.value.content) { + return false; + } + } + else { + // directive + const exp = a.exp; + const branchExp = b.exp; + if (exp.type !== branchExp.type) { + return false; + } + if (exp.type !== 4 /* SIMPLE_EXPRESSION */ || + exp.isStatic !== branchExp.isStatic || + exp.content !== branchExp.content) { + return false; + } + } + return true; +} +function getParentCondition(node) { + while (true) { + if (node.type === 19 /* JS_CONDITIONAL_EXPRESSION */) { + if (node.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) { + node = node.alternate; + } + else { + return node; + } + } + else if (node.type === 20 /* JS_CACHE_EXPRESSION */) { + node = node.value; + } + } } -const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => { - const { helper, removeHelper } = context; - return processFor(node, dir, context, forNode => { - // create the loop render function expression now, and add the - // iterator on exit after all children have been traversed - const renderExp = createCallExpression(helper(RENDER_LIST), [ - forNode.source - ]); - const isTemplate = isTemplateNode(node); - const memo = findDir(node, 'memo'); - const keyProp = findProp(node, `key`); - const keyExp = keyProp && - (keyProp.type === 6 /* ATTRIBUTE */ - ? createSimpleExpression(keyProp.value.content, true) - : keyProp.exp); - const keyProperty = keyProp ? createObjectProperty(`key`, keyExp) : null; - const isStableFragment = forNode.source.type === 4 /* SIMPLE_EXPRESSION */ && - forNode.source.constType > 0 /* NOT_CONSTANT */; - const fragmentFlag = isStableFragment - ? 64 /* STABLE_FRAGMENT */ - : keyProp - ? 128 /* KEYED_FRAGMENT */ - : 256 /* UNKEYED_FRAGMENT */; - forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, fragmentFlag + - ((process.env.NODE_ENV !== 'production') ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``), undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, false /* isComponent */, node.loc); - return () => { - // finish the codegen now that all children have been traversed - let childBlock; - const { children } = forNode; - // check <template v-for> key placement - if (((process.env.NODE_ENV !== 'production') || !true) && isTemplate) { - node.children.some(c => { - if (c.type === 1 /* ELEMENT */) { - const key = findProp(c, 'key'); - if (key) { - context.onError(createCompilerError(33 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc)); - return true; - } - } - }); - } - const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */; - const slotOutlet = isSlotOutlet(node) - ? node - : isTemplate && - node.children.length === 1 && - isSlotOutlet(node.children[0]) - ? node.children[0] // api-extractor somehow fails to infer this - : null; - if (slotOutlet) { - // <slot v-for="..."> or <template v-for="..."><slot/></template> - childBlock = slotOutlet.codegenNode; - if (isTemplate && keyProperty) { - // <template v-for="..." :key="..."><slot/></template> - // we need to inject the key to the renderSlot() call. - // the props for renderSlot is passed as the 3rd argument. - injectProp(childBlock, keyProperty, context); - } - } - else if (needFragmentWrapper) { - // <template v-for="..."> with text or multi-elements - // should generate a fragment block for each loop - childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, 64 /* STABLE_FRAGMENT */ + - ((process.env.NODE_ENV !== 'production') - ? ` /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */` - : ``), undefined, undefined, true, undefined, false /* isComponent */); - } - else { - // Normal element v-for. Directly use the child's codegenNode - // but mark it as a block. - childBlock = children[0] - .codegenNode; - if (isTemplate && keyProperty) { - injectProp(childBlock, keyProperty, context); - } - if (childBlock.isBlock !== !isStableFragment) { - if (childBlock.isBlock) { - // switch from block to vnode - removeHelper(OPEN_BLOCK); - removeHelper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent)); - } - else { - // switch from vnode to block - removeHelper(getVNodeHelper(context.inSSR, childBlock.isComponent)); - } - } - childBlock.isBlock = !isStableFragment; - if (childBlock.isBlock) { - helper(OPEN_BLOCK); - helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent)); - } - else { - helper(getVNodeHelper(context.inSSR, childBlock.isComponent)); - } - } - if (memo) { - const loop = createFunctionExpression(createForLoopParams(forNode.parseResult, [ - createSimpleExpression(`_cached`) - ])); - loop.body = createBlockStatement([ - createCompoundExpression([`const _memo = (`, memo.exp, `)`]), - createCompoundExpression([ - `if (_cached`, - ...(keyExp ? [` && _cached.key === `, keyExp] : []), - ` && ${context.helperString(IS_MEMO_SAME)}(_cached, _memo)) return _cached` - ]), - createCompoundExpression([`const _item = `, childBlock]), - createSimpleExpression(`_item.memo = _memo`), - createSimpleExpression(`return _item`) - ]); - renderExp.arguments.push(loop, createSimpleExpression(`_cache`), createSimpleExpression(String(context.cached++))); - } - else { - renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */)); - } - }; - }); -}); -// target-agnostic transform used for both Client and SSR -function processFor(node, dir, context, processCodegen) { - if (!dir.exp) { - context.onError(createCompilerError(31 /* X_V_FOR_NO_EXPRESSION */, dir.loc)); - return; - } - const parseResult = parseForExpression( - // can only be simple expression because vFor transform is applied - // before expression transform. - dir.exp, context); - if (!parseResult) { - context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc)); - return; - } - const { addIdentifiers, removeIdentifiers, scopes } = context; - const { source, value, key, index } = parseResult; - const forNode = { - type: 11 /* FOR */, - loc: dir.loc, - source, - valueAlias: value, - keyAlias: key, - objectIndexAlias: index, - parseResult, - children: isTemplateNode(node) ? node.children : [node] - }; - context.replaceNode(forNode); - // bookkeeping - scopes.vFor++; - const onExit = processCodegen && processCodegen(forNode); - return () => { - scopes.vFor--; - if (onExit) - onExit(); - }; -} -const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/; -// This regex doesn't cover the case if key or index aliases have destructuring, -// but those do not make sense in the first place, so this works in practice. -const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/; -const stripParensRE = /^\(|\)$/g; -function parseForExpression(input, context) { - const loc = input.loc; - const exp = input.content; - const inMatch = exp.match(forAliasRE); - if (!inMatch) - return; - const [, LHS, RHS] = inMatch; - const result = { - source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)), - value: undefined, - key: undefined, - index: undefined - }; - if ((process.env.NODE_ENV !== 'production') && true) { - validateBrowserExpression(result.source, context); - } - let valueContent = LHS.trim().replace(stripParensRE, '').trim(); - const trimmedOffset = LHS.indexOf(valueContent); - const iteratorMatch = valueContent.match(forIteratorRE); - if (iteratorMatch) { - valueContent = valueContent.replace(forIteratorRE, '').trim(); - const keyContent = iteratorMatch[1].trim(); - let keyOffset; - if (keyContent) { - keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length); - result.key = createAliasExpression(loc, keyContent, keyOffset); - if ((process.env.NODE_ENV !== 'production') && true) { - validateBrowserExpression(result.key, context, true); - } - } - if (iteratorMatch[2]) { - const indexContent = iteratorMatch[2].trim(); - if (indexContent) { - result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key - ? keyOffset + keyContent.length - : trimmedOffset + valueContent.length)); - if ((process.env.NODE_ENV !== 'production') && true) { - validateBrowserExpression(result.index, context, true); - } - } - } - } - if (valueContent) { - result.value = createAliasExpression(loc, valueContent, trimmedOffset); - if ((process.env.NODE_ENV !== 'production') && true) { - validateBrowserExpression(result.value, context, true); - } - } - return result; -} -function createAliasExpression(range, content, offset) { - return createSimpleExpression(content, false, getInnerRange(range, offset, content.length)); -} -function createForLoopParams({ value, key, index }, memoArgs = []) { - return createParamsList([value, key, index, ...memoArgs]); -} -function createParamsList(args) { - let i = args.length; - while (i--) { - if (args[i]) - break; - } - return args - .slice(0, i + 1) - .map((arg, i) => arg || createSimpleExpression(`_`.repeat(i + 1), false)); +const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => { + const { helper, removeHelper } = context; + return processFor(node, dir, context, forNode => { + // create the loop render function expression now, and add the + // iterator on exit after all children have been traversed + const renderExp = createCallExpression(helper(RENDER_LIST), [ + forNode.source + ]); + const isTemplate = isTemplateNode(node); + const memo = findDir(node, 'memo'); + const keyProp = findProp(node, `key`); + const keyExp = keyProp && + (keyProp.type === 6 /* ATTRIBUTE */ + ? createSimpleExpression(keyProp.value.content, true) + : keyProp.exp); + const keyProperty = keyProp ? createObjectProperty(`key`, keyExp) : null; + const isStableFragment = forNode.source.type === 4 /* SIMPLE_EXPRESSION */ && + forNode.source.constType > 0 /* NOT_CONSTANT */; + const fragmentFlag = isStableFragment + ? 64 /* STABLE_FRAGMENT */ + : keyProp + ? 128 /* KEYED_FRAGMENT */ + : 256 /* UNKEYED_FRAGMENT */; + forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, fragmentFlag + + ((process.env.NODE_ENV !== 'production') ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``), undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, false /* isComponent */, node.loc); + return () => { + // finish the codegen now that all children have been traversed + let childBlock; + const { children } = forNode; + // check <template v-for> key placement + if (((process.env.NODE_ENV !== 'production') || !true) && isTemplate) { + node.children.some(c => { + if (c.type === 1 /* ELEMENT */) { + const key = findProp(c, 'key'); + if (key) { + context.onError(createCompilerError(33 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc)); + return true; + } + } + }); + } + const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */; + const slotOutlet = isSlotOutlet(node) + ? node + : isTemplate && + node.children.length === 1 && + isSlotOutlet(node.children[0]) + ? node.children[0] // api-extractor somehow fails to infer this + : null; + if (slotOutlet) { + // <slot v-for="..."> or <template v-for="..."><slot/></template> + childBlock = slotOutlet.codegenNode; + if (isTemplate && keyProperty) { + // <template v-for="..." :key="..."><slot/></template> + // we need to inject the key to the renderSlot() call. + // the props for renderSlot is passed as the 3rd argument. + injectProp(childBlock, keyProperty, context); + } + } + else if (needFragmentWrapper) { + // <template v-for="..."> with text or multi-elements + // should generate a fragment block for each loop + childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, 64 /* STABLE_FRAGMENT */ + + ((process.env.NODE_ENV !== 'production') + ? ` /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */` + : ``), undefined, undefined, true, undefined, false /* isComponent */); + } + else { + // Normal element v-for. Directly use the child's codegenNode + // but mark it as a block. + childBlock = children[0] + .codegenNode; + if (isTemplate && keyProperty) { + injectProp(childBlock, keyProperty, context); + } + if (childBlock.isBlock !== !isStableFragment) { + if (childBlock.isBlock) { + // switch from block to vnode + removeHelper(OPEN_BLOCK); + removeHelper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent)); + } + else { + // switch from vnode to block + removeHelper(getVNodeHelper(context.inSSR, childBlock.isComponent)); + } + } + childBlock.isBlock = !isStableFragment; + if (childBlock.isBlock) { + helper(OPEN_BLOCK); + helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent)); + } + else { + helper(getVNodeHelper(context.inSSR, childBlock.isComponent)); + } + } + if (memo) { + const loop = createFunctionExpression(createForLoopParams(forNode.parseResult, [ + createSimpleExpression(`_cached`) + ])); + loop.body = createBlockStatement([ + createCompoundExpression([`const _memo = (`, memo.exp, `)`]), + createCompoundExpression([ + `if (_cached`, + ...(keyExp ? [` && _cached.key === `, keyExp] : []), + ` && ${context.helperString(IS_MEMO_SAME)}(_cached, _memo)) return _cached` + ]), + createCompoundExpression([`const _item = `, childBlock]), + createSimpleExpression(`_item.memo = _memo`), + createSimpleExpression(`return _item`) + ]); + renderExp.arguments.push(loop, createSimpleExpression(`_cache`), createSimpleExpression(String(context.cached++))); + } + else { + renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */)); + } + }; + }); +}); +// target-agnostic transform used for both Client and SSR +function processFor(node, dir, context, processCodegen) { + if (!dir.exp) { + context.onError(createCompilerError(31 /* X_V_FOR_NO_EXPRESSION */, dir.loc)); + return; + } + const parseResult = parseForExpression( + // can only be simple expression because vFor transform is applied + // before expression transform. + dir.exp, context); + if (!parseResult) { + context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc)); + return; + } + const { addIdentifiers, removeIdentifiers, scopes } = context; + const { source, value, key, index } = parseResult; + const forNode = { + type: 11 /* FOR */, + loc: dir.loc, + source, + valueAlias: value, + keyAlias: key, + objectIndexAlias: index, + parseResult, + children: isTemplateNode(node) ? node.children : [node] + }; + context.replaceNode(forNode); + // bookkeeping + scopes.vFor++; + const onExit = processCodegen && processCodegen(forNode); + return () => { + scopes.vFor--; + if (onExit) + onExit(); + }; +} +const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/; +// This regex doesn't cover the case if key or index aliases have destructuring, +// but those do not make sense in the first place, so this works in practice. +const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/; +const stripParensRE = /^\(|\)$/g; +function parseForExpression(input, context) { + const loc = input.loc; + const exp = input.content; + const inMatch = exp.match(forAliasRE); + if (!inMatch) + return; + const [, LHS, RHS] = inMatch; + const result = { + source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)), + value: undefined, + key: undefined, + index: undefined + }; + if ((process.env.NODE_ENV !== 'production') && true) { + validateBrowserExpression(result.source, context); + } + let valueContent = LHS.trim().replace(stripParensRE, '').trim(); + const trimmedOffset = LHS.indexOf(valueContent); + const iteratorMatch = valueContent.match(forIteratorRE); + if (iteratorMatch) { + valueContent = valueContent.replace(forIteratorRE, '').trim(); + const keyContent = iteratorMatch[1].trim(); + let keyOffset; + if (keyContent) { + keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length); + result.key = createAliasExpression(loc, keyContent, keyOffset); + if ((process.env.NODE_ENV !== 'production') && true) { + validateBrowserExpression(result.key, context, true); + } + } + if (iteratorMatch[2]) { + const indexContent = iteratorMatch[2].trim(); + if (indexContent) { + result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key + ? keyOffset + keyContent.length + : trimmedOffset + valueContent.length)); + if ((process.env.NODE_ENV !== 'production') && true) { + validateBrowserExpression(result.index, context, true); + } + } + } + } + if (valueContent) { + result.value = createAliasExpression(loc, valueContent, trimmedOffset); + if ((process.env.NODE_ENV !== 'production') && true) { + validateBrowserExpression(result.value, context, true); + } + } + return result; +} +function createAliasExpression(range, content, offset) { + return createSimpleExpression(content, false, getInnerRange(range, offset, content.length)); +} +function createForLoopParams({ value, key, index }, memoArgs = []) { + return createParamsList([value, key, index, ...memoArgs]); +} +function createParamsList(args) { + let i = args.length; + while (i--) { + if (args[i]) + break; + } + return args + .slice(0, i + 1) + .map((arg, i) => arg || createSimpleExpression(`_`.repeat(i + 1), false)); } -const defaultFallback = createSimpleExpression(`undefined`, false); -// A NodeTransform that: -// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed -// by transformExpression. This is only applied in non-browser builds with -// { prefixIdentifiers: true }. -// 2. Track v-slot depths so that we know a slot is inside another slot. -// Note the exit callback is executed before buildSlots() on the same node, -// so only nested slots see positive numbers. -const trackSlotScopes = (node, context) => { - if (node.type === 1 /* ELEMENT */ && - (node.tagType === 1 /* COMPONENT */ || - node.tagType === 3 /* TEMPLATE */)) { - // We are only checking non-empty v-slot here - // since we only care about slots that introduce scope variables. - const vSlot = findDir(node, 'slot'); - if (vSlot) { - context.scopes.vSlot++; - return () => { - context.scopes.vSlot--; - }; - } - } -}; -// A NodeTransform that tracks scope identifiers for scoped slots with v-for. -// This transform is only applied in non-browser builds with { prefixIdentifiers: true } -const trackVForSlotScopes = (node, context) => { - let vFor; - if (isTemplateNode(node) && - node.props.some(isVSlot) && - (vFor = findDir(node, 'for'))) { - const result = (vFor.parseResult = parseForExpression(vFor.exp, context)); - if (result) { - const { value, key, index } = result; - const { addIdentifiers, removeIdentifiers } = context; - value && addIdentifiers(value); - key && addIdentifiers(key); - index && addIdentifiers(index); - return () => { - value && removeIdentifiers(value); - key && removeIdentifiers(key); - index && removeIdentifiers(index); - }; - } - } -}; -const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc); -// Instead of being a DirectiveTransform, v-slot processing is called during -// transformElement to build the slots object for a component. -function buildSlots(node, context, buildSlotFn = buildClientSlotFn) { - context.helper(WITH_CTX); - const { children, loc } = node; - const slotsProperties = []; - const dynamicSlots = []; - // If the slot is inside a v-for or another v-slot, force it to be dynamic - // since it likely uses a scope variable. - let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0; - // 1. Check for slot with slotProps on component itself. - // <Comp v-slot="{ prop }"/> - const onComponentSlot = findDir(node, 'slot', true); - if (onComponentSlot) { - const { arg, exp } = onComponentSlot; - if (arg && !isStaticExp(arg)) { - hasDynamicSlots = true; - } - slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc))); - } - // 2. Iterate through children and check for template slots - // <template v-slot:foo="{ prop }"> - let hasTemplateSlots = false; - let hasNamedDefaultSlot = false; - const implicitDefaultChildren = []; - const seenSlotNames = new Set(); - for (let i = 0; i < children.length; i++) { - const slotElement = children[i]; - let slotDir; - if (!isTemplateNode(slotElement) || - !(slotDir = findDir(slotElement, 'slot', true))) { - // not a <template v-slot>, skip. - if (slotElement.type !== 3 /* COMMENT */) { - implicitDefaultChildren.push(slotElement); - } - continue; - } - if (onComponentSlot) { - // already has on-component slot - this is incorrect usage. - context.onError(createCompilerError(37 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc)); - break; - } - hasTemplateSlots = true; - const { children: slotChildren, loc: slotLoc } = slotElement; - const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir; - // check if name is dynamic. - let staticSlotName; - if (isStaticExp(slotName)) { - staticSlotName = slotName ? slotName.content : `default`; - } - else { - hasDynamicSlots = true; - } - const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc); - // check if this slot is conditional (v-if/v-for) - let vIf; - let vElse; - let vFor; - if ((vIf = findDir(slotElement, 'if'))) { - hasDynamicSlots = true; - dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)); - } - else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) { - // find adjacent v-if - let j = i; - let prev; - while (j--) { - prev = children[j]; - if (prev.type !== 3 /* COMMENT */) { - break; - } - } - if (prev && isTemplateNode(prev) && findDir(prev, 'if')) { - // remove node - children.splice(i, 1); - i--; - // attach this slot to previous conditional - let conditional = dynamicSlots[dynamicSlots.length - 1]; - while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) { - conditional = conditional.alternate; - } - conditional.alternate = vElse.exp - ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback) - : buildDynamicSlot(slotName, slotFunction); - } - else { - context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc)); - } - } - else if ((vFor = findDir(slotElement, 'for'))) { - hasDynamicSlots = true; - const parseResult = vFor.parseResult || - parseForExpression(vFor.exp, context); - if (parseResult) { - // Render the dynamic slots as an array and add it to the createSlot() - // args. The runtime knows how to handle it appropriately. - dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [ - parseResult.source, - createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */) - ])); - } - else { - context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc)); - } - } - else { - // check duplicate static names - if (staticSlotName) { - if (seenSlotNames.has(staticSlotName)) { - context.onError(createCompilerError(38 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc)); - continue; - } - seenSlotNames.add(staticSlotName); - if (staticSlotName === 'default') { - hasNamedDefaultSlot = true; - } - } - slotsProperties.push(createObjectProperty(slotName, slotFunction)); - } - } - if (!onComponentSlot) { - const buildDefaultSlotProperty = (props, children) => { - const fn = buildSlotFn(props, children, loc); - if (context.compatConfig) { - fn.isNonScopedSlot = true; - } - return createObjectProperty(`default`, fn); - }; - if (!hasTemplateSlots) { - // implicit default slot (on component) - slotsProperties.push(buildDefaultSlotProperty(undefined, children)); - } - else if (implicitDefaultChildren.length && - // #3766 - // with whitespace: 'preserve', whitespaces between slots will end up in - // implicitDefaultChildren. Ignore if all implicit children are whitespaces. - implicitDefaultChildren.some(node => isNonWhitespaceContent(node))) { - // implicit default slot (mixed with named slots) - if (hasNamedDefaultSlot) { - context.onError(createCompilerError(39 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc)); - } - else { - slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren)); - } - } - } - const slotFlag = hasDynamicSlots - ? 2 /* DYNAMIC */ - : hasForwardedSlots(node.children) - ? 3 /* FORWARDED */ - : 1 /* STABLE */; - let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, - // 2 = compiled but dynamic = can skip normalization, but must run diff - // 1 = compiled and static = can skip normalization AND diff as optimized - createSimpleExpression(slotFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${slotFlagsText[slotFlag]} */` : ``), false))), loc); - if (dynamicSlots.length) { - slots = createCallExpression(context.helper(CREATE_SLOTS), [ - slots, - createArrayExpression(dynamicSlots) - ]); - } - return { - slots, - hasDynamicSlots - }; -} -function buildDynamicSlot(name, fn) { - return createObjectExpression([ - createObjectProperty(`name`, name), - createObjectProperty(`fn`, fn) - ]); -} -function hasForwardedSlots(children) { - for (let i = 0; i < children.length; i++) { - const child = children[i]; - switch (child.type) { - case 1 /* ELEMENT */: - if (child.tagType === 2 /* SLOT */ || - hasForwardedSlots(child.children)) { - return true; - } - break; - case 9 /* IF */: - if (hasForwardedSlots(child.branches)) - return true; - break; - case 10 /* IF_BRANCH */: - case 11 /* FOR */: - if (hasForwardedSlots(child.children)) - return true; - break; - } - } - return false; -} -function isNonWhitespaceContent(node) { - if (node.type !== 2 /* TEXT */ && node.type !== 12 /* TEXT_CALL */) - return true; - return node.type === 2 /* TEXT */ - ? !!node.content.trim() - : isNonWhitespaceContent(node.content); +const defaultFallback = createSimpleExpression(`undefined`, false); +// A NodeTransform that: +// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed +// by transformExpression. This is only applied in non-browser builds with +// { prefixIdentifiers: true }. +// 2. Track v-slot depths so that we know a slot is inside another slot. +// Note the exit callback is executed before buildSlots() on the same node, +// so only nested slots see positive numbers. +const trackSlotScopes = (node, context) => { + if (node.type === 1 /* ELEMENT */ && + (node.tagType === 1 /* COMPONENT */ || + node.tagType === 3 /* TEMPLATE */)) { + // We are only checking non-empty v-slot here + // since we only care about slots that introduce scope variables. + const vSlot = findDir(node, 'slot'); + if (vSlot) { + context.scopes.vSlot++; + return () => { + context.scopes.vSlot--; + }; + } + } +}; +// A NodeTransform that tracks scope identifiers for scoped slots with v-for. +// This transform is only applied in non-browser builds with { prefixIdentifiers: true } +const trackVForSlotScopes = (node, context) => { + let vFor; + if (isTemplateNode(node) && + node.props.some(isVSlot) && + (vFor = findDir(node, 'for'))) { + const result = (vFor.parseResult = parseForExpression(vFor.exp, context)); + if (result) { + const { value, key, index } = result; + const { addIdentifiers, removeIdentifiers } = context; + value && addIdentifiers(value); + key && addIdentifiers(key); + index && addIdentifiers(index); + return () => { + value && removeIdentifiers(value); + key && removeIdentifiers(key); + index && removeIdentifiers(index); + }; + } + } +}; +const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc); +// Instead of being a DirectiveTransform, v-slot processing is called during +// transformElement to build the slots object for a component. +function buildSlots(node, context, buildSlotFn = buildClientSlotFn) { + context.helper(WITH_CTX); + const { children, loc } = node; + const slotsProperties = []; + const dynamicSlots = []; + // If the slot is inside a v-for or another v-slot, force it to be dynamic + // since it likely uses a scope variable. + let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0; + // 1. Check for slot with slotProps on component itself. + // <Comp v-slot="{ prop }"/> + const onComponentSlot = findDir(node, 'slot', true); + if (onComponentSlot) { + const { arg, exp } = onComponentSlot; + if (arg && !isStaticExp(arg)) { + hasDynamicSlots = true; + } + slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc))); + } + // 2. Iterate through children and check for template slots + // <template v-slot:foo="{ prop }"> + let hasTemplateSlots = false; + let hasNamedDefaultSlot = false; + const implicitDefaultChildren = []; + const seenSlotNames = new Set(); + for (let i = 0; i < children.length; i++) { + const slotElement = children[i]; + let slotDir; + if (!isTemplateNode(slotElement) || + !(slotDir = findDir(slotElement, 'slot', true))) { + // not a <template v-slot>, skip. + if (slotElement.type !== 3 /* COMMENT */) { + implicitDefaultChildren.push(slotElement); + } + continue; + } + if (onComponentSlot) { + // already has on-component slot - this is incorrect usage. + context.onError(createCompilerError(37 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc)); + break; + } + hasTemplateSlots = true; + const { children: slotChildren, loc: slotLoc } = slotElement; + const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir; + // check if name is dynamic. + let staticSlotName; + if (isStaticExp(slotName)) { + staticSlotName = slotName ? slotName.content : `default`; + } + else { + hasDynamicSlots = true; + } + const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc); + // check if this slot is conditional (v-if/v-for) + let vIf; + let vElse; + let vFor; + if ((vIf = findDir(slotElement, 'if'))) { + hasDynamicSlots = true; + dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)); + } + else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) { + // find adjacent v-if + let j = i; + let prev; + while (j--) { + prev = children[j]; + if (prev.type !== 3 /* COMMENT */) { + break; + } + } + if (prev && isTemplateNode(prev) && findDir(prev, 'if')) { + // remove node + children.splice(i, 1); + i--; + // attach this slot to previous conditional + let conditional = dynamicSlots[dynamicSlots.length - 1]; + while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) { + conditional = conditional.alternate; + } + conditional.alternate = vElse.exp + ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback) + : buildDynamicSlot(slotName, slotFunction); + } + else { + context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc)); + } + } + else if ((vFor = findDir(slotElement, 'for'))) { + hasDynamicSlots = true; + const parseResult = vFor.parseResult || + parseForExpression(vFor.exp, context); + if (parseResult) { + // Render the dynamic slots as an array and add it to the createSlot() + // args. The runtime knows how to handle it appropriately. + dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [ + parseResult.source, + createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */) + ])); + } + else { + context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc)); + } + } + else { + // check duplicate static names + if (staticSlotName) { + if (seenSlotNames.has(staticSlotName)) { + context.onError(createCompilerError(38 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc)); + continue; + } + seenSlotNames.add(staticSlotName); + if (staticSlotName === 'default') { + hasNamedDefaultSlot = true; + } + } + slotsProperties.push(createObjectProperty(slotName, slotFunction)); + } + } + if (!onComponentSlot) { + const buildDefaultSlotProperty = (props, children) => { + const fn = buildSlotFn(props, children, loc); + if (context.compatConfig) { + fn.isNonScopedSlot = true; + } + return createObjectProperty(`default`, fn); + }; + if (!hasTemplateSlots) { + // implicit default slot (on component) + slotsProperties.push(buildDefaultSlotProperty(undefined, children)); + } + else if (implicitDefaultChildren.length && + // #3766 + // with whitespace: 'preserve', whitespaces between slots will end up in + // implicitDefaultChildren. Ignore if all implicit children are whitespaces. + implicitDefaultChildren.some(node => isNonWhitespaceContent(node))) { + // implicit default slot (mixed with named slots) + if (hasNamedDefaultSlot) { + context.onError(createCompilerError(39 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc)); + } + else { + slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren)); + } + } + } + const slotFlag = hasDynamicSlots + ? 2 /* DYNAMIC */ + : hasForwardedSlots(node.children) + ? 3 /* FORWARDED */ + : 1 /* STABLE */; + let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, + // 2 = compiled but dynamic = can skip normalization, but must run diff + // 1 = compiled and static = can skip normalization AND diff as optimized + createSimpleExpression(slotFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${slotFlagsText[slotFlag]} */` : ``), false))), loc); + if (dynamicSlots.length) { + slots = createCallExpression(context.helper(CREATE_SLOTS), [ + slots, + createArrayExpression(dynamicSlots) + ]); + } + return { + slots, + hasDynamicSlots + }; +} +function buildDynamicSlot(name, fn) { + return createObjectExpression([ + createObjectProperty(`name`, name), + createObjectProperty(`fn`, fn) + ]); +} +function hasForwardedSlots(children) { + for (let i = 0; i < children.length; i++) { + const child = children[i]; + switch (child.type) { + case 1 /* ELEMENT */: + if (child.tagType === 2 /* SLOT */ || + hasForwardedSlots(child.children)) { + return true; + } + break; + case 9 /* IF */: + if (hasForwardedSlots(child.branches)) + return true; + break; + case 10 /* IF_BRANCH */: + case 11 /* FOR */: + if (hasForwardedSlots(child.children)) + return true; + break; + } + } + return false; +} +function isNonWhitespaceContent(node) { + if (node.type !== 2 /* TEXT */ && node.type !== 12 /* TEXT_CALL */) + return true; + return node.type === 2 /* TEXT */ + ? !!node.content.trim() + : isNonWhitespaceContent(node.content); } -// some directive transforms (e.g. v-model) may return a symbol for runtime -// import, which should be used instead of a resolveDirective call. -const directiveImportMap = new WeakMap(); -// generate a JavaScript AST for this element's codegen -const transformElement = (node, context) => { - // perform the work on exit, after all child expressions have been - // processed and merged. - return function postTransformElement() { - node = context.currentNode; - if (!(node.type === 1 /* ELEMENT */ && - (node.tagType === 0 /* ELEMENT */ || - node.tagType === 1 /* COMPONENT */))) { - return; - } - const { tag, props } = node; - const isComponent = node.tagType === 1 /* COMPONENT */; - // The goal of the transform is to create a codegenNode implementing the - // VNodeCall interface. - let vnodeTag = isComponent - ? resolveComponentType(node, context) - : `"${tag}"`; - const isDynamicComponent = isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT; - let vnodeProps; - let vnodeChildren; - let vnodePatchFlag; - let patchFlag = 0; - let vnodeDynamicProps; - let dynamicPropNames; - let vnodeDirectives; - let shouldUseBlock = - // dynamic component may resolve to plain elements - isDynamicComponent || - vnodeTag === TELEPORT || - vnodeTag === SUSPENSE || - (!isComponent && - // <svg> and <foreignObject> must be forced into blocks so that block - // updates inside get proper isSVG flag at runtime. (#639, #643) - // This is technically web-specific, but splitting the logic out of core - // leads to too much unnecessary complexity. - (tag === 'svg' || tag === 'foreignObject')); - // props - if (props.length > 0) { - const propsBuildResult = buildProps(node, context, undefined, isComponent, isDynamicComponent); - vnodeProps = propsBuildResult.props; - patchFlag = propsBuildResult.patchFlag; - dynamicPropNames = propsBuildResult.dynamicPropNames; - const directives = propsBuildResult.directives; - vnodeDirectives = - directives && directives.length - ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context))) - : undefined; - if (propsBuildResult.shouldUseBlock) { - shouldUseBlock = true; - } - } - // children - if (node.children.length > 0) { - if (vnodeTag === KEEP_ALIVE) { - // Although a built-in component, we compile KeepAlive with raw children - // instead of slot functions so that it can be used inside Transition - // or other Transition-wrapping HOCs. - // To ensure correct updates with block optimizations, we need to: - // 1. Force keep-alive into a block. This avoids its children being - // collected by a parent block. - shouldUseBlock = true; - // 2. Force keep-alive to always be updated, since it uses raw children. - patchFlag |= 1024 /* DYNAMIC_SLOTS */; - if ((process.env.NODE_ENV !== 'production') && node.children.length > 1) { - context.onError(createCompilerError(45 /* X_KEEP_ALIVE_INVALID_CHILDREN */, { - start: node.children[0].loc.start, - end: node.children[node.children.length - 1].loc.end, - source: '' - })); - } - } - const shouldBuildAsSlots = isComponent && - // Teleport is not a real component and has dedicated runtime handling - vnodeTag !== TELEPORT && - // explained above. - vnodeTag !== KEEP_ALIVE; - if (shouldBuildAsSlots) { - const { slots, hasDynamicSlots } = buildSlots(node, context); - vnodeChildren = slots; - if (hasDynamicSlots) { - patchFlag |= 1024 /* DYNAMIC_SLOTS */; - } - } - else if (node.children.length === 1 && vnodeTag !== TELEPORT) { - const child = node.children[0]; - const type = child.type; - // check for dynamic text children - const hasDynamicTextChild = type === 5 /* INTERPOLATION */ || - type === 8 /* COMPOUND_EXPRESSION */; - if (hasDynamicTextChild && - getConstantType(child, context) === 0 /* NOT_CONSTANT */) { - patchFlag |= 1 /* TEXT */; - } - // pass directly if the only child is a text node - // (plain / interpolation / expression) - if (hasDynamicTextChild || type === 2 /* TEXT */) { - vnodeChildren = child; - } - else { - vnodeChildren = node.children; - } - } - else { - vnodeChildren = node.children; - } - } - // patchFlag & dynamicPropNames - if (patchFlag !== 0) { - if ((process.env.NODE_ENV !== 'production')) { - if (patchFlag < 0) { - // special flags (negative and mutually exclusive) - vnodePatchFlag = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`; - } - else { - // bitwise flags - const flagNames = Object.keys(PatchFlagNames) - .map(Number) - .filter(n => n > 0 && patchFlag & n) - .map(n => PatchFlagNames[n]) - .join(`, `); - vnodePatchFlag = patchFlag + ` /* ${flagNames} */`; - } - } - else { - vnodePatchFlag = String(patchFlag); - } - if (dynamicPropNames && dynamicPropNames.length) { - vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames); - } - } - node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, isComponent, node.loc); - }; -}; -function resolveComponentType(node, context, ssr = false) { - let { tag } = node; - // 1. dynamic component - const isExplicitDynamic = isComponentTag(tag); - const isProp = findProp(node, 'is'); - if (isProp) { - if (isExplicitDynamic || - (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) { - const exp = isProp.type === 6 /* ATTRIBUTE */ - ? isProp.value && createSimpleExpression(isProp.value.content, true) - : isProp.exp; - if (exp) { - return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [ - exp - ]); - } - } - else if (isProp.type === 6 /* ATTRIBUTE */ && - isProp.value.content.startsWith('vue:')) { - // <button is="vue:xxx"> - // if not <component>, only is value that starts with "vue:" will be - // treated as component by the parse phase and reach here, unless it's - // compat mode where all is values are considered components - tag = isProp.value.content.slice(4); - } - } - // 1.5 v-is (TODO: Deprecate) - const isDir = !isExplicitDynamic && findDir(node, 'is'); - if (isDir && isDir.exp) { - return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [ - isDir.exp - ]); - } - // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...) - const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag); - if (builtIn) { - // built-ins are simply fallthroughs / have special handling during ssr - // so we don't need to import their runtime equivalents - if (!ssr) - context.helper(builtIn); - return builtIn; - } - // 5. user component (resolve) - context.helper(RESOLVE_COMPONENT); - context.components.add(tag); - return toValidAssetId(tag, `component`); -} -function buildProps(node, context, props = node.props, isComponent, isDynamicComponent, ssr = false) { - const { tag, loc: elementLoc, children } = node; - let properties = []; - const mergeArgs = []; - const runtimeDirectives = []; - const hasChildren = children.length > 0; - let shouldUseBlock = false; - // patchFlag analysis - let patchFlag = 0; - let hasRef = false; - let hasClassBinding = false; - let hasStyleBinding = false; - let hasHydrationEventBinding = false; - let hasDynamicKeys = false; - let hasVnodeHook = false; - const dynamicPropNames = []; - const analyzePatchFlag = ({ key, value }) => { - if (isStaticExp(key)) { - const name = key.content; - const isEventHandler = isOn(name); - if (isEventHandler && - (!isComponent || isDynamicComponent) && - // omit the flag for click handlers because hydration gives click - // dedicated fast path. - name.toLowerCase() !== 'onclick' && - // omit v-model handlers - name !== 'onUpdate:modelValue' && - // omit onVnodeXXX hooks - !isReservedProp(name)) { - hasHydrationEventBinding = true; - } - if (isEventHandler && isReservedProp(name)) { - hasVnodeHook = true; - } - if (value.type === 20 /* JS_CACHE_EXPRESSION */ || - ((value.type === 4 /* SIMPLE_EXPRESSION */ || - value.type === 8 /* COMPOUND_EXPRESSION */) && - getConstantType(value, context) > 0)) { - // skip if the prop is a cached handler or has constant value - return; - } - if (name === 'ref') { - hasRef = true; - } - else if (name === 'class') { - hasClassBinding = true; - } - else if (name === 'style') { - hasStyleBinding = true; - } - else if (name !== 'key' && !dynamicPropNames.includes(name)) { - dynamicPropNames.push(name); - } - // treat the dynamic class and style binding of the component as dynamic props - if (isComponent && - (name === 'class' || name === 'style') && - !dynamicPropNames.includes(name)) { - dynamicPropNames.push(name); - } - } - else { - hasDynamicKeys = true; - } - }; - for (let i = 0; i < props.length; i++) { - // static attribute - const prop = props[i]; - if (prop.type === 6 /* ATTRIBUTE */) { - const { loc, name, value } = prop; - let isStatic = true; - if (name === 'ref') { - hasRef = true; - if (context.scopes.vFor > 0) { - properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true'))); - } - } - // skip is on <component>, or is="vue:xxx" - if (name === 'is' && - (isComponentTag(tag) || - (value && value.content.startsWith('vue:')) || - (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) { - continue; - } - properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc))); - } - else { - // directives - const { name, arg, exp, loc } = prop; - const isVBind = name === 'bind'; - const isVOn = name === 'on'; - // skip v-slot - it is handled by its dedicated transform. - if (name === 'slot') { - if (!isComponent) { - context.onError(createCompilerError(40 /* X_V_SLOT_MISPLACED */, loc)); - } - continue; - } - // skip v-once/v-memo - they are handled by dedicated transforms. - if (name === 'once' || name === 'memo') { - continue; - } - // skip v-is and :is on <component> - if (name === 'is' || - (isVBind && - isStaticArgOf(arg, 'is') && - (isComponentTag(tag) || - (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) { - continue; - } - // skip v-on in SSR compilation - if (isVOn && ssr) { - continue; - } - if ( - // #938: elements with dynamic keys should be forced into blocks - (isVBind && isStaticArgOf(arg, 'key')) || - // inline before-update hooks need to force block so that it is invoked - // before children - (isVOn && hasChildren && isStaticArgOf(arg, 'vue:before-update'))) { - shouldUseBlock = true; - } - if (isVBind && isStaticArgOf(arg, 'ref') && context.scopes.vFor > 0) { - properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true'))); - } - // special case for v-bind and v-on with no argument - if (!arg && (isVBind || isVOn)) { - hasDynamicKeys = true; - if (exp) { - if (properties.length) { - mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc)); - properties = []; - } - if (isVBind) { - { - // 2.x v-bind object order compat - if ((process.env.NODE_ENV !== 'production')) { - const hasOverridableKeys = mergeArgs.some(arg => { - if (arg.type === 15 /* JS_OBJECT_EXPRESSION */) { - return arg.properties.some(({ key }) => { - if (key.type !== 4 /* SIMPLE_EXPRESSION */ || - !key.isStatic) { - return true; - } - return (key.content !== 'class' && - key.content !== 'style' && - !isOn(key.content)); - }); - } - else { - // dynamic expression - return true; - } - }); - if (hasOverridableKeys) { - checkCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context, loc); - } - } - if (isCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context)) { - mergeArgs.unshift(exp); - continue; - } - } - mergeArgs.push(exp); - } - else { - // v-on="obj" -> toHandlers(obj) - mergeArgs.push({ - type: 14 /* JS_CALL_EXPRESSION */, - loc, - callee: context.helper(TO_HANDLERS), - arguments: [exp] - }); - } - } - else { - context.onError(createCompilerError(isVBind - ? 34 /* X_V_BIND_NO_EXPRESSION */ - : 35 /* X_V_ON_NO_EXPRESSION */, loc)); - } - continue; - } - const directiveTransform = context.directiveTransforms[name]; - if (directiveTransform) { - // has built-in directive transform. - const { props, needRuntime } = directiveTransform(prop, node, context); - !ssr && props.forEach(analyzePatchFlag); - properties.push(...props); - if (needRuntime) { - runtimeDirectives.push(prop); - if (isSymbol(needRuntime)) { - directiveImportMap.set(prop, needRuntime); - } - } - } - else if (!isBuiltInDirective(name)) { - // no built-in transform, this is a user custom directive. - runtimeDirectives.push(prop); - // custom dirs may use beforeUpdate so they need to force blocks - // to ensure before-update gets called before children update - if (hasChildren) { - shouldUseBlock = true; - } - } - } - } - let propsExpression = undefined; - // has v-bind="object" or v-on="object", wrap with mergeProps - if (mergeArgs.length) { - if (properties.length) { - mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc)); - } - if (mergeArgs.length > 1) { - propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc); - } - else { - // single v-bind with nothing else - no need for a mergeProps call - propsExpression = mergeArgs[0]; - } - } - else if (properties.length) { - propsExpression = createObjectExpression(dedupeProperties(properties), elementLoc); - } - // patchFlag analysis - if (hasDynamicKeys) { - patchFlag |= 16 /* FULL_PROPS */; - } - else { - if (hasClassBinding && !isComponent) { - patchFlag |= 2 /* CLASS */; - } - if (hasStyleBinding && !isComponent) { - patchFlag |= 4 /* STYLE */; - } - if (dynamicPropNames.length) { - patchFlag |= 8 /* PROPS */; - } - if (hasHydrationEventBinding) { - patchFlag |= 32 /* HYDRATE_EVENTS */; - } - } - if (!shouldUseBlock && - (patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) && - (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) { - patchFlag |= 512 /* NEED_PATCH */; - } - // pre-normalize props, SSR is skipped for now - if (!context.inSSR && propsExpression) { - switch (propsExpression.type) { - case 15 /* JS_OBJECT_EXPRESSION */: - // means that there is no v-bind, - // but still need to deal with dynamic key binding - let classKeyIndex = -1; - let styleKeyIndex = -1; - let hasDynamicKey = false; - for (let i = 0; i < propsExpression.properties.length; i++) { - const key = propsExpression.properties[i].key; - if (isStaticExp(key)) { - if (key.content === 'class') { - classKeyIndex = i; - } - else if (key.content === 'style') { - styleKeyIndex = i; - } - } - else if (!key.isHandlerKey) { - hasDynamicKey = true; - } - } - const classProp = propsExpression.properties[classKeyIndex]; - const styleProp = propsExpression.properties[styleKeyIndex]; - // no dynamic key - if (!hasDynamicKey) { - if (classProp && !isStaticExp(classProp.value)) { - classProp.value = createCallExpression(context.helper(NORMALIZE_CLASS), [classProp.value]); - } - if (styleProp && - // the static style is compiled into an object, - // so use `hasStyleBinding` to ensure that it is a dynamic style binding - (hasStyleBinding || - (styleProp.value.type === 4 /* SIMPLE_EXPRESSION */ && - styleProp.value.content.trim()[0] === `[`) || - // v-bind:style and style both exist, - // v-bind:style with static literal object - styleProp.value.type === 17 /* JS_ARRAY_EXPRESSION */)) { - styleProp.value = createCallExpression(context.helper(NORMALIZE_STYLE), [styleProp.value]); - } - } - else { - // dynamic key binding, wrap with `normalizeProps` - propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [propsExpression]); - } - break; - case 14 /* JS_CALL_EXPRESSION */: - // mergeProps call, do nothing - break; - default: - // single v-bind - propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [ - createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [ - propsExpression - ]) - ]); - break; - } - } - return { - props: propsExpression, - directives: runtimeDirectives, - patchFlag, - dynamicPropNames, - shouldUseBlock - }; -} -// Dedupe props in an object literal. -// Literal duplicated attributes would have been warned during the parse phase, -// however, it's possible to encounter duplicated `onXXX` handlers with different -// modifiers. We also need to merge static and dynamic class / style attributes. -// - onXXX handlers / style: merge into array -// - class: merge into single expression with concatenation -function dedupeProperties(properties) { - const knownProps = new Map(); - const deduped = []; - for (let i = 0; i < properties.length; i++) { - const prop = properties[i]; - // dynamic keys are always allowed - if (prop.key.type === 8 /* COMPOUND_EXPRESSION */ || !prop.key.isStatic) { - deduped.push(prop); - continue; - } - const name = prop.key.content; - const existing = knownProps.get(name); - if (existing) { - if (name === 'style' || name === 'class' || isOn(name)) { - mergeAsArray(existing, prop); - } - // unexpected duplicate, should have emitted error during parse - } - else { - knownProps.set(name, prop); - deduped.push(prop); - } - } - return deduped; -} -function mergeAsArray(existing, incoming) { - if (existing.value.type === 17 /* JS_ARRAY_EXPRESSION */) { - existing.value.elements.push(incoming.value); - } - else { - existing.value = createArrayExpression([existing.value, incoming.value], existing.loc); - } -} -function buildDirectiveArgs(dir, context) { - const dirArgs = []; - const runtime = directiveImportMap.get(dir); - if (runtime) { - // built-in directive with runtime - dirArgs.push(context.helperString(runtime)); - } - else { - { - // inject statement for resolving directive - context.helper(RESOLVE_DIRECTIVE); - context.directives.add(dir.name); - dirArgs.push(toValidAssetId(dir.name, `directive`)); - } - } - const { loc } = dir; - if (dir.exp) - dirArgs.push(dir.exp); - if (dir.arg) { - if (!dir.exp) { - dirArgs.push(`void 0`); - } - dirArgs.push(dir.arg); - } - if (Object.keys(dir.modifiers).length) { - if (!dir.arg) { - if (!dir.exp) { - dirArgs.push(`void 0`); - } - dirArgs.push(`void 0`); - } - const trueExpression = createSimpleExpression(`true`, false, loc); - dirArgs.push(createObjectExpression(dir.modifiers.map(modifier => createObjectProperty(modifier, trueExpression)), loc)); - } - return createArrayExpression(dirArgs, dir.loc); -} -function stringifyDynamicPropNames(props) { - let propsNamesString = `[`; - for (let i = 0, l = props.length; i < l; i++) { - propsNamesString += JSON.stringify(props[i]); - if (i < l - 1) - propsNamesString += ', '; - } - return propsNamesString + `]`; -} -function isComponentTag(tag) { - return tag === 'component' || tag === 'Component'; +// some directive transforms (e.g. v-model) may return a symbol for runtime +// import, which should be used instead of a resolveDirective call. +const directiveImportMap = new WeakMap(); +// generate a JavaScript AST for this element's codegen +const transformElement = (node, context) => { + // perform the work on exit, after all child expressions have been + // processed and merged. + return function postTransformElement() { + node = context.currentNode; + if (!(node.type === 1 /* ELEMENT */ && + (node.tagType === 0 /* ELEMENT */ || + node.tagType === 1 /* COMPONENT */))) { + return; + } + const { tag, props } = node; + const isComponent = node.tagType === 1 /* COMPONENT */; + // The goal of the transform is to create a codegenNode implementing the + // VNodeCall interface. + let vnodeTag = isComponent + ? resolveComponentType(node, context) + : `"${tag}"`; + const isDynamicComponent = isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT; + let vnodeProps; + let vnodeChildren; + let vnodePatchFlag; + let patchFlag = 0; + let vnodeDynamicProps; + let dynamicPropNames; + let vnodeDirectives; + let shouldUseBlock = + // dynamic component may resolve to plain elements + isDynamicComponent || + vnodeTag === TELEPORT || + vnodeTag === SUSPENSE || + (!isComponent && + // <svg> and <foreignObject> must be forced into blocks so that block + // updates inside get proper isSVG flag at runtime. (#639, #643) + // This is technically web-specific, but splitting the logic out of core + // leads to too much unnecessary complexity. + (tag === 'svg' || tag === 'foreignObject')); + // props + if (props.length > 0) { + const propsBuildResult = buildProps(node, context, undefined, isComponent, isDynamicComponent); + vnodeProps = propsBuildResult.props; + patchFlag = propsBuildResult.patchFlag; + dynamicPropNames = propsBuildResult.dynamicPropNames; + const directives = propsBuildResult.directives; + vnodeDirectives = + directives && directives.length + ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context))) + : undefined; + if (propsBuildResult.shouldUseBlock) { + shouldUseBlock = true; + } + } + // children + if (node.children.length > 0) { + if (vnodeTag === KEEP_ALIVE) { + // Although a built-in component, we compile KeepAlive with raw children + // instead of slot functions so that it can be used inside Transition + // or other Transition-wrapping HOCs. + // To ensure correct updates with block optimizations, we need to: + // 1. Force keep-alive into a block. This avoids its children being + // collected by a parent block. + shouldUseBlock = true; + // 2. Force keep-alive to always be updated, since it uses raw children. + patchFlag |= 1024 /* DYNAMIC_SLOTS */; + if ((process.env.NODE_ENV !== 'production') && node.children.length > 1) { + context.onError(createCompilerError(45 /* X_KEEP_ALIVE_INVALID_CHILDREN */, { + start: node.children[0].loc.start, + end: node.children[node.children.length - 1].loc.end, + source: '' + })); + } + } + const shouldBuildAsSlots = isComponent && + // Teleport is not a real component and has dedicated runtime handling + vnodeTag !== TELEPORT && + // explained above. + vnodeTag !== KEEP_ALIVE; + if (shouldBuildAsSlots) { + const { slots, hasDynamicSlots } = buildSlots(node, context); + vnodeChildren = slots; + if (hasDynamicSlots) { + patchFlag |= 1024 /* DYNAMIC_SLOTS */; + } + } + else if (node.children.length === 1 && vnodeTag !== TELEPORT) { + const child = node.children[0]; + const type = child.type; + // check for dynamic text children + const hasDynamicTextChild = type === 5 /* INTERPOLATION */ || + type === 8 /* COMPOUND_EXPRESSION */; + if (hasDynamicTextChild && + getConstantType(child, context) === 0 /* NOT_CONSTANT */) { + patchFlag |= 1 /* TEXT */; + } + // pass directly if the only child is a text node + // (plain / interpolation / expression) + if (hasDynamicTextChild || type === 2 /* TEXT */) { + vnodeChildren = child; + } + else { + vnodeChildren = node.children; + } + } + else { + vnodeChildren = node.children; + } + } + // patchFlag & dynamicPropNames + if (patchFlag !== 0) { + if ((process.env.NODE_ENV !== 'production')) { + if (patchFlag < 0) { + // special flags (negative and mutually exclusive) + vnodePatchFlag = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`; + } + else { + // bitwise flags + const flagNames = Object.keys(PatchFlagNames) + .map(Number) + .filter(n => n > 0 && patchFlag & n) + .map(n => PatchFlagNames[n]) + .join(`, `); + vnodePatchFlag = patchFlag + ` /* ${flagNames} */`; + } + } + else { + vnodePatchFlag = String(patchFlag); + } + if (dynamicPropNames && dynamicPropNames.length) { + vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames); + } + } + node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, isComponent, node.loc); + }; +}; +function resolveComponentType(node, context, ssr = false) { + let { tag } = node; + // 1. dynamic component + const isExplicitDynamic = isComponentTag(tag); + const isProp = findProp(node, 'is'); + if (isProp) { + if (isExplicitDynamic || + (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) { + const exp = isProp.type === 6 /* ATTRIBUTE */ + ? isProp.value && createSimpleExpression(isProp.value.content, true) + : isProp.exp; + if (exp) { + return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [ + exp + ]); + } + } + else if (isProp.type === 6 /* ATTRIBUTE */ && + isProp.value.content.startsWith('vue:')) { + // <button is="vue:xxx"> + // if not <component>, only is value that starts with "vue:" will be + // treated as component by the parse phase and reach here, unless it's + // compat mode where all is values are considered components + tag = isProp.value.content.slice(4); + } + } + // 1.5 v-is (TODO: Deprecate) + const isDir = !isExplicitDynamic && findDir(node, 'is'); + if (isDir && isDir.exp) { + return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [ + isDir.exp + ]); + } + // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...) + const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag); + if (builtIn) { + // built-ins are simply fallthroughs / have special handling during ssr + // so we don't need to import their runtime equivalents + if (!ssr) + context.helper(builtIn); + return builtIn; + } + // 5. user component (resolve) + context.helper(RESOLVE_COMPONENT); + context.components.add(tag); + return toValidAssetId(tag, `component`); +} +function buildProps(node, context, props = node.props, isComponent, isDynamicComponent, ssr = false) { + const { tag, loc: elementLoc, children } = node; + let properties = []; + const mergeArgs = []; + const runtimeDirectives = []; + const hasChildren = children.length > 0; + let shouldUseBlock = false; + // patchFlag analysis + let patchFlag = 0; + let hasRef = false; + let hasClassBinding = false; + let hasStyleBinding = false; + let hasHydrationEventBinding = false; + let hasDynamicKeys = false; + let hasVnodeHook = false; + const dynamicPropNames = []; + const analyzePatchFlag = ({ key, value }) => { + if (isStaticExp(key)) { + const name = key.content; + const isEventHandler = isOn(name); + if (isEventHandler && + (!isComponent || isDynamicComponent) && + // omit the flag for click handlers because hydration gives click + // dedicated fast path. + name.toLowerCase() !== 'onclick' && + // omit v-model handlers + name !== 'onUpdate:modelValue' && + // omit onVnodeXXX hooks + !isReservedProp(name)) { + hasHydrationEventBinding = true; + } + if (isEventHandler && isReservedProp(name)) { + hasVnodeHook = true; + } + if (value.type === 20 /* JS_CACHE_EXPRESSION */ || + ((value.type === 4 /* SIMPLE_EXPRESSION */ || + value.type === 8 /* COMPOUND_EXPRESSION */) && + getConstantType(value, context) > 0)) { + // skip if the prop is a cached handler or has constant value + return; + } + if (name === 'ref') { + hasRef = true; + } + else if (name === 'class') { + hasClassBinding = true; + } + else if (name === 'style') { + hasStyleBinding = true; + } + else if (name !== 'key' && !dynamicPropNames.includes(name)) { + dynamicPropNames.push(name); + } + // treat the dynamic class and style binding of the component as dynamic props + if (isComponent && + (name === 'class' || name === 'style') && + !dynamicPropNames.includes(name)) { + dynamicPropNames.push(name); + } + } + else { + hasDynamicKeys = true; + } + }; + for (let i = 0; i < props.length; i++) { + // static attribute + const prop = props[i]; + if (prop.type === 6 /* ATTRIBUTE */) { + const { loc, name, value } = prop; + let isStatic = true; + if (name === 'ref') { + hasRef = true; + if (context.scopes.vFor > 0) { + properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true'))); + } + } + // skip is on <component>, or is="vue:xxx" + if (name === 'is' && + (isComponentTag(tag) || + (value && value.content.startsWith('vue:')) || + (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) { + continue; + } + properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc))); + } + else { + // directives + const { name, arg, exp, loc } = prop; + const isVBind = name === 'bind'; + const isVOn = name === 'on'; + // skip v-slot - it is handled by its dedicated transform. + if (name === 'slot') { + if (!isComponent) { + context.onError(createCompilerError(40 /* X_V_SLOT_MISPLACED */, loc)); + } + continue; + } + // skip v-once/v-memo - they are handled by dedicated transforms. + if (name === 'once' || name === 'memo') { + continue; + } + // skip v-is and :is on <component> + if (name === 'is' || + (isVBind && + isStaticArgOf(arg, 'is') && + (isComponentTag(tag) || + (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) { + continue; + } + // skip v-on in SSR compilation + if (isVOn && ssr) { + continue; + } + if ( + // #938: elements with dynamic keys should be forced into blocks + (isVBind && isStaticArgOf(arg, 'key')) || + // inline before-update hooks need to force block so that it is invoked + // before children + (isVOn && hasChildren && isStaticArgOf(arg, 'vue:before-update'))) { + shouldUseBlock = true; + } + if (isVBind && isStaticArgOf(arg, 'ref') && context.scopes.vFor > 0) { + properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true'))); + } + // special case for v-bind and v-on with no argument + if (!arg && (isVBind || isVOn)) { + hasDynamicKeys = true; + if (exp) { + if (properties.length) { + mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc)); + properties = []; + } + if (isVBind) { + { + // 2.x v-bind object order compat + if ((process.env.NODE_ENV !== 'production')) { + const hasOverridableKeys = mergeArgs.some(arg => { + if (arg.type === 15 /* JS_OBJECT_EXPRESSION */) { + return arg.properties.some(({ key }) => { + if (key.type !== 4 /* SIMPLE_EXPRESSION */ || + !key.isStatic) { + return true; + } + return (key.content !== 'class' && + key.content !== 'style' && + !isOn(key.content)); + }); + } + else { + // dynamic expression + return true; + } + }); + if (hasOverridableKeys) { + checkCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context, loc); + } + } + if (isCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context)) { + mergeArgs.unshift(exp); + continue; + } + } + mergeArgs.push(exp); + } + else { + // v-on="obj" -> toHandlers(obj) + mergeArgs.push({ + type: 14 /* JS_CALL_EXPRESSION */, + loc, + callee: context.helper(TO_HANDLERS), + arguments: [exp] + }); + } + } + else { + context.onError(createCompilerError(isVBind + ? 34 /* X_V_BIND_NO_EXPRESSION */ + : 35 /* X_V_ON_NO_EXPRESSION */, loc)); + } + continue; + } + const directiveTransform = context.directiveTransforms[name]; + if (directiveTransform) { + // has built-in directive transform. + const { props, needRuntime } = directiveTransform(prop, node, context); + !ssr && props.forEach(analyzePatchFlag); + properties.push(...props); + if (needRuntime) { + runtimeDirectives.push(prop); + if (isSymbol(needRuntime)) { + directiveImportMap.set(prop, needRuntime); + } + } + } + else if (!isBuiltInDirective(name)) { + // no built-in transform, this is a user custom directive. + runtimeDirectives.push(prop); + // custom dirs may use beforeUpdate so they need to force blocks + // to ensure before-update gets called before children update + if (hasChildren) { + shouldUseBlock = true; + } + } + } + } + let propsExpression = undefined; + // has v-bind="object" or v-on="object", wrap with mergeProps + if (mergeArgs.length) { + if (properties.length) { + mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc)); + } + if (mergeArgs.length > 1) { + propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc); + } + else { + // single v-bind with nothing else - no need for a mergeProps call + propsExpression = mergeArgs[0]; + } + } + else if (properties.length) { + propsExpression = createObjectExpression(dedupeProperties(properties), elementLoc); + } + // patchFlag analysis + if (hasDynamicKeys) { + patchFlag |= 16 /* FULL_PROPS */; + } + else { + if (hasClassBinding && !isComponent) { + patchFlag |= 2 /* CLASS */; + } + if (hasStyleBinding && !isComponent) { + patchFlag |= 4 /* STYLE */; + } + if (dynamicPropNames.length) { + patchFlag |= 8 /* PROPS */; + } + if (hasHydrationEventBinding) { + patchFlag |= 32 /* HYDRATE_EVENTS */; + } + } + if (!shouldUseBlock && + (patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) && + (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) { + patchFlag |= 512 /* NEED_PATCH */; + } + // pre-normalize props, SSR is skipped for now + if (!context.inSSR && propsExpression) { + switch (propsExpression.type) { + case 15 /* JS_OBJECT_EXPRESSION */: + // means that there is no v-bind, + // but still need to deal with dynamic key binding + let classKeyIndex = -1; + let styleKeyIndex = -1; + let hasDynamicKey = false; + for (let i = 0; i < propsExpression.properties.length; i++) { + const key = propsExpression.properties[i].key; + if (isStaticExp(key)) { + if (key.content === 'class') { + classKeyIndex = i; + } + else if (key.content === 'style') { + styleKeyIndex = i; + } + } + else if (!key.isHandlerKey) { + hasDynamicKey = true; + } + } + const classProp = propsExpression.properties[classKeyIndex]; + const styleProp = propsExpression.properties[styleKeyIndex]; + // no dynamic key + if (!hasDynamicKey) { + if (classProp && !isStaticExp(classProp.value)) { + classProp.value = createCallExpression(context.helper(NORMALIZE_CLASS), [classProp.value]); + } + if (styleProp && + // the static style is compiled into an object, + // so use `hasStyleBinding` to ensure that it is a dynamic style binding + (hasStyleBinding || + (styleProp.value.type === 4 /* SIMPLE_EXPRESSION */ && + styleProp.value.content.trim()[0] === `[`) || + // v-bind:style and style both exist, + // v-bind:style with static literal object + styleProp.value.type === 17 /* JS_ARRAY_EXPRESSION */)) { + styleProp.value = createCallExpression(context.helper(NORMALIZE_STYLE), [styleProp.value]); + } + } + else { + // dynamic key binding, wrap with `normalizeProps` + propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [propsExpression]); + } + break; + case 14 /* JS_CALL_EXPRESSION */: + // mergeProps call, do nothing + break; + default: + // single v-bind + propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [ + createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [ + propsExpression + ]) + ]); + break; + } + } + return { + props: propsExpression, + directives: runtimeDirectives, + patchFlag, + dynamicPropNames, + shouldUseBlock + }; +} +// Dedupe props in an object literal. +// Literal duplicated attributes would have been warned during the parse phase, +// however, it's possible to encounter duplicated `onXXX` handlers with different +// modifiers. We also need to merge static and dynamic class / style attributes. +// - onXXX handlers / style: merge into array +// - class: merge into single expression with concatenation +function dedupeProperties(properties) { + const knownProps = new Map(); + const deduped = []; + for (let i = 0; i < properties.length; i++) { + const prop = properties[i]; + // dynamic keys are always allowed + if (prop.key.type === 8 /* COMPOUND_EXPRESSION */ || !prop.key.isStatic) { + deduped.push(prop); + continue; + } + const name = prop.key.content; + const existing = knownProps.get(name); + if (existing) { + if (name === 'style' || name === 'class' || isOn(name)) { + mergeAsArray(existing, prop); + } + // unexpected duplicate, should have emitted error during parse + } + else { + knownProps.set(name, prop); + deduped.push(prop); + } + } + return deduped; +} +function mergeAsArray(existing, incoming) { + if (existing.value.type === 17 /* JS_ARRAY_EXPRESSION */) { + existing.value.elements.push(incoming.value); + } + else { + existing.value = createArrayExpression([existing.value, incoming.value], existing.loc); + } +} +function buildDirectiveArgs(dir, context) { + const dirArgs = []; + const runtime = directiveImportMap.get(dir); + if (runtime) { + // built-in directive with runtime + dirArgs.push(context.helperString(runtime)); + } + else { + { + // inject statement for resolving directive + context.helper(RESOLVE_DIRECTIVE); + context.directives.add(dir.name); + dirArgs.push(toValidAssetId(dir.name, `directive`)); + } + } + const { loc } = dir; + if (dir.exp) + dirArgs.push(dir.exp); + if (dir.arg) { + if (!dir.exp) { + dirArgs.push(`void 0`); + } + dirArgs.push(dir.arg); + } + if (Object.keys(dir.modifiers).length) { + if (!dir.arg) { + if (!dir.exp) { + dirArgs.push(`void 0`); + } + dirArgs.push(`void 0`); + } + const trueExpression = createSimpleExpression(`true`, false, loc); + dirArgs.push(createObjectExpression(dir.modifiers.map(modifier => createObjectProperty(modifier, trueExpression)), loc)); + } + return createArrayExpression(dirArgs, dir.loc); +} +function stringifyDynamicPropNames(props) { + let propsNamesString = `[`; + for (let i = 0, l = props.length; i < l; i++) { + propsNamesString += JSON.stringify(props[i]); + if (i < l - 1) + propsNamesString += ', '; + } + return propsNamesString + `]`; +} +function isComponentTag(tag) { + return tag === 'component' || tag === 'Component'; } -(process.env.NODE_ENV !== 'production') - ? Object.freeze({}) - : {}; -(process.env.NODE_ENV !== 'production') ? Object.freeze([]) : []; -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() : '')); +(process.env.NODE_ENV !== 'production') + ? Object.freeze({}) + : {}; +(process.env.NODE_ENV !== 'production') ? Object.freeze([]) : []; +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 transformSlotOutlet = (node, context) => { - if (isSlotOutlet(node)) { - const { children, loc } = node; - const { slotName, slotProps } = processSlotOutlet(node, context); - const slotArgs = [ - context.prefixIdentifiers ? `_ctx.$slots` : `$slots`, - slotName, - '{}', - 'undefined', - 'true' - ]; - let expectedLen = 2; - if (slotProps) { - slotArgs[2] = slotProps; - expectedLen = 3; - } - if (children.length) { - slotArgs[3] = createFunctionExpression([], children, false, false, loc); - expectedLen = 4; - } - if (context.scopeId && !context.slotted) { - expectedLen = 5; - } - slotArgs.splice(expectedLen); // remove unused arguments - node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc); - } -}; -function processSlotOutlet(node, context) { - let slotName = `"default"`; - let slotProps = undefined; - const nonNameProps = []; - for (let i = 0; i < node.props.length; i++) { - const p = node.props[i]; - if (p.type === 6 /* ATTRIBUTE */) { - if (p.value) { - if (p.name === 'name') { - slotName = JSON.stringify(p.value.content); - } - else { - p.name = camelize(p.name); - nonNameProps.push(p); - } - } - } - else { - if (p.name === 'bind' && isStaticArgOf(p.arg, 'name')) { - if (p.exp) - slotName = p.exp; - } - else { - if (p.name === 'bind' && p.arg && isStaticExp(p.arg)) { - p.arg.content = camelize(p.arg.content); - } - nonNameProps.push(p); - } - } - } - if (nonNameProps.length > 0) { - const { props, directives } = buildProps(node, context, nonNameProps, false, false); - slotProps = props; - if (directives.length) { - context.onError(createCompilerError(36 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, directives[0].loc)); - } - } - return { - slotName, - slotProps - }; +const transformSlotOutlet = (node, context) => { + if (isSlotOutlet(node)) { + const { children, loc } = node; + const { slotName, slotProps } = processSlotOutlet(node, context); + const slotArgs = [ + context.prefixIdentifiers ? `_ctx.$slots` : `$slots`, + slotName, + '{}', + 'undefined', + 'true' + ]; + let expectedLen = 2; + if (slotProps) { + slotArgs[2] = slotProps; + expectedLen = 3; + } + if (children.length) { + slotArgs[3] = createFunctionExpression([], children, false, false, loc); + expectedLen = 4; + } + if (context.scopeId && !context.slotted) { + expectedLen = 5; + } + slotArgs.splice(expectedLen); // remove unused arguments + node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc); + } +}; +function processSlotOutlet(node, context) { + let slotName = `"default"`; + let slotProps = undefined; + const nonNameProps = []; + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i]; + if (p.type === 6 /* ATTRIBUTE */) { + if (p.value) { + if (p.name === 'name') { + slotName = JSON.stringify(p.value.content); + } + else { + p.name = camelize(p.name); + nonNameProps.push(p); + } + } + } + else { + if (p.name === 'bind' && isStaticArgOf(p.arg, 'name')) { + if (p.exp) + slotName = p.exp; + } + else { + if (p.name === 'bind' && p.arg && isStaticExp(p.arg)) { + p.arg.content = camelize(p.arg.content); + } + nonNameProps.push(p); + } + } + } + if (nonNameProps.length > 0) { + const { props, directives } = buildProps(node, context, nonNameProps, false, false); + slotProps = props; + if (directives.length) { + context.onError(createCompilerError(36 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, directives[0].loc)); + } + } + return { + slotName, + slotProps + }; } -const fnExpRE = /^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/; -const transformOn = (dir, node, context, augmentor) => { - const { loc, modifiers, arg } = dir; - if (!dir.exp && !modifiers.length) { - context.onError(createCompilerError(35 /* X_V_ON_NO_EXPRESSION */, loc)); - } - let eventName; - if (arg.type === 4 /* SIMPLE_EXPRESSION */) { - if (arg.isStatic) { - let rawName = arg.content; - // TODO deprecate @vnodeXXX usage - if (rawName.startsWith('vue:')) { - rawName = `vnode-${rawName.slice(4)}`; - } - // for all event listeners, auto convert it to camelCase. See issue #2249 - eventName = createSimpleExpression(toHandlerKey(camelize$1(rawName)), true, arg.loc); - } - else { - // #2388 - eventName = createCompoundExpression([ - `${context.helperString(TO_HANDLER_KEY)}(`, - arg, - `)` - ]); - } - } - else { - // already a compound expression. - eventName = arg; - eventName.children.unshift(`${context.helperString(TO_HANDLER_KEY)}(`); - eventName.children.push(`)`); - } - // handler processing - let exp = dir.exp; - if (exp && !exp.content.trim()) { - exp = undefined; - } - let shouldCache = context.cacheHandlers && !exp && !context.inVOnce; - if (exp) { - const isMemberExp = isMemberExpression(exp.content); - const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content)); - const hasMultipleStatements = exp.content.includes(`;`); - if ((process.env.NODE_ENV !== 'production') && true) { - validateBrowserExpression(exp, context, false, hasMultipleStatements); - } - if (isInlineStatement || (shouldCache && isMemberExp)) { - // wrap inline statement in a function expression - exp = createCompoundExpression([ - `${isInlineStatement - ? `$event` - : `${``}(...args)`} => ${hasMultipleStatements ? `{` : `(`}`, - exp, - hasMultipleStatements ? `}` : `)` - ]); - } - } - let ret = { - props: [ - createObjectProperty(eventName, exp || createSimpleExpression(`() => {}`, false, loc)) - ] - }; - // apply extended compiler augmentor - if (augmentor) { - ret = augmentor(ret); - } - if (shouldCache) { - // cache handlers so that it's always the same handler being passed down. - // this avoids unnecessary re-renders when users use inline handlers on - // components. - ret.props[0].value = context.cache(ret.props[0].value); - } - // mark the key as handler for props normalization check - ret.props.forEach(p => (p.key.isHandlerKey = true)); - return ret; +const fnExpRE = /^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/; +const transformOn = (dir, node, context, augmentor) => { + const { loc, modifiers, arg } = dir; + if (!dir.exp && !modifiers.length) { + context.onError(createCompilerError(35 /* X_V_ON_NO_EXPRESSION */, loc)); + } + let eventName; + if (arg.type === 4 /* SIMPLE_EXPRESSION */) { + if (arg.isStatic) { + let rawName = arg.content; + // TODO deprecate @vnodeXXX usage + if (rawName.startsWith('vue:')) { + rawName = `vnode-${rawName.slice(4)}`; + } + // for all event listeners, auto convert it to camelCase. See issue #2249 + eventName = createSimpleExpression(toHandlerKey(camelize$1(rawName)), true, arg.loc); + } + else { + // #2388 + eventName = createCompoundExpression([ + `${context.helperString(TO_HANDLER_KEY)}(`, + arg, + `)` + ]); + } + } + else { + // already a compound expression. + eventName = arg; + eventName.children.unshift(`${context.helperString(TO_HANDLER_KEY)}(`); + eventName.children.push(`)`); + } + // handler processing + let exp = dir.exp; + if (exp && !exp.content.trim()) { + exp = undefined; + } + let shouldCache = context.cacheHandlers && !exp && !context.inVOnce; + if (exp) { + const isMemberExp = isMemberExpression(exp.content); + const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content)); + const hasMultipleStatements = exp.content.includes(`;`); + if ((process.env.NODE_ENV !== 'production') && true) { + validateBrowserExpression(exp, context, false, hasMultipleStatements); + } + if (isInlineStatement || (shouldCache && isMemberExp)) { + // wrap inline statement in a function expression + exp = createCompoundExpression([ + `${isInlineStatement + ? `$event` + : `${``}(...args)`} => ${hasMultipleStatements ? `{` : `(`}`, + exp, + hasMultipleStatements ? `}` : `)` + ]); + } + } + let ret = { + props: [ + createObjectProperty(eventName, exp || createSimpleExpression(`() => {}`, false, loc)) + ] + }; + // apply extended compiler augmentor + if (augmentor) { + ret = augmentor(ret); + } + if (shouldCache) { + // cache handlers so that it's always the same handler being passed down. + // this avoids unnecessary re-renders when users use inline handlers on + // components. + ret.props[0].value = context.cache(ret.props[0].value); + } + // mark the key as handler for props normalization check + ret.props.forEach(p => (p.key.isHandlerKey = true)); + return ret; }; -// v-bind without arg is handled directly in ./transformElements.ts due to it affecting -// codegen for the entire props object. This transform here is only for v-bind -// *with* args. -const transformBind = (dir, _node, context) => { - const { exp, modifiers, loc } = dir; - const arg = dir.arg; - if (arg.type !== 4 /* SIMPLE_EXPRESSION */) { - arg.children.unshift(`(`); - arg.children.push(`) || ""`); - } - else if (!arg.isStatic) { - arg.content = `${arg.content} || ""`; - } - // .sync is replaced by v-model:arg - if (modifiers.includes('camel')) { - if (arg.type === 4 /* SIMPLE_EXPRESSION */) { - if (arg.isStatic) { - arg.content = camelize$1(arg.content); - } - else { - arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`; - } - } - else { - arg.children.unshift(`${context.helperString(CAMELIZE)}(`); - arg.children.push(`)`); - } - } - if (!context.inSSR) { - if (modifiers.includes('prop')) { - injectPrefix(arg, '.'); - } - if (modifiers.includes('attr')) { - injectPrefix(arg, '^'); - } - } - if (!exp || - (exp.type === 4 /* SIMPLE_EXPRESSION */ && !exp.content.trim())) { - context.onError(createCompilerError(34 /* X_V_BIND_NO_EXPRESSION */, loc)); - return { - props: [createObjectProperty(arg, createSimpleExpression('', true, loc))] - }; - } - return { - props: [createObjectProperty(arg, exp)] - }; -}; -const injectPrefix = (arg, prefix) => { - if (arg.type === 4 /* SIMPLE_EXPRESSION */) { - if (arg.isStatic) { - arg.content = prefix + arg.content; - } - else { - arg.content = `\`${prefix}\${${arg.content}}\``; - } - } - else { - arg.children.unshift(`'${prefix}' + (`); - arg.children.push(`)`); - } +// v-bind without arg is handled directly in ./transformElements.ts due to it affecting +// codegen for the entire props object. This transform here is only for v-bind +// *with* args. +const transformBind = (dir, _node, context) => { + const { exp, modifiers, loc } = dir; + const arg = dir.arg; + if (arg.type !== 4 /* SIMPLE_EXPRESSION */) { + arg.children.unshift(`(`); + arg.children.push(`) || ""`); + } + else if (!arg.isStatic) { + arg.content = `${arg.content} || ""`; + } + // .sync is replaced by v-model:arg + if (modifiers.includes('camel')) { + if (arg.type === 4 /* SIMPLE_EXPRESSION */) { + if (arg.isStatic) { + arg.content = camelize$1(arg.content); + } + else { + arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`; + } + } + else { + arg.children.unshift(`${context.helperString(CAMELIZE)}(`); + arg.children.push(`)`); + } + } + if (!context.inSSR) { + if (modifiers.includes('prop')) { + injectPrefix(arg, '.'); + } + if (modifiers.includes('attr')) { + injectPrefix(arg, '^'); + } + } + if (!exp || + (exp.type === 4 /* SIMPLE_EXPRESSION */ && !exp.content.trim())) { + context.onError(createCompilerError(34 /* X_V_BIND_NO_EXPRESSION */, loc)); + return { + props: [createObjectProperty(arg, createSimpleExpression('', true, loc))] + }; + } + return { + props: [createObjectProperty(arg, exp)] + }; +}; +const injectPrefix = (arg, prefix) => { + if (arg.type === 4 /* SIMPLE_EXPRESSION */) { + if (arg.isStatic) { + arg.content = prefix + arg.content; + } + else { + arg.content = `\`${prefix}\${${arg.content}}\``; + } + } + else { + arg.children.unshift(`'${prefix}' + (`); + arg.children.push(`)`); + } }; -// Merge adjacent text nodes and expressions into a single expression -// e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child. -const transformText = (node, context) => { - if (node.type === 0 /* ROOT */ || - node.type === 1 /* ELEMENT */ || - node.type === 11 /* FOR */ || - node.type === 10 /* IF_BRANCH */) { - // perform the transform on node exit so that all expressions have already - // been processed. - return () => { - const children = node.children; - let currentContainer = undefined; - let hasText = false; - for (let i = 0; i < children.length; i++) { - const child = children[i]; - if (isText(child)) { - hasText = true; - for (let j = i + 1; j < children.length; j++) { - const next = children[j]; - if (isText(next)) { - if (!currentContainer) { - currentContainer = children[i] = createCompoundExpression([child], child.loc); - } - // merge adjacent text node into current - currentContainer.children.push(` + `, next); - children.splice(j, 1); - j--; - } - else { - currentContainer = undefined; - break; - } - } - } - } - if (!hasText || - // if this is a plain element with a single text child, leave it - // as-is since the runtime has dedicated fast path for this by directly - // setting textContent of the element. - // for component root it's always normalized anyway. - (children.length === 1 && - (node.type === 0 /* ROOT */ || - (node.type === 1 /* ELEMENT */ && - node.tagType === 0 /* ELEMENT */ && - // #3756 - // custom directives can potentially add DOM elements arbitrarily, - // we need to avoid setting textContent of the element at runtime - // to avoid accidentally overwriting the DOM elements added - // by the user through custom directives. - !node.props.find(p => p.type === 7 /* DIRECTIVE */ && - !context.directiveTransforms[p.name]) && - // in compat mode, <template> tags with no special directives - // will be rendered as a fragment so its children must be - // converted into vnodes. - !(node.tag === 'template'))))) { - return; - } - // pre-convert text nodes into createTextVNode(text) calls to avoid - // runtime normalization. - for (let i = 0; i < children.length; i++) { - const child = children[i]; - if (isText(child) || child.type === 8 /* COMPOUND_EXPRESSION */) { - const callArgs = []; - // createTextVNode defaults to single whitespace, so if it is a - // single space the code could be an empty call to save bytes. - if (child.type !== 2 /* TEXT */ || child.content !== ' ') { - callArgs.push(child); - } - // mark dynamic text with flag so it gets patched inside a block - if (!context.ssr && - getConstantType(child, context) === 0 /* NOT_CONSTANT */) { - callArgs.push(1 /* TEXT */ + - ((process.env.NODE_ENV !== 'production') ? ` /* ${PatchFlagNames[1 /* TEXT */]} */` : ``)); - } - children[i] = { - type: 12 /* TEXT_CALL */, - content: child, - loc: child.loc, - codegenNode: createCallExpression(context.helper(CREATE_TEXT), callArgs) - }; - } - } - }; - } +// Merge adjacent text nodes and expressions into a single expression +// e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child. +const transformText = (node, context) => { + if (node.type === 0 /* ROOT */ || + node.type === 1 /* ELEMENT */ || + node.type === 11 /* FOR */ || + node.type === 10 /* IF_BRANCH */) { + // perform the transform on node exit so that all expressions have already + // been processed. + return () => { + const children = node.children; + let currentContainer = undefined; + let hasText = false; + for (let i = 0; i < children.length; i++) { + const child = children[i]; + if (isText(child)) { + hasText = true; + for (let j = i + 1; j < children.length; j++) { + const next = children[j]; + if (isText(next)) { + if (!currentContainer) { + currentContainer = children[i] = createCompoundExpression([child], child.loc); + } + // merge adjacent text node into current + currentContainer.children.push(` + `, next); + children.splice(j, 1); + j--; + } + else { + currentContainer = undefined; + break; + } + } + } + } + if (!hasText || + // if this is a plain element with a single text child, leave it + // as-is since the runtime has dedicated fast path for this by directly + // setting textContent of the element. + // for component root it's always normalized anyway. + (children.length === 1 && + (node.type === 0 /* ROOT */ || + (node.type === 1 /* ELEMENT */ && + node.tagType === 0 /* ELEMENT */ && + // #3756 + // custom directives can potentially add DOM elements arbitrarily, + // we need to avoid setting textContent of the element at runtime + // to avoid accidentally overwriting the DOM elements added + // by the user through custom directives. + !node.props.find(p => p.type === 7 /* DIRECTIVE */ && + !context.directiveTransforms[p.name]) && + // in compat mode, <template> tags with no special directives + // will be rendered as a fragment so its children must be + // converted into vnodes. + !(node.tag === 'template'))))) { + return; + } + // pre-convert text nodes into createTextVNode(text) calls to avoid + // runtime normalization. + for (let i = 0; i < children.length; i++) { + const child = children[i]; + if (isText(child) || child.type === 8 /* COMPOUND_EXPRESSION */) { + const callArgs = []; + // createTextVNode defaults to single whitespace, so if it is a + // single space the code could be an empty call to save bytes. + if (child.type !== 2 /* TEXT */ || child.content !== ' ') { + callArgs.push(child); + } + // mark dynamic text with flag so it gets patched inside a block + if (!context.ssr && + getConstantType(child, context) === 0 /* NOT_CONSTANT */) { + callArgs.push(1 /* TEXT */ + + ((process.env.NODE_ENV !== 'production') ? ` /* ${PatchFlagNames[1 /* TEXT */]} */` : ``)); + } + children[i] = { + type: 12 /* TEXT_CALL */, + content: child, + loc: child.loc, + codegenNode: createCallExpression(context.helper(CREATE_TEXT), callArgs) + }; + } + } + }; + } }; -const seen = new WeakSet(); -const transformOnce = (node, context) => { - if (node.type === 1 /* ELEMENT */ && findDir(node, 'once', true)) { - if (seen.has(node) || context.inVOnce) { - return; - } - seen.add(node); - context.inVOnce = true; - context.helper(SET_BLOCK_TRACKING); - return () => { - context.inVOnce = false; - const cur = context.currentNode; - if (cur.codegenNode) { - cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */); - } - }; - } +const seen = new WeakSet(); +const transformOnce = (node, context) => { + if (node.type === 1 /* ELEMENT */ && findDir(node, 'once', true)) { + if (seen.has(node) || context.inVOnce) { + return; + } + seen.add(node); + context.inVOnce = true; + context.helper(SET_BLOCK_TRACKING); + return () => { + context.inVOnce = false; + const cur = context.currentNode; + if (cur.codegenNode) { + cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */); + } + }; + } }; -const transformModel = (dir, node, context) => { - const { exp, arg } = dir; - if (!exp) { - context.onError(createCompilerError(41 /* X_V_MODEL_NO_EXPRESSION */, dir.loc)); - return createTransformProps(); - } - const rawExp = exp.loc.source; - const expString = exp.type === 4 /* SIMPLE_EXPRESSION */ ? exp.content : rawExp; - const maybeRef = !true /* SETUP_CONST */; - if (!expString.trim() || - (!isMemberExpression(expString) && !maybeRef)) { - context.onError(createCompilerError(42 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc)); - return createTransformProps(); - } - const propName = arg ? arg : createSimpleExpression('modelValue', true); - const eventName = arg - ? isStaticExp(arg) - ? `onUpdate:${arg.content}` - : createCompoundExpression(['"onUpdate:" + ', arg]) - : `onUpdate:modelValue`; - let assignmentExp; - const eventArg = context.isTS ? `($event: any)` : `$event`; - { - assignmentExp = createCompoundExpression([ - `${eventArg} => ((`, - exp, - `) = $event)` - ]); - } - const props = [ - // modelValue: foo - createObjectProperty(propName, dir.exp), - // "onUpdate:modelValue": $event => (foo = $event) - createObjectProperty(eventName, assignmentExp) - ]; - // modelModifiers: { foo: true, "bar-baz": true } - if (dir.modifiers.length && node.tagType === 1 /* COMPONENT */) { - const modifiers = dir.modifiers - .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`) - .join(`, `); - const modifiersKey = arg - ? isStaticExp(arg) - ? `${arg.content}Modifiers` - : createCompoundExpression([arg, ' + "Modifiers"']) - : `modelModifiers`; - props.push(createObjectProperty(modifiersKey, createSimpleExpression(`{ ${modifiers} }`, false, dir.loc, 2 /* CAN_HOIST */))); - } - return createTransformProps(props); -}; -function createTransformProps(props = []) { - return { props }; +const transformModel = (dir, node, context) => { + const { exp, arg } = dir; + if (!exp) { + context.onError(createCompilerError(41 /* X_V_MODEL_NO_EXPRESSION */, dir.loc)); + return createTransformProps(); + } + const rawExp = exp.loc.source; + const expString = exp.type === 4 /* SIMPLE_EXPRESSION */ ? exp.content : rawExp; + const maybeRef = !true /* SETUP_CONST */; + if (!expString.trim() || + (!isMemberExpression(expString) && !maybeRef)) { + context.onError(createCompilerError(42 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc)); + return createTransformProps(); + } + const propName = arg ? arg : createSimpleExpression('modelValue', true); + const eventName = arg + ? isStaticExp(arg) + ? `onUpdate:${arg.content}` + : createCompoundExpression(['"onUpdate:" + ', arg]) + : `onUpdate:modelValue`; + let assignmentExp; + const eventArg = context.isTS ? `($event: any)` : `$event`; + { + assignmentExp = createCompoundExpression([ + `${eventArg} => ((`, + exp, + `) = $event)` + ]); + } + const props = [ + // modelValue: foo + createObjectProperty(propName, dir.exp), + // "onUpdate:modelValue": $event => (foo = $event) + createObjectProperty(eventName, assignmentExp) + ]; + // modelModifiers: { foo: true, "bar-baz": true } + if (dir.modifiers.length && node.tagType === 1 /* COMPONENT */) { + const modifiers = dir.modifiers + .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`) + .join(`, `); + const modifiersKey = arg + ? isStaticExp(arg) + ? `${arg.content}Modifiers` + : createCompoundExpression([arg, ' + "Modifiers"']) + : `modelModifiers`; + props.push(createObjectProperty(modifiersKey, createSimpleExpression(`{ ${modifiers} }`, false, dir.loc, 2 /* CAN_HOIST */))); + } + return createTransformProps(props); +}; +function createTransformProps(props = []) { + return { props }; } -const validDivisionCharRE = /[\w).+\-_$\]]/; -const transformFilter = (node, context) => { - if (!isCompatEnabled("COMPILER_FILTER" /* COMPILER_FILTERS */, context)) { - return; - } - if (node.type === 5 /* INTERPOLATION */) { - // filter rewrite is applied before expression transform so only - // simple expressions are possible at this stage - rewriteFilter(node.content, context); - } - if (node.type === 1 /* ELEMENT */) { - node.props.forEach((prop) => { - if (prop.type === 7 /* DIRECTIVE */ && - prop.name !== 'for' && - prop.exp) { - rewriteFilter(prop.exp, context); - } - }); - } -}; -function rewriteFilter(node, context) { - if (node.type === 4 /* SIMPLE_EXPRESSION */) { - parseFilter(node, context); - } - else { - for (let i = 0; i < node.children.length; i++) { - const child = node.children[i]; - if (typeof child !== 'object') - continue; - if (child.type === 4 /* SIMPLE_EXPRESSION */) { - parseFilter(child, context); - } - else if (child.type === 8 /* COMPOUND_EXPRESSION */) { - rewriteFilter(node, context); - } - else if (child.type === 5 /* INTERPOLATION */) { - rewriteFilter(child.content, context); - } - } - } -} -function parseFilter(node, context) { - const exp = node.content; - let inSingle = false; - let inDouble = false; - let inTemplateString = false; - let inRegex = false; - let curly = 0; - let square = 0; - let paren = 0; - let lastFilterIndex = 0; - let c, prev, i, expression, filters = []; - for (i = 0; i < exp.length; i++) { - prev = c; - c = exp.charCodeAt(i); - if (inSingle) { - if (c === 0x27 && prev !== 0x5c) - inSingle = false; - } - else if (inDouble) { - if (c === 0x22 && prev !== 0x5c) - inDouble = false; - } - else if (inTemplateString) { - if (c === 0x60 && prev !== 0x5c) - inTemplateString = false; - } - else if (inRegex) { - if (c === 0x2f && prev !== 0x5c) - inRegex = false; - } - else if (c === 0x7c && // pipe - exp.charCodeAt(i + 1) !== 0x7c && - exp.charCodeAt(i - 1) !== 0x7c && - !curly && - !square && - !paren) { - if (expression === undefined) { - // first filter, end of expression - lastFilterIndex = i + 1; - expression = exp.slice(0, i).trim(); - } - else { - pushFilter(); - } - } - else { - switch (c) { - case 0x22: - inDouble = true; - break; // " - case 0x27: - inSingle = true; - break; // ' - case 0x60: - inTemplateString = true; - break; // ` - case 0x28: - paren++; - break; // ( - case 0x29: - paren--; - break; // ) - case 0x5b: - square++; - break; // [ - case 0x5d: - square--; - break; // ] - case 0x7b: - curly++; - break; // { - case 0x7d: - curly--; - break; // } - } - if (c === 0x2f) { - // / - let j = i - 1; - let p; - // find first non-whitespace prev char - for (; j >= 0; j--) { - p = exp.charAt(j); - if (p !== ' ') - break; - } - if (!p || !validDivisionCharRE.test(p)) { - inRegex = true; - } - } - } - } - if (expression === undefined) { - expression = exp.slice(0, i).trim(); - } - else if (lastFilterIndex !== 0) { - pushFilter(); - } - function pushFilter() { - filters.push(exp.slice(lastFilterIndex, i).trim()); - lastFilterIndex = i + 1; - } - if (filters.length) { - (process.env.NODE_ENV !== 'production') && - warnDeprecation("COMPILER_FILTER" /* COMPILER_FILTERS */, context, node.loc); - for (i = 0; i < filters.length; i++) { - expression = wrapFilter(expression, filters[i], context); - } - node.content = expression; - } -} -function wrapFilter(exp, filter, context) { - context.helper(RESOLVE_FILTER); - const i = filter.indexOf('('); - if (i < 0) { - context.filters.add(filter); - return `${toValidAssetId(filter, 'filter')}(${exp})`; - } - else { - const name = filter.slice(0, i); - const args = filter.slice(i + 1); - context.filters.add(name); - return `${toValidAssetId(name, 'filter')}(${exp}${args !== ')' ? ',' + args : args}`; - } +const validDivisionCharRE = /[\w).+\-_$\]]/; +const transformFilter = (node, context) => { + if (!isCompatEnabled("COMPILER_FILTER" /* COMPILER_FILTERS */, context)) { + return; + } + if (node.type === 5 /* INTERPOLATION */) { + // filter rewrite is applied before expression transform so only + // simple expressions are possible at this stage + rewriteFilter(node.content, context); + } + if (node.type === 1 /* ELEMENT */) { + node.props.forEach((prop) => { + if (prop.type === 7 /* DIRECTIVE */ && + prop.name !== 'for' && + prop.exp) { + rewriteFilter(prop.exp, context); + } + }); + } +}; +function rewriteFilter(node, context) { + if (node.type === 4 /* SIMPLE_EXPRESSION */) { + parseFilter(node, context); + } + else { + for (let i = 0; i < node.children.length; i++) { + const child = node.children[i]; + if (typeof child !== 'object') + continue; + if (child.type === 4 /* SIMPLE_EXPRESSION */) { + parseFilter(child, context); + } + else if (child.type === 8 /* COMPOUND_EXPRESSION */) { + rewriteFilter(node, context); + } + else if (child.type === 5 /* INTERPOLATION */) { + rewriteFilter(child.content, context); + } + } + } +} +function parseFilter(node, context) { + const exp = node.content; + let inSingle = false; + let inDouble = false; + let inTemplateString = false; + let inRegex = false; + let curly = 0; + let square = 0; + let paren = 0; + let lastFilterIndex = 0; + let c, prev, i, expression, filters = []; + for (i = 0; i < exp.length; i++) { + prev = c; + c = exp.charCodeAt(i); + if (inSingle) { + if (c === 0x27 && prev !== 0x5c) + inSingle = false; + } + else if (inDouble) { + if (c === 0x22 && prev !== 0x5c) + inDouble = false; + } + else if (inTemplateString) { + if (c === 0x60 && prev !== 0x5c) + inTemplateString = false; + } + else if (inRegex) { + if (c === 0x2f && prev !== 0x5c) + inRegex = false; + } + else if (c === 0x7c && // pipe + exp.charCodeAt(i + 1) !== 0x7c && + exp.charCodeAt(i - 1) !== 0x7c && + !curly && + !square && + !paren) { + if (expression === undefined) { + // first filter, end of expression + lastFilterIndex = i + 1; + expression = exp.slice(0, i).trim(); + } + else { + pushFilter(); + } + } + else { + switch (c) { + case 0x22: + inDouble = true; + break; // " + case 0x27: + inSingle = true; + break; // ' + case 0x60: + inTemplateString = true; + break; // ` + case 0x28: + paren++; + break; // ( + case 0x29: + paren--; + break; // ) + case 0x5b: + square++; + break; // [ + case 0x5d: + square--; + break; // ] + case 0x7b: + curly++; + break; // { + case 0x7d: + curly--; + break; // } + } + if (c === 0x2f) { + // / + let j = i - 1; + let p; + // find first non-whitespace prev char + for (; j >= 0; j--) { + p = exp.charAt(j); + if (p !== ' ') + break; + } + if (!p || !validDivisionCharRE.test(p)) { + inRegex = true; + } + } + } + } + if (expression === undefined) { + expression = exp.slice(0, i).trim(); + } + else if (lastFilterIndex !== 0) { + pushFilter(); + } + function pushFilter() { + filters.push(exp.slice(lastFilterIndex, i).trim()); + lastFilterIndex = i + 1; + } + if (filters.length) { + (process.env.NODE_ENV !== 'production') && + warnDeprecation("COMPILER_FILTER" /* COMPILER_FILTERS */, context, node.loc); + for (i = 0; i < filters.length; i++) { + expression = wrapFilter(expression, filters[i], context); + } + node.content = expression; + } +} +function wrapFilter(exp, filter, context) { + context.helper(RESOLVE_FILTER); + const i = filter.indexOf('('); + if (i < 0) { + context.filters.add(filter); + return `${toValidAssetId(filter, 'filter')}(${exp})`; + } + else { + const name = filter.slice(0, i); + const args = filter.slice(i + 1); + context.filters.add(name); + return `${toValidAssetId(name, 'filter')}(${exp}${args !== ')' ? ',' + args : args}`; + } } -const seen$1 = new WeakSet(); -const transformMemo = (node, context) => { - if (node.type === 1 /* ELEMENT */) { - const dir = findDir(node, 'memo'); - if (!dir || seen$1.has(node)) { - return; - } - seen$1.add(node); - return () => { - const codegenNode = node.codegenNode || - context.currentNode.codegenNode; - if (codegenNode && codegenNode.type === 13 /* VNODE_CALL */) { - // non-component sub tree should be turned into a block - if (node.tagType !== 1 /* COMPONENT */) { - makeBlock(codegenNode, context); - } - node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [ - dir.exp, - createFunctionExpression(undefined, codegenNode), - `_cache`, - String(context.cached++) - ]); - } - }; - } +const seen$1 = new WeakSet(); +const transformMemo = (node, context) => { + if (node.type === 1 /* ELEMENT */) { + const dir = findDir(node, 'memo'); + if (!dir || seen$1.has(node)) { + return; + } + seen$1.add(node); + return () => { + const codegenNode = node.codegenNode || + context.currentNode.codegenNode; + if (codegenNode && codegenNode.type === 13 /* VNODE_CALL */) { + // non-component sub tree should be turned into a block + if (node.tagType !== 1 /* COMPONENT */) { + makeBlock(codegenNode, context); + } + node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [ + dir.exp, + createFunctionExpression(undefined, codegenNode), + `_cache`, + String(context.cached++) + ]); + } + }; + } }; -function getBaseTransformPreset(prefixIdentifiers) { - return [ - [ - transformOnce, - transformIf, - transformMemo, - transformFor, - ...([transformFilter] ), - ...((process.env.NODE_ENV !== 'production') - ? [transformExpression] - : []), - transformSlotOutlet, - transformElement, - trackSlotScopes, - transformText - ], - { - on: transformOn, - bind: transformBind, - model: transformModel - } - ]; -} -// we name it `baseCompile` so that higher order compilers like -// @vue/compiler-dom can export `compile` while re-exporting everything else. -function baseCompile(template, options = {}) { - const onError = options.onError || defaultOnError; - const isModuleMode = options.mode === 'module'; - /* istanbul ignore if */ - { - if (options.prefixIdentifiers === true) { - onError(createCompilerError(46 /* X_PREFIX_ID_NOT_SUPPORTED */)); - } - else if (isModuleMode) { - onError(createCompilerError(47 /* X_MODULE_MODE_NOT_SUPPORTED */)); - } - } - const prefixIdentifiers = !true ; - if (options.cacheHandlers) { - onError(createCompilerError(48 /* X_CACHE_HANDLER_NOT_SUPPORTED */)); - } - if (options.scopeId && !isModuleMode) { - onError(createCompilerError(49 /* X_SCOPE_ID_NOT_SUPPORTED */)); - } - const ast = isString(template) ? baseParse(template, options) : template; - const [nodeTransforms, directiveTransforms] = getBaseTransformPreset(); - transform(ast, extend({}, options, { - prefixIdentifiers, - nodeTransforms: [ - ...nodeTransforms, - ...(options.nodeTransforms || []) // user transforms - ], - directiveTransforms: extend({}, directiveTransforms, options.directiveTransforms || {} // user transforms - ) - })); - return generate(ast, extend({}, options, { - prefixIdentifiers - })); +function getBaseTransformPreset(prefixIdentifiers) { + return [ + [ + transformOnce, + transformIf, + transformMemo, + transformFor, + ...([transformFilter] ), + ...((process.env.NODE_ENV !== 'production') + ? [transformExpression] + : []), + transformSlotOutlet, + transformElement, + trackSlotScopes, + transformText + ], + { + on: transformOn, + bind: transformBind, + model: transformModel + } + ]; +} +// we name it `baseCompile` so that higher order compilers like +// @vue/compiler-dom can export `compile` while re-exporting everything else. +function baseCompile(template, options = {}) { + const onError = options.onError || defaultOnError; + const isModuleMode = options.mode === 'module'; + /* istanbul ignore if */ + { + if (options.prefixIdentifiers === true) { + onError(createCompilerError(46 /* X_PREFIX_ID_NOT_SUPPORTED */)); + } + else if (isModuleMode) { + onError(createCompilerError(47 /* X_MODULE_MODE_NOT_SUPPORTED */)); + } + } + const prefixIdentifiers = !true ; + if (options.cacheHandlers) { + onError(createCompilerError(48 /* X_CACHE_HANDLER_NOT_SUPPORTED */)); + } + if (options.scopeId && !isModuleMode) { + onError(createCompilerError(49 /* X_SCOPE_ID_NOT_SUPPORTED */)); + } + const ast = isString(template) ? baseParse(template, options) : template; + const [nodeTransforms, directiveTransforms] = getBaseTransformPreset(); + transform(ast, extend({}, options, { + prefixIdentifiers, + nodeTransforms: [ + ...nodeTransforms, + ...(options.nodeTransforms || []) // user transforms + ], + directiveTransforms: extend({}, directiveTransforms, options.directiveTransforms || {} // user transforms + ) + })); + return generate(ast, extend({}, options, { + prefixIdentifiers + })); } const noopDirectiveTransform = () => ({ props: [] }); @@ -5675,27 +5675,27 @@ var require$$1 = /*@__PURE__*/getAugmentedNamespace(shared_esmBundler); var compilerCore = require$$0; var shared = require$$1; - const V_MODEL_RADIO = Symbol(`vModelRadio` ); - const V_MODEL_CHECKBOX = Symbol(`vModelCheckbox` ); - const V_MODEL_TEXT = Symbol(`vModelText` ); - const V_MODEL_SELECT = Symbol(`vModelSelect` ); - const V_MODEL_DYNAMIC = Symbol(`vModelDynamic` ); - const V_ON_WITH_MODIFIERS = Symbol(`vOnModifiersGuard` ); - const V_ON_WITH_KEYS = Symbol(`vOnKeysGuard` ); - const V_SHOW = Symbol(`vShow` ); - const TRANSITION = Symbol(`Transition` ); - const TRANSITION_GROUP = Symbol(`TransitionGroup` ); - compilerCore.registerRuntimeHelpers({ - [V_MODEL_RADIO]: `vModelRadio`, - [V_MODEL_CHECKBOX]: `vModelCheckbox`, - [V_MODEL_TEXT]: `vModelText`, - [V_MODEL_SELECT]: `vModelSelect`, - [V_MODEL_DYNAMIC]: `vModelDynamic`, - [V_ON_WITH_MODIFIERS]: `withModifiers`, - [V_ON_WITH_KEYS]: `withKeys`, - [V_SHOW]: `vShow`, - [TRANSITION]: `Transition`, - [TRANSITION_GROUP]: `TransitionGroup` + const V_MODEL_RADIO = Symbol(`vModelRadio` ); + const V_MODEL_CHECKBOX = Symbol(`vModelCheckbox` ); + const V_MODEL_TEXT = Symbol(`vModelText` ); + const V_MODEL_SELECT = Symbol(`vModelSelect` ); + const V_MODEL_DYNAMIC = Symbol(`vModelDynamic` ); + const V_ON_WITH_MODIFIERS = Symbol(`vOnModifiersGuard` ); + const V_ON_WITH_KEYS = Symbol(`vOnKeysGuard` ); + const V_SHOW = Symbol(`vShow` ); + const TRANSITION = Symbol(`Transition` ); + const TRANSITION_GROUP = Symbol(`TransitionGroup` ); + compilerCore.registerRuntimeHelpers({ + [V_MODEL_RADIO]: `vModelRadio`, + [V_MODEL_CHECKBOX]: `vModelCheckbox`, + [V_MODEL_TEXT]: `vModelText`, + [V_MODEL_SELECT]: `vModelSelect`, + [V_MODEL_DYNAMIC]: `vModelDynamic`, + [V_ON_WITH_MODIFIERS]: `withModifiers`, + [V_ON_WITH_KEYS]: `withKeys`, + [V_SHOW]: `vShow`, + [TRANSITION]: `Transition`, + [TRANSITION_GROUP]: `TransitionGroup` }); var namedCharacterReferences = { @@ -7932,856 +7932,856 @@ var require$$1 = /*@__PURE__*/getAugmentedNamespace(shared_esmBundler); "CounterClockwiseContourIntegral;": "∳" }; - // lazy compute this to make this file tree-shakable for browser - let maxCRNameLength; - const decodeHtml = (rawText, asAttr) => { - let offset = 0; - const end = rawText.length; - let decodedText = ''; - function advance(length) { - offset += length; - rawText = rawText.slice(length); - } - while (offset < end) { - const head = /&(?:#x?)?/i.exec(rawText); - if (!head || offset + head.index >= end) { - const remaining = end - offset; - decodedText += rawText.slice(0, remaining); - advance(remaining); - break; - } - // Advance to the "&". - decodedText += rawText.slice(0, head.index); - advance(head.index); - if (head[0] === '&') { - // Named character reference. - let name = ''; - let value = undefined; - if (/[0-9a-z]/i.test(rawText[1])) { - if (!maxCRNameLength) { - maxCRNameLength = Object.keys(namedCharacterReferences).reduce((max, name) => Math.max(max, name.length), 0); - } - for (let length = maxCRNameLength; !value && length > 0; --length) { - name = rawText.slice(1, 1 + length); - value = namedCharacterReferences[name]; - } - if (value) { - const semi = name.endsWith(';'); - if (asAttr && - !semi && - /[=a-z0-9]/i.test(rawText[name.length + 1] || '')) { - decodedText += '&' + name; - advance(1 + name.length); - } - else { - decodedText += value; - advance(1 + name.length); - } - } - else { - decodedText += '&' + name; - advance(1 + name.length); - } - } - else { - decodedText += '&'; - advance(1); - } - } - else { - // Numeric character reference. - const hex = head[0] === '&#x'; - const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/; - const body = pattern.exec(rawText); - if (!body) { - decodedText += head[0]; - advance(head[0].length); - } - else { - // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state - let cp = Number.parseInt(body[1], hex ? 16 : 10); - if (cp === 0) { - cp = 0xfffd; - } - else if (cp > 0x10ffff) { - cp = 0xfffd; - } - else if (cp >= 0xd800 && cp <= 0xdfff) { - cp = 0xfffd; - } - else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) ; - else if ((cp >= 0x01 && cp <= 0x08) || - cp === 0x0b || - (cp >= 0x0d && cp <= 0x1f) || - (cp >= 0x7f && cp <= 0x9f)) { - cp = CCR_REPLACEMENTS[cp] || cp; - } - decodedText += String.fromCodePoint(cp); - advance(body[0].length); - } - } - } - return decodedText; - }; - // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state - const CCR_REPLACEMENTS = { - 0x80: 0x20ac, - 0x82: 0x201a, - 0x83: 0x0192, - 0x84: 0x201e, - 0x85: 0x2026, - 0x86: 0x2020, - 0x87: 0x2021, - 0x88: 0x02c6, - 0x89: 0x2030, - 0x8a: 0x0160, - 0x8b: 0x2039, - 0x8c: 0x0152, - 0x8e: 0x017d, - 0x91: 0x2018, - 0x92: 0x2019, - 0x93: 0x201c, - 0x94: 0x201d, - 0x95: 0x2022, - 0x96: 0x2013, - 0x97: 0x2014, - 0x98: 0x02dc, - 0x99: 0x2122, - 0x9a: 0x0161, - 0x9b: 0x203a, - 0x9c: 0x0153, - 0x9e: 0x017e, - 0x9f: 0x0178 + // lazy compute this to make this file tree-shakable for browser + let maxCRNameLength; + const decodeHtml = (rawText, asAttr) => { + let offset = 0; + const end = rawText.length; + let decodedText = ''; + function advance(length) { + offset += length; + rawText = rawText.slice(length); + } + while (offset < end) { + const head = /&(?:#x?)?/i.exec(rawText); + if (!head || offset + head.index >= end) { + const remaining = end - offset; + decodedText += rawText.slice(0, remaining); + advance(remaining); + break; + } + // Advance to the "&". + decodedText += rawText.slice(0, head.index); + advance(head.index); + if (head[0] === '&') { + // Named character reference. + let name = ''; + let value = undefined; + if (/[0-9a-z]/i.test(rawText[1])) { + if (!maxCRNameLength) { + maxCRNameLength = Object.keys(namedCharacterReferences).reduce((max, name) => Math.max(max, name.length), 0); + } + for (let length = maxCRNameLength; !value && length > 0; --length) { + name = rawText.slice(1, 1 + length); + value = namedCharacterReferences[name]; + } + if (value) { + const semi = name.endsWith(';'); + if (asAttr && + !semi && + /[=a-z0-9]/i.test(rawText[name.length + 1] || '')) { + decodedText += '&' + name; + advance(1 + name.length); + } + else { + decodedText += value; + advance(1 + name.length); + } + } + else { + decodedText += '&' + name; + advance(1 + name.length); + } + } + else { + decodedText += '&'; + advance(1); + } + } + else { + // Numeric character reference. + const hex = head[0] === '&#x'; + const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/; + const body = pattern.exec(rawText); + if (!body) { + decodedText += head[0]; + advance(head[0].length); + } + else { + // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state + let cp = Number.parseInt(body[1], hex ? 16 : 10); + if (cp === 0) { + cp = 0xfffd; + } + else if (cp > 0x10ffff) { + cp = 0xfffd; + } + else if (cp >= 0xd800 && cp <= 0xdfff) { + cp = 0xfffd; + } + else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) ; + else if ((cp >= 0x01 && cp <= 0x08) || + cp === 0x0b || + (cp >= 0x0d && cp <= 0x1f) || + (cp >= 0x7f && cp <= 0x9f)) { + cp = CCR_REPLACEMENTS[cp] || cp; + } + decodedText += String.fromCodePoint(cp); + advance(body[0].length); + } + } + } + return decodedText; + }; + // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state + const CCR_REPLACEMENTS = { + 0x80: 0x20ac, + 0x82: 0x201a, + 0x83: 0x0192, + 0x84: 0x201e, + 0x85: 0x2026, + 0x86: 0x2020, + 0x87: 0x2021, + 0x88: 0x02c6, + 0x89: 0x2030, + 0x8a: 0x0160, + 0x8b: 0x2039, + 0x8c: 0x0152, + 0x8e: 0x017d, + 0x91: 0x2018, + 0x92: 0x2019, + 0x93: 0x201c, + 0x94: 0x201d, + 0x95: 0x2022, + 0x96: 0x2013, + 0x97: 0x2014, + 0x98: 0x02dc, + 0x99: 0x2122, + 0x9a: 0x0161, + 0x9b: 0x203a, + 0x9c: 0x0153, + 0x9e: 0x017e, + 0x9f: 0x0178 }; - const isRawTextContainer = /*#__PURE__*/ shared.makeMap('style,iframe,script,noscript', true); - const parserOptions = { - isVoidTag: shared.isVoidTag, - isNativeTag: tag => shared.isHTMLTag(tag) || shared.isSVGTag(tag), - isPreTag: tag => tag === 'pre', - decodeEntities: decodeHtml, - isBuiltInComponent: (tag) => { - if (compilerCore.isBuiltInType(tag, `Transition`)) { - return TRANSITION; - } - else if (compilerCore.isBuiltInType(tag, `TransitionGroup`)) { - return TRANSITION_GROUP; - } - }, - // https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher - getNamespace(tag, parent) { - let ns = parent ? parent.ns : 0 /* HTML */; - if (parent && ns === 2 /* MATH_ML */) { - if (parent.tag === 'annotation-xml') { - if (tag === 'svg') { - return 1 /* SVG */; - } - if (parent.props.some(a => a.type === 6 /* ATTRIBUTE */ && - a.name === 'encoding' && - a.value != null && - (a.value.content === 'text/html' || - a.value.content === 'application/xhtml+xml'))) { - ns = 0 /* HTML */; - } - } - else if (/^m(?:[ions]|text)$/.test(parent.tag) && - tag !== 'mglyph' && - tag !== 'malignmark') { - ns = 0 /* HTML */; - } - } - else if (parent && ns === 1 /* SVG */) { - if (parent.tag === 'foreignObject' || - parent.tag === 'desc' || - parent.tag === 'title') { - ns = 0 /* HTML */; - } - } - if (ns === 0 /* HTML */) { - if (tag === 'svg') { - return 1 /* SVG */; - } - if (tag === 'math') { - return 2 /* MATH_ML */; - } - } - return ns; - }, - // https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments - getTextMode({ tag, ns }) { - if (ns === 0 /* HTML */) { - if (tag === 'textarea' || tag === 'title') { - return 1 /* RCDATA */; - } - if (isRawTextContainer(tag)) { - return 2 /* RAWTEXT */; - } - } - return 0 /* DATA */; - } + const isRawTextContainer = /*#__PURE__*/ shared.makeMap('style,iframe,script,noscript', true); + const parserOptions = { + isVoidTag: shared.isVoidTag, + isNativeTag: tag => shared.isHTMLTag(tag) || shared.isSVGTag(tag), + isPreTag: tag => tag === 'pre', + decodeEntities: decodeHtml, + isBuiltInComponent: (tag) => { + if (compilerCore.isBuiltInType(tag, `Transition`)) { + return TRANSITION; + } + else if (compilerCore.isBuiltInType(tag, `TransitionGroup`)) { + return TRANSITION_GROUP; + } + }, + // https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher + getNamespace(tag, parent) { + let ns = parent ? parent.ns : 0 /* HTML */; + if (parent && ns === 2 /* MATH_ML */) { + if (parent.tag === 'annotation-xml') { + if (tag === 'svg') { + return 1 /* SVG */; + } + if (parent.props.some(a => a.type === 6 /* ATTRIBUTE */ && + a.name === 'encoding' && + a.value != null && + (a.value.content === 'text/html' || + a.value.content === 'application/xhtml+xml'))) { + ns = 0 /* HTML */; + } + } + else if (/^m(?:[ions]|text)$/.test(parent.tag) && + tag !== 'mglyph' && + tag !== 'malignmark') { + ns = 0 /* HTML */; + } + } + else if (parent && ns === 1 /* SVG */) { + if (parent.tag === 'foreignObject' || + parent.tag === 'desc' || + parent.tag === 'title') { + ns = 0 /* HTML */; + } + } + if (ns === 0 /* HTML */) { + if (tag === 'svg') { + return 1 /* SVG */; + } + if (tag === 'math') { + return 2 /* MATH_ML */; + } + } + return ns; + }, + // https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments + getTextMode({ tag, ns }) { + if (ns === 0 /* HTML */) { + if (tag === 'textarea' || tag === 'title') { + return 1 /* RCDATA */; + } + if (isRawTextContainer(tag)) { + return 2 /* RAWTEXT */; + } + } + return 0 /* DATA */; + } }; - // Parse inline CSS strings for static style attributes into an object. - // This is a NodeTransform since it works on the static `style` attribute and - // converts it into a dynamic equivalent: - // style="color: red" -> :style='{ "color": "red" }' - // It is then processed by `transformElement` and included in the generated - // props. - const transformStyle = node => { - if (node.type === 1 /* ELEMENT */) { - node.props.forEach((p, i) => { - if (p.type === 6 /* ATTRIBUTE */ && p.name === 'style' && p.value) { - // replace p with an expression node - node.props[i] = { - type: 7 /* DIRECTIVE */, - name: `bind`, - arg: compilerCore.createSimpleExpression(`style`, true, p.loc), - exp: parseInlineCSS(p.value.content, p.loc), - modifiers: [], - loc: p.loc - }; - } - }); - } - }; - const parseInlineCSS = (cssText, loc) => { - const normalized = shared.parseStringStyle(cssText); - return compilerCore.createSimpleExpression(JSON.stringify(normalized), false, loc, 3 /* CAN_STRINGIFY */); + // Parse inline CSS strings for static style attributes into an object. + // This is a NodeTransform since it works on the static `style` attribute and + // converts it into a dynamic equivalent: + // style="color: red" -> :style='{ "color": "red" }' + // It is then processed by `transformElement` and included in the generated + // props. + const transformStyle = node => { + if (node.type === 1 /* ELEMENT */) { + node.props.forEach((p, i) => { + if (p.type === 6 /* ATTRIBUTE */ && p.name === 'style' && p.value) { + // replace p with an expression node + node.props[i] = { + type: 7 /* DIRECTIVE */, + name: `bind`, + arg: compilerCore.createSimpleExpression(`style`, true, p.loc), + exp: parseInlineCSS(p.value.content, p.loc), + modifiers: [], + loc: p.loc + }; + } + }); + } + }; + const parseInlineCSS = (cssText, loc) => { + const normalized = shared.parseStringStyle(cssText); + return compilerCore.createSimpleExpression(JSON.stringify(normalized), false, loc, 3 /* CAN_STRINGIFY */); }; - function createDOMCompilerError(code, loc) { - return compilerCore.createCompilerError(code, loc, DOMErrorMessages ); - } - const DOMErrorMessages = { - [50 /* X_V_HTML_NO_EXPRESSION */]: `v-html is missing expression.`, - [51 /* X_V_HTML_WITH_CHILDREN */]: `v-html will override element children.`, - [52 /* X_V_TEXT_NO_EXPRESSION */]: `v-text is missing expression.`, - [53 /* X_V_TEXT_WITH_CHILDREN */]: `v-text will override element children.`, - [54 /* X_V_MODEL_ON_INVALID_ELEMENT */]: `v-model can only be used on <input>, <textarea> and <select> elements.`, - [55 /* X_V_MODEL_ARG_ON_ELEMENT */]: `v-model argument is not supported on plain elements.`, - [56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */]: `v-model cannot be used on file inputs since they are read-only. Use a v-on:change listener instead.`, - [57 /* X_V_MODEL_UNNECESSARY_VALUE */]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`, - [58 /* X_V_SHOW_NO_EXPRESSION */]: `v-show is missing expression.`, - [59 /* X_TRANSITION_INVALID_CHILDREN */]: `<Transition> expects exactly one child element or component.`, - [60 /* X_IGNORED_SIDE_EFFECT_TAG */]: `Tags with side effect (<script> and <style>) are ignored in client component templates.` + function createDOMCompilerError(code, loc) { + return compilerCore.createCompilerError(code, loc, DOMErrorMessages ); + } + const DOMErrorMessages = { + [50 /* X_V_HTML_NO_EXPRESSION */]: `v-html is missing expression.`, + [51 /* X_V_HTML_WITH_CHILDREN */]: `v-html will override element children.`, + [52 /* X_V_TEXT_NO_EXPRESSION */]: `v-text is missing expression.`, + [53 /* X_V_TEXT_WITH_CHILDREN */]: `v-text will override element children.`, + [54 /* X_V_MODEL_ON_INVALID_ELEMENT */]: `v-model can only be used on <input>, <textarea> and <select> elements.`, + [55 /* X_V_MODEL_ARG_ON_ELEMENT */]: `v-model argument is not supported on plain elements.`, + [56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */]: `v-model cannot be used on file inputs since they are read-only. Use a v-on:change listener instead.`, + [57 /* X_V_MODEL_UNNECESSARY_VALUE */]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`, + [58 /* X_V_SHOW_NO_EXPRESSION */]: `v-show is missing expression.`, + [59 /* X_TRANSITION_INVALID_CHILDREN */]: `<Transition> expects exactly one child element or component.`, + [60 /* X_IGNORED_SIDE_EFFECT_TAG */]: `Tags with side effect (<script> and <style>) are ignored in client component templates.` }; - const transformVHtml = (dir, node, context) => { - const { exp, loc } = dir; - if (!exp) { - context.onError(createDOMCompilerError(50 /* X_V_HTML_NO_EXPRESSION */, loc)); - } - if (node.children.length) { - context.onError(createDOMCompilerError(51 /* X_V_HTML_WITH_CHILDREN */, loc)); - node.children.length = 0; - } - return { - props: [ - compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`innerHTML`, true, loc), exp || compilerCore.createSimpleExpression('', true)) - ] - }; + const transformVHtml = (dir, node, context) => { + const { exp, loc } = dir; + if (!exp) { + context.onError(createDOMCompilerError(50 /* X_V_HTML_NO_EXPRESSION */, loc)); + } + if (node.children.length) { + context.onError(createDOMCompilerError(51 /* X_V_HTML_WITH_CHILDREN */, loc)); + node.children.length = 0; + } + return { + props: [ + compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`innerHTML`, true, loc), exp || compilerCore.createSimpleExpression('', true)) + ] + }; }; - const transformVText = (dir, node, context) => { - const { exp, loc } = dir; - if (!exp) { - context.onError(createDOMCompilerError(52 /* X_V_TEXT_NO_EXPRESSION */, loc)); - } - if (node.children.length) { - context.onError(createDOMCompilerError(53 /* X_V_TEXT_WITH_CHILDREN */, loc)); - node.children.length = 0; - } - return { - props: [ - compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`textContent`, true), exp - ? compilerCore.getConstantType(exp, context) > 0 - ? exp - : compilerCore.createCallExpression(context.helperString(compilerCore.TO_DISPLAY_STRING), [exp], loc) - : compilerCore.createSimpleExpression('', true)) - ] - }; + const transformVText = (dir, node, context) => { + const { exp, loc } = dir; + if (!exp) { + context.onError(createDOMCompilerError(52 /* X_V_TEXT_NO_EXPRESSION */, loc)); + } + if (node.children.length) { + context.onError(createDOMCompilerError(53 /* X_V_TEXT_WITH_CHILDREN */, loc)); + node.children.length = 0; + } + return { + props: [ + compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`textContent`, true), exp + ? compilerCore.getConstantType(exp, context) > 0 + ? exp + : compilerCore.createCallExpression(context.helperString(compilerCore.TO_DISPLAY_STRING), [exp], loc) + : compilerCore.createSimpleExpression('', true)) + ] + }; }; - const transformModel = (dir, node, context) => { - const baseResult = compilerCore.transformModel(dir, node, context); - // base transform has errors OR component v-model (only need props) - if (!baseResult.props.length || node.tagType === 1 /* COMPONENT */) { - return baseResult; - } - if (dir.arg) { - context.onError(createDOMCompilerError(55 /* X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc)); - } - function checkDuplicatedValue() { - const value = compilerCore.findProp(node, 'value'); - if (value) { - context.onError(createDOMCompilerError(57 /* X_V_MODEL_UNNECESSARY_VALUE */, value.loc)); - } - } - const { tag } = node; - const isCustomElement = context.isCustomElement(tag); - if (tag === 'input' || - tag === 'textarea' || - tag === 'select' || - isCustomElement) { - let directiveToUse = V_MODEL_TEXT; - let isInvalidType = false; - if (tag === 'input' || isCustomElement) { - const type = compilerCore.findProp(node, `type`); - if (type) { - if (type.type === 7 /* DIRECTIVE */) { - // :type="foo" - directiveToUse = V_MODEL_DYNAMIC; - } - else if (type.value) { - switch (type.value.content) { - case 'radio': - directiveToUse = V_MODEL_RADIO; - break; - case 'checkbox': - directiveToUse = V_MODEL_CHECKBOX; - break; - case 'file': - isInvalidType = true; - context.onError(createDOMCompilerError(56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc)); - break; - default: - // text type - checkDuplicatedValue(); - break; - } - } - } - else if (compilerCore.hasDynamicKeyVBind(node)) { - // element has bindings with dynamic keys, which can possibly contain - // "type". - directiveToUse = V_MODEL_DYNAMIC; - } - else { - // text type - checkDuplicatedValue(); - } - } - else if (tag === 'select') { - directiveToUse = V_MODEL_SELECT; - } - else { - // textarea - checkDuplicatedValue(); - } - // inject runtime directive - // by returning the helper symbol via needRuntime - // the import will replaced a resolveDirective call. - if (!isInvalidType) { - baseResult.needRuntime = context.helper(directiveToUse); - } - } - else { - context.onError(createDOMCompilerError(54 /* X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc)); - } - // native vmodel doesn't need the `modelValue` props since they are also - // passed to the runtime as `binding.value`. removing it reduces code size. - baseResult.props = baseResult.props.filter(p => !(p.key.type === 4 /* SIMPLE_EXPRESSION */ && - p.key.content === 'modelValue')); - return baseResult; + const transformModel = (dir, node, context) => { + const baseResult = compilerCore.transformModel(dir, node, context); + // base transform has errors OR component v-model (only need props) + if (!baseResult.props.length || node.tagType === 1 /* COMPONENT */) { + return baseResult; + } + if (dir.arg) { + context.onError(createDOMCompilerError(55 /* X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc)); + } + function checkDuplicatedValue() { + const value = compilerCore.findProp(node, 'value'); + if (value) { + context.onError(createDOMCompilerError(57 /* X_V_MODEL_UNNECESSARY_VALUE */, value.loc)); + } + } + const { tag } = node; + const isCustomElement = context.isCustomElement(tag); + if (tag === 'input' || + tag === 'textarea' || + tag === 'select' || + isCustomElement) { + let directiveToUse = V_MODEL_TEXT; + let isInvalidType = false; + if (tag === 'input' || isCustomElement) { + const type = compilerCore.findProp(node, `type`); + if (type) { + if (type.type === 7 /* DIRECTIVE */) { + // :type="foo" + directiveToUse = V_MODEL_DYNAMIC; + } + else if (type.value) { + switch (type.value.content) { + case 'radio': + directiveToUse = V_MODEL_RADIO; + break; + case 'checkbox': + directiveToUse = V_MODEL_CHECKBOX; + break; + case 'file': + isInvalidType = true; + context.onError(createDOMCompilerError(56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc)); + break; + default: + // text type + checkDuplicatedValue(); + break; + } + } + } + else if (compilerCore.hasDynamicKeyVBind(node)) { + // element has bindings with dynamic keys, which can possibly contain + // "type". + directiveToUse = V_MODEL_DYNAMIC; + } + else { + // text type + checkDuplicatedValue(); + } + } + else if (tag === 'select') { + directiveToUse = V_MODEL_SELECT; + } + else { + // textarea + checkDuplicatedValue(); + } + // inject runtime directive + // by returning the helper symbol via needRuntime + // the import will replaced a resolveDirective call. + if (!isInvalidType) { + baseResult.needRuntime = context.helper(directiveToUse); + } + } + else { + context.onError(createDOMCompilerError(54 /* X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc)); + } + // native vmodel doesn't need the `modelValue` props since they are also + // passed to the runtime as `binding.value`. removing it reduces code size. + baseResult.props = baseResult.props.filter(p => !(p.key.type === 4 /* SIMPLE_EXPRESSION */ && + p.key.content === 'modelValue')); + return baseResult; }; - const isEventOptionModifier = /*#__PURE__*/ shared.makeMap(`passive,once,capture`); - const isNonKeyModifier = /*#__PURE__*/ shared.makeMap( - // event propagation management - `stop,prevent,self,` + - // system modifiers + exact - `ctrl,shift,alt,meta,exact,` + - // mouse - `middle`); - // left & right could be mouse or key modifiers based on event type - const maybeKeyModifier = /*#__PURE__*/ shared.makeMap('left,right'); - const isKeyboardEvent = /*#__PURE__*/ shared.makeMap(`onkeyup,onkeydown,onkeypress`, true); - const resolveModifiers = (key, modifiers, context, loc) => { - const keyModifiers = []; - const nonKeyModifiers = []; - const eventOptionModifiers = []; - for (let i = 0; i < modifiers.length; i++) { - const modifier = modifiers[i]; - if (modifier === 'native' && - compilerCore.checkCompatEnabled("COMPILER_V_ON_NATIVE" /* COMPILER_V_ON_NATIVE */, context, loc)) { - eventOptionModifiers.push(modifier); - } - else if (isEventOptionModifier(modifier)) { - // eventOptionModifiers: modifiers for addEventListener() options, - // e.g. .passive & .capture - eventOptionModifiers.push(modifier); - } - else { - // runtimeModifiers: modifiers that needs runtime guards - if (maybeKeyModifier(modifier)) { - if (compilerCore.isStaticExp(key)) { - if (isKeyboardEvent(key.content)) { - keyModifiers.push(modifier); - } - else { - nonKeyModifiers.push(modifier); - } - } - else { - keyModifiers.push(modifier); - nonKeyModifiers.push(modifier); - } - } - else { - if (isNonKeyModifier(modifier)) { - nonKeyModifiers.push(modifier); - } - else { - keyModifiers.push(modifier); - } - } - } - } - return { - keyModifiers, - nonKeyModifiers, - eventOptionModifiers - }; - }; - const transformClick = (key, event) => { - const isStaticClick = compilerCore.isStaticExp(key) && key.content.toLowerCase() === 'onclick'; - return isStaticClick - ? compilerCore.createSimpleExpression(event, true) - : key.type !== 4 /* SIMPLE_EXPRESSION */ - ? compilerCore.createCompoundExpression([ - `(`, - key, - `) === "onClick" ? "${event}" : (`, - key, - `)` - ]) - : key; - }; - const transformOn = (dir, node, context) => { - return compilerCore.transformOn(dir, node, context, baseResult => { - const { modifiers } = dir; - if (!modifiers.length) - return baseResult; - let { key, value: handlerExp } = baseResult.props[0]; - const { keyModifiers, nonKeyModifiers, eventOptionModifiers } = resolveModifiers(key, modifiers, context, dir.loc); - // normalize click.right and click.middle since they don't actually fire - if (nonKeyModifiers.includes('right')) { - key = transformClick(key, `onContextmenu`); - } - if (nonKeyModifiers.includes('middle')) { - key = transformClick(key, `onMouseup`); - } - if (nonKeyModifiers.length) { - handlerExp = compilerCore.createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [ - handlerExp, - JSON.stringify(nonKeyModifiers) - ]); - } - if (keyModifiers.length && - // if event name is dynamic, always wrap with keys guard - (!compilerCore.isStaticExp(key) || isKeyboardEvent(key.content))) { - handlerExp = compilerCore.createCallExpression(context.helper(V_ON_WITH_KEYS), [ - handlerExp, - JSON.stringify(keyModifiers) - ]); - } - if (eventOptionModifiers.length) { - const modifierPostfix = eventOptionModifiers.map(shared.capitalize).join(''); - key = compilerCore.isStaticExp(key) - ? compilerCore.createSimpleExpression(`${key.content}${modifierPostfix}`, true) - : compilerCore.createCompoundExpression([`(`, key, `) + "${modifierPostfix}"`]); - } - return { - props: [compilerCore.createObjectProperty(key, handlerExp)] - }; - }); + const isEventOptionModifier = /*#__PURE__*/ shared.makeMap(`passive,once,capture`); + const isNonKeyModifier = /*#__PURE__*/ shared.makeMap( + // event propagation management + `stop,prevent,self,` + + // system modifiers + exact + `ctrl,shift,alt,meta,exact,` + + // mouse + `middle`); + // left & right could be mouse or key modifiers based on event type + const maybeKeyModifier = /*#__PURE__*/ shared.makeMap('left,right'); + const isKeyboardEvent = /*#__PURE__*/ shared.makeMap(`onkeyup,onkeydown,onkeypress`, true); + const resolveModifiers = (key, modifiers, context, loc) => { + const keyModifiers = []; + const nonKeyModifiers = []; + const eventOptionModifiers = []; + for (let i = 0; i < modifiers.length; i++) { + const modifier = modifiers[i]; + if (modifier === 'native' && + compilerCore.checkCompatEnabled("COMPILER_V_ON_NATIVE" /* COMPILER_V_ON_NATIVE */, context, loc)) { + eventOptionModifiers.push(modifier); + } + else if (isEventOptionModifier(modifier)) { + // eventOptionModifiers: modifiers for addEventListener() options, + // e.g. .passive & .capture + eventOptionModifiers.push(modifier); + } + else { + // runtimeModifiers: modifiers that needs runtime guards + if (maybeKeyModifier(modifier)) { + if (compilerCore.isStaticExp(key)) { + if (isKeyboardEvent(key.content)) { + keyModifiers.push(modifier); + } + else { + nonKeyModifiers.push(modifier); + } + } + else { + keyModifiers.push(modifier); + nonKeyModifiers.push(modifier); + } + } + else { + if (isNonKeyModifier(modifier)) { + nonKeyModifiers.push(modifier); + } + else { + keyModifiers.push(modifier); + } + } + } + } + return { + keyModifiers, + nonKeyModifiers, + eventOptionModifiers + }; + }; + const transformClick = (key, event) => { + const isStaticClick = compilerCore.isStaticExp(key) && key.content.toLowerCase() === 'onclick'; + return isStaticClick + ? compilerCore.createSimpleExpression(event, true) + : key.type !== 4 /* SIMPLE_EXPRESSION */ + ? compilerCore.createCompoundExpression([ + `(`, + key, + `) === "onClick" ? "${event}" : (`, + key, + `)` + ]) + : key; + }; + const transformOn = (dir, node, context) => { + return compilerCore.transformOn(dir, node, context, baseResult => { + const { modifiers } = dir; + if (!modifiers.length) + return baseResult; + let { key, value: handlerExp } = baseResult.props[0]; + const { keyModifiers, nonKeyModifiers, eventOptionModifiers } = resolveModifiers(key, modifiers, context, dir.loc); + // normalize click.right and click.middle since they don't actually fire + if (nonKeyModifiers.includes('right')) { + key = transformClick(key, `onContextmenu`); + } + if (nonKeyModifiers.includes('middle')) { + key = transformClick(key, `onMouseup`); + } + if (nonKeyModifiers.length) { + handlerExp = compilerCore.createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [ + handlerExp, + JSON.stringify(nonKeyModifiers) + ]); + } + if (keyModifiers.length && + // if event name is dynamic, always wrap with keys guard + (!compilerCore.isStaticExp(key) || isKeyboardEvent(key.content))) { + handlerExp = compilerCore.createCallExpression(context.helper(V_ON_WITH_KEYS), [ + handlerExp, + JSON.stringify(keyModifiers) + ]); + } + if (eventOptionModifiers.length) { + const modifierPostfix = eventOptionModifiers.map(shared.capitalize).join(''); + key = compilerCore.isStaticExp(key) + ? compilerCore.createSimpleExpression(`${key.content}${modifierPostfix}`, true) + : compilerCore.createCompoundExpression([`(`, key, `) + "${modifierPostfix}"`]); + } + return { + props: [compilerCore.createObjectProperty(key, handlerExp)] + }; + }); }; - const transformShow = (dir, node, context) => { - const { exp, loc } = dir; - if (!exp) { - context.onError(createDOMCompilerError(58 /* X_V_SHOW_NO_EXPRESSION */, loc)); - } - return { - props: [], - needRuntime: context.helper(V_SHOW) - }; + const transformShow = (dir, node, context) => { + const { exp, loc } = dir; + if (!exp) { + context.onError(createDOMCompilerError(58 /* X_V_SHOW_NO_EXPRESSION */, loc)); + } + return { + props: [], + needRuntime: context.helper(V_SHOW) + }; }; - const transformTransition = (node, context) => { - if (node.type === 1 /* ELEMENT */ && - node.tagType === 1 /* COMPONENT */) { - const component = context.isBuiltInComponent(node.tag); - if (component === TRANSITION) { - return () => { - if (!node.children.length) { - return; - } - // warn multiple transition children - if (hasMultipleChildren(node)) { - context.onError(createDOMCompilerError(59 /* X_TRANSITION_INVALID_CHILDREN */, { - start: node.children[0].loc.start, - end: node.children[node.children.length - 1].loc.end, - source: '' - })); - } - // check if it's s single child w/ v-show - // if yes, inject "persisted: true" to the transition props - const child = node.children[0]; - if (child.type === 1 /* ELEMENT */) { - for (const p of child.props) { - if (p.type === 7 /* DIRECTIVE */ && p.name === 'show') { - node.props.push({ - type: 6 /* ATTRIBUTE */, - name: 'persisted', - value: undefined, - loc: node.loc - }); - } - } - } - }; - } - } - }; - function hasMultipleChildren(node) { - // #1352 filter out potential comment nodes. - const children = (node.children = node.children.filter(c => c.type !== 3 /* COMMENT */ && - !(c.type === 2 /* TEXT */ && !c.content.trim()))); - const child = children[0]; - return (children.length !== 1 || - child.type === 11 /* FOR */ || - (child.type === 9 /* IF */ && child.branches.some(hasMultipleChildren))); + const transformTransition = (node, context) => { + if (node.type === 1 /* ELEMENT */ && + node.tagType === 1 /* COMPONENT */) { + const component = context.isBuiltInComponent(node.tag); + if (component === TRANSITION) { + return () => { + if (!node.children.length) { + return; + } + // warn multiple transition children + if (hasMultipleChildren(node)) { + context.onError(createDOMCompilerError(59 /* X_TRANSITION_INVALID_CHILDREN */, { + start: node.children[0].loc.start, + end: node.children[node.children.length - 1].loc.end, + source: '' + })); + } + // check if it's s single child w/ v-show + // if yes, inject "persisted: true" to the transition props + const child = node.children[0]; + if (child.type === 1 /* ELEMENT */) { + for (const p of child.props) { + if (p.type === 7 /* DIRECTIVE */ && p.name === 'show') { + node.props.push({ + type: 6 /* ATTRIBUTE */, + name: 'persisted', + value: undefined, + loc: node.loc + }); + } + } + } + }; + } + } + }; + function hasMultipleChildren(node) { + // #1352 filter out potential comment nodes. + const children = (node.children = node.children.filter(c => c.type !== 3 /* COMMENT */ && + !(c.type === 2 /* TEXT */ && !c.content.trim()))); + const child = children[0]; + return (children.length !== 1 || + child.type === 11 /* FOR */ || + (child.type === 9 /* IF */ && child.branches.some(hasMultipleChildren))); } - /** - * This module is Node-only. - */ - /** - * Regex for replacing placeholders for embedded constant variables - * (e.g. import URL string constants generated by compiler-sfc) - */ - const expReplaceRE = /__VUE_EXP_START__(.*?)__VUE_EXP_END__/g; - /** - * Turn eligible hoisted static trees into stringified static nodes, e.g. - * - * ```js - * const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`) - * ``` - * - * A single static vnode can contain stringified content for **multiple** - * consecutive nodes (element and plain text), called a "chunk". - * `@vue/runtime-dom` will create the content via innerHTML in a hidden - * container element and insert all the nodes in place. The call must also - * provide the number of nodes contained in the chunk so that during hydration - * we can know how many nodes the static vnode should adopt. - * - * The optimization scans a children list that contains hoisted nodes, and - * tries to find the largest chunk of consecutive hoisted nodes before running - * into a non-hoisted node or the end of the list. A chunk is then converted - * into a single static vnode and replaces the hoisted expression of the first - * node in the chunk. Other nodes in the chunk are considered "merged" and - * therefore removed from both the hoist list and the children array. - * - * This optimization is only performed in Node.js. - */ - const stringifyStatic = (children, context, parent) => { - // bail stringification for slot content - if (context.scopes.vSlot > 0) { - return; - } - let nc = 0; // current node count - let ec = 0; // current element with binding count - const currentChunk = []; - const stringifyCurrentChunk = (currentIndex) => { - if (nc >= 20 /* NODE_COUNT */ || - ec >= 5 /* ELEMENT_WITH_BINDING_COUNT */) { - // combine all currently eligible nodes into a single static vnode call - const staticCall = compilerCore.createCallExpression(context.helper(compilerCore.CREATE_STATIC), [ - JSON.stringify(currentChunk.map(node => stringifyNode(node, context)).join('')).replace(expReplaceRE, `" + $1 + "`), - // the 2nd argument indicates the number of DOM nodes this static vnode - // will insert / hydrate - String(currentChunk.length) - ]); - // replace the first node's hoisted expression with the static vnode call - replaceHoist(currentChunk[0], staticCall, context); - if (currentChunk.length > 1) { - for (let i = 1; i < currentChunk.length; i++) { - // for the merged nodes, set their hoisted expression to null - replaceHoist(currentChunk[i], null, context); - } - // also remove merged nodes from children - const deleteCount = currentChunk.length - 1; - children.splice(currentIndex - currentChunk.length + 1, deleteCount); - return deleteCount; - } - } - return 0; - }; - let i = 0; - for (; i < children.length; i++) { - const child = children[i]; - const hoisted = getHoistedNode(child); - if (hoisted) { - // presence of hoisted means child must be a stringifiable node - const node = child; - const result = analyzeNode(node); - if (result) { - // node is stringifiable, record state - nc += result[0]; - ec += result[1]; - currentChunk.push(node); - continue; - } - } - // we only reach here if we ran into a node that is not stringifiable - // check if currently analyzed nodes meet criteria for stringification. - // adjust iteration index - i -= stringifyCurrentChunk(i); - // reset state - nc = 0; - ec = 0; - currentChunk.length = 0; - } - // in case the last node was also stringifiable - stringifyCurrentChunk(i); - }; - const getHoistedNode = (node) => ((node.type === 1 /* ELEMENT */ && node.tagType === 0 /* ELEMENT */) || - node.type == 12 /* TEXT_CALL */) && - node.codegenNode && - node.codegenNode.type === 4 /* SIMPLE_EXPRESSION */ && - node.codegenNode.hoisted; - const dataAriaRE = /^(data|aria)-/; - const isStringifiableAttr = (name, ns) => { - return ((ns === 0 /* HTML */ - ? shared.isKnownHtmlAttr(name) - : ns === 1 /* SVG */ - ? shared.isKnownSvgAttr(name) - : false) || dataAriaRE.test(name)); - }; - const replaceHoist = (node, replacement, context) => { - const hoistToReplace = node.codegenNode.hoisted; - context.hoists[context.hoists.indexOf(hoistToReplace)] = replacement; - }; - const isNonStringifiable = /*#__PURE__*/ shared.makeMap(`caption,thead,tr,th,tbody,td,tfoot,colgroup,col`); - /** - * for a hoisted node, analyze it and return: - * - false: bailed (contains non-stringifiable props or runtime constant) - * - [nc, ec] where - * - nc is the number of nodes inside - * - ec is the number of element with bindings inside - */ - function analyzeNode(node) { - if (node.type === 1 /* ELEMENT */ && isNonStringifiable(node.tag)) { - return false; - } - if (node.type === 12 /* TEXT_CALL */) { - return [1, 0]; - } - let nc = 1; // node count - let ec = node.props.length > 0 ? 1 : 0; // element w/ binding count - let bailed = false; - const bail = () => { - bailed = true; - return false; - }; - // TODO: check for cases where using innerHTML will result in different - // output compared to imperative node insertions. - // probably only need to check for most common case - // i.e. non-phrasing-content tags inside `<p>` - function walk(node) { - for (let i = 0; i < node.props.length; i++) { - const p = node.props[i]; - // bail on non-attr bindings - if (p.type === 6 /* ATTRIBUTE */ && - !isStringifiableAttr(p.name, node.ns)) { - return bail(); - } - if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind') { - // bail on non-attr bindings - if (p.arg && - (p.arg.type === 8 /* COMPOUND_EXPRESSION */ || - (p.arg.isStatic && !isStringifiableAttr(p.arg.content, node.ns)))) { - return bail(); - } - if (p.exp && - (p.exp.type === 8 /* COMPOUND_EXPRESSION */ || - p.exp.constType < 3 /* CAN_STRINGIFY */)) { - return bail(); - } - } - } - for (let i = 0; i < node.children.length; i++) { - nc++; - const child = node.children[i]; - if (child.type === 1 /* ELEMENT */) { - if (child.props.length > 0) { - ec++; - } - walk(child); - if (bailed) { - return false; - } - } - } - return true; - } - return walk(node) ? [nc, ec] : false; - } - function stringifyNode(node, context) { - if (shared.isString(node)) { - return node; - } - if (shared.isSymbol(node)) { - return ``; - } - switch (node.type) { - case 1 /* ELEMENT */: - return stringifyElement(node, context); - case 2 /* TEXT */: - return shared.escapeHtml(node.content); - case 3 /* COMMENT */: - return `<!--${shared.escapeHtml(node.content)}-->`; - case 5 /* INTERPOLATION */: - return shared.escapeHtml(shared.toDisplayString(evaluateConstant(node.content))); - case 8 /* COMPOUND_EXPRESSION */: - return shared.escapeHtml(evaluateConstant(node)); - case 12 /* TEXT_CALL */: - return stringifyNode(node.content, context); - default: - // static trees will not contain if/for nodes - return ''; - } - } - function stringifyElement(node, context) { - let res = `<${node.tag}`; - let innerHTML = ''; - for (let i = 0; i < node.props.length; i++) { - const p = node.props[i]; - if (p.type === 6 /* ATTRIBUTE */) { - res += ` ${p.name}`; - if (p.value) { - res += `="${shared.escapeHtml(p.value.content)}"`; - } - } - else if (p.type === 7 /* DIRECTIVE */) { - if (p.name === 'bind') { - const exp = p.exp; - if (exp.content[0] === '_') { - // internally generated string constant references - // e.g. imported URL strings via compiler-sfc transformAssetUrl plugin - res += ` ${p.arg.content}="__VUE_EXP_START__${exp.content}__VUE_EXP_END__"`; - continue; - } - // constant v-bind, e.g. :foo="1" - let evaluated = evaluateConstant(exp); - if (evaluated != null) { - const arg = p.arg && p.arg.content; - if (arg === 'class') { - evaluated = shared.normalizeClass(evaluated); - } - else if (arg === 'style') { - evaluated = shared.stringifyStyle(shared.normalizeStyle(evaluated)); - } - res += ` ${p.arg.content}="${shared.escapeHtml(evaluated)}"`; - } - } - else if (p.name === 'html') { - // #5439 v-html with constant value - // not sure why would anyone do this but it can happen - innerHTML = evaluateConstant(p.exp); - } - else if (p.name === 'text') { - innerHTML = shared.escapeHtml(shared.toDisplayString(evaluateConstant(p.exp))); - } - } - } - if (context.scopeId) { - res += ` ${context.scopeId}`; - } - res += `>`; - if (innerHTML) { - res += innerHTML; - } - else { - for (let i = 0; i < node.children.length; i++) { - res += stringifyNode(node.children[i], context); - } - } - if (!shared.isVoidTag(node.tag)) { - res += `</${node.tag}>`; - } - return res; - } - // __UNSAFE__ - // Reason: eval. - // It's technically safe to eval because only constant expressions are possible - // here, e.g. `{{ 1 }}` or `{{ 'foo' }}` - // in addition, constant exps bail on presence of parens so you can't even - // run JSFuck in here. But we mark it unsafe for security review purposes. - // (see compiler-core/src/transforms/transformExpression) - function evaluateConstant(exp) { - if (exp.type === 4 /* SIMPLE_EXPRESSION */) { - return new Function(`return ${exp.content}`)(); - } - else { - // compound - let res = ``; - exp.children.forEach(c => { - if (shared.isString(c) || shared.isSymbol(c)) { - return; - } - if (c.type === 2 /* TEXT */) { - res += c.content; - } - else if (c.type === 5 /* INTERPOLATION */) { - res += shared.toDisplayString(evaluateConstant(c.content)); - } - else { - res += evaluateConstant(c); - } - }); - return res; - } + /** + * This module is Node-only. + */ + /** + * Regex for replacing placeholders for embedded constant variables + * (e.g. import URL string constants generated by compiler-sfc) + */ + const expReplaceRE = /__VUE_EXP_START__(.*?)__VUE_EXP_END__/g; + /** + * Turn eligible hoisted static trees into stringified static nodes, e.g. + * + * ```js + * const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`) + * ``` + * + * A single static vnode can contain stringified content for **multiple** + * consecutive nodes (element and plain text), called a "chunk". + * `@vue/runtime-dom` will create the content via innerHTML in a hidden + * container element and insert all the nodes in place. The call must also + * provide the number of nodes contained in the chunk so that during hydration + * we can know how many nodes the static vnode should adopt. + * + * The optimization scans a children list that contains hoisted nodes, and + * tries to find the largest chunk of consecutive hoisted nodes before running + * into a non-hoisted node or the end of the list. A chunk is then converted + * into a single static vnode and replaces the hoisted expression of the first + * node in the chunk. Other nodes in the chunk are considered "merged" and + * therefore removed from both the hoist list and the children array. + * + * This optimization is only performed in Node.js. + */ + const stringifyStatic = (children, context, parent) => { + // bail stringification for slot content + if (context.scopes.vSlot > 0) { + return; + } + let nc = 0; // current node count + let ec = 0; // current element with binding count + const currentChunk = []; + const stringifyCurrentChunk = (currentIndex) => { + if (nc >= 20 /* NODE_COUNT */ || + ec >= 5 /* ELEMENT_WITH_BINDING_COUNT */) { + // combine all currently eligible nodes into a single static vnode call + const staticCall = compilerCore.createCallExpression(context.helper(compilerCore.CREATE_STATIC), [ + JSON.stringify(currentChunk.map(node => stringifyNode(node, context)).join('')).replace(expReplaceRE, `" + $1 + "`), + // the 2nd argument indicates the number of DOM nodes this static vnode + // will insert / hydrate + String(currentChunk.length) + ]); + // replace the first node's hoisted expression with the static vnode call + replaceHoist(currentChunk[0], staticCall, context); + if (currentChunk.length > 1) { + for (let i = 1; i < currentChunk.length; i++) { + // for the merged nodes, set their hoisted expression to null + replaceHoist(currentChunk[i], null, context); + } + // also remove merged nodes from children + const deleteCount = currentChunk.length - 1; + children.splice(currentIndex - currentChunk.length + 1, deleteCount); + return deleteCount; + } + } + return 0; + }; + let i = 0; + for (; i < children.length; i++) { + const child = children[i]; + const hoisted = getHoistedNode(child); + if (hoisted) { + // presence of hoisted means child must be a stringifiable node + const node = child; + const result = analyzeNode(node); + if (result) { + // node is stringifiable, record state + nc += result[0]; + ec += result[1]; + currentChunk.push(node); + continue; + } + } + // we only reach here if we ran into a node that is not stringifiable + // check if currently analyzed nodes meet criteria for stringification. + // adjust iteration index + i -= stringifyCurrentChunk(i); + // reset state + nc = 0; + ec = 0; + currentChunk.length = 0; + } + // in case the last node was also stringifiable + stringifyCurrentChunk(i); + }; + const getHoistedNode = (node) => ((node.type === 1 /* ELEMENT */ && node.tagType === 0 /* ELEMENT */) || + node.type == 12 /* TEXT_CALL */) && + node.codegenNode && + node.codegenNode.type === 4 /* SIMPLE_EXPRESSION */ && + node.codegenNode.hoisted; + const dataAriaRE = /^(data|aria)-/; + const isStringifiableAttr = (name, ns) => { + return ((ns === 0 /* HTML */ + ? shared.isKnownHtmlAttr(name) + : ns === 1 /* SVG */ + ? shared.isKnownSvgAttr(name) + : false) || dataAriaRE.test(name)); + }; + const replaceHoist = (node, replacement, context) => { + const hoistToReplace = node.codegenNode.hoisted; + context.hoists[context.hoists.indexOf(hoistToReplace)] = replacement; + }; + const isNonStringifiable = /*#__PURE__*/ shared.makeMap(`caption,thead,tr,th,tbody,td,tfoot,colgroup,col`); + /** + * for a hoisted node, analyze it and return: + * - false: bailed (contains non-stringifiable props or runtime constant) + * - [nc, ec] where + * - nc is the number of nodes inside + * - ec is the number of element with bindings inside + */ + function analyzeNode(node) { + if (node.type === 1 /* ELEMENT */ && isNonStringifiable(node.tag)) { + return false; + } + if (node.type === 12 /* TEXT_CALL */) { + return [1, 0]; + } + let nc = 1; // node count + let ec = node.props.length > 0 ? 1 : 0; // element w/ binding count + let bailed = false; + const bail = () => { + bailed = true; + return false; + }; + // TODO: check for cases where using innerHTML will result in different + // output compared to imperative node insertions. + // probably only need to check for most common case + // i.e. non-phrasing-content tags inside `<p>` + function walk(node) { + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i]; + // bail on non-attr bindings + if (p.type === 6 /* ATTRIBUTE */ && + !isStringifiableAttr(p.name, node.ns)) { + return bail(); + } + if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind') { + // bail on non-attr bindings + if (p.arg && + (p.arg.type === 8 /* COMPOUND_EXPRESSION */ || + (p.arg.isStatic && !isStringifiableAttr(p.arg.content, node.ns)))) { + return bail(); + } + if (p.exp && + (p.exp.type === 8 /* COMPOUND_EXPRESSION */ || + p.exp.constType < 3 /* CAN_STRINGIFY */)) { + return bail(); + } + } + } + for (let i = 0; i < node.children.length; i++) { + nc++; + const child = node.children[i]; + if (child.type === 1 /* ELEMENT */) { + if (child.props.length > 0) { + ec++; + } + walk(child); + if (bailed) { + return false; + } + } + } + return true; + } + return walk(node) ? [nc, ec] : false; + } + function stringifyNode(node, context) { + if (shared.isString(node)) { + return node; + } + if (shared.isSymbol(node)) { + return ``; + } + switch (node.type) { + case 1 /* ELEMENT */: + return stringifyElement(node, context); + case 2 /* TEXT */: + return shared.escapeHtml(node.content); + case 3 /* COMMENT */: + return `<!--${shared.escapeHtml(node.content)}-->`; + case 5 /* INTERPOLATION */: + return shared.escapeHtml(shared.toDisplayString(evaluateConstant(node.content))); + case 8 /* COMPOUND_EXPRESSION */: + return shared.escapeHtml(evaluateConstant(node)); + case 12 /* TEXT_CALL */: + return stringifyNode(node.content, context); + default: + // static trees will not contain if/for nodes + return ''; + } + } + function stringifyElement(node, context) { + let res = `<${node.tag}`; + let innerHTML = ''; + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i]; + if (p.type === 6 /* ATTRIBUTE */) { + res += ` ${p.name}`; + if (p.value) { + res += `="${shared.escapeHtml(p.value.content)}"`; + } + } + else if (p.type === 7 /* DIRECTIVE */) { + if (p.name === 'bind') { + const exp = p.exp; + if (exp.content[0] === '_') { + // internally generated string constant references + // e.g. imported URL strings via compiler-sfc transformAssetUrl plugin + res += ` ${p.arg.content}="__VUE_EXP_START__${exp.content}__VUE_EXP_END__"`; + continue; + } + // constant v-bind, e.g. :foo="1" + let evaluated = evaluateConstant(exp); + if (evaluated != null) { + const arg = p.arg && p.arg.content; + if (arg === 'class') { + evaluated = shared.normalizeClass(evaluated); + } + else if (arg === 'style') { + evaluated = shared.stringifyStyle(shared.normalizeStyle(evaluated)); + } + res += ` ${p.arg.content}="${shared.escapeHtml(evaluated)}"`; + } + } + else if (p.name === 'html') { + // #5439 v-html with constant value + // not sure why would anyone do this but it can happen + innerHTML = evaluateConstant(p.exp); + } + else if (p.name === 'text') { + innerHTML = shared.escapeHtml(shared.toDisplayString(evaluateConstant(p.exp))); + } + } + } + if (context.scopeId) { + res += ` ${context.scopeId}`; + } + res += `>`; + if (innerHTML) { + res += innerHTML; + } + else { + for (let i = 0; i < node.children.length; i++) { + res += stringifyNode(node.children[i], context); + } + } + if (!shared.isVoidTag(node.tag)) { + res += `</${node.tag}>`; + } + return res; + } + // __UNSAFE__ + // Reason: eval. + // It's technically safe to eval because only constant expressions are possible + // here, e.g. `{{ 1 }}` or `{{ 'foo' }}` + // in addition, constant exps bail on presence of parens so you can't even + // run JSFuck in here. But we mark it unsafe for security review purposes. + // (see compiler-core/src/transforms/transformExpression) + function evaluateConstant(exp) { + if (exp.type === 4 /* SIMPLE_EXPRESSION */) { + return new Function(`return ${exp.content}`)(); + } + else { + // compound + let res = ``; + exp.children.forEach(c => { + if (shared.isString(c) || shared.isSymbol(c)) { + return; + } + if (c.type === 2 /* TEXT */) { + res += c.content; + } + else if (c.type === 5 /* INTERPOLATION */) { + res += shared.toDisplayString(evaluateConstant(c.content)); + } + else { + res += evaluateConstant(c); + } + }); + return res; + } } - const ignoreSideEffectTags = (node, context) => { - if (node.type === 1 /* ELEMENT */ && - node.tagType === 0 /* ELEMENT */ && - (node.tag === 'script' || node.tag === 'style')) { - context.onError(createDOMCompilerError(60 /* X_IGNORED_SIDE_EFFECT_TAG */, node.loc)); - context.removeNode(); - } + const ignoreSideEffectTags = (node, context) => { + if (node.type === 1 /* ELEMENT */ && + node.tagType === 0 /* ELEMENT */ && + (node.tag === 'script' || node.tag === 'style')) { + context.onError(createDOMCompilerError(60 /* X_IGNORED_SIDE_EFFECT_TAG */, node.loc)); + context.removeNode(); + } }; - const DOMNodeTransforms = [ - transformStyle, - ...([transformTransition] ) - ]; - const DOMDirectiveTransforms = { - cloak: compilerCore.noopDirectiveTransform, - html: transformVHtml, - text: transformVText, - model: transformModel, - on: transformOn, - show: transformShow - }; - function compile(template, options = {}) { - return compilerCore.baseCompile(template, shared.extend({}, parserOptions, options, { - nodeTransforms: [ - // ignore <script> and <tag> - // this is not put inside DOMNodeTransforms because that list is used - // by compiler-ssr to generate vnode fallback branches - ignoreSideEffectTags, - ...DOMNodeTransforms, - ...(options.nodeTransforms || []) - ], - directiveTransforms: shared.extend({}, DOMDirectiveTransforms, options.directiveTransforms || {}), - transformHoist: stringifyStatic - })); - } - function parse(template, options = {}) { - return compilerCore.baseParse(template, shared.extend({}, parserOptions, options)); + const DOMNodeTransforms = [ + transformStyle, + ...([transformTransition] ) + ]; + const DOMDirectiveTransforms = { + cloak: compilerCore.noopDirectiveTransform, + html: transformVHtml, + text: transformVText, + model: transformModel, + on: transformOn, + show: transformShow + }; + function compile(template, options = {}) { + return compilerCore.baseCompile(template, shared.extend({}, parserOptions, options, { + nodeTransforms: [ + // ignore <script> and <tag> + // this is not put inside DOMNodeTransforms because that list is used + // by compiler-ssr to generate vnode fallback branches + ignoreSideEffectTags, + ...DOMNodeTransforms, + ...(options.nodeTransforms || []) + ], + directiveTransforms: shared.extend({}, DOMDirectiveTransforms, options.directiveTransforms || {}), + transformHoist: stringifyStatic + })); + } + function parse(template, options = {}) { + return compilerCore.baseParse(template, shared.extend({}, parserOptions, options)); } Object.keys(compilerCore).forEach(function (k) { diff --git a/webui/node_modules/vite/dist/node/index.d.ts b/webui/node_modules/vite/dist/node/index.d.ts index fbf9b6d..573567e 100644 --- a/webui/node_modules/vite/dist/node/index.d.ts +++ b/webui/node_modules/vite/dist/node/index.d.ts @@ -1,3292 +1,3292 @@ -/// <reference types="node" /> - -import type { Agent } from 'node:http'; -import type { BuildOptions as BuildOptions_2 } from 'esbuild'; -import type { ClientRequest } from 'node:http'; -import type { ClientRequestArgs } from 'node:http'; -import type { CustomPluginOptions } from 'rollup'; -import type { Duplex } from 'node:stream'; -import type { DuplexOptions } from 'node:stream'; -import { TransformOptions as EsbuildTransformOptions } from 'esbuild'; -import { version as esbuildVersion } from 'esbuild'; -import { EventEmitter } from 'node:events'; -import * as events from 'node:events'; -import type { ExistingRawSourceMap } from 'rollup'; -import type * as fs from 'node:fs'; -import type { GetManualChunk } from 'rollup'; -import * as http from 'node:http'; -import type { IncomingMessage } from 'node:http'; -import type { InputOptions } from 'rollup'; -import type { LoadResult } from 'rollup'; -import type { ModuleFormat } from 'rollup'; -import type { ModuleInfo } from 'rollup'; -import type * as net from 'node:net'; -import type { OutgoingHttpHeaders } from 'node:http'; -import type { OutputBundle } from 'rollup'; -import type { OutputChunk } from 'rollup'; -import type { PartialResolvedId } from 'rollup'; -import type { Plugin as Plugin_3 } from 'rollup'; -import type { PluginContext } from 'rollup'; -import type { PluginHooks } from 'rollup'; -import type * as PostCSS from 'postcss'; -import type { ResolveIdResult } from 'rollup'; -import type { RollupError } from 'rollup'; -import type { RollupOptions } from 'rollup'; -import type { RollupOutput } from 'rollup'; -import { VERSION as rollupVersion } from 'rollup'; -import type { RollupWatcher } from 'rollup'; -import type { SecureContextOptions } from 'node:tls'; -import type { Server } from 'node:http'; -import type { Server as Server_2 } from 'node:https'; -import type { ServerOptions as ServerOptions_2 } from 'node:https'; -import type { ServerResponse } from 'node:http'; -import type { SourceDescription } from 'rollup'; -import type { SourceMap } from 'rollup'; -import type * as stream from 'node:stream'; -import type { TransformPluginContext } from 'rollup'; -import type { TransformResult as TransformResult_2 } from 'rollup'; -import type { TransformResult as TransformResult_3 } from 'esbuild'; -import type * as url from 'node:url'; -import type { URL as URL_2 } from 'node:url'; -import type { WatcherOptions } from 'rollup'; -import type { ZlibOptions } from 'node:zlib'; - -export declare interface Alias { - find: string | RegExp - replacement: string - /** - * Instructs the plugin to use an alternative resolving algorithm, - * rather than the Rollup's resolver. - * @default null - */ - customResolver?: ResolverFunction | ResolverObject | null -} - -/** - * Specifies an `Object`, or an `Array` of `Object`, - * which defines aliases used to replace values in `import` or `require` statements. - * With either format, the order of the entries is important, - * in that the first defined rules are applied first. - * - * This is passed to \@rollup/plugin-alias as the "entries" field - * https://github.com/rollup/plugins/tree/master/packages/alias#entries - */ -export declare type AliasOptions = readonly Alias[] | { [find: string]: string } - -export declare type AnymatchFn = (testString: string) => boolean - -export declare type AnymatchPattern = string | RegExp | AnymatchFn - -/** - * spa: include SPA fallback middleware and configure sirv with `single: true` in preview - * - * mpa: only include non-SPA HTML middlewares - * - * custom: don't include HTML middlewares - */ -export declare type AppType = 'spa' | 'mpa' | 'custom'; - -export declare interface AwaitWriteFinishOptions { - /** - * Amount of time in milliseconds for a file size to remain constant before emitting its event. - */ - stabilityThreshold?: number - - /** - * File size polling interval. - */ - pollInterval?: number -} - -/** - * Bundles the app for production. - * Returns a Promise containing the build result. - */ -export declare function build(inlineConfig?: InlineConfig): Promise<RollupOutput | RollupOutput[] | RollupWatcher>; - -export declare interface BuildOptions { - /** - * Compatibility transform target. The transform is performed with esbuild - * and the lowest supported target is es2015/es6. Note this only handles - * syntax transformation and does not cover polyfills (except for dynamic - * import) - * - * Default: 'modules' - Similar to `@babel/preset-env`'s targets.esmodules, - * transpile targeting browsers that natively support dynamic es module imports. - * https://caniuse.com/es6-module-dynamic-import - * - * Another special value is 'esnext' - which only performs minimal transpiling - * (for minification compat) and assumes native dynamic imports support. - * - * For custom targets, see https://esbuild.github.io/api/#target and - * https://esbuild.github.io/content-types/#javascript for more details. - */ - target?: 'modules' | EsbuildTransformOptions['target'] | false; - /** - * whether to inject module preload polyfill. - * Note: does not apply to library mode. - * @default true - */ - polyfillModulePreload?: boolean; - /** - * Directory relative from `root` where build output will be placed. If the - * directory exists, it will be removed before the build. - * @default 'dist' - */ - outDir?: string; - /** - * Directory relative from `outDir` where the built js/css/image assets will - * be placed. - * @default 'assets' - */ - assetsDir?: string; - /** - * Static asset files smaller than this number (in bytes) will be inlined as - * base64 strings. Default limit is `4096` (4kb). Set to `0` to disable. - * @default 4096 - */ - assetsInlineLimit?: number; - /** - * Whether to code-split CSS. When enabled, CSS in async chunks will be - * inlined as strings in the chunk and inserted via dynamically created - * style tags when the chunk is loaded. - * @default true - */ - cssCodeSplit?: boolean; - /** - * An optional separate target for CSS minification. - * As esbuild only supports configuring targets to mainstream - * browsers, users may need this option when they are targeting - * a niche browser that comes with most modern JavaScript features - * but has poor CSS support, e.g. Android WeChat WebView, which - * doesn't support the #RGBA syntax. - */ - cssTarget?: EsbuildTransformOptions['target'] | false; - /** - * If `true`, a separate sourcemap file will be created. If 'inline', the - * sourcemap will be appended to the resulting output file as data URI. - * 'hidden' works like `true` except that the corresponding sourcemap - * comments in the bundled files are suppressed. - * @default false - */ - sourcemap?: boolean | 'inline' | 'hidden'; - /** - * Set to `false` to disable minification, or specify the minifier to use. - * Available options are 'terser' or 'esbuild'. - * @default 'esbuild' - */ - minify?: boolean | 'terser' | 'esbuild'; - /** - * Options for terser - * https://terser.org/docs/api-reference#minify-options - */ - terserOptions?: Terser.MinifyOptions; - /** - * Will be merged with internal rollup options. - * https://rollupjs.org/guide/en/#big-list-of-options - */ - rollupOptions?: RollupOptions; - /** - * Options to pass on to `@rollup/plugin-commonjs` - */ - commonjsOptions?: RollupCommonJSOptions; - /** - * Options to pass on to `@rollup/plugin-dynamic-import-vars` - */ - dynamicImportVarsOptions?: RollupDynamicImportVarsOptions; - /** - * Whether to write bundle to disk - * @default true - */ - write?: boolean; - /** - * Empty outDir on write. - * @default true when outDir is a sub directory of project root - */ - emptyOutDir?: boolean | null; - /** - * Whether to emit a manifest.json under assets dir to map hash-less filenames - * to their hashed versions. Useful when you want to generate your own HTML - * instead of using the one generated by Vite. - * - * Example: - * - * ```json - * { - * "main.js": { - * "file": "main.68fe3fad.js", - * "css": "main.e6b63442.css", - * "imports": [...], - * "dynamicImports": [...] - * } - * } - * ``` - * @default false - */ - manifest?: boolean | string; - /** - * Build in library mode. The value should be the global name of the lib in - * UMD mode. This will produce esm + cjs + umd bundle formats with default - * configurations that are suitable for distributing libraries. - */ - lib?: LibraryOptions | false; - /** - * Produce SSR oriented build. Note this requires specifying SSR entry via - * `rollupOptions.input`. - */ - ssr?: boolean | string; - /** - * Generate SSR manifest for determining style links and asset preload - * directives in production. - */ - ssrManifest?: boolean | string; - /** - * Set to false to disable reporting compressed chunk sizes. - * Can slightly improve build speed. - */ - reportCompressedSize?: boolean; - /** - * Adjust chunk size warning limit (in kbs). - * @default 500 - */ - chunkSizeWarningLimit?: number; - /** - * Rollup watch options - * https://rollupjs.org/guide/en/#watchoptions - */ - watch?: WatcherOptions | null; -} - -export declare interface ChunkMetadata { - importedAssets: Set<string>; - importedCss: Set<string>; -} - -export declare interface CommonServerOptions { - /** - * Specify server port. Note if the port is already being used, Vite will - * automatically try the next available port so this may not be the actual - * port the server ends up listening on. - */ - port?: number; - /** - * If enabled, vite will exit if specified port is already in use - */ - strictPort?: boolean; - /** - * Specify which IP addresses the server should listen on. - * Set to 0.0.0.0 to listen on all addresses, including LAN and public addresses. - */ - host?: string | boolean; - /** - * Enable TLS + HTTP/2. - * Note: this downgrades to TLS only when the proxy option is also used. - */ - https?: boolean | ServerOptions_2; - /** - * Open browser window on startup - */ - open?: boolean | string; - /** - * Configure custom proxy rules for the dev server. Expects an object - * of `{ key: options }` pairs. - * Uses [`http-proxy`](https://github.com/http-party/node-http-proxy). - * Full options [here](https://github.com/http-party/node-http-proxy#options). - * - * Example `vite.config.js`: - * ``` js - * module.exports = { - * proxy: { - * // string shorthand - * '/foo': 'http://localhost:4567/foo', - * // with options - * '/api': { - * target: 'http://jsonplaceholder.typicode.com', - * changeOrigin: true, - * rewrite: path => path.replace(/^\/api/, '') - * } - * } - * } - * ``` - */ - proxy?: Record<string, string | ProxyOptions>; - /** - * Configure CORS for the dev server. - * Uses https://github.com/expressjs/cors. - * Set to `true` to allow all methods from any origin, or configure separately - * using an object. - */ - cors?: CorsOptions | boolean; - /** - * Specify server response headers. - */ - headers?: OutgoingHttpHeaders; -} - -export declare interface ConfigEnv { - command: 'build' | 'serve'; - mode: string; - /** - * @experimental - */ - ssrBuild?: boolean; -} - -export declare namespace Connect { - export type ServerHandle = HandleFunction | http.Server - - export class IncomingMessage extends http.IncomingMessage { - originalUrl?: http.IncomingMessage['url'] | undefined - } - - export type NextFunction = (err?: any) => void - - export type SimpleHandleFunction = ( - req: IncomingMessage, - res: http.ServerResponse - ) => void - export type NextHandleFunction = ( - req: IncomingMessage, - res: http.ServerResponse, - next: NextFunction - ) => void - export type ErrorHandleFunction = ( - err: any, - req: IncomingMessage, - res: http.ServerResponse, - next: NextFunction - ) => void - export type HandleFunction = - | SimpleHandleFunction - | NextHandleFunction - | ErrorHandleFunction - - export interface ServerStackItem { - route: string - handle: ServerHandle - } - - export interface Server extends NodeJS.EventEmitter { - (req: http.IncomingMessage, res: http.ServerResponse, next?: Function): void - - route: string - stack: ServerStackItem[] - - /** - * Utilize the given middleware `handle` to the given `route`, - * defaulting to _/_. This "route" is the mount-point for the - * middleware, when given a value other than _/_ the middleware - * is only effective when that segment is present in the request's - * pathname. - * - * For example if we were to mount a function at _/admin_, it would - * be invoked on _/admin_, and _/admin/settings_, however it would - * not be invoked for _/_, or _/posts_. - */ - use(fn: NextHandleFunction): Server - use(fn: HandleFunction): Server - use(route: string, fn: NextHandleFunction): Server - use(route: string, fn: HandleFunction): Server - - /** - * Handle server requests, punting them down - * the middleware stack. - */ - handle( - req: http.IncomingMessage, - res: http.ServerResponse, - next: Function - ): void - - /** - * Listen for connections. - * - * This method takes the same arguments - * as node's `http.Server#listen()`. - * - * HTTP and HTTPS: - * - * If you run your application both as HTTP - * and HTTPS you may wrap them individually, - * since your Connect "server" is really just - * a JavaScript `Function`. - * - * var connect = require('connect') - * , http = require('http') - * , https = require('https'); - * - * var app = connect(); - * - * http.createServer(app).listen(80); - * https.createServer(options, app).listen(443); - */ - listen( - port: number, - hostname?: string, - backlog?: number, - callback?: Function - ): http.Server - listen(port: number, hostname?: string, callback?: Function): http.Server - listen(path: string, callback?: Function): http.Server - listen(handle: any, listeningListener?: Function): http.Server - } -} - -export declare interface ConnectedPayload { - type: 'connected' -} - -/** - * https://github.com/expressjs/cors#configuration-options - */ -export declare interface CorsOptions { - origin?: CorsOrigin | ((origin: string, cb: (err: Error, origins: CorsOrigin) => void) => void); - methods?: string | string[]; - allowedHeaders?: string | string[]; - exposedHeaders?: string | string[]; - credentials?: boolean; - maxAge?: number; - preflightContinue?: boolean; - optionsSuccessStatus?: number; -} - -export declare type CorsOrigin = boolean | string | RegExp | (string | RegExp)[]; - -export declare const createFilter: (include?: FilterPattern | undefined, exclude?: FilterPattern | undefined, options?: { - resolve?: string | false | null | undefined; -} | undefined) => (id: string | unknown) => boolean; - -export declare function createLogger(level?: LogLevel, options?: LoggerOptions): Logger; - -export declare function createServer(inlineConfig?: InlineConfig): Promise<ViteDevServer>; - -export declare interface CSSModulesOptions { - getJSON?: (cssFileName: string, json: Record<string, string>, outputFileName: string) => void; - scopeBehaviour?: 'global' | 'local'; - globalModulePaths?: RegExp[]; - generateScopedName?: string | ((name: string, filename: string, css: string) => string); - hashPrefix?: string; - /** - * default: null - */ - localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly' | null; -} - -export declare interface CSSOptions { - /** - * https://github.com/css-modules/postcss-modules - */ - modules?: CSSModulesOptions | false; - preprocessorOptions?: Record<string, any>; - postcss?: string | (PostCSS.ProcessOptions & { - plugins?: PostCSS.AcceptedPlugin[]; - }); - /** - * Enables css sourcemaps during dev - * @default false - * @experimental - */ - devSourcemap?: boolean; -} - -export declare interface CustomEventMap { - 'vite:beforeUpdate': UpdatePayload - 'vite:beforePrune': PrunePayload - 'vite:beforeFullReload': FullReloadPayload - 'vite:error': ErrorPayload -} - -export declare interface CustomPayload { - type: 'custom' - event: string - data?: any -} - -/** - * Type helper to make it easier to use vite.config.ts - * accepts a direct {@link UserConfig} object, or a function that returns it. - * The function receives a {@link ConfigEnv} object that exposes two properties: - * `command` (either `'build'` or `'serve'`), and `mode`. - */ -export declare function defineConfig(config: UserConfigExport): UserConfigExport; - -export declare interface DepOptimizationConfig { - /** - * Force optimize listed dependencies (must be resolvable import paths, - * cannot be globs). - */ - include?: string[]; - /** - * Do not optimize these dependencies (must be resolvable import paths, - * cannot be globs). - */ - exclude?: string[]; - /** - * Force ESM interop when importing for these dependencies. Some legacy - * packages advertise themselves as ESM but use `require` internally - * @experimental - */ - needsInterop?: string[]; - /** - * Options to pass to esbuild during the dep scanning and optimization - * - * Certain options are omitted since changing them would not be compatible - * with Vite's dep optimization. - * - * - `external` is also omitted, use Vite's `optimizeDeps.exclude` option - * - `plugins` are merged with Vite's dep plugin - * - * https://esbuild.github.io/api - */ - esbuildOptions?: Omit<BuildOptions_2, 'bundle' | 'entryPoints' | 'external' | 'write' | 'watch' | 'outdir' | 'outfile' | 'outbase' | 'outExtension' | 'metafile'>; - /** - * List of file extensions that can be optimized. A corresponding esbuild - * plugin must exist to handle the specific extension. - * - * By default, Vite can optimize `.mjs`, `.js`, `.ts`, and `.mts` files. This option - * allows specifying additional extensions. - * - * @experimental - */ - extensions?: string[]; - /** - * Disables dependencies optimizations, true disables the optimizer during - * build and dev. Pass 'build' or 'dev' to only disable the optimizer in - * one of the modes. Deps optimization is enabled by default in dev only. - * @default 'build' - * @experimental - */ - disabled?: boolean | 'build' | 'dev'; -} - -export declare interface DepOptimizationMetadata { - /** - * The main hash is determined by user config and dependency lockfiles. - * This is checked on server startup to avoid unnecessary re-bundles. - */ - hash: string; - /** - * The browser hash is determined by the main hash plus additional dependencies - * discovered at runtime. This is used to invalidate browser requests to - * optimized deps. - */ - browserHash: string; - /** - * Metadata for each already optimized dependency - */ - optimized: Record<string, OptimizedDepInfo>; - /** - * Metadata for non-entry optimized chunks and dynamic imports - */ - chunks: Record<string, OptimizedDepInfo>; - /** - * Metadata for each newly discovered dependency after processing - */ - discovered: Record<string, OptimizedDepInfo>; - /** - * OptimizedDepInfo list - */ - depInfoList: OptimizedDepInfo[]; -} - -export declare type DepOptimizationOptions = DepOptimizationConfig & { - /** - * By default, Vite will crawl your `index.html` to detect dependencies that - * need to be pre-bundled. If `build.rollupOptions.input` is specified, Vite - * will crawl those entry points instead. - * - * If neither of these fit your needs, you can specify custom entries using - * this option - the value should be a fast-glob pattern or array of patterns - * (https://github.com/mrmlnc/fast-glob#basic-syntax) that are relative from - * vite project root. This will overwrite default entries inference. - */ - entries?: string | string[]; - /** - * Force dep pre-optimization regardless of whether deps have changed. - * @experimental - */ - force?: boolean; -}; - -export declare interface DepOptimizationProcessing { - promise: Promise<void>; - resolve: () => void; -} - -export declare interface DepOptimizationResult { - metadata: DepOptimizationMetadata; - /** - * When doing a re-run, if there are newly discovered dependencies - * the page reload will be delayed until the next rerun so we need - * to be able to discard the result - */ - commit: () => Promise<void>; - cancel: () => void; -} - -export declare interface DepsOptimizer { - metadata: DepOptimizationMetadata; - scanProcessing?: Promise<void>; - registerMissingImport: (id: string, resolved: string) => OptimizedDepInfo; - run: () => void; - isOptimizedDepFile: (id: string) => boolean; - isOptimizedDepUrl: (url: string) => boolean; - getOptimizedDepId: (depInfo: OptimizedDepInfo) => string; - delayDepsOptimizerUntil: (id: string, done: () => Promise<any>) => void; - registerWorkersSource: (id: string) => void; - resetRegisteredIds: () => void; - ensureFirstRun: () => void; - options: DepOptimizationOptions; -} - -export declare interface ErrorPayload { - type: 'error' - err: { - [name: string]: any - message: string - stack: string - id?: string - frame?: string - plugin?: string - pluginCode?: string - loc?: { - file?: string - line: number - column: number - } - } -} - -export declare interface ESBuildOptions extends EsbuildTransformOptions { - include?: string | RegExp | string[] | RegExp[]; - exclude?: string | RegExp | string[] | RegExp[]; - jsxInject?: string; - /** - * This option is not respected. Use `build.minify` instead. - */ - minify?: never; -} - -export { EsbuildTransformOptions } - -export declare type ESBuildTransformResult = Omit<TransformResult_3, 'map'> & { - map: SourceMap; -}; - -export { esbuildVersion } - -export declare interface ExperimentalOptions { - /** - * Append fake `&lang.(ext)` when queries are specified, to preserve the file extension for following plugins to process. - * - * @experimental - * @default false - */ - importGlobRestoreExtension?: boolean; - /** - * Allow finegrain control over assets and public files paths - * - * @experimental - */ - renderBuiltUrl?: RenderBuiltAssetUrl; - /** - * Enables support of HMR partial accept via `import.meta.hot.acceptExports`. - * - * @experimental - * @default false - */ - hmrPartialAccept?: boolean; -} - -export declare type ExportsData = { - hasImports: boolean; - exports: readonly string[]; - facade: boolean; - hasReExports?: boolean; - jsxLoader?: boolean; -}; - -export declare interface FileSystemServeOptions { - /** - * Strictly restrict file accessing outside of allowing paths. - * - * Set to `false` to disable the warning - * - * @default true - */ - strict?: boolean; - /** - * Restrict accessing files outside the allowed directories. - * - * Accepts absolute path or a path relative to project root. - * Will try to search up for workspace root by default. - */ - allow?: string[]; - /** - * Restrict accessing files that matches the patterns. - * - * This will have higher priority than `allow`. - * Glob patterns are supported. - * - * @default ['.env', '.env.*', '*.crt', '*.pem'] - */ - deny?: string[]; -} - -/** - * Inlined to keep `@rollup/pluginutils` in devDependencies - */ -export declare type FilterPattern = ReadonlyArray<string | RegExp> | string | RegExp | null; - -export declare function formatPostcssSourceMap(rawMap: ExistingRawSourceMap, file: string): Promise<ExistingRawSourceMap>; - -export declare class FSWatcher extends EventEmitter implements fs.FSWatcher { - options: WatchOptions - - /** - * Constructs a new FSWatcher instance with optional WatchOptions parameter. - */ - constructor(options?: WatchOptions) - - /** - * Add files, directories, or glob patterns for tracking. Takes an array of strings or just one - * string. - */ - add(paths: string | ReadonlyArray<string>): this - - /** - * Stop watching files, directories, or glob patterns. Takes an array of strings or just one - * string. - */ - unwatch(paths: string | ReadonlyArray<string>): this - - /** - * Returns an object representing all the paths on the file system being watched by this - * `FSWatcher` instance. The object's keys are all the directories (using absolute paths unless - * the `cwd` option was used), and the values are arrays of the names of the items contained in - * each directory. - */ - getWatched(): { - [directory: string]: string[] - } - - /** - * Removes all listeners from watched files. - */ - close(): Promise<void> - - on( - event: 'add' | 'addDir' | 'change', - listener: (path: string, stats?: fs.Stats) => void - ): this - - on( - event: 'all', - listener: ( - eventName: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir', - path: string, - stats?: fs.Stats - ) => void - ): this - - /** - * Error occurred - */ - on(event: 'error', listener: (error: Error) => void): this - - /** - * Exposes the native Node `fs.FSWatcher events` - */ - on( - event: 'raw', - listener: (eventName: string, path: string, details: any) => void - ): this - - /** - * Fires when the initial scan is complete - */ - on(event: 'ready', listener: () => void): this - - on(event: 'unlink' | 'unlinkDir', listener: (path: string) => void): this - - on(event: string, listener: (...args: any[]) => void): this -} - -export declare interface FullReloadPayload { - type: 'full-reload' - path?: string -} - -export declare function getDepOptimizationConfig(config: ResolvedConfig, ssr: boolean): DepOptimizationConfig; - -export declare interface HmrContext { - file: string; - timestamp: number; - modules: Array<ModuleNode>; - read: () => string | Promise<string>; - server: ViteDevServer; -} - -export declare interface HmrOptions { - protocol?: string; - host?: string; - port?: number; - clientPort?: number; - path?: string; - timeout?: number; - overlay?: boolean; - server?: Server; -} - -export declare type HMRPayload = -| ConnectedPayload -| UpdatePayload -| FullReloadPayload -| CustomPayload -| ErrorPayload -| PrunePayload - -export declare interface HtmlTagDescriptor { - tag: string; - attrs?: Record<string, string | boolean | undefined>; - children?: string | HtmlTagDescriptor[]; - /** - * default: 'head-prepend' - */ - injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'; -} - -export declare namespace HttpProxy { - export type ProxyTarget = ProxyTargetUrl | ProxyTargetDetailed - - export type ProxyTargetUrl = string | Partial<url.Url> - - export interface ProxyTargetDetailed { - host: string - port: number - protocol?: string | undefined - hostname?: string | undefined - socketPath?: string | undefined - key?: string | undefined - passphrase?: string | undefined - pfx?: Buffer | string | undefined - cert?: string | undefined - ca?: string | undefined - ciphers?: string | undefined - secureProtocol?: string | undefined - } - - export type ErrorCallback = ( - err: Error, - req: http.IncomingMessage, - res: http.ServerResponse, - target?: ProxyTargetUrl - ) => void - - export class Server extends events.EventEmitter { - /** - * Creates the proxy server with specified options. - * @param options - Config object passed to the proxy - */ - constructor(options?: ServerOptions) - - /** - * Used for proxying regular HTTP(S) requests - * @param req - Client request. - * @param res - Client response. - * @param options - Additional options. - */ - web( - req: http.IncomingMessage, - res: http.ServerResponse, - options?: ServerOptions, - callback?: ErrorCallback - ): void - - /** - * Used for proxying regular HTTP(S) requests - * @param req - Client request. - * @param socket - Client socket. - * @param head - Client head. - * @param options - Additional options. - */ - ws( - req: http.IncomingMessage, - socket: unknown, - head: unknown, - options?: ServerOptions, - callback?: ErrorCallback - ): void - - /** - * A function that wraps the object in a webserver, for your convenience - * @param port - Port to listen on - */ - listen(port: number): Server - - /** - * A function that closes the inner webserver and stops listening on given port - */ - close(callback?: () => void): void - - /** - * Creates the proxy server with specified options. - * @param options - Config object passed to the proxy - * @returns Proxy object with handlers for `ws` and `web` requests - */ - static createProxyServer(options?: ServerOptions): Server - - /** - * Creates the proxy server with specified options. - * @param options - Config object passed to the proxy - * @returns Proxy object with handlers for `ws` and `web` requests - */ - static createServer(options?: ServerOptions): Server - - /** - * Creates the proxy server with specified options. - * @param options - Config object passed to the proxy - * @returns Proxy object with handlers for `ws` and `web` requests - */ - static createProxy(options?: ServerOptions): Server - - addListener(event: string, listener: () => void): this - on(event: string, listener: () => void): this - on(event: 'error', listener: ErrorCallback): this - on( - event: 'start', - listener: ( - req: http.IncomingMessage, - res: http.ServerResponse, - target: ProxyTargetUrl - ) => void - ): this - on( - event: 'proxyReq', - listener: ( - proxyReq: http.ClientRequest, - req: http.IncomingMessage, - res: http.ServerResponse, - options: ServerOptions - ) => void - ): this - on( - event: 'proxyRes', - listener: ( - proxyRes: http.IncomingMessage, - req: http.IncomingMessage, - res: http.ServerResponse - ) => void - ): this - on( - event: 'proxyReqWs', - listener: ( - proxyReq: http.ClientRequest, - req: http.IncomingMessage, - socket: net.Socket, - options: ServerOptions, - head: any - ) => void - ): this - on( - event: 'econnreset', - listener: ( - err: Error, - req: http.IncomingMessage, - res: http.ServerResponse, - target: ProxyTargetUrl - ) => void - ): this - on( - event: 'end', - listener: ( - req: http.IncomingMessage, - res: http.ServerResponse, - proxyRes: http.IncomingMessage - ) => void - ): this - on( - event: 'close', - listener: ( - proxyRes: http.IncomingMessage, - proxySocket: net.Socket, - proxyHead: any - ) => void - ): this - - once(event: string, listener: () => void): this - removeListener(event: string, listener: () => void): this - removeAllListeners(event?: string): this - getMaxListeners(): number - setMaxListeners(n: number): this - listeners(event: string): Array<() => void> - emit(event: string, ...args: any[]): boolean - listenerCount(type: string): number - } - - export interface ServerOptions { - /** URL string to be parsed with the url module. */ - target?: ProxyTarget | undefined - /** URL string to be parsed with the url module. */ - forward?: ProxyTargetUrl | undefined - /** Object to be passed to http(s).request. */ - agent?: any - /** Object to be passed to https.createServer(). */ - ssl?: any - /** If you want to proxy websockets. */ - ws?: boolean | undefined - /** Adds x- forward headers. */ - xfwd?: boolean | undefined - /** Verify SSL certificate. */ - secure?: boolean | undefined - /** Explicitly specify if we are proxying to another proxy. */ - toProxy?: boolean | undefined - /** Specify whether you want to prepend the target's path to the proxy path. */ - prependPath?: boolean | undefined - /** Specify whether you want to ignore the proxy path of the incoming request. */ - ignorePath?: boolean | undefined - /** Local interface string to bind for outgoing connections. */ - localAddress?: string | undefined - /** Changes the origin of the host header to the target URL. */ - changeOrigin?: boolean | undefined - /** specify whether you want to keep letter case of response header key */ - preserveHeaderKeyCase?: boolean | undefined - /** Basic authentication i.e. 'user:password' to compute an Authorization header. */ - auth?: string | undefined - /** Rewrites the location hostname on (301 / 302 / 307 / 308) redirects, Default: null. */ - hostRewrite?: string | undefined - /** Rewrites the location host/ port on (301 / 302 / 307 / 308) redirects based on requested host/ port.Default: false. */ - autoRewrite?: boolean | undefined - /** Rewrites the location protocol on (301 / 302 / 307 / 308) redirects to 'http' or 'https'.Default: null. */ - protocolRewrite?: string | undefined - /** rewrites domain of set-cookie headers. */ - cookieDomainRewrite?: - | false - | string - | { [oldDomain: string]: string } - | undefined - /** rewrites path of set-cookie headers. Default: false */ - cookiePathRewrite?: - | false - | string - | { [oldPath: string]: string } - | undefined - /** object with extra headers to be added to target requests. */ - headers?: { [header: string]: string } | undefined - /** Timeout (in milliseconds) when proxy receives no response from target. Default: 120000 (2 minutes) */ - proxyTimeout?: number | undefined - /** Timeout (in milliseconds) for incoming requests */ - timeout?: number | undefined - /** Specify whether you want to follow redirects. Default: false */ - followRedirects?: boolean | undefined - /** If set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the proxyRes event */ - selfHandleResponse?: boolean | undefined - /** Buffer */ - buffer?: stream.Stream | undefined - } -} - -export declare interface ImportGlobEagerFunction { - /** - * Eagerly import a list of files with a glob pattern. - * - * Overload 1: No generic provided, infer the type from `as` - */ - < - As extends string, - T = As extends keyof KnownAsTypeMap ? KnownAsTypeMap[As] : unknown - >( - glob: string | string[], - options?: Omit<ImportGlobOptions<boolean, As>, 'eager'> - ): Record<string, T> - /** - * Eagerly import a list of files with a glob pattern. - * - * Overload 2: Module generic provided - */ - <M>( - glob: string | string[], - options?: Omit<ImportGlobOptions<boolean, string>, 'eager'> - ): Record<string, M> -} - -export declare interface ImportGlobFunction { - /** - * Import a list of files with a glob pattern. - * - * Overload 1: No generic provided, infer the type from `eager` and `as` - */ - < - Eager extends boolean, - As extends string, - T = As extends keyof KnownAsTypeMap ? KnownAsTypeMap[As] : unknown - >( - glob: string | string[], - options?: ImportGlobOptions<Eager, As> - ): (Eager extends true ? true : false) extends true - ? Record<string, T> - : Record<string, () => Promise<T>> - /** - * Import a list of files with a glob pattern. - * - * Overload 2: Module generic provided, infer the type from `eager: false` - */ - <M>( - glob: string | string[], - options?: ImportGlobOptions<false, string> - ): Record<string, () => Promise<M>> - /** - * Import a list of files with a glob pattern. - * - * Overload 3: Module generic provided, infer the type from `eager: true` - */ - <M>( - glob: string | string[], - options: ImportGlobOptions<true, string> - ): Record<string, M> -} - -export declare interface ImportGlobOptions< -Eager extends boolean, -AsType extends string -> { - /** - * Import type for the import url. - */ - as?: AsType - /** - * Import as static or dynamic - * - * @default false - */ - eager?: Eager - /** - * Import only the specific named export. Set to `default` to import the default export. - */ - import?: string - /** - * Custom queries - */ - query?: string | Record<string, string | number | boolean> - /** - * Search files also inside `node_modules/` and hidden directories (e.g. `.git/`). This might have impact on performance. - * - * @default false - */ - exhaustive?: boolean -} - -export declare type IndexHtmlTransform = IndexHtmlTransformHook | { - enforce?: 'pre' | 'post'; - transform: IndexHtmlTransformHook; -}; - -export declare interface IndexHtmlTransformContext { - /** - * public path when served - */ - path: string; - /** - * filename on disk - */ - filename: string; - server?: ViteDevServer; - bundle?: OutputBundle; - chunk?: OutputChunk; - originalUrl?: string; -} - -export declare type IndexHtmlTransformHook = (html: string, ctx: IndexHtmlTransformContext) => IndexHtmlTransformResult | void | Promise<IndexHtmlTransformResult | void>; - -export declare type IndexHtmlTransformResult = string | HtmlTagDescriptor[] | { - html: string; - tags: HtmlTagDescriptor[]; -}; - -export declare type InferCustomEventPayload<T extends string> = -T extends keyof CustomEventMap ? CustomEventMap[T] : any - -export declare interface InlineConfig extends UserConfig { - configFile?: string | false; - envFile?: false; -} - -export declare interface InternalResolveOptions extends ResolveOptions { - root: string; - isBuild: boolean; - isProduction: boolean; - ssrConfig?: SSROptions; - packageCache?: PackageCache; - /** - * src code mode also attempts the following: - * - resolving /xxx as URLs - * - resolving bare imports from optimized deps - */ - asSrc?: boolean; - tryIndex?: boolean; - tryPrefix?: string; - skipPackageJson?: boolean; - preferRelative?: boolean; - preserveSymlinks?: boolean; - isRequire?: boolean; - isFromTsImporter?: boolean; - tryEsmOnly?: boolean; - scan?: boolean; - ssrOptimizeCheck?: boolean; - getDepsOptimizer?: (ssr: boolean) => DepsOptimizer | undefined; - shouldExternalize?: (id: string) => boolean | undefined; -} - -export declare function isDepsOptimizerEnabled(config: ResolvedConfig, ssr: boolean): boolean; - -export declare interface JsonOptions { - /** - * Generate a named export for every property of the JSON object - * @default true - */ - namedExports?: boolean; - /** - * Generate performant output as JSON.parse("stringified"). - * Enabling this will disable namedExports. - * @default false - */ - stringify?: boolean; -} - -export declare interface KnownAsTypeMap { - raw: string - url: string - worker: Worker -} - -export declare interface LegacyOptions { - /** - * Revert vite build --ssr to the v2.9 strategy. Use CJS SSR build and v2.9 externalization heuristics - * - * @experimental - * @deprecated - * @default false - */ - buildSsrCjsExternalHeuristics?: boolean; -} - -export declare type LibraryFormats = 'es' | 'cjs' | 'umd' | 'iife'; - -export declare interface LibraryOptions { - /** - * Path of library entry - */ - entry: string; - /** - * The name of the exposed global variable. Required when the `formats` option includes - * `umd` or `iife` - */ - name?: string; - /** - * Output bundle formats - * @default ['es', 'umd'] - */ - formats?: LibraryFormats[]; - /** - * The name of the package file output. The default file name is the name option - * of the project package.json. It can also be defined as a function taking the - * format as an argument. - */ - fileName?: string | ((format: ModuleFormat) => string); -} - -export declare function loadConfigFromFile(configEnv: ConfigEnv, configFile?: string, configRoot?: string, logLevel?: LogLevel): Promise<{ - path: string; - config: UserConfig; - dependencies: string[]; -} | null>; - -export declare function loadEnv(mode: string, envDir: string, prefixes?: string | string[]): Record<string, string>; - -export declare interface LogErrorOptions extends LogOptions { - error?: Error | RollupError | null; -} - -export declare interface Logger { - info(msg: string, options?: LogOptions): void; - warn(msg: string, options?: LogOptions): void; - warnOnce(msg: string, options?: LogOptions): void; - error(msg: string, options?: LogErrorOptions): void; - clearScreen(type: LogType): void; - hasErrorLogged(error: Error | RollupError): boolean; - hasWarned: boolean; -} - -export declare interface LoggerOptions { - prefix?: string; - allowClearScreen?: boolean; - customLogger?: Logger; -} - -export declare type LogLevel = LogType | 'silent'; - -export declare interface LogOptions { - clear?: boolean; - timestamp?: boolean; -} - -export declare type LogType = 'error' | 'warn' | 'info'; - -export declare type Manifest = Record<string, ManifestChunk>; - -export declare interface ManifestChunk { - src?: string; - file: string; - css?: string[]; - assets?: string[]; - isEntry?: boolean; - isDynamicEntry?: boolean; - imports?: string[]; - dynamicImports?: string[]; -} - -export declare type Matcher = AnymatchPattern | AnymatchPattern[] - -export declare function mergeAlias(a?: AliasOptions, b?: AliasOptions): AliasOptions | undefined; - -export declare function mergeConfig(defaults: Record<string, any>, overrides: Record<string, any>, isRoot?: boolean): Record<string, any>; - -export declare class ModuleGraph { - private resolveId; - urlToModuleMap: Map<string, ModuleNode>; - idToModuleMap: Map<string, ModuleNode>; - fileToModulesMap: Map<string, Set<ModuleNode>>; - safeModulesPath: Set<string>; - constructor(resolveId: (url: string, ssr: boolean) => Promise<PartialResolvedId | null>); - getModuleByUrl(rawUrl: string, ssr?: boolean): Promise<ModuleNode | undefined>; - getModuleById(id: string): ModuleNode | undefined; - getModulesByFile(file: string): Set<ModuleNode> | undefined; - onFileChange(file: string): void; - invalidateModule(mod: ModuleNode, seen?: Set<ModuleNode>, timestamp?: number): void; - invalidateAll(): void; - /** - * Update the module graph based on a module's updated imports information - * If there are dependencies that no longer have any importers, they are - * returned as a Set. - */ - updateModuleInfo(mod: ModuleNode, importedModules: Set<string | ModuleNode>, importedBindings: Map<string, Set<string>> | null, acceptedModules: Set<string | ModuleNode>, acceptedExports: Set<string> | null, isSelfAccepting: boolean, ssr?: boolean): Promise<Set<ModuleNode> | undefined>; - ensureEntryFromUrl(rawUrl: string, ssr?: boolean, setIsSelfAccepting?: boolean): Promise<ModuleNode>; - createFileOnlyEntry(file: string): ModuleNode; - resolveUrl(url: string, ssr?: boolean): Promise<ResolvedUrl>; -} - -export declare class ModuleNode { - /** - * Public served url path, starts with / - */ - url: string; - /** - * Resolved file system path + query - */ - id: string | null; - file: string | null; - type: 'js' | 'css'; - info?: ModuleInfo; - meta?: Record<string, any>; - importers: Set<ModuleNode>; - importedModules: Set<ModuleNode>; - acceptedHmrDeps: Set<ModuleNode>; - acceptedHmrExports: Set<string> | null; - importedBindings: Map<string, Set<string>> | null; - isSelfAccepting?: boolean; - transformResult: TransformResult | null; - ssrTransformResult: TransformResult | null; - ssrModule: Record<string, any> | null; - ssrError: Error | null; - lastHMRTimestamp: number; - lastInvalidationTimestamp: number; - /** - * @param setIsSelfAccepting - set `false` to set `isSelfAccepting` later. e.g. #7870 - */ - constructor(url: string, setIsSelfAccepting?: boolean); -} - -export declare function normalizePath(id: string): string; - -export declare interface OptimizedDepInfo { - id: string; - file: string; - src?: string; - needsInterop?: boolean; - browserHash?: string; - fileHash?: string; - /** - * During optimization, ids can still be resolved to their final location - * but the bundles may not yet be saved to disk - */ - processing?: Promise<void>; - /** - * ExportData cache, discovered deps will parse the src entry to get exports - * data used both to define if interop is needed and when pre-bundling - */ - exportsData?: Promise<ExportsData>; -} - -/** - * Scan and optimize dependencies within a project. - * Used by Vite CLI when running `vite optimize`. - */ -export declare function optimizeDeps(config: ResolvedConfig, force?: boolean | undefined, asCommand?: boolean): Promise<DepOptimizationMetadata>; - -/** Cache for package.json resolution and package.json contents */ -export declare type PackageCache = Map<string, PackageData>; - -export declare interface PackageData { - dir: string; - hasSideEffects: (id: string) => boolean | 'no-treeshake'; - webResolvedImports: Record<string, string | undefined>; - nodeResolvedImports: Record<string, string | undefined>; - setResolvedCache: (key: string, entry: string, targetWeb: boolean) => void; - getResolvedCache: (key: string, targetWeb: boolean) => string | undefined; - data: { - [field: string]: any; - name: string; - type: string; - version: string; - main: string; - module: string; - browser: string | Record<string, string | false>; - exports: string | Record<string, any> | string[]; - dependencies: Record<string, string>; - }; -} - -/** - * Vite plugins extends the Rollup plugin interface with a few extra - * vite-specific options. A valid vite plugin is also a valid Rollup plugin. - * On the contrary, a Rollup plugin may or may NOT be a valid vite universal - * plugin, since some Rollup features do not make sense in an unbundled - * dev server context. That said, as long as a rollup plugin doesn't have strong - * coupling between its bundle phase and output phase hooks then it should - * just work (that means, most of them). - * - * By default, the plugins are run during both serve and build. When a plugin - * is applied during serve, it will only run **non output plugin hooks** (see - * rollup type definition of {@link rollup#PluginHooks}). You can think of the - * dev server as only running `const bundle = rollup.rollup()` but never calling - * `bundle.generate()`. - * - * A plugin that expects to have different behavior depending on serve/build can - * export a factory function that receives the command being run via options. - * - * If a plugin should be applied only for server or build, a function format - * config file can be used to conditional determine the plugins to use. - */ -declare interface Plugin_2 extends Plugin_3 { - /** - * Enforce plugin invocation tier similar to webpack loaders. - * - * Plugin invocation order: - * - alias resolution - * - `enforce: 'pre'` plugins - * - vite core plugins - * - normal plugins - * - vite build plugins - * - `enforce: 'post'` plugins - * - vite build post plugins - */ - enforce?: 'pre' | 'post'; - /** - * Apply the plugin only for serve or build, or on certain conditions. - */ - apply?: 'serve' | 'build' | ((config: UserConfig, env: ConfigEnv) => boolean); - /** - * Modify vite config before it's resolved. The hook can either mutate the - * passed-in config directly, or return a partial config object that will be - * deeply merged into existing config. - * - * Note: User plugins are resolved before running this hook so injecting other - * plugins inside the `config` hook will have no effect. - */ - config?: (config: UserConfig, env: ConfigEnv) => UserConfig | null | void | Promise<UserConfig | null | void>; - /** - * Use this hook to read and store the final resolved vite config. - */ - configResolved?: (config: ResolvedConfig) => void | Promise<void>; - /** - * Configure the vite server. The hook receives the {@link ViteDevServer} - * instance. This can also be used to store a reference to the server - * for use in other hooks. - * - * The hooks will be called before internal middlewares are applied. A hook - * can return a post hook that will be called after internal middlewares - * are applied. Hook can be async functions and will be called in series. - */ - configureServer?: ServerHook; - /** - * Configure the preview server. The hook receives the connect server and - * its underlying http server. - * - * The hooks are called before other middlewares are applied. A hook can - * return a post hook that will be called after other middlewares are - * applied. Hooks can be async functions and will be called in series. - */ - configurePreviewServer?: PreviewServerHook; - /** - * Transform index.html. - * The hook receives the following arguments: - * - * - html: string - * - ctx?: vite.ServerContext (only present during serve) - * - bundle?: rollup.OutputBundle (only present during build) - * - * It can either return a transformed string, or a list of html tag - * descriptors that will be injected into the <head> or <body>. - * - * By default the transform is applied **after** vite's internal html - * transform. If you need to apply the transform before vite, use an object: - * `{ enforce: 'pre', transform: hook }` - */ - transformIndexHtml?: IndexHtmlTransform; - /** - * Perform custom handling of HMR updates. - * The handler receives a context containing changed filename, timestamp, a - * list of modules affected by the file change, and the dev server instance. - * - * - The hook can return a filtered list of modules to narrow down the update. - * e.g. for a Vue SFC, we can narrow down the part to update by comparing - * the descriptors. - * - * - The hook can also return an empty array and then perform custom updates - * by sending a custom hmr payload via server.ws.send(). - * - * - If the hook doesn't return a value, the hmr update will be performed as - * normal. - */ - handleHotUpdate?(ctx: HmrContext): Array<ModuleNode> | void | Promise<Array<ModuleNode> | void>; - /** - * extend hooks with ssr flag - */ - resolveId?: (this: PluginContext, source: string, importer: string | undefined, options: { - custom?: CustomPluginOptions; - ssr?: boolean; - /* Excluded from this release type: scan */ - isEntry: boolean; - }) => Promise<ResolveIdResult> | ResolveIdResult; - load?: (this: PluginContext, id: string, options?: { - ssr?: boolean; - }) => Promise<LoadResult> | LoadResult; - transform?: (this: TransformPluginContext, code: string, id: string, options?: { - ssr?: boolean; - }) => Promise<TransformResult_2> | TransformResult_2; -} -export { Plugin_2 as Plugin } - -export declare interface PluginContainer { - options: InputOptions; - getModuleInfo(id: string): ModuleInfo | null; - buildStart(options: InputOptions): Promise<void>; - resolveId(id: string, importer?: string, options?: { - custom?: CustomPluginOptions; - skip?: Set<Plugin_2>; - ssr?: boolean; - /* Excluded from this release type: scan */ - isEntry?: boolean; - }): Promise<PartialResolvedId | null>; - transform(code: string, id: string, options?: { - inMap?: SourceDescription['map']; - ssr?: boolean; - }): Promise<SourceDescription | null>; - load(id: string, options?: { - ssr?: boolean; - }): Promise<LoadResult | null>; - close(): Promise<void>; -} - -export declare type PluginOption = Plugin_2 | false | null | undefined | PluginOption[] | Promise<Plugin_2 | false | null | undefined | PluginOption[]>; - -/** - * Starts the Vite server in preview mode, to simulate a production deployment - */ -export declare function preview(inlineConfig?: InlineConfig): Promise<PreviewServer>; - -export declare interface PreviewOptions extends CommonServerOptions { -} - -export declare interface PreviewServer { - /** - * The resolved vite config object - */ - config: ResolvedConfig; - /** - * native Node http server instance - */ - httpServer: http.Server; - /** - * The resolved urls Vite prints on the CLI - * - * @experimental - */ - resolvedUrls: ResolvedServerUrls; - /** - * Print server urls - */ - printUrls(): void; -} - -export declare type PreviewServerHook = (server: { - middlewares: Connect.Server; - httpServer: http.Server; -}) => (() => void) | void | Promise<(() => void) | void>; - -export declare interface ProxyOptions extends HttpProxy.ServerOptions { - /** - * rewrite path - */ - rewrite?: (path: string) => string; - /** - * configure the proxy server (e.g. listen to events) - */ - configure?: (proxy: HttpProxy.Server, options: ProxyOptions) => void; - /** - * webpack-dev-server style bypass function - */ - bypass?: (req: http.IncomingMessage, res: http.ServerResponse, options: ProxyOptions) => void | null | undefined | false | string; -} - -export declare interface PrunePayload { - type: 'prune' - paths: string[] -} - -export declare type RenderBuiltAssetUrl = (filename: string, type: { - type: 'asset' | 'public'; - hostId: string; - hostType: 'js' | 'css' | 'html'; - ssr: boolean; -}) => string | { - relative?: boolean; - runtime?: string; -} | undefined; - -/** - * Resolve base url. Note that some users use Vite to build for non-web targets like - * electron or expects to deploy - */ -export declare function resolveBaseUrl(base: string | undefined, isBuild: boolean, logger: Logger): string; - -export declare function resolveConfig(inlineConfig: InlineConfig, command: 'build' | 'serve', defaultMode?: string): Promise<ResolvedConfig>; - -export declare type ResolvedBuildOptions = Required<BuildOptions>; - -export declare type ResolvedConfig = Readonly<Omit<UserConfig, 'plugins' | 'assetsInclude' | 'optimizeDeps' | 'worker'> & { - configFile: string | undefined; - configFileDependencies: string[]; - inlineConfig: InlineConfig; - root: string; - base: string; - publicDir: string; - cacheDir: string; - command: 'build' | 'serve'; - mode: string; - isWorker: boolean; - /* Excluded from this release type: mainConfig */ - isProduction: boolean; - env: Record<string, any>; - resolve: ResolveOptions & { - alias: Alias[]; - }; - plugins: readonly Plugin_2[]; - server: ResolvedServerOptions; - build: ResolvedBuildOptions; - preview: ResolvedPreviewOptions; - ssr: ResolvedSSROptions; - assetsInclude: (file: string) => boolean; - logger: Logger; - createResolver: (options?: Partial<InternalResolveOptions>) => ResolveFn; - optimizeDeps: DepOptimizationOptions; - /* Excluded from this release type: packageCache */ - worker: ResolveWorkerOptions; - appType: AppType; - experimental: ExperimentalOptions; -}>; - -export declare interface ResolvedPreviewOptions extends PreviewOptions { -} - -export declare interface ResolvedServerOptions extends ServerOptions { - fs: Required<FileSystemServeOptions>; - middlewareMode: boolean; -} - -export declare interface ResolvedServerUrls { - local: string[]; - network: string[]; -} - -export declare interface ResolvedSSROptions extends SSROptions { - target: SSRTarget; - format: SSRFormat; - optimizeDeps: SsrDepOptimizationOptions; -} - -export declare type ResolvedUrl = [ -url: string, -resolvedId: string, -meta: object | null | undefined -]; - -export declare function resolveEnvPrefix({ envPrefix }: UserConfig): string[]; - -export declare type ResolveFn = (id: string, importer?: string, aliasOnly?: boolean, ssr?: boolean) => Promise<string | undefined>; - -export declare interface ResolveOptions { - mainFields?: string[]; - conditions?: string[]; - extensions?: string[]; - dedupe?: string[]; - preserveSymlinks?: boolean; -} - -export declare function resolvePackageData(id: string, basedir: string, preserveSymlinks?: boolean, packageCache?: PackageCache): PackageData | null; - -export declare function resolvePackageEntry(id: string, { dir, data, setResolvedCache, getResolvedCache }: PackageData, targetWeb: boolean, options: InternalResolveOptions): string | undefined; - -export declare type ResolverFunction = PluginHooks['resolveId'] - -export declare interface ResolverObject { - buildStart?: PluginHooks['buildStart'] - resolveId: ResolverFunction -} - -export declare interface ResolveWorkerOptions { - format: 'es' | 'iife'; - plugins: Plugin_2[]; - rollupOptions: RollupOptions; -} - -/** - * https://github.com/rollup/plugins/blob/master/packages/commonjs/types/index.d.ts - * - * This source code is licensed under the MIT license found in the - * LICENSE file at - * https://github.com/rollup/plugins/blob/master/LICENSE - */ -export declare interface RollupCommonJSOptions { - /** - * A minimatch pattern, or array of patterns, which specifies the files in - * the build the plugin should operate on. By default, all files with - * extension `".cjs"` or those in `extensions` are included, but you can - * narrow this list by only including specific files. These files will be - * analyzed and transpiled if either the analysis does not find ES module - * specific statements or `transformMixedEsModules` is `true`. - * @default undefined - */ - include?: string | RegExp | readonly (string | RegExp)[] - /** - * A minimatch pattern, or array of patterns, which specifies the files in - * the build the plugin should _ignore_. By default, all files with - * extensions other than those in `extensions` or `".cjs"` are ignored, but you - * can exclude additional files. See also the `include` option. - * @default undefined - */ - exclude?: string | RegExp | readonly (string | RegExp)[] - /** - * For extensionless imports, search for extensions other than .js in the - * order specified. Note that you need to make sure that non-JavaScript files - * are transpiled by another plugin first. - * @default [ '.js' ] - */ - extensions?: ReadonlyArray<string> - /** - * If true then uses of `global` won't be dealt with by this plugin - * @default false - */ - ignoreGlobal?: boolean - /** - * If false, skips source map generation for CommonJS modules. This will - * improve performance. - * @default true - */ - sourceMap?: boolean - /** - * Some `require` calls cannot be resolved statically to be translated to - * imports. - * When this option is set to `false`, the generated code will either - * directly throw an error when such a call is encountered or, when - * `dynamicRequireTargets` is used, when such a call cannot be resolved with a - * configured dynamic require target. - * Setting this option to `true` will instead leave the `require` call in the - * code or use it as a fallback for `dynamicRequireTargets`. - * @default false - */ - ignoreDynamicRequires?: boolean - /** - * Instructs the plugin whether to enable mixed module transformations. This - * is useful in scenarios with modules that contain a mix of ES `import` - * statements and CommonJS `require` expressions. Set to `true` if `require` - * calls should be transformed to imports in mixed modules, or `false` if the - * `require` expressions should survive the transformation. The latter can be - * important if the code contains environment detection, or you are coding - * for an environment with special treatment for `require` calls such as - * ElectronJS. See also the `ignore` option. - * @default false - */ - transformMixedEsModules?: boolean - /** - * By default, this plugin will try to hoist `require` statements as imports - * to the top of each file. While this works well for many code bases and - * allows for very efficient ESM output, it does not perfectly capture - * CommonJS semantics as the order of side effects like log statements may - * change. But it is especially problematic when there are circular `require` - * calls between CommonJS modules as those often rely on the lazy execution of - * nested `require` calls. - * - * Setting this option to `true` will wrap all CommonJS files in functions - * which are executed when they are required for the first time, preserving - * NodeJS semantics. Note that this can have an impact on the size and - * performance of the generated code. - * - * The default value of `"auto"` will only wrap CommonJS files when they are - * part of a CommonJS dependency cycle, e.g. an index file that is required by - * many of its dependencies. All other CommonJS files are hoisted. This is the - * recommended setting for most code bases. - * - * `false` will entirely prevent wrapping and hoist all files. This may still - * work depending on the nature of cyclic dependencies but will often cause - * problems. - * - * You can also provide a minimatch pattern, or array of patterns, to only - * specify a subset of files which should be wrapped in functions for proper - * `require` semantics. - * - * `"debug"` works like `"auto"` but after bundling, it will display a warning - * containing a list of ids that have been wrapped which can be used as - * minimatch pattern for fine-tuning. - * @default "auto" - */ - strictRequires?: boolean | string | RegExp | readonly (string | RegExp)[] - /** - * Sometimes you have to leave require statements unconverted. Pass an array - * containing the IDs or a `id => boolean` function. - * @default [] - */ - ignore?: ReadonlyArray<string> | ((id: string) => boolean) - /** - * In most cases, where `require` calls are inside a `try-catch` clause, - * they should be left unconverted as it requires an optional dependency - * that may or may not be installed beside the rolled up package. - * Due to the conversion of `require` to a static `import` - the call is - * hoisted to the top of the file, outside of the `try-catch` clause. - * - * - `true`: All `require` calls inside a `try` will be left unconverted. - * - `false`: All `require` calls inside a `try` will be converted as if the - * `try-catch` clause is not there. - * - `remove`: Remove all `require` calls from inside any `try` block. - * - `string[]`: Pass an array containing the IDs to left unconverted. - * - `((id: string) => boolean|'remove')`: Pass a function that control - * individual IDs. - * - * @default false - */ - ignoreTryCatch?: - | boolean - | 'remove' - | ReadonlyArray<string> - | ((id: string) => boolean | 'remove') - /** - * Controls how to render imports from external dependencies. By default, - * this plugin assumes that all external dependencies are CommonJS. This - * means they are rendered as default imports to be compatible with e.g. - * NodeJS where ES modules can only import a default export from a CommonJS - * dependency. - * - * If you set `esmExternals` to `true`, this plugins assumes that all - * external dependencies are ES modules and respect the - * `requireReturnsDefault` option. If that option is not set, they will be - * rendered as namespace imports. - * - * You can also supply an array of ids to be treated as ES modules, or a - * function that will be passed each external id to determine if it is an ES - * module. - * @default false - */ - esmExternals?: boolean | ReadonlyArray<string> | ((id: string) => boolean) - /** - * Controls what is returned when requiring an ES module from a CommonJS file. - * When using the `esmExternals` option, this will also apply to external - * modules. By default, this plugin will render those imports as namespace - * imports i.e. - * - * ```js - * // input - * const foo = require('foo'); - * - * // output - * import * as foo from 'foo'; - * ``` - * - * However there are some situations where this may not be desired. - * For these situations, you can change Rollup's behaviour either globally or - * per module. To change it globally, set the `requireReturnsDefault` option - * to one of the following values: - * - * - `false`: This is the default, requiring an ES module returns its - * namespace. This is the only option that will also add a marker - * `__esModule: true` to the namespace to support interop patterns in - * CommonJS modules that are transpiled ES modules. - * - `"namespace"`: Like `false`, requiring an ES module returns its - * namespace, but the plugin does not add the `__esModule` marker and thus - * creates more efficient code. For external dependencies when using - * `esmExternals: true`, no additional interop code is generated. - * - `"auto"`: This is complementary to how `output.exports: "auto"` works in - * Rollup: If a module has a default export and no named exports, requiring - * that module returns the default export. In all other cases, the namespace - * is returned. For external dependencies when using `esmExternals: true`, a - * corresponding interop helper is added. - * - `"preferred"`: If a module has a default export, requiring that module - * always returns the default export, no matter whether additional named - * exports exist. This is similar to how previous versions of this plugin - * worked. Again for external dependencies when using `esmExternals: true`, - * an interop helper is added. - * - `true`: This will always try to return the default export on require - * without checking if it actually exists. This can throw at build time if - * there is no default export. This is how external dependencies are handled - * when `esmExternals` is not used. The advantage over the other options is - * that, like `false`, this does not add an interop helper for external - * dependencies, keeping the code lean. - * - * To change this for individual modules, you can supply a function for - * `requireReturnsDefault` instead. This function will then be called once for - * each required ES module or external dependency with the corresponding id - * and allows you to return different values for different modules. - * @default false - */ - requireReturnsDefault?: - | boolean - | 'auto' - | 'preferred' - | 'namespace' - | ((id: string) => boolean | 'auto' | 'preferred' | 'namespace') - - /** - * @default "auto" - */ - defaultIsModuleExports?: boolean | 'auto' | ((id: string) => boolean | 'auto') - /** - * Some modules contain dynamic `require` calls, or require modules that - * contain circular dependencies, which are not handled well by static - * imports. Including those modules as `dynamicRequireTargets` will simulate a - * CommonJS (NodeJS-like) environment for them with support for dynamic - * dependencies. It also enables `strictRequires` for those modules. - * - * Note: In extreme cases, this feature may result in some paths being - * rendered as absolute in the final bundle. The plugin tries to avoid - * exposing paths from the local machine, but if you are `dynamicRequirePaths` - * with paths that are far away from your project's folder, that may require - * replacing strings like `"/Users/John/Desktop/foo-project/"` -\> `"/"`. - */ - dynamicRequireTargets?: string | ReadonlyArray<string> - /** - * To avoid long paths when using the `dynamicRequireTargets` option, you can use this option to specify a directory - * that is a common parent for all files that use dynamic require statements. Using a directory higher up such as `/` - * may lead to unnecessarily long paths in the generated code and may expose directory names on your machine like your - * home directory name. By default it uses the current working directory. - */ - dynamicRequireRoot?: string -} - -export declare interface RollupDynamicImportVarsOptions { - /** - * Files to include in this plugin (default all). - * @default [] - */ - include?: string | RegExp | (string | RegExp)[] - /** - * Files to exclude in this plugin (default none). - * @default [] - */ - exclude?: string | RegExp | (string | RegExp)[] - /** - * By default, the plugin quits the build process when it encounters an error. If you set this option to true, it will throw a warning instead and leave the code untouched. - * @default false - */ - warnOnError?: boolean -} - -export { rollupVersion } - -/** - * Search up for the nearest workspace root - */ -export declare function searchForWorkspaceRoot(current: string, root?: string): string; - -export declare function send(req: IncomingMessage, res: ServerResponse, content: string | Buffer, type: string, options: SendOptions): void; - -export declare interface SendOptions { - etag?: string; - cacheControl?: string; - headers?: OutgoingHttpHeaders; - map?: SourceMap | null; -} - -export declare type ServerHook = (server: ViteDevServer) => (() => void) | void | Promise<(() => void) | void>; - -export declare interface ServerOptions extends CommonServerOptions { - /** - * Configure HMR-specific options (port, host, path & protocol) - */ - hmr?: HmrOptions | boolean; - /** - * chokidar watch options - * https://github.com/paulmillr/chokidar#api - */ - watch?: WatchOptions; - /** - * Create Vite dev server to be used as a middleware in an existing server - */ - middlewareMode?: boolean | 'html' | 'ssr'; - /** - * Prepend this folder to http requests, for use when proxying vite as a subfolder - * Should start and end with the `/` character - */ - base?: string; - /** - * Options for files served via '/\@fs/'. - */ - fs?: FileSystemServeOptions; - /** - * Origin for the generated asset URLs. - * - * @example `http://127.0.0.1:8080` - */ - origin?: string; - /** - * Pre-transform known direct imports - * @default true - */ - preTransformRequests?: boolean; - /** - * Force dep pre-optimization regardless of whether deps have changed. - * - * @deprecated Use optimizeDeps.force instead, this option may be removed - * in a future minor version without following semver - */ - force?: boolean; -} - -export declare function sortUserPlugins(plugins: (Plugin_2 | Plugin_2[])[] | undefined): [Plugin_2[], Plugin_2[], Plugin_2[]]; - -export declare function splitVendorChunk(options?: { - cache?: SplitVendorChunkCache; -}): GetManualChunk; - -export declare class SplitVendorChunkCache { - cache: Map<string, boolean>; - constructor(); - reset(): void; -} - -export declare function splitVendorChunkPlugin(): Plugin_2; - -export declare type SsrDepOptimizationOptions = DepOptimizationConfig; - -export declare type SSRFormat = 'esm' | 'cjs'; - -export declare interface SSROptions { - noExternal?: string | RegExp | (string | RegExp)[] | true; - external?: string[]; - /** - * Define the target for the ssr build. The browser field in package.json - * is ignored for node but used if webworker is the target - * Default: 'node' - */ - target?: SSRTarget; - /** - * Define the format for the ssr build. Since Vite v3 the SSR build generates ESM by default. - * `'cjs'` can be selected to generate a CJS build, but it isn't recommended. This option is - * left marked as experimental to give users more time to update to ESM. CJS builds requires - * complex externalization heuristics that aren't present in the ESM format. - * @experimental - */ - format?: SSRFormat; - /** - * Control over which dependencies are optimized during SSR and esbuild options - * During build: - * no external CJS dependencies are optimized by default - * During dev: - * explicit no external CJS dependencies are optimized by default - * @experimental - */ - optimizeDeps?: SsrDepOptimizationOptions; -} - -export declare type SSRTarget = 'node' | 'webworker'; - -export declare namespace Terser { - export type ECMA = 5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 - - export interface ParseOptions { - bare_returns?: boolean - /** @deprecated legacy option. Currently, all supported EcmaScript is valid to parse. */ - ecma?: ECMA - html5_comments?: boolean - shebang?: boolean - } - - export interface CompressOptions { - arguments?: boolean - arrows?: boolean - booleans_as_integers?: boolean - booleans?: boolean - collapse_vars?: boolean - comparisons?: boolean - computed_props?: boolean - conditionals?: boolean - dead_code?: boolean - defaults?: boolean - directives?: boolean - drop_console?: boolean - drop_debugger?: boolean - ecma?: ECMA - evaluate?: boolean - expression?: boolean - global_defs?: object - hoist_funs?: boolean - hoist_props?: boolean - hoist_vars?: boolean - ie8?: boolean - if_return?: boolean - inline?: boolean | InlineFunctions - join_vars?: boolean - keep_classnames?: boolean | RegExp - keep_fargs?: boolean - keep_fnames?: boolean | RegExp - keep_infinity?: boolean - loops?: boolean - module?: boolean - negate_iife?: boolean - passes?: number - properties?: boolean - pure_funcs?: string[] - pure_getters?: boolean | 'strict' - reduce_funcs?: boolean - reduce_vars?: boolean - sequences?: boolean | number - side_effects?: boolean - switches?: boolean - toplevel?: boolean - top_retain?: null | string | string[] | RegExp - typeofs?: boolean - unsafe_arrows?: boolean - unsafe?: boolean - unsafe_comps?: boolean - unsafe_Function?: boolean - unsafe_math?: boolean - unsafe_symbols?: boolean - unsafe_methods?: boolean - unsafe_proto?: boolean - unsafe_regexp?: boolean - unsafe_undefined?: boolean - unused?: boolean - } - - export enum InlineFunctions { - Disabled = 0, - SimpleFunctions = 1, - WithArguments = 2, - WithArgumentsAndVariables = 3 - } - - export interface MangleOptions { - eval?: boolean - keep_classnames?: boolean | RegExp - keep_fnames?: boolean | RegExp - module?: boolean - nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler - properties?: boolean | ManglePropertiesOptions - reserved?: string[] - safari10?: boolean - toplevel?: boolean - } - - /** - * An identifier mangler for which the output is invariant with respect to the source code. - */ - export interface SimpleIdentifierMangler { - /** - * Obtains the nth most favored (usually shortest) identifier to rename a variable to. - * The mangler will increment n and retry until the return value is not in use in scope, and is not a reserved word. - * This function is expected to be stable; Evaluating get(n) === get(n) should always return true. - * @param n - The ordinal of the identifier. - */ - get(n: number): string - } - - /** - * An identifier mangler that leverages character frequency analysis to determine identifier precedence. - */ - export interface WeightedIdentifierMangler extends SimpleIdentifierMangler { - /** - * Modifies the internal weighting of the input characters by the specified delta. - * Will be invoked on the entire printed AST, and then deduct mangleable identifiers. - * @param chars - The characters to modify the weighting of. - * @param delta - The numeric weight to add to the characters. - */ - consider(chars: string, delta: number): number - /** - * Resets character weights. - */ - reset(): void - /** - * Sorts identifiers by character frequency, in preparation for calls to get(n). - */ - sort(): void - } - - export interface ManglePropertiesOptions { - builtins?: boolean - debug?: boolean - keep_quoted?: boolean | 'strict' - nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler - regex?: RegExp | string - reserved?: string[] - } - - export interface FormatOptions { - ascii_only?: boolean - /** @deprecated Not implemented anymore */ - beautify?: boolean - braces?: boolean - comments?: - | boolean - | 'all' - | 'some' - | RegExp - | (( - node: any, - comment: { - value: string - type: 'comment1' | 'comment2' | 'comment3' | 'comment4' - pos: number - line: number - col: number - } - ) => boolean) - ecma?: ECMA - ie8?: boolean - keep_numbers?: boolean - indent_level?: number - indent_start?: number - inline_script?: boolean - keep_quoted_props?: boolean - max_line_len?: number | false - preamble?: string - preserve_annotations?: boolean - quote_keys?: boolean - quote_style?: OutputQuoteStyle - safari10?: boolean - semicolons?: boolean - shebang?: boolean - shorthand?: boolean - source_map?: SourceMapOptions - webkit?: boolean - width?: number - wrap_iife?: boolean - wrap_func_args?: boolean - } - - export enum OutputQuoteStyle { - PreferDouble = 0, - AlwaysSingle = 1, - AlwaysDouble = 2, - AlwaysOriginal = 3 - } - - export interface MinifyOptions { - compress?: boolean | CompressOptions - ecma?: ECMA - enclose?: boolean | string - ie8?: boolean - keep_classnames?: boolean | RegExp - keep_fnames?: boolean | RegExp - mangle?: boolean | MangleOptions - module?: boolean - nameCache?: object - format?: FormatOptions - /** @deprecated deprecated */ - output?: FormatOptions - parse?: ParseOptions - safari10?: boolean - sourceMap?: boolean | SourceMapOptions - toplevel?: boolean - } - - export interface MinifyOutput { - code?: string - map?: object | string - decoded_map?: object | null - } - - export interface SourceMapOptions { - /** Source map object, 'inline' or source map file content */ - content?: object | string - includeSources?: boolean - filename?: string - root?: string - url?: string | 'inline' - } -} - -export declare interface TransformOptions { - ssr?: boolean; - html?: boolean; -} - -export declare interface TransformResult { - code: string; - map: SourceMap | null; - etag?: string; - deps?: string[]; - dynamicDeps?: string[]; -} - -export declare function transformWithEsbuild(code: string, filename: string, options?: EsbuildTransformOptions, inMap?: object): Promise<ESBuildTransformResult>; - -export declare interface Update { - type: 'js-update' | 'css-update' - path: string - acceptedPath: string - timestamp: number -} - -export declare interface UpdatePayload { - type: 'update' - updates: Update[] -} - -export declare interface UserConfig { - /** - * Project root directory. Can be an absolute path, or a path relative from - * the location of the config file itself. - * @default process.cwd() - */ - root?: string; - /** - * Base public path when served in development or production. - * @default '/' - */ - base?: string; - /** - * Directory to serve as plain static assets. Files in this directory are - * served and copied to build dist dir as-is without transform. The value - * can be either an absolute file system path or a path relative to <root>. - * - * Set to `false` or an empty string to disable copied static assets to build dist dir. - * @default 'public' - */ - publicDir?: string | false; - /** - * Directory to save cache files. Files in this directory are pre-bundled - * deps or some other cache files that generated by vite, which can improve - * the performance. You can use `--force` flag or manually delete the directory - * to regenerate the cache files. The value can be either an absolute file - * system path or a path relative to <root>. - * Default to `.vite` when no `package.json` is detected. - * @default 'node_modules/.vite' - */ - cacheDir?: string; - /** - * Explicitly set a mode to run in. This will override the default mode for - * each command, and can be overridden by the command line --mode option. - */ - mode?: string; - /** - * Define global variable replacements. - * Entries will be defined on `window` during dev and replaced during build. - */ - define?: Record<string, any>; - /** - * Array of vite plugins to use. - */ - plugins?: PluginOption[]; - /** - * Configure resolver - */ - resolve?: ResolveOptions & { - alias?: AliasOptions; - }; - /** - * CSS related options (preprocessors and CSS modules) - */ - css?: CSSOptions; - /** - * JSON loading options - */ - json?: JsonOptions; - /** - * Transform options to pass to esbuild. - * Or set to `false` to disable esbuild. - */ - esbuild?: ESBuildOptions | false; - /** - * Specify additional picomatch patterns to be treated as static assets. - */ - assetsInclude?: string | RegExp | (string | RegExp)[]; - /** - * Server specific options, e.g. host, port, https... - */ - server?: ServerOptions; - /** - * Build specific options - */ - build?: BuildOptions; - /** - * Preview specific options, e.g. host, port, https... - */ - preview?: PreviewOptions; - /** - * Dep optimization options - */ - optimizeDeps?: DepOptimizationOptions; - /** - * SSR specific options - */ - ssr?: SSROptions; - /** - * Experimental features - * - * Features under this field could change in the future and might NOT follow semver. - * Please be careful and always pin Vite's version when using them. - * @experimental - */ - experimental?: ExperimentalOptions; - /** - * Legacy options - * - * Features under this field only follow semver for patches, they could be removed in a - * future minor version. Please always pin Vite's version to a minor when using them. - */ - legacy?: LegacyOptions; - /** - * Log level. - * Default: 'info' - */ - logLevel?: LogLevel; - /** - * Custom logger. - */ - customLogger?: Logger; - /** - * Default: true - */ - clearScreen?: boolean; - /** - * Environment files directory. Can be an absolute path, or a path relative from - * the location of the config file itself. - * @default root - */ - envDir?: string; - /** - * Env variables starts with `envPrefix` will be exposed to your client source code via import.meta.env. - * @default 'VITE_' - */ - envPrefix?: string | string[]; - /** - * Worker bundle options - */ - worker?: { - /** - * Output format for worker bundle - * @default 'iife' - */ - format?: 'es' | 'iife'; - /** - * Vite plugins that apply to worker bundle - */ - plugins?: PluginOption[]; - /** - * Rollup options to build worker bundle - */ - rollupOptions?: Omit<RollupOptions, 'plugins' | 'input' | 'onwarn' | 'preserveEntrySignatures'>; - }; - /** - * Whether your application is a Single Page Application (SPA), - * a Multi-Page Application (MPA), or Custom Application (SSR - * and frameworks with custom HTML handling) - * @default 'spa' - */ - appType?: AppType; -} - -export declare type UserConfigExport = UserConfig | Promise<UserConfig> | UserConfigFn; - -export declare type UserConfigFn = (env: ConfigEnv) => UserConfig | Promise<UserConfig>; - -export declare const version: string; - -export declare interface ViteDevServer { - /** - * The resolved vite config object - */ - config: ResolvedConfig; - /** - * A connect app instance. - * - Can be used to attach custom middlewares to the dev server. - * - Can also be used as the handler function of a custom http server - * or as a middleware in any connect-style Node.js frameworks - * - * https://github.com/senchalabs/connect#use-middleware - */ - middlewares: Connect.Server; - /** - * native Node http server instance - * will be null in middleware mode - */ - httpServer: http.Server | null; - /** - * chokidar watcher instance - * https://github.com/paulmillr/chokidar#api - */ - watcher: FSWatcher; - /** - * web socket server with `send(payload)` method - */ - ws: WebSocketServer; - /** - * Rollup plugin container that can run plugin hooks on a given file - */ - pluginContainer: PluginContainer; - /** - * Module graph that tracks the import relationships, url to file mapping - * and hmr state. - */ - moduleGraph: ModuleGraph; - /** - * The resolved urls Vite prints on the CLI. null in middleware mode or - * before `server.listen` is called. - * - * @experimental - */ - resolvedUrls: ResolvedServerUrls | null; - /** - * Programmatically resolve, load and transform a URL and get the result - * without going through the http request pipeline. - */ - transformRequest(url: string, options?: TransformOptions): Promise<TransformResult | null>; - /** - * Apply vite built-in HTML transforms and any plugin HTML transforms. - */ - transformIndexHtml(url: string, html: string, originalUrl?: string): Promise<string>; - /** - * Transform module code into SSR format. - */ - ssrTransform(code: string, inMap: SourceMap | null, url: string): Promise<TransformResult | null>; - /** - * Load a given URL as an instantiated module for SSR. - */ - ssrLoadModule(url: string, opts?: { - fixStacktrace?: boolean; - }): Promise<Record<string, any>>; - /** - * Returns a fixed version of the given stack - */ - ssrRewriteStacktrace(stack: string): string; - /** - * Mutates the given SSR error by rewriting the stacktrace - */ - ssrFixStacktrace(e: Error): void; - /** - * Start the server. - */ - listen(port?: number, isRestart?: boolean): Promise<ViteDevServer>; - /** - * Stop the server. - */ - close(): Promise<void>; - /** - * Print server urls - */ - printUrls(): void; - /** - * Restart the server. - * - * @param forceOptimize - force the optimizer to re-bundle, same as --force cli flag - */ - restart(forceOptimize?: boolean): Promise<void>; - /* Excluded from this release type: _importGlobMap */ - /* Excluded from this release type: _ssrExternals */ - /* Excluded from this release type: _restartPromise */ - /* Excluded from this release type: _forceOptimizeOnRestart */ - /* Excluded from this release type: _pendingRequests */ -} - -export declare interface WatchOptions { - /** - * Indicates whether the process should continue to run as long as files are being watched. If - * set to `false` when using `fsevents` to watch, no more events will be emitted after `ready`, - * even if the process continues to run. - */ - persistent?: boolean - - /** - * ([anymatch](https://github.com/micromatch/anymatch)-compatible definition) Defines files/paths to - * be ignored. The whole relative or absolute path is tested, not just filename. If a function - * with two arguments is provided, it gets called twice per path - once with a single argument - * (the path), second time with two arguments (the path and the - * [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object of that path). - */ - ignored?: Matcher - - /** - * If set to `false` then `add`/`addDir` events are also emitted for matching paths while - * instantiating the watching as chokidar discovers these file paths (before the `ready` event). - */ - ignoreInitial?: boolean - - /** - * When `false`, only the symlinks themselves will be watched for changes instead of following - * the link references and bubbling events through the link's path. - */ - followSymlinks?: boolean - - /** - * The base directory from which watch `paths` are to be derived. Paths emitted with events will - * be relative to this. - */ - cwd?: string - - /** - * If set to true then the strings passed to .watch() and .add() are treated as literal path - * names, even if they look like globs. - * - * @default false - */ - disableGlobbing?: boolean - - /** - * Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU - * utilization, consider setting this to `false`. It is typically necessary to **set this to - * `true` to successfully watch files over a network**, and it may be necessary to successfully - * watch files in other non-standard situations. Setting to `true` explicitly on OS X overrides - * the `useFsEvents` default. - */ - usePolling?: boolean - - /** - * Whether to use the `fsevents` watching interface if available. When set to `true` explicitly - * and `fsevents` is available this supercedes the `usePolling` setting. When set to `false` on - * OS X, `usePolling: true` becomes the default. - */ - useFsEvents?: boolean - - /** - * If relying upon the [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object that - * may get passed with `add`, `addDir`, and `change` events, set this to `true` to ensure it is - * provided even in cases where it wasn't already available from the underlying watch events. - */ - alwaysStat?: boolean - - /** - * If set, limits how many levels of subdirectories will be traversed. - */ - depth?: number - - /** - * Interval of file system polling. - */ - interval?: number - - /** - * Interval of file system polling for binary files. ([see list of binary extensions](https://gi - * thub.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json)) - */ - binaryInterval?: number - - /** - * Indicates whether to watch files that don't have read permissions if possible. If watching - * fails due to `EPERM` or `EACCES` with this set to `true`, the errors will be suppressed - * silently. - */ - ignorePermissionErrors?: boolean - - /** - * `true` if `useFsEvents` and `usePolling` are `false`). Automatically filters out artifacts - * that occur when using editors that use "atomic writes" instead of writing directly to the - * source file. If a file is re-added within 100 ms of being deleted, Chokidar emits a `change` - * event rather than `unlink` then `add`. If the default of 100 ms does not work well for you, - * you can override it by setting `atomic` to a custom value, in milliseconds. - */ - atomic?: boolean | number - - /** - * can be set to an object in order to adjust timing params: - */ - awaitWriteFinish?: AwaitWriteFinishOptions | boolean -} - -declare class WebSocket_2 extends EventEmitter { - /** The connection is not yet open. */ - static readonly CONNECTING: 0 - /** The connection is open and ready to communicate. */ - static readonly OPEN: 1 - /** The connection is in the process of closing. */ - static readonly CLOSING: 2 - /** The connection is closed. */ - static readonly CLOSED: 3 - - binaryType: 'nodebuffer' | 'arraybuffer' | 'fragments' - readonly bufferedAmount: number - readonly extensions: string - /** Indicates whether the websocket is paused */ - readonly isPaused: boolean - readonly protocol: string - /** The current state of the connection */ - readonly readyState: - | typeof WebSocket_2.CONNECTING - | typeof WebSocket_2.OPEN - | typeof WebSocket_2.CLOSING - | typeof WebSocket_2.CLOSED - readonly url: string - - /** The connection is not yet open. */ - readonly CONNECTING: 0 - /** The connection is open and ready to communicate. */ - readonly OPEN: 1 - /** The connection is in the process of closing. */ - readonly CLOSING: 2 - /** The connection is closed. */ - readonly CLOSED: 3 - - onopen: ((event: WebSocket_2.Event) => void) | null - onerror: ((event: WebSocket_2.ErrorEvent) => void) | null - onclose: ((event: WebSocket_2.CloseEvent) => void) | null - onmessage: ((event: WebSocket_2.MessageEvent) => void) | null - - constructor(address: null) - constructor( - address: string | URL_2, - options?: WebSocket_2.ClientOptions | ClientRequestArgs - ) - constructor( - address: string | URL_2, - protocols?: string | string[], - options?: WebSocket_2.ClientOptions | ClientRequestArgs - ) - - close(code?: number, data?: string | Buffer): void - ping(data?: any, mask?: boolean, cb?: (err: Error) => void): void - pong(data?: any, mask?: boolean, cb?: (err: Error) => void): void - send(data: any, cb?: (err?: Error) => void): void - send( - data: any, - options: { - mask?: boolean | undefined - binary?: boolean | undefined - compress?: boolean | undefined - fin?: boolean | undefined - }, - cb?: (err?: Error) => void - ): void - terminate(): void - - /** - * Pause the websocket causing it to stop emitting events. Some events can still be - * emitted after this is called, until all buffered data is consumed. This method - * is a noop if the ready state is `CONNECTING` or `CLOSED`. - */ - pause(): void - /** - * Make a paused socket resume emitting events. This method is a noop if the ready - * state is `CONNECTING` or `CLOSED`. - */ - resume(): void - - // HTML5 WebSocket events - addEventListener( - method: 'message', - cb: (event: WebSocket_2.MessageEvent) => void, - options?: WebSocket_2.EventListenerOptions - ): void - addEventListener( - method: 'close', - cb: (event: WebSocket_2.CloseEvent) => void, - options?: WebSocket_2.EventListenerOptions - ): void - addEventListener( - method: 'error', - cb: (event: WebSocket_2.ErrorEvent) => void, - options?: WebSocket_2.EventListenerOptions - ): void - addEventListener( - method: 'open', - cb: (event: WebSocket_2.Event) => void, - options?: WebSocket_2.EventListenerOptions - ): void - - removeEventListener( - method: 'message', - cb: (event: WebSocket_2.MessageEvent) => void - ): void - removeEventListener( - method: 'close', - cb: (event: WebSocket_2.CloseEvent) => void - ): void - removeEventListener( - method: 'error', - cb: (event: WebSocket_2.ErrorEvent) => void - ): void - removeEventListener( - method: 'open', - cb: (event: WebSocket_2.Event) => void - ): void - - // Events - on( - event: 'close', - listener: (this: WebSocket_2, code: number, reason: Buffer) => void - ): this - on(event: 'error', listener: (this: WebSocket_2, err: Error) => void): this - on( - event: 'upgrade', - listener: (this: WebSocket_2, request: IncomingMessage) => void - ): this - on( - event: 'message', - listener: ( - this: WebSocket_2, - data: WebSocket_2.RawData, - isBinary: boolean - ) => void - ): this - on(event: 'open', listener: (this: WebSocket_2) => void): this - on( - event: 'ping' | 'pong', - listener: (this: WebSocket_2, data: Buffer) => void - ): this - on( - event: 'unexpected-response', - listener: ( - this: WebSocket_2, - request: ClientRequest, - response: IncomingMessage - ) => void - ): this - on( - event: string | symbol, - listener: (this: WebSocket_2, ...args: any[]) => void - ): this - - once( - event: 'close', - listener: (this: WebSocket_2, code: number, reason: Buffer) => void - ): this - once(event: 'error', listener: (this: WebSocket_2, err: Error) => void): this - once( - event: 'upgrade', - listener: (this: WebSocket_2, request: IncomingMessage) => void - ): this - once( - event: 'message', - listener: ( - this: WebSocket_2, - data: WebSocket_2.RawData, - isBinary: boolean - ) => void - ): this - once(event: 'open', listener: (this: WebSocket_2) => void): this - once( - event: 'ping' | 'pong', - listener: (this: WebSocket_2, data: Buffer) => void - ): this - once( - event: 'unexpected-response', - listener: ( - this: WebSocket_2, - request: ClientRequest, - response: IncomingMessage - ) => void - ): this - once( - event: string | symbol, - listener: (this: WebSocket_2, ...args: any[]) => void - ): this - - off( - event: 'close', - listener: (this: WebSocket_2, code: number, reason: Buffer) => void - ): this - off(event: 'error', listener: (this: WebSocket_2, err: Error) => void): this - off( - event: 'upgrade', - listener: (this: WebSocket_2, request: IncomingMessage) => void - ): this - off( - event: 'message', - listener: ( - this: WebSocket_2, - data: WebSocket_2.RawData, - isBinary: boolean - ) => void - ): this - off(event: 'open', listener: (this: WebSocket_2) => void): this - off( - event: 'ping' | 'pong', - listener: (this: WebSocket_2, data: Buffer) => void - ): this - off( - event: 'unexpected-response', - listener: ( - this: WebSocket_2, - request: ClientRequest, - response: IncomingMessage - ) => void - ): this - off( - event: string | symbol, - listener: (this: WebSocket_2, ...args: any[]) => void - ): this - - addListener( - event: 'close', - listener: (code: number, reason: Buffer) => void - ): this - addListener(event: 'error', listener: (err: Error) => void): this - addListener( - event: 'upgrade', - listener: (request: IncomingMessage) => void - ): this - addListener( - event: 'message', - listener: (data: WebSocket_2.RawData, isBinary: boolean) => void - ): this - addListener(event: 'open', listener: () => void): this - addListener(event: 'ping' | 'pong', listener: (data: Buffer) => void): this - addListener( - event: 'unexpected-response', - listener: (request: ClientRequest, response: IncomingMessage) => void - ): this - addListener(event: string | symbol, listener: (...args: any[]) => void): this - - removeListener( - event: 'close', - listener: (code: number, reason: Buffer) => void - ): this - removeListener(event: 'error', listener: (err: Error) => void): this - removeListener( - event: 'upgrade', - listener: (request: IncomingMessage) => void - ): this - removeListener( - event: 'message', - listener: (data: WebSocket_2.RawData, isBinary: boolean) => void - ): this - removeListener(event: 'open', listener: () => void): this - removeListener(event: 'ping' | 'pong', listener: (data: Buffer) => void): this - removeListener( - event: 'unexpected-response', - listener: (request: ClientRequest, response: IncomingMessage) => void - ): this - removeListener( - event: string | symbol, - listener: (...args: any[]) => void - ): this -} - -declare namespace WebSocket_2 { - /** - * Data represents the raw message payload received over the WebSocket. - */ - type RawData = Buffer | ArrayBuffer | Buffer[] - - /** - * Data represents the message payload received over the WebSocket. - */ - type Data = string | Buffer | ArrayBuffer | Buffer[] - - /** - * CertMeta represents the accepted types for certificate & key data. - */ - type CertMeta = string | string[] | Buffer | Buffer[] - - /** - * VerifyClientCallbackSync is a synchronous callback used to inspect the - * incoming message. The return value (boolean) of the function determines - * whether or not to accept the handshake. - */ - type VerifyClientCallbackSync = (info: { - origin: string - secure: boolean - req: IncomingMessage - }) => boolean - - /** - * VerifyClientCallbackAsync is an asynchronous callback used to inspect the - * incoming message. The return value (boolean) of the function determines - * whether or not to accept the handshake. - */ - type VerifyClientCallbackAsync = ( - info: { origin: string; secure: boolean; req: IncomingMessage }, - callback: ( - res: boolean, - code?: number, - message?: string, - headers?: OutgoingHttpHeaders - ) => void - ) => void - - interface ClientOptions extends SecureContextOptions { - protocol?: string | undefined - followRedirects?: boolean | undefined - generateMask?(mask: Buffer): void - handshakeTimeout?: number | undefined - maxRedirects?: number | undefined - perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined - localAddress?: string | undefined - protocolVersion?: number | undefined - headers?: { [key: string]: string } | undefined - origin?: string | undefined - agent?: Agent | undefined - host?: string | undefined - family?: number | undefined - checkServerIdentity?(servername: string, cert: CertMeta): boolean - rejectUnauthorized?: boolean | undefined - maxPayload?: number | undefined - skipUTF8Validation?: boolean | undefined - } - - interface PerMessageDeflateOptions { - serverNoContextTakeover?: boolean | undefined - clientNoContextTakeover?: boolean | undefined - serverMaxWindowBits?: number | undefined - clientMaxWindowBits?: number | undefined - zlibDeflateOptions?: - | { - flush?: number | undefined - finishFlush?: number | undefined - chunkSize?: number | undefined - windowBits?: number | undefined - level?: number | undefined - memLevel?: number | undefined - strategy?: number | undefined - dictionary?: Buffer | Buffer[] | DataView | undefined - info?: boolean | undefined - } - | undefined - zlibInflateOptions?: ZlibOptions | undefined - threshold?: number | undefined - concurrencyLimit?: number | undefined - } - - interface Event { - type: string - target: WebSocket - } - - interface ErrorEvent { - error: any - message: string - type: string - target: WebSocket - } - - interface CloseEvent { - wasClean: boolean - code: number - reason: string - type: string - target: WebSocket - } - - interface MessageEvent { - data: Data - type: string - target: WebSocket - } - - interface EventListenerOptions { - once?: boolean | undefined - } - - interface ServerOptions { - host?: string | undefined - port?: number | undefined - backlog?: number | undefined - server?: Server | Server_2 | undefined - verifyClient?: - | VerifyClientCallbackAsync - | VerifyClientCallbackSync - | undefined - handleProtocols?: ( - protocols: Set<string>, - request: IncomingMessage - ) => string | false - path?: string | undefined - noServer?: boolean | undefined - clientTracking?: boolean | undefined - perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined - maxPayload?: number | undefined - skipUTF8Validation?: boolean | undefined - WebSocket?: typeof WebSocket.WebSocket | undefined - } - - interface AddressInfo { - address: string - family: string - port: number - } - - // WebSocket Server - class Server<T extends WebSocket = WebSocket> extends EventEmitter { - options: ServerOptions - path: string - clients: Set<T> - - constructor(options?: ServerOptions, callback?: () => void) - - address(): AddressInfo | string - close(cb?: (err?: Error) => void): void - handleUpgrade( - request: IncomingMessage, - socket: Duplex, - upgradeHead: Buffer, - callback: (client: T, request: IncomingMessage) => void - ): void - shouldHandle(request: IncomingMessage): boolean | Promise<boolean> - - // Events - on( - event: 'connection', - cb: (this: Server<T>, socket: T, request: IncomingMessage) => void - ): this - on(event: 'error', cb: (this: Server<T>, error: Error) => void): this - on( - event: 'headers', - cb: (this: Server<T>, headers: string[], request: IncomingMessage) => void - ): this - on(event: 'close' | 'listening', cb: (this: Server<T>) => void): this - on( - event: string | symbol, - listener: (this: Server<T>, ...args: any[]) => void - ): this - - once( - event: 'connection', - cb: (this: Server<T>, socket: T, request: IncomingMessage) => void - ): this - once(event: 'error', cb: (this: Server<T>, error: Error) => void): this - once( - event: 'headers', - cb: (this: Server<T>, headers: string[], request: IncomingMessage) => void - ): this - once(event: 'close' | 'listening', cb: (this: Server<T>) => void): this - once( - event: string | symbol, - listener: (this: Server<T>, ...args: any[]) => void - ): this - - off( - event: 'connection', - cb: (this: Server<T>, socket: T, request: IncomingMessage) => void - ): this - off(event: 'error', cb: (this: Server<T>, error: Error) => void): this - off( - event: 'headers', - cb: (this: Server<T>, headers: string[], request: IncomingMessage) => void - ): this - off(event: 'close' | 'listening', cb: (this: Server<T>) => void): this - off( - event: string | symbol, - listener: (this: Server<T>, ...args: any[]) => void - ): this - - addListener( - event: 'connection', - cb: (client: T, request: IncomingMessage) => void - ): this - addListener(event: 'error', cb: (err: Error) => void): this - addListener( - event: 'headers', - cb: (headers: string[], request: IncomingMessage) => void - ): this - addListener(event: 'close' | 'listening', cb: () => void): this - addListener( - event: string | symbol, - listener: (...args: any[]) => void - ): this - - removeListener(event: 'connection', cb: (client: T) => void): this - removeListener(event: 'error', cb: (err: Error) => void): this - removeListener( - event: 'headers', - cb: (headers: string[], request: IncomingMessage) => void - ): this - removeListener(event: 'close' | 'listening', cb: () => void): this - removeListener( - event: string | symbol, - listener: (...args: any[]) => void - ): this - } - - const WebSocketServer: typeof Server - interface WebSocketServer extends Server {} // tslint:disable-line no-empty-interface - const WebSocket: typeof WebSocketAlias - interface WebSocket extends WebSocketAlias {} // tslint:disable-line no-empty-interface - - // WebSocket stream - function createWebSocketStream( - websocket: WebSocket, - options?: DuplexOptions - ): Duplex -} -export { WebSocket_2 as WebSocket } - -export declare const WebSocketAlias: typeof WebSocket_2; - -export declare interface WebSocketAlias extends WebSocket_2 {} - -export declare interface WebSocketClient { - /** - * Send event to the client - */ - send(payload: HMRPayload): void; - /** - * Send custom event - */ - send(event: string, payload?: CustomPayload['data']): void; - /** - * The raw WebSocket instance - * @advanced - */ - socket: WebSocket_2; -} - -export declare type WebSocketCustomListener<T> = (data: T, client: WebSocketClient) => void; - -export declare interface WebSocketServer { - /** - * Get all connected clients. - */ - clients: Set<WebSocketClient>; - /** - * Broadcast events to all clients - */ - send(payload: HMRPayload): void; - /** - * Send custom event - */ - send<T extends string>(event: T, payload?: InferCustomEventPayload<T>): void; - /** - * Disconnect all clients and terminate the server. - */ - close(): Promise<void>; - /** - * Handle custom event emitted by `import.meta.hot.send` - */ - on: WebSocket_2.Server['on'] & { - <T extends string>(event: T, listener: WebSocketCustomListener<InferCustomEventPayload<T>>): void; - }; - /** - * Unregister event listener. - */ - off: WebSocket_2.Server['off'] & { - (event: string, listener: Function): void; - }; -} - -export { } +/// <reference types="node" /> + +import type { Agent } from 'node:http'; +import type { BuildOptions as BuildOptions_2 } from 'esbuild'; +import type { ClientRequest } from 'node:http'; +import type { ClientRequestArgs } from 'node:http'; +import type { CustomPluginOptions } from 'rollup'; +import type { Duplex } from 'node:stream'; +import type { DuplexOptions } from 'node:stream'; +import { TransformOptions as EsbuildTransformOptions } from 'esbuild'; +import { version as esbuildVersion } from 'esbuild'; +import { EventEmitter } from 'node:events'; +import * as events from 'node:events'; +import type { ExistingRawSourceMap } from 'rollup'; +import type * as fs from 'node:fs'; +import type { GetManualChunk } from 'rollup'; +import * as http from 'node:http'; +import type { IncomingMessage } from 'node:http'; +import type { InputOptions } from 'rollup'; +import type { LoadResult } from 'rollup'; +import type { ModuleFormat } from 'rollup'; +import type { ModuleInfo } from 'rollup'; +import type * as net from 'node:net'; +import type { OutgoingHttpHeaders } from 'node:http'; +import type { OutputBundle } from 'rollup'; +import type { OutputChunk } from 'rollup'; +import type { PartialResolvedId } from 'rollup'; +import type { Plugin as Plugin_3 } from 'rollup'; +import type { PluginContext } from 'rollup'; +import type { PluginHooks } from 'rollup'; +import type * as PostCSS from 'postcss'; +import type { ResolveIdResult } from 'rollup'; +import type { RollupError } from 'rollup'; +import type { RollupOptions } from 'rollup'; +import type { RollupOutput } from 'rollup'; +import { VERSION as rollupVersion } from 'rollup'; +import type { RollupWatcher } from 'rollup'; +import type { SecureContextOptions } from 'node:tls'; +import type { Server } from 'node:http'; +import type { Server as Server_2 } from 'node:https'; +import type { ServerOptions as ServerOptions_2 } from 'node:https'; +import type { ServerResponse } from 'node:http'; +import type { SourceDescription } from 'rollup'; +import type { SourceMap } from 'rollup'; +import type * as stream from 'node:stream'; +import type { TransformPluginContext } from 'rollup'; +import type { TransformResult as TransformResult_2 } from 'rollup'; +import type { TransformResult as TransformResult_3 } from 'esbuild'; +import type * as url from 'node:url'; +import type { URL as URL_2 } from 'node:url'; +import type { WatcherOptions } from 'rollup'; +import type { ZlibOptions } from 'node:zlib'; + +export declare interface Alias { + find: string | RegExp + replacement: string + /** + * Instructs the plugin to use an alternative resolving algorithm, + * rather than the Rollup's resolver. + * @default null + */ + customResolver?: ResolverFunction | ResolverObject | null +} + +/** + * Specifies an `Object`, or an `Array` of `Object`, + * which defines aliases used to replace values in `import` or `require` statements. + * With either format, the order of the entries is important, + * in that the first defined rules are applied first. + * + * This is passed to \@rollup/plugin-alias as the "entries" field + * https://github.com/rollup/plugins/tree/master/packages/alias#entries + */ +export declare type AliasOptions = readonly Alias[] | { [find: string]: string } + +export declare type AnymatchFn = (testString: string) => boolean + +export declare type AnymatchPattern = string | RegExp | AnymatchFn + +/** + * spa: include SPA fallback middleware and configure sirv with `single: true` in preview + * + * mpa: only include non-SPA HTML middlewares + * + * custom: don't include HTML middlewares + */ +export declare type AppType = 'spa' | 'mpa' | 'custom'; + +export declare interface AwaitWriteFinishOptions { + /** + * Amount of time in milliseconds for a file size to remain constant before emitting its event. + */ + stabilityThreshold?: number + + /** + * File size polling interval. + */ + pollInterval?: number +} + +/** + * Bundles the app for production. + * Returns a Promise containing the build result. + */ +export declare function build(inlineConfig?: InlineConfig): Promise<RollupOutput | RollupOutput[] | RollupWatcher>; + +export declare interface BuildOptions { + /** + * Compatibility transform target. The transform is performed with esbuild + * and the lowest supported target is es2015/es6. Note this only handles + * syntax transformation and does not cover polyfills (except for dynamic + * import) + * + * Default: 'modules' - Similar to `@babel/preset-env`'s targets.esmodules, + * transpile targeting browsers that natively support dynamic es module imports. + * https://caniuse.com/es6-module-dynamic-import + * + * Another special value is 'esnext' - which only performs minimal transpiling + * (for minification compat) and assumes native dynamic imports support. + * + * For custom targets, see https://esbuild.github.io/api/#target and + * https://esbuild.github.io/content-types/#javascript for more details. + */ + target?: 'modules' | EsbuildTransformOptions['target'] | false; + /** + * whether to inject module preload polyfill. + * Note: does not apply to library mode. + * @default true + */ + polyfillModulePreload?: boolean; + /** + * Directory relative from `root` where build output will be placed. If the + * directory exists, it will be removed before the build. + * @default 'dist' + */ + outDir?: string; + /** + * Directory relative from `outDir` where the built js/css/image assets will + * be placed. + * @default 'assets' + */ + assetsDir?: string; + /** + * Static asset files smaller than this number (in bytes) will be inlined as + * base64 strings. Default limit is `4096` (4kb). Set to `0` to disable. + * @default 4096 + */ + assetsInlineLimit?: number; + /** + * Whether to code-split CSS. When enabled, CSS in async chunks will be + * inlined as strings in the chunk and inserted via dynamically created + * style tags when the chunk is loaded. + * @default true + */ + cssCodeSplit?: boolean; + /** + * An optional separate target for CSS minification. + * As esbuild only supports configuring targets to mainstream + * browsers, users may need this option when they are targeting + * a niche browser that comes with most modern JavaScript features + * but has poor CSS support, e.g. Android WeChat WebView, which + * doesn't support the #RGBA syntax. + */ + cssTarget?: EsbuildTransformOptions['target'] | false; + /** + * If `true`, a separate sourcemap file will be created. If 'inline', the + * sourcemap will be appended to the resulting output file as data URI. + * 'hidden' works like `true` except that the corresponding sourcemap + * comments in the bundled files are suppressed. + * @default false + */ + sourcemap?: boolean | 'inline' | 'hidden'; + /** + * Set to `false` to disable minification, or specify the minifier to use. + * Available options are 'terser' or 'esbuild'. + * @default 'esbuild' + */ + minify?: boolean | 'terser' | 'esbuild'; + /** + * Options for terser + * https://terser.org/docs/api-reference#minify-options + */ + terserOptions?: Terser.MinifyOptions; + /** + * Will be merged with internal rollup options. + * https://rollupjs.org/guide/en/#big-list-of-options + */ + rollupOptions?: RollupOptions; + /** + * Options to pass on to `@rollup/plugin-commonjs` + */ + commonjsOptions?: RollupCommonJSOptions; + /** + * Options to pass on to `@rollup/plugin-dynamic-import-vars` + */ + dynamicImportVarsOptions?: RollupDynamicImportVarsOptions; + /** + * Whether to write bundle to disk + * @default true + */ + write?: boolean; + /** + * Empty outDir on write. + * @default true when outDir is a sub directory of project root + */ + emptyOutDir?: boolean | null; + /** + * Whether to emit a manifest.json under assets dir to map hash-less filenames + * to their hashed versions. Useful when you want to generate your own HTML + * instead of using the one generated by Vite. + * + * Example: + * + * ```json + * { + * "main.js": { + * "file": "main.68fe3fad.js", + * "css": "main.e6b63442.css", + * "imports": [...], + * "dynamicImports": [...] + * } + * } + * ``` + * @default false + */ + manifest?: boolean | string; + /** + * Build in library mode. The value should be the global name of the lib in + * UMD mode. This will produce esm + cjs + umd bundle formats with default + * configurations that are suitable for distributing libraries. + */ + lib?: LibraryOptions | false; + /** + * Produce SSR oriented build. Note this requires specifying SSR entry via + * `rollupOptions.input`. + */ + ssr?: boolean | string; + /** + * Generate SSR manifest for determining style links and asset preload + * directives in production. + */ + ssrManifest?: boolean | string; + /** + * Set to false to disable reporting compressed chunk sizes. + * Can slightly improve build speed. + */ + reportCompressedSize?: boolean; + /** + * Adjust chunk size warning limit (in kbs). + * @default 500 + */ + chunkSizeWarningLimit?: number; + /** + * Rollup watch options + * https://rollupjs.org/guide/en/#watchoptions + */ + watch?: WatcherOptions | null; +} + +export declare interface ChunkMetadata { + importedAssets: Set<string>; + importedCss: Set<string>; +} + +export declare interface CommonServerOptions { + /** + * Specify server port. Note if the port is already being used, Vite will + * automatically try the next available port so this may not be the actual + * port the server ends up listening on. + */ + port?: number; + /** + * If enabled, vite will exit if specified port is already in use + */ + strictPort?: boolean; + /** + * Specify which IP addresses the server should listen on. + * Set to 0.0.0.0 to listen on all addresses, including LAN and public addresses. + */ + host?: string | boolean; + /** + * Enable TLS + HTTP/2. + * Note: this downgrades to TLS only when the proxy option is also used. + */ + https?: boolean | ServerOptions_2; + /** + * Open browser window on startup + */ + open?: boolean | string; + /** + * Configure custom proxy rules for the dev server. Expects an object + * of `{ key: options }` pairs. + * Uses [`http-proxy`](https://github.com/http-party/node-http-proxy). + * Full options [here](https://github.com/http-party/node-http-proxy#options). + * + * Example `vite.config.js`: + * ``` js + * module.exports = { + * proxy: { + * // string shorthand + * '/foo': 'http://localhost:4567/foo', + * // with options + * '/api': { + * target: 'http://jsonplaceholder.typicode.com', + * changeOrigin: true, + * rewrite: path => path.replace(/^\/api/, '') + * } + * } + * } + * ``` + */ + proxy?: Record<string, string | ProxyOptions>; + /** + * Configure CORS for the dev server. + * Uses https://github.com/expressjs/cors. + * Set to `true` to allow all methods from any origin, or configure separately + * using an object. + */ + cors?: CorsOptions | boolean; + /** + * Specify server response headers. + */ + headers?: OutgoingHttpHeaders; +} + +export declare interface ConfigEnv { + command: 'build' | 'serve'; + mode: string; + /** + * @experimental + */ + ssrBuild?: boolean; +} + +export declare namespace Connect { + export type ServerHandle = HandleFunction | http.Server + + export class IncomingMessage extends http.IncomingMessage { + originalUrl?: http.IncomingMessage['url'] | undefined + } + + export type NextFunction = (err?: any) => void + + export type SimpleHandleFunction = ( + req: IncomingMessage, + res: http.ServerResponse + ) => void + export type NextHandleFunction = ( + req: IncomingMessage, + res: http.ServerResponse, + next: NextFunction + ) => void + export type ErrorHandleFunction = ( + err: any, + req: IncomingMessage, + res: http.ServerResponse, + next: NextFunction + ) => void + export type HandleFunction = + | SimpleHandleFunction + | NextHandleFunction + | ErrorHandleFunction + + export interface ServerStackItem { + route: string + handle: ServerHandle + } + + export interface Server extends NodeJS.EventEmitter { + (req: http.IncomingMessage, res: http.ServerResponse, next?: Function): void + + route: string + stack: ServerStackItem[] + + /** + * Utilize the given middleware `handle` to the given `route`, + * defaulting to _/_. This "route" is the mount-point for the + * middleware, when given a value other than _/_ the middleware + * is only effective when that segment is present in the request's + * pathname. + * + * For example if we were to mount a function at _/admin_, it would + * be invoked on _/admin_, and _/admin/settings_, however it would + * not be invoked for _/_, or _/posts_. + */ + use(fn: NextHandleFunction): Server + use(fn: HandleFunction): Server + use(route: string, fn: NextHandleFunction): Server + use(route: string, fn: HandleFunction): Server + + /** + * Handle server requests, punting them down + * the middleware stack. + */ + handle( + req: http.IncomingMessage, + res: http.ServerResponse, + next: Function + ): void + + /** + * Listen for connections. + * + * This method takes the same arguments + * as node's `http.Server#listen()`. + * + * HTTP and HTTPS: + * + * If you run your application both as HTTP + * and HTTPS you may wrap them individually, + * since your Connect "server" is really just + * a JavaScript `Function`. + * + * var connect = require('connect') + * , http = require('http') + * , https = require('https'); + * + * var app = connect(); + * + * http.createServer(app).listen(80); + * https.createServer(options, app).listen(443); + */ + listen( + port: number, + hostname?: string, + backlog?: number, + callback?: Function + ): http.Server + listen(port: number, hostname?: string, callback?: Function): http.Server + listen(path: string, callback?: Function): http.Server + listen(handle: any, listeningListener?: Function): http.Server + } +} + +export declare interface ConnectedPayload { + type: 'connected' +} + +/** + * https://github.com/expressjs/cors#configuration-options + */ +export declare interface CorsOptions { + origin?: CorsOrigin | ((origin: string, cb: (err: Error, origins: CorsOrigin) => void) => void); + methods?: string | string[]; + allowedHeaders?: string | string[]; + exposedHeaders?: string | string[]; + credentials?: boolean; + maxAge?: number; + preflightContinue?: boolean; + optionsSuccessStatus?: number; +} + +export declare type CorsOrigin = boolean | string | RegExp | (string | RegExp)[]; + +export declare const createFilter: (include?: FilterPattern | undefined, exclude?: FilterPattern | undefined, options?: { + resolve?: string | false | null | undefined; +} | undefined) => (id: string | unknown) => boolean; + +export declare function createLogger(level?: LogLevel, options?: LoggerOptions): Logger; + +export declare function createServer(inlineConfig?: InlineConfig): Promise<ViteDevServer>; + +export declare interface CSSModulesOptions { + getJSON?: (cssFileName: string, json: Record<string, string>, outputFileName: string) => void; + scopeBehaviour?: 'global' | 'local'; + globalModulePaths?: RegExp[]; + generateScopedName?: string | ((name: string, filename: string, css: string) => string); + hashPrefix?: string; + /** + * default: null + */ + localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly' | null; +} + +export declare interface CSSOptions { + /** + * https://github.com/css-modules/postcss-modules + */ + modules?: CSSModulesOptions | false; + preprocessorOptions?: Record<string, any>; + postcss?: string | (PostCSS.ProcessOptions & { + plugins?: PostCSS.AcceptedPlugin[]; + }); + /** + * Enables css sourcemaps during dev + * @default false + * @experimental + */ + devSourcemap?: boolean; +} + +export declare interface CustomEventMap { + 'vite:beforeUpdate': UpdatePayload + 'vite:beforePrune': PrunePayload + 'vite:beforeFullReload': FullReloadPayload + 'vite:error': ErrorPayload +} + +export declare interface CustomPayload { + type: 'custom' + event: string + data?: any +} + +/** + * Type helper to make it easier to use vite.config.ts + * accepts a direct {@link UserConfig} object, or a function that returns it. + * The function receives a {@link ConfigEnv} object that exposes two properties: + * `command` (either `'build'` or `'serve'`), and `mode`. + */ +export declare function defineConfig(config: UserConfigExport): UserConfigExport; + +export declare interface DepOptimizationConfig { + /** + * Force optimize listed dependencies (must be resolvable import paths, + * cannot be globs). + */ + include?: string[]; + /** + * Do not optimize these dependencies (must be resolvable import paths, + * cannot be globs). + */ + exclude?: string[]; + /** + * Force ESM interop when importing for these dependencies. Some legacy + * packages advertise themselves as ESM but use `require` internally + * @experimental + */ + needsInterop?: string[]; + /** + * Options to pass to esbuild during the dep scanning and optimization + * + * Certain options are omitted since changing them would not be compatible + * with Vite's dep optimization. + * + * - `external` is also omitted, use Vite's `optimizeDeps.exclude` option + * - `plugins` are merged with Vite's dep plugin + * + * https://esbuild.github.io/api + */ + esbuildOptions?: Omit<BuildOptions_2, 'bundle' | 'entryPoints' | 'external' | 'write' | 'watch' | 'outdir' | 'outfile' | 'outbase' | 'outExtension' | 'metafile'>; + /** + * List of file extensions that can be optimized. A corresponding esbuild + * plugin must exist to handle the specific extension. + * + * By default, Vite can optimize `.mjs`, `.js`, `.ts`, and `.mts` files. This option + * allows specifying additional extensions. + * + * @experimental + */ + extensions?: string[]; + /** + * Disables dependencies optimizations, true disables the optimizer during + * build and dev. Pass 'build' or 'dev' to only disable the optimizer in + * one of the modes. Deps optimization is enabled by default in dev only. + * @default 'build' + * @experimental + */ + disabled?: boolean | 'build' | 'dev'; +} + +export declare interface DepOptimizationMetadata { + /** + * The main hash is determined by user config and dependency lockfiles. + * This is checked on server startup to avoid unnecessary re-bundles. + */ + hash: string; + /** + * The browser hash is determined by the main hash plus additional dependencies + * discovered at runtime. This is used to invalidate browser requests to + * optimized deps. + */ + browserHash: string; + /** + * Metadata for each already optimized dependency + */ + optimized: Record<string, OptimizedDepInfo>; + /** + * Metadata for non-entry optimized chunks and dynamic imports + */ + chunks: Record<string, OptimizedDepInfo>; + /** + * Metadata for each newly discovered dependency after processing + */ + discovered: Record<string, OptimizedDepInfo>; + /** + * OptimizedDepInfo list + */ + depInfoList: OptimizedDepInfo[]; +} + +export declare type DepOptimizationOptions = DepOptimizationConfig & { + /** + * By default, Vite will crawl your `index.html` to detect dependencies that + * need to be pre-bundled. If `build.rollupOptions.input` is specified, Vite + * will crawl those entry points instead. + * + * If neither of these fit your needs, you can specify custom entries using + * this option - the value should be a fast-glob pattern or array of patterns + * (https://github.com/mrmlnc/fast-glob#basic-syntax) that are relative from + * vite project root. This will overwrite default entries inference. + */ + entries?: string | string[]; + /** + * Force dep pre-optimization regardless of whether deps have changed. + * @experimental + */ + force?: boolean; +}; + +export declare interface DepOptimizationProcessing { + promise: Promise<void>; + resolve: () => void; +} + +export declare interface DepOptimizationResult { + metadata: DepOptimizationMetadata; + /** + * When doing a re-run, if there are newly discovered dependencies + * the page reload will be delayed until the next rerun so we need + * to be able to discard the result + */ + commit: () => Promise<void>; + cancel: () => void; +} + +export declare interface DepsOptimizer { + metadata: DepOptimizationMetadata; + scanProcessing?: Promise<void>; + registerMissingImport: (id: string, resolved: string) => OptimizedDepInfo; + run: () => void; + isOptimizedDepFile: (id: string) => boolean; + isOptimizedDepUrl: (url: string) => boolean; + getOptimizedDepId: (depInfo: OptimizedDepInfo) => string; + delayDepsOptimizerUntil: (id: string, done: () => Promise<any>) => void; + registerWorkersSource: (id: string) => void; + resetRegisteredIds: () => void; + ensureFirstRun: () => void; + options: DepOptimizationOptions; +} + +export declare interface ErrorPayload { + type: 'error' + err: { + [name: string]: any + message: string + stack: string + id?: string + frame?: string + plugin?: string + pluginCode?: string + loc?: { + file?: string + line: number + column: number + } + } +} + +export declare interface ESBuildOptions extends EsbuildTransformOptions { + include?: string | RegExp | string[] | RegExp[]; + exclude?: string | RegExp | string[] | RegExp[]; + jsxInject?: string; + /** + * This option is not respected. Use `build.minify` instead. + */ + minify?: never; +} + +export { EsbuildTransformOptions } + +export declare type ESBuildTransformResult = Omit<TransformResult_3, 'map'> & { + map: SourceMap; +}; + +export { esbuildVersion } + +export declare interface ExperimentalOptions { + /** + * Append fake `&lang.(ext)` when queries are specified, to preserve the file extension for following plugins to process. + * + * @experimental + * @default false + */ + importGlobRestoreExtension?: boolean; + /** + * Allow finegrain control over assets and public files paths + * + * @experimental + */ + renderBuiltUrl?: RenderBuiltAssetUrl; + /** + * Enables support of HMR partial accept via `import.meta.hot.acceptExports`. + * + * @experimental + * @default false + */ + hmrPartialAccept?: boolean; +} + +export declare type ExportsData = { + hasImports: boolean; + exports: readonly string[]; + facade: boolean; + hasReExports?: boolean; + jsxLoader?: boolean; +}; + +export declare interface FileSystemServeOptions { + /** + * Strictly restrict file accessing outside of allowing paths. + * + * Set to `false` to disable the warning + * + * @default true + */ + strict?: boolean; + /** + * Restrict accessing files outside the allowed directories. + * + * Accepts absolute path or a path relative to project root. + * Will try to search up for workspace root by default. + */ + allow?: string[]; + /** + * Restrict accessing files that matches the patterns. + * + * This will have higher priority than `allow`. + * Glob patterns are supported. + * + * @default ['.env', '.env.*', '*.crt', '*.pem'] + */ + deny?: string[]; +} + +/** + * Inlined to keep `@rollup/pluginutils` in devDependencies + */ +export declare type FilterPattern = ReadonlyArray<string | RegExp> | string | RegExp | null; + +export declare function formatPostcssSourceMap(rawMap: ExistingRawSourceMap, file: string): Promise<ExistingRawSourceMap>; + +export declare class FSWatcher extends EventEmitter implements fs.FSWatcher { + options: WatchOptions + + /** + * Constructs a new FSWatcher instance with optional WatchOptions parameter. + */ + constructor(options?: WatchOptions) + + /** + * Add files, directories, or glob patterns for tracking. Takes an array of strings or just one + * string. + */ + add(paths: string | ReadonlyArray<string>): this + + /** + * Stop watching files, directories, or glob patterns. Takes an array of strings or just one + * string. + */ + unwatch(paths: string | ReadonlyArray<string>): this + + /** + * Returns an object representing all the paths on the file system being watched by this + * `FSWatcher` instance. The object's keys are all the directories (using absolute paths unless + * the `cwd` option was used), and the values are arrays of the names of the items contained in + * each directory. + */ + getWatched(): { + [directory: string]: string[] + } + + /** + * Removes all listeners from watched files. + */ + close(): Promise<void> + + on( + event: 'add' | 'addDir' | 'change', + listener: (path: string, stats?: fs.Stats) => void + ): this + + on( + event: 'all', + listener: ( + eventName: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir', + path: string, + stats?: fs.Stats + ) => void + ): this + + /** + * Error occurred + */ + on(event: 'error', listener: (error: Error) => void): this + + /** + * Exposes the native Node `fs.FSWatcher events` + */ + on( + event: 'raw', + listener: (eventName: string, path: string, details: any) => void + ): this + + /** + * Fires when the initial scan is complete + */ + on(event: 'ready', listener: () => void): this + + on(event: 'unlink' | 'unlinkDir', listener: (path: string) => void): this + + on(event: string, listener: (...args: any[]) => void): this +} + +export declare interface FullReloadPayload { + type: 'full-reload' + path?: string +} + +export declare function getDepOptimizationConfig(config: ResolvedConfig, ssr: boolean): DepOptimizationConfig; + +export declare interface HmrContext { + file: string; + timestamp: number; + modules: Array<ModuleNode>; + read: () => string | Promise<string>; + server: ViteDevServer; +} + +export declare interface HmrOptions { + protocol?: string; + host?: string; + port?: number; + clientPort?: number; + path?: string; + timeout?: number; + overlay?: boolean; + server?: Server; +} + +export declare type HMRPayload = +| ConnectedPayload +| UpdatePayload +| FullReloadPayload +| CustomPayload +| ErrorPayload +| PrunePayload + +export declare interface HtmlTagDescriptor { + tag: string; + attrs?: Record<string, string | boolean | undefined>; + children?: string | HtmlTagDescriptor[]; + /** + * default: 'head-prepend' + */ + injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'; +} + +export declare namespace HttpProxy { + export type ProxyTarget = ProxyTargetUrl | ProxyTargetDetailed + + export type ProxyTargetUrl = string | Partial<url.Url> + + export interface ProxyTargetDetailed { + host: string + port: number + protocol?: string | undefined + hostname?: string | undefined + socketPath?: string | undefined + key?: string | undefined + passphrase?: string | undefined + pfx?: Buffer | string | undefined + cert?: string | undefined + ca?: string | undefined + ciphers?: string | undefined + secureProtocol?: string | undefined + } + + export type ErrorCallback = ( + err: Error, + req: http.IncomingMessage, + res: http.ServerResponse, + target?: ProxyTargetUrl + ) => void + + export class Server extends events.EventEmitter { + /** + * Creates the proxy server with specified options. + * @param options - Config object passed to the proxy + */ + constructor(options?: ServerOptions) + + /** + * Used for proxying regular HTTP(S) requests + * @param req - Client request. + * @param res - Client response. + * @param options - Additional options. + */ + web( + req: http.IncomingMessage, + res: http.ServerResponse, + options?: ServerOptions, + callback?: ErrorCallback + ): void + + /** + * Used for proxying regular HTTP(S) requests + * @param req - Client request. + * @param socket - Client socket. + * @param head - Client head. + * @param options - Additional options. + */ + ws( + req: http.IncomingMessage, + socket: unknown, + head: unknown, + options?: ServerOptions, + callback?: ErrorCallback + ): void + + /** + * A function that wraps the object in a webserver, for your convenience + * @param port - Port to listen on + */ + listen(port: number): Server + + /** + * A function that closes the inner webserver and stops listening on given port + */ + close(callback?: () => void): void + + /** + * Creates the proxy server with specified options. + * @param options - Config object passed to the proxy + * @returns Proxy object with handlers for `ws` and `web` requests + */ + static createProxyServer(options?: ServerOptions): Server + + /** + * Creates the proxy server with specified options. + * @param options - Config object passed to the proxy + * @returns Proxy object with handlers for `ws` and `web` requests + */ + static createServer(options?: ServerOptions): Server + + /** + * Creates the proxy server with specified options. + * @param options - Config object passed to the proxy + * @returns Proxy object with handlers for `ws` and `web` requests + */ + static createProxy(options?: ServerOptions): Server + + addListener(event: string, listener: () => void): this + on(event: string, listener: () => void): this + on(event: 'error', listener: ErrorCallback): this + on( + event: 'start', + listener: ( + req: http.IncomingMessage, + res: http.ServerResponse, + target: ProxyTargetUrl + ) => void + ): this + on( + event: 'proxyReq', + listener: ( + proxyReq: http.ClientRequest, + req: http.IncomingMessage, + res: http.ServerResponse, + options: ServerOptions + ) => void + ): this + on( + event: 'proxyRes', + listener: ( + proxyRes: http.IncomingMessage, + req: http.IncomingMessage, + res: http.ServerResponse + ) => void + ): this + on( + event: 'proxyReqWs', + listener: ( + proxyReq: http.ClientRequest, + req: http.IncomingMessage, + socket: net.Socket, + options: ServerOptions, + head: any + ) => void + ): this + on( + event: 'econnreset', + listener: ( + err: Error, + req: http.IncomingMessage, + res: http.ServerResponse, + target: ProxyTargetUrl + ) => void + ): this + on( + event: 'end', + listener: ( + req: http.IncomingMessage, + res: http.ServerResponse, + proxyRes: http.IncomingMessage + ) => void + ): this + on( + event: 'close', + listener: ( + proxyRes: http.IncomingMessage, + proxySocket: net.Socket, + proxyHead: any + ) => void + ): this + + once(event: string, listener: () => void): this + removeListener(event: string, listener: () => void): this + removeAllListeners(event?: string): this + getMaxListeners(): number + setMaxListeners(n: number): this + listeners(event: string): Array<() => void> + emit(event: string, ...args: any[]): boolean + listenerCount(type: string): number + } + + export interface ServerOptions { + /** URL string to be parsed with the url module. */ + target?: ProxyTarget | undefined + /** URL string to be parsed with the url module. */ + forward?: ProxyTargetUrl | undefined + /** Object to be passed to http(s).request. */ + agent?: any + /** Object to be passed to https.createServer(). */ + ssl?: any + /** If you want to proxy websockets. */ + ws?: boolean | undefined + /** Adds x- forward headers. */ + xfwd?: boolean | undefined + /** Verify SSL certificate. */ + secure?: boolean | undefined + /** Explicitly specify if we are proxying to another proxy. */ + toProxy?: boolean | undefined + /** Specify whether you want to prepend the target's path to the proxy path. */ + prependPath?: boolean | undefined + /** Specify whether you want to ignore the proxy path of the incoming request. */ + ignorePath?: boolean | undefined + /** Local interface string to bind for outgoing connections. */ + localAddress?: string | undefined + /** Changes the origin of the host header to the target URL. */ + changeOrigin?: boolean | undefined + /** specify whether you want to keep letter case of response header key */ + preserveHeaderKeyCase?: boolean | undefined + /** Basic authentication i.e. 'user:password' to compute an Authorization header. */ + auth?: string | undefined + /** Rewrites the location hostname on (301 / 302 / 307 / 308) redirects, Default: null. */ + hostRewrite?: string | undefined + /** Rewrites the location host/ port on (301 / 302 / 307 / 308) redirects based on requested host/ port.Default: false. */ + autoRewrite?: boolean | undefined + /** Rewrites the location protocol on (301 / 302 / 307 / 308) redirects to 'http' or 'https'.Default: null. */ + protocolRewrite?: string | undefined + /** rewrites domain of set-cookie headers. */ + cookieDomainRewrite?: + | false + | string + | { [oldDomain: string]: string } + | undefined + /** rewrites path of set-cookie headers. Default: false */ + cookiePathRewrite?: + | false + | string + | { [oldPath: string]: string } + | undefined + /** object with extra headers to be added to target requests. */ + headers?: { [header: string]: string } | undefined + /** Timeout (in milliseconds) when proxy receives no response from target. Default: 120000 (2 minutes) */ + proxyTimeout?: number | undefined + /** Timeout (in milliseconds) for incoming requests */ + timeout?: number | undefined + /** Specify whether you want to follow redirects. Default: false */ + followRedirects?: boolean | undefined + /** If set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the proxyRes event */ + selfHandleResponse?: boolean | undefined + /** Buffer */ + buffer?: stream.Stream | undefined + } +} + +export declare interface ImportGlobEagerFunction { + /** + * Eagerly import a list of files with a glob pattern. + * + * Overload 1: No generic provided, infer the type from `as` + */ + < + As extends string, + T = As extends keyof KnownAsTypeMap ? KnownAsTypeMap[As] : unknown + >( + glob: string | string[], + options?: Omit<ImportGlobOptions<boolean, As>, 'eager'> + ): Record<string, T> + /** + * Eagerly import a list of files with a glob pattern. + * + * Overload 2: Module generic provided + */ + <M>( + glob: string | string[], + options?: Omit<ImportGlobOptions<boolean, string>, 'eager'> + ): Record<string, M> +} + +export declare interface ImportGlobFunction { + /** + * Import a list of files with a glob pattern. + * + * Overload 1: No generic provided, infer the type from `eager` and `as` + */ + < + Eager extends boolean, + As extends string, + T = As extends keyof KnownAsTypeMap ? KnownAsTypeMap[As] : unknown + >( + glob: string | string[], + options?: ImportGlobOptions<Eager, As> + ): (Eager extends true ? true : false) extends true + ? Record<string, T> + : Record<string, () => Promise<T>> + /** + * Import a list of files with a glob pattern. + * + * Overload 2: Module generic provided, infer the type from `eager: false` + */ + <M>( + glob: string | string[], + options?: ImportGlobOptions<false, string> + ): Record<string, () => Promise<M>> + /** + * Import a list of files with a glob pattern. + * + * Overload 3: Module generic provided, infer the type from `eager: true` + */ + <M>( + glob: string | string[], + options: ImportGlobOptions<true, string> + ): Record<string, M> +} + +export declare interface ImportGlobOptions< +Eager extends boolean, +AsType extends string +> { + /** + * Import type for the import url. + */ + as?: AsType + /** + * Import as static or dynamic + * + * @default false + */ + eager?: Eager + /** + * Import only the specific named export. Set to `default` to import the default export. + */ + import?: string + /** + * Custom queries + */ + query?: string | Record<string, string | number | boolean> + /** + * Search files also inside `node_modules/` and hidden directories (e.g. `.git/`). This might have impact on performance. + * + * @default false + */ + exhaustive?: boolean +} + +export declare type IndexHtmlTransform = IndexHtmlTransformHook | { + enforce?: 'pre' | 'post'; + transform: IndexHtmlTransformHook; +}; + +export declare interface IndexHtmlTransformContext { + /** + * public path when served + */ + path: string; + /** + * filename on disk + */ + filename: string; + server?: ViteDevServer; + bundle?: OutputBundle; + chunk?: OutputChunk; + originalUrl?: string; +} + +export declare type IndexHtmlTransformHook = (html: string, ctx: IndexHtmlTransformContext) => IndexHtmlTransformResult | void | Promise<IndexHtmlTransformResult | void>; + +export declare type IndexHtmlTransformResult = string | HtmlTagDescriptor[] | { + html: string; + tags: HtmlTagDescriptor[]; +}; + +export declare type InferCustomEventPayload<T extends string> = +T extends keyof CustomEventMap ? CustomEventMap[T] : any + +export declare interface InlineConfig extends UserConfig { + configFile?: string | false; + envFile?: false; +} + +export declare interface InternalResolveOptions extends ResolveOptions { + root: string; + isBuild: boolean; + isProduction: boolean; + ssrConfig?: SSROptions; + packageCache?: PackageCache; + /** + * src code mode also attempts the following: + * - resolving /xxx as URLs + * - resolving bare imports from optimized deps + */ + asSrc?: boolean; + tryIndex?: boolean; + tryPrefix?: string; + skipPackageJson?: boolean; + preferRelative?: boolean; + preserveSymlinks?: boolean; + isRequire?: boolean; + isFromTsImporter?: boolean; + tryEsmOnly?: boolean; + scan?: boolean; + ssrOptimizeCheck?: boolean; + getDepsOptimizer?: (ssr: boolean) => DepsOptimizer | undefined; + shouldExternalize?: (id: string) => boolean | undefined; +} + +export declare function isDepsOptimizerEnabled(config: ResolvedConfig, ssr: boolean): boolean; + +export declare interface JsonOptions { + /** + * Generate a named export for every property of the JSON object + * @default true + */ + namedExports?: boolean; + /** + * Generate performant output as JSON.parse("stringified"). + * Enabling this will disable namedExports. + * @default false + */ + stringify?: boolean; +} + +export declare interface KnownAsTypeMap { + raw: string + url: string + worker: Worker +} + +export declare interface LegacyOptions { + /** + * Revert vite build --ssr to the v2.9 strategy. Use CJS SSR build and v2.9 externalization heuristics + * + * @experimental + * @deprecated + * @default false + */ + buildSsrCjsExternalHeuristics?: boolean; +} + +export declare type LibraryFormats = 'es' | 'cjs' | 'umd' | 'iife'; + +export declare interface LibraryOptions { + /** + * Path of library entry + */ + entry: string; + /** + * The name of the exposed global variable. Required when the `formats` option includes + * `umd` or `iife` + */ + name?: string; + /** + * Output bundle formats + * @default ['es', 'umd'] + */ + formats?: LibraryFormats[]; + /** + * The name of the package file output. The default file name is the name option + * of the project package.json. It can also be defined as a function taking the + * format as an argument. + */ + fileName?: string | ((format: ModuleFormat) => string); +} + +export declare function loadConfigFromFile(configEnv: ConfigEnv, configFile?: string, configRoot?: string, logLevel?: LogLevel): Promise<{ + path: string; + config: UserConfig; + dependencies: string[]; +} | null>; + +export declare function loadEnv(mode: string, envDir: string, prefixes?: string | string[]): Record<string, string>; + +export declare interface LogErrorOptions extends LogOptions { + error?: Error | RollupError | null; +} + +export declare interface Logger { + info(msg: string, options?: LogOptions): void; + warn(msg: string, options?: LogOptions): void; + warnOnce(msg: string, options?: LogOptions): void; + error(msg: string, options?: LogErrorOptions): void; + clearScreen(type: LogType): void; + hasErrorLogged(error: Error | RollupError): boolean; + hasWarned: boolean; +} + +export declare interface LoggerOptions { + prefix?: string; + allowClearScreen?: boolean; + customLogger?: Logger; +} + +export declare type LogLevel = LogType | 'silent'; + +export declare interface LogOptions { + clear?: boolean; + timestamp?: boolean; +} + +export declare type LogType = 'error' | 'warn' | 'info'; + +export declare type Manifest = Record<string, ManifestChunk>; + +export declare interface ManifestChunk { + src?: string; + file: string; + css?: string[]; + assets?: string[]; + isEntry?: boolean; + isDynamicEntry?: boolean; + imports?: string[]; + dynamicImports?: string[]; +} + +export declare type Matcher = AnymatchPattern | AnymatchPattern[] + +export declare function mergeAlias(a?: AliasOptions, b?: AliasOptions): AliasOptions | undefined; + +export declare function mergeConfig(defaults: Record<string, any>, overrides: Record<string, any>, isRoot?: boolean): Record<string, any>; + +export declare class ModuleGraph { + private resolveId; + urlToModuleMap: Map<string, ModuleNode>; + idToModuleMap: Map<string, ModuleNode>; + fileToModulesMap: Map<string, Set<ModuleNode>>; + safeModulesPath: Set<string>; + constructor(resolveId: (url: string, ssr: boolean) => Promise<PartialResolvedId | null>); + getModuleByUrl(rawUrl: string, ssr?: boolean): Promise<ModuleNode | undefined>; + getModuleById(id: string): ModuleNode | undefined; + getModulesByFile(file: string): Set<ModuleNode> | undefined; + onFileChange(file: string): void; + invalidateModule(mod: ModuleNode, seen?: Set<ModuleNode>, timestamp?: number): void; + invalidateAll(): void; + /** + * Update the module graph based on a module's updated imports information + * If there are dependencies that no longer have any importers, they are + * returned as a Set. + */ + updateModuleInfo(mod: ModuleNode, importedModules: Set<string | ModuleNode>, importedBindings: Map<string, Set<string>> | null, acceptedModules: Set<string | ModuleNode>, acceptedExports: Set<string> | null, isSelfAccepting: boolean, ssr?: boolean): Promise<Set<ModuleNode> | undefined>; + ensureEntryFromUrl(rawUrl: string, ssr?: boolean, setIsSelfAccepting?: boolean): Promise<ModuleNode>; + createFileOnlyEntry(file: string): ModuleNode; + resolveUrl(url: string, ssr?: boolean): Promise<ResolvedUrl>; +} + +export declare class ModuleNode { + /** + * Public served url path, starts with / + */ + url: string; + /** + * Resolved file system path + query + */ + id: string | null; + file: string | null; + type: 'js' | 'css'; + info?: ModuleInfo; + meta?: Record<string, any>; + importers: Set<ModuleNode>; + importedModules: Set<ModuleNode>; + acceptedHmrDeps: Set<ModuleNode>; + acceptedHmrExports: Set<string> | null; + importedBindings: Map<string, Set<string>> | null; + isSelfAccepting?: boolean; + transformResult: TransformResult | null; + ssrTransformResult: TransformResult | null; + ssrModule: Record<string, any> | null; + ssrError: Error | null; + lastHMRTimestamp: number; + lastInvalidationTimestamp: number; + /** + * @param setIsSelfAccepting - set `false` to set `isSelfAccepting` later. e.g. #7870 + */ + constructor(url: string, setIsSelfAccepting?: boolean); +} + +export declare function normalizePath(id: string): string; + +export declare interface OptimizedDepInfo { + id: string; + file: string; + src?: string; + needsInterop?: boolean; + browserHash?: string; + fileHash?: string; + /** + * During optimization, ids can still be resolved to their final location + * but the bundles may not yet be saved to disk + */ + processing?: Promise<void>; + /** + * ExportData cache, discovered deps will parse the src entry to get exports + * data used both to define if interop is needed and when pre-bundling + */ + exportsData?: Promise<ExportsData>; +} + +/** + * Scan and optimize dependencies within a project. + * Used by Vite CLI when running `vite optimize`. + */ +export declare function optimizeDeps(config: ResolvedConfig, force?: boolean | undefined, asCommand?: boolean): Promise<DepOptimizationMetadata>; + +/** Cache for package.json resolution and package.json contents */ +export declare type PackageCache = Map<string, PackageData>; + +export declare interface PackageData { + dir: string; + hasSideEffects: (id: string) => boolean | 'no-treeshake'; + webResolvedImports: Record<string, string | undefined>; + nodeResolvedImports: Record<string, string | undefined>; + setResolvedCache: (key: string, entry: string, targetWeb: boolean) => void; + getResolvedCache: (key: string, targetWeb: boolean) => string | undefined; + data: { + [field: string]: any; + name: string; + type: string; + version: string; + main: string; + module: string; + browser: string | Record<string, string | false>; + exports: string | Record<string, any> | string[]; + dependencies: Record<string, string>; + }; +} + +/** + * Vite plugins extends the Rollup plugin interface with a few extra + * vite-specific options. A valid vite plugin is also a valid Rollup plugin. + * On the contrary, a Rollup plugin may or may NOT be a valid vite universal + * plugin, since some Rollup features do not make sense in an unbundled + * dev server context. That said, as long as a rollup plugin doesn't have strong + * coupling between its bundle phase and output phase hooks then it should + * just work (that means, most of them). + * + * By default, the plugins are run during both serve and build. When a plugin + * is applied during serve, it will only run **non output plugin hooks** (see + * rollup type definition of {@link rollup#PluginHooks}). You can think of the + * dev server as only running `const bundle = rollup.rollup()` but never calling + * `bundle.generate()`. + * + * A plugin that expects to have different behavior depending on serve/build can + * export a factory function that receives the command being run via options. + * + * If a plugin should be applied only for server or build, a function format + * config file can be used to conditional determine the plugins to use. + */ +declare interface Plugin_2 extends Plugin_3 { + /** + * Enforce plugin invocation tier similar to webpack loaders. + * + * Plugin invocation order: + * - alias resolution + * - `enforce: 'pre'` plugins + * - vite core plugins + * - normal plugins + * - vite build plugins + * - `enforce: 'post'` plugins + * - vite build post plugins + */ + enforce?: 'pre' | 'post'; + /** + * Apply the plugin only for serve or build, or on certain conditions. + */ + apply?: 'serve' | 'build' | ((config: UserConfig, env: ConfigEnv) => boolean); + /** + * Modify vite config before it's resolved. The hook can either mutate the + * passed-in config directly, or return a partial config object that will be + * deeply merged into existing config. + * + * Note: User plugins are resolved before running this hook so injecting other + * plugins inside the `config` hook will have no effect. + */ + config?: (config: UserConfig, env: ConfigEnv) => UserConfig | null | void | Promise<UserConfig | null | void>; + /** + * Use this hook to read and store the final resolved vite config. + */ + configResolved?: (config: ResolvedConfig) => void | Promise<void>; + /** + * Configure the vite server. The hook receives the {@link ViteDevServer} + * instance. This can also be used to store a reference to the server + * for use in other hooks. + * + * The hooks will be called before internal middlewares are applied. A hook + * can return a post hook that will be called after internal middlewares + * are applied. Hook can be async functions and will be called in series. + */ + configureServer?: ServerHook; + /** + * Configure the preview server. The hook receives the connect server and + * its underlying http server. + * + * The hooks are called before other middlewares are applied. A hook can + * return a post hook that will be called after other middlewares are + * applied. Hooks can be async functions and will be called in series. + */ + configurePreviewServer?: PreviewServerHook; + /** + * Transform index.html. + * The hook receives the following arguments: + * + * - html: string + * - ctx?: vite.ServerContext (only present during serve) + * - bundle?: rollup.OutputBundle (only present during build) + * + * It can either return a transformed string, or a list of html tag + * descriptors that will be injected into the <head> or <body>. + * + * By default the transform is applied **after** vite's internal html + * transform. If you need to apply the transform before vite, use an object: + * `{ enforce: 'pre', transform: hook }` + */ + transformIndexHtml?: IndexHtmlTransform; + /** + * Perform custom handling of HMR updates. + * The handler receives a context containing changed filename, timestamp, a + * list of modules affected by the file change, and the dev server instance. + * + * - The hook can return a filtered list of modules to narrow down the update. + * e.g. for a Vue SFC, we can narrow down the part to update by comparing + * the descriptors. + * + * - The hook can also return an empty array and then perform custom updates + * by sending a custom hmr payload via server.ws.send(). + * + * - If the hook doesn't return a value, the hmr update will be performed as + * normal. + */ + handleHotUpdate?(ctx: HmrContext): Array<ModuleNode> | void | Promise<Array<ModuleNode> | void>; + /** + * extend hooks with ssr flag + */ + resolveId?: (this: PluginContext, source: string, importer: string | undefined, options: { + custom?: CustomPluginOptions; + ssr?: boolean; + /* Excluded from this release type: scan */ + isEntry: boolean; + }) => Promise<ResolveIdResult> | ResolveIdResult; + load?: (this: PluginContext, id: string, options?: { + ssr?: boolean; + }) => Promise<LoadResult> | LoadResult; + transform?: (this: TransformPluginContext, code: string, id: string, options?: { + ssr?: boolean; + }) => Promise<TransformResult_2> | TransformResult_2; +} +export { Plugin_2 as Plugin } + +export declare interface PluginContainer { + options: InputOptions; + getModuleInfo(id: string): ModuleInfo | null; + buildStart(options: InputOptions): Promise<void>; + resolveId(id: string, importer?: string, options?: { + custom?: CustomPluginOptions; + skip?: Set<Plugin_2>; + ssr?: boolean; + /* Excluded from this release type: scan */ + isEntry?: boolean; + }): Promise<PartialResolvedId | null>; + transform(code: string, id: string, options?: { + inMap?: SourceDescription['map']; + ssr?: boolean; + }): Promise<SourceDescription | null>; + load(id: string, options?: { + ssr?: boolean; + }): Promise<LoadResult | null>; + close(): Promise<void>; +} + +export declare type PluginOption = Plugin_2 | false | null | undefined | PluginOption[] | Promise<Plugin_2 | false | null | undefined | PluginOption[]>; + +/** + * Starts the Vite server in preview mode, to simulate a production deployment + */ +export declare function preview(inlineConfig?: InlineConfig): Promise<PreviewServer>; + +export declare interface PreviewOptions extends CommonServerOptions { +} + +export declare interface PreviewServer { + /** + * The resolved vite config object + */ + config: ResolvedConfig; + /** + * native Node http server instance + */ + httpServer: http.Server; + /** + * The resolved urls Vite prints on the CLI + * + * @experimental + */ + resolvedUrls: ResolvedServerUrls; + /** + * Print server urls + */ + printUrls(): void; +} + +export declare type PreviewServerHook = (server: { + middlewares: Connect.Server; + httpServer: http.Server; +}) => (() => void) | void | Promise<(() => void) | void>; + +export declare interface ProxyOptions extends HttpProxy.ServerOptions { + /** + * rewrite path + */ + rewrite?: (path: string) => string; + /** + * configure the proxy server (e.g. listen to events) + */ + configure?: (proxy: HttpProxy.Server, options: ProxyOptions) => void; + /** + * webpack-dev-server style bypass function + */ + bypass?: (req: http.IncomingMessage, res: http.ServerResponse, options: ProxyOptions) => void | null | undefined | false | string; +} + +export declare interface PrunePayload { + type: 'prune' + paths: string[] +} + +export declare type RenderBuiltAssetUrl = (filename: string, type: { + type: 'asset' | 'public'; + hostId: string; + hostType: 'js' | 'css' | 'html'; + ssr: boolean; +}) => string | { + relative?: boolean; + runtime?: string; +} | undefined; + +/** + * Resolve base url. Note that some users use Vite to build for non-web targets like + * electron or expects to deploy + */ +export declare function resolveBaseUrl(base: string | undefined, isBuild: boolean, logger: Logger): string; + +export declare function resolveConfig(inlineConfig: InlineConfig, command: 'build' | 'serve', defaultMode?: string): Promise<ResolvedConfig>; + +export declare type ResolvedBuildOptions = Required<BuildOptions>; + +export declare type ResolvedConfig = Readonly<Omit<UserConfig, 'plugins' | 'assetsInclude' | 'optimizeDeps' | 'worker'> & { + configFile: string | undefined; + configFileDependencies: string[]; + inlineConfig: InlineConfig; + root: string; + base: string; + publicDir: string; + cacheDir: string; + command: 'build' | 'serve'; + mode: string; + isWorker: boolean; + /* Excluded from this release type: mainConfig */ + isProduction: boolean; + env: Record<string, any>; + resolve: ResolveOptions & { + alias: Alias[]; + }; + plugins: readonly Plugin_2[]; + server: ResolvedServerOptions; + build: ResolvedBuildOptions; + preview: ResolvedPreviewOptions; + ssr: ResolvedSSROptions; + assetsInclude: (file: string) => boolean; + logger: Logger; + createResolver: (options?: Partial<InternalResolveOptions>) => ResolveFn; + optimizeDeps: DepOptimizationOptions; + /* Excluded from this release type: packageCache */ + worker: ResolveWorkerOptions; + appType: AppType; + experimental: ExperimentalOptions; +}>; + +export declare interface ResolvedPreviewOptions extends PreviewOptions { +} + +export declare interface ResolvedServerOptions extends ServerOptions { + fs: Required<FileSystemServeOptions>; + middlewareMode: boolean; +} + +export declare interface ResolvedServerUrls { + local: string[]; + network: string[]; +} + +export declare interface ResolvedSSROptions extends SSROptions { + target: SSRTarget; + format: SSRFormat; + optimizeDeps: SsrDepOptimizationOptions; +} + +export declare type ResolvedUrl = [ +url: string, +resolvedId: string, +meta: object | null | undefined +]; + +export declare function resolveEnvPrefix({ envPrefix }: UserConfig): string[]; + +export declare type ResolveFn = (id: string, importer?: string, aliasOnly?: boolean, ssr?: boolean) => Promise<string | undefined>; + +export declare interface ResolveOptions { + mainFields?: string[]; + conditions?: string[]; + extensions?: string[]; + dedupe?: string[]; + preserveSymlinks?: boolean; +} + +export declare function resolvePackageData(id: string, basedir: string, preserveSymlinks?: boolean, packageCache?: PackageCache): PackageData | null; + +export declare function resolvePackageEntry(id: string, { dir, data, setResolvedCache, getResolvedCache }: PackageData, targetWeb: boolean, options: InternalResolveOptions): string | undefined; + +export declare type ResolverFunction = PluginHooks['resolveId'] + +export declare interface ResolverObject { + buildStart?: PluginHooks['buildStart'] + resolveId: ResolverFunction +} + +export declare interface ResolveWorkerOptions { + format: 'es' | 'iife'; + plugins: Plugin_2[]; + rollupOptions: RollupOptions; +} + +/** + * https://github.com/rollup/plugins/blob/master/packages/commonjs/types/index.d.ts + * + * This source code is licensed under the MIT license found in the + * LICENSE file at + * https://github.com/rollup/plugins/blob/master/LICENSE + */ +export declare interface RollupCommonJSOptions { + /** + * A minimatch pattern, or array of patterns, which specifies the files in + * the build the plugin should operate on. By default, all files with + * extension `".cjs"` or those in `extensions` are included, but you can + * narrow this list by only including specific files. These files will be + * analyzed and transpiled if either the analysis does not find ES module + * specific statements or `transformMixedEsModules` is `true`. + * @default undefined + */ + include?: string | RegExp | readonly (string | RegExp)[] + /** + * A minimatch pattern, or array of patterns, which specifies the files in + * the build the plugin should _ignore_. By default, all files with + * extensions other than those in `extensions` or `".cjs"` are ignored, but you + * can exclude additional files. See also the `include` option. + * @default undefined + */ + exclude?: string | RegExp | readonly (string | RegExp)[] + /** + * For extensionless imports, search for extensions other than .js in the + * order specified. Note that you need to make sure that non-JavaScript files + * are transpiled by another plugin first. + * @default [ '.js' ] + */ + extensions?: ReadonlyArray<string> + /** + * If true then uses of `global` won't be dealt with by this plugin + * @default false + */ + ignoreGlobal?: boolean + /** + * If false, skips source map generation for CommonJS modules. This will + * improve performance. + * @default true + */ + sourceMap?: boolean + /** + * Some `require` calls cannot be resolved statically to be translated to + * imports. + * When this option is set to `false`, the generated code will either + * directly throw an error when such a call is encountered or, when + * `dynamicRequireTargets` is used, when such a call cannot be resolved with a + * configured dynamic require target. + * Setting this option to `true` will instead leave the `require` call in the + * code or use it as a fallback for `dynamicRequireTargets`. + * @default false + */ + ignoreDynamicRequires?: boolean + /** + * Instructs the plugin whether to enable mixed module transformations. This + * is useful in scenarios with modules that contain a mix of ES `import` + * statements and CommonJS `require` expressions. Set to `true` if `require` + * calls should be transformed to imports in mixed modules, or `false` if the + * `require` expressions should survive the transformation. The latter can be + * important if the code contains environment detection, or you are coding + * for an environment with special treatment for `require` calls such as + * ElectronJS. See also the `ignore` option. + * @default false + */ + transformMixedEsModules?: boolean + /** + * By default, this plugin will try to hoist `require` statements as imports + * to the top of each file. While this works well for many code bases and + * allows for very efficient ESM output, it does not perfectly capture + * CommonJS semantics as the order of side effects like log statements may + * change. But it is especially problematic when there are circular `require` + * calls between CommonJS modules as those often rely on the lazy execution of + * nested `require` calls. + * + * Setting this option to `true` will wrap all CommonJS files in functions + * which are executed when they are required for the first time, preserving + * NodeJS semantics. Note that this can have an impact on the size and + * performance of the generated code. + * + * The default value of `"auto"` will only wrap CommonJS files when they are + * part of a CommonJS dependency cycle, e.g. an index file that is required by + * many of its dependencies. All other CommonJS files are hoisted. This is the + * recommended setting for most code bases. + * + * `false` will entirely prevent wrapping and hoist all files. This may still + * work depending on the nature of cyclic dependencies but will often cause + * problems. + * + * You can also provide a minimatch pattern, or array of patterns, to only + * specify a subset of files which should be wrapped in functions for proper + * `require` semantics. + * + * `"debug"` works like `"auto"` but after bundling, it will display a warning + * containing a list of ids that have been wrapped which can be used as + * minimatch pattern for fine-tuning. + * @default "auto" + */ + strictRequires?: boolean | string | RegExp | readonly (string | RegExp)[] + /** + * Sometimes you have to leave require statements unconverted. Pass an array + * containing the IDs or a `id => boolean` function. + * @default [] + */ + ignore?: ReadonlyArray<string> | ((id: string) => boolean) + /** + * In most cases, where `require` calls are inside a `try-catch` clause, + * they should be left unconverted as it requires an optional dependency + * that may or may not be installed beside the rolled up package. + * Due to the conversion of `require` to a static `import` - the call is + * hoisted to the top of the file, outside of the `try-catch` clause. + * + * - `true`: All `require` calls inside a `try` will be left unconverted. + * - `false`: All `require` calls inside a `try` will be converted as if the + * `try-catch` clause is not there. + * - `remove`: Remove all `require` calls from inside any `try` block. + * - `string[]`: Pass an array containing the IDs to left unconverted. + * - `((id: string) => boolean|'remove')`: Pass a function that control + * individual IDs. + * + * @default false + */ + ignoreTryCatch?: + | boolean + | 'remove' + | ReadonlyArray<string> + | ((id: string) => boolean | 'remove') + /** + * Controls how to render imports from external dependencies. By default, + * this plugin assumes that all external dependencies are CommonJS. This + * means they are rendered as default imports to be compatible with e.g. + * NodeJS where ES modules can only import a default export from a CommonJS + * dependency. + * + * If you set `esmExternals` to `true`, this plugins assumes that all + * external dependencies are ES modules and respect the + * `requireReturnsDefault` option. If that option is not set, they will be + * rendered as namespace imports. + * + * You can also supply an array of ids to be treated as ES modules, or a + * function that will be passed each external id to determine if it is an ES + * module. + * @default false + */ + esmExternals?: boolean | ReadonlyArray<string> | ((id: string) => boolean) + /** + * Controls what is returned when requiring an ES module from a CommonJS file. + * When using the `esmExternals` option, this will also apply to external + * modules. By default, this plugin will render those imports as namespace + * imports i.e. + * + * ```js + * // input + * const foo = require('foo'); + * + * // output + * import * as foo from 'foo'; + * ``` + * + * However there are some situations where this may not be desired. + * For these situations, you can change Rollup's behaviour either globally or + * per module. To change it globally, set the `requireReturnsDefault` option + * to one of the following values: + * + * - `false`: This is the default, requiring an ES module returns its + * namespace. This is the only option that will also add a marker + * `__esModule: true` to the namespace to support interop patterns in + * CommonJS modules that are transpiled ES modules. + * - `"namespace"`: Like `false`, requiring an ES module returns its + * namespace, but the plugin does not add the `__esModule` marker and thus + * creates more efficient code. For external dependencies when using + * `esmExternals: true`, no additional interop code is generated. + * - `"auto"`: This is complementary to how `output.exports: "auto"` works in + * Rollup: If a module has a default export and no named exports, requiring + * that module returns the default export. In all other cases, the namespace + * is returned. For external dependencies when using `esmExternals: true`, a + * corresponding interop helper is added. + * - `"preferred"`: If a module has a default export, requiring that module + * always returns the default export, no matter whether additional named + * exports exist. This is similar to how previous versions of this plugin + * worked. Again for external dependencies when using `esmExternals: true`, + * an interop helper is added. + * - `true`: This will always try to return the default export on require + * without checking if it actually exists. This can throw at build time if + * there is no default export. This is how external dependencies are handled + * when `esmExternals` is not used. The advantage over the other options is + * that, like `false`, this does not add an interop helper for external + * dependencies, keeping the code lean. + * + * To change this for individual modules, you can supply a function for + * `requireReturnsDefault` instead. This function will then be called once for + * each required ES module or external dependency with the corresponding id + * and allows you to return different values for different modules. + * @default false + */ + requireReturnsDefault?: + | boolean + | 'auto' + | 'preferred' + | 'namespace' + | ((id: string) => boolean | 'auto' | 'preferred' | 'namespace') + + /** + * @default "auto" + */ + defaultIsModuleExports?: boolean | 'auto' | ((id: string) => boolean | 'auto') + /** + * Some modules contain dynamic `require` calls, or require modules that + * contain circular dependencies, which are not handled well by static + * imports. Including those modules as `dynamicRequireTargets` will simulate a + * CommonJS (NodeJS-like) environment for them with support for dynamic + * dependencies. It also enables `strictRequires` for those modules. + * + * Note: In extreme cases, this feature may result in some paths being + * rendered as absolute in the final bundle. The plugin tries to avoid + * exposing paths from the local machine, but if you are `dynamicRequirePaths` + * with paths that are far away from your project's folder, that may require + * replacing strings like `"/Users/John/Desktop/foo-project/"` -\> `"/"`. + */ + dynamicRequireTargets?: string | ReadonlyArray<string> + /** + * To avoid long paths when using the `dynamicRequireTargets` option, you can use this option to specify a directory + * that is a common parent for all files that use dynamic require statements. Using a directory higher up such as `/` + * may lead to unnecessarily long paths in the generated code and may expose directory names on your machine like your + * home directory name. By default it uses the current working directory. + */ + dynamicRequireRoot?: string +} + +export declare interface RollupDynamicImportVarsOptions { + /** + * Files to include in this plugin (default all). + * @default [] + */ + include?: string | RegExp | (string | RegExp)[] + /** + * Files to exclude in this plugin (default none). + * @default [] + */ + exclude?: string | RegExp | (string | RegExp)[] + /** + * By default, the plugin quits the build process when it encounters an error. If you set this option to true, it will throw a warning instead and leave the code untouched. + * @default false + */ + warnOnError?: boolean +} + +export { rollupVersion } + +/** + * Search up for the nearest workspace root + */ +export declare function searchForWorkspaceRoot(current: string, root?: string): string; + +export declare function send(req: IncomingMessage, res: ServerResponse, content: string | Buffer, type: string, options: SendOptions): void; + +export declare interface SendOptions { + etag?: string; + cacheControl?: string; + headers?: OutgoingHttpHeaders; + map?: SourceMap | null; +} + +export declare type ServerHook = (server: ViteDevServer) => (() => void) | void | Promise<(() => void) | void>; + +export declare interface ServerOptions extends CommonServerOptions { + /** + * Configure HMR-specific options (port, host, path & protocol) + */ + hmr?: HmrOptions | boolean; + /** + * chokidar watch options + * https://github.com/paulmillr/chokidar#api + */ + watch?: WatchOptions; + /** + * Create Vite dev server to be used as a middleware in an existing server + */ + middlewareMode?: boolean | 'html' | 'ssr'; + /** + * Prepend this folder to http requests, for use when proxying vite as a subfolder + * Should start and end with the `/` character + */ + base?: string; + /** + * Options for files served via '/\@fs/'. + */ + fs?: FileSystemServeOptions; + /** + * Origin for the generated asset URLs. + * + * @example `http://127.0.0.1:8080` + */ + origin?: string; + /** + * Pre-transform known direct imports + * @default true + */ + preTransformRequests?: boolean; + /** + * Force dep pre-optimization regardless of whether deps have changed. + * + * @deprecated Use optimizeDeps.force instead, this option may be removed + * in a future minor version without following semver + */ + force?: boolean; +} + +export declare function sortUserPlugins(plugins: (Plugin_2 | Plugin_2[])[] | undefined): [Plugin_2[], Plugin_2[], Plugin_2[]]; + +export declare function splitVendorChunk(options?: { + cache?: SplitVendorChunkCache; +}): GetManualChunk; + +export declare class SplitVendorChunkCache { + cache: Map<string, boolean>; + constructor(); + reset(): void; +} + +export declare function splitVendorChunkPlugin(): Plugin_2; + +export declare type SsrDepOptimizationOptions = DepOptimizationConfig; + +export declare type SSRFormat = 'esm' | 'cjs'; + +export declare interface SSROptions { + noExternal?: string | RegExp | (string | RegExp)[] | true; + external?: string[]; + /** + * Define the target for the ssr build. The browser field in package.json + * is ignored for node but used if webworker is the target + * Default: 'node' + */ + target?: SSRTarget; + /** + * Define the format for the ssr build. Since Vite v3 the SSR build generates ESM by default. + * `'cjs'` can be selected to generate a CJS build, but it isn't recommended. This option is + * left marked as experimental to give users more time to update to ESM. CJS builds requires + * complex externalization heuristics that aren't present in the ESM format. + * @experimental + */ + format?: SSRFormat; + /** + * Control over which dependencies are optimized during SSR and esbuild options + * During build: + * no external CJS dependencies are optimized by default + * During dev: + * explicit no external CJS dependencies are optimized by default + * @experimental + */ + optimizeDeps?: SsrDepOptimizationOptions; +} + +export declare type SSRTarget = 'node' | 'webworker'; + +export declare namespace Terser { + export type ECMA = 5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 + + export interface ParseOptions { + bare_returns?: boolean + /** @deprecated legacy option. Currently, all supported EcmaScript is valid to parse. */ + ecma?: ECMA + html5_comments?: boolean + shebang?: boolean + } + + export interface CompressOptions { + arguments?: boolean + arrows?: boolean + booleans_as_integers?: boolean + booleans?: boolean + collapse_vars?: boolean + comparisons?: boolean + computed_props?: boolean + conditionals?: boolean + dead_code?: boolean + defaults?: boolean + directives?: boolean + drop_console?: boolean + drop_debugger?: boolean + ecma?: ECMA + evaluate?: boolean + expression?: boolean + global_defs?: object + hoist_funs?: boolean + hoist_props?: boolean + hoist_vars?: boolean + ie8?: boolean + if_return?: boolean + inline?: boolean | InlineFunctions + join_vars?: boolean + keep_classnames?: boolean | RegExp + keep_fargs?: boolean + keep_fnames?: boolean | RegExp + keep_infinity?: boolean + loops?: boolean + module?: boolean + negate_iife?: boolean + passes?: number + properties?: boolean + pure_funcs?: string[] + pure_getters?: boolean | 'strict' + reduce_funcs?: boolean + reduce_vars?: boolean + sequences?: boolean | number + side_effects?: boolean + switches?: boolean + toplevel?: boolean + top_retain?: null | string | string[] | RegExp + typeofs?: boolean + unsafe_arrows?: boolean + unsafe?: boolean + unsafe_comps?: boolean + unsafe_Function?: boolean + unsafe_math?: boolean + unsafe_symbols?: boolean + unsafe_methods?: boolean + unsafe_proto?: boolean + unsafe_regexp?: boolean + unsafe_undefined?: boolean + unused?: boolean + } + + export enum InlineFunctions { + Disabled = 0, + SimpleFunctions = 1, + WithArguments = 2, + WithArgumentsAndVariables = 3 + } + + export interface MangleOptions { + eval?: boolean + keep_classnames?: boolean | RegExp + keep_fnames?: boolean | RegExp + module?: boolean + nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler + properties?: boolean | ManglePropertiesOptions + reserved?: string[] + safari10?: boolean + toplevel?: boolean + } + + /** + * An identifier mangler for which the output is invariant with respect to the source code. + */ + export interface SimpleIdentifierMangler { + /** + * Obtains the nth most favored (usually shortest) identifier to rename a variable to. + * The mangler will increment n and retry until the return value is not in use in scope, and is not a reserved word. + * This function is expected to be stable; Evaluating get(n) === get(n) should always return true. + * @param n - The ordinal of the identifier. + */ + get(n: number): string + } + + /** + * An identifier mangler that leverages character frequency analysis to determine identifier precedence. + */ + export interface WeightedIdentifierMangler extends SimpleIdentifierMangler { + /** + * Modifies the internal weighting of the input characters by the specified delta. + * Will be invoked on the entire printed AST, and then deduct mangleable identifiers. + * @param chars - The characters to modify the weighting of. + * @param delta - The numeric weight to add to the characters. + */ + consider(chars: string, delta: number): number + /** + * Resets character weights. + */ + reset(): void + /** + * Sorts identifiers by character frequency, in preparation for calls to get(n). + */ + sort(): void + } + + export interface ManglePropertiesOptions { + builtins?: boolean + debug?: boolean + keep_quoted?: boolean | 'strict' + nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler + regex?: RegExp | string + reserved?: string[] + } + + export interface FormatOptions { + ascii_only?: boolean + /** @deprecated Not implemented anymore */ + beautify?: boolean + braces?: boolean + comments?: + | boolean + | 'all' + | 'some' + | RegExp + | (( + node: any, + comment: { + value: string + type: 'comment1' | 'comment2' | 'comment3' | 'comment4' + pos: number + line: number + col: number + } + ) => boolean) + ecma?: ECMA + ie8?: boolean + keep_numbers?: boolean + indent_level?: number + indent_start?: number + inline_script?: boolean + keep_quoted_props?: boolean + max_line_len?: number | false + preamble?: string + preserve_annotations?: boolean + quote_keys?: boolean + quote_style?: OutputQuoteStyle + safari10?: boolean + semicolons?: boolean + shebang?: boolean + shorthand?: boolean + source_map?: SourceMapOptions + webkit?: boolean + width?: number + wrap_iife?: boolean + wrap_func_args?: boolean + } + + export enum OutputQuoteStyle { + PreferDouble = 0, + AlwaysSingle = 1, + AlwaysDouble = 2, + AlwaysOriginal = 3 + } + + export interface MinifyOptions { + compress?: boolean | CompressOptions + ecma?: ECMA + enclose?: boolean | string + ie8?: boolean + keep_classnames?: boolean | RegExp + keep_fnames?: boolean | RegExp + mangle?: boolean | MangleOptions + module?: boolean + nameCache?: object + format?: FormatOptions + /** @deprecated deprecated */ + output?: FormatOptions + parse?: ParseOptions + safari10?: boolean + sourceMap?: boolean | SourceMapOptions + toplevel?: boolean + } + + export interface MinifyOutput { + code?: string + map?: object | string + decoded_map?: object | null + } + + export interface SourceMapOptions { + /** Source map object, 'inline' or source map file content */ + content?: object | string + includeSources?: boolean + filename?: string + root?: string + url?: string | 'inline' + } +} + +export declare interface TransformOptions { + ssr?: boolean; + html?: boolean; +} + +export declare interface TransformResult { + code: string; + map: SourceMap | null; + etag?: string; + deps?: string[]; + dynamicDeps?: string[]; +} + +export declare function transformWithEsbuild(code: string, filename: string, options?: EsbuildTransformOptions, inMap?: object): Promise<ESBuildTransformResult>; + +export declare interface Update { + type: 'js-update' | 'css-update' + path: string + acceptedPath: string + timestamp: number +} + +export declare interface UpdatePayload { + type: 'update' + updates: Update[] +} + +export declare interface UserConfig { + /** + * Project root directory. Can be an absolute path, or a path relative from + * the location of the config file itself. + * @default process.cwd() + */ + root?: string; + /** + * Base public path when served in development or production. + * @default '/' + */ + base?: string; + /** + * Directory to serve as plain static assets. Files in this directory are + * served and copied to build dist dir as-is without transform. The value + * can be either an absolute file system path or a path relative to <root>. + * + * Set to `false` or an empty string to disable copied static assets to build dist dir. + * @default 'public' + */ + publicDir?: string | false; + /** + * Directory to save cache files. Files in this directory are pre-bundled + * deps or some other cache files that generated by vite, which can improve + * the performance. You can use `--force` flag or manually delete the directory + * to regenerate the cache files. The value can be either an absolute file + * system path or a path relative to <root>. + * Default to `.vite` when no `package.json` is detected. + * @default 'node_modules/.vite' + */ + cacheDir?: string; + /** + * Explicitly set a mode to run in. This will override the default mode for + * each command, and can be overridden by the command line --mode option. + */ + mode?: string; + /** + * Define global variable replacements. + * Entries will be defined on `window` during dev and replaced during build. + */ + define?: Record<string, any>; + /** + * Array of vite plugins to use. + */ + plugins?: PluginOption[]; + /** + * Configure resolver + */ + resolve?: ResolveOptions & { + alias?: AliasOptions; + }; + /** + * CSS related options (preprocessors and CSS modules) + */ + css?: CSSOptions; + /** + * JSON loading options + */ + json?: JsonOptions; + /** + * Transform options to pass to esbuild. + * Or set to `false` to disable esbuild. + */ + esbuild?: ESBuildOptions | false; + /** + * Specify additional picomatch patterns to be treated as static assets. + */ + assetsInclude?: string | RegExp | (string | RegExp)[]; + /** + * Server specific options, e.g. host, port, https... + */ + server?: ServerOptions; + /** + * Build specific options + */ + build?: BuildOptions; + /** + * Preview specific options, e.g. host, port, https... + */ + preview?: PreviewOptions; + /** + * Dep optimization options + */ + optimizeDeps?: DepOptimizationOptions; + /** + * SSR specific options + */ + ssr?: SSROptions; + /** + * Experimental features + * + * Features under this field could change in the future and might NOT follow semver. + * Please be careful and always pin Vite's version when using them. + * @experimental + */ + experimental?: ExperimentalOptions; + /** + * Legacy options + * + * Features under this field only follow semver for patches, they could be removed in a + * future minor version. Please always pin Vite's version to a minor when using them. + */ + legacy?: LegacyOptions; + /** + * Log level. + * Default: 'info' + */ + logLevel?: LogLevel; + /** + * Custom logger. + */ + customLogger?: Logger; + /** + * Default: true + */ + clearScreen?: boolean; + /** + * Environment files directory. Can be an absolute path, or a path relative from + * the location of the config file itself. + * @default root + */ + envDir?: string; + /** + * Env variables starts with `envPrefix` will be exposed to your client source code via import.meta.env. + * @default 'VITE_' + */ + envPrefix?: string | string[]; + /** + * Worker bundle options + */ + worker?: { + /** + * Output format for worker bundle + * @default 'iife' + */ + format?: 'es' | 'iife'; + /** + * Vite plugins that apply to worker bundle + */ + plugins?: PluginOption[]; + /** + * Rollup options to build worker bundle + */ + rollupOptions?: Omit<RollupOptions, 'plugins' | 'input' | 'onwarn' | 'preserveEntrySignatures'>; + }; + /** + * Whether your application is a Single Page Application (SPA), + * a Multi-Page Application (MPA), or Custom Application (SSR + * and frameworks with custom HTML handling) + * @default 'spa' + */ + appType?: AppType; +} + +export declare type UserConfigExport = UserConfig | Promise<UserConfig> | UserConfigFn; + +export declare type UserConfigFn = (env: ConfigEnv) => UserConfig | Promise<UserConfig>; + +export declare const version: string; + +export declare interface ViteDevServer { + /** + * The resolved vite config object + */ + config: ResolvedConfig; + /** + * A connect app instance. + * - Can be used to attach custom middlewares to the dev server. + * - Can also be used as the handler function of a custom http server + * or as a middleware in any connect-style Node.js frameworks + * + * https://github.com/senchalabs/connect#use-middleware + */ + middlewares: Connect.Server; + /** + * native Node http server instance + * will be null in middleware mode + */ + httpServer: http.Server | null; + /** + * chokidar watcher instance + * https://github.com/paulmillr/chokidar#api + */ + watcher: FSWatcher; + /** + * web socket server with `send(payload)` method + */ + ws: WebSocketServer; + /** + * Rollup plugin container that can run plugin hooks on a given file + */ + pluginContainer: PluginContainer; + /** + * Module graph that tracks the import relationships, url to file mapping + * and hmr state. + */ + moduleGraph: ModuleGraph; + /** + * The resolved urls Vite prints on the CLI. null in middleware mode or + * before `server.listen` is called. + * + * @experimental + */ + resolvedUrls: ResolvedServerUrls | null; + /** + * Programmatically resolve, load and transform a URL and get the result + * without going through the http request pipeline. + */ + transformRequest(url: string, options?: TransformOptions): Promise<TransformResult | null>; + /** + * Apply vite built-in HTML transforms and any plugin HTML transforms. + */ + transformIndexHtml(url: string, html: string, originalUrl?: string): Promise<string>; + /** + * Transform module code into SSR format. + */ + ssrTransform(code: string, inMap: SourceMap | null, url: string): Promise<TransformResult | null>; + /** + * Load a given URL as an instantiated module for SSR. + */ + ssrLoadModule(url: string, opts?: { + fixStacktrace?: boolean; + }): Promise<Record<string, any>>; + /** + * Returns a fixed version of the given stack + */ + ssrRewriteStacktrace(stack: string): string; + /** + * Mutates the given SSR error by rewriting the stacktrace + */ + ssrFixStacktrace(e: Error): void; + /** + * Start the server. + */ + listen(port?: number, isRestart?: boolean): Promise<ViteDevServer>; + /** + * Stop the server. + */ + close(): Promise<void>; + /** + * Print server urls + */ + printUrls(): void; + /** + * Restart the server. + * + * @param forceOptimize - force the optimizer to re-bundle, same as --force cli flag + */ + restart(forceOptimize?: boolean): Promise<void>; + /* Excluded from this release type: _importGlobMap */ + /* Excluded from this release type: _ssrExternals */ + /* Excluded from this release type: _restartPromise */ + /* Excluded from this release type: _forceOptimizeOnRestart */ + /* Excluded from this release type: _pendingRequests */ +} + +export declare interface WatchOptions { + /** + * Indicates whether the process should continue to run as long as files are being watched. If + * set to `false` when using `fsevents` to watch, no more events will be emitted after `ready`, + * even if the process continues to run. + */ + persistent?: boolean + + /** + * ([anymatch](https://github.com/micromatch/anymatch)-compatible definition) Defines files/paths to + * be ignored. The whole relative or absolute path is tested, not just filename. If a function + * with two arguments is provided, it gets called twice per path - once with a single argument + * (the path), second time with two arguments (the path and the + * [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object of that path). + */ + ignored?: Matcher + + /** + * If set to `false` then `add`/`addDir` events are also emitted for matching paths while + * instantiating the watching as chokidar discovers these file paths (before the `ready` event). + */ + ignoreInitial?: boolean + + /** + * When `false`, only the symlinks themselves will be watched for changes instead of following + * the link references and bubbling events through the link's path. + */ + followSymlinks?: boolean + + /** + * The base directory from which watch `paths` are to be derived. Paths emitted with events will + * be relative to this. + */ + cwd?: string + + /** + * If set to true then the strings passed to .watch() and .add() are treated as literal path + * names, even if they look like globs. + * + * @default false + */ + disableGlobbing?: boolean + + /** + * Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU + * utilization, consider setting this to `false`. It is typically necessary to **set this to + * `true` to successfully watch files over a network**, and it may be necessary to successfully + * watch files in other non-standard situations. Setting to `true` explicitly on OS X overrides + * the `useFsEvents` default. + */ + usePolling?: boolean + + /** + * Whether to use the `fsevents` watching interface if available. When set to `true` explicitly + * and `fsevents` is available this supercedes the `usePolling` setting. When set to `false` on + * OS X, `usePolling: true` becomes the default. + */ + useFsEvents?: boolean + + /** + * If relying upon the [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object that + * may get passed with `add`, `addDir`, and `change` events, set this to `true` to ensure it is + * provided even in cases where it wasn't already available from the underlying watch events. + */ + alwaysStat?: boolean + + /** + * If set, limits how many levels of subdirectories will be traversed. + */ + depth?: number + + /** + * Interval of file system polling. + */ + interval?: number + + /** + * Interval of file system polling for binary files. ([see list of binary extensions](https://gi + * thub.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json)) + */ + binaryInterval?: number + + /** + * Indicates whether to watch files that don't have read permissions if possible. If watching + * fails due to `EPERM` or `EACCES` with this set to `true`, the errors will be suppressed + * silently. + */ + ignorePermissionErrors?: boolean + + /** + * `true` if `useFsEvents` and `usePolling` are `false`). Automatically filters out artifacts + * that occur when using editors that use "atomic writes" instead of writing directly to the + * source file. If a file is re-added within 100 ms of being deleted, Chokidar emits a `change` + * event rather than `unlink` then `add`. If the default of 100 ms does not work well for you, + * you can override it by setting `atomic` to a custom value, in milliseconds. + */ + atomic?: boolean | number + + /** + * can be set to an object in order to adjust timing params: + */ + awaitWriteFinish?: AwaitWriteFinishOptions | boolean +} + +declare class WebSocket_2 extends EventEmitter { + /** The connection is not yet open. */ + static readonly CONNECTING: 0 + /** The connection is open and ready to communicate. */ + static readonly OPEN: 1 + /** The connection is in the process of closing. */ + static readonly CLOSING: 2 + /** The connection is closed. */ + static readonly CLOSED: 3 + + binaryType: 'nodebuffer' | 'arraybuffer' | 'fragments' + readonly bufferedAmount: number + readonly extensions: string + /** Indicates whether the websocket is paused */ + readonly isPaused: boolean + readonly protocol: string + /** The current state of the connection */ + readonly readyState: + | typeof WebSocket_2.CONNECTING + | typeof WebSocket_2.OPEN + | typeof WebSocket_2.CLOSING + | typeof WebSocket_2.CLOSED + readonly url: string + + /** The connection is not yet open. */ + readonly CONNECTING: 0 + /** The connection is open and ready to communicate. */ + readonly OPEN: 1 + /** The connection is in the process of closing. */ + readonly CLOSING: 2 + /** The connection is closed. */ + readonly CLOSED: 3 + + onopen: ((event: WebSocket_2.Event) => void) | null + onerror: ((event: WebSocket_2.ErrorEvent) => void) | null + onclose: ((event: WebSocket_2.CloseEvent) => void) | null + onmessage: ((event: WebSocket_2.MessageEvent) => void) | null + + constructor(address: null) + constructor( + address: string | URL_2, + options?: WebSocket_2.ClientOptions | ClientRequestArgs + ) + constructor( + address: string | URL_2, + protocols?: string | string[], + options?: WebSocket_2.ClientOptions | ClientRequestArgs + ) + + close(code?: number, data?: string | Buffer): void + ping(data?: any, mask?: boolean, cb?: (err: Error) => void): void + pong(data?: any, mask?: boolean, cb?: (err: Error) => void): void + send(data: any, cb?: (err?: Error) => void): void + send( + data: any, + options: { + mask?: boolean | undefined + binary?: boolean | undefined + compress?: boolean | undefined + fin?: boolean | undefined + }, + cb?: (err?: Error) => void + ): void + terminate(): void + + /** + * Pause the websocket causing it to stop emitting events. Some events can still be + * emitted after this is called, until all buffered data is consumed. This method + * is a noop if the ready state is `CONNECTING` or `CLOSED`. + */ + pause(): void + /** + * Make a paused socket resume emitting events. This method is a noop if the ready + * state is `CONNECTING` or `CLOSED`. + */ + resume(): void + + // HTML5 WebSocket events + addEventListener( + method: 'message', + cb: (event: WebSocket_2.MessageEvent) => void, + options?: WebSocket_2.EventListenerOptions + ): void + addEventListener( + method: 'close', + cb: (event: WebSocket_2.CloseEvent) => void, + options?: WebSocket_2.EventListenerOptions + ): void + addEventListener( + method: 'error', + cb: (event: WebSocket_2.ErrorEvent) => void, + options?: WebSocket_2.EventListenerOptions + ): void + addEventListener( + method: 'open', + cb: (event: WebSocket_2.Event) => void, + options?: WebSocket_2.EventListenerOptions + ): void + + removeEventListener( + method: 'message', + cb: (event: WebSocket_2.MessageEvent) => void + ): void + removeEventListener( + method: 'close', + cb: (event: WebSocket_2.CloseEvent) => void + ): void + removeEventListener( + method: 'error', + cb: (event: WebSocket_2.ErrorEvent) => void + ): void + removeEventListener( + method: 'open', + cb: (event: WebSocket_2.Event) => void + ): void + + // Events + on( + event: 'close', + listener: (this: WebSocket_2, code: number, reason: Buffer) => void + ): this + on(event: 'error', listener: (this: WebSocket_2, err: Error) => void): this + on( + event: 'upgrade', + listener: (this: WebSocket_2, request: IncomingMessage) => void + ): this + on( + event: 'message', + listener: ( + this: WebSocket_2, + data: WebSocket_2.RawData, + isBinary: boolean + ) => void + ): this + on(event: 'open', listener: (this: WebSocket_2) => void): this + on( + event: 'ping' | 'pong', + listener: (this: WebSocket_2, data: Buffer) => void + ): this + on( + event: 'unexpected-response', + listener: ( + this: WebSocket_2, + request: ClientRequest, + response: IncomingMessage + ) => void + ): this + on( + event: string | symbol, + listener: (this: WebSocket_2, ...args: any[]) => void + ): this + + once( + event: 'close', + listener: (this: WebSocket_2, code: number, reason: Buffer) => void + ): this + once(event: 'error', listener: (this: WebSocket_2, err: Error) => void): this + once( + event: 'upgrade', + listener: (this: WebSocket_2, request: IncomingMessage) => void + ): this + once( + event: 'message', + listener: ( + this: WebSocket_2, + data: WebSocket_2.RawData, + isBinary: boolean + ) => void + ): this + once(event: 'open', listener: (this: WebSocket_2) => void): this + once( + event: 'ping' | 'pong', + listener: (this: WebSocket_2, data: Buffer) => void + ): this + once( + event: 'unexpected-response', + listener: ( + this: WebSocket_2, + request: ClientRequest, + response: IncomingMessage + ) => void + ): this + once( + event: string | symbol, + listener: (this: WebSocket_2, ...args: any[]) => void + ): this + + off( + event: 'close', + listener: (this: WebSocket_2, code: number, reason: Buffer) => void + ): this + off(event: 'error', listener: (this: WebSocket_2, err: Error) => void): this + off( + event: 'upgrade', + listener: (this: WebSocket_2, request: IncomingMessage) => void + ): this + off( + event: 'message', + listener: ( + this: WebSocket_2, + data: WebSocket_2.RawData, + isBinary: boolean + ) => void + ): this + off(event: 'open', listener: (this: WebSocket_2) => void): this + off( + event: 'ping' | 'pong', + listener: (this: WebSocket_2, data: Buffer) => void + ): this + off( + event: 'unexpected-response', + listener: ( + this: WebSocket_2, + request: ClientRequest, + response: IncomingMessage + ) => void + ): this + off( + event: string | symbol, + listener: (this: WebSocket_2, ...args: any[]) => void + ): this + + addListener( + event: 'close', + listener: (code: number, reason: Buffer) => void + ): this + addListener(event: 'error', listener: (err: Error) => void): this + addListener( + event: 'upgrade', + listener: (request: IncomingMessage) => void + ): this + addListener( + event: 'message', + listener: (data: WebSocket_2.RawData, isBinary: boolean) => void + ): this + addListener(event: 'open', listener: () => void): this + addListener(event: 'ping' | 'pong', listener: (data: Buffer) => void): this + addListener( + event: 'unexpected-response', + listener: (request: ClientRequest, response: IncomingMessage) => void + ): this + addListener(event: string | symbol, listener: (...args: any[]) => void): this + + removeListener( + event: 'close', + listener: (code: number, reason: Buffer) => void + ): this + removeListener(event: 'error', listener: (err: Error) => void): this + removeListener( + event: 'upgrade', + listener: (request: IncomingMessage) => void + ): this + removeListener( + event: 'message', + listener: (data: WebSocket_2.RawData, isBinary: boolean) => void + ): this + removeListener(event: 'open', listener: () => void): this + removeListener(event: 'ping' | 'pong', listener: (data: Buffer) => void): this + removeListener( + event: 'unexpected-response', + listener: (request: ClientRequest, response: IncomingMessage) => void + ): this + removeListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this +} + +declare namespace WebSocket_2 { + /** + * Data represents the raw message payload received over the WebSocket. + */ + type RawData = Buffer | ArrayBuffer | Buffer[] + + /** + * Data represents the message payload received over the WebSocket. + */ + type Data = string | Buffer | ArrayBuffer | Buffer[] + + /** + * CertMeta represents the accepted types for certificate & key data. + */ + type CertMeta = string | string[] | Buffer | Buffer[] + + /** + * VerifyClientCallbackSync is a synchronous callback used to inspect the + * incoming message. The return value (boolean) of the function determines + * whether or not to accept the handshake. + */ + type VerifyClientCallbackSync = (info: { + origin: string + secure: boolean + req: IncomingMessage + }) => boolean + + /** + * VerifyClientCallbackAsync is an asynchronous callback used to inspect the + * incoming message. The return value (boolean) of the function determines + * whether or not to accept the handshake. + */ + type VerifyClientCallbackAsync = ( + info: { origin: string; secure: boolean; req: IncomingMessage }, + callback: ( + res: boolean, + code?: number, + message?: string, + headers?: OutgoingHttpHeaders + ) => void + ) => void + + interface ClientOptions extends SecureContextOptions { + protocol?: string | undefined + followRedirects?: boolean | undefined + generateMask?(mask: Buffer): void + handshakeTimeout?: number | undefined + maxRedirects?: number | undefined + perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined + localAddress?: string | undefined + protocolVersion?: number | undefined + headers?: { [key: string]: string } | undefined + origin?: string | undefined + agent?: Agent | undefined + host?: string | undefined + family?: number | undefined + checkServerIdentity?(servername: string, cert: CertMeta): boolean + rejectUnauthorized?: boolean | undefined + maxPayload?: number | undefined + skipUTF8Validation?: boolean | undefined + } + + interface PerMessageDeflateOptions { + serverNoContextTakeover?: boolean | undefined + clientNoContextTakeover?: boolean | undefined + serverMaxWindowBits?: number | undefined + clientMaxWindowBits?: number | undefined + zlibDeflateOptions?: + | { + flush?: number | undefined + finishFlush?: number | undefined + chunkSize?: number | undefined + windowBits?: number | undefined + level?: number | undefined + memLevel?: number | undefined + strategy?: number | undefined + dictionary?: Buffer | Buffer[] | DataView | undefined + info?: boolean | undefined + } + | undefined + zlibInflateOptions?: ZlibOptions | undefined + threshold?: number | undefined + concurrencyLimit?: number | undefined + } + + interface Event { + type: string + target: WebSocket + } + + interface ErrorEvent { + error: any + message: string + type: string + target: WebSocket + } + + interface CloseEvent { + wasClean: boolean + code: number + reason: string + type: string + target: WebSocket + } + + interface MessageEvent { + data: Data + type: string + target: WebSocket + } + + interface EventListenerOptions { + once?: boolean | undefined + } + + interface ServerOptions { + host?: string | undefined + port?: number | undefined + backlog?: number | undefined + server?: Server | Server_2 | undefined + verifyClient?: + | VerifyClientCallbackAsync + | VerifyClientCallbackSync + | undefined + handleProtocols?: ( + protocols: Set<string>, + request: IncomingMessage + ) => string | false + path?: string | undefined + noServer?: boolean | undefined + clientTracking?: boolean | undefined + perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined + maxPayload?: number | undefined + skipUTF8Validation?: boolean | undefined + WebSocket?: typeof WebSocket.WebSocket | undefined + } + + interface AddressInfo { + address: string + family: string + port: number + } + + // WebSocket Server + class Server<T extends WebSocket = WebSocket> extends EventEmitter { + options: ServerOptions + path: string + clients: Set<T> + + constructor(options?: ServerOptions, callback?: () => void) + + address(): AddressInfo | string + close(cb?: (err?: Error) => void): void + handleUpgrade( + request: IncomingMessage, + socket: Duplex, + upgradeHead: Buffer, + callback: (client: T, request: IncomingMessage) => void + ): void + shouldHandle(request: IncomingMessage): boolean | Promise<boolean> + + // Events + on( + event: 'connection', + cb: (this: Server<T>, socket: T, request: IncomingMessage) => void + ): this + on(event: 'error', cb: (this: Server<T>, error: Error) => void): this + on( + event: 'headers', + cb: (this: Server<T>, headers: string[], request: IncomingMessage) => void + ): this + on(event: 'close' | 'listening', cb: (this: Server<T>) => void): this + on( + event: string | symbol, + listener: (this: Server<T>, ...args: any[]) => void + ): this + + once( + event: 'connection', + cb: (this: Server<T>, socket: T, request: IncomingMessage) => void + ): this + once(event: 'error', cb: (this: Server<T>, error: Error) => void): this + once( + event: 'headers', + cb: (this: Server<T>, headers: string[], request: IncomingMessage) => void + ): this + once(event: 'close' | 'listening', cb: (this: Server<T>) => void): this + once( + event: string | symbol, + listener: (this: Server<T>, ...args: any[]) => void + ): this + + off( + event: 'connection', + cb: (this: Server<T>, socket: T, request: IncomingMessage) => void + ): this + off(event: 'error', cb: (this: Server<T>, error: Error) => void): this + off( + event: 'headers', + cb: (this: Server<T>, headers: string[], request: IncomingMessage) => void + ): this + off(event: 'close' | 'listening', cb: (this: Server<T>) => void): this + off( + event: string | symbol, + listener: (this: Server<T>, ...args: any[]) => void + ): this + + addListener( + event: 'connection', + cb: (client: T, request: IncomingMessage) => void + ): this + addListener(event: 'error', cb: (err: Error) => void): this + addListener( + event: 'headers', + cb: (headers: string[], request: IncomingMessage) => void + ): this + addListener(event: 'close' | 'listening', cb: () => void): this + addListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this + + removeListener(event: 'connection', cb: (client: T) => void): this + removeListener(event: 'error', cb: (err: Error) => void): this + removeListener( + event: 'headers', + cb: (headers: string[], request: IncomingMessage) => void + ): this + removeListener(event: 'close' | 'listening', cb: () => void): this + removeListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this + } + + const WebSocketServer: typeof Server + interface WebSocketServer extends Server {} // tslint:disable-line no-empty-interface + const WebSocket: typeof WebSocketAlias + interface WebSocket extends WebSocketAlias {} // tslint:disable-line no-empty-interface + + // WebSocket stream + function createWebSocketStream( + websocket: WebSocket, + options?: DuplexOptions + ): Duplex +} +export { WebSocket_2 as WebSocket } + +export declare const WebSocketAlias: typeof WebSocket_2; + +export declare interface WebSocketAlias extends WebSocket_2 {} + +export declare interface WebSocketClient { + /** + * Send event to the client + */ + send(payload: HMRPayload): void; + /** + * Send custom event + */ + send(event: string, payload?: CustomPayload['data']): void; + /** + * The raw WebSocket instance + * @advanced + */ + socket: WebSocket_2; +} + +export declare type WebSocketCustomListener<T> = (data: T, client: WebSocketClient) => void; + +export declare interface WebSocketServer { + /** + * Get all connected clients. + */ + clients: Set<WebSocketClient>; + /** + * Broadcast events to all clients + */ + send(payload: HMRPayload): void; + /** + * Send custom event + */ + send<T extends string>(event: T, payload?: InferCustomEventPayload<T>): void; + /** + * Disconnect all clients and terminate the server. + */ + close(): Promise<void>; + /** + * Handle custom event emitted by `import.meta.hot.send` + */ + on: WebSocket_2.Server['on'] & { + <T extends string>(event: T, listener: WebSocketCustomListener<InferCustomEventPayload<T>>): void; + }; + /** + * Unregister event listener. + */ + off: WebSocket_2.Server['off'] & { + (event: string, listener: Function): void; + }; +} + +export { }