Best JavaScript code snippet using playwright-internal
note-ast-transform.js
Source:note-ast-transform.js
...193 }194 });195 }196 const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */;197 const slotOutlet = isSlotOutlet(node)198 ? node199 : isTemplate &&200 node.children.length === 1 &&201 isSlotOutlet(node.children[0])202 ? node.children[0] // api-extractor somehow fails to infer this203 : null;204 if (slotOutlet) {205 // <slot v-for="..."> or <template v-for="..."><slot/></template>206 childBlock = slotOutlet.codegenNode;207 if (isTemplate && keyProperty) {208 // <template v-for="..." :key="..."><slot/></template>209 // we need to inject the key to the renderSlot() call.210 // the props for renderSlot is passed as the 3rd argument.211 injectProp(childBlock, keyProperty, context);212 }213 }214 else if (needFragmentWrapper) {215 // <template v-for="..."> with text or multi-elements216 // should generate a fragment block for each loop217 childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, `${64 /* STABLE_FRAGMENT */} /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`, undefined, undefined, true);218 }219 else {220 // Normal element v-for. Directly use the child's codegenNode221 // but mark it as a block.222 childBlock = children[0]223 .codegenNode;224 if (isTemplate && keyProperty) {225 injectProp(childBlock, keyProperty, context);226 }227 childBlock.isBlock = !isStableFragment;228 if (childBlock.isBlock) {229 helper(OPEN_BLOCK);230 helper(CREATE_BLOCK);231 }232 }233 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));234 };235 });236 });237 function createCallExpression(callee, args = [], loc = locStub) {238 return {239 type: 14 /* JS_CALL_EXPRESSION */,240 loc,241 callee,242 arguments: args243 };244 }245 function createObjectProperty(key, value) {246 return {247 type: 16 /* JS_PROPERTY */,248 loc: locStub,249 key: isString(key) ? createSimpleExpression(key, true) : key,250 value251 };252 }253 function createSimpleExpression(content, isStatic, loc = locStub, isConstant = false) {254 return {255 type: 4 /* SIMPLE_EXPRESSION */,256 loc,257 isConstant,258 content,259 isStatic260 };261 }262 function createFunctionExpression(params, returns = undefined, newline = false, isSlot = false, loc = locStub) {263 return {264 type: 18 /* JS_FUNCTION_EXPRESSION */,265 params,266 returns,267 newline,268 isSlot,269 loc270 };271 }272 function createForLoopParams({ value, key, index }) {273 const params = [];274 if (value) {275 params.push(value);276 }277 if (key) {278 if (!value) {279 params.push(createSimpleExpression(`_`, false));280 }281 params.push(key);282 }283 if (index) {284 if (!key) {285 if (!value) {286 params.push(createSimpleExpression(`_`, false));287 }288 params.push(createSimpleExpression(`__`, false));289 }290 params.push(index);291 }292 return params;293 }294 function createVNodeCall(context, tag, props, children, patchFlag, dynamicProps, directives, isBlock = false, disableTracking = false, loc = locStub) {295 if (context) {296 if (isBlock) {297 context.helper(OPEN_BLOCK);298 context.helper(CREATE_BLOCK);299 }300 else {301 context.helper(CREATE_VNODE);302 }303 if (directives) {304 context.helper(WITH_DIRECTIVES);305 }306 }307 return {308 type: 13 /* VNODE_CALL */,309 tag,310 props,311 children,312 patchFlag,313 dynamicProps,314 directives,315 isBlock,316 disableTracking,317 loc318 };319 }320 // AST Utilities ---------------------------------------------------------------321 // Some expressions, e.g. sequence and conditional expressions, are never322 // associated with template nodes, so their source locations are just a stub.323 // Container types like CompoundExpression also don't need a real location.324 const locStub = {325 source: '',326 start: { line: 1, column: 1, offset: 0 },327 end: { line: 1, column: 1, offset: 0 }328 };329 330 // Patch flags are optimization hints generated by the compiler.331 // when a block with dynamicChildren is encountered during diff, the algorithm332 // enters "optimized mode". In this mode, we know that the vdom is produced by333 // a render function generated by the compiler, so the algorithm only needs to334 // handle updates explicitly marked by these patch flags.335 // dev only flag -> name mapping336 const PatchFlagNames = {337 [1 /* TEXT */]: `TEXT`,338 [2 /* CLASS */]: `CLASS`,339 [4 /* STYLE */]: `STYLE`,340 [8 /* PROPS */]: `PROPS`,341 [16 /* FULL_PROPS */]: `FULL_PROPS`,342 [32 /* HYDRATE_EVENTS */]: `HYDRATE_EVENTS`,343 [64 /* STABLE_FRAGMENT */]: `STABLE_FRAGMENT`,344 [128 /* KEYED_FRAGMENT */]: `KEYED_FRAGMENT`,345 [256 /* UNKEYED_FRAGMENT */]: `UNKEYED_FRAGMENT`,346 [512 /* NEED_PATCH */]: `NEED_PATCH`,347 [1024 /* DYNAMIC_SLOTS */]: `DYNAMIC_SLOTS`,348 [-1 /* HOISTED */]: `HOISTED`,349 [-2 /* BAIL */]: `BAIL`350 };351 function createObjectProperty(key, value) {352 return {353 type: 16 /* JS_PROPERTY */,354 loc: locStub,355 key: isString(key) ? createSimpleExpression(key, true) : key,356 value357 };358 }359 360 // target-agnostic transform used for both Client and SSR361 function processFor(node, dir, context, processCodegen) {362 if (!dir.exp) {363 context.onError(createCompilerError(30 /* X_V_FOR_NO_EXPRESSION */, dir.loc));364 return;365 }366 const parseResult = parseForExpression(367 // can only be simple expression because vFor transform is applied368 // before expression transform.369 dir.exp, context);370 if (!parseResult) {371 context.onError(createCompilerError(31 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));372 return;373 }374 const { addIdentifiers, removeIdentifiers, scopes } = context;375 const { source, value, key, index } = parseResult;376 const forNode = {377 type: 11 /* FOR */,378 loc: dir.loc,379 source,380 valueAlias: value,381 keyAlias: key,382 objectIndexAlias: index,383 parseResult,384 children: isTemplateNode(node) ? node.children : [node]385 };386 context.replaceNode(forNode);387 // bookkeeping388 scopes.vFor++;389 const onExit = processCodegen && processCodegen(forNode);390 return () => {391 scopes.vFor--;392 if (onExit)393 onExit();394 };395 }396 const forNode = {397 type: 11 /* FOR */,398 loc: dir.loc,399 source,400 valueAlias: value,401 keyAlias: key,402 objectIndexAlias: index,403 parseResult,404 children: isTemplateNode(node) ? node.children : [node]405 };406 const transformExpression = (node, context) => {407 if (node.type === 5 /* INTERPOLATION */) {408 node.content = processExpression(node.content, context);409 }410 else if (node.type === 1 /* ELEMENT */) {411 // handle directives on element412 for (let i = 0; i < node.props.length; i++) {413 const dir = node.props[i];414 // do not process for v-on & v-for since they are special handled415 if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') {416 const exp = dir.exp;417 const arg = dir.arg;418 // do not process exp if this is v-on:arg - we need special handling419 // for wrapping inline statements.420 if (exp &&421 exp.type === 4 /* SIMPLE_EXPRESSION */ &&422 !(dir.name === 'on' && arg)) {423 dir.exp = processExpression(exp, context, 424 // slot args must be processed as function params425 dir.name === 'slot');426 }427 if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) {428 dir.arg = processExpression(arg, context);429 }430 }431 }432 }433 };434 const transformSlotOutlet = (node, context) => {435 if (isSlotOutlet(node)) {436 const { children, loc } = node;437 const { slotName, slotProps } = processSlotOutlet(node, context);438 const slotArgs = [439 context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,440 slotName441 ];442 if (slotProps) {443 slotArgs.push(slotProps);444 }445 if (children.length) {446 if (!slotProps) {447 slotArgs.push(`{}`);448 }449 slotArgs.push(createFunctionExpression([], children, false, false, loc));450 }451 node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);452 }453 };454 function isSlotOutlet(node) {455 return node.type === 1 /* ELEMENT */ && node.tagType === 2 /* SLOT */;456 }457 function processSlotOutlet(node, context) {458 let slotName = `"default"`;459 let slotProps = undefined;460 // check for <slot name="xxx" OR :name="xxx" />461 const name = findProp(node, 'name');462 if (name) {463 if (name.type === 6 /* ATTRIBUTE */ && name.value) {464 // static name465 slotName = JSON.stringify(name.value.content);466 }467 else if (name.type === 7 /* DIRECTIVE */ && name.exp) {468 // dynamic name469 slotName = name.exp;470 }471 }472 const propsWithoutName = name473 ? node.props.filter(p => p !== name)474 : node.props;475 if (propsWithoutName.length > 0) {476 const { props, directives } = buildProps(node, context, propsWithoutName);477 slotProps = props;478 if (directives.length) {479 context.onError(createCompilerError(35 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, directives[0].loc));480 }481 }482 return {483 slotName,484 slotProps485 };486 }487 function buildProps(node, context, props = node.props, ssr = false) {488 const { tag, loc: elementLoc } = node;489 const isComponent = node.tagType === 1 /* COMPONENT */;490 let properties = [];491 const mergeArgs = [];492 const runtimeDirectives = [];493 // patchFlag analysis494 let patchFlag = 0;495 let hasRef = false;496 let hasClassBinding = false;497 let hasStyleBinding = false;498 let hasHydrationEventBinding = false;499 let hasDynamicKeys = false;500 let hasVnodeHook = false;501 const dynamicPropNames = [];502 const analyzePatchFlag = ({ key, value }) => {503 // if (content.startsWith('[')) {504 // isStatic = false;505 // if (!content.endsWith(']')) {506 // emitError(context, 26 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);507 // }508 // content = content.substr(1, content.length - 2);509 // }510 if (isStaticExp(key)) { // const isStaticExp = (p) => p.type === 4 /* SIMPLE_EXPRESSION */ && p.isStatic;511 const name = key.content;512 const isEventHandler = isOn(name);513 if (!isComponent &&514 isEventHandler &&515 // omit the flag for click handlers because hydration gives click516 // dedicated fast path.517 name.toLowerCase() !== 'onclick' &&518 // omit v-model handlers519 name !== 'onUpdate:modelValue' &&520 // omit onVnodeXXX hooks521 !isReservedProp(name)) {522 hasHydrationEventBinding = true;523 }524 if (isEventHandler && isReservedProp(name)) {525 hasVnodeHook = true;526 }527 if (value.type === 20 /* JS_CACHE_EXPRESSION */ ||528 ((value.type === 4 /* SIMPLE_EXPRESSION */ ||529 value.type === 8 /* COMPOUND_EXPRESSION */) &&530 getStaticType(value) > 0)) {531 // skip if the prop is a cached handler or has constant value532 return;533 }534 if (name === 'ref') {535 hasRef = true;536 }537 else if (name === 'class' && !isComponent) {538 hasClassBinding = true;539 }540 else if (name === 'style' && !isComponent) {541 hasStyleBinding = true;542 }543 else if (name !== 'key' && !dynamicPropNames.includes(name)) {544 dynamicPropNames.push(name);545 }546 }547 else {548 hasDynamicKeys = true;549 }550 };551 for (let i = 0; i < props.length; i++) {552 // static attribute553 const prop = props[i];554 if (prop.type === 6 /* ATTRIBUTE */) {555 const { loc, name, value } = prop;556 if (name === 'ref') {557 hasRef = true;558 }559 // skip :is on <component>560 if (name === 'is' && tag === 'component') {561 continue;562 }563 properties.push(createObjectProperty(564 createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), 565 createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc)566 )567 );568 }569 else {570 // directives571 const { name, arg, exp, loc } = prop;572 const isBind = name === 'bind';573 const isOn = name === 'on';574 // skip v-slot - it is handled by its dedicated transform.575 if (name === 'slot') {576 if (!isComponent) {577 context.onError(createCompilerError(39 /* X_V_SLOT_MISPLACED */, loc));578 }579 continue;580 }581 // skip v-once - it is handled by its dedicated transform.582 if (name === 'once') {583 continue;584 }585 // skip v-is and :is on <component>586 if (name === 'is' ||587 (isBind && tag === 'component' && isBindKey(arg, 'is'))) { // åèparseAttribute588 continue;589 }590 // skip v-on in SSR compilation591 if (isOn && ssr) {592 continue;593 }594 // special case for v-bind and v-on with no argument595 if (!arg && (isBind || isOn)) { // åèparseAttribute596 hasDynamicKeys = true;597 if (exp) {598 if (properties.length) {599 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));600 properties = [];601 }602 if (isBind) {603 mergeArgs.push(exp);604 }605 else {606 // v-on="obj" -> toHandlers(obj)607 mergeArgs.push({608 type: 14 /* JS_CALL_EXPRESSION */,609 loc,610 callee: context.helper(TO_HANDLERS),611 arguments: [exp]612 });613 }614 }615 else {616 context.onError(createCompilerError(isBind617 ? 33 /* X_V_BIND_NO_EXPRESSION */618 : 34 /* X_V_ON_NO_EXPRESSION */, loc));619 }620 continue;621 }622 const directiveTransform = context.directiveTransforms[name]; // on, bind. model623 if (directiveTransform) {624 // has built-in directive transform.625 const { props, needRuntime } = directiveTransform(prop, node, context);626 !ssr && props.forEach(analyzePatchFlag);627 properties.push(...props);628 if (needRuntime) {629 runtimeDirectives.push(prop);630 if (isSymbol(needRuntime)) {631 directiveImportMap.set(prop, needRuntime);632 }633 }634 }635 else {636 // no built-in transform, this is a user custom directive.637 runtimeDirectives.push(prop);638 }639 }640 }641 let propsExpression = undefined;642 // has v-bind="object" or v-on="object", wrap with mergeProps643 if (mergeArgs.length) {644 if (properties.length) {645 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));646 }647 if (mergeArgs.length > 1) {648 propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);649 }650 else {651 // single v-bind with nothing else - no need for a mergeProps call652 propsExpression = mergeArgs[0];653 }654 }655 else if (properties.length) {656 propsExpression = createObjectExpression(dedupeProperties(properties), elementLoc);657 }658 // patchFlag analysis659 if (hasDynamicKeys) {660 patchFlag |= 16 /* FULL_PROPS */;661 }662 else {663 if (hasClassBinding) {664 patchFlag |= 2 /* CLASS */;665 }666 if (hasStyleBinding) {667 patchFlag |= 4 /* STYLE */;668 }669 if (dynamicPropNames.length) {670 patchFlag |= 8 /* PROPS */;671 }672 if (hasHydrationEventBinding) {673 patchFlag |= 32 /* HYDRATE_EVENTS */;674 }675 }676 if ((patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&677 (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {678 patchFlag |= 512 /* NEED_PATCH */;679 }680 return {681 props: propsExpression,682 directives: runtimeDirectives,683 patchFlag,684 dynamicPropNames685 };686 }687 // Dedupe props in an object literal.688 // Literal duplicated attributes would have been warned during the parse phase,689 // however, it's possible to encounter duplicated `onXXX` handlers with different690 // modifiers. We also need to merge static and dynamic class / style attributes.691 // - onXXX handlers / style: merge into array692 // - class: merge into single expression with concatenation693 function dedupeProperties(properties) {694 const knownProps = new Map();695 const deduped = [];696 for (let i = 0; i < properties.length; i++) {697 const prop = properties[i];698 // dynamic keys are always allowed699 if (prop.key.type === 8 /* COMPOUND_EXPRESSION */ || !prop.key.isStatic) { // onXXX700 deduped.push(prop);701 continue;702 }703 const name = prop.key.content;704 const existing = knownProps.get(name);705 if (existing) {706 if (name === 'style' || name === 'class' || name.startsWith('on')) {707 mergeAsArray(existing, prop);708 }709 // unexpected duplicate, should have emitted error during parse710 }711 else {712 knownProps.set(name, prop);713 deduped.push(prop);714 }715 }716 return deduped;717 }718 function createArrayExpression(elements, loc = locStub) {719 return {720 type: 17 /* JS_ARRAY_EXPRESSION */,721 loc,722 elements723 };724 }725 function getStaticType(node, resultCache = new Map()) {726 switch (node.type) {727 case 1 /* ELEMENT */:728 if (node.tagType !== 0 /* ELEMENT */) {729 return 0 /* NOT_STATIC */;730 }731 const cached = resultCache.get(node);732 if (cached !== undefined) {733 return cached;734 }735 const codegenNode = node.codegenNode;736 if (codegenNode.type !== 13 /* VNODE_CALL */) {737 return 0 /* NOT_STATIC */;738 }739 const flag = getPatchFlag(codegenNode);740 if (!flag && !hasNonHoistableProps(node)) {741 // element self is static. check its children.742 let returnType = 1 /* FULL_STATIC */;743 for (let i = 0; i < node.children.length; i++) {744 const childType = getStaticType(node.children[i], resultCache);745 if (childType === 0 /* NOT_STATIC */) {746 resultCache.set(node, 0 /* NOT_STATIC */);747 return 0 /* NOT_STATIC */;748 }749 else if (childType === 2 /* HAS_RUNTIME_CONSTANT */) {750 returnType = 2 /* HAS_RUNTIME_CONSTANT */;751 }752 }753 // check if any of the props contain runtime constants754 if (returnType !== 2 /* HAS_RUNTIME_CONSTANT */) {755 for (let i = 0; i < node.props.length; i++) {756 const p = node.props[i];757 if (p.type === 7 /* DIRECTIVE */ &&758 p.name === 'bind' &&759 p.exp &&760 (p.exp.type === 8 /* COMPOUND_EXPRESSION */ ||761 p.exp.isRuntimeConstant)) {762 returnType = 2 /* HAS_RUNTIME_CONSTANT */;763 }764 }765 }766 // only svg/foreignObject could be block here, however if they are767 // stati then they don't need to be blocks since there will be no768 // nested updates.769 if (codegenNode.isBlock) {770 codegenNode.isBlock = false;771 }772 resultCache.set(node, returnType);773 return returnType;774 }775 else {776 resultCache.set(node, 0 /* NOT_STATIC */);777 return 0 /* NOT_STATIC */;778 }779 case 2 /* TEXT */:780 case 3 /* COMMENT */:781 return 1 /* FULL_STATIC */;782 case 9 /* IF */:783 case 11 /* FOR */:784 case 10 /* IF_BRANCH */:785 return 0 /* NOT_STATIC */;786 case 5 /* INTERPOLATION */:787 case 12 /* TEXT_CALL */:788 return getStaticType(node.content, resultCache);789 case 4 /* SIMPLE_EXPRESSION */:790 return node.isConstant791 ? node.isRuntimeConstant792 ? 2 /* HAS_RUNTIME_CONSTANT */793 : 1 /* FULL_STATIC */794 : 0 /* NOT_STATIC */;795 case 8 /* COMPOUND_EXPRESSION */:796 let returnType = 1 /* FULL_STATIC */;797 for (let i = 0; i < node.children.length; i++) {798 const child = node.children[i];799 if (isString(child) || isSymbol(child)) {800 continue;801 }802 const childType = getStaticType(child, resultCache);803 if (childType === 0 /* NOT_STATIC */) {804 return 0 /* NOT_STATIC */;805 }806 else if (childType === 2 /* HAS_RUNTIME_CONSTANT */) {807 returnType = 2 /* HAS_RUNTIME_CONSTANT */;808 }809 }810 return returnType;811 default:812 return 0 /* NOT_STATIC */;813 }814 }815 const transformElement = (node, context) => {816 if (!(node.type === 1 /* ELEMENT */ &&817 (node.tagType === 0 /* ELEMENT */ ||818 node.tagType === 1 /* COMPONENT */))) {819 return;820 }821 // perform the work on exit, after all child expressions have been822 // processed and merged.823 return function postTransformElement() {824 const { tag, props } = node;825 const isComponent = node.tagType === 1 /* COMPONENT */;826 // The goal of the transform is to create a codegenNode implementing the827 // VNodeCall interface.828 const vnodeTag = isComponent829 ? resolveComponentType(node, context)830 : `"${tag}"`;831 const isDynamicComponent = isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT;832 let vnodeProps;833 let vnodeChildren;834 let vnodePatchFlag;835 let patchFlag = 0;836 let vnodeDynamicProps;837 let dynamicPropNames;838 let vnodeDirectives;839 let shouldUseBlock = 840 // dynamic component may resolve to plain elements841 isDynamicComponent ||842 vnodeTag === TELEPORT ||843 vnodeTag === SUSPENSE ||844 (!isComponent &&845 // <svg> and <foreignObject> must be forced into blocks so that block846 // updates inside get proper isSVG flag at runtime. (#639, #643)847 // This is technically web-specific, but splitting the logic out of core848 // leads to too much unnecessary complexity.849 (tag === 'svg' ||850 tag === 'foreignObject' ||851 // #938: elements with dynamic keys should be forced into blocks852 findProp(node, 'key', true)));853 // props854 if (props.length > 0) {855 const propsBuildResult = buildProps(node, context);856 vnodeProps = propsBuildResult.props;857 patchFlag = propsBuildResult.patchFlag;858 dynamicPropNames = propsBuildResult.dynamicPropNames;859 const directives = propsBuildResult.directives;860 vnodeDirectives =861 directives && directives.length862 ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))863 : undefined;864 }865 // children866 if (node.children.length > 0) {867 if (vnodeTag === KEEP_ALIVE) {868 // Although a built-in component, we compile KeepAlive with raw children869 // instead of slot functions so that it can be used inside Transition870 // or other Transition-wrapping HOCs.871 // To ensure correct updates with block optimizations, we need to:872 // 1. Force keep-alive into a block. This avoids its children being873 // collected by a parent block.874 shouldUseBlock = true;875 // 2. Force keep-alive to always be updated, since it uses raw children.876 patchFlag |= 1024 /* DYNAMIC_SLOTS */;877 if ( node.children.length > 1) {878 context.onError(createCompilerError(44 /* X_KEEP_ALIVE_INVALID_CHILDREN */, {879 start: node.children[0].loc.start,880 end: node.children[node.children.length - 1].loc.end,881 source: ''882 }));883 }884 }885 const shouldBuildAsSlots = isComponent &&886 // Teleport is not a real component and has dedicated runtime handling887 vnodeTag !== TELEPORT &&888 // explained above.889 vnodeTag !== KEEP_ALIVE;890 if (shouldBuildAsSlots) {891 const { slots, hasDynamicSlots } = buildSlots(node, context);892 vnodeChildren = slots;893 if (hasDynamicSlots) {894 patchFlag |= 1024 /* DYNAMIC_SLOTS */;895 }896 }897 else if (node.children.length === 1 && vnodeTag !== TELEPORT) {898 const child = node.children[0];899 const type = child.type;900 // check for dynamic text children901 const hasDynamicTextChild = type === 5 /* INTERPOLATION */ ||902 type === 8 /* COMPOUND_EXPRESSION */;903 if (hasDynamicTextChild && !getStaticType(child)) {904 patchFlag |= 1 /* TEXT */;905 }906 // pass directly if the only child is a text node907 // (plain / interpolation / expression)908 if (hasDynamicTextChild || type === 2 /* TEXT */) {909 vnodeChildren = child;910 }911 else {912 vnodeChildren = node.children;913 }914 }915 else {916 vnodeChildren = node.children;917 }918 }919 // patchFlag & dynamicPropNames920 if (patchFlag !== 0) {921 {922 if (patchFlag < 0) {923 // special flags (negative and mutually exclusive)924 vnodePatchFlag = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`;925 }926 else {927 // bitwise flags928 const flagNames = Object.keys(PatchFlagNames)929 .map(Number)930 .filter(n => n > 0 && patchFlag & n)931 .map(n => PatchFlagNames[n])932 .join(`, `);933 vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;934 }935 }936 if (dynamicPropNames && dynamicPropNames.length) {937 vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);938 }939 }940 // function createVNodeCall(context, tag, props, children, patchFlag, dynamicProps, directives, isBlock = false, disableTracking = false, loc = locStub) 941 node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, node.loc);942 };943 };944 function stringifyDynamicPropNames(props) {945 let propsNamesString = `[`;946 for (let i = 0, l = props.length; i < l; i++) {947 propsNamesString += JSON.stringify(props[i]);948 if (i < l - 1)949 propsNamesString += ', ';950 }951 return propsNamesString + `]`;952 }953 /**954 * Even for a node with no patch flag, it is possible for it to contain955 * non-hoistable expressions that refers to scope variables, e.g. compiler956 * injected keys or cached event handlers. Therefore we need to always check the957 * codegenNode's props to be sure.958 */959 function hasNonHoistableProps(node) {960 const props = getNodeProps(node);961 if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) {962 const { properties } = props;963 for (let i = 0; i < properties.length; i++) {964 const { key, value } = properties[i];965 if (key.type !== 4 /* SIMPLE_EXPRESSION */ ||966 !key.isStatic ||967 (value.type !== 4 /* SIMPLE_EXPRESSION */ ||968 (!value.isStatic && !value.isConstant))) {969 return true;970 }971 }972 }973 return false;974 }975 const vModelSelect = {976 created(el, binding, vnode) {977 addEventListener(el, 'change', () => {978 const selectedVal = Array.prototype.filter979 .call(el.options, (o) => o.selected)980 .map(getValue);981 el._assign(el.multiple ? selectedVal : selectedVal[0]);982 });983 el._assign = getModelAssigner(vnode);984 },985 // set value in mounted & updated because <select> relies on its children986 // <option>s.987 mounted(el, { value }) {988 setSelected(el, value);989 },990 beforeUpdate(el, _binding, vnode) {991 el._assign = getModelAssigner(vnode);992 },993 updated(el, { value }) {994 setSelected(el, value);995 }996 };997 /**998 * 999 * node.type:0 ROOT 1 ELEMENT 2 TEXT 3 COMMENT 4 SIMPLE_EXPRESSION 5 INTERPOLATION 8 COMPOUND_EXPRESSION 9 IF 10 IF_BRANCH IF 11 FOR 12 TEXT_CALL1000 * 1001 * static type 0 NOT_STATIC 1 FULL_STATIC 2 HAS_RUNTIME_CONSTANT1002 * tagtype: 0 element 1 template 2 slot1003 * 1004 * codegennode.patchFlag -2 BAIL -1 HOISTED 1 TEXT 2 CLASS 4 STYLE 8 PROPS 16 FULL_PROPS 32 HYDRATE_EVENTS 64 STABLE_FRAGMENT 128 KEYED_FRAGMENT 256 UNKEYED_FRAGMENT 512 NEED_PATCH 1024 DYNAMIC_SLOTS1005 * 1006 */1007 function getStaticType(node, resultCache = new Map()) { // 0 NOT_STATIC 1 FULL_STATIC 2 HAS_RUNTIME_CONSTANT1008 switch (node.type) {1009 case 1 /* ELEMENT */:1010 if (node.tagType !== 0 /* ELEMENT */) {1011 return 0 /* NOT_STATIC */;1012 }1013 const cached = resultCache.get(node);1014 if (cached !== undefined) {1015 return cached;1016 }1017 const codegenNode = node.codegenNode;1018 if (codegenNode.type !== 13 /* VNODE_CALL */) {1019 return 0 /* NOT_STATIC */;1020 }1021 const flag = getPatchFlag(codegenNode);1022 if (!flag && !hasNonHoistableProps(node)) {1023 // element self is static. check its children.1024 let returnType = 1 /* FULL_STATIC */;1025 for (let i = 0; i < node.children.length; i++) {1026 const childType = getStaticType(node.children[i], resultCache);1027 if (childType === 0 /* NOT_STATIC */) {1028 resultCache.set(node, 0 /* NOT_STATIC */);1029 return 0 /* NOT_STATIC */;1030 }1031 else if (childType === 2 /* HAS_RUNTIME_CONSTANT */) {1032 returnType = 2 /* HAS_RUNTIME_CONSTANT */;1033 }1034 }1035 // check if any of the props contain runtime constants1036 if (returnType !== 2 /* HAS_RUNTIME_CONSTANT */) {1037 for (let i = 0; i < node.props.length; i++) {1038 const p = node.props[i];1039 if (p.type === 7 /* DIRECTIVE */ &&1040 p.name === 'bind' &&1041 p.exp &&1042 (p.exp.type === 8 /* COMPOUND_EXPRESSION */ ||1043 p.exp.isRuntimeConstant)) {1044 returnType = 2 /* HAS_RUNTIME_CONSTANT */;1045 }1046 }1047 }1048 // only svg/foreignObject could be block here, however if they are1049 // stati then they don't need to be blocks since there will be no1050 // nested updates.1051 if (codegenNode.isBlock) {1052 codegenNode.isBlock = false;1053 }1054 resultCache.set(node, returnType);1055 return returnType;1056 }1057 else {1058 resultCache.set(node, 0 /* NOT_STATIC */);1059 return 0 /* NOT_STATIC */;1060 }1061 case 2 /* TEXT */:1062 case 3 /* COMMENT */:1063 return 1 /* FULL_STATIC */;1064 case 9 /* IF */:1065 case 11 /* FOR */:1066 case 10 /* IF_BRANCH */:1067 return 0 /* NOT_STATIC */;1068 case 5 /* INTERPOLATION */:1069 case 12 /* TEXT_CALL */:1070 return getStaticType(node.content, resultCache);1071 case 4 /* SIMPLE_EXPRESSION */:1072 return node.isConstant1073 ? node.isRuntimeConstant1074 ? 2 /* HAS_RUNTIME_CONSTANT */1075 : 1 /* FULL_STATIC */1076 : 0 /* NOT_STATIC */;1077 case 8 /* COMPOUND_EXPRESSION */:1078 let returnType = 1 /* FULL_STATIC */;1079 for (let i = 0; i < node.children.length; i++) {1080 const child = node.children[i];1081 if (isString(child) || isSymbol(child)) {1082 continue;1083 }1084 const childType = getStaticType(child, resultCache);1085 if (childType === 0 /* NOT_STATIC */) {1086 return 0 /* NOT_STATIC */;1087 }1088 else if (childType === 2 /* HAS_RUNTIME_CONSTANT */) {1089 returnType = 2 /* HAS_RUNTIME_CONSTANT */;1090 }1091 }1092 return returnType;1093 default:1094 return 0 /* NOT_STATIC */;1095 }1096 }1097 /**1098 * context.scopes1099 * scopes: {1100 vFor: 0,1101 vSlot: 0,1102 vPre: 0,1103 vOnce: 01104 },1105 */1106 function isCoreComponent(tag) {1107 if (isBuiltInType(tag, 'Teleport')) {1108 return TELEPORT;1109 }1110 else if (isBuiltInType(tag, 'Suspense')) {1111 return SUSPENSE;1112 }1113 else if (isBuiltInType(tag, 'KeepAlive')) {1114 return KEEP_ALIVE;1115 }1116 else if (isBuiltInType(tag, 'BaseTransition')) {1117 return BASE_TRANSITION;1118 }1119 }1120 const buildClientSlotFn = (props, children, loc) => {1121 createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);1122 }1123 function createFunctionExpression(params, returns = undefined, newline = false, isSlot = false, loc = locStub) {1124 return {1125 type: 18 /* JS_FUNCTION_EXPRESSION */,1126 params,1127 returns,1128 newline,1129 isSlot,1130 loc1131 };1132 }1133 function buildDynamicSlot(name, fn) {1134 return createObjectExpression([1135 createObjectProperty(`name`, name),1136 createObjectProperty(`fn`, fn)1137 ]);1138 }1139 function createConditionalExpression(test, consequent, alternate, newline = true) {1140 return {1141 type: 19 /* JS_CONDITIONAL_EXPRESSION */,1142 test,1143 consequent,1144 alternate,1145 newline,1146 loc: locStub1147 };1148 }1149 function createForLoopParams({ value, key, index }) {1150 const params = [];1151 if (value) {1152 params.push(value);1153 }1154 if (key) {1155 if (!value) {1156 params.push(createSimpleExpression(`_`, false));1157 }1158 params.push(key);1159 }1160 if (index) {1161 if (!key) {1162 if (!value) {1163 params.push(createSimpleExpression(`_`, false));1164 }1165 params.push(createSimpleExpression(`__`, false));1166 }1167 params.push(index);1168 }1169 return params;1170 }1171 // Instead of being a DirectiveTransform, v-slot processing is called during1172 // transformElement to build the slots object for a component.1173 function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {1174 context.helper(WITH_CTX);1175 const { children, loc } = node;1176 const slotsProperties = [];1177 const dynamicSlots = [];1178 const buildDefaultSlotProperty = (props, children) => createObjectProperty(`default`, buildSlotFn(props, children, loc));1179 // If the slot is inside a v-for or another v-slot, force it to be dynamic1180 // since it likely uses a scope variable.1181 1182 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;1183 // 1. Check for slot with slotProps on component itself.1184 // <Comp v-slot="{ prop }"/>1185 const onComponentSlot = findDir(node, 'slot', true);1186 if (onComponentSlot) {1187 const { arg, exp } = onComponentSlot;1188 if (arg && !isStaticExp(arg)) {1189 hasDynamicSlots = true;1190 }1191 slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc)));1192 }1193 // 2. Iterate through children and check for template slots1194 // <template v-slot:foo="{ prop }">1195 let hasTemplateSlots = false;1196 let hasNamedDefaultSlot = false;1197 const implicitDefaultChildren = [];1198 const seenSlotNames = new Set();1199 for (let i = 0; i < children.length; i++) {1200 const slotElement = children[i];1201 let slotDir;1202 if (!isTemplateNode(slotElement) ||1203 !(slotDir = findDir(slotElement, 'slot', true))) {1204 // not a <template v-slot>, skip.1205 if (slotElement.type !== 3 /* COMMENT */) {1206 implicitDefaultChildren.push(slotElement);1207 }1208 continue;1209 }1210 if (onComponentSlot) {1211 // already has on-component slot - this is incorrect usage.1212 context.onError(createCompilerError(36 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));1213 break;1214 }1215 hasTemplateSlots = true;1216 const { children: slotChildren, loc: slotLoc } = slotElement;1217 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;1218 // check if name is dynamic.1219 let staticSlotName;1220 if (isStaticExp(slotName)) {1221 staticSlotName = slotName ? slotName.content : `default`;1222 }1223 else {1224 hasDynamicSlots = true;1225 }1226 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);1227 // check if this slot is conditional (v-if/v-for)1228 let vIf;1229 let vElse;1230 let vFor;1231 if ((vIf = findDir(slotElement, 'if'))) {1232 hasDynamicSlots = true;1233 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));1234 }1235 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {1236 // find adjacent v-if1237 let j = i;1238 let prev;1239 while (j--) {1240 prev = children[j];1241 if (prev.type !== 3 /* COMMENT */) {1242 break;1243 }1244 }1245 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {1246 // remove node1247 children.splice(i, 1);1248 i--;1249 // attach this slot to previous conditional1250 let conditional = dynamicSlots[dynamicSlots.length - 1];1251 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {1252 conditional = conditional.alternate;1253 }1254 conditional.alternate = vElse.exp1255 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)1256 : buildDynamicSlot(slotName, slotFunction);1257 }1258 else {1259 context.onError(createCompilerError(29 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));1260 }1261 }1262 else if ((vFor = findDir(slotElement, 'for'))) {1263 hasDynamicSlots = true;1264 const parseResult = vFor.parseResult ||1265 parseForExpression(vFor.exp, context);1266 if (parseResult) {1267 // Render the dynamic slots as an array and add it to the createSlot()1268 // args. The runtime knows how to handle it appropriately.1269 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [1270 parseResult.source,1271 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)1272 ]));1273 }1274 else {1275 context.onError(createCompilerError(31 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));1276 }1277 }1278 else {1279 // check duplicate static names1280 if (staticSlotName) {1281 if (seenSlotNames.has(staticSlotName)) {1282 context.onError(createCompilerError(37 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));1283 continue;1284 }1285 seenSlotNames.add(staticSlotName);1286 if (staticSlotName === 'default') {1287 hasNamedDefaultSlot = true;1288 }1289 }1290 slotsProperties.push(createObjectProperty(slotName, slotFunction));1291 }1292 }1293 if (!onComponentSlot) {1294 if (!hasTemplateSlots) {1295 // implicit default slot (on component)1296 slotsProperties.push(buildDefaultSlotProperty(undefined, children));1297 }1298 else if (implicitDefaultChildren.length) {1299 // implicit default slot (mixed with named slots)1300 if (hasNamedDefaultSlot) {1301 context.onError(createCompilerError(38 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));1302 }1303 else {1304 slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));1305 }1306 }1307 }1308 const slotFlag = hasDynamicSlots1309 ? 2 /* DYNAMIC */1310 : hasForwardedSlots(node.children)1311 ? 3 /* FORWARDED */1312 : 1 /* STABLE */;1313 let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, 1314 // 2 = compiled but dynamic = can skip normalization, but must run diff1315 // 1 = compiled and static = can skip normalization AND diff as optimized1316 createSimpleExpression('' + slotFlag, false))), loc);1317 if (dynamicSlots.length) {1318 slots = createCallExpression(context.helper(CREATE_SLOTS), [1319 slots,1320 createArrayExpression(dynamicSlots)1321 ]);1322 }1323 return {1324 slots,1325 hasDynamicSlots1326 };1327 }1328 const trackSlotScopes = (node, context) => {1329 if (node.type === 1 /* ELEMENT */ &&1330 (node.tagType === 1 /* COMPONENT */ ||1331 node.tagType === 3 /* TEMPLATE */)) {1332 // We are only checking non-empty v-slot here1333 // since we only care about slots that introduce scope variables.1334 const vSlot = findDir(node, 'slot');1335 if (vSlot) {1336 const slotProps = vSlot.exp;1337 context.scopes.vSlot++;1338 return () => {1339 context.scopes.vSlot--;1340 };1341 }1342 }1343 };1344 // Merge adjacent text nodes and expressions into a single expression1345 // e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.1346 const transformText = (node, context) => {1347 if (node.type === 0 /* ROOT */ ||1348 node.type === 1 /* ELEMENT */ ||1349 node.type === 11 /* FOR */ ||1350 node.type === 10 /* IF_BRANCH */) {1351 // perform the transform on node exit so that all expressions have already1352 // been processed.1353 return () => {1354 const children = node.children;1355 let currentContainer = undefined;1356 let hasText = false;1357 for (let i = 0; i < children.length; i++) {1358 const child = children[i];1359 if (isText(child)) {1360 hasText = true;1361 for (let j = i + 1; j < children.length; j++) {1362 const next = children[j];1363 if (isText(next)) {1364 if (!currentContainer) {1365 currentContainer = children[i] = {1366 type: 8 /* COMPOUND_EXPRESSION */,1367 loc: child.loc,1368 children: [child]1369 };1370 }1371 // merge adjacent text node into current1372 currentContainer.children.push(` + `, next);1373 children.splice(j, 1);1374 j--;1375 }1376 else {1377 currentContainer = undefined;1378 break;1379 }1380 }1381 }1382 }1383 if (!hasText ||1384 // if this is a plain element with a single text child, leave it1385 // as-is since the runtime has dedicated fast path for this by directly1386 // setting textContent of the element.1387 // for component root it's always normalized anyway.1388 (children.length === 1 &&1389 (node.type === 0 /* ROOT */ ||1390 (node.type === 1 /* ELEMENT */ &&1391 node.tagType === 0 /* ELEMENT */)))) {1392 return;1393 }1394 // pre-convert text nodes into createTextVNode(text) calls to avoid1395 // runtime normalization.1396 for (let i = 0; i < children.length; i++) {1397 const child = children[i];1398 if (isText(child) || child.type === 8 /* COMPOUND_EXPRESSION */) {1399 const callArgs = [];1400 // createTextVNode defaults to single whitespace, so if it is a1401 // single space the code could be an empty call to save bytes.1402 if (child.type !== 2 /* TEXT */ || child.content !== ' ') {1403 callArgs.push(child);1404 }1405 // mark dynamic text with flag so it gets patched inside a block1406 if (!context.ssr && child.type !== 2 /* TEXT */) {1407 callArgs.push(`${1 /* TEXT */} /* ${PatchFlagNames[1 /* TEXT */]} */`);1408 }1409 children[i] = {1410 type: 12 /* TEXT_CALL */,1411 content: child,1412 loc: child.loc,1413 codegenNode: createCallExpression(context.helper(CREATE_TEXT), callArgs)1414 };1415 }1416 }1417 };1418 }1419 };1420 // 2.2 directiveTransforms1421 const transformOn = (dir, node, context, augmentor) => {1422 const { loc, modifiers, arg } = dir;1423 if (!dir.exp && !modifiers.length) {1424 context.onError(createCompilerError(34 /* X_V_ON_NO_EXPRESSION */, loc));1425 }1426 let eventName;1427 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {1428 if (arg.isStatic) {1429 const rawName = arg.content;1430 // for @vnode-xxx event listeners, auto convert it to camelCase1431 const normalizedName = rawName.startsWith(`vnode`)1432 ? capitalize(camelize(rawName))1433 : capitalize(rawName);1434 eventName = createSimpleExpression(`on${normalizedName}`, true, arg.loc);1435 }1436 else {1437 eventName = createCompoundExpression([1438 `"on" + ${context.helperString(CAPITALIZE)}(`,1439 arg,1440 `)`1441 ]);1442 }1443 }1444 else {1445 // already a compound expression.1446 eventName = arg;1447 eventName.children.unshift(`"on" + ${context.helperString(CAPITALIZE)}(`);1448 eventName.children.push(`)`);1449 }1450 // handler processing1451 let exp = dir.exp;1452 if (exp && !exp.content.trim()) {1453 exp = undefined;1454 }1455 let isCacheable = context.cacheHandlers && !exp;1456 if (exp) {1457 const isMemberExp = isMemberExpression(exp.content);1458 const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content));1459 const hasMultipleStatements = exp.content.includes(`;`);1460 {1461 validateBrowserExpression(exp, context, false, hasMultipleStatements);1462 }1463 if (isInlineStatement || (isCacheable && isMemberExp)) {1464 // wrap inline statement in a function expression1465 exp = createCompoundExpression([1466 `${isInlineStatement ? `$event` : `(...args)`} => ${hasMultipleStatements ? `{` : `(`}`,1467 exp,1468 hasMultipleStatements ? `}` : `)`1469 ]);1470 }1471 }1472 let ret = {1473 props: [1474 createObjectProperty(eventName, exp || createSimpleExpression(`() => {}`, false, loc))1475 ]1476 };1477 // apply extended compiler augmentor1478 if (augmentor) {1479 ret = augmentor(ret);1480 }1481 if (isCacheable) {1482 // cache handlers so that it's always the same handler being passed down.1483 // this avoids unnecessary re-renders when users use inline handlers on1484 // components.1485 ret.props[0].value = context.cache(ret.props[0].value);1486 }1487 return ret;1488 };1489 // v-bind without arg is handled directly in ./transformElements.ts due to it affecting1490 // codegen for the entire props object. This transform here is only for v-bind1491 // *with* args.1492 const transformBind = (dir, node, context) => {1493 const { exp, modifiers, loc } = dir;1494 const arg = dir.arg;1495 // .prop is no longer necessary due to new patch behavior1496 // .sync is replaced by v-model:arg1497 if (modifiers.includes('camel')) {1498 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {1499 if (arg.isStatic) {1500 arg.content = camelize(arg.content);1501 }1502 else {1503 arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`;1504 }1505 }1506 else {1507 arg.children.unshift(`${context.helperString(CAMELIZE)}(`);1508 arg.children.push(`)`);1509 }1510 }1511 if (!exp ||1512 (exp.type === 4 /* SIMPLE_EXPRESSION */ && !exp.content.trim())) {1513 context.onError(createCompilerError(33 /* X_V_BIND_NO_EXPRESSION */, loc));1514 return {1515 props: [createObjectProperty(arg, createSimpleExpression('', true, loc))]1516 };1517 }1518 return {1519 props: [createObjectProperty(arg, exp)]1520 };1521 };1522 const transformModel = (dir, node, context) => {1523 const { exp, arg } = dir;1524 if (!exp) {1525 context.onError(createCompilerError(40 /* X_V_MODEL_NO_EXPRESSION */, dir.loc));1526 return createTransformProps();1527 }1528 const expString = exp.type === 4 /* SIMPLE_EXPRESSION */ ? exp.content : exp.loc.source;1529 if (!isMemberExpression(expString)) {1530 context.onError(createCompilerError(41 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));1531 return createTransformProps();1532 }1533 const propName = arg ? arg : createSimpleExpression('modelValue', true);1534 const eventName = arg1535 ? isStaticExp(arg)1536 ? `onUpdate:${arg.content}`1537 : createCompoundExpression(['"onUpdate:" + ', arg])1538 : `onUpdate:modelValue`;1539 const props = [1540 // modelValue: foo1541 createObjectProperty(propName, dir.exp),1542 // "onUpdate:modelValue": $event => (foo = $event)1543 createObjectProperty(eventName, createCompoundExpression([`$event => (`, exp, ` = $event)`]))1544 ];1545 // modelModifiers: { foo: true, "bar-baz": true }1546 if (dir.modifiers.length && node.tagType === 1 /* COMPONENT */) {1547 const modifiers = dir.modifiers1548 .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`)1549 .join(`, `);1550 const modifiersKey = arg1551 ? isStaticExp(arg)1552 ? `${arg.content}Modifiers`1553 : createCompoundExpression([arg, ' + "Modifiers"'])1554 : `modelModifiers`;1555 props.push(createObjectProperty(modifiersKey, createSimpleExpression(`{ ${modifiers} }`, false, dir.loc, true)));1556 }1557 return createTransformProps(props);1558 };1559/**1560 * 3 转æ¢1561 * transform(ast, extend({}, options, {1562 prefixIdentifiers,1563 nodeTransforms: [1564 ...nodeTransforms,1565 ...(options.nodeTransforms || []) // user transforms1566 ],1567 directiveTransforms: extend({}, directiveTransforms, options.directiveTransforms || {} // user transforms1568 )1569 }));1570 */1571function transform(root, options) {1572 const context = createTransformContext(root, options);1573 traverseNode(root, context);1574 if (options.hoistStatic) {1575 hoistStatic(root, context);1576 }1577 if (!options.ssr) {1578 createRootCodegen(root, context);1579 }1580 // finalize meta information1581 root.helpers = [...context.helpers];1582 root.components = [...context.components];1583 root.directives = [...context.directives];1584 root.imports = [...context.imports];1585 root.hoists = context.hoists;1586 root.temps = context.temps;1587 root.cached = context.cached;1588}1589 // 3.1 createTransformContext(root, options);1590 function createTransformContext(root, { prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, isCustomElement = NOOP, expressionPlugins = [], scopeId = null, ssr = false, ssrCssVars = ``, bindingMetadata = {}, onError = defaultOnError }) {1591 const context = {1592 // options1593 prefixIdentifiers,1594 hoistStatic,1595 cacheHandlers,1596 nodeTransforms,1597 directiveTransforms,1598 transformHoist,1599 isBuiltInComponent,1600 isCustomElement,1601 expressionPlugins,1602 scopeId,1603 ssr,1604 ssrCssVars,1605 bindingMetadata,1606 onError,1607 // state1608 root,1609 helpers: new Set(),1610 components: new Set(),1611 directives: new Set(),1612 hoists: [],1613 imports: new Set(),1614 temps: 0,1615 cached: 0,1616 identifiers: Object.create(null),1617 scopes: {1618 vFor: 0,1619 vSlot: 0,1620 vPre: 0,1621 vOnce: 01622 },1623 parent: null,1624 currentNode: root,1625 childIndex: 0,1626 // methods1627 helper(name) {1628 context.helpers.add(name);1629 return name;1630 },1631 helperString(name) {1632 return `_${helperNameMap[context.helper(name)]}`;1633 },1634 replaceNode(node) {1635 /* istanbul ignore if */1636 {1637 if (!context.currentNode) {1638 throw new Error(`Node being replaced is already removed.`);1639 }1640 if (!context.parent) {1641 throw new Error(`Cannot replace root node.`);1642 }1643 }1644 context.parent.children[context.childIndex] = context.currentNode = node;1645 },1646 removeNode(node) {1647 if ( !context.parent) {1648 throw new Error(`Cannot remove root node.`);1649 }1650 const list = context.parent.children;1651 const removalIndex = node1652 ? list.indexOf(node)1653 : context.currentNode1654 ? context.childIndex1655 : -1;1656 /* istanbul ignore if */1657 if ( removalIndex < 0) {1658 throw new Error(`node being removed is not a child of current parent`);1659 }1660 if (!node || node === context.currentNode) {1661 // current node removed1662 context.currentNode = null;1663 context.onNodeRemoved();1664 }1665 else {1666 // sibling node removed1667 if (context.childIndex > removalIndex) {1668 context.childIndex--;1669 context.onNodeRemoved();1670 }1671 }1672 context.parent.children.splice(removalIndex, 1);1673 },1674 onNodeRemoved: () => { },1675 addIdentifiers(exp) {1676 },1677 removeIdentifiers(exp) {1678 },1679 hoist(exp) {1680 context.hoists.push(exp);1681 const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, true);1682 identifier.hoisted = exp;1683 return identifier;1684 },1685 cache(exp, isVNode = false) {1686 return createCacheExpression(++context.cached, exp, isVNode);1687 }1688 };1689 return context;1690 }1691 // 3.2 traverseNode(node, context)1692 function traverseNode(node, context) {1693 context.currentNode = node;1694 // apply transform plugins1695 const { nodeTransforms } = context;1696 const exitFns = [];1697 for (let i = 0; i < nodeTransforms.length; i++) {1698 const onExit = nodeTransforms[i](node, context);1699 if (onExit) {1700 if (isArray(onExit)) {1701 exitFns.push(...onExit);1702 }1703 else {1704 exitFns.push(onExit);1705 }1706 }1707 if (!context.currentNode) {1708 // node was removed1709 return;1710 }1711 else {1712 // node may have been replaced1713 node = context.currentNode;1714 }1715 }1716 switch (node.type) {1717 case 3 /* COMMENT */:1718 if (!context.ssr) {1719 // inject import for the Comment symbol, which is needed for creating1720 // comment nodes with `createVNode`1721 context.helper(CREATE_COMMENT);1722 }1723 break;1724 case 5 /* INTERPOLATION */:1725 // no need to traverse, but we need to inject toString helper1726 if (!context.ssr) {1727 context.helper(TO_DISPLAY_STRING);1728 }1729 break;1730 // for container types, further traverse downwards1731 case 9 /* IF */:1732 for (let i = 0; i < node.branches.length; i++) {1733 traverseNode(node.branches[i], context);1734 }1735 break;1736 case 10 /* IF_BRANCH */:1737 case 11 /* FOR */:1738 case 1 /* ELEMENT */:1739 case 0 /* ROOT */:1740 traverseChildren(node, context);1741 break;1742 }1743 // exit transforms1744 context.currentNode = node;1745 let i = exitFns.length;1746 while (i--) {1747 exitFns[i]();1748 }1749 }1750 function hoistStatic(root, context) {1751 walk(root, context, new Map(), 1752 // Root node is unfortunately non-hoistable due to potential parent1753 // fallthrough attributes.1754 isSingleElementRoot(root, root.children[0]));1755 }1756 /**1757 * context.hoists: []1758 */1759 function hoist(exp) {1760 context.hoists.push(exp);1761 const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, true);1762 identifier.hoisted = exp;1763 return identifier;1764 }1765 function isSingleElementRoot(root, child) {1766 const { children } = root;1767 return (children.length === 1 &&1768 child.type === 1 /* ELEMENT */ &&1769 !isSlotOutlet(child));1770 }1771 function walk(node, context, resultCache, doNotHoistNode = false) {1772 let hasHoistedNode = false;1773 // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces1774 // static bindings with expressions. These expressions are guaranteed to be1775 // constant so they are still eligible for hoisting, but they are only1776 // available at runtime and therefore cannot be evaluated ahead of time.1777 // This is only a concern for pre-stringification (via transformHoist by1778 // @vue/compiler-dom), but doing it here allows us to perform only one full1779 // walk of the AST and allow `stringifyStatic` to stop walking as soon as its1780 // stringficiation threshold is met.1781 let hasRuntimeConstant = false;1782 const { children } = node;1783 for (let i = 0; i < children.length; i++) {...
stable_fragment.js
Source:stable_fragment.js
...223 }224 });225 }226 const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */;227 const slotOutlet = isSlotOutlet(node)228 ? node229 : isTemplate &&230 node.children.length === 1 &&231 isSlotOutlet(node.children[0])232 ? node.children[0] // api-extractor somehow fails to infer this233 : null;234 if (slotOutlet) {235 // <slot v-for="..."> or <template v-for="..."><slot/></template>236 childBlock = slotOutlet.codegenNode;237 if (isTemplate && keyProperty) {238 // <template v-for="..." :key="..."><slot/></template>239 // we need to inject the key to the renderSlot() call.240 // the props for renderSlot is passed as the 3rd argument.241 injectProp(childBlock, keyProperty, context);242 }243 }244 else if (needFragmentWrapper) {245 // <template v-for="..."> with text or multi-elements...
vFor.js
Source:vFor.js
...74 })75 }76 const needFragmentWrapper =77 children.length !== 1 || children[0].type !== 178 const slotOutlet = isSlotOutlet(node)79 ? node80 : isTemplate &&81 node.children.length === 1 &&82 isSlotOutlet(node.children[0])83 ? node.children[0]84 : null85 if (slotOutlet) {86 childBlock = slotOutlet.codegenNode87 if (isTemplate && keyProperty) {88 injectProp(childBlock, keyProperty, context)89 }90 } else if (needFragmentWrapper) {91 childBlock = createVNodeCall(92 context,93 helper(FRAGMENT),94 keyProperty ? createObjectExpression([keyProperty]) : undefined,95 node.children,96 64 + ` /* ${PatchFlagNames[64]} */`,...
utils.js
Source:utils.js
...136function isTemplateNode(node) {137 return (node.type === 1 && node.tagType === 3);138}139exports.isTemplateNode = isTemplateNode;140function isSlotOutlet(node) {141 return node.type === 1 && node.tagType === 2;142}143exports.isSlotOutlet = isSlotOutlet;144function injectProp(node, prop, context) {145 var propsWithInjection;146 var props = node.callee === runtimeHelpers_1.RENDER_SLOT ? node.arguments[2] : node.arguments[1];147 if (props == null || shared_1.isString(props)) {148 propsWithInjection = ast_1.createObjectExpression([prop]);149 }150 else if (props.type === 13) {151 var first = props.arguments[0];152 if (!shared_1.isString(first) && first.type === 14) {153 first.properties.unshift(prop);154 }...
hoistStatic.js
Source:hoistStatic.js
...12 walk(root, context, isSingleElementRoot(root, root.children[0]))13}14export function isSingleElementRoot (root, child) {15 const { children } = root16 return children.length === 1 && child.type === 1 && !isSlotOutlet(child)17}18function walk (node, context, doNotHoistNode = false) {19 const { children } = node20 const originalCount = children.length21 let hoistedCount = 022 for (let i = 0; i < children.length; i++) {23 const child = children[i]24 if (child.type === 1 && child.tagType === 0) {25 const constantType = doNotHoistNode ? 0 : getConstantType(child, context)26 if (constantType > 0) {27 if (constantType >= 2) {28 child.codegenNode.patchFlag = -1 + ` /* HOISTED */`29 child.codegenNode = context.hoist(child.codegenNode)30 hoistedCount++...
disableTracking.js
Source:disableTracking.js
...63 }64 });65 }66 const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */;67 const slotOutlet = isSlotOutlet(node)68 ? node69 : isTemplate &&70 node.children.length === 1 &&71 isSlotOutlet(node.children[0])72 ? node.children[0] // api-extractor somehow fails to infer this73 : null;74 if (slotOutlet) {75 // <slot v-for="..."> or <template v-for="..."><slot/></template>76 childBlock = slotOutlet.codegenNode;77 if (isTemplate && keyProperty) {78 // <template v-for="..." :key="..."><slot/></template>79 // we need to inject the key to the renderSlot() call.80 // the props for renderSlot is passed as the 3rd argument.81 injectProp(childBlock, keyProperty, context);82 }83 }84 else if (needFragmentWrapper) {85 // <template v-for="..."> with text or multi-elements...
transform.simple.js
Source:transform.simple.js
...111 const { children } = root112 return (113 children.length === 1 &&114 child.type === NodeTypes.ELEMENT &&115 !isSlotOutlet(child)116 )117}118function isSlotOutlet( node ){119 return node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT120}121function createBlockExpression( blockExp, context ) {122 return createSequenceExpression([123 createCallExpression(context.helper(OPEN_BLOCK)),124 blockExp125 ])126}127function createSequenceExpression( expressions ){128 return {129 type: NodeTypes.JS_SEQUENCE_EXPRESSION,130 expressions,131 loc: locStub132 }...
transformSlotOutlet.js
Source:transformSlotOutlet.js
...3import { buildProps } from './transformElement.js'4import { RENDER_SLOT } from '../runtimeHelpers.js'5import { camelize } from '../../shared/index.js'6export const transformSlotOutlet = (node, context) => {7 if (isSlotOutlet(node)) {8 const { children, loc } = node9 const { slotName, slotProps } = processSlotOutlet(node, context)10 const slotArgs = [11 context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,12 slotName,13 '{}',14 'undefined',15 'true'16 ]17 let expectedLen = 218 if (slotProps) {19 slotArgs[2] = slotProps20 expectedLen = 321 }...
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch({4 });5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.waitForSelector('#api-class-playwright');8 const slot = await page.$('#api-class-playwright');9 const isSlot = await slot.isSlotOutlet();10 console.log('isSlot:', isSlot);11 await browser.close();12})();
Using AI Code Generation
1const { isSlotOutlet } = require('@playwright/test/lib/internal/frames');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const page = await browser.newPage();6 const frame = page.mainFrame();7 const slot = await frame.$('#gbw');8 const isOutlet = await isSlotOutlet(slot);9 console.log(isOutlet);10 await browser.close();11})();
Using AI Code Generation
1const { isSlotOutlet } = require('@playwright/test/lib/server/frames');2const { Page } = require('@playwright/test');3const { ElementHandle } = require('@playwright/test/lib/server/dom');4const page = new Page();5const elementHandle = new ElementHandle(page, 'elementHandleId');6console.log(isSlotOutlet(elementHandle));7const { isSlotOutlet } = require('@playwright/test/lib/server/frames');8const { Page } = require('@playwright/test');9const { ElementHandle } = require('@playwright/test/lib/server/dom');10const page = new Page();11const elementHandle = new ElementHandle(page, 'elementHandleId');12console.log(isSlotOutlet(elementHandle));13const { isSlotOutlet } = require('@playwright/test/lib/server/frames');14const { Page } = require('@playwright/test');15const { ElementHandle } = require('@playwright/test/lib/server/dom');16const page = new Page();17const elementHandle = new ElementHandle(page, 'elementHandleId');18console.log(isSlotOutlet(elementHandle));19const { isSlotOutlet } = require('@playwright/test/lib/server/frames');20const { Page } = require('@playwright/test');21const { ElementHandle } = require('@playwright/test/lib/server/dom');22const page = new Page();23const elementHandle = new ElementHandle(page, 'elementHandleId');24console.log(isSlotOutlet(elementHandle));25const { isSlotOutlet } = require('@playwright/test/lib/server/frames');26const { Page } = require('@playwright/test');27const { ElementHandle } = require('@playwright/test/lib/server/dom');28const page = new Page();29const elementHandle = new ElementHandle(page, 'elementHandleId');30console.log(isSlotOutlet(elementHandle));31const { isSlotOutlet } = require('@playwright/test/lib/server/frames');32const { Page } = require('@playwright/test');33const { ElementHandle } = require('@playwright/test/lib/server/dom');34const page = new Page();35const elementHandle = new ElementHandle(page, 'elementHandleId');36console.log(isSlotOutlet(elementHandle));
Using AI Code Generation
1import { isSlotOutlet } from 'playwright/lib/server/dom';2const element = document.getElementById('id');3console.log(isSlotOutlet(element));4import { isSlotOutlet } from 'playwright/lib/server/dom';5const element = document.getElementById('id');6console.log(isSlotOutlet(element));
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!!