UNPKG

jsv-compiler

Version:
1,306 lines 169 kB
'use strict'; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; var _a, _b; Object.defineProperty(exports, '__esModule', { value: true }); var shared = require('@vue/shared'); var sourceMap = require('source-map'); var parser = require('@babel/parser'); var estreeWalker = require('estree-walker'); function defaultOnError(error) { throw error; } function createCompilerError(code, loc, messages, additionalMessage) { var msg = (messages || errorMessages)[code] + (additionalMessage || ""); var error = new SyntaxError(String(msg)); error.code = code; error.loc = loc; return error; } var errorMessages = (_a = {}, // parse errors _a[0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */] = 'Illegal comment.', _a[1 /* CDATA_IN_HTML_CONTENT */] = 'CDATA section is allowed only in XML context.', _a[2 /* DUPLICATE_ATTRIBUTE */] = 'Duplicate attribute.', _a[3 /* END_TAG_WITH_ATTRIBUTES */] = 'End tag cannot have attributes.', _a[4 /* END_TAG_WITH_TRAILING_SOLIDUS */] = "Illegal '/' in tags.", _a[5 /* EOF_BEFORE_TAG_NAME */] = 'Unexpected EOF in tag.', _a[6 /* EOF_IN_CDATA */] = 'Unexpected EOF in CDATA section.', _a[7 /* EOF_IN_COMMENT */] = 'Unexpected EOF in comment.', _a[8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */] = 'Unexpected EOF in script.', _a[9 /* EOF_IN_TAG */] = 'Unexpected EOF in tag.', _a[10 /* INCORRECTLY_CLOSED_COMMENT */] = 'Incorrectly closed comment.', _a[11 /* INCORRECTLY_OPENED_COMMENT */] = 'Incorrectly opened comment.', _a[12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */] = "Illegal tag name. Use '&lt;' to print '<'.", _a[13 /* MISSING_ATTRIBUTE_VALUE */] = 'Attribute value was expected.', _a[14 /* MISSING_END_TAG_NAME */] = 'End tag name was expected.', _a[15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */] = 'Whitespace was expected.', _a[16 /* NESTED_COMMENT */] = "Unexpected '<!--' in comment.", _a[17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */] = 'Attribute name cannot contain U+0022 ("), U+0027 (\'), and U+003C (<).', _a[18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */] = 'Unquoted attribute value cannot contain U+0022 ("), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).', _a[19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */] = "Attribute name cannot start with '='.", _a[21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */] = "'<?' is allowed only in XML context.", _a[22 /* UNEXPECTED_SOLIDUS_IN_TAG */] = "Illegal '/' in tags.", // Vue-specific parse errors _a[23 /* X_INVALID_END_TAG */] = 'Invalid end tag.', _a[24 /* X_MISSING_END_TAG */] = 'Element is missing end tag.', _a[25 /* X_MISSING_INTERPOLATION_END */] = 'Interpolation end sign was not found.', _a[26 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */] = 'End bracket for dynamic directive argument was not found. ' + 'Note that dynamic directive argument cannot contain spaces.', // transform errors _a[27 /* X_V_IF_NO_EXPRESSION */] = "v-if/v-else-if is missing expression.", _a[28 /* X_V_IF_SAME_KEY */] = "v-if/else branches must use unique keys.", _a[29 /* X_V_ELSE_NO_ADJACENT_IF */] = "v-else/v-else-if has no adjacent v-if.", _a[30 /* X_V_FOR_NO_EXPRESSION */] = "v-for is missing expression.", _a[31 /* X_V_FOR_MALFORMED_EXPRESSION */] = "v-for has invalid expression.", _a[32 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */] = "<template v-for> key should be placed on the <template> tag.", _a[33 /* X_V_BIND_NO_EXPRESSION */] = "v-bind is missing expression.", _a[34 /* X_V_ON_NO_EXPRESSION */] = "v-on is missing expression.", _a[35 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */] = "Unexpected custom directive on <slot> outlet.", _a[36 /* 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.", _a[37 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */] = "Duplicate slot names found. ", _a[38 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */] = "Extraneous children found when component already has explicitly named " + "default slot. These children will be ignored.", _a[39 /* X_V_SLOT_MISPLACED */] = "v-slot can only be used on components or <template> tags.", _a[40 /* X_V_MODEL_NO_EXPRESSION */] = "v-model is missing expression.", _a[41 /* X_V_MODEL_MALFORMED_EXPRESSION */] = "v-model value must be a valid JavaScript member expression.", _a[42 /* X_V_MODEL_ON_SCOPE_VARIABLE */] = "v-model cannot be used on v-for or v-slot scope variables because they are not writable.", _a[43 /* X_INVALID_EXPRESSION */] = "Error parsing JavaScript expression: ", _a[44 /* X_KEEP_ALIVE_INVALID_CHILDREN */] = "<KeepAlive> expects exactly one child component.", // generic errors _a[45 /* X_PREFIX_ID_NOT_SUPPORTED */] = "\"prefixIdentifiers\" option is not supported in this build of compiler.", _a[46 /* X_MODULE_MODE_NOT_SUPPORTED */] = "ES module mode is not supported in this build of compiler.", _a[47 /* X_CACHE_HANDLER_NOT_SUPPORTED */] = "\"cacheHandlers\" option is only supported when the \"prefixIdentifiers\" option is enabled.", _a[48 /* X_SCOPE_ID_NOT_SUPPORTED */] = "\"scopeId\" option is only supported in module mode.", _a); var FRAGMENT = Symbol("Fragment"); var TELEPORT = Symbol("Teleport"); var SUSPENSE = Symbol("Suspense"); var KEEP_ALIVE = Symbol("KeepAlive"); var BASE_TRANSITION = Symbol("BaseTransition"); var OPEN_BLOCK = Symbol("openBlock"); var CREATE_BLOCK = Symbol("createBlock"); var CREATE_VNODE = Symbol("createVNode"); var CREATE_COMMENT = Symbol("createCommentVNode"); var CREATE_TEXT = Symbol("createTextVNode"); var CREATE_STATIC = Symbol("createStaticVNode"); var RESOLVE_COMPONENT = Symbol("resolveComponent"); var RESOLVE_DYNAMIC_COMPONENT = Symbol("resolveDynamicComponent"); var RESOLVE_DIRECTIVE = Symbol("resolveDirective"); var WITH_DIRECTIVES = Symbol("withDirectives"); var RENDER_LIST = Symbol("renderList"); var RENDER_SLOT = Symbol("renderSlot"); var CREATE_SLOTS = Symbol("createSlots"); var TO_DISPLAY_STRING = Symbol("toDisplayString"); var MERGE_PROPS = Symbol("mergeProps"); var TO_HANDLERS = Symbol("toHandlers"); var CAMELIZE = Symbol("camelize"); var CAPITALIZE = Symbol("capitalize"); var SET_BLOCK_TRACKING = Symbol("setBlockTracking"); var PUSH_SCOPE_ID = Symbol("pushScopeId"); var POP_SCOPE_ID = Symbol("popScopeId"); var WITH_SCOPE_ID = Symbol("withScopeId"); var WITH_CTX = Symbol("withCtx"); // 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. var helperNameMap = (_b = {}, _b[FRAGMENT] = "Fragment", _b[TELEPORT] = "Teleport", _b[SUSPENSE] = "Suspense", _b[KEEP_ALIVE] = "KeepAlive", _b[BASE_TRANSITION] = "BaseTransition", _b[OPEN_BLOCK] = "openBlock", _b[CREATE_BLOCK] = "createBlock", _b[CREATE_VNODE] = "createVNode", _b[CREATE_COMMENT] = "createCommentVNode", _b[CREATE_TEXT] = "createTextVNode", _b[CREATE_STATIC] = "createStaticVNode", _b[RESOLVE_COMPONENT] = "resolveComponent", _b[RESOLVE_DYNAMIC_COMPONENT] = "resolveDynamicComponent", _b[RESOLVE_DIRECTIVE] = "resolveDirective", _b[WITH_DIRECTIVES] = "withDirectives", _b[RENDER_LIST] = "renderList", _b[RENDER_SLOT] = "renderSlot", _b[CREATE_SLOTS] = "createSlots", _b[TO_DISPLAY_STRING] = "toDisplayString", _b[MERGE_PROPS] = "mergeProps", _b[TO_HANDLERS] = "toHandlers", _b[CAMELIZE] = "camelize", _b[CAPITALIZE] = "capitalize", _b[SET_BLOCK_TRACKING] = "setBlockTracking", _b[PUSH_SCOPE_ID] = "pushScopeId", _b[POP_SCOPE_ID] = "popScopeId", _b[WITH_SCOPE_ID] = "withScopeId", _b[WITH_CTX] = "withCtx", _b); function registerRuntimeHelpers(helpers) { Object.getOwnPropertySymbols(helpers).forEach(function (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. var locStub = { source: '', start: { line: 1, column: 1, offset: 0 }, end: { line: 1, column: 1, offset: 0 } }; function createRoot(children, loc) { if (loc === void 0) { loc = locStub; } return { type: 0 /* ROOT */, children: children, helpers: [], components: [], directives: [], hoists: [], imports: [], cached: 0, temps: 0, codegenNode: undefined, loc: loc }; } function createVNodeCall(context, tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking, loc) { if (isBlock === void 0) { isBlock = false; } if (disableTracking === void 0) { disableTracking = false; } if (loc === void 0) { loc = locStub; } if (context) { if (isBlock) { context.helper(OPEN_BLOCK); context.helper(CREATE_BLOCK); } else { context.helper(CREATE_VNODE); } if (directives) { context.helper(WITH_DIRECTIVES); } } return { type: 13 /* VNODE_CALL */, tag: tag, props: props, children: children, patchFlag: patchFlag, dynamicProps: dynamicProps, directives: directives, isBlock: isBlock, disableTracking: disableTracking, loc: loc }; } function createArrayExpression(elements, loc) { if (loc === void 0) { loc = locStub; } return { type: 17 /* JS_ARRAY_EXPRESSION */, loc: loc, elements: elements }; } function createObjectExpression(properties, loc) { if (loc === void 0) { loc = locStub; } return { type: 15 /* JS_OBJECT_EXPRESSION */, loc: loc, properties: properties }; } function createObjectProperty(key, value) { return { type: 16 /* JS_PROPERTY */, loc: locStub, key: shared.isString(key) ? createSimpleExpression(key, true) : key, value: value }; } function createSimpleExpression(content, isStatic, loc, isConstant) { if (loc === void 0) { loc = locStub; } if (isConstant === void 0) { isConstant = false; } return { type: 4 /* SIMPLE_EXPRESSION */, loc: loc, isConstant: isConstant, content: content, isStatic: isStatic }; } function createInterpolation(content, loc) { return { type: 5 /* INTERPOLATION */, loc: loc, content: shared.isString(content) ? createSimpleExpression(content, false, loc) : content }; } function createCompoundExpression(children, loc) { if (loc === void 0) { loc = locStub; } return { type: 8 /* COMPOUND_EXPRESSION */, loc: loc, children: children }; } function createCallExpression(callee, args, loc) { if (args === void 0) { args = []; } if (loc === void 0) { loc = locStub; } return { type: 14 /* JS_CALL_EXPRESSION */, loc: loc, callee: callee, arguments: args }; } function createFunctionExpression(params, returns, newline, isSlot, loc) { if (returns === void 0) { returns = undefined; } if (newline === void 0) { newline = false; } if (isSlot === void 0) { isSlot = false; } if (loc === void 0) { loc = locStub; } return { type: 18 /* JS_FUNCTION_EXPRESSION */, params: params, returns: returns, newline: newline, isSlot: isSlot, loc: loc }; } function createConditionalExpression(test, consequent, alternate, newline) { if (newline === void 0) { newline = true; } return { type: 19 /* JS_CONDITIONAL_EXPRESSION */, test: test, consequent: consequent, alternate: alternate, newline: newline, loc: locStub }; } function createCacheExpression(index, value, isVNode) { if (isVNode === void 0) { isVNode = false; } return { type: 20 /* JS_CACHE_EXPRESSION */, index: index, value: value, isVNode: isVNode, loc: locStub }; } function createBlockStatement(body) { return { type: 21 /* JS_BLOCK_STATEMENT */, body: body, loc: locStub }; } function createTemplateLiteral(elements) { return { type: 22 /* JS_TEMPLATE_LITERAL */, elements: elements, loc: locStub }; } function createIfStatement(test, consequent, alternate) { return { type: 23 /* JS_IF_STATEMENT */, test: test, consequent: consequent, alternate: alternate, loc: locStub }; } function createAssignmentExpression(left, right) { return { type: 24 /* JS_ASSIGNMENT_EXPRESSION */, left: left, right: right, loc: locStub }; } function createSequenceExpression(expressions) { return { type: 25 /* JS_SEQUENCE_EXPRESSION */, expressions: expressions, loc: locStub }; } function createReturnStatement(returns) { return { type: 26 /* JS_RETURN_STATEMENT */, returns: returns, loc: locStub }; } var isStaticExp = function (p) { return p.type === 4 /* SIMPLE_EXPRESSION */ && p.isStatic; }; var isBuiltInType = function (tag, expected) { return tag === expected || tag === shared.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; } } var nonIdentifierRE = /^\d|[^\$\w]/; var isSimpleIdentifier = function (name) { return !nonIdentifierRE.test(name); }; var memberExpRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\[[^\]]+\])*$/; var isMemberExpression = function (path) { if (!path) return false; return memberExpRE.test(path.trim()); }; function getInnerRange(loc, offset, length) { var source = loc.source.substr(offset, length); var newLoc = { source: 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) { if (numberOfCharacters === void 0) { numberOfCharacters = source.length; } return advancePositionWithMutation(shared.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) { if (numberOfCharacters === void 0) { numberOfCharacters = source.length; } var linesCount = 0; var lastNewLinePos = -1; for (var 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) { if (allowEmpty === void 0) { allowEmpty = false; } for (var i = 0; i < node.props.length; i++) { var p = node.props[i]; if (p.type === 7 /* DIRECTIVE */ && (allowEmpty || p.exp) && (shared.isString(name) ? p.name === name : name.test(p.name))) { return p; } } } function findProp(node, name, dynamicOnly, allowEmpty) { if (dynamicOnly === void 0) { dynamicOnly = false; } if (allowEmpty === void 0) { allowEmpty = false; } for (var i = 0; i < node.props.length; i++) { var 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) && isBindKey(p.arg, name)) { return p; } } } function isBindKey(arg, name) { return !!(arg && isStaticExp(arg) && arg.content === name); } function hasDynamicKeyVBind(node) { return node.props.some(function (p) { return 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 injectProp(node, prop, context) { var propsWithInjection; var props = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2]; if (props == null || shared.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 var first = props.arguments[0]; if (!shared.isString(first) && first.type === 15 /* JS_OBJECT_EXPRESSION */) { first.properties.unshift(prop); } else { props.arguments.unshift(createObjectExpression([prop])); } propsWithInjection = props; } else if (props.type === 15 /* JS_OBJECT_EXPRESSION */) { var alreadyExists = false; // check existing key to avoid overriding user provided keys if (prop.key.type === 4 /* SIMPLE_EXPRESSION */) { var propKeyName_1 = prop.key.content; alreadyExists = props.properties.some(function (p) { return p.key.type === 4 /* SIMPLE_EXPRESSION */ && p.key.content === propKeyName_1; }); } 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 ]); } if (node.type === 13 /* VNODE_CALL */) { node.props = propsWithInjection; } else { node.arguments[2] = propsWithInjection; } } function toValidAssetId(name, type) { return "_" + type + "_" + name.replace(/[^\w]/g, '_'); } // 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 (var i = 0; i < node.props.length; i++) { var p = node.props[i]; if (p.type === 7 /* DIRECTIVE */ && (hasScopeRef(p.arg, ids) || hasScopeRef(p.exp, ids))) { return true; } } return node.children.some(function (c) { return hasScopeRef(c, ids); }); case 11 /* FOR */: if (hasScopeRef(node.source, ids)) { return true; } return node.children.some(function (c) { return hasScopeRef(c, ids); }); case 9 /* IF */: return node.branches.some(function (b) { return hasScopeRef(b, ids); }); case 10 /* IF_BRANCH */: if (hasScopeRef(node.condition, ids)) { return true; } return node.children.some(function (c) { return hasScopeRef(c, ids); }); case 4 /* SIMPLE_EXPRESSION */: return (!node.isStatic && isSimpleIdentifier(node.content) && !!ids[node.content]); case 8 /* COMPOUND_EXPRESSION */: return node.children.some(function (c) { return shared.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: return false; } } // 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. var decodeRE = /&(gt|lt|amp|apos|quot);/g; var decodeMap = { gt: '>', lt: '<', amp: '&', apos: "'", quot: '"' }; var defaultParserOptions = { delimiters: ["{{", "}}"], getNamespace: function () { return 0; } /* HTML */, getTextMode: function () { return 0; } /* DATA */, isVoidTag: shared.NO, isPreTag: shared.NO, isCustomElement: shared.NO, decodeEntities: function (rawText) { return rawText.replace(decodeRE, function (_, p1) { return decodeMap[p1]; }); }, onError: defaultOnError, comments: false }; function baseParse(content, options) { if (options === void 0) { options = {}; } var context = createParserContext(content, options); var start = getCursor(context); return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start)); } function createParserContext(content, rawOptions) { var options = shared.extend({}, defaultParserOptions); for (var key in rawOptions) { // @ts-ignore options[key] = rawOptions[key] || defaultParserOptions[key]; } return { options: options, column: 1, line: 1, offset: 0, originalSource: content, source: content, inPre: false, inVPre: false }; } function parseChildren(context, mode, ancestors) { var parent = last(ancestors); var ns = parent ? parent.ns : 0 /* HTML */; var nodes = []; while (!isEnd(context, mode, ancestors)) { var s = context.source; var 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); } 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 (shared.isArray(node)) { for (var i = 0; i < node.length; i++) { pushNode(nodes, node[i]); } } else { pushNode(nodes, node); } } // Whitespace management for more efficient output // (same as v2 whitespace: 'condense') var removedWhitespace = false; if (mode !== 2 /* RAWTEXT */) { if (!context.inPre) { for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node.type === 2 /* TEXT */) { if (!/[^\t\r\n\f ]/.test(node.content)) { var prev = nodes[i - 1]; var next = nodes[i + 1]; // If: // - the whitespace is the first or last node, or: // - the whitespace is adjacent to a comment, or: // - the whitespace is between two elements AND contains newline // Then the whitespace is ignored. if (!prev || !next || 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, condensed consecutive whitespace inside the text // down to a single space node.content = ' '; } } else { node.content = node.content.replace(/[\t\r\n\f ]+/g, ' '); } } } } else if (parent && context.options.isPreTag(parent.tag)) { // remove leading newline per html spec // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element var 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 */) { var 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); var 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) { var start = getCursor(context); var content; // Regular comment. var 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. var s = context.source.slice(0, match.index); var 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: content, loc: getSelection(context, start) }; } function parseBogusComment(context) { var start = getCursor(context); var contentStart = context.source[1] === '?' ? 1 : 2; var content; var 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: content, loc: getSelection(context, start) }; } function parseElement(context, ancestors) { // Start tag. var wasInPre = context.inPre; var wasInVPre = context.inVPre; var parent = last(ancestors); var element = parseTag(context, 0 /* Start */, parent); var isPreBoundary = context.inPre && !wasInPre; var isVPreBoundary = context.inVPre && !wasInVPre; if (element.isSelfClosing || context.options.isVoidTag(element.tag)) { return element; } // Children. ancestors.push(element); var mode = context.options.getTextMode(element, parent); var children = parseChildren(context, mode, ancestors); ancestors.pop(); 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') { var 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; } var isSpecialTemplateDirective = /*#__PURE__*/ shared.makeMap("if,else,else-if,for,slot"); /** * Parse a tag (E.g. `<div id=a>`) with that type (start tag or end tag). */ function parseTag(context, type, parent) { // Tag open. var start = getCursor(context); var match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source); var tag = match[1]; var 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 var cursor = getCursor(context); var currentSource = context.source; // Attributes. var props = parseAttributes(context, type); // check <pre> tag if (context.options.isPreTag(tag)) { context.inPre = true; } // check v-pre if (!context.inVPre && props.some(function (p) { return p.type === 7 /* DIRECTIVE */ && p.name === 'pre'; })) { context.inVPre = true; // reset context shared.extend(context, cursor); context.source = currentSource; // re-parse attrs and filter out v-pre itself props = parseAttributes(context, type).filter(function (p) { return p.name !== 'v-pre'; }); } // Tag close. var 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); } var tagType = 0 /* ELEMENT */; var options = context.options; if (!context.inVPre && !options.isCustomElement(tag)) { var hasVIs = props.some(function (p) { return p.type === 7 /* DIRECTIVE */ && p.name === 'is'; }); if (options.isNativeTag && !hasVIs) { if (!options.isNativeTag(tag)) tagType = 1 /* COMPONENT */; } else if (hasVIs || isCoreComponent(tag) || (options.isBuiltInComponent && options.isBuiltInComponent(tag)) || /^[A-Z]/.test(tag) || tag === 'component') { tagType = 1 /* COMPONENT */; } if (tag === 'slot') { tagType = 2 /* SLOT */; } else if (tag === 'template' && props.some(function (p) { return (p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name)); })) { tagType = 3 /* TEMPLATE */; } } return { type: 1 /* ELEMENT */, ns: ns, tag: tag, tagType: tagType, props: props, isSelfClosing: isSelfClosing, children: [], loc: getSelection(context, start), codegenNode: undefined // to be created during transform phase }; } function parseAttributes(context, type) { var props = []; var 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 */); } var attr = parseAttribute(context, attributeNames); 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. var start = getCursor(context); var match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source); var 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 */); } { var pattern = /["'<]/g; var m = void 0; while ((m = pattern.exec(name))) { emitError(context, 17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index); } } advanceBy(context, name.length); // Value var 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 */); } } var loc = getSelection(context, start); if (!context.inVPre && /^(v-|:|@|#)/.test(name)) { var match_1 = /(?:^v-([a-z0-9-]+))?(?:(?::|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name); var dirName = match_1[1] || (startsWith(name, ':') ? 'bind' : startsWith(name, '@') ? 'on' : 'slot'); var arg = void 0; if (match_1[2]) { var isSlot = dirName === 'slot'; var startOffset = name.indexOf(match_1[2]); var loc_1 = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match_1[2].length + ((isSlot && match_1[3]) || '').length)); var content = match_1[2]; var isStatic = true; if (content.startsWith('[')) { isStatic = false; if (!content.endsWith(']')) { emitError(context, 26 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */); } content = content.substr(1, content.length - 2); } 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_1[3] || ''; } arg = { type: 4 /* SIMPLE_EXPRESSION */, content: content, isStatic: isStatic, isConstant: isStatic, loc: loc_1 }; } if (value && value.isQuoted) { var valueLoc = value.loc; valueLoc.start.offset++; valueLoc.start.column++; valueLoc.end = advancePositionWithClone(valueLoc.start, value.content); valueLoc.source = valueLoc.source.slice(1, -1); } 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 // true by `transformExpression` to make it eligible for hoisting. isConstant: false, loc: value.loc }, arg: arg, modifiers: match_1[3] ? match_1[3].substr(1).split('.') : [], loc: loc }; } return { type: 6 /* ATTRIBUTE */, name: name, value: value && { type: 2 /* TEXT */, content: value.content, loc: value.loc }, loc: loc }; } function parseAttributeValue(context) { var start = getCursor(context); var content; var quote = context.source[0]; var isQuoted = quote === "\"" || quote === "'"; if (isQuoted) { // Quoted value. advanceBy(context, 1); var 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 var match = /^[^\t\r\n\f >]+/.exec(context.source); if (!match) { return undefined; } var unexpectedChars = /["'<=`]/g; var m = void 0; 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: content, isQuoted: isQuoted, loc: getSelection(context, start) }; } function parseInterpolation(context, mode) { var _a = context.options.delimiters, open = _a[0], close = _a[1]; var closeIndex = context.source.indexOf(close, open.length); if (closeIndex === -1) { emitError(context, 25 /* X_MISSING_INTERPOLATION_END */); return undefined; } var start = getCursor(context); advanceBy(context, open.length); var innerStart = getCursor(context); var innerEnd = getCursor(context); var rawContentLength = closeIndex - open.length; var rawContent = context.source.slice(0, rawContentLength); var preTrimContent = parseTextData(context, rawContentLength, mode); var content = preTrimContent.trim(); var startOffset = preTrimContent.indexOf(content); if (startOffset > 0) { advancePositionWithMutation(innerStart, rawContent, startOffset); } var 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 isConstant: false, content: content, loc: getSelection(context, innerStart, innerEnd) }, loc: getSelection(context, start) }; } function parseText(context, mode) { var endTokens = ['<', context.options.delimiters[0]]; if (mode === 3 /* CDATA */) { endTokens.push(']]>'); } var endIndex = context.source.length; for (var i = 0; i < endTokens.length; i++) { var index = context.source.indexOf(endTokens[i], 1); if (index !== -1 && endIndex > index) { endIndex = index; } } var start = getCursor(context); var content = parseTextData(context, endIndex, mode); return { type: 2 /* TEXT */, content: 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) { var rawText = context.source.slice(0, length); advanceBy(context, length); if (mode === 2 /* RAWTEXT */ || mode === 3 /* CDATA */ || rawText.indexOf('&') === -1) { return rawText; } else { // DATA or RCDATA containing "&"". Entity decoding required. return context.options.decodeEntities(rawText, mode === 4 /* ATTRIBUTE_VALUE */); } } function getCursor(context) { var column = context.column, line = context.line, offset = context.offset; return { column: column, line: line, offset: offset }; } function getSelection(context, start, end) { end = end || getCursor(context); return { start: start, end: 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) { var source = context.source; advancePositionWithMutation(context, source, numberOfCharacters); context.source = source.slice(numberOfCharacters); } function advanceSpaces(context) { var 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) { if (loc === void 0) { 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) { var s = context.source; switch (mode) { case 0 /* DATA */: if (startsWith(s, '</')) { //TODO: probably bad performance for (var i = ancestors.length - 1; i >= 0; --i) { if (startsWithEndTagOpen(s, ancestors[i].tag)) { return true; } } } break; case 1 /* RCDATA */: case 2 /* RAWTEXT */: { var parent_1 = last(ancestors); if (parent_1 && startsWithEndTagOpen(s, parent_1.tag)) { return true; } break; } case 3 /* CDATA */: if (startsWith(s, ']]>')) { return true; } break; } return !s; } function startsWithEndTagOpen(source, tag) { return (startsWith(source, '</') && source.substr(2, tag.length).toLowerCase() === tag.toLowerCase() && /[\t\r\n\f />]/.test(source[2 + tag.length] || '>')); } function hoistStatic(root, context) { walk(root, context, new Map(), // Root node is unfortunately non-hoistable due to potential parent // fallthrough attributes. isSingleElementRoot(root, root.children[0])); } function isSingleElementRoot(root, child) { var children = root.children; return (children.length === 1 && child.type === 1 /* ELEMENT */ && !isSlotOutlet(child)); } function walk(node, context, resultCache, doNotHoistNode) { if (doNotHoistNode === void 0) { doNotHoistNode = false; } var hasHoistedNode = false; // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces // static bindings with expressions. These expressions are guaranteed to be // constant so they are still eligible for hoisting, but they are only // available at runtime and therefore cannot be evaluated ahead of time. // This is only a concern for pre-stringification (via transformHoist by // @vue/compiler-dom), but doing it here allows us to perform only one full // walk of the AST and allow `stringifyStatic` to stop walking as soon as its // stringficiation threshold is met. var hasRuntimeConstant = false; var children = node.children; for (var i = 0; i < children.length; i++) { var child = children[i]; // only plain elements & text calls are eligible for hoisting. if (child.type === 1 /* ELEMENT */ && child.tagType === 0 /* ELEMENT */) { var staticType = void 0; if (!doNotHoistNode && (staticType = getStaticType(child, resultCache)) > 0) { if (staticType === 2 /* HAS_RUNTIME_CONSTANT */) { hasRuntimeConstant = true; } child.codegenNode.patchFlag = -1 /* HOISTED */ + (" /* HOISTED */"); child.codegenNode = context.hoist(child.codegenNode); hasHoistedNode = true; continue; } else { // node may contain dynamic children, but its props may be eligible for // hoisting. var codegenNode = child.codegenNode; if (codegenNode.type === 13 /* VNODE_CALL */) { var flag = getPatchFlag(codegenNode); if ((!flag || flag === 512 /* NEED_PATCH */ || flag === 1 /* TEXT */) && !hasNonHoistableProps(child)) { var props = getNodeProps(child); if (props) { codegenNode.props = context.hoist(props); } } } } } else if (child.type === 12 /* TEXT_CALL */) { var staticType = getStaticType(child.content, resultCache); if (staticType > 0) { if (staticType === 2 /* HAS_RUNTIME_CONSTANT */) { hasRunti