diff --git a/packages/uni-cli-shared/src/constants.ts b/packages/uni-cli-shared/src/constants.ts index 497e6d0b9c5844069e7c9071488baf5f831ada17..92cc58d8829d1bff9d4ee1c2e40766f74c28a911 100644 --- a/packages/uni-cli-shared/src/constants.ts +++ b/packages/uni-cli-shared/src/constants.ts @@ -1,6 +1,7 @@ export const PUBLIC_DIR = 'static' export const EXTNAME_JS = ['.js', '.ts'] export const EXTNAME_VUE = ['.vue', '.nvue', '.fvue'] +export const EXTNAME_VUE_RE = /\.(vue|nvue|fvue)$/ export const H5_API_STYLE_PATH = '@dcloudio/uni-h5/style/api/' export const H5_FRAMEWORK_STYLE_PATH = '@dcloudio/uni-h5/style/framework/' diff --git a/packages/uni-cli-shared/src/preprocess/context.ts b/packages/uni-cli-shared/src/preprocess/context.ts index 4ad572140f7cbf6836eaceb86395dedac25de98b..5f8b88b616132d8c8b276a0285594b917ce8e62e 100644 --- a/packages/uni-cli-shared/src/preprocess/context.ts +++ b/packages/uni-cli-shared/src/preprocess/context.ts @@ -9,6 +9,8 @@ export const jsContext = { MP_WEIXIN: false, QUICKAPP_NATIVE: false, QUICKAPP_WEBVIEW: false, + QUICKAPP_WEBVIEW_UNION: false, + QUICKAPP_WEBVIEW_HUAWEI: false, MP: false, APP: false, APP_PLUS_NVUE: false, diff --git a/packages/uni-h5-vue/dist/vue.runtime.compat.cjs.js b/packages/uni-h5-vue/dist/vue.runtime.compat.cjs.js index d767391bfa072d2e4778894bdf6a7e420839b685..ec6a2a9e2ce8b85cffb8a3568e6ef8585e57c113 100644 --- a/packages/uni-h5-vue/dist/vue.runtime.compat.cjs.js +++ b/packages/uni-h5-vue/dist/vue.runtime.compat.cjs.js @@ -1,9 +1,5 @@ 'use strict'; -var parser = require('@babel/parser'); -var estreeWalker = require('estree-walker'); -var sourceMap = require('source-map'); - /** * Make a map and return a function for checking if a key * is in that map. @@ -20,74 +16,11 @@ function makeMap(str, expectsLowerCase) { return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val]; } -/** - * dev only flag -> name mapping - */ -const PatchFlagNames = { - [1 /* TEXT */]: `TEXT`, - [2 /* CLASS */]: `CLASS`, - [4 /* STYLE */]: `STYLE`, - [8 /* PROPS */]: `PROPS`, - [16 /* FULL_PROPS */]: `FULL_PROPS`, - [32 /* HYDRATE_EVENTS */]: `HYDRATE_EVENTS`, - [64 /* STABLE_FRAGMENT */]: `STABLE_FRAGMENT`, - [128 /* KEYED_FRAGMENT */]: `KEYED_FRAGMENT`, - [256 /* UNKEYED_FRAGMENT */]: `UNKEYED_FRAGMENT`, - [512 /* NEED_PATCH */]: `NEED_PATCH`, - [1024 /* DYNAMIC_SLOTS */]: `DYNAMIC_SLOTS`, - [2048 /* DEV_ROOT_FRAGMENT */]: `DEV_ROOT_FRAGMENT`, - [-1 /* HOISTED */]: `HOISTED`, - [-2 /* BAIL */]: `BAIL` -}; - -/** - * Dev only - */ -const slotFlagsText = { - [1 /* STABLE */]: 'STABLE', - [2 /* DYNAMIC */]: 'DYNAMIC', - [3 /* FORWARDED */]: 'FORWARDED' -}; - const GLOBALS_WHITE_LISTED = 'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' + 'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' + 'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt'; const isGloballyWhitelisted = /*#__PURE__*/ makeMap(GLOBALS_WHITE_LISTED); -const range = 2; -function generateCodeFrame(source, start = 0, end = source.length) { - const lines = source.split(/\r?\n/); - let count = 0; - const res = []; - for (let i = 0; i < lines.length; i++) { - count += lines[i].length + 1; - 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; - if (j === i) { - // push underline - const pad = start - (count - lineLength) + 1; - 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 + 1; - } - } - 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: @@ -100,40 +33,7 @@ function generateCodeFrame(source, start = 0, end = source.length) { * - readonly -> readOnly */ const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`; -const isSpecialBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs); -/** - * CSS properties that accept plain numbers - */ -const isNoUnitNumericStyleProp = /*#__PURE__*/ makeMap(`animation-iteration-count,border-image-outset,border-image-slice,` + - `border-image-width,box-flex,box-flex-group,box-ordinal-group,column-count,` + - `columns,flex,flex-grow,flex-positive,flex-shrink,flex-negative,flex-order,` + - `grid-row,grid-row-end,grid-row-span,grid-row-start,grid-column,` + - `grid-column-end,grid-column-span,grid-column-start,font-weight,line-clamp,` + - `line-height,opacity,order,orphans,tab-size,widows,z-index,zoom,` + - // SVG - `fill-opacity,flood-opacity,stop-opacity,stroke-dasharray,stroke-dashoffset,` + - `stroke-miterlimit,stroke-opacity,stroke-width`); -/** - * Known attributes, this is used for stringification of runtime static nodes - * so that we don't stringify bindings that cannot be set from HTML. - * Don't also forget to allow `data-*` and `aria-*`! - * Generated from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes - */ -const isKnownAttr = /*#__PURE__*/ makeMap(`accept,accept-charset,accesskey,action,align,allow,alt,async,` + - `autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,` + - `border,buffered,capture,challenge,charset,checked,cite,class,code,` + - `codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,` + - `coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,` + - `disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,` + - `formaction,formenctype,formmethod,formnovalidate,formtarget,headers,` + - `height,hidden,high,href,hreflang,http-equiv,icon,id,importance,integrity,` + - `ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,` + - `manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,` + - `open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,` + - `referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,` + - `selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,` + - `start,step,style,summary,tabindex,target,title,translate,type,usemap,` + - `value,width,wrap`); +const isSpecialBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs); function normalizeStyle(value) { if (isArray(value)) { @@ -165,22 +65,6 @@ function parseStringStyle(cssText) { }); return ret; } -function stringifyStyle(styles) { - let ret = ''; - if (!styles) { - return ret; - } - for (const key in styles) { - const value = styles[key]; - const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key); - if (isString(value) || - (typeof value === 'number' && isNoUnitNumericStyleProp(normalizedKey))) { - // only render valid values - ret += `${normalizedKey}:${value};`; - } - } - return ret; -} function normalizeClass(value) { let res = ''; if (isString(value)) { @@ -226,50 +110,8 @@ const SVG_TAGS = 'svg,animate,animateMotion,animateTransform,circle,clipPath,col 'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' + 'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' + 'text,textPath,title,tspan,unknown,use,view'; -const VOID_TAGS = 'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr'; const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS); -const isSVGTag = /*#__PURE__*/ makeMap(SVG_TAGS); -const isVoidTag = /*#__PURE__*/ makeMap(VOID_TAGS); - -const escapeRE = /["'&<>]/; -function escapeHtml(string) { - const str = '' + string; - const match = escapeRE.exec(str); - if (!match) { - return str; - } - let html = ''; - let escaped; - let index; - let lastIndex = 0; - for (index = match.index; index < str.length; index++) { - switch (str.charCodeAt(index)) { - case 34: // " - escaped = '"'; - break; - case 38: // & - escaped = '&'; - break; - case 39: // ' - escaped = '''; - break; - case 60: // < - escaped = '<'; - break; - case 62: // > - escaped = '>'; - break; - default: - continue; - } - if (lastIndex !== index) { - html += str.substring(lastIndex, index); - } - lastIndex = index + 1; - html += escaped; - } - return lastIndex !== index ? html + str.substring(lastIndex, index) : html; -} +const isSVGTag = /*#__PURE__*/ makeMap(SVG_TAGS); function looseCompareArrays(a, b) { if (a.length !== b.length) @@ -352,17 +194,6 @@ const replacer = (_key, val) => { return val; }; -/** - * List of @babel/parser plugins that are used for template expression - * transforms and SFC script transforms. By default we enable proposals slated - * for ES2020. This will need to be updated as the spec moves forward. - * Full list at https://babeljs.io/docs/en/next/babel-parser#plugins - */ -const babelParserDefaultPlugins = [ - 'bigInt', - 'optionalChaining', - 'nullishCoalescingOperator' -]; const EMPTY_OBJ = Object.freeze({}) ; const EMPTY_ARR = Object.freeze([]) ; @@ -3586,6 +3417,23 @@ function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EM callWithErrorHandling(fn, instance, 4 /* WATCH_CLEANUP */); }; }; + // in SSR there is no need to setup an actual effect, and it should be noop + // unless it's eager + if (isInSSRComponentSetup) { + // we will also not call the invalidate callback (+ runner is not set up) + onInvalidate = NOOP; + if (!cb) { + getter(); + } + else if (immediate) { + callWithAsyncErrorHandling(cb, instance, 3 /* WATCH_CALLBACK */, [ + getter(), + undefined, + onInvalidate + ]); + } + return NOOP; + } let oldValue = isMultiSource ? [] : INITIAL_WATCHER_VALUE; const job = () => { if (!runner.active) { @@ -6738,7 +6586,7 @@ function defineAsyncComponent(source) { }; // suspense-controlled or SSR. if ((suspensible && instance.suspense) || - (false )) { + (isInSSRComponentSetup)) { return load() .then(comp => { return () => createInnerComp(comp, instance); @@ -9953,7 +9801,12 @@ function setupStatefulComponent(instance, isSSR) { function handleSetupResult(instance, setupResult, isSSR) { if (isFunction(setupResult)) { // setup returned an inline render function - { + if (instance.type.__ssrInlineRender) { + // when the function's name is `ssrRender` (compiled by SFC inline mode), + // set it as ssrRender instead. + instance.ssrRender = setupResult; + } + else { instance.render = setupResult; } } @@ -9996,7 +9849,17 @@ function finishComponentSetup(instance, isSSR, skipOptions) { } } // template / render function normalization - if (!instance.render) { + if (isSSR) { + // 1. the render function may already exist, returned by `setup` + // 2. otherwise try to use the `Component.render` + // 3. if the component doesn't have a render function, + // set `instance.render` to NOOP so that it can inherit the render + // function from mixins/extend + instance.render = (instance.render || + Component.render || + NOOP); + } + else if (!instance.render) { // could be set from setup() if (compile && !Component.render) { const template = (instance.vnode.props && @@ -10400,11 +10263,19 @@ function initCustomFormatter() { // Core API ------------------------------------------------------------------ const version = "3.1.0-beta.3"; +const _ssrUtils = { + createComponentInstance, + setupComponent, + renderComponentRoot, + setCurrentRenderingInstance, + isVNode, + normalizeVNode +}; /** * SSR utils for \@vue/server-renderer. Only exposed in cjs builds. * @internal */ -const ssrUtils = (null); +const ssrUtils = (_ssrUtils ); /** * @internal only exposed in compat builds */ @@ -11637,6 +11508,30 @@ function callModelHook(el, binding, vnode, prevVNode, hook) { } const fn = modelToUse[hook]; fn && fn(el, binding, vnode, prevVNode); +} +// SSR vnode transforms +{ + vModelText.getSSRProps = ({ value }) => ({ value }); + vModelRadio.getSSRProps = ({ value }, vnode) => { + if (vnode.props && looseEqual(vnode.props.value, value)) { + return { checked: true }; + } + }; + vModelCheckbox.getSSRProps = ({ value }, vnode) => { + if (isArray(value)) { + if (vnode.props && looseIndexOf(value, vnode.props.value) > -1) { + return { checked: true }; + } + } + else if (isSet(value)) { + if (vnode.props && value.has(vnode.props.value)) { + return { checked: true }; + } + } + else if (value) { + return { checked: true }; + } + }; } const systemModifiers = ['ctrl', 'shift', 'alt', 'meta']; @@ -11764,6 +11659,13 @@ const vShow = { setDisplay(el, value); } }; +{ + vShow.getSSRProps = ({ value }) => { + if (!value) { + return { style: { display: 'none' } }; + } + }; +} function setDisplay(el, value) { el.style.display = value ? el._vod : 'none'; } @@ -12048,8039 +11950,14 @@ function createCompatVue$1() { return Vue; } -function defaultOnError(error) { - throw error; -} -function defaultOnWarn(msg) { - console.warn(`[Vue warn] ${msg.message}`); -} -function createCompilerError(code, loc, messages, additionalMessage) { - const msg = (messages || errorMessages)[code] + (additionalMessage || ``) - ; - 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 ' isRef(x) ? x.value = y : x = y - const rVal = parent.right; - const rExp = rawExp.slice(rVal.start - 1, rVal.end - 1); - const rExpString = stringifyExpression(processExpression(createSimpleExpression(rExp, false), context)); - return `${context.helperString(IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${raw}.value = ${rExpString} : ${raw}`; - } - else if (isUpdateArg) { - // make id replace parent in the code range so the raw update operator - // is removed - id.start = parent.start; - id.end = parent.end; - const { prefix: isPrefix, operator } = parent; - const prefix = isPrefix ? operator : ``; - const postfix = isPrefix ? `` : operator; - // let binding. - // x++ --> isRef(a) ? a.value++ : a++ - return `${context.helperString(IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${prefix}${raw}.value${postfix} : ${prefix}${raw}${postfix}`; - } - else if (isDestructureAssignment) { - // TODO - // let binding in a destructure assignment - it's very tricky to - // handle both possible cases here without altering the original - // structure of the code, so we just assume it's not a ref here - // for now - return raw; - } - else { - return `${context.helperString(UNREF)}(${raw})`; - } - } - else if (type === "props" /* PROPS */) { - // use __props which is generated by compileScript so in ts mode - // it gets correct type - return `__props.${raw}`; - } - } - else { - if (type && type.startsWith('setup')) { - // setup bindings in non-inline mode - return `$setup.${raw}`; - } - else if (type) { - return `$${type}.${raw}`; - } - } - // fallback to ctx - return `_ctx.${raw}`; - }; - // fast path if expression is a simple identifier. - const rawExp = node.content; - // bail constant on parens (function invocation) and dot (member access) - const bailConstant = rawExp.indexOf(`(`) > -1 || rawExp.indexOf('.') > 0; - if (isSimpleIdentifier(rawExp)) { - const isScopeVarReference = context.identifiers[rawExp]; - const isAllowedGlobal = isGloballyWhitelisted(rawExp); - const isLiteral = isLiteralWhitelisted(rawExp); - if (!asParams && !isScopeVarReference && !isAllowedGlobal && !isLiteral) { - // const bindings exposed from setup can be skipped for patching but - // cannot be hoisted to module scope - if (bindingMetadata[node.content] === "setup-const" /* SETUP_CONST */) { - node.constType = 1 /* CAN_SKIP_PATCH */; - } - node.content = rewriteIdentifier(rawExp); - } - else if (!isScopeVarReference) { - if (isLiteral) { - node.constType = 3 /* CAN_STRINGIFY */; - } - else { - node.constType = 2 /* CAN_HOIST */; - } - } - return node; - } - let ast; - // exp needs to be parsed differently: - // 1. Multiple inline statements (v-on, with presence of `;`): parse as raw - // exp, but make sure to pad with spaces for consistent ranges - // 2. Expressions: wrap with parens (for e.g. object expressions) - // 3. Function arguments (v-for, v-slot): place in a function argument position - const source = asRawStatements - ? ` ${rawExp} ` - : `(${rawExp})${asParams ? `=>{}` : ``}`; - try { - ast = parser.parse(source, { - plugins: [...context.expressionPlugins, ...babelParserDefaultPlugins] - }).program; - } - catch (e) { - context.onError(createCompilerError(43 /* X_INVALID_EXPRESSION */, node.loc, undefined, e.message)); - return node; - } - const ids = []; - const knownIds = Object.create(context.identifiers); - const isDuplicate = (node) => ids.some(id => id.start === node.start); - const parentStack = []; - estreeWalker.walk(ast, { - enter(node, parent) { - parent && parentStack.push(parent); - if (node.type === 'Identifier') { - if (!isDuplicate(node)) { - // v2 wrapped filter call - if (node.name.startsWith('_filter_')) { - return; - } - const needPrefix = shouldPrefix(node, parent, parentStack); - if (!knownIds[node.name] && needPrefix) { - if (isStaticProperty(parent) && parent.shorthand) { - // property shorthand like { foo }, we need to add the key since - // we rewrite the value - node.prefix = `${node.name}: `; - } - node.name = rewriteIdentifier(node.name, parent, node); - ids.push(node); - } - else if (!isStaticPropertyKey(node, parent)) { - // The identifier is considered constant unless it's pointing to a - // scope variable (a v-for alias, or a v-slot prop) - if (!(needPrefix && knownIds[node.name]) && !bailConstant) { - node.isConstant = true; - } - // also generate sub-expressions for other identifiers for better - // source map support. (except for property keys which are static) - ids.push(node); - } - } - } - else if (isFunction$1(node)) { - // walk function expressions and add its arguments to known identifiers - // so that we don't prefix them - node.params.forEach(p => estreeWalker.walk(p, { - enter(child, parent) { - if (child.type === 'Identifier' && - // do not record as scope variable if is a destructured key - !isStaticPropertyKey(child, parent) && - // do not record if this is a default value - // assignment of a destructured variable - !(parent && - parent.type === 'AssignmentPattern' && - parent.right === child)) { - const { name } = child; - if (node.scopeIds && node.scopeIds.has(name)) { - return; - } - if (name in knownIds) { - knownIds[name]++; - } - else { - knownIds[name] = 1; - } - (node.scopeIds || (node.scopeIds = new Set())).add(name); - } - } - })); - } - }, - leave(node, parent) { - parent && parentStack.pop(); - if (node !== ast.body[0].expression && node.scopeIds) { - node.scopeIds.forEach((id) => { - knownIds[id]--; - if (knownIds[id] === 0) { - delete knownIds[id]; - } - }); - } - } - }); - // We break up the compound expression into an array of strings and sub - // expressions (for identifiers that have been prefixed). In codegen, if - // an ExpressionNode has the `.children` property, it will be used instead of - // `.content`. - const children = []; - ids.sort((a, b) => a.start - b.start); - ids.forEach((id, i) => { - // range is offset by -1 due to the wrapping parens when parsed - const start = id.start - 1; - const end = id.end - 1; - const last = ids[i - 1]; - const leadingText = rawExp.slice(last ? last.end - 1 : 0, start); - if (leadingText.length || id.prefix) { - children.push(leadingText + (id.prefix || ``)); - } - const source = rawExp.slice(start, end); - children.push(createSimpleExpression(id.name, false, { - source, - start: advancePositionWithClone(node.loc.start, source, start), - end: advancePositionWithClone(node.loc.start, source, end) - }, id.isConstant ? 3 /* CAN_STRINGIFY */ : 0 /* NOT_CONSTANT */)); - if (i === ids.length - 1 && end < rawExp.length) { - children.push(rawExp.slice(end)); - } - }); - let ret; - if (children.length) { - ret = createCompoundExpression(children, node.loc); - } - else { - ret = node; - ret.constType = bailConstant - ? 0 /* NOT_CONSTANT */ - : 3 /* CAN_STRINGIFY */; - } - ret.identifiers = Object.keys(knownIds); - return ret; -} -const isFunction$1 = (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; -function shouldPrefix(id, parent, parentStack) { - // declaration id - if ((parent.type === 'VariableDeclarator' || - parent.type === 'ClassDeclaration') && - parent.id === id) { - return false; - } - if (isFunction$1(parent)) { - // function decalration/expression id - if (parent.id === id) { - return false; - } - // params list - if (parent.params.includes(id)) { - return false; - } - } - // property key - // this also covers object destructure pattern - if (isStaticPropertyKey(id, parent)) { - return false; - } - // non-assignment array destructure pattern - if (parent.type === 'ArrayPattern' && - !isInDestructureAssignment(parent, parentStack)) { - return false; - } - // member expression property - if ((parent.type === 'MemberExpression' || - parent.type === 'OptionalMemberExpression') && - parent.property === id && - !parent.computed) { - return false; - } - // is a special keyword but parsed as identifier - if (id.name === 'arguments') { - return false; - } - // skip whitelisted globals - if (isGloballyWhitelisted(id.name)) { - return false; - } - // special case for webpack compilation - if (id.name === 'require') { - return false; - } - return true; -} -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 stringifyExpression(exp) { - if (isString(exp)) { - return exp; - } - else if (exp.type === 4 /* SIMPLE_EXPRESSION */) { - return exp.content; - } - else { - return exp.children - .map(stringifyExpression) - .join(''); - } -} - -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(27 /* X_V_IF_NO_EXPRESSION */, dir.loc)); - dir.exp = createSimpleExpression(`true`, false, loc); - } - if (context.prefixIdentifiers && dir.exp) { - // dir.exp can only be simple expression because vIf transform is applied - // before expression transform. - dir.exp = processExpression(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 (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 */) { - // move the node to the if node's branches - context.removeNode(); - const branch = createIfBranch(node, dir); - if (comments.length) { - branch.children = [...comments, ...branch.children]; - } - // check if user is forcing same key on different branches - { - const key = branch.userKey; - if (key) { - sibling.branches.forEach(({ userKey }) => { - if (isSameKey(userKey, key)) { - context.onError(createCompilerError(28 /* 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(29 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc)); - } - break; - } - } -} -function createIfBranch(node, dir) { - return { - type: 10 /* IF_BRANCH */, - loc: node.loc, - condition: dir.name === 'else' ? undefined : dir.exp, - children: node.tagType === 3 /* TEMPLATE */ && !findDir(node, 'for') - ? node.children - : [node], - userKey: findProp(node, `key`) - }; -} -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), [ - '"v-if"' , - 'true' - ])); - } - else { - return createChildrenCodegenNode(branch, keyIndex, context); - } -} -function createChildrenCodegenNode(branch, keyIndex, context) { - const { helper, removeHelper } = 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 (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 + (` /* ${patchFlagText} */` ), undefined, undefined, true, false, branch.loc); - } - } - else { - const vnodeCall = firstChild - .codegenNode; - // Change createVNode to createBlock. - if (vnodeCall.type === 13 /* VNODE_CALL */ && !vnodeCall.isBlock) { - removeHelper(CREATE_VNODE); - vnodeCall.isBlock = true; - helper(OPEN_BLOCK); - helper(CREATE_BLOCK); - } - // inject branch key - injectProp(vnodeCall, keyProperty, context); - return vnodeCall; - } -} -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 keyProp = findProp(node, `key`); - const keyProperty = keyProp - ? createObjectProperty(`key`, keyProp.type === 6 /* ATTRIBUTE */ - ? createSimpleExpression(keyProp.value.content, true) - : keyProp.exp) - : null; - if (context.prefixIdentifiers && keyProperty) { - // #2085 process :key expression needs to be processed in order for it - // to behave consistently for