How to use isSlotOutlet method in Playwright Internal

Best JavaScript code snippet using playwright-internal

note-ast-transform.js

Source:note-ast-transform.js Github

copy

Full Screen

...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++) {...

Full Screen

Full Screen

stable_fragment.js

Source:stable_fragment.js Github

copy

Full Screen

...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...

Full Screen

Full Screen

vFor.js

Source:vFor.js Github

copy

Full Screen

...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]} */`,...

Full Screen

Full Screen

utils.js

Source:utils.js Github

copy

Full Screen

...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 }...

Full Screen

Full Screen

hoistStatic.js

Source:hoistStatic.js Github

copy

Full Screen

...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++...

Full Screen

Full Screen

disableTracking.js

Source:disableTracking.js Github

copy

Full Screen

...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...

Full Screen

Full Screen

transform.simple.js

Source:transform.simple.js Github

copy

Full Screen

...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 }...

Full Screen

Full Screen

transformSlotOutlet.js

Source:transformSlotOutlet.js Github

copy

Full Screen

...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 }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

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})();

Full Screen

Using AI Code Generation

copy

Full Screen

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})();

Full Screen

Using AI Code Generation

copy

Full Screen

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));

Full Screen

Using AI Code Generation

copy

Full Screen

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));

Full Screen

Playwright tutorial

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.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful