Best JavaScript code snippet using playwright-internal
compiler-dom.global.js
Source:compiler-dom.global.js
...213 alternate,214 loc: locStub215 };216 }217 function createCacheExpression(index, value, isVNode = false) {218 return {219 type: 20 /* JS_CACHE_EXPRESSION */,220 index,221 value,222 isVNode,223 loc: locStub224 };225 }226 const FRAGMENT = Symbol( `Fragment` );227 const PORTAL = Symbol( `Portal` );228 const SUSPENSE = Symbol( `Suspense` );229 const OPEN_BLOCK = Symbol( `openBlock` );230 const CREATE_BLOCK = Symbol( `createBlock` );231 const CREATE_VNODE = Symbol( `createVNode` );232 const CREATE_COMMENT = Symbol( `createCommentVNode` );233 const CREATE_TEXT = Symbol( `createTextVNode` );234 const RESOLVE_COMPONENT = Symbol( `resolveComponent` );235 const RESOLVE_DYNAMIC_COMPONENT = Symbol( `resolveDynamicComponent` );236 const RESOLVE_DIRECTIVE = Symbol( `resolveDirective` );237 const WITH_DIRECTIVES = Symbol( `withDirectives` );238 const RENDER_LIST = Symbol( `renderList` );239 const RENDER_SLOT = Symbol( `renderSlot` );240 const CREATE_SLOTS = Symbol( `createSlots` );241 const TO_STRING = Symbol( `toString` );242 const MERGE_PROPS = Symbol( `mergeProps` );243 const TO_HANDLERS = Symbol( `toHandlers` );244 const CAMELIZE = Symbol( `camelize` );245 const SET_BLOCK_TRACKING = Symbol( `setBlockTracking` );246 // Name mapping for runtime helpers that need to be imported from 'vue' in247 // generated code. Make sure these are correctly exported in the runtime!248 // Using `any` here because TS doesn't allow symbols as index type.249 const helperNameMap = {250 [FRAGMENT]: `Fragment`,251 [PORTAL]: `Portal`,252 [SUSPENSE]: `Suspense`,253 [OPEN_BLOCK]: `openBlock`,254 [CREATE_BLOCK]: `createBlock`,255 [CREATE_VNODE]: `createVNode`,256 [CREATE_COMMENT]: `createCommentVNode`,257 [CREATE_TEXT]: `createTextVNode`,258 [RESOLVE_COMPONENT]: `resolveComponent`,259 [RESOLVE_DYNAMIC_COMPONENT]: `resolveDynamicComponent`,260 [RESOLVE_DIRECTIVE]: `resolveDirective`,261 [WITH_DIRECTIVES]: `withDirectives`,262 [RENDER_LIST]: `renderList`,263 [RENDER_SLOT]: `renderSlot`,264 [CREATE_SLOTS]: `createSlots`,265 [TO_STRING]: `toString`,266 [MERGE_PROPS]: `mergeProps`,267 [TO_HANDLERS]: `toHandlers`,268 [CAMELIZE]: `camelize`,269 [SET_BLOCK_TRACKING]: `setBlockTracking`270 };271 function registerRuntimeHelpers(helpers) {272 Object.getOwnPropertySymbols(helpers).forEach(s => {273 helperNameMap[s] = helpers[s];274 });275 }276 // cache node requires277 // lazy require dependencies so that they don't end up in rollup's dep graph278 // and thus can be tree-shaken in browser builds.279 let _parse;280 let _walk;281 function loadDep(name) {282 if (typeof process !== 'undefined' && isFunction(require)) {283 return require(name);284 }285 else {286 // This is only used when we are building a dev-only build of the compiler287 // which runs in the browser but also uses Node deps.288 return window._deps[name];289 }290 }291 const parseJS = (code, options) => {292 assert(!true, `Expression AST analysis can only be performed in non-browser builds.`);293 const parse = _parse || (_parse = loadDep('acorn').parse);294 return parse(code, options);295 };296 const walkJS = (ast, walker) => {297 assert(!true, `Expression AST analysis can only be performed in non-browser builds.`);298 const walk = _walk || (_walk = loadDep('estree-walker').walk);299 return walk(ast, walker);300 };301 const nonIdentifierRE = /^\d|[^\$\w]/;302 const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);303 const memberExpRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\[[^\]]+\])*$/;304 const isMemberExpression = (path) => memberExpRE.test(path);305 function getInnerRange(loc, offset, length) {306 assert(offset <= loc.source.length);307 const source = loc.source.substr(offset, length);308 const newLoc = {309 source,310 start: advancePositionWithClone(loc.start, loc.source, offset),311 end: loc.end312 };313 if (length != null) {314 assert(offset + length <= loc.source.length);315 newLoc.end = advancePositionWithClone(loc.start, loc.source, offset + length);316 }317 return newLoc;318 }319 function advancePositionWithClone(pos, source, numberOfCharacters = source.length) {320 return advancePositionWithMutation({ ...pos }, source, numberOfCharacters);321 }322 // advance by mutation without cloning (for performance reasons), since this323 // gets called a lot in the parser324 function advancePositionWithMutation(pos, source, numberOfCharacters = source.length) {325 let linesCount = 0;326 let lastNewLinePos = -1;327 for (let i = 0; i < numberOfCharacters; i++) {328 if (source.charCodeAt(i) === 10 /* newline char code */) {329 linesCount++;330 lastNewLinePos = i;331 }332 }333 pos.offset += numberOfCharacters;334 pos.line += linesCount;335 pos.column =336 lastNewLinePos === -1337 ? pos.column + numberOfCharacters338 : Math.max(1, numberOfCharacters - lastNewLinePos);339 return pos;340 }341 function assert(condition, msg) {342 /* istanbul ignore if */343 if (!condition) {344 throw new Error(msg || `unexpected compiler condition`);345 }346 }347 function findDir(node, name, allowEmpty = false) {348 for (let i = 0; i < node.props.length; i++) {349 const p = node.props[i];350 if (p.type === 7 /* DIRECTIVE */ &&351 (allowEmpty || p.exp) &&352 (isString(name) ? p.name === name : name.test(p.name))) {353 return p;354 }355 }356 }357 function findProp(node, name, dynamicOnly = false) {358 for (let i = 0; i < node.props.length; i++) {359 const p = node.props[i];360 if (p.type === 6 /* ATTRIBUTE */) {361 if (dynamicOnly)362 continue;363 if (p.name === name && p.value) {364 return p;365 }366 }367 else if (p.name === 'bind' &&368 p.arg &&369 p.arg.type === 4 /* SIMPLE_EXPRESSION */ &&370 p.arg.isStatic &&371 p.arg.content === name &&372 p.exp) {373 return p;374 }375 }376 }377 function createBlockExpression(blockExp, context) {378 return createSequenceExpression([379 createCallExpression(context.helper(OPEN_BLOCK)),380 blockExp381 ]);382 }383 function isVSlot(p) {384 return p.type === 7 /* DIRECTIVE */ && p.name === 'slot';385 }386 function isTemplateNode(node) {387 return (node.type === 1 /* ELEMENT */ && node.tagType === 3 /* TEMPLATE */);388 }389 function isSlotOutlet(node) {390 return node.type === 1 /* ELEMENT */ && node.tagType === 2 /* SLOT */;391 }392 function injectProp(node, prop, context) {393 let propsWithInjection;394 const props = node.callee === RENDER_SLOT ? node.arguments[2] : node.arguments[1];395 if (props == null || isString(props)) {396 propsWithInjection = createObjectExpression([prop]);397 }398 else if (props.type === 13 /* JS_CALL_EXPRESSION */) {399 // merged props... add ours400 // only inject key to object literal if it's the first argument so that401 // if doesn't override user provided keys402 const first = props.arguments[0];403 if (!isString(first) && first.type === 14 /* JS_OBJECT_EXPRESSION */) {404 first.properties.unshift(prop);405 }406 else {407 props.arguments.unshift(createObjectExpression([prop]));408 }409 propsWithInjection = props;410 }411 else if (props.type === 14 /* JS_OBJECT_EXPRESSION */) {412 props.properties.unshift(prop);413 propsWithInjection = props;414 }415 else {416 // single v-bind with expression, return a merged replacement417 propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [418 createObjectExpression([prop]),419 props420 ]);421 }422 if (node.callee === RENDER_SLOT) {423 node.arguments[2] = propsWithInjection;424 }425 else {426 node.arguments[1] = propsWithInjection;427 }428 }429 function toValidAssetId(name, type) {430 return `_${type}_${name.replace(/[^\w]/g, '_')}`;431 }432 // Check if a node contains expressions that reference current context scope ids433 function hasScopeRef(node, ids) {434 if (!node || Object.keys(ids).length === 0) {435 return false;436 }437 switch (node.type) {438 case 1 /* ELEMENT */:439 for (let i = 0; i < node.props.length; i++) {440 const p = node.props[i];441 if (p.type === 7 /* DIRECTIVE */ &&442 (hasScopeRef(p.arg, ids) || hasScopeRef(p.exp, ids))) {443 return true;444 }445 }446 return node.children.some(c => hasScopeRef(c, ids));447 case 11 /* FOR */:448 if (hasScopeRef(node.source, ids)) {449 return true;450 }451 return node.children.some(c => hasScopeRef(c, ids));452 case 9 /* IF */:453 return node.branches.some(b => hasScopeRef(b, ids));454 case 10 /* IF_BRANCH */:455 if (hasScopeRef(node.condition, ids)) {456 return true;457 }458 return node.children.some(c => hasScopeRef(c, ids));459 case 4 /* SIMPLE_EXPRESSION */:460 return (!node.isStatic &&461 isSimpleIdentifier(node.content) &&462 !!ids[node.content]);463 case 8 /* COMPOUND_EXPRESSION */:464 return node.children.some(c => isObject(c) && hasScopeRef(c, ids));465 case 5 /* INTERPOLATION */:466 case 12 /* TEXT_CALL */:467 return hasScopeRef(node.content, ids);468 case 2 /* TEXT */:469 case 3 /* COMMENT */:470 return false;471 default:472 return false;473 }474 }475 const defaultParserOptions = {476 delimiters: [`{{`, `}}`],477 getNamespace: () => 0 /* HTML */,478 getTextMode: () => 0 /* DATA */,479 isVoidTag: NO,480 isPreTag: NO,481 isCustomElement: NO,482 namedCharacterReferences: {483 'gt;': '>',484 'lt;': '<',485 'amp;': '&',486 'apos;': "'",487 'quot;': '"'488 },489 onError: defaultOnError490 };491 function parse(content, options = {}) {492 const context = createParserContext(content, options);493 const start = getCursor(context);494 return {495 type: 0 /* ROOT */,496 children: parseChildren(context, 0 /* DATA */, []),497 helpers: [],498 components: [],499 directives: [],500 hoists: [],501 cached: 0,502 codegenNode: undefined,503 loc: getSelection(context, start)504 };505 }506 function createParserContext(content, options) {507 return {508 options: {509 ...defaultParserOptions,510 ...options511 },512 column: 1,513 line: 1,514 offset: 0,515 originalSource: content,516 source: content,517 maxCRNameLength: Object.keys(options.namedCharacterReferences ||518 defaultParserOptions.namedCharacterReferences).reduce((max, name) => Math.max(max, name.length), 0),519 inPre: false520 };521 }522 function parseChildren(context, mode, ancestors) {523 const parent = last(ancestors);524 const ns = parent ? parent.ns : 0 /* HTML */;525 const nodes = [];526 while (!isEnd(context, mode, ancestors)) {527 assert(context.source.length > 0);528 const s = context.source;529 let node = undefined;530 if (!context.inPre && startsWith(s, context.options.delimiters[0])) {531 // '{{'532 node = parseInterpolation(context, mode);533 }534 else if (mode === 0 /* DATA */ && s[0] === '<') {535 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state536 if (s.length === 1) {537 emitError(context, 8 /* EOF_BEFORE_TAG_NAME */, 1);538 }539 else if (s[1] === '!') {540 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state541 if (startsWith(s, '<!--')) {542 node = parseComment(context);543 }544 else if (startsWith(s, '<!DOCTYPE')) {545 // Ignore DOCTYPE by a limitation.546 node = parseBogusComment(context);547 }548 else if (startsWith(s, '<![CDATA[')) {549 if (ns !== 0 /* HTML */) {550 node = parseCDATA(context, ancestors);551 }552 else {553 emitError(context, 2 /* CDATA_IN_HTML_CONTENT */);554 node = parseBogusComment(context);555 }556 }557 else {558 emitError(context, 14 /* INCORRECTLY_OPENED_COMMENT */);559 node = parseBogusComment(context);560 }561 }562 else if (s[1] === '/') {563 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state564 if (s.length === 2) {565 emitError(context, 8 /* EOF_BEFORE_TAG_NAME */, 2);566 }567 else if (s[2] === '>') {568 emitError(context, 17 /* MISSING_END_TAG_NAME */, 2);569 advanceBy(context, 3);570 continue;571 }572 else if (/[a-z]/i.test(s[2])) {573 emitError(context, 31 /* X_INVALID_END_TAG */);574 parseTag(context, 1 /* End */, parent);575 continue;576 }577 else {578 emitError(context, 15 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);579 node = parseBogusComment(context);580 }581 }582 else if (/[a-z]/i.test(s[1])) {583 node = parseElement(context, ancestors);584 }585 else if (s[1] === '?') {586 emitError(context, 28 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);587 node = parseBogusComment(context);588 }589 else {590 emitError(context, 15 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);591 }592 }593 if (!node) {594 node = parseText(context, mode);595 }596 if (Array.isArray(node)) {597 for (let i = 0; i < node.length; i++) {598 pushNode(nodes, node[i]);599 }600 }601 else {602 pushNode(nodes, node);603 }604 }605 // Whitespace management for more efficient output606 // (same as v2 whitespance: 'condense')607 let removedWhitespace = false;608 if (!parent || !context.options.isPreTag(parent.tag)) {609 for (let i = 0; i < nodes.length; i++) {610 const node = nodes[i];611 if (node.type === 2 /* TEXT */) {612 if (!node.content.trim()) {613 const prev = nodes[i - 1];614 const next = nodes[i + 1];615 // If:616 // - the whitespace is the first or last node, or:617 // - the whitespace is adjacent to a comment, or:618 // - the whitespace is between two elements AND contains newline619 // Then the whitespace is ignored.620 if (!prev ||621 !next ||622 prev.type === 3 /* COMMENT */ ||623 next.type === 3 /* COMMENT */ ||624 (prev.type === 1 /* ELEMENT */ &&625 next.type === 1 /* ELEMENT */ &&626 /[\r\n]/.test(node.content))) {627 removedWhitespace = true;628 nodes[i] = null;629 }630 else {631 // Otherwise, condensed consecutive whitespace inside the text down to632 // a single space633 node.content = ' ';634 }635 }636 else {637 node.content = node.content.replace(/\s+/g, ' ');638 }639 }640 }641 }642 return removedWhitespace ? nodes.filter(node => node !== null) : nodes;643 }644 function pushNode(nodes, node) {645 if (node.type === 2 /* TEXT */) {646 const prev = last(nodes);647 // Merge if both this and the previous node are text and those are648 // consecutive. This happens for cases like "a < b".649 if (prev &&650 prev.type === 2 /* TEXT */ &&651 prev.loc.end.offset === node.loc.start.offset) {652 prev.content += node.content;653 prev.loc.end = node.loc.end;654 prev.loc.source += node.loc.source;655 return;656 }657 }658 nodes.push(node);659 }660 function parseCDATA(context, ancestors) {661 662 assert(last(ancestors) == null || last(ancestors).ns !== 0 /* HTML */);663 assert(startsWith(context.source, '<![CDATA['));664 advanceBy(context, 9);665 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);666 if (context.source.length === 0) {667 emitError(context, 9 /* EOF_IN_CDATA */);668 }669 else {670 assert(startsWith(context.source, ']]>'));671 advanceBy(context, 3);672 }673 return nodes;674 }675 function parseComment(context) {676 assert(startsWith(context.source, '<!--'));677 const start = getCursor(context);678 let content;679 // Regular comment.680 const match = /--(\!)?>/.exec(context.source);681 if (!match) {682 content = context.source.slice(4);683 advanceBy(context, context.source.length);684 emitError(context, 10 /* EOF_IN_COMMENT */);685 }686 else {687 if (match.index <= 3) {688 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);689 }690 if (match[1]) {691 emitError(context, 13 /* INCORRECTLY_CLOSED_COMMENT */);692 }693 content = context.source.slice(4, match.index);694 // Advancing with reporting nested comments.695 const s = context.source.slice(0, match.index);696 let prevIndex = 1, nestedIndex = 0;697 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {698 advanceBy(context, nestedIndex - prevIndex + 1);699 if (nestedIndex + 4 < s.length) {700 emitError(context, 20 /* NESTED_COMMENT */);701 }702 prevIndex = nestedIndex + 1;703 }704 advanceBy(context, match.index + match[0].length - prevIndex + 1);705 }706 return {707 type: 3 /* COMMENT */,708 content,709 loc: getSelection(context, start)710 };711 }712 function parseBogusComment(context) {713 assert(/^<(?:[\!\?]|\/[^a-z>])/i.test(context.source));714 const start = getCursor(context);715 const contentStart = context.source[1] === '?' ? 1 : 2;716 let content;717 const closeIndex = context.source.indexOf('>');718 if (closeIndex === -1) {719 content = context.source.slice(contentStart);720 advanceBy(context, context.source.length);721 }722 else {723 content = context.source.slice(contentStart, closeIndex);724 advanceBy(context, closeIndex + 1);725 }726 return {727 type: 3 /* COMMENT */,728 content,729 loc: getSelection(context, start)730 };731 }732 function parseElement(context, ancestors) {733 assert(/^<[a-z]/i.test(context.source));734 // Start tag.735 const wasInPre = context.inPre;736 const parent = last(ancestors);737 const element = parseTag(context, 0 /* Start */, parent);738 const isPreBoundary = context.inPre && !wasInPre;739 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {740 return element;741 }742 // Children.743 ancestors.push(element);744 const mode = context.options.getTextMode(element.tag, element.ns);745 const children = parseChildren(context, mode, ancestors);746 ancestors.pop();747 element.children = children;748 // End tag.749 if (startsWithEndTagOpen(context.source, element.tag)) {750 parseTag(context, 1 /* End */, parent);751 }752 else {753 emitError(context, 32 /* X_MISSING_END_TAG */);754 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {755 const first = children[0];756 if (first && startsWith(first.loc.source, '<!--')) {757 emitError(context, 11 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);758 }759 }760 }761 element.loc = getSelection(context, element.loc.start);762 if (isPreBoundary) {763 context.inPre = false;764 }765 return element;766 }767 /**768 * Parse a tag (E.g. `<div id=a>`) with that type (start tag or end tag).769 */770 function parseTag(context, type, parent) {771 assert(/^<\/?[a-z]/i.test(context.source));772 773 assert(type === (startsWith(context.source, '</') ? 1 /* End */ : 0 /* Start */));774 // Tag open.775 const start = getCursor(context);776 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);777 const tag = match[1];778 const ns = context.options.getNamespace(tag, parent);779 advanceBy(context, match[0].length);780 advanceSpaces(context);781 // save current state in case we need to re-parse attributes with v-pre782 const cursor = getCursor(context);783 const currentSource = context.source;784 // Attributes.785 let props = parseAttributes(context, type);786 // check v-pre787 if (!context.inPre &&788 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {789 context.inPre = true;790 // reset context791 extend(context, cursor);792 context.source = currentSource;793 // re-parse attrs and filter out v-pre itself794 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');795 }796 // Tag close.797 let isSelfClosing = false;798 if (context.source.length === 0) {799 emitError(context, 12 /* EOF_IN_TAG */);800 }801 else {802 isSelfClosing = startsWith(context.source, '/>');803 if (type === 1 /* End */ && isSelfClosing) {804 emitError(context, 7 /* END_TAG_WITH_TRAILING_SOLIDUS */);805 }806 advanceBy(context, isSelfClosing ? 2 : 1);807 }808 let tagType = 0 /* ELEMENT */;809 if (!context.inPre && !context.options.isCustomElement(tag)) {810 if (context.options.isNativeTag) {811 if (!context.options.isNativeTag(tag))812 tagType = 1 /* COMPONENT */;813 }814 else {815 if (/^[A-Z]/.test(tag))816 tagType = 1 /* COMPONENT */;817 }818 if (tag === 'slot')819 tagType = 2 /* SLOT */;820 else if (tag === 'template')821 tagType = 3 /* TEMPLATE */;822 else if (tag === 'portal' || tag === 'Portal')823 tagType = 4 /* PORTAL */;824 else if (tag === 'suspense' || tag === 'Suspense')825 tagType = 5 /* SUSPENSE */;826 }827 return {828 type: 1 /* ELEMENT */,829 ns,830 tag,831 tagType,832 props,833 isSelfClosing,834 children: [],835 loc: getSelection(context, start),836 codegenNode: undefined // to be created during transform phase837 };838 }839 function parseAttributes(context, type) {840 const props = [];841 const attributeNames = new Set();842 while (context.source.length > 0 &&843 !startsWith(context.source, '>') &&844 !startsWith(context.source, '/>')) {845 if (startsWith(context.source, '/')) {846 emitError(context, 29 /* UNEXPECTED_SOLIDUS_IN_TAG */);847 advanceBy(context, 1);848 advanceSpaces(context);849 continue;850 }851 if (type === 1 /* End */) {852 emitError(context, 6 /* END_TAG_WITH_ATTRIBUTES */);853 }854 const attr = parseAttribute(context, attributeNames);855 if (type === 0 /* Start */) {856 props.push(attr);857 }858 if (/^[^\t\r\n\f />]/.test(context.source)) {859 emitError(context, 19 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);860 }861 advanceSpaces(context);862 }863 return props;864 }865 function parseAttribute(context, nameSet) {866 assert(/^[^\t\r\n\f />]/.test(context.source));867 // Name.868 const start = getCursor(context);869 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);870 const name = match[0];871 if (nameSet.has(name)) {872 emitError(context, 5 /* DUPLICATE_ATTRIBUTE */);873 }874 nameSet.add(name);875 if (name[0] === '=') {876 emitError(context, 26 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);877 }878 {879 const pattern = /["'<]/g;880 let m;881 while ((m = pattern.exec(name)) !== null) {882 emitError(context, 24 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);883 }884 }885 advanceBy(context, name.length);886 // Value887 let value = undefined;888 if (/^[\t\r\n\f ]*=/.test(context.source)) {889 advanceSpaces(context);890 advanceBy(context, 1);891 advanceSpaces(context);892 value = parseAttributeValue(context);893 if (!value) {894 emitError(context, 16 /* MISSING_ATTRIBUTE_VALUE */);895 }896 }897 const loc = getSelection(context, start);898 if (!context.inPre && /^(v-|:|@|#)/.test(name)) {899 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^@|^#)([^\.]+))?(.+)?$/i.exec(name);900 let arg;901 if (match[2]) {902 const startOffset = name.split(match[2], 2).shift().length;903 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length));904 let content = match[2];905 let isStatic = true;906 if (content.startsWith('[')) {907 isStatic = false;908 if (!content.endsWith(']')) {909 emitError(context, 34 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);910 }911 content = content.substr(1, content.length - 2);912 }913 arg = {914 type: 4 /* SIMPLE_EXPRESSION */,915 content,916 isStatic,917 isConstant: isStatic,918 loc919 };920 }921 if (value && value.isQuoted) {922 const valueLoc = value.loc;923 valueLoc.start.offset++;924 valueLoc.start.column++;925 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);926 valueLoc.source = valueLoc.source.slice(1, -1);927 }928 return {929 type: 7 /* DIRECTIVE */,930 name: match[1] ||931 (startsWith(name, ':')932 ? 'bind'933 : startsWith(name, '@')934 ? 'on'935 : 'slot'),936 exp: value && {937 type: 4 /* SIMPLE_EXPRESSION */,938 content: value.content,939 isStatic: false,940 // Treat as non-constant by default. This can be potentially set to941 // true by `transformExpression` to make it eligible for hoisting.942 isConstant: false,943 loc: value.loc944 },945 arg,946 modifiers: match[3] ? match[3].substr(1).split('.') : [],947 loc948 };949 }950 return {951 type: 6 /* ATTRIBUTE */,952 name,953 value: value && {954 type: 2 /* TEXT */,955 content: value.content,956 loc: value.loc957 },958 loc959 };960 }961 function parseAttributeValue(context) {962 const start = getCursor(context);963 let content;964 const quote = context.source[0];965 const isQuoted = quote === `"` || quote === `'`;966 if (isQuoted) {967 // Quoted value.968 advanceBy(context, 1);969 const endIndex = context.source.indexOf(quote);970 if (endIndex === -1) {971 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);972 }973 else {974 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);975 advanceBy(context, 1);976 }977 }978 else {979 // Unquoted980 const match = /^[^\t\r\n\f >]+/.exec(context.source);981 if (!match) {982 return undefined;983 }984 let unexpectedChars = /["'<=`]/g;985 let m;986 while ((m = unexpectedChars.exec(match[0])) !== null) {987 emitError(context, 25 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);988 }989 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);990 }991 return { content, isQuoted, loc: getSelection(context, start) };992 }993 function parseInterpolation(context, mode) {994 const [open, close] = context.options.delimiters;995 assert(startsWith(context.source, open));996 const closeIndex = context.source.indexOf(close, open.length);997 if (closeIndex === -1) {998 emitError(context, 33 /* X_MISSING_INTERPOLATION_END */);999 return undefined;1000 }1001 const start = getCursor(context);1002 advanceBy(context, open.length);1003 const innerStart = getCursor(context);1004 const innerEnd = getCursor(context);1005 const rawContentLength = closeIndex - open.length;1006 const rawContent = context.source.slice(0, rawContentLength);1007 const preTrimContent = parseTextData(context, rawContentLength, mode);1008 const content = preTrimContent.trim();1009 const startOffset = preTrimContent.indexOf(content);1010 if (startOffset > 0) {1011 advancePositionWithMutation(innerStart, rawContent, startOffset);1012 }1013 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);1014 advancePositionWithMutation(innerEnd, rawContent, endOffset);1015 advanceBy(context, close.length);1016 return {1017 type: 5 /* INTERPOLATION */,1018 content: {1019 type: 4 /* SIMPLE_EXPRESSION */,1020 isStatic: false,1021 // Set `isConstant` to false by default and will decide in transformExpression1022 isConstant: false,1023 content,1024 loc: getSelection(context, innerStart, innerEnd)1025 },1026 loc: getSelection(context, start)1027 };1028 }1029 function parseText(context, mode) {1030 assert(context.source.length > 0);1031 const [open] = context.options.delimiters;1032 // TODO could probably use some perf optimization1033 const endIndex = Math.min(...[1034 context.source.indexOf('<', 1),1035 context.source.indexOf(open, 1),1036 mode === 3 /* CDATA */ ? context.source.indexOf(']]>') : -1,1037 context.source.length1038 ].filter(n => n !== -1));1039 assert(endIndex > 0);1040 const start = getCursor(context);1041 const content = parseTextData(context, endIndex, mode);1042 return {1043 type: 2 /* TEXT */,1044 content,1045 loc: getSelection(context, start)1046 };1047 }1048 /**1049 * Get text data with a given length from the current location.1050 * This translates HTML entities in the text data.1051 */1052 function parseTextData(context, length, mode) {1053 if (mode === 2 /* RAWTEXT */ || mode === 3 /* CDATA */) {1054 const text = context.source.slice(0, length);1055 advanceBy(context, length);1056 return text;1057 }1058 // DATA or RCDATA. Entity decoding required.1059 const end = context.offset + length;1060 let text = '';1061 while (context.offset < end) {1062 const head = /&(?:#x?)?/i.exec(context.source);1063 if (!head || context.offset + head.index >= end) {1064 const remaining = end - context.offset;1065 text += context.source.slice(0, remaining);1066 advanceBy(context, remaining);1067 break;1068 }1069 // Advance to the "&".1070 text += context.source.slice(0, head.index);1071 advanceBy(context, head.index);1072 if (head[0] === '&') {1073 // Named character reference.1074 let name = '', value = undefined;1075 if (/[0-9a-z]/i.test(context.source[1])) {1076 for (let length = context.maxCRNameLength; !value && length > 0; --length) {1077 name = context.source.substr(1, length);1078 value = context.options.namedCharacterReferences[name];1079 }1080 if (value) {1081 const semi = name.endsWith(';');1082 if (mode === 4 /* ATTRIBUTE_VALUE */ &&1083 !semi &&1084 /[=a-z0-9]/i.test(context.source[1 + name.length] || '')) {1085 text += '&';1086 text += name;1087 advanceBy(context, 1 + name.length);1088 }1089 else {1090 text += value;1091 advanceBy(context, 1 + name.length);1092 if (!semi) {1093 emitError(context, 18 /* MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE */);1094 }1095 }1096 }1097 else {1098 emitError(context, 30 /* UNKNOWN_NAMED_CHARACTER_REFERENCE */);1099 text += '&';1100 text += name;1101 advanceBy(context, 1 + name.length);1102 }1103 }1104 else {1105 text += '&';1106 advanceBy(context, 1);1107 }1108 }1109 else {1110 // Numeric character reference.1111 const hex = head[0] === '&#x';1112 const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/;1113 const body = pattern.exec(context.source);1114 if (!body) {1115 text += head[0];1116 emitError(context, 1 /* ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE */);1117 advanceBy(context, head[0].length);1118 }1119 else {1120 // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state1121 let cp = Number.parseInt(body[1], hex ? 16 : 10);1122 if (cp === 0) {1123 emitError(context, 22 /* NULL_CHARACTER_REFERENCE */);1124 cp = 0xfffd;1125 }1126 else if (cp > 0x10ffff) {1127 emitError(context, 3 /* CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE */);1128 cp = 0xfffd;1129 }1130 else if (cp >= 0xd800 && cp <= 0xdfff) {1131 emitError(context, 23 /* SURROGATE_CHARACTER_REFERENCE */);1132 cp = 0xfffd;1133 }1134 else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) {1135 emitError(context, 21 /* NONCHARACTER_CHARACTER_REFERENCE */);1136 }1137 else if ((cp >= 0x01 && cp <= 0x08) ||1138 cp === 0x0b ||1139 (cp >= 0x0d && cp <= 0x1f) ||1140 (cp >= 0x7f && cp <= 0x9f)) {1141 emitError(context, 4 /* CONTROL_CHARACTER_REFERENCE */);1142 cp = CCR_REPLACEMENTS[cp] || cp;1143 }1144 text += String.fromCodePoint(cp);1145 advanceBy(context, body[0].length);1146 if (!body[0].endsWith(';')) {1147 emitError(context, 18 /* MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE */);1148 }1149 }1150 }1151 }1152 return text;1153 }1154 function getCursor(context) {1155 const { column, line, offset } = context;1156 return { column, line, offset };1157 }1158 function getSelection(context, start, end) {1159 end = end || getCursor(context);1160 return {1161 start,1162 end,1163 source: context.originalSource.slice(start.offset, end.offset)1164 };1165 }1166 function last(xs) {1167 return xs[xs.length - 1];1168 }1169 function startsWith(source, searchString) {1170 return source.startsWith(searchString);1171 }1172 function advanceBy(context, numberOfCharacters) {1173 const { source } = context;1174 assert(numberOfCharacters <= source.length);1175 advancePositionWithMutation(context, source, numberOfCharacters);1176 context.source = source.slice(numberOfCharacters);1177 }1178 function advanceSpaces(context) {1179 const match = /^[\t\r\n\f ]+/.exec(context.source);1180 if (match) {1181 advanceBy(context, match[0].length);1182 }1183 }1184 function getNewPosition(context, start, numberOfCharacters) {1185 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);1186 }1187 function emitError(context, code, offset) {1188 const loc = getCursor(context);1189 if (offset) {1190 loc.offset += offset;1191 loc.column += offset;1192 }1193 context.options.onError(createCompilerError(code, {1194 start: loc,1195 end: loc,1196 source: ''1197 }));1198 }1199 function isEnd(context, mode, ancestors) {1200 const s = context.source;1201 switch (mode) {1202 case 0 /* DATA */:1203 if (startsWith(s, '</')) {1204 //TODO: probably bad performance1205 for (let i = ancestors.length - 1; i >= 0; --i) {1206 if (startsWithEndTagOpen(s, ancestors[i].tag)) {1207 return true;1208 }1209 }1210 }1211 break;1212 case 1 /* RCDATA */:1213 case 2 /* RAWTEXT */: {1214 const parent = last(ancestors);1215 if (parent && startsWithEndTagOpen(s, parent.tag)) {1216 return true;1217 }1218 break;1219 }1220 case 3 /* CDATA */:1221 if (startsWith(s, ']]>')) {1222 return true;1223 }1224 break;1225 }1226 return !s;1227 }1228 function startsWithEndTagOpen(source, tag) {1229 return (startsWith(source, '</') &&1230 source.substr(2, tag.length).toLowerCase() === tag.toLowerCase() &&1231 /[\t\n\f />]/.test(source[2 + tag.length] || '>'));1232 }1233 // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state1234 const CCR_REPLACEMENTS = {1235 0x80: 0x20ac,1236 0x82: 0x201a,1237 0x83: 0x0192,1238 0x84: 0x201e,1239 0x85: 0x2026,1240 0x86: 0x2020,1241 0x87: 0x2021,1242 0x88: 0x02c6,1243 0x89: 0x2030,1244 0x8a: 0x0160,1245 0x8b: 0x2039,1246 0x8c: 0x0152,1247 0x8e: 0x017d,1248 0x91: 0x2018,1249 0x92: 0x2019,1250 0x93: 0x201c,1251 0x94: 0x201d,1252 0x95: 0x2022,1253 0x96: 0x2013,1254 0x97: 0x2014,1255 0x98: 0x02dc,1256 0x99: 0x2122,1257 0x9a: 0x0161,1258 0x9b: 0x203a,1259 0x9c: 0x0153,1260 0x9e: 0x017e,1261 0x9f: 0x01781262 };1263 function hoistStatic(root, context) {1264 walk(root.children, context, new Map(), isSingleElementRoot(root, root.children[0]));1265 }1266 function isSingleElementRoot(root, child) {1267 const { children } = root;1268 return (children.length === 1 &&1269 child.type === 1 /* ELEMENT */ &&1270 !isSlotOutlet(child));1271 }1272 function walk(children, context, resultCache, doNotHoistNode = false) {1273 for (let i = 0; i < children.length; i++) {1274 const child = children[i];1275 // only plain elements are eligible for hoisting.1276 if (child.type === 1 /* ELEMENT */ &&1277 child.tagType === 0 /* ELEMENT */) {1278 if (!doNotHoistNode && isStaticNode(child, resultCache)) {1279 // whole tree is static1280 child.codegenNode = context.hoist(child.codegenNode);1281 continue;1282 }1283 else {1284 // node may contain dynamic children, but its props may be eligible for1285 // hoisting.1286 const codegenNode = child.codegenNode;1287 if (codegenNode.type === 13 /* JS_CALL_EXPRESSION */) {1288 const flag = getPatchFlag(codegenNode);1289 if ((!flag ||1290 flag === 32 /* NEED_PATCH */ ||1291 flag === 1 /* TEXT */) &&1292 !hasDynamicKeyOrRef(child) &&1293 !hasCachedProps()) {1294 const props = getNodeProps(child);1295 if (props && props !== `null`) {1296 getVNodeCall(codegenNode).arguments[1] = context.hoist(props);1297 }1298 }1299 }1300 }1301 }1302 if (child.type === 1 /* ELEMENT */) {1303 walk(child.children, context, resultCache);1304 }1305 else if (child.type === 11 /* FOR */) {1306 // Do not hoist v-for single child because it has to be a block1307 walk(child.children, context, resultCache, child.children.length === 1);1308 }1309 else if (child.type === 9 /* IF */) {1310 for (let i = 0; i < child.branches.length; i++) {1311 const branchChildren = child.branches[i].children;1312 // Do not hoist v-if single child because it has to be a block1313 walk(branchChildren, context, resultCache, branchChildren.length === 1);1314 }1315 }1316 }1317 }1318 function isStaticNode(node, resultCache = new Map()) {1319 switch (node.type) {1320 case 1 /* ELEMENT */:1321 if (node.tagType !== 0 /* ELEMENT */) {1322 return false;1323 }1324 const cached = resultCache.get(node);1325 if (cached !== undefined) {1326 return cached;1327 }1328 const codegenNode = node.codegenNode;1329 if (codegenNode.type !== 13 /* JS_CALL_EXPRESSION */) {1330 return false;1331 }1332 const flag = getPatchFlag(codegenNode);1333 if (!flag && !hasDynamicKeyOrRef(node) && !hasCachedProps()) {1334 // element self is static. check its children.1335 for (let i = 0; i < node.children.length; i++) {1336 if (!isStaticNode(node.children[i], resultCache)) {1337 resultCache.set(node, false);1338 return false;1339 }1340 }1341 resultCache.set(node, true);1342 return true;1343 }1344 else {1345 resultCache.set(node, false);1346 return false;1347 }1348 case 2 /* TEXT */:1349 case 3 /* COMMENT */:1350 return true;1351 case 9 /* IF */:1352 case 11 /* FOR */:1353 return false;1354 case 5 /* INTERPOLATION */:1355 case 12 /* TEXT_CALL */:1356 return isStaticNode(node.content, resultCache);1357 case 4 /* SIMPLE_EXPRESSION */:1358 return node.isConstant;1359 case 8 /* COMPOUND_EXPRESSION */:1360 return node.children.every(child => {1361 return (isString(child) || isSymbol(child) || isStaticNode(child, resultCache));1362 });1363 default:1364 return false;1365 }1366 }1367 function hasDynamicKeyOrRef(node) {1368 return !!(findProp(node, 'key', true) || findProp(node, 'ref', true));1369 }1370 function hasCachedProps(node) {1371 {1372 return false;1373 }1374 }1375 function getNodeProps(node) {1376 const codegenNode = node.codegenNode;1377 if (codegenNode.type === 13 /* JS_CALL_EXPRESSION */) {1378 return getVNodeArgAt(codegenNode, 1);1379 }1380 }1381 function getVNodeArgAt(node, index) {1382 return getVNodeCall(node).arguments[index];1383 }1384 function getVNodeCall(node) {1385 return node.callee === WITH_DIRECTIVES ? node.arguments[0] : node;1386 }1387 function getPatchFlag(node) {1388 const flag = getVNodeArgAt(node, 3);1389 return flag ? parseInt(flag, 10) : undefined;1390 }1391 function createTransformContext(root, { prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, onError = defaultOnError }) {1392 const context = {1393 root,1394 helpers: new Set(),1395 components: new Set(),1396 directives: new Set(),1397 hoists: [],1398 cached: 0,1399 identifiers: {},1400 scopes: {1401 vFor: 0,1402 vSlot: 0,1403 vPre: 0,1404 vOnce: 01405 },1406 prefixIdentifiers,1407 hoistStatic,1408 cacheHandlers,1409 nodeTransforms,1410 directiveTransforms,1411 onError,1412 parent: null,1413 currentNode: root,1414 childIndex: 0,1415 helper(name) {1416 context.helpers.add(name);1417 return name;1418 },1419 helperString(name) {1420 return ((context.prefixIdentifiers ? `` : `_`) +1421 helperNameMap[context.helper(name)]);1422 },1423 replaceNode(node) {1424 /* istanbul ignore if */1425 {1426 if (!context.currentNode) {1427 throw new Error(`Node being replaced is already removed.`);1428 }1429 if (!context.parent) {1430 throw new Error(`Cannot replace root node.`);1431 }1432 }1433 context.parent.children[context.childIndex] = context.currentNode = node;1434 },1435 removeNode(node) {1436 if ( !context.parent) {1437 throw new Error(`Cannot remove root node.`);1438 }1439 const list = context.parent.children;1440 const removalIndex = node1441 ? list.indexOf(node)1442 : context.currentNode1443 ? context.childIndex1444 : -1;1445 /* istanbul ignore if */1446 if ( removalIndex < 0) {1447 throw new Error(`node being removed is not a child of current parent`);1448 }1449 if (!node || node === context.currentNode) {1450 // current node removed1451 context.currentNode = null;1452 context.onNodeRemoved();1453 }1454 else {1455 // sibling node removed1456 if (context.childIndex > removalIndex) {1457 context.childIndex--;1458 context.onNodeRemoved();1459 }1460 }1461 context.parent.children.splice(removalIndex, 1);1462 },1463 onNodeRemoved: () => { },1464 addIdentifiers(exp) {1465 },1466 removeIdentifiers(exp) {1467 },1468 hoist(exp) {1469 context.hoists.push(exp);1470 return createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, true);1471 },1472 cache(exp, isVNode = false) {1473 return createCacheExpression(++context.cached, exp, isVNode);1474 }1475 };1476 return context;1477 }1478 function transform(root, options) {1479 const context = createTransformContext(root, options);1480 traverseNode(root, context);1481 if (options.hoistStatic) {1482 hoistStatic(root, context);1483 }1484 finalizeRoot(root, context);1485 }1486 function finalizeRoot(root, context) {1487 const { helper } = context;...
compiler-core.cjs.js
Source:compiler-core.cjs.js
...217 alternate,218 loc: locStub219 };220}221function createCacheExpression(index, value, isVNode = false) {222 return {223 type: 20 /* JS_CACHE_EXPRESSION */,224 index,225 value,226 isVNode,227 loc: locStub228 };229}230const FRAGMENT = Symbol( `Fragment` );231const PORTAL = Symbol( `Portal` );232const SUSPENSE = Symbol( `Suspense` );233const OPEN_BLOCK = Symbol( `openBlock` );234const CREATE_BLOCK = Symbol( `createBlock` );235const CREATE_VNODE = Symbol( `createVNode` );236const CREATE_COMMENT = Symbol( `createCommentVNode` );237const CREATE_TEXT = Symbol( `createTextVNode` );238const RESOLVE_COMPONENT = Symbol( `resolveComponent` );239const RESOLVE_DYNAMIC_COMPONENT = Symbol( `resolveDynamicComponent` );240const RESOLVE_DIRECTIVE = Symbol( `resolveDirective` );241const WITH_DIRECTIVES = Symbol( `withDirectives` );242const RENDER_LIST = Symbol( `renderList` );243const RENDER_SLOT = Symbol( `renderSlot` );244const CREATE_SLOTS = Symbol( `createSlots` );245const TO_STRING = Symbol( `toString` );246const MERGE_PROPS = Symbol( `mergeProps` );247const TO_HANDLERS = Symbol( `toHandlers` );248const CAMELIZE = Symbol( `camelize` );249const SET_BLOCK_TRACKING = Symbol( `setBlockTracking` );250// Name mapping for runtime helpers that need to be imported from 'vue' in251// generated code. Make sure these are correctly exported in the runtime!252// Using `any` here because TS doesn't allow symbols as index type.253const helperNameMap = {254 [FRAGMENT]: `Fragment`,255 [PORTAL]: `Portal`,256 [SUSPENSE]: `Suspense`,257 [OPEN_BLOCK]: `openBlock`,258 [CREATE_BLOCK]: `createBlock`,259 [CREATE_VNODE]: `createVNode`,260 [CREATE_COMMENT]: `createCommentVNode`,261 [CREATE_TEXT]: `createTextVNode`,262 [RESOLVE_COMPONENT]: `resolveComponent`,263 [RESOLVE_DYNAMIC_COMPONENT]: `resolveDynamicComponent`,264 [RESOLVE_DIRECTIVE]: `resolveDirective`,265 [WITH_DIRECTIVES]: `withDirectives`,266 [RENDER_LIST]: `renderList`,267 [RENDER_SLOT]: `renderSlot`,268 [CREATE_SLOTS]: `createSlots`,269 [TO_STRING]: `toString`,270 [MERGE_PROPS]: `mergeProps`,271 [TO_HANDLERS]: `toHandlers`,272 [CAMELIZE]: `camelize`,273 [SET_BLOCK_TRACKING]: `setBlockTracking`274};275function registerRuntimeHelpers(helpers) {276 Object.getOwnPropertySymbols(helpers).forEach(s => {277 helperNameMap[s] = helpers[s];278 });279}280// cache node requires281// lazy require dependencies so that they don't end up in rollup's dep graph282// and thus can be tree-shaken in browser builds.283let _parse;284let _walk;285function loadDep(name) {286 if (typeof process !== 'undefined' && isFunction(require)) {287 return require(name);288 }289 else {290 // This is only used when we are building a dev-only build of the compiler291 // which runs in the browser but also uses Node deps.292 return window._deps[name];293 }294}295const parseJS = (code, options) => {296 assert(!false, `Expression AST analysis can only be performed in non-browser builds.`);297 const parse = _parse || (_parse = loadDep('acorn').parse);298 return parse(code, options);299};300const walkJS = (ast, walker) => {301 assert(!false, `Expression AST analysis can only be performed in non-browser builds.`);302 const walk = _walk || (_walk = loadDep('estree-walker').walk);303 return walk(ast, walker);304};305const nonIdentifierRE = /^\d|[^\$\w]/;306const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);307const memberExpRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\[[^\]]+\])*$/;308const isMemberExpression = (path) => memberExpRE.test(path);309function getInnerRange(loc, offset, length) {310 assert(offset <= loc.source.length);311 const source = loc.source.substr(offset, length);312 const newLoc = {313 source,314 start: advancePositionWithClone(loc.start, loc.source, offset),315 end: loc.end316 };317 if (length != null) {318 assert(offset + length <= loc.source.length);319 newLoc.end = advancePositionWithClone(loc.start, loc.source, offset + length);320 }321 return newLoc;322}323function advancePositionWithClone(pos, source, numberOfCharacters = source.length) {324 return advancePositionWithMutation({ ...pos }, source, numberOfCharacters);325}326// advance by mutation without cloning (for performance reasons), since this327// gets called a lot in the parser328function advancePositionWithMutation(pos, source, numberOfCharacters = source.length) {329 let linesCount = 0;330 let lastNewLinePos = -1;331 for (let i = 0; i < numberOfCharacters; i++) {332 if (source.charCodeAt(i) === 10 /* newline char code */) {333 linesCount++;334 lastNewLinePos = i;335 }336 }337 pos.offset += numberOfCharacters;338 pos.line += linesCount;339 pos.column =340 lastNewLinePos === -1341 ? pos.column + numberOfCharacters342 : Math.max(1, numberOfCharacters - lastNewLinePos);343 return pos;344}345function assert(condition, msg) {346 /* istanbul ignore if */347 if (!condition) {348 throw new Error(msg || `unexpected compiler condition`);349 }350}351function findDir(node, name, allowEmpty = false) {352 for (let i = 0; i < node.props.length; i++) {353 const p = node.props[i];354 if (p.type === 7 /* DIRECTIVE */ &&355 (allowEmpty || p.exp) &&356 (isString(name) ? p.name === name : name.test(p.name))) {357 return p;358 }359 }360}361function findProp(node, name, dynamicOnly = false) {362 for (let i = 0; i < node.props.length; i++) {363 const p = node.props[i];364 if (p.type === 6 /* ATTRIBUTE */) {365 if (dynamicOnly)366 continue;367 if (p.name === name && p.value) {368 return p;369 }370 }371 else if (p.name === 'bind' &&372 p.arg &&373 p.arg.type === 4 /* SIMPLE_EXPRESSION */ &&374 p.arg.isStatic &&375 p.arg.content === name &&376 p.exp) {377 return p;378 }379 }380}381function createBlockExpression(blockExp, context) {382 return createSequenceExpression([383 createCallExpression(context.helper(OPEN_BLOCK)),384 blockExp385 ]);386}387function isVSlot(p) {388 return p.type === 7 /* DIRECTIVE */ && p.name === 'slot';389}390function isTemplateNode(node) {391 return (node.type === 1 /* ELEMENT */ && node.tagType === 3 /* TEMPLATE */);392}393function isSlotOutlet(node) {394 return node.type === 1 /* ELEMENT */ && node.tagType === 2 /* SLOT */;395}396function injectProp(node, prop, context) {397 let propsWithInjection;398 const props = node.callee === RENDER_SLOT ? node.arguments[2] : node.arguments[1];399 if (props == null || isString(props)) {400 propsWithInjection = createObjectExpression([prop]);401 }402 else if (props.type === 13 /* JS_CALL_EXPRESSION */) {403 // merged props... add ours404 // only inject key to object literal if it's the first argument so that405 // if doesn't override user provided keys406 const first = props.arguments[0];407 if (!isString(first) && first.type === 14 /* JS_OBJECT_EXPRESSION */) {408 first.properties.unshift(prop);409 }410 else {411 props.arguments.unshift(createObjectExpression([prop]));412 }413 propsWithInjection = props;414 }415 else if (props.type === 14 /* JS_OBJECT_EXPRESSION */) {416 props.properties.unshift(prop);417 propsWithInjection = props;418 }419 else {420 // single v-bind with expression, return a merged replacement421 propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [422 createObjectExpression([prop]),423 props424 ]);425 }426 if (node.callee === RENDER_SLOT) {427 node.arguments[2] = propsWithInjection;428 }429 else {430 node.arguments[1] = propsWithInjection;431 }432}433function toValidAssetId(name, type) {434 return `_${type}_${name.replace(/[^\w]/g, '_')}`;435}436// Check if a node contains expressions that reference current context scope ids437function hasScopeRef(node, ids) {438 if (!node || Object.keys(ids).length === 0) {439 return false;440 }441 switch (node.type) {442 case 1 /* ELEMENT */:443 for (let i = 0; i < node.props.length; i++) {444 const p = node.props[i];445 if (p.type === 7 /* DIRECTIVE */ &&446 (hasScopeRef(p.arg, ids) || hasScopeRef(p.exp, ids))) {447 return true;448 }449 }450 return node.children.some(c => hasScopeRef(c, ids));451 case 11 /* FOR */:452 if (hasScopeRef(node.source, ids)) {453 return true;454 }455 return node.children.some(c => hasScopeRef(c, ids));456 case 9 /* IF */:457 return node.branches.some(b => hasScopeRef(b, ids));458 case 10 /* IF_BRANCH */:459 if (hasScopeRef(node.condition, ids)) {460 return true;461 }462 return node.children.some(c => hasScopeRef(c, ids));463 case 4 /* SIMPLE_EXPRESSION */:464 return (!node.isStatic &&465 isSimpleIdentifier(node.content) &&466 !!ids[node.content]);467 case 8 /* COMPOUND_EXPRESSION */:468 return node.children.some(c => isObject(c) && hasScopeRef(c, ids));469 case 5 /* INTERPOLATION */:470 case 12 /* TEXT_CALL */:471 return hasScopeRef(node.content, ids);472 case 2 /* TEXT */:473 case 3 /* COMMENT */:474 return false;475 default:476 return false;477 }478}479const defaultParserOptions = {480 delimiters: [`{{`, `}}`],481 getNamespace: () => 0 /* HTML */,482 getTextMode: () => 0 /* DATA */,483 isVoidTag: NO,484 isPreTag: NO,485 isCustomElement: NO,486 namedCharacterReferences: {487 'gt;': '>',488 'lt;': '<',489 'amp;': '&',490 'apos;': "'",491 'quot;': '"'492 },493 onError: defaultOnError494};495function parse(content, options = {}) {496 const context = createParserContext(content, options);497 const start = getCursor(context);498 return {499 type: 0 /* ROOT */,500 children: parseChildren(context, 0 /* DATA */, []),501 helpers: [],502 components: [],503 directives: [],504 hoists: [],505 cached: 0,506 codegenNode: undefined,507 loc: getSelection(context, start)508 };509}510function createParserContext(content, options) {511 return {512 options: {513 ...defaultParserOptions,514 ...options515 },516 column: 1,517 line: 1,518 offset: 0,519 originalSource: content,520 source: content,521 maxCRNameLength: Object.keys(options.namedCharacterReferences ||522 defaultParserOptions.namedCharacterReferences).reduce((max, name) => Math.max(max, name.length), 0),523 inPre: false524 };525}526function parseChildren(context, mode, ancestors) {527 const parent = last(ancestors);528 const ns = parent ? parent.ns : 0 /* HTML */;529 const nodes = [];530 while (!isEnd(context, mode, ancestors)) {531 assert(context.source.length > 0);532 const s = context.source;533 let node = undefined;534 if (!context.inPre && startsWith(s, context.options.delimiters[0])) {535 // '{{'536 node = parseInterpolation(context, mode);537 }538 else if (mode === 0 /* DATA */ && s[0] === '<') {539 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state540 if (s.length === 1) {541 emitError(context, 8 /* EOF_BEFORE_TAG_NAME */, 1);542 }543 else if (s[1] === '!') {544 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state545 if (startsWith(s, '<!--')) {546 node = parseComment(context);547 }548 else if (startsWith(s, '<!DOCTYPE')) {549 // Ignore DOCTYPE by a limitation.550 node = parseBogusComment(context);551 }552 else if (startsWith(s, '<![CDATA[')) {553 if (ns !== 0 /* HTML */) {554 node = parseCDATA(context, ancestors);555 }556 else {557 emitError(context, 2 /* CDATA_IN_HTML_CONTENT */);558 node = parseBogusComment(context);559 }560 }561 else {562 emitError(context, 14 /* INCORRECTLY_OPENED_COMMENT */);563 node = parseBogusComment(context);564 }565 }566 else if (s[1] === '/') {567 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state568 if (s.length === 2) {569 emitError(context, 8 /* EOF_BEFORE_TAG_NAME */, 2);570 }571 else if (s[2] === '>') {572 emitError(context, 17 /* MISSING_END_TAG_NAME */, 2);573 advanceBy(context, 3);574 continue;575 }576 else if (/[a-z]/i.test(s[2])) {577 emitError(context, 31 /* X_INVALID_END_TAG */);578 parseTag(context, 1 /* End */, parent);579 continue;580 }581 else {582 emitError(context, 15 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);583 node = parseBogusComment(context);584 }585 }586 else if (/[a-z]/i.test(s[1])) {587 node = parseElement(context, ancestors);588 }589 else if (s[1] === '?') {590 emitError(context, 28 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);591 node = parseBogusComment(context);592 }593 else {594 emitError(context, 15 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);595 }596 }597 if (!node) {598 node = parseText(context, mode);599 }600 if (Array.isArray(node)) {601 for (let i = 0; i < node.length; i++) {602 pushNode(nodes, node[i]);603 }604 }605 else {606 pushNode(nodes, node);607 }608 }609 // Whitespace management for more efficient output610 // (same as v2 whitespance: 'condense')611 let removedWhitespace = false;612 if (!parent || !context.options.isPreTag(parent.tag)) {613 for (let i = 0; i < nodes.length; i++) {614 const node = nodes[i];615 if (node.type === 2 /* TEXT */) {616 if (!node.content.trim()) {617 const prev = nodes[i - 1];618 const next = nodes[i + 1];619 // If:620 // - the whitespace is the first or last node, or:621 // - the whitespace is adjacent to a comment, or:622 // - the whitespace is between two elements AND contains newline623 // Then the whitespace is ignored.624 if (!prev ||625 !next ||626 prev.type === 3 /* COMMENT */ ||627 next.type === 3 /* COMMENT */ ||628 (prev.type === 1 /* ELEMENT */ &&629 next.type === 1 /* ELEMENT */ &&630 /[\r\n]/.test(node.content))) {631 removedWhitespace = true;632 nodes[i] = null;633 }634 else {635 // Otherwise, condensed consecutive whitespace inside the text down to636 // a single space637 node.content = ' ';638 }639 }640 else {641 node.content = node.content.replace(/\s+/g, ' ');642 }643 }644 }645 }646 return removedWhitespace ? nodes.filter(node => node !== null) : nodes;647}648function pushNode(nodes, node) {649 if (node.type === 2 /* TEXT */) {650 const prev = last(nodes);651 // Merge if both this and the previous node are text and those are652 // consecutive. This happens for cases like "a < b".653 if (prev &&654 prev.type === 2 /* TEXT */ &&655 prev.loc.end.offset === node.loc.start.offset) {656 prev.content += node.content;657 prev.loc.end = node.loc.end;658 prev.loc.source += node.loc.source;659 return;660 }661 }662 nodes.push(node);663}664function parseCDATA(context, ancestors) {665 666 assert(last(ancestors) == null || last(ancestors).ns !== 0 /* HTML */);667 assert(startsWith(context.source, '<![CDATA['));668 advanceBy(context, 9);669 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);670 if (context.source.length === 0) {671 emitError(context, 9 /* EOF_IN_CDATA */);672 }673 else {674 assert(startsWith(context.source, ']]>'));675 advanceBy(context, 3);676 }677 return nodes;678}679function parseComment(context) {680 assert(startsWith(context.source, '<!--'));681 const start = getCursor(context);682 let content;683 // Regular comment.684 const match = /--(\!)?>/.exec(context.source);685 if (!match) {686 content = context.source.slice(4);687 advanceBy(context, context.source.length);688 emitError(context, 10 /* EOF_IN_COMMENT */);689 }690 else {691 if (match.index <= 3) {692 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);693 }694 if (match[1]) {695 emitError(context, 13 /* INCORRECTLY_CLOSED_COMMENT */);696 }697 content = context.source.slice(4, match.index);698 // Advancing with reporting nested comments.699 const s = context.source.slice(0, match.index);700 let prevIndex = 1, nestedIndex = 0;701 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {702 advanceBy(context, nestedIndex - prevIndex + 1);703 if (nestedIndex + 4 < s.length) {704 emitError(context, 20 /* NESTED_COMMENT */);705 }706 prevIndex = nestedIndex + 1;707 }708 advanceBy(context, match.index + match[0].length - prevIndex + 1);709 }710 return {711 type: 3 /* COMMENT */,712 content,713 loc: getSelection(context, start)714 };715}716function parseBogusComment(context) {717 assert(/^<(?:[\!\?]|\/[^a-z>])/i.test(context.source));718 const start = getCursor(context);719 const contentStart = context.source[1] === '?' ? 1 : 2;720 let content;721 const closeIndex = context.source.indexOf('>');722 if (closeIndex === -1) {723 content = context.source.slice(contentStart);724 advanceBy(context, context.source.length);725 }726 else {727 content = context.source.slice(contentStart, closeIndex);728 advanceBy(context, closeIndex + 1);729 }730 return {731 type: 3 /* COMMENT */,732 content,733 loc: getSelection(context, start)734 };735}736function parseElement(context, ancestors) {737 assert(/^<[a-z]/i.test(context.source));738 // Start tag.739 const wasInPre = context.inPre;740 const parent = last(ancestors);741 const element = parseTag(context, 0 /* Start */, parent);742 const isPreBoundary = context.inPre && !wasInPre;743 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {744 return element;745 }746 // Children.747 ancestors.push(element);748 const mode = context.options.getTextMode(element.tag, element.ns);749 const children = parseChildren(context, mode, ancestors);750 ancestors.pop();751 element.children = children;752 // End tag.753 if (startsWithEndTagOpen(context.source, element.tag)) {754 parseTag(context, 1 /* End */, parent);755 }756 else {757 emitError(context, 32 /* X_MISSING_END_TAG */);758 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {759 const first = children[0];760 if (first && startsWith(first.loc.source, '<!--')) {761 emitError(context, 11 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);762 }763 }764 }765 element.loc = getSelection(context, element.loc.start);766 if (isPreBoundary) {767 context.inPre = false;768 }769 return element;770}771/**772 * Parse a tag (E.g. `<div id=a>`) with that type (start tag or end tag).773 */774function parseTag(context, type, parent) {775 assert(/^<\/?[a-z]/i.test(context.source));776 777 assert(type === (startsWith(context.source, '</') ? 1 /* End */ : 0 /* Start */));778 // Tag open.779 const start = getCursor(context);780 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);781 const tag = match[1];782 const ns = context.options.getNamespace(tag, parent);783 advanceBy(context, match[0].length);784 advanceSpaces(context);785 // save current state in case we need to re-parse attributes with v-pre786 const cursor = getCursor(context);787 const currentSource = context.source;788 // Attributes.789 let props = parseAttributes(context, type);790 // check v-pre791 if (!context.inPre &&792 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {793 context.inPre = true;794 // reset context795 extend(context, cursor);796 context.source = currentSource;797 // re-parse attrs and filter out v-pre itself798 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');799 }800 // Tag close.801 let isSelfClosing = false;802 if (context.source.length === 0) {803 emitError(context, 12 /* EOF_IN_TAG */);804 }805 else {806 isSelfClosing = startsWith(context.source, '/>');807 if (type === 1 /* End */ && isSelfClosing) {808 emitError(context, 7 /* END_TAG_WITH_TRAILING_SOLIDUS */);809 }810 advanceBy(context, isSelfClosing ? 2 : 1);811 }812 let tagType = 0 /* ELEMENT */;813 if (!context.inPre && !context.options.isCustomElement(tag)) {814 if (context.options.isNativeTag) {815 if (!context.options.isNativeTag(tag))816 tagType = 1 /* COMPONENT */;817 }818 else {819 if (/^[A-Z]/.test(tag))820 tagType = 1 /* COMPONENT */;821 }822 if (tag === 'slot')823 tagType = 2 /* SLOT */;824 else if (tag === 'template')825 tagType = 3 /* TEMPLATE */;826 else if (tag === 'portal' || tag === 'Portal')827 tagType = 4 /* PORTAL */;828 else if (tag === 'suspense' || tag === 'Suspense')829 tagType = 5 /* SUSPENSE */;830 }831 return {832 type: 1 /* ELEMENT */,833 ns,834 tag,835 tagType,836 props,837 isSelfClosing,838 children: [],839 loc: getSelection(context, start),840 codegenNode: undefined // to be created during transform phase841 };842}843function parseAttributes(context, type) {844 const props = [];845 const attributeNames = new Set();846 while (context.source.length > 0 &&847 !startsWith(context.source, '>') &&848 !startsWith(context.source, '/>')) {849 if (startsWith(context.source, '/')) {850 emitError(context, 29 /* UNEXPECTED_SOLIDUS_IN_TAG */);851 advanceBy(context, 1);852 advanceSpaces(context);853 continue;854 }855 if (type === 1 /* End */) {856 emitError(context, 6 /* END_TAG_WITH_ATTRIBUTES */);857 }858 const attr = parseAttribute(context, attributeNames);859 if (type === 0 /* Start */) {860 props.push(attr);861 }862 if (/^[^\t\r\n\f />]/.test(context.source)) {863 emitError(context, 19 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);864 }865 advanceSpaces(context);866 }867 return props;868}869function parseAttribute(context, nameSet) {870 assert(/^[^\t\r\n\f />]/.test(context.source));871 // Name.872 const start = getCursor(context);873 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);874 const name = match[0];875 if (nameSet.has(name)) {876 emitError(context, 5 /* DUPLICATE_ATTRIBUTE */);877 }878 nameSet.add(name);879 if (name[0] === '=') {880 emitError(context, 26 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);881 }882 {883 const pattern = /["'<]/g;884 let m;885 while ((m = pattern.exec(name)) !== null) {886 emitError(context, 24 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);887 }888 }889 advanceBy(context, name.length);890 // Value891 let value = undefined;892 if (/^[\t\r\n\f ]*=/.test(context.source)) {893 advanceSpaces(context);894 advanceBy(context, 1);895 advanceSpaces(context);896 value = parseAttributeValue(context);897 if (!value) {898 emitError(context, 16 /* MISSING_ATTRIBUTE_VALUE */);899 }900 }901 const loc = getSelection(context, start);902 if (!context.inPre && /^(v-|:|@|#)/.test(name)) {903 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^@|^#)([^\.]+))?(.+)?$/i.exec(name);904 let arg;905 if (match[2]) {906 const startOffset = name.split(match[2], 2).shift().length;907 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length));908 let content = match[2];909 let isStatic = true;910 if (content.startsWith('[')) {911 isStatic = false;912 if (!content.endsWith(']')) {913 emitError(context, 34 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);914 }915 content = content.substr(1, content.length - 2);916 }917 arg = {918 type: 4 /* SIMPLE_EXPRESSION */,919 content,920 isStatic,921 isConstant: isStatic,922 loc923 };924 }925 if (value && value.isQuoted) {926 const valueLoc = value.loc;927 valueLoc.start.offset++;928 valueLoc.start.column++;929 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);930 valueLoc.source = valueLoc.source.slice(1, -1);931 }932 return {933 type: 7 /* DIRECTIVE */,934 name: match[1] ||935 (startsWith(name, ':')936 ? 'bind'937 : startsWith(name, '@')938 ? 'on'939 : 'slot'),940 exp: value && {941 type: 4 /* SIMPLE_EXPRESSION */,942 content: value.content,943 isStatic: false,944 // Treat as non-constant by default. This can be potentially set to945 // true by `transformExpression` to make it eligible for hoisting.946 isConstant: false,947 loc: value.loc948 },949 arg,950 modifiers: match[3] ? match[3].substr(1).split('.') : [],951 loc952 };953 }954 return {955 type: 6 /* ATTRIBUTE */,956 name,957 value: value && {958 type: 2 /* TEXT */,959 content: value.content,960 loc: value.loc961 },962 loc963 };964}965function parseAttributeValue(context) {966 const start = getCursor(context);967 let content;968 const quote = context.source[0];969 const isQuoted = quote === `"` || quote === `'`;970 if (isQuoted) {971 // Quoted value.972 advanceBy(context, 1);973 const endIndex = context.source.indexOf(quote);974 if (endIndex === -1) {975 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);976 }977 else {978 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);979 advanceBy(context, 1);980 }981 }982 else {983 // Unquoted984 const match = /^[^\t\r\n\f >]+/.exec(context.source);985 if (!match) {986 return undefined;987 }988 let unexpectedChars = /["'<=`]/g;989 let m;990 while ((m = unexpectedChars.exec(match[0])) !== null) {991 emitError(context, 25 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);992 }993 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);994 }995 return { content, isQuoted, loc: getSelection(context, start) };996}997function parseInterpolation(context, mode) {998 const [open, close] = context.options.delimiters;999 assert(startsWith(context.source, open));1000 const closeIndex = context.source.indexOf(close, open.length);1001 if (closeIndex === -1) {1002 emitError(context, 33 /* X_MISSING_INTERPOLATION_END */);1003 return undefined;1004 }1005 const start = getCursor(context);1006 advanceBy(context, open.length);1007 const innerStart = getCursor(context);1008 const innerEnd = getCursor(context);1009 const rawContentLength = closeIndex - open.length;1010 const rawContent = context.source.slice(0, rawContentLength);1011 const preTrimContent = parseTextData(context, rawContentLength, mode);1012 const content = preTrimContent.trim();1013 const startOffset = preTrimContent.indexOf(content);1014 if (startOffset > 0) {1015 advancePositionWithMutation(innerStart, rawContent, startOffset);1016 }1017 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);1018 advancePositionWithMutation(innerEnd, rawContent, endOffset);1019 advanceBy(context, close.length);1020 return {1021 type: 5 /* INTERPOLATION */,1022 content: {1023 type: 4 /* SIMPLE_EXPRESSION */,1024 isStatic: false,1025 // Set `isConstant` to false by default and will decide in transformExpression1026 isConstant: false,1027 content,1028 loc: getSelection(context, innerStart, innerEnd)1029 },1030 loc: getSelection(context, start)1031 };1032}1033function parseText(context, mode) {1034 assert(context.source.length > 0);1035 const [open] = context.options.delimiters;1036 // TODO could probably use some perf optimization1037 const endIndex = Math.min(...[1038 context.source.indexOf('<', 1),1039 context.source.indexOf(open, 1),1040 mode === 3 /* CDATA */ ? context.source.indexOf(']]>') : -1,1041 context.source.length1042 ].filter(n => n !== -1));1043 assert(endIndex > 0);1044 const start = getCursor(context);1045 const content = parseTextData(context, endIndex, mode);1046 return {1047 type: 2 /* TEXT */,1048 content,1049 loc: getSelection(context, start)1050 };1051}1052/**1053 * Get text data with a given length from the current location.1054 * This translates HTML entities in the text data.1055 */1056function parseTextData(context, length, mode) {1057 if (mode === 2 /* RAWTEXT */ || mode === 3 /* CDATA */) {1058 const text = context.source.slice(0, length);1059 advanceBy(context, length);1060 return text;1061 }1062 // DATA or RCDATA. Entity decoding required.1063 const end = context.offset + length;1064 let text = '';1065 while (context.offset < end) {1066 const head = /&(?:#x?)?/i.exec(context.source);1067 if (!head || context.offset + head.index >= end) {1068 const remaining = end - context.offset;1069 text += context.source.slice(0, remaining);1070 advanceBy(context, remaining);1071 break;1072 }1073 // Advance to the "&".1074 text += context.source.slice(0, head.index);1075 advanceBy(context, head.index);1076 if (head[0] === '&') {1077 // Named character reference.1078 let name = '', value = undefined;1079 if (/[0-9a-z]/i.test(context.source[1])) {1080 for (let length = context.maxCRNameLength; !value && length > 0; --length) {1081 name = context.source.substr(1, length);1082 value = context.options.namedCharacterReferences[name];1083 }1084 if (value) {1085 const semi = name.endsWith(';');1086 if (mode === 4 /* ATTRIBUTE_VALUE */ &&1087 !semi &&1088 /[=a-z0-9]/i.test(context.source[1 + name.length] || '')) {1089 text += '&';1090 text += name;1091 advanceBy(context, 1 + name.length);1092 }1093 else {1094 text += value;1095 advanceBy(context, 1 + name.length);1096 if (!semi) {1097 emitError(context, 18 /* MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE */);1098 }1099 }1100 }1101 else {1102 emitError(context, 30 /* UNKNOWN_NAMED_CHARACTER_REFERENCE */);1103 text += '&';1104 text += name;1105 advanceBy(context, 1 + name.length);1106 }1107 }1108 else {1109 text += '&';1110 advanceBy(context, 1);1111 }1112 }1113 else {1114 // Numeric character reference.1115 const hex = head[0] === '&#x';1116 const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/;1117 const body = pattern.exec(context.source);1118 if (!body) {1119 text += head[0];1120 emitError(context, 1 /* ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE */);1121 advanceBy(context, head[0].length);1122 }1123 else {1124 // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state1125 let cp = Number.parseInt(body[1], hex ? 16 : 10);1126 if (cp === 0) {1127 emitError(context, 22 /* NULL_CHARACTER_REFERENCE */);1128 cp = 0xfffd;1129 }1130 else if (cp > 0x10ffff) {1131 emitError(context, 3 /* CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE */);1132 cp = 0xfffd;1133 }1134 else if (cp >= 0xd800 && cp <= 0xdfff) {1135 emitError(context, 23 /* SURROGATE_CHARACTER_REFERENCE */);1136 cp = 0xfffd;1137 }1138 else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) {1139 emitError(context, 21 /* NONCHARACTER_CHARACTER_REFERENCE */);1140 }1141 else if ((cp >= 0x01 && cp <= 0x08) ||1142 cp === 0x0b ||1143 (cp >= 0x0d && cp <= 0x1f) ||1144 (cp >= 0x7f && cp <= 0x9f)) {1145 emitError(context, 4 /* CONTROL_CHARACTER_REFERENCE */);1146 cp = CCR_REPLACEMENTS[cp] || cp;1147 }1148 text += String.fromCodePoint(cp);1149 advanceBy(context, body[0].length);1150 if (!body[0].endsWith(';')) {1151 emitError(context, 18 /* MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE */);1152 }1153 }1154 }1155 }1156 return text;1157}1158function getCursor(context) {1159 const { column, line, offset } = context;1160 return { column, line, offset };1161}1162function getSelection(context, start, end) {1163 end = end || getCursor(context);1164 return {1165 start,1166 end,1167 source: context.originalSource.slice(start.offset, end.offset)1168 };1169}1170function last(xs) {1171 return xs[xs.length - 1];1172}1173function startsWith(source, searchString) {1174 return source.startsWith(searchString);1175}1176function advanceBy(context, numberOfCharacters) {1177 const { source } = context;1178 assert(numberOfCharacters <= source.length);1179 advancePositionWithMutation(context, source, numberOfCharacters);1180 context.source = source.slice(numberOfCharacters);1181}1182function advanceSpaces(context) {1183 const match = /^[\t\r\n\f ]+/.exec(context.source);1184 if (match) {1185 advanceBy(context, match[0].length);1186 }1187}1188function getNewPosition(context, start, numberOfCharacters) {1189 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);1190}1191function emitError(context, code, offset) {1192 const loc = getCursor(context);1193 if (offset) {1194 loc.offset += offset;1195 loc.column += offset;1196 }1197 context.options.onError(createCompilerError(code, {1198 start: loc,1199 end: loc,1200 source: ''1201 }));1202}1203function isEnd(context, mode, ancestors) {1204 const s = context.source;1205 switch (mode) {1206 case 0 /* DATA */:1207 if (startsWith(s, '</')) {1208 //TODO: probably bad performance1209 for (let i = ancestors.length - 1; i >= 0; --i) {1210 if (startsWithEndTagOpen(s, ancestors[i].tag)) {1211 return true;1212 }1213 }1214 }1215 break;1216 case 1 /* RCDATA */:1217 case 2 /* RAWTEXT */: {1218 const parent = last(ancestors);1219 if (parent && startsWithEndTagOpen(s, parent.tag)) {1220 return true;1221 }1222 break;1223 }1224 case 3 /* CDATA */:1225 if (startsWith(s, ']]>')) {1226 return true;1227 }1228 break;1229 }1230 return !s;1231}1232function startsWithEndTagOpen(source, tag) {1233 return (startsWith(source, '</') &&1234 source.substr(2, tag.length).toLowerCase() === tag.toLowerCase() &&1235 /[\t\n\f />]/.test(source[2 + tag.length] || '>'));1236}1237// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state1238const CCR_REPLACEMENTS = {1239 0x80: 0x20ac,1240 0x82: 0x201a,1241 0x83: 0x0192,1242 0x84: 0x201e,1243 0x85: 0x2026,1244 0x86: 0x2020,1245 0x87: 0x2021,1246 0x88: 0x02c6,1247 0x89: 0x2030,1248 0x8a: 0x0160,1249 0x8b: 0x2039,1250 0x8c: 0x0152,1251 0x8e: 0x017d,1252 0x91: 0x2018,1253 0x92: 0x2019,1254 0x93: 0x201c,1255 0x94: 0x201d,1256 0x95: 0x2022,1257 0x96: 0x2013,1258 0x97: 0x2014,1259 0x98: 0x02dc,1260 0x99: 0x2122,1261 0x9a: 0x0161,1262 0x9b: 0x203a,1263 0x9c: 0x0153,1264 0x9e: 0x017e,1265 0x9f: 0x01781266};1267function hoistStatic(root, context) {1268 walk(root.children, context, new Map(), isSingleElementRoot(root, root.children[0]));1269}1270function isSingleElementRoot(root, child) {1271 const { children } = root;1272 return (children.length === 1 &&1273 child.type === 1 /* ELEMENT */ &&1274 !isSlotOutlet(child));1275}1276function walk(children, context, resultCache, doNotHoistNode = false) {1277 for (let i = 0; i < children.length; i++) {1278 const child = children[i];1279 // only plain elements are eligible for hoisting.1280 if (child.type === 1 /* ELEMENT */ &&1281 child.tagType === 0 /* ELEMENT */) {1282 if (!doNotHoistNode && isStaticNode(child, resultCache)) {1283 // whole tree is static1284 child.codegenNode = context.hoist(child.codegenNode);1285 continue;1286 }1287 else {1288 // node may contain dynamic children, but its props may be eligible for1289 // hoisting.1290 const codegenNode = child.codegenNode;1291 if (codegenNode.type === 13 /* JS_CALL_EXPRESSION */) {1292 const flag = getPatchFlag(codegenNode);1293 if ((!flag ||1294 flag === 32 /* NEED_PATCH */ ||1295 flag === 1 /* TEXT */) &&1296 !hasDynamicKeyOrRef(child) &&1297 !hasCachedProps(child)) {1298 const props = getNodeProps(child);1299 if (props && props !== `null`) {1300 getVNodeCall(codegenNode).arguments[1] = context.hoist(props);1301 }1302 }1303 }1304 }1305 }1306 if (child.type === 1 /* ELEMENT */) {1307 walk(child.children, context, resultCache);1308 }1309 else if (child.type === 11 /* FOR */) {1310 // Do not hoist v-for single child because it has to be a block1311 walk(child.children, context, resultCache, child.children.length === 1);1312 }1313 else if (child.type === 9 /* IF */) {1314 for (let i = 0; i < child.branches.length; i++) {1315 const branchChildren = child.branches[i].children;1316 // Do not hoist v-if single child because it has to be a block1317 walk(branchChildren, context, resultCache, branchChildren.length === 1);1318 }1319 }1320 }1321}1322function isStaticNode(node, resultCache = new Map()) {1323 switch (node.type) {1324 case 1 /* ELEMENT */:1325 if (node.tagType !== 0 /* ELEMENT */) {1326 return false;1327 }1328 const cached = resultCache.get(node);1329 if (cached !== undefined) {1330 return cached;1331 }1332 const codegenNode = node.codegenNode;1333 if (codegenNode.type !== 13 /* JS_CALL_EXPRESSION */) {1334 return false;1335 }1336 const flag = getPatchFlag(codegenNode);1337 if (!flag && !hasDynamicKeyOrRef(node) && !hasCachedProps(node)) {1338 // element self is static. check its children.1339 for (let i = 0; i < node.children.length; i++) {1340 if (!isStaticNode(node.children[i], resultCache)) {1341 resultCache.set(node, false);1342 return false;1343 }1344 }1345 resultCache.set(node, true);1346 return true;1347 }1348 else {1349 resultCache.set(node, false);1350 return false;1351 }1352 case 2 /* TEXT */:1353 case 3 /* COMMENT */:1354 return true;1355 case 9 /* IF */:1356 case 11 /* FOR */:1357 return false;1358 case 5 /* INTERPOLATION */:1359 case 12 /* TEXT_CALL */:1360 return isStaticNode(node.content, resultCache);1361 case 4 /* SIMPLE_EXPRESSION */:1362 return node.isConstant;1363 case 8 /* COMPOUND_EXPRESSION */:1364 return node.children.every(child => {1365 return (isString(child) || isSymbol(child) || isStaticNode(child, resultCache));1366 });1367 default:1368 return false;1369 }1370}1371function hasDynamicKeyOrRef(node) {1372 return !!(findProp(node, 'key', true) || findProp(node, 'ref', true));1373}1374function hasCachedProps(node) {1375 const props = getNodeProps(node);1376 if (props &&1377 props !== 'null' &&1378 props.type === 14 /* JS_OBJECT_EXPRESSION */) {1379 const { properties } = props;1380 for (let i = 0; i < properties.length; i++) {1381 if (properties[i].value.type === 20 /* JS_CACHE_EXPRESSION */) {1382 return true;1383 }1384 }1385 }1386 return false;1387}1388function getNodeProps(node) {1389 const codegenNode = node.codegenNode;1390 if (codegenNode.type === 13 /* JS_CALL_EXPRESSION */) {1391 return getVNodeArgAt(codegenNode, 1);1392 }1393}1394function getVNodeArgAt(node, index) {1395 return getVNodeCall(node).arguments[index];1396}1397function getVNodeCall(node) {1398 return node.callee === WITH_DIRECTIVES ? node.arguments[0] : node;1399}1400function getPatchFlag(node) {1401 const flag = getVNodeArgAt(node, 3);1402 return flag ? parseInt(flag, 10) : undefined;1403}1404function createTransformContext(root, { prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, onError = defaultOnError }) {1405 const context = {1406 root,1407 helpers: new Set(),1408 components: new Set(),1409 directives: new Set(),1410 hoists: [],1411 cached: 0,1412 identifiers: {},1413 scopes: {1414 vFor: 0,1415 vSlot: 0,1416 vPre: 0,1417 vOnce: 01418 },1419 prefixIdentifiers,1420 hoistStatic,1421 cacheHandlers,1422 nodeTransforms,1423 directiveTransforms,1424 onError,1425 parent: null,1426 currentNode: root,1427 childIndex: 0,1428 helper(name) {1429 context.helpers.add(name);1430 return name;1431 },1432 helperString(name) {1433 return ((context.prefixIdentifiers ? `` : `_`) +1434 helperNameMap[context.helper(name)]);1435 },1436 replaceNode(node) {1437 /* istanbul ignore if */1438 {1439 if (!context.currentNode) {1440 throw new Error(`Node being replaced is already removed.`);1441 }1442 if (!context.parent) {1443 throw new Error(`Cannot replace root node.`);1444 }1445 }1446 context.parent.children[context.childIndex] = context.currentNode = node;1447 },1448 removeNode(node) {1449 if ( !context.parent) {1450 throw new Error(`Cannot remove root node.`);1451 }1452 const list = context.parent.children;1453 const removalIndex = node1454 ? list.indexOf(node)1455 : context.currentNode1456 ? context.childIndex1457 : -1;1458 /* istanbul ignore if */1459 if ( removalIndex < 0) {1460 throw new Error(`node being removed is not a child of current parent`);1461 }1462 if (!node || node === context.currentNode) {1463 // current node removed1464 context.currentNode = null;1465 context.onNodeRemoved();1466 }1467 else {1468 // sibling node removed1469 if (context.childIndex > removalIndex) {1470 context.childIndex--;1471 context.onNodeRemoved();1472 }1473 }1474 context.parent.children.splice(removalIndex, 1);1475 },1476 onNodeRemoved: () => { },1477 addIdentifiers(exp) {1478 // identifier tracking only happens in non-browser builds.1479 {1480 if (isString(exp)) {1481 addId(exp);1482 }1483 else if (exp.identifiers) {1484 exp.identifiers.forEach(addId);1485 }1486 else if (exp.type === 4 /* SIMPLE_EXPRESSION */) {1487 addId(exp.content);1488 }1489 }1490 },1491 removeIdentifiers(exp) {1492 {1493 if (isString(exp)) {1494 removeId(exp);1495 }1496 else if (exp.identifiers) {1497 exp.identifiers.forEach(removeId);1498 }1499 else if (exp.type === 4 /* SIMPLE_EXPRESSION */) {1500 removeId(exp.content);1501 }1502 }1503 },1504 hoist(exp) {1505 context.hoists.push(exp);1506 return createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, true);1507 },1508 cache(exp, isVNode = false) {1509 return createCacheExpression(++context.cached, exp, isVNode);1510 }1511 };1512 function addId(id) {1513 const { identifiers } = context;1514 if (identifiers[id] === undefined) {1515 identifiers[id] = 0;1516 }1517 identifiers[id]++;1518 }1519 function removeId(id) {1520 context.identifiers[id]--;1521 }1522 return context;1523}...
compiler-core.cjs.prod.js
Source:compiler-core.cjs.prod.js
...215 alternate,216 loc: locStub217 };218}219function createCacheExpression(index, value, isVNode = false) {220 return {221 type: 20 /* JS_CACHE_EXPRESSION */,222 index,223 value,224 isVNode,225 loc: locStub226 };227}228const FRAGMENT = Symbol( ``);229const PORTAL = Symbol( ``);230const SUSPENSE = Symbol( ``);231const OPEN_BLOCK = Symbol( ``);232const CREATE_BLOCK = Symbol( ``);233const CREATE_VNODE = Symbol( ``);234const CREATE_COMMENT = Symbol( ``);235const CREATE_TEXT = Symbol( ``);236const RESOLVE_COMPONENT = Symbol( ``);237const RESOLVE_DYNAMIC_COMPONENT = Symbol( ``);238const RESOLVE_DIRECTIVE = Symbol( ``);239const WITH_DIRECTIVES = Symbol( ``);240const RENDER_LIST = Symbol( ``);241const RENDER_SLOT = Symbol( ``);242const CREATE_SLOTS = Symbol( ``);243const TO_STRING = Symbol( ``);244const MERGE_PROPS = Symbol( ``);245const TO_HANDLERS = Symbol( ``);246const CAMELIZE = Symbol( ``);247const SET_BLOCK_TRACKING = Symbol( ``);248// Name mapping for runtime helpers that need to be imported from 'vue' in249// generated code. Make sure these are correctly exported in the runtime!250// Using `any` here because TS doesn't allow symbols as index type.251const helperNameMap = {252 [FRAGMENT]: `Fragment`,253 [PORTAL]: `Portal`,254 [SUSPENSE]: `Suspense`,255 [OPEN_BLOCK]: `openBlock`,256 [CREATE_BLOCK]: `createBlock`,257 [CREATE_VNODE]: `createVNode`,258 [CREATE_COMMENT]: `createCommentVNode`,259 [CREATE_TEXT]: `createTextVNode`,260 [RESOLVE_COMPONENT]: `resolveComponent`,261 [RESOLVE_DYNAMIC_COMPONENT]: `resolveDynamicComponent`,262 [RESOLVE_DIRECTIVE]: `resolveDirective`,263 [WITH_DIRECTIVES]: `withDirectives`,264 [RENDER_LIST]: `renderList`,265 [RENDER_SLOT]: `renderSlot`,266 [CREATE_SLOTS]: `createSlots`,267 [TO_STRING]: `toString`,268 [MERGE_PROPS]: `mergeProps`,269 [TO_HANDLERS]: `toHandlers`,270 [CAMELIZE]: `camelize`,271 [SET_BLOCK_TRACKING]: `setBlockTracking`272};273function registerRuntimeHelpers(helpers) {274 Object.getOwnPropertySymbols(helpers).forEach(s => {275 helperNameMap[s] = helpers[s];276 });277}278// cache node requires279// lazy require dependencies so that they don't end up in rollup's dep graph280// and thus can be tree-shaken in browser builds.281let _parse;282let _walk;283function loadDep(name) {284 if (typeof process !== 'undefined' && isFunction(require)) {285 return require(name);286 }287 else {288 // This is only used when we are building a dev-only build of the compiler289 // which runs in the browser but also uses Node deps.290 return window._deps[name];291 }292}293const parseJS = (code, options) => {294 assert(!false, `Expression AST analysis can only be performed in non-browser builds.`);295 const parse = _parse || (_parse = loadDep('acorn').parse);296 return parse(code, options);297};298const walkJS = (ast, walker) => {299 assert(!false, `Expression AST analysis can only be performed in non-browser builds.`);300 const walk = _walk || (_walk = loadDep('estree-walker').walk);301 return walk(ast, walker);302};303const nonIdentifierRE = /^\d|[^\$\w]/;304const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);305const memberExpRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\[[^\]]+\])*$/;306const isMemberExpression = (path) => memberExpRE.test(path);307function getInnerRange(loc, offset, length) {308 const source = loc.source.substr(offset, length);309 const newLoc = {310 source,311 start: advancePositionWithClone(loc.start, loc.source, offset),312 end: loc.end313 };314 if (length != null) {315 newLoc.end = advancePositionWithClone(loc.start, loc.source, offset + length);316 }317 return newLoc;318}319function advancePositionWithClone(pos, source, numberOfCharacters = source.length) {320 return advancePositionWithMutation({ ...pos }, source, numberOfCharacters);321}322// advance by mutation without cloning (for performance reasons), since this323// gets called a lot in the parser324function advancePositionWithMutation(pos, source, numberOfCharacters = source.length) {325 let linesCount = 0;326 let lastNewLinePos = -1;327 for (let i = 0; i < numberOfCharacters; i++) {328 if (source.charCodeAt(i) === 10 /* newline char code */) {329 linesCount++;330 lastNewLinePos = i;331 }332 }333 pos.offset += numberOfCharacters;334 pos.line += linesCount;335 pos.column =336 lastNewLinePos === -1337 ? pos.column + numberOfCharacters338 : Math.max(1, numberOfCharacters - lastNewLinePos);339 return pos;340}341function assert(condition, msg) {342 /* istanbul ignore if */343 if (!condition) {344 throw new Error(msg || `unexpected compiler condition`);345 }346}347function findDir(node, name, allowEmpty = false) {348 for (let i = 0; i < node.props.length; i++) {349 const p = node.props[i];350 if (p.type === 7 /* DIRECTIVE */ &&351 (allowEmpty || p.exp) &&352 (isString(name) ? p.name === name : name.test(p.name))) {353 return p;354 }355 }356}357function findProp(node, name, dynamicOnly = false) {358 for (let i = 0; i < node.props.length; i++) {359 const p = node.props[i];360 if (p.type === 6 /* ATTRIBUTE */) {361 if (dynamicOnly)362 continue;363 if (p.name === name && p.value) {364 return p;365 }366 }367 else if (p.name === 'bind' &&368 p.arg &&369 p.arg.type === 4 /* SIMPLE_EXPRESSION */ &&370 p.arg.isStatic &&371 p.arg.content === name &&372 p.exp) {373 return p;374 }375 }376}377function createBlockExpression(blockExp, context) {378 return createSequenceExpression([379 createCallExpression(context.helper(OPEN_BLOCK)),380 blockExp381 ]);382}383function isVSlot(p) {384 return p.type === 7 /* DIRECTIVE */ && p.name === 'slot';385}386function isTemplateNode(node) {387 return (node.type === 1 /* ELEMENT */ && node.tagType === 3 /* TEMPLATE */);388}389function isSlotOutlet(node) {390 return node.type === 1 /* ELEMENT */ && node.tagType === 2 /* SLOT */;391}392function injectProp(node, prop, context) {393 let propsWithInjection;394 const props = node.callee === RENDER_SLOT ? node.arguments[2] : node.arguments[1];395 if (props == null || isString(props)) {396 propsWithInjection = createObjectExpression([prop]);397 }398 else if (props.type === 13 /* JS_CALL_EXPRESSION */) {399 // merged props... add ours400 // only inject key to object literal if it's the first argument so that401 // if doesn't override user provided keys402 const first = props.arguments[0];403 if (!isString(first) && first.type === 14 /* JS_OBJECT_EXPRESSION */) {404 first.properties.unshift(prop);405 }406 else {407 props.arguments.unshift(createObjectExpression([prop]));408 }409 propsWithInjection = props;410 }411 else if (props.type === 14 /* JS_OBJECT_EXPRESSION */) {412 props.properties.unshift(prop);413 propsWithInjection = props;414 }415 else {416 // single v-bind with expression, return a merged replacement417 propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [418 createObjectExpression([prop]),419 props420 ]);421 }422 if (node.callee === RENDER_SLOT) {423 node.arguments[2] = propsWithInjection;424 }425 else {426 node.arguments[1] = propsWithInjection;427 }428}429function toValidAssetId(name, type) {430 return `_${type}_${name.replace(/[^\w]/g, '_')}`;431}432// Check if a node contains expressions that reference current context scope ids433function hasScopeRef(node, ids) {434 if (!node || Object.keys(ids).length === 0) {435 return false;436 }437 switch (node.type) {438 case 1 /* ELEMENT */:439 for (let i = 0; i < node.props.length; i++) {440 const p = node.props[i];441 if (p.type === 7 /* DIRECTIVE */ &&442 (hasScopeRef(p.arg, ids) || hasScopeRef(p.exp, ids))) {443 return true;444 }445 }446 return node.children.some(c => hasScopeRef(c, ids));447 case 11 /* FOR */:448 if (hasScopeRef(node.source, ids)) {449 return true;450 }451 return node.children.some(c => hasScopeRef(c, ids));452 case 9 /* IF */:453 return node.branches.some(b => hasScopeRef(b, ids));454 case 10 /* IF_BRANCH */:455 if (hasScopeRef(node.condition, ids)) {456 return true;457 }458 return node.children.some(c => hasScopeRef(c, ids));459 case 4 /* SIMPLE_EXPRESSION */:460 return (!node.isStatic &&461 isSimpleIdentifier(node.content) &&462 !!ids[node.content]);463 case 8 /* COMPOUND_EXPRESSION */:464 return node.children.some(c => isObject(c) && hasScopeRef(c, ids));465 case 5 /* INTERPOLATION */:466 case 12 /* TEXT_CALL */:467 return hasScopeRef(node.content, ids);468 case 2 /* TEXT */:469 case 3 /* COMMENT */:470 return false;471 default:472 return false;473 }474}475const defaultParserOptions = {476 delimiters: [`{{`, `}}`],477 getNamespace: () => 0 /* HTML */,478 getTextMode: () => 0 /* DATA */,479 isVoidTag: NO,480 isPreTag: NO,481 isCustomElement: NO,482 namedCharacterReferences: {483 'gt;': '>',484 'lt;': '<',485 'amp;': '&',486 'apos;': "'",487 'quot;': '"'488 },489 onError: defaultOnError490};491function parse(content, options = {}) {492 const context = createParserContext(content, options);493 const start = getCursor(context);494 return {495 type: 0 /* ROOT */,496 children: parseChildren(context, 0 /* DATA */, []),497 helpers: [],498 components: [],499 directives: [],500 hoists: [],501 cached: 0,502 codegenNode: undefined,503 loc: getSelection(context, start)504 };505}506function createParserContext(content, options) {507 return {508 options: {509 ...defaultParserOptions,510 ...options511 },512 column: 1,513 line: 1,514 offset: 0,515 originalSource: content,516 source: content,517 maxCRNameLength: Object.keys(options.namedCharacterReferences ||518 defaultParserOptions.namedCharacterReferences).reduce((max, name) => Math.max(max, name.length), 0),519 inPre: false520 };521}522function parseChildren(context, mode, ancestors) {523 const parent = last(ancestors);524 const ns = parent ? parent.ns : 0 /* HTML */;525 const nodes = [];526 while (!isEnd(context, mode, ancestors)) {527 const s = context.source;528 let node = undefined;529 if (!context.inPre && startsWith(s, context.options.delimiters[0])) {530 // '{{'531 node = parseInterpolation(context, mode);532 }533 else if (mode === 0 /* DATA */ && s[0] === '<') {534 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state535 if (s.length === 1) {536 emitError(context, 8 /* EOF_BEFORE_TAG_NAME */, 1);537 }538 else if (s[1] === '!') {539 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state540 if (startsWith(s, '<!--')) {541 node = parseComment(context);542 }543 else if (startsWith(s, '<!DOCTYPE')) {544 // Ignore DOCTYPE by a limitation.545 node = parseBogusComment(context);546 }547 else if (startsWith(s, '<![CDATA[')) {548 if (ns !== 0 /* HTML */) {549 node = parseCDATA(context, ancestors);550 }551 else {552 emitError(context, 2 /* CDATA_IN_HTML_CONTENT */);553 node = parseBogusComment(context);554 }555 }556 else {557 emitError(context, 14 /* INCORRECTLY_OPENED_COMMENT */);558 node = parseBogusComment(context);559 }560 }561 else if (s[1] === '/') {562 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state563 if (s.length === 2) {564 emitError(context, 8 /* EOF_BEFORE_TAG_NAME */, 2);565 }566 else if (s[2] === '>') {567 emitError(context, 17 /* MISSING_END_TAG_NAME */, 2);568 advanceBy(context, 3);569 continue;570 }571 else if (/[a-z]/i.test(s[2])) {572 emitError(context, 31 /* X_INVALID_END_TAG */);573 parseTag(context, 1 /* End */, parent);574 continue;575 }576 else {577 emitError(context, 15 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);578 node = parseBogusComment(context);579 }580 }581 else if (/[a-z]/i.test(s[1])) {582 node = parseElement(context, ancestors);583 }584 else if (s[1] === '?') {585 emitError(context, 28 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);586 node = parseBogusComment(context);587 }588 else {589 emitError(context, 15 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);590 }591 }592 if (!node) {593 node = parseText(context, mode);594 }595 if (Array.isArray(node)) {596 for (let i = 0; i < node.length; i++) {597 pushNode(nodes, node[i]);598 }599 }600 else {601 pushNode(nodes, node);602 }603 }604 // Whitespace management for more efficient output605 // (same as v2 whitespance: 'condense')606 let removedWhitespace = false;607 if (!parent || !context.options.isPreTag(parent.tag)) {608 for (let i = 0; i < nodes.length; i++) {609 const node = nodes[i];610 if (node.type === 2 /* TEXT */) {611 if (!node.content.trim()) {612 const prev = nodes[i - 1];613 const next = nodes[i + 1];614 // If:615 // - the whitespace is the first or last node, or:616 // - the whitespace is adjacent to a comment, or:617 // - the whitespace is between two elements AND contains newline618 // Then the whitespace is ignored.619 if (!prev ||620 !next ||621 prev.type === 3 /* COMMENT */ ||622 next.type === 3 /* COMMENT */ ||623 (prev.type === 1 /* ELEMENT */ &&624 next.type === 1 /* ELEMENT */ &&625 /[\r\n]/.test(node.content))) {626 removedWhitespace = true;627 nodes[i] = null;628 }629 else {630 // Otherwise, condensed consecutive whitespace inside the text down to631 // a single space632 node.content = ' ';633 }634 }635 else {636 node.content = node.content.replace(/\s+/g, ' ');637 }638 }639 }640 }641 return removedWhitespace ? nodes.filter(node => node !== null) : nodes;642}643function pushNode(nodes, node) {644 // ignore comments in production645 /* istanbul ignore next */646 if ( node.type === 3 /* COMMENT */) {647 return;648 }649 if (node.type === 2 /* TEXT */) {650 const prev = last(nodes);651 // Merge if both this and the previous node are text and those are652 // consecutive. This happens for cases like "a < b".653 if (prev &&654 prev.type === 2 /* TEXT */ &&655 prev.loc.end.offset === node.loc.start.offset) {656 prev.content += node.content;657 prev.loc.end = node.loc.end;658 prev.loc.source += node.loc.source;659 return;660 }661 }662 nodes.push(node);663}664function parseCDATA(context, ancestors) {665 advanceBy(context, 9);666 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);667 if (context.source.length === 0) {668 emitError(context, 9 /* EOF_IN_CDATA */);669 }670 else {671 advanceBy(context, 3);672 }673 return nodes;674}675function parseComment(context) {676 const start = getCursor(context);677 let content;678 // Regular comment.679 const match = /--(\!)?>/.exec(context.source);680 if (!match) {681 content = context.source.slice(4);682 advanceBy(context, context.source.length);683 emitError(context, 10 /* EOF_IN_COMMENT */);684 }685 else {686 if (match.index <= 3) {687 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);688 }689 if (match[1]) {690 emitError(context, 13 /* INCORRECTLY_CLOSED_COMMENT */);691 }692 content = context.source.slice(4, match.index);693 // Advancing with reporting nested comments.694 const s = context.source.slice(0, match.index);695 let prevIndex = 1, nestedIndex = 0;696 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {697 advanceBy(context, nestedIndex - prevIndex + 1);698 if (nestedIndex + 4 < s.length) {699 emitError(context, 20 /* NESTED_COMMENT */);700 }701 prevIndex = nestedIndex + 1;702 }703 advanceBy(context, match.index + match[0].length - prevIndex + 1);704 }705 return {706 type: 3 /* COMMENT */,707 content,708 loc: getSelection(context, start)709 };710}711function parseBogusComment(context) {712 const start = getCursor(context);713 const contentStart = context.source[1] === '?' ? 1 : 2;714 let content;715 const closeIndex = context.source.indexOf('>');716 if (closeIndex === -1) {717 content = context.source.slice(contentStart);718 advanceBy(context, context.source.length);719 }720 else {721 content = context.source.slice(contentStart, closeIndex);722 advanceBy(context, closeIndex + 1);723 }724 return {725 type: 3 /* COMMENT */,726 content,727 loc: getSelection(context, start)728 };729}730function parseElement(context, ancestors) {731 // Start tag.732 const wasInPre = context.inPre;733 const parent = last(ancestors);734 const element = parseTag(context, 0 /* Start */, parent);735 const isPreBoundary = context.inPre && !wasInPre;736 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {737 return element;738 }739 // Children.740 ancestors.push(element);741 const mode = context.options.getTextMode(element.tag, element.ns);742 const children = parseChildren(context, mode, ancestors);743 ancestors.pop();744 element.children = children;745 // End tag.746 if (startsWithEndTagOpen(context.source, element.tag)) {747 parseTag(context, 1 /* End */, parent);748 }749 else {750 emitError(context, 32 /* X_MISSING_END_TAG */);751 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {752 const first = children[0];753 if (first && startsWith(first.loc.source, '<!--')) {754 emitError(context, 11 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);755 }756 }757 }758 element.loc = getSelection(context, element.loc.start);759 if (isPreBoundary) {760 context.inPre = false;761 }762 return element;763}764/**765 * Parse a tag (E.g. `<div id=a>`) with that type (start tag or end tag).766 */767function parseTag(context, type, parent) {768 // Tag open.769 const start = getCursor(context);770 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);771 const tag = match[1];772 const ns = context.options.getNamespace(tag, parent);773 advanceBy(context, match[0].length);774 advanceSpaces(context);775 // save current state in case we need to re-parse attributes with v-pre776 const cursor = getCursor(context);777 const currentSource = context.source;778 // Attributes.779 let props = parseAttributes(context, type);780 // check v-pre781 if (!context.inPre &&782 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {783 context.inPre = true;784 // reset context785 extend(context, cursor);786 context.source = currentSource;787 // re-parse attrs and filter out v-pre itself788 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');789 }790 // Tag close.791 let isSelfClosing = false;792 if (context.source.length === 0) {793 emitError(context, 12 /* EOF_IN_TAG */);794 }795 else {796 isSelfClosing = startsWith(context.source, '/>');797 if (type === 1 /* End */ && isSelfClosing) {798 emitError(context, 7 /* END_TAG_WITH_TRAILING_SOLIDUS */);799 }800 advanceBy(context, isSelfClosing ? 2 : 1);801 }802 let tagType = 0 /* ELEMENT */;803 if (!context.inPre && !context.options.isCustomElement(tag)) {804 if (context.options.isNativeTag) {805 if (!context.options.isNativeTag(tag))806 tagType = 1 /* COMPONENT */;807 }808 else {809 if (/^[A-Z]/.test(tag))810 tagType = 1 /* COMPONENT */;811 }812 if (tag === 'slot')813 tagType = 2 /* SLOT */;814 else if (tag === 'template')815 tagType = 3 /* TEMPLATE */;816 else if (tag === 'portal' || tag === 'Portal')817 tagType = 4 /* PORTAL */;818 else if (tag === 'suspense' || tag === 'Suspense')819 tagType = 5 /* SUSPENSE */;820 }821 return {822 type: 1 /* ELEMENT */,823 ns,824 tag,825 tagType,826 props,827 isSelfClosing,828 children: [],829 loc: getSelection(context, start),830 codegenNode: undefined // to be created during transform phase831 };832}833function parseAttributes(context, type) {834 const props = [];835 const attributeNames = new Set();836 while (context.source.length > 0 &&837 !startsWith(context.source, '>') &&838 !startsWith(context.source, '/>')) {839 if (startsWith(context.source, '/')) {840 emitError(context, 29 /* UNEXPECTED_SOLIDUS_IN_TAG */);841 advanceBy(context, 1);842 advanceSpaces(context);843 continue;844 }845 if (type === 1 /* End */) {846 emitError(context, 6 /* END_TAG_WITH_ATTRIBUTES */);847 }848 const attr = parseAttribute(context, attributeNames);849 if (type === 0 /* Start */) {850 props.push(attr);851 }852 if (/^[^\t\r\n\f />]/.test(context.source)) {853 emitError(context, 19 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);854 }855 advanceSpaces(context);856 }857 return props;858}859function parseAttribute(context, nameSet) {860 // Name.861 const start = getCursor(context);862 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);863 const name = match[0];864 if (nameSet.has(name)) {865 emitError(context, 5 /* DUPLICATE_ATTRIBUTE */);866 }867 nameSet.add(name);868 if (name[0] === '=') {869 emitError(context, 26 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);870 }871 {872 const pattern = /["'<]/g;873 let m;874 while ((m = pattern.exec(name)) !== null) {875 emitError(context, 24 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);876 }877 }878 advanceBy(context, name.length);879 // Value880 let value = undefined;881 if (/^[\t\r\n\f ]*=/.test(context.source)) {882 advanceSpaces(context);883 advanceBy(context, 1);884 advanceSpaces(context);885 value = parseAttributeValue(context);886 if (!value) {887 emitError(context, 16 /* MISSING_ATTRIBUTE_VALUE */);888 }889 }890 const loc = getSelection(context, start);891 if (!context.inPre && /^(v-|:|@|#)/.test(name)) {892 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^@|^#)([^\.]+))?(.+)?$/i.exec(name);893 let arg;894 if (match[2]) {895 const startOffset = name.split(match[2], 2).shift().length;896 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length));897 let content = match[2];898 let isStatic = true;899 if (content.startsWith('[')) {900 isStatic = false;901 if (!content.endsWith(']')) {902 emitError(context, 34 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);903 }904 content = content.substr(1, content.length - 2);905 }906 arg = {907 type: 4 /* SIMPLE_EXPRESSION */,908 content,909 isStatic,910 isConstant: isStatic,911 loc912 };913 }914 if (value && value.isQuoted) {915 const valueLoc = value.loc;916 valueLoc.start.offset++;917 valueLoc.start.column++;918 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);919 valueLoc.source = valueLoc.source.slice(1, -1);920 }921 return {922 type: 7 /* DIRECTIVE */,923 name: match[1] ||924 (startsWith(name, ':')925 ? 'bind'926 : startsWith(name, '@')927 ? 'on'928 : 'slot'),929 exp: value && {930 type: 4 /* SIMPLE_EXPRESSION */,931 content: value.content,932 isStatic: false,933 // Treat as non-constant by default. This can be potentially set to934 // true by `transformExpression` to make it eligible for hoisting.935 isConstant: false,936 loc: value.loc937 },938 arg,939 modifiers: match[3] ? match[3].substr(1).split('.') : [],940 loc941 };942 }943 return {944 type: 6 /* ATTRIBUTE */,945 name,946 value: value && {947 type: 2 /* TEXT */,948 content: value.content,949 loc: value.loc950 },951 loc952 };953}954function parseAttributeValue(context) {955 const start = getCursor(context);956 let content;957 const quote = context.source[0];958 const isQuoted = quote === `"` || quote === `'`;959 if (isQuoted) {960 // Quoted value.961 advanceBy(context, 1);962 const endIndex = context.source.indexOf(quote);963 if (endIndex === -1) {964 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);965 }966 else {967 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);968 advanceBy(context, 1);969 }970 }971 else {972 // Unquoted973 const match = /^[^\t\r\n\f >]+/.exec(context.source);974 if (!match) {975 return undefined;976 }977 let unexpectedChars = /["'<=`]/g;978 let m;979 while ((m = unexpectedChars.exec(match[0])) !== null) {980 emitError(context, 25 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);981 }982 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);983 }984 return { content, isQuoted, loc: getSelection(context, start) };985}986function parseInterpolation(context, mode) {987 const [open, close] = context.options.delimiters;988 const closeIndex = context.source.indexOf(close, open.length);989 if (closeIndex === -1) {990 emitError(context, 33 /* X_MISSING_INTERPOLATION_END */);991 return undefined;992 }993 const start = getCursor(context);994 advanceBy(context, open.length);995 const innerStart = getCursor(context);996 const innerEnd = getCursor(context);997 const rawContentLength = closeIndex - open.length;998 const rawContent = context.source.slice(0, rawContentLength);999 const preTrimContent = parseTextData(context, rawContentLength, mode);1000 const content = preTrimContent.trim();1001 const startOffset = preTrimContent.indexOf(content);1002 if (startOffset > 0) {1003 advancePositionWithMutation(innerStart, rawContent, startOffset);1004 }1005 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);1006 advancePositionWithMutation(innerEnd, rawContent, endOffset);1007 advanceBy(context, close.length);1008 return {1009 type: 5 /* INTERPOLATION */,1010 content: {1011 type: 4 /* SIMPLE_EXPRESSION */,1012 isStatic: false,1013 // Set `isConstant` to false by default and will decide in transformExpression1014 isConstant: false,1015 content,1016 loc: getSelection(context, innerStart, innerEnd)1017 },1018 loc: getSelection(context, start)1019 };1020}1021function parseText(context, mode) {1022 const [open] = context.options.delimiters;1023 // TODO could probably use some perf optimization1024 const endIndex = Math.min(...[1025 context.source.indexOf('<', 1),1026 context.source.indexOf(open, 1),1027 mode === 3 /* CDATA */ ? context.source.indexOf(']]>') : -1,1028 context.source.length1029 ].filter(n => n !== -1));1030 const start = getCursor(context);1031 const content = parseTextData(context, endIndex, mode);1032 return {1033 type: 2 /* TEXT */,1034 content,1035 loc: getSelection(context, start)1036 };1037}1038/**1039 * Get text data with a given length from the current location.1040 * This translates HTML entities in the text data.1041 */1042function parseTextData(context, length, mode) {1043 if (mode === 2 /* RAWTEXT */ || mode === 3 /* CDATA */) {1044 const text = context.source.slice(0, length);1045 advanceBy(context, length);1046 return text;1047 }1048 // DATA or RCDATA. Entity decoding required.1049 const end = context.offset + length;1050 let text = '';1051 while (context.offset < end) {1052 const head = /&(?:#x?)?/i.exec(context.source);1053 if (!head || context.offset + head.index >= end) {1054 const remaining = end - context.offset;1055 text += context.source.slice(0, remaining);1056 advanceBy(context, remaining);1057 break;1058 }1059 // Advance to the "&".1060 text += context.source.slice(0, head.index);1061 advanceBy(context, head.index);1062 if (head[0] === '&') {1063 // Named character reference.1064 let name = '', value = undefined;1065 if (/[0-9a-z]/i.test(context.source[1])) {1066 for (let length = context.maxCRNameLength; !value && length > 0; --length) {1067 name = context.source.substr(1, length);1068 value = context.options.namedCharacterReferences[name];1069 }1070 if (value) {1071 const semi = name.endsWith(';');1072 if (mode === 4 /* ATTRIBUTE_VALUE */ &&1073 !semi &&1074 /[=a-z0-9]/i.test(context.source[1 + name.length] || '')) {1075 text += '&';1076 text += name;1077 advanceBy(context, 1 + name.length);1078 }1079 else {1080 text += value;1081 advanceBy(context, 1 + name.length);1082 if (!semi) {1083 emitError(context, 18 /* MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE */);1084 }1085 }1086 }1087 else {1088 emitError(context, 30 /* UNKNOWN_NAMED_CHARACTER_REFERENCE */);1089 text += '&';1090 text += name;1091 advanceBy(context, 1 + name.length);1092 }1093 }1094 else {1095 text += '&';1096 advanceBy(context, 1);1097 }1098 }1099 else {1100 // Numeric character reference.1101 const hex = head[0] === '&#x';1102 const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/;1103 const body = pattern.exec(context.source);1104 if (!body) {1105 text += head[0];1106 emitError(context, 1 /* ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE */);1107 advanceBy(context, head[0].length);1108 }1109 else {1110 // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state1111 let cp = Number.parseInt(body[1], hex ? 16 : 10);1112 if (cp === 0) {1113 emitError(context, 22 /* NULL_CHARACTER_REFERENCE */);1114 cp = 0xfffd;1115 }1116 else if (cp > 0x10ffff) {1117 emitError(context, 3 /* CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE */);1118 cp = 0xfffd;1119 }1120 else if (cp >= 0xd800 && cp <= 0xdfff) {1121 emitError(context, 23 /* SURROGATE_CHARACTER_REFERENCE */);1122 cp = 0xfffd;1123 }1124 else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) {1125 emitError(context, 21 /* NONCHARACTER_CHARACTER_REFERENCE */);1126 }1127 else if ((cp >= 0x01 && cp <= 0x08) ||1128 cp === 0x0b ||1129 (cp >= 0x0d && cp <= 0x1f) ||1130 (cp >= 0x7f && cp <= 0x9f)) {1131 emitError(context, 4 /* CONTROL_CHARACTER_REFERENCE */);1132 cp = CCR_REPLACEMENTS[cp] || cp;1133 }1134 text += String.fromCodePoint(cp);1135 advanceBy(context, body[0].length);1136 if (!body[0].endsWith(';')) {1137 emitError(context, 18 /* MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE */);1138 }1139 }1140 }1141 }1142 return text;1143}1144function getCursor(context) {1145 const { column, line, offset } = context;1146 return { column, line, offset };1147}1148function getSelection(context, start, end) {1149 end = end || getCursor(context);1150 return {1151 start,1152 end,1153 source: context.originalSource.slice(start.offset, end.offset)1154 };1155}1156function last(xs) {1157 return xs[xs.length - 1];1158}1159function startsWith(source, searchString) {1160 return source.startsWith(searchString);1161}1162function advanceBy(context, numberOfCharacters) {1163 const { source } = context;1164 advancePositionWithMutation(context, source, numberOfCharacters);1165 context.source = source.slice(numberOfCharacters);1166}1167function advanceSpaces(context) {1168 const match = /^[\t\r\n\f ]+/.exec(context.source);1169 if (match) {1170 advanceBy(context, match[0].length);1171 }1172}1173function getNewPosition(context, start, numberOfCharacters) {1174 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);1175}1176function emitError(context, code, offset) {1177 const loc = getCursor(context);1178 if (offset) {1179 loc.offset += offset;1180 loc.column += offset;1181 }1182 context.options.onError(createCompilerError(code, {1183 start: loc,1184 end: loc,1185 source: ''1186 }));1187}1188function isEnd(context, mode, ancestors) {1189 const s = context.source;1190 switch (mode) {1191 case 0 /* DATA */:1192 if (startsWith(s, '</')) {1193 //TODO: probably bad performance1194 for (let i = ancestors.length - 1; i >= 0; --i) {1195 if (startsWithEndTagOpen(s, ancestors[i].tag)) {1196 return true;1197 }1198 }1199 }1200 break;1201 case 1 /* RCDATA */:1202 case 2 /* RAWTEXT */: {1203 const parent = last(ancestors);1204 if (parent && startsWithEndTagOpen(s, parent.tag)) {1205 return true;1206 }1207 break;1208 }1209 case 3 /* CDATA */:1210 if (startsWith(s, ']]>')) {1211 return true;1212 }1213 break;1214 }1215 return !s;1216}1217function startsWithEndTagOpen(source, tag) {1218 return (startsWith(source, '</') &&1219 source.substr(2, tag.length).toLowerCase() === tag.toLowerCase() &&1220 /[\t\n\f />]/.test(source[2 + tag.length] || '>'));1221}1222// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state1223const CCR_REPLACEMENTS = {1224 0x80: 0x20ac,1225 0x82: 0x201a,1226 0x83: 0x0192,1227 0x84: 0x201e,1228 0x85: 0x2026,1229 0x86: 0x2020,1230 0x87: 0x2021,1231 0x88: 0x02c6,1232 0x89: 0x2030,1233 0x8a: 0x0160,1234 0x8b: 0x2039,1235 0x8c: 0x0152,1236 0x8e: 0x017d,1237 0x91: 0x2018,1238 0x92: 0x2019,1239 0x93: 0x201c,1240 0x94: 0x201d,1241 0x95: 0x2022,1242 0x96: 0x2013,1243 0x97: 0x2014,1244 0x98: 0x02dc,1245 0x99: 0x2122,1246 0x9a: 0x0161,1247 0x9b: 0x203a,1248 0x9c: 0x0153,1249 0x9e: 0x017e,1250 0x9f: 0x01781251};1252function hoistStatic(root, context) {1253 walk(root.children, context, new Map(), isSingleElementRoot(root, root.children[0]));1254}1255function isSingleElementRoot(root, child) {1256 const { children } = root;1257 return (children.length === 1 &&1258 child.type === 1 /* ELEMENT */ &&1259 !isSlotOutlet(child));1260}1261function walk(children, context, resultCache, doNotHoistNode = false) {1262 for (let i = 0; i < children.length; i++) {1263 const child = children[i];1264 // only plain elements are eligible for hoisting.1265 if (child.type === 1 /* ELEMENT */ &&1266 child.tagType === 0 /* ELEMENT */) {1267 if (!doNotHoistNode && isStaticNode(child, resultCache)) {1268 // whole tree is static1269 child.codegenNode = context.hoist(child.codegenNode);1270 continue;1271 }1272 else {1273 // node may contain dynamic children, but its props may be eligible for1274 // hoisting.1275 const codegenNode = child.codegenNode;1276 if (codegenNode.type === 13 /* JS_CALL_EXPRESSION */) {1277 const flag = getPatchFlag(codegenNode);1278 if ((!flag ||1279 flag === 32 /* NEED_PATCH */ ||1280 flag === 1 /* TEXT */) &&1281 !hasDynamicKeyOrRef(child) &&1282 !hasCachedProps(child)) {1283 const props = getNodeProps(child);1284 if (props && props !== `null`) {1285 getVNodeCall(codegenNode).arguments[1] = context.hoist(props);1286 }1287 }1288 }1289 }1290 }1291 if (child.type === 1 /* ELEMENT */) {1292 walk(child.children, context, resultCache);1293 }1294 else if (child.type === 11 /* FOR */) {1295 // Do not hoist v-for single child because it has to be a block1296 walk(child.children, context, resultCache, child.children.length === 1);1297 }1298 else if (child.type === 9 /* IF */) {1299 for (let i = 0; i < child.branches.length; i++) {1300 const branchChildren = child.branches[i].children;1301 // Do not hoist v-if single child because it has to be a block1302 walk(branchChildren, context, resultCache, branchChildren.length === 1);1303 }1304 }1305 }1306}1307function isStaticNode(node, resultCache = new Map()) {1308 switch (node.type) {1309 case 1 /* ELEMENT */:1310 if (node.tagType !== 0 /* ELEMENT */) {1311 return false;1312 }1313 const cached = resultCache.get(node);1314 if (cached !== undefined) {1315 return cached;1316 }1317 const codegenNode = node.codegenNode;1318 if (codegenNode.type !== 13 /* JS_CALL_EXPRESSION */) {1319 return false;1320 }1321 const flag = getPatchFlag(codegenNode);1322 if (!flag && !hasDynamicKeyOrRef(node) && !hasCachedProps(node)) {1323 // element self is static. check its children.1324 for (let i = 0; i < node.children.length; i++) {1325 if (!isStaticNode(node.children[i], resultCache)) {1326 resultCache.set(node, false);1327 return false;1328 }1329 }1330 resultCache.set(node, true);1331 return true;1332 }1333 else {1334 resultCache.set(node, false);1335 return false;1336 }1337 case 2 /* TEXT */:1338 case 3 /* COMMENT */:1339 return true;1340 case 9 /* IF */:1341 case 11 /* FOR */:1342 return false;1343 case 5 /* INTERPOLATION */:1344 case 12 /* TEXT_CALL */:1345 return isStaticNode(node.content, resultCache);1346 case 4 /* SIMPLE_EXPRESSION */:1347 return node.isConstant;1348 case 8 /* COMPOUND_EXPRESSION */:1349 return node.children.every(child => {1350 return (isString(child) || isSymbol(child) || isStaticNode(child, resultCache));1351 });1352 default:1353 return false;1354 }1355}1356function hasDynamicKeyOrRef(node) {1357 return !!(findProp(node, 'key', true) || findProp(node, 'ref', true));1358}1359function hasCachedProps(node) {1360 const props = getNodeProps(node);1361 if (props &&1362 props !== 'null' &&1363 props.type === 14 /* JS_OBJECT_EXPRESSION */) {1364 const { properties } = props;1365 for (let i = 0; i < properties.length; i++) {1366 if (properties[i].value.type === 20 /* JS_CACHE_EXPRESSION */) {1367 return true;1368 }1369 }1370 }1371 return false;1372}1373function getNodeProps(node) {1374 const codegenNode = node.codegenNode;1375 if (codegenNode.type === 13 /* JS_CALL_EXPRESSION */) {1376 return getVNodeArgAt(codegenNode, 1);1377 }1378}1379function getVNodeArgAt(node, index) {1380 return getVNodeCall(node).arguments[index];1381}1382function getVNodeCall(node) {1383 return node.callee === WITH_DIRECTIVES ? node.arguments[0] : node;1384}1385function getPatchFlag(node) {1386 const flag = getVNodeArgAt(node, 3);1387 return flag ? parseInt(flag, 10) : undefined;1388}1389function createTransformContext(root, { prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, onError = defaultOnError }) {1390 const context = {1391 root,1392 helpers: new Set(),1393 components: new Set(),1394 directives: new Set(),1395 hoists: [],1396 cached: 0,1397 identifiers: {},1398 scopes: {1399 vFor: 0,1400 vSlot: 0,1401 vPre: 0,1402 vOnce: 01403 },1404 prefixIdentifiers,1405 hoistStatic,1406 cacheHandlers,1407 nodeTransforms,1408 directiveTransforms,1409 onError,1410 parent: null,1411 currentNode: root,1412 childIndex: 0,1413 helper(name) {1414 context.helpers.add(name);1415 return name;1416 },1417 helperString(name) {1418 return ((context.prefixIdentifiers ? `` : `_`) +1419 helperNameMap[context.helper(name)]);1420 },1421 replaceNode(node) {1422 context.parent.children[context.childIndex] = context.currentNode = node;1423 },1424 removeNode(node) {1425 const list = context.parent.children;1426 const removalIndex = node1427 ? list.indexOf(node)1428 : context.currentNode1429 ? context.childIndex1430 : -1;1431 if (!node || node === context.currentNode) {1432 // current node removed1433 context.currentNode = null;1434 context.onNodeRemoved();1435 }1436 else {1437 // sibling node removed1438 if (context.childIndex > removalIndex) {1439 context.childIndex--;1440 context.onNodeRemoved();1441 }1442 }1443 context.parent.children.splice(removalIndex, 1);1444 },1445 onNodeRemoved: () => { },1446 addIdentifiers(exp) {1447 // identifier tracking only happens in non-browser builds.1448 {1449 if (isString(exp)) {1450 addId(exp);1451 }1452 else if (exp.identifiers) {1453 exp.identifiers.forEach(addId);1454 }1455 else if (exp.type === 4 /* SIMPLE_EXPRESSION */) {1456 addId(exp.content);1457 }1458 }1459 },1460 removeIdentifiers(exp) {1461 {1462 if (isString(exp)) {1463 removeId(exp);1464 }1465 else if (exp.identifiers) {1466 exp.identifiers.forEach(removeId);1467 }1468 else if (exp.type === 4 /* SIMPLE_EXPRESSION */) {1469 removeId(exp.content);1470 }1471 }1472 },1473 hoist(exp) {1474 context.hoists.push(exp);1475 return createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, true);1476 },1477 cache(exp, isVNode = false) {1478 return createCacheExpression(++context.cached, exp, isVNode);1479 }1480 };1481 function addId(id) {1482 const { identifiers } = context;1483 if (identifiers[id] === undefined) {1484 identifiers[id] = 0;1485 }1486 identifiers[id]++;1487 }1488 function removeId(id) {1489 context.identifiers[id]--;1490 }1491 return context;1492}...
codegen.js
Source:codegen.js
...103 alternate,104 loc: locStub105 };106}107function createCacheExpression(index, value, isVNode = false) {108 return {109 type: 20 /* JS_CACHE_EXPRESSION */,110 index,111 value,112 isVNode,113 loc: locStub114 };115}116function createElementWithCodegen(args) {117 return {118 type: 1,119 loc: locStub,120 ns: 0,121 tag: 'div',122 tagType: 0,123 isSelfClosing: false,124 props: [],125 children: [],126 codegenNode: {127 type: 13,128 loc: locStub,129 callee: CREATE_VNODE,130 arguments: args131 }132 }133}134/**135 * @function createRoot 136 * éè¿ä¸é¢å¯ä»¥åç°ï¼è¿ä¸ªæ¹æ³å°±æ¯è¿åä¸ä¸ªæ ¹èç¹ãæåæ°å并è¿å»137 */138const root = createRoot({139 helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]140})141const rootResult = { 142 type: 0,143 children: [],144 helpers: [ CREATE_VNODE, RESOLVE_DIRECTIVE ],145 components: [],146 directives: [],147 hoists: [],148 cached: 0,149 codegenNode: { 150 type: 4,151 loc: [null],152 isConstant: false,153 content: 'null',154 isStatic: false 155 },156 loc: 'USELESS2' 157}158/**159 * @param { Number 001 }160 * @function generate 161 * æ¹æ³å
¥åï¼æ ¹èç¹rootãmodule模å¼162 * æ¹æ³åºåï¼astãcode163 * æ¹æ³æ»ç»ï¼164 * 1ãgenerateè½å¤import helperséé¢å¯¹åºç模å165 */166const untest001 = generate(root, { mode: 'module' })167const output001 = { 168 ast: { 169 type: 0,170 children: [],171 helpers: [ CREATE_VNODE, RESOLVE_DIRECTIVE ],172 components: [],173 directives: [],174 hoists: [],175 cached: 0,176 codegenNode: { 177 type: 4,178 loc: [null],179 isConstant: false,180 content: 'null',181 isStatic: false 182 },183 loc: 'USELESS2' 184 },185 code: `186 import { createVNode, resolveDirective } from "vue"187 export default function render() {188 const _ctx = this189 return null190 }191 `,192 map: undefined 193}194/**195 * @symbol 196 * å
³æ³¨ç¹ï¼æ们å¯ä»¥ççVueéé¢æ¯å¦ä½ä½¿ç¨symbolç197 */198function anonymous(){199 const result = `import { ${helperNameMap[CREATE_VNODE]}, ${200 helperNameMap[RESOLVE_DIRECTIVE]201 } } from "vue"`202 const CREATE_VNODE = Symbol('createVNode')203 const RESOLVE_DIRECTIVE = Symbol('resolveDirective')204 const helperNameMap = {205 [CREATE_VNODE]: 'createVNode',206 [RESOLVE_DIRECTIVE]: 'resolveDirective',207 }208 // import { createVNode, resolveDirective } from "vue"209}210/**211 * @param { Number 002 }212 * @function generate 213 * æ¹æ³å
¥åï¼æ ¹èç¹rootãfunction模å¼214 * æ¹æ³åºåï¼astãcode215 * æ¹æ³æ»ç»ï¼216 * 1ãgenerateè½å¤import helperséé¢å¯¹åºç模å217 * 2ã并ä¸ä¼å ä¸ä¸å线çé¢å¤ç218 */219const untest002 = generate(root, { mode: 'function' })220const output002 = { 221 ast: { 222 root223 },224 code: `225 const _Vue = Vue226 return function render() {227 with (this) {228 const { createVNode: _createVNode , resolveDirective: _resolveDirective } = _Vue229 return null230 }231 }`,232 map: undefined 233}234/**235 * @param { Number 003 }236 * @function generate237 * æ¹æ³å
¥åï¼æ ¹èç¹rootãfunction模å¼ãåç¼æ å¿ç¬¦true238 * æ¹æ³åºåï¼astãcode239 * æ¹æ³æ»ç»ï¼240 * 1ãä¸å
å«const _Vue241 * 2ãå
å«å¯¹helperséé¢ç解æèµå¼242 */243const untest003 = generate(root, { mode: 'function', prefixIdentifiers: true })244const output003 = { 245 ast: { 246 root247 },248 code: `249 const { createVNode, resolveDirective } = Vue250 return function render() {251 const _ctx = this252 return null253 }254 `,255 map: undefined 256}257/**258 * @param { Number 004 }259 * @function generate260 * æ¹æ³å
¥åï¼æ ¹èç¹root2ãfunction模å¼261 * æ¹æ³åºåï¼astãcode262 * æ¹æ³æ»ç»ï¼263 * 1ãè½å¤æ ¹æ®æ ¹èç¹root2éé¢çcomponentsãdirectivesï¼å¨ä»£ç ä¸æ£ç¡®çconstå¼åº264 */265const root2 = createRoot({266 components: [`Foo`, `bar-baz`, `barbaz`],267 directives: [`my_dir`]268})269const untest004 = generate(root2, { mode: 'function' })270const output004 = { 271 ast: { 272 components: [ 'Foo', 'bar-baz', 'barbaz' ],273 directives: [ 'my_dir' ],274 ...root2275 },276 code: `277 return function render() {278 with (this) {279 const _component_Foo = _resolveComponent("Foo")280 const _component_bar_baz = _resolveComponent("bar-baz")281 const _component_barbaz = _resolveComponent("barbaz")282 const _directive_my_dir = _resolveDirective("my_dir")283 return null284 }285 }286 `,287 map: undefined 288}289/**290 * @param { Number 005 }291 * @function generate292 * æ¹æ³å
¥åï¼hoistsï¼å符串293 * æ¹æ³åºåï¼astãcode294 * æ¹æ³æ»ç»ï¼295 * 1ãcreateSimpleExpression å建ä¸ä¸ªå£°æå符串ç表达å¼296 * 2ãcreateObjectExpression å建ä¸ä¸ªå¯¹è±¡297 * 3ãcreateObjectProperty å建ä¸ä¸ªå¯¹è±¡çå±æ§298 */299const root3 = createRoot({300 hoists: [301 createSimpleExpression(`hello`, false, locStub),302 createObjectExpression(303 [304 createObjectProperty(305 createSimpleExpression(`id`, true, locStub),306 createSimpleExpression(`foo`, true, locStub)307 )308 ],309 locStub310 )311 ]312})313const untest005 = generate(root3)314const output005 = { 315 ast: { 316 root317 },318 code:`319 const _hoisted_1 = hello320 const _hoisted_2 = { id: "foo" }321 return function render() {322 with (this) {323 return null324 }325 }326 `,327 map: undefined 328}329/**330 * @param { Number 006 }331 * @function generate prefixIdentifiers332 * æ¹æ³å
¥åï¼ç©ºrootï¼åç¼è¡¨è¾¾å¼false333 * æ¹æ³åºåï¼astãcode334 * æ¹æ³æ»ç»ï¼335 * 1ãå
å«const _ctx = this 336 */337const untest006 = generate(createRoot(), { prefixIdentifiers: true })338const output006 = { 339 ast: { 340 root341 },342 code:`343 return function render() { 344 const _ctx = this 345 return null346 }347 `,348 map: undefined 349}350/**351 * @param { Number 007 }352 * @function generate 353 * æ¹æ³å
¥åï¼codegenNode354 * æ¹æ³åºåï¼astãcode355 * æ¹æ³æ»ç»ï¼356 * 1ãé对NodeTypes.TEXTç±»åï¼è½å¤è¿åcodegenNodeéé¢çcontentå段357 */358const untest007 = generate(359 createRoot({360 codegenNode: {361 type: 2,362 content: 'hello',363 loc: locStub364 }365 })366)367var output007 = { 368 ast: { 369 root370 },371 code:`372 return function render() {373 with (this) {374 return "hello" 375 }376 }377 `,378 map: undefined 379}380/**381 * @param { Number 008 }382 * @function generate interpolation383 * æ¹æ³å
¥åï¼codegenNode å建æå¼384 * æ¹æ³åºåï¼astãcode385 * æ¹æ³æ»ç»ï¼386 * 1ãé对createInterpolationï¼è½å¤è¿ååæ°çtoString387 */388const untest008 = generate(389 createRoot({390 codegenNode: createInterpolation(`hello`, locStub)391 })392)393const output008 = {394 ast: {395 },396 code:`397 return function render() {398 with (this) {399 return _toString(hello) 400 }401 }402 `403}404/**405 * @param { Number 009 }406 * @function generate 407 * æ¹æ³å
¥åï¼codegenNode å建æå¼408 * æ¹æ³åºåï¼astãcode409 * æ¹æ³æ»ç»ï¼410 * 1ãé对NodeTypes.COMMENTï¼è½å¤è¿ååæ°ç_createCommentVNode411 */412const untest009 = generate(413 createRoot({414 codegenNode: {415 type: 3,416 content: 'foo',417 loc: {}418 }419 })420)421const output009 = { 422 ast: {423 },424 code: `425 return function render() {426 with (this) {427 return _createCommentVNode("foo")428 }429 }430 `,431 map: undefined 432}433/**434 * @param { Number 010 }435 * @function generate 436 * æ¹æ³å
¥åï¼codegenNode å建å¤å表达å¼437 * æ¹æ³åºåï¼astãcode438 * æ¹æ³æ»ç»ï¼439 * 1ãé对createCompoundExpressionï¼è½å¤è¿åæ£ç¡®çåç¼ + toString440 */441const untest010 = generate(442 createRoot({443 codegenNode: createCompoundExpression([444 `_ctx.`,445 createSimpleExpression(`foo`, false, locStub),446 ` + `,447 {448 type: 5,449 loc: locStub,450 content: createSimpleExpression(`bar`, false, locStub)451 }452 ])453 })454)455const output010 = { 456 ast: {457 },458 code: `459 return function render() {460 with (this) {461 return _ctx.foo + _toString(bar)462 }463 }464 `,465 map: undefined 466}467/**468 * @param { Number 011 }469 * @function generate 470 * æ¹æ³å
¥åï¼codegenNode å建åºå表达å¼471 * æ¹æ³åºåï¼astãcode472 * æ¹æ³æ»ç»ï¼473 * 1ãNodeTypes.IF474 */475const untest011 = generate(476 createRoot({477 codegenNode: {478 type: 9,479 loc: locStub,480 branches: [],481 codegenNode: createSequenceExpression([482 createSimpleExpression('foo', false),483 createSimpleExpression('bar', false)484 ])485 }486 })487)488const output011 = { 489 ast: {490 },491 code:492 `return function render() {493 with (this) {494 return (foo, bar)495 }496 }497 `,498 map: undefined 499}500/**501 * @param { Number 012 }502 * @function generate 503 * æ¹æ³å
¥åï¼codegenNode å建åºå表达å¼504 * æ¹æ³åºåï¼astãcode505 * æ¹æ³æ»ç»ï¼506 * 1ãé对NodeTypes.IF507 */508const expression012 = generate(509 createRoot({510 codegenNode: {511 type: 11,512 loc: locStub,513 source: createSimpleExpression('foo', false),514 valueAlias: undefined,515 keyAlias: undefined,516 objectIndexAlias: undefined,517 children: [],518 codegenNode: createSequenceExpression([519 createSimpleExpression('foo', false),520 createSimpleExpression('bar', false)521 ])522 }523 })524)525const result012 = { ast:526 { type: 0,527 children: [],528 helpers: [],529 components: [],530 directives: [],531 hoists: [],532 cached: 0,533 codegenNode:534 { type: 11,535 loc: [Object],536 source: [Object],537 valueAlias: undefined,538 keyAlias: undefined,539 objectIndexAlias: undefined,540 children: [],541 codegenNode: [Object] },542 loc: 'USELESS2' },543 code:544 `545 return function render() {546 with (this) {547 return (foo, bar)548 }549 }550 `,551 map: undefined }552 /**553 * @param { Number 013 }554 * @function generate 555 * æ¹æ³å
¥åï¼556 * æ¹æ³åºåï¼557 * æ¹æ³æ»ç»ï¼558 * 1ã559 */560const expression013 = generate(561 createRoot({562 codegenNode: createElementWithCodegen([563 // string564 `"div"`,565 // ObjectExpression566 createObjectExpression(567 [568 createObjectProperty(569 createSimpleExpression(`id`, true, locStub),570 createSimpleExpression(`foo`, true, locStub)571 ),572 createObjectProperty(573 createSimpleExpression(`prop`, false, locStub),574 createSimpleExpression(`bar`, false, locStub)575 ),576 // compound expression as computed key577 createObjectProperty(578 {579 type: 8,580 loc: locStub,581 children: [582 `foo + `,583 createSimpleExpression(`bar`, false, locStub)584 ]585 },586 createSimpleExpression(`bar`, false, locStub)587 )588 ],589 locStub590 ),591 // ChildNode[]592 [593 createElementWithCodegen([594 `"p"`,595 createObjectExpression(596 [597 createObjectProperty(598 // should quote the key!599 createSimpleExpression(`some-key`, true, locStub),600 createSimpleExpression(`foo`, true, locStub)601 )602 ],603 locStub604 )605 ])606 ],607 // flag608 (1 << 4) + ''609 ])610 })611)612const result013 = { ast:613 { type: 0,614 children: [],615 helpers: [],616 components: [],617 directives: [],618 hoists: [],619 cached: 0,620 codegenNode:621 { type: 1,622 loc: [Object],623 ns: 0,624 tag: 'div',625 tagType: 0,626 isSelfClosing: false,627 props: [],628 children: [],629 codegenNode: [Object] },630 loc: 'USELESS2' },631 code:632 `633 return function render() {634 with (this) {635 return _createVNode("div", {636 id: "foo",637 [prop]: bar,638 [foo + bar]: bar639 }, [640 _createVNode("p", { "some-key": "foo" })641 ], 16)642 }643 }644 `,645 map: undefined }646/**647 * @param { Number 014 }648 * @function generate 649 * æ¹æ³å
¥åï¼650 * æ¹æ³åºåï¼651 * æ¹æ³æ»ç»ï¼652 * 1ã653 */654const expression014 = generate(655 createRoot({656 codegenNode: createArrayExpression([657 createSimpleExpression(`foo`, false),658 createCallExpression(`bar`, [`baz`])659 ])660 })661)662const result014 = { ast:663 { type: 0,664 children: [],665 helpers: [],666 components: [],667 directives: [],668 hoists: [],669 cached: 0,670 codegenNode: { type: 16, loc: undefined, elements: [Array] },671 loc: 'USELESS2' },672 code:673 `674 return function render() {675 with (this) {676 return [677 foo,678 bar(baz)679 ]680 }681 }682 `,683 map: undefined }684/**685 * @param { Number 015 }686 * @function generate 687 * æ¹æ³å
¥åï¼688 * æ¹æ³åºåï¼689 * æ¹æ³æ»ç»ï¼690 * 1ã691 */692const expression015 = generate(693 createRoot({694 codegenNode: createSequenceExpression([695 createSimpleExpression(`foo`, false),696 createCallExpression(`bar`, [`baz`])697 ])698 })699)700const result015 = { ast:701 { type: 0,702 children: [],703 helpers: [],704 components: [],705 directives: [],706 hoists: [],707 cached: 0,708 codegenNode: { type: 18, expressions: [Array], loc: [Object] },709 loc: 'USELESS2' },710 code:711 `712 return function render() {713 with (this) {714 return (foo, bar(baz))715 }716 }717 `,718 map: undefined }719/**720 * @param { Number 016 }721 * @function generate 722 * æ¹æ³å
¥åï¼723 * æ¹æ³åºåï¼724 * æ¹æ³æ»ç»ï¼725 * 1ã726 */727const expression016 = generate(728 createRoot({729 codegenNode: createConditionalExpression(730 createSimpleExpression(`ok`, false),731 createCallExpression(`foo`),732 createConditionalExpression(733 createSimpleExpression(`orNot`, false),734 createCallExpression(`bar`),735 createCallExpression(`baz`)736 )737 )738 })739)740const result016 = { ast:741 { type: 0,742 children: [],743 helpers: [],744 components: [],745 directives: [],746 hoists: [],747 cached: 0,748 codegenNode:749 { type: 19,750 test: [Object],751 consequent: [Object],752 alternate: [Object],753 loc: [Object] },754 loc: 'USELESS2' },755 code:756 `757 return function render() {758 with (this) {759 return ok760 ? foo()761 : orNot762 ? bar()763 : baz()764 }765 }766 `,767 map: undefined }768/**769 * @param { Number 017 }770 * @function generate 771 * æ¹æ³å
¥åï¼772 * æ¹æ³åºåï¼773 * æ¹æ³æ»ç»ï¼774 * 1ã775 */776const expression017 = generate(777 createRoot({778 cached: 1,779 codegenNode: createCacheExpression(780 1,781 createSimpleExpression(`foo`, false)782 )783 }),784 {785 mode: 'module',786 prefixIdentifiers: true787 }788)789const result017 = { ast:790 { type: 0,791 children: [],792 helpers: [],793 components: [],794 directives: [],795 hoists: [],796 cached: 1,797 codegenNode:798 { type: 20,799 index: 1,800 value: [Object],801 isVNode: false,802 loc: [Object] },803 loc: 'USELESS2' },804 code:805 `806 export default function render() {807 const _ctx = this808 const _cache = _ctx.$cache809 return _cache[1] || (_cache[1] = foo)810 }811 `,812 map: undefined }813/**814 * @param { Number 018 }815 * @function generate 816 * æ¹æ³å
¥åï¼817 * æ¹æ³åºåï¼818 * æ¹æ³æ»ç»ï¼819 * 1ã820 */821const expression018 = generate(822 createRoot({823 cached: 1,824 codegenNode: createCacheExpression(825 1,826 createSimpleExpression(`foo`, false),827 true828 )829 }),830 {831 mode: 'module',832 prefixIdentifiers: true833 }834)835const result018 = { ast:836 { type: 0,837 children: [],838 helpers: [],...
~codegen.js
Source:~codegen.js
...114 alternate,115 loc: locStub116 };117}118function createCacheExpression(index, value, isVNode = false) {119 return {120 type: 20 /* JS_CACHE_EXPRESSION */,121 index,122 value,123 isVNode,124 loc: locStub125 };126}127function createElementWithCodegen(args) {128 return {129 type: 1,130 loc: locStub,131 ns: 0,132 tag: 'div',133 tagType: 0,134 isSelfClosing: false,135 props: [],136 children: [],137 codegenNode: {138 type: 13,139 loc: locStub,140 callee: CREATE_VNODE,141 arguments: args142 }143 }144}145/**146 * @function createRoot 147 * éè¿ä¸é¢å¯ä»¥åç°ï¼è¿ä¸ªæ¹æ³å°±æ¯è¿åä¸ä¸ªæ ¹èç¹ãæåæ°å并è¿å»148 */149const root = createRoot({150 helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]151})152const rootResult = { 153 type: 0,154 helpers: [ CREATE_VNODE, RESOLVE_DIRECTIVE ],155 codegenNode: { 156 type: 4,157 loc: [null],158 isConstant: false,159 content: 'null',160 isStatic: false 161 },162 loc: 'USELESS2' 163}164/**165 * @param { Number 001 }166 * @function generate 167 * æ¹æ³å
¥åï¼æ ¹èç¹rootãmodule模å¼168 * æ¹æ³åºåï¼astãcode169 * æ¹æ³æ»ç»ï¼170 * 1ãgenerateè½å¤import helperséé¢å¯¹åºç模å171 */172const untest001 = generate(root, { mode: 'module' })173const output001 = { 174 ast: { 175 type: 0,176 children: [],177 helpers: [ CREATE_VNODE, RESOLVE_DIRECTIVE ],178 components: [],179 directives: [],180 hoists: [],181 cached: 0,182 codegenNode: { 183 type: 4,184 loc: [null],185 isConstant: false,186 content: 'null',187 isStatic: false 188 },189 loc: 'USELESS2' 190 },191 code: `192 import { createVNode, resolveDirective } from "vue"193 export default function render() {194 const _ctx = this195 return null196 }197 `,198 map: undefined 199}200/**201 * @symbol 202 * å
³æ³¨ç¹ï¼æ们å¯ä»¥ççVueéé¢æ¯å¦ä½ä½¿ç¨symbolç203 */204function anonymous(){205 const result = `import { ${helperNameMap[CREATE_VNODE]}, ${206 helperNameMap[RESOLVE_DIRECTIVE]207 } } from "vue"`208 const CREATE_VNODE = Symbol('createVNode')209 const RESOLVE_DIRECTIVE = Symbol('resolveDirective')210 const helperNameMap = {211 [CREATE_VNODE]: 'createVNode',212 [RESOLVE_DIRECTIVE]: 'resolveDirective',213 }214 // import { createVNode, resolveDirective } from "vue"215}216/**217 * @param { Number 002 }218 * @function generate 219 * æ¹æ³å
¥åï¼æ ¹èç¹rootãfunction模å¼220 * æ¹æ³åºåï¼astãcode221 * æ¹æ³æ»ç»ï¼222 * 1ãgenerateè½å¤import helperséé¢å¯¹åºç模å223 * 2ã并ä¸ä¼å ä¸ä¸å线çé¢å¤ç224 */225const untest002 = generate(root, { mode: 'function' })226const output002 = { 227 ast: { 228 root229 },230 code: `231 const _Vue = Vue232 return function render() {233 with (this) {234 const { createVNode: _createVNode , resolveDirective: _resolveDirective } = _Vue235 return null236 }237 }`,238 map: undefined 239}240/**241 * @param { Number 003 }242 * @function generate243 * æ¹æ³å
¥åï¼æ ¹èç¹rootãfunction模å¼ãåç¼æ å¿ç¬¦true244 * æ¹æ³åºåï¼astãcode245 * æ¹æ³æ»ç»ï¼246 * 1ãä¸å
å«const _Vue247 * 2ãå
å«å¯¹helperséé¢ç解æèµå¼248 */249const untest003 = generate(root, { mode: 'function', prefixIdentifiers: true })250const output003 = { 251 ast: { 252 root253 },254 code: `255 const { createVNode, resolveDirective } = Vue256 return function render() {257 const _ctx = this258 return null259 }260 `,261 map: undefined 262}263/**264 * @param { Number 004 }265 * @function generate266 * æ¹æ³å
¥åï¼æ ¹èç¹root2ãfunction模å¼267 * æ¹æ³åºåï¼astãcode268 * æ¹æ³æ»ç»ï¼269 * 1ãè½å¤æ ¹æ®æ ¹èç¹root2éé¢çcomponentsãdirectivesï¼å¨ä»£ç ä¸æ£ç¡®çconstå¼åº270 */271const root2 = createRoot({272 components: [`Foo`, `bar-baz`, `barbaz`],273 directives: [`my_dir`]274})275const untest004 = generate(root2, { mode: 'function' })276const output004 = { 277 ast: { 278 components: [ 'Foo', 'bar-baz', 'barbaz' ],279 directives: [ 'my_dir' ],280 ...root2281 },282 code: `283 return function render() {284 with (this) {285 const _component_Foo = _resolveComponent("Foo")286 const _component_bar_baz = _resolveComponent("bar-baz")287 const _component_barbaz = _resolveComponent("barbaz")288 const _directive_my_dir = _resolveDirective("my_dir")289 return null290 }291 }292 `,293 map: undefined 294}295/**296 * @param { Number 005 }297 * @function generate298 * æ¹æ³å
¥åï¼hoistsï¼å符串299 * æ¹æ³åºåï¼astãcode300 * æ¹æ³æ»ç»ï¼301 * 1ãcreateSimpleExpression å建ä¸ä¸ªå£°æå符串ç表达å¼302 * 2ãcreateObjectExpression å建ä¸ä¸ªå¯¹è±¡303 * 3ãcreateObjectProperty å建ä¸ä¸ªå¯¹è±¡çå±æ§304 */305const root3 = createRoot({306 hoists: [307 createSimpleExpression(`hello`, false, locStub),308 createObjectExpression(309 [310 createObjectProperty(311 createSimpleExpression(`id`, true, locStub),312 createSimpleExpression(`foo`, true, locStub)313 )314 ],315 locStub316 )317 ]318})319const untest005 = generate(root3)320const output005 = { 321 ast: { 322 root323 },324 code:`325 const _hoisted_1 = hello326 const _hoisted_2 = { id: "foo" }327 return function render() {328 with (this) {329 return null330 }331 }332 `,333 map: undefined 334}335/**336 * @param { Number 006 }337 * @function generate prefixIdentifiers338 * æ¹æ³å
¥åï¼ç©ºrootï¼åç¼è¡¨è¾¾å¼false339 * æ¹æ³åºåï¼astãcode340 * æ¹æ³æ»ç»ï¼341 * 1ãå
å«const _ctx = this 342 */343const untest006 = generate(createRoot(), { prefixIdentifiers: true })344const output006 = { 345 ast: { 346 root347 },348 code:`349 return function render() { 350 const _ctx = this 351 return null352 }353 `,354 map: undefined 355}356/**357 * @param { Number 007 }358 * @function generate 359 * æ¹æ³å
¥åï¼codegenNode360 * æ¹æ³åºåï¼astãcode361 * æ¹æ³æ»ç»ï¼362 * 1ãé对NodeTypes.TEXTç±»åï¼è½å¤è¿åcodegenNodeéé¢çcontentå段363 */364const untest007 = generate(365 createRoot({366 codegenNode: {367 type: 2,368 content: 'hello',369 loc: locStub370 }371 })372)373var output007 = { 374 ast: { 375 root376 },377 code:`378 return function render() {379 with (this) {380 return "hello" 381 }382 }383 `,384 map: undefined 385}386/**387 * @param { Number 008 }388 * @function generate interpolation389 * æ¹æ³å
¥åï¼codegenNode å建æå¼390 * æ¹æ³åºåï¼astãcode391 * æ¹æ³æ»ç»ï¼392 * 1ãé对createInterpolationï¼è½å¤è¿ååæ°çtoString393 */394const untest008 = generate(395 createRoot({396 codegenNode: createInterpolation(`hello`, locStub)397 })398)399const output008 = {400 ast: {401 },402 code:`403 return function render() {404 with (this) {405 return _toString(hello) 406 }407 }408 `409}410/**411 * @param { Number 009 }412 * @function generate 413 * æ¹æ³å
¥åï¼codegenNode å建æå¼414 * æ¹æ³åºåï¼astãcode415 * æ¹æ³æ»ç»ï¼416 * 1ãé对NodeTypes.COMMENTï¼è½å¤è¿ååæ°ç_createCommentVNode417 */418const untest009 = generate(419 createRoot({420 codegenNode: {421 type: 3,422 content: 'foo',423 loc: {}424 }425 })426)427const output009 = { 428 ast: {429 },430 code: `431 return function render() {432 with (this) {433 return _createCommentVNode("foo")434 }435 }436 `,437 map: undefined 438}439/**440 * @param { Number 010 }441 * @function generate 442 * æ¹æ³å
¥åï¼codegenNode å建å¤å表达å¼443 * æ¹æ³åºåï¼astãcode444 * æ¹æ³æ»ç»ï¼445 * 1ãé对createCompoundExpressionï¼è½å¤è¿åæ£ç¡®çåç¼ + toString446 */447const untest010 = generate(448 createRoot({449 codegenNode: createCompoundExpression([450 `_ctx.`,451 createSimpleExpression(`foo`, false, locStub),452 ` + `,453 {454 type: 5,455 loc: locStub,456 content: createSimpleExpression(`bar`, false, locStub)457 }458 ])459 })460)461const output010 = { 462 ast: {463 },464 code: `465 return function render() {466 with (this) {467 return _ctx.foo + _toString(bar)468 }469 }470 `,471 map: undefined 472}473/**474 * @param { Number 011 }475 * @function generate 476 * æ¹æ³å
¥åï¼codegenNode å建åºå表达å¼477 * æ¹æ³åºåï¼astãcode478 * æ¹æ³æ»ç»ï¼479 * 1ãé对NodeTypes.IFï¼è½è¿ååºå表达å¼åæ°480 */481const untest011 = generate(482 createRoot({483 codegenNode: {484 type: 9,485 loc: locStub,486 branches: [],487 codegenNode: createSequenceExpression([488 createSimpleExpression('foo', false),489 createSimpleExpression('bar', false)490 ])491 }492 })493)494const output011 = { 495 ast: {496 },497 code:498 `return function render() {499 with (this) {500 return (foo, bar)501 }502 }503 `,504 map: undefined 505}506/**507 * @param { Number 012 }508 * @function generate 509 * æ¹æ³å
¥åï¼codegenNode å建åºå表达å¼510 * æ¹æ³åºåï¼astãcode511 * æ¹æ³æ»ç»ï¼512 * 1ãé对NodeTypes.FORï¼è½è¿ååºå表达å¼åæ°513 */514const untest012 = generate(515 createRoot({516 codegenNode: {517 type: 11,518 loc: locStub,519 source: createSimpleExpression('foo', false),520 valueAlias: undefined,521 keyAlias: undefined,522 objectIndexAlias: undefined,523 children: [],524 codegenNode: createSequenceExpression([525 createSimpleExpression('foo', false),526 createSimpleExpression('bar', false)527 ])528 }529 })530)531const output012 = { 532 ast: {533 },534 code:`535 return function render() {536 with (this) {537 return (foo, bar)538 }539 }540 `,541 map: undefined 542}543 /**544 * @param { Number 013 }545 * @function generate 546 * æ¹æ³å
¥åï¼è¥å¹²æ¹æ³ï¼å建vnode547 * æ¹æ³åºåï¼astãcode548 * æ¹æ³æ»ç»ï¼549 * 0ãcreateElementWithCodegen æ ¹æ®Codegenå建对象550 * 1ãcreateSimpleExpression å建ä¸ä¸ªå£°æå符串ç表达å¼551 * 2ãcreateObjectExpression å建ä¸ä¸ªå¯¹è±¡552 * 3ãcreateObjectProperty å建ä¸ä¸ªå¯¹è±¡çå±æ§553 */554const untest013 = generate(555 createRoot({556 codegenNode: createElementWithCodegen([557 // string558 `"div"`,559 // ObjectExpression560 createObjectExpression(561 [562 createObjectProperty(563 createSimpleExpression(`id`, true, locStub),564 createSimpleExpression(`foo`, true, locStub)565 ),566 createObjectProperty(567 createSimpleExpression(`prop`, false, locStub),568 createSimpleExpression(`bar`, false, locStub)569 ),570 // compound expression as computed key571 createObjectProperty(572 {573 type: 8,574 loc: locStub,575 children: [576 `foo + `,577 createSimpleExpression(`bar`, false, locStub)578 ]579 },580 createSimpleExpression(`bar`, false, locStub)581 )582 ],583 locStub584 ),585 // ChildNode[]586 [587 createElementWithCodegen([588 `"p"`,589 createObjectExpression(590 [591 createObjectProperty(592 // should quote the key!593 createSimpleExpression(`some-key`, true, locStub),594 createSimpleExpression(`foo`, true, locStub)595 )596 ],597 locStub598 )599 ])600 ],601 // flag602 (1 << 4) + ''603 ])604 })605)606const output013 = { 607 ast: {608 },609 code: `610 return function render() {611 with (this) {612 return _createVNode("div", {613 id: "foo",614 [prop]: bar,615 [foo + bar]: bar616 }, [617 _createVNode("p", { "some-key": "foo" })618 ], 16)619 }620 }621 `,622 map: undefined 623}624/**625 * @param { Number 014 }626 * @function generate 627 * æ¹æ³å
¥åï¼createArrayExpression å建æ°ç»è¡¨è¾¾å¼628 * æ¹æ³åºåï¼astãcode629 * æ¹æ³æ»ç»ï¼630 * 1ãè½è¿åæ£ç¡®çæ°ç»è¡¨è¾¾å¼631 */632const untest014 = generate(633 createRoot({634 codegenNode: createArrayExpression([635 createSimpleExpression(`foo`, false),636 createCallExpression(`bar`, [`baz`])637 ])638 })639)640const output014 = { 641 ast:{642 },643 code:`644 return function render() {645 with (this) {646 return [647 foo,648 bar(baz)649 ]650 }651 }652 `,653 map: undefined 654}655/**656 * @param { Number 015 }657 * @function generate 658 * æ¹æ³å
¥åï¼createSequenceExpression å建åºå表达å¼659 * æ¹æ³åºåï¼astãcode660 * æ¹æ³æ»ç»ï¼661 * 1ãè½è¿åæ£ç¡®çåºå表达å¼662 */663const untest015 = generate(664 createRoot({665 codegenNode: createSequenceExpression([666 createSimpleExpression(`foo`, false),667 createCallExpression(`bar`, [`baz`])668 ])669 })670)671const output015 = { 672 ast: { 673 },674 code:675 `676 return function render() {677 with (this) {678 return (foo, bar(baz))679 }680 }681 `,682 map: undefined 683}684/**685 * @param { Number 016 }686 * @function generate 687 * æ¹æ³å
¥åï¼createConditionalExpression å建æ¡ä»¶è¡¨è¾¾å¼688 * æ¹æ³åºåï¼astãcode689 * æ¹æ³æ»ç»ï¼690 * 1ãè½è¿åæ£ç¡®çæ¡ä»¶è¡¨è¾¾å¼691 */692const untest016 = generate(693 createRoot({694 codegenNode: createConditionalExpression(695 createSimpleExpression(`ok`, false),696 createCallExpression(`foo`),697 createConditionalExpression(698 createSimpleExpression(`orNot`, false),699 createCallExpression(`bar`),700 createCallExpression(`baz`)701 )702 )703 })704)705const output016 = { 706 ast: {707 708 },709 code:`710 return function render() {711 with (this) {712 return ok713 ? foo()714 : orNot715 ? bar()716 : baz()717 }718 }719 `,720 map: undefined 721}722/**723 * @param { Number 017 }724 * @function generate 725 * æ¹æ³å
¥åï¼createCacheExpression å建ç¼å表达å¼726 * æ¹æ³åºåï¼astãcode727 * æ¹æ³æ»ç»ï¼728 * 1ãè½è¿åæ£ç¡®çç¼å表达å¼729 */730const untest017 = generate(731 createRoot({732 cached: 1,733 codegenNode: createCacheExpression(734 1,735 createSimpleExpression(`foo`, false)736 )737 }),738 {739 mode: 'module',740 prefixIdentifiers: true741 }742)743const output017 = { 744 ast: {745 },746 code: `747 export default function render() {748 const _ctx = this749 const _cache = _ctx.$cache750 return _cache[1] || (_cache[1] = foo)751 }752 `,753 map: undefined 754}755/**756 * @param { Number 018 }757 * @function generate 758 * æ¹æ³å
¥åï¼createCacheExpression å建ç¼å表达å¼ï¼å¤äºä¸ä¸ªtrue759 * æ¹æ³åºåï¼astãcode760 * æ¹æ³æ»ç»ï¼761 * 1ãè½è¿åæ£ç¡®çç¼å表达å¼762 * 2ãå¤äºä¸ä¸ªsetBlockTracking763 */764const untest018 = generate(765 createRoot({766 cached: 1,767 codegenNode: createCacheExpression(768 1,769 createSimpleExpression(`foo`, false),770 true771 )772 }),773 {774 mode: 'module',775 prefixIdentifiers: true776 }777)778const output018 = { 779 ast: {780 },781 code: `...
codegen.spec.js
Source:codegen.spec.js
...218 });219 test('CacheExpression', function () {220 var code = src_1.generate(createRoot({221 cached: 1,222 codegenNode: src_1.createCacheExpression(1, src_1.createSimpleExpression("foo", false))223 }), {224 mode: 'module',225 prefixIdentifiers: true226 }).code;227 expect(code).toMatch("const _cache = _ctx.$cache");228 expect(code).toMatch("_cache[1] || (_cache[1] = foo)");229 expect(code).toMatchSnapshot();230 });231 test('CacheExpression w/ isVNode: true', function () {232 var code = src_1.generate(createRoot({233 cached: 1,234 codegenNode: src_1.createCacheExpression(1, src_1.createSimpleExpression("foo", false), true)235 }), {236 mode: 'module',237 prefixIdentifiers: true238 }).code;239 expect(code).toMatch("const _cache = _ctx.$cache");240 expect(code).toMatch("\n _cache[1] || (\n setBlockTracking(-1),\n _cache[1] = foo,\n setBlockTracking(1),\n _cache[1]\n )\n ".trim());241 expect(code).toMatchSnapshot();242 });...
transform.js
Source:transform.js
...118 identifier.hoisted = exp;119 return identifier;120 },121 cache(exp, isVNode = false) {122 return createCacheExpression(++context.cached, exp, isVNode);123 },124 };125 function addId(id) {}126 function removeId(id) {}127 return context;128}129export function traverseNode(node, context) {130 context.currentNode = node;131 const { nodeTransforms } = context;132 const exitFns = [];133 for (let i = 0; i < nodeTransforms.length; i++) {134 // è°ç¨è¯¸å¦ transformText çå½æ°135 const onExit = nodeTransforms[i](node, context);136 if (onExit) {...
ast.js
Source:ast.js
...104 loc: exports.locStub105 };106}107exports.createConditionalExpression = createConditionalExpression;108function createCacheExpression(index, value, isVNode) {109 if (isVNode === void 0) { isVNode = false; }110 return {111 type: 20,112 index: index,113 value: value,114 isVNode: isVNode,115 loc: exports.locStub116 };117}...
Using AI Code Generation
1import { createCacheExpression } from 'playwright/lib/server/frames';2const cacheExpression = createCacheExpression('test');3console.log(cacheExpression);4import { createCacheExpression } from 'playwright/lib/server/frames';5const cacheExpression = createCacheExpression('test', 'test');6console.log(cacheExpression);7import { createCacheExpression } from 'playwright/lib/server/frames';8const cacheExpression = createCacheExpression('test', 'test', 'test');9console.log(cacheExpression);10import { createCacheExpression } from 'playwright/lib/server/frames';11const cacheExpression = createCacheExpression('test', 'test', 'test', 'test');12console.log(cacheExpression);13import { createCacheExpression } from 'playwright/lib/server/frames';14const cacheExpression = createCacheExpression('test', 'test', 'test', 'test', 'test');15console.log(cacheExpression);16import { createCacheExpression } from 'playwright/lib/server/frames';17const cacheExpression = createCacheExpression('test', 'test', 'test', 'test', 'test', 'test');18console.log(cacheExpression);19import { createCacheExpression } from 'playwright/lib/server/frames';20const cacheExpression = createCacheExpression('test', 'test', 'test', 'test', 'test', 'test', 'test');21console.log(cacheExpression);22import { createCacheExpression } from 'playwright/lib/server/frames';23const cacheExpression = createCacheExpression('test', 'test', 'test', 'test', 'test', 'test', 'test', 'test');24console.log(cacheExpression);25import { createCacheExpression } from 'playwright/lib/server/frames';
Using AI Code Generation
1const { createCacheExpression } = require('playwright/lib/server/frames');2const cacheExpression = createCacheExpression('test');3const result = await page.evaluate(cacheExpression, 'test');4console.log(result);5{6}
Using AI Code Generation
1const { createCacheExpression } = require("playwright/lib/server/browserContext");2const { createHash } = require("crypto");3const { serialize } = require("playwright/lib/server/serializers");4const { createHash } = require("crypto");5const { serialize } = require("playwright/lib/server/serializers");6const { createCacheExpression } = require("playwright/lib/server/browserContext");7const { createHash } = require("crypto");8const { serialize } = require("playwright/lib/server/serializers");9const { createCacheExpression } = require("playwright/lib/server/browserContext");10const { createHash } = require("crypto");11const { serialize } = require("playwright/lib/server/serializers");12const { createCacheExpression } = require("playwright/lib/server/browserContext");13const { createHash } = require("crypto");14const { serialize } = require("playwright/lib/server/serializers");15const { createCacheExpression } = require("playwright/lib/server/browserContext");16const { createHash } = require("crypto");17const { serialize } = require("playwright/lib/server/serializers");18const { createCacheExpression } = require("playwright/lib/server/browserContext");19const { createHash } = require("crypto");20const { serialize } = require("playwright/lib/server/serializers");21const { createCacheExpression } = require("playwright/lib/server/browserContext");22const { createHash } = require("crypto");23const { serialize } = require("playwright/lib/server/serializers");24const { createCacheExpression } = require("playwright/lib/server/browserContext");25const { createHash } = require("crypto");26const { serialize } = require("playwright/lib/server/serializers");27const { createCacheExpression } = require("playwright/lib/server/browserContext");28const { createHash } = require("crypto");29const { serialize } = require("playwright/lib/server/serializers");30const { createCacheExpression } = require("playwright/lib/server/browserContext");31const { createHash } = require("crypto");32const { serialize } = require("playwright/lib/server/serializers");33const { createCacheExpression } = require("playwright/lib/server/browserContext");34const { createHash } = require("crypto");35const { serialize } = require("playwright/lib/server/serializers");36const { createCacheExpression } = require("playwright/lib/server/browserContext");37const { createHash }
Using AI Code Generation
1const { createCacheExpression, createCacheKey } = require('@playwright/test/lib/server/cacheUtils');2const path = require('path');3const fs = require('fs');4const cacheExpression = createCacheExpression(5 path.resolve(__dirname, 'test.js'),6 fs.readFileSync(path.resolve(__dirname, 'test.js')),7 {8 },
Using AI Code Generation
1const { createCacheExpression } = require('playwright/lib/server/cacheStorage');2console.log(cacheExpression);3const { createCacheExpression } = require('playwright/lib/server/cacheStorage');4const cookies = [{name: 'foo', value: 'bar'}];5console.log(cacheExpression);6const { createCacheExpression } = require('playwright/lib/server/cacheStorage');7const headers = { 'foo': 'bar' };8console.log(cacheExpression);9const { createCacheExpression } = require('playwright/lib/server/cacheStorage');10const cookies = [{name: 'foo', value: 'bar'}];11const headers = { 'foo': 'bar' };12console.log(cacheExpression);13const { createCacheExpression } = require('playwright/lib/server/cacheStorage');14const cookies = [{name: 'foo', value: 'bar'}];15const headers = { 'foo': 'bar' };16console.log(cacheExpression);17const { createCacheExpression } = require('playwright/lib/server/cacheStorage');18const cookies = [{name: 'foo', value: 'bar'}];19const headers = { 'foo': 'bar' };
Using AI Code Generation
1const { createCacheExpression } = require('@playwright/test');2const cacheExpression = createCacheExpression('myCacheExpression', 'myCacheKey', (a, b) => a + b);3cacheExpression(2, 3);4cacheExpression(2, 3);5const { createCacheExpression } = require('@playwright/test');6const cacheExpression = createCacheExpression('myCacheExpression', 'myCacheKey', (a, b) => a + b);7cacheExpression(2, 3);8cacheExpression(2, 3);9const { createCacheExpression } = require('@playwright/test');10const cacheExpression = createCacheExpression('myCacheExpression', 'myCacheKey', (a, b) => a + b);11cacheExpression(2, 3);12cacheExpression(2, 3);13const { createCacheExpression } = require('@playwright/test');14const cacheExpression = createCacheExpression('myCacheExpression', 'myCacheKey', (a, b) => a + b);15cacheExpression(2, 3);16cacheExpression(2, 3);17const { createCacheExpression } = require('@playwright/test');18const cacheExpression = createCacheExpression('myCacheExpression', 'myCacheKey', (a, b) => a + b);19cacheExpression(2, 3);20cacheExpression(2, 3);21const { createCacheExpression } = require('@playwright/test');22const cacheExpression = createCacheExpression('myCacheExpression', 'myCacheKey', (a, b) => a + b);23cacheExpression(2, 3);24cacheExpression(2, 3);25const { createCacheExpression } = require('@playwright/test');26const cacheExpression = createCacheExpression('myCacheExpression', 'myCacheKey', (a, b) => a + b);27cacheExpression(2, 3);28cacheExpression(2, 3);29const { createCacheExpression } =
Using AI Code Generation
1const { createCacheExpression } = require('playwright/lib/internal/recorder/frames');2const elementHandle = await page.$('css=div');3const cacheExpression = await createCacheExpression(elementHandle);4const element = await page.evaluateHandle(cacheExpression);5const { createCacheExpression } = require('playwright/lib/internal/recorder/frames');6const elementHandle = await page.$('css=div');7const cacheExpression = await createCacheExpression(elementHandle);8const element = await page.evaluateHandle(cacheExpression);9const { createCacheExpression } = require('playwright/lib/internal/recorder/frames');10const elementHandle = await page.$('css=div');11const cacheExpression = await createCacheExpression(elementHandle);12const element = await page.evaluateHandle(cacheExpression);13const { createCacheExpression } = require('playwright/lib/internal/recorder/frames');14const elementHandle = await page.$('css=div');15const cacheExpression = await createCacheExpression(elementHandle);16const element = await page.evaluateHandle(cacheExpression);17const { createCacheExpression } = require('playwright/lib/internal/recorder/frames');18const elementHandle = await page.$('css=div');19const cacheExpression = await createCacheExpression(elementHandle);20const element = await page.evaluateHandle(cacheExpression);
Using AI Code Generation
1const { chromium } = require('playwright');2const { createCacheExpression } = require('playwright/lib/server/cacheUtils');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.route('**', (route) => {8 route.fulfill({9 headers: {10 },11 });12 });13 await page.close();14 await context.close();15 await browser.close();16})();17const { chromium } = require('playwright');18const { createCacheExpression } = require('playwright/lib/server/cacheUtils');19(async () => {20 const browser = await chromium.launch();21 const context = await browser.newContext();22 const page = await context.newPage();23 await page.route('**', (route) => {24 route.fulfill({25 headers: {26 },27 });28 });29 await page.close();30 await context.close();31 await browser.close();32})();33const { chromium } = require('playwright');34const { createCacheExpression } = require('playwright/lib/server/cacheUtils');35(async () => {36 const browser = await chromium.launch();
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!