wip(compiler): adjust renderSlot() signature
This commit is contained in:
		
							parent
							
								
									306c22efe1
								
							
						
					
					
						commit
						05db2a9c6c
					
				| @ -277,8 +277,7 @@ describe('compiler: transform', () => { | ||||
|       expect(ast.codegenNode).toMatchObject({ | ||||
|         codegenNode: { | ||||
|           type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|           callee: `_${RENDER_SLOT}`, | ||||
|           arguments: ['$slots.default'] | ||||
|           callee: `_${RENDER_SLOT}` | ||||
|         } | ||||
|       }) | ||||
|     }) | ||||
|  | ||||
| @ -112,7 +112,7 @@ return function render() { | ||||
|     const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue | ||||
|      | ||||
|     return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => { | ||||
|       return _renderSlot($slots.default) | ||||
|       return _renderSlot($slots, \\"default\\") | ||||
|     }), 128 /* UNKEYED_FRAGMENT */)) | ||||
|   } | ||||
| }" | ||||
| @ -126,7 +126,7 @@ return function render() { | ||||
|     const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue | ||||
|      | ||||
|     return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => { | ||||
|       return _renderSlot($slots.default) | ||||
|       return _renderSlot($slots, \\"default\\") | ||||
|     }), 128 /* UNKEYED_FRAGMENT */)) | ||||
|   } | ||||
| }" | ||||
|  | ||||
| @ -40,7 +40,7 @@ return function render() { | ||||
|     const { openBlock: _openBlock, renderSlot: _renderSlot, createBlock: _createBlock, Empty: _Empty } = _Vue | ||||
|      | ||||
|     return (_openBlock(), ok | ||||
|       ? _renderSlot($slots.default, { key: 0 }) | ||||
|       ? _renderSlot($slots, \\"default\\", { key: 0 }) | ||||
|       : _createBlock(_Empty)) | ||||
|   } | ||||
| }" | ||||
| @ -91,3 +91,17 @@ return function render() { | ||||
|   } | ||||
| }" | ||||
| `; | ||||
| 
 | ||||
| exports[`compiler: v-if codegen v-if on <slot/> 1`] = ` | ||||
| "const _Vue = Vue | ||||
| 
 | ||||
| return function render() { | ||||
|   with (this) { | ||||
|     const { openBlock: _openBlock, renderSlot: _renderSlot, createBlock: _createBlock, Empty: _Empty } = _Vue | ||||
|      | ||||
|     return (_openBlock(), ok | ||||
|       ? _renderSlot($slots, \\"default\\", { key: 0 }) | ||||
|       : _createBlock(_Empty)) | ||||
|   } | ||||
| }" | ||||
| `; | ||||
|  | ||||
| @ -36,7 +36,7 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|     expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({ | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [`$slots.default`] | ||||
|       arguments: [`$slots`, `"default"`] | ||||
|     }) | ||||
|   }) | ||||
| 
 | ||||
| @ -45,16 +45,7 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|     expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({ | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [`$slots.foo`] | ||||
|     }) | ||||
|   }) | ||||
| 
 | ||||
|   test('statically named slot outlet w/ name that needs quotes', () => { | ||||
|     const ast = parseWithSlots(`<slot name="foo-bar" />`) | ||||
|     expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({ | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [`$slots["foo-bar"]`] | ||||
|       arguments: [`$slots`, `"foo"`] | ||||
|     }) | ||||
|   }) | ||||
| 
 | ||||
| @ -64,17 +55,11 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [ | ||||
|         `$slots`, | ||||
|         { | ||||
|           type: NodeTypes.COMPOUND_EXPRESSION, | ||||
|           children: [ | ||||
|             `$slots[`, | ||||
|             { | ||||
|               type: NodeTypes.SIMPLE_EXPRESSION, | ||||
|               content: `foo`, | ||||
|               isStatic: false | ||||
|             }, | ||||
|             `]` | ||||
|           ] | ||||
|           type: NodeTypes.SIMPLE_EXPRESSION, | ||||
|           content: `foo`, | ||||
|           isStatic: false | ||||
|         } | ||||
|       ] | ||||
|     }) | ||||
| @ -88,10 +73,10 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: RENDER_SLOT, | ||||
|       arguments: [ | ||||
|         `_ctx.$slots`, | ||||
|         { | ||||
|           type: NodeTypes.COMPOUND_EXPRESSION, | ||||
|           children: [ | ||||
|             `_ctx.$slots[`, | ||||
|             { | ||||
|               type: NodeTypes.SIMPLE_EXPRESSION, | ||||
|               content: `_ctx.foo`, | ||||
| @ -102,8 +87,7 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|               type: NodeTypes.SIMPLE_EXPRESSION, | ||||
|               content: `_ctx.bar`, | ||||
|               isStatic: false | ||||
|             }, | ||||
|             `]` | ||||
|             } | ||||
|           ] | ||||
|         } | ||||
|       ] | ||||
| @ -116,7 +100,8 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [ | ||||
|         `$slots.default`, | ||||
|         `$slots`, | ||||
|         `"default"`, | ||||
|         { | ||||
|           type: NodeTypes.JS_OBJECT_EXPRESSION, | ||||
|           properties: [ | ||||
| @ -152,7 +137,8 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [ | ||||
|         `$slots.foo`, | ||||
|         `$slots`, | ||||
|         `"foo"`, | ||||
|         { | ||||
|           type: NodeTypes.JS_OBJECT_EXPRESSION, | ||||
|           // props should not include name
 | ||||
| @ -189,10 +175,8 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [ | ||||
|         { | ||||
|           type: NodeTypes.COMPOUND_EXPRESSION, | ||||
|           children: [`$slots[`, { content: `foo` }, `]`] | ||||
|         }, | ||||
|         `$slots`, | ||||
|         { content: `foo`, isStatic: false }, | ||||
|         { | ||||
|           type: NodeTypes.JS_OBJECT_EXPRESSION, | ||||
|           // props should not include name
 | ||||
| @ -229,7 +213,8 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [ | ||||
|         `$slots.default`, | ||||
|         `$slots`, | ||||
|         `"default"`, | ||||
|         `{}`, | ||||
|         [ | ||||
|           { | ||||
| @ -247,7 +232,8 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [ | ||||
|         `$slots.foo`, | ||||
|         `$slots`, | ||||
|         `"foo"`, | ||||
|         `{}`, | ||||
|         [ | ||||
|           { | ||||
| @ -265,7 +251,8 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [ | ||||
|         `$slots.default`, | ||||
|         `$slots`, | ||||
|         `"default"`, | ||||
|         { | ||||
|           type: NodeTypes.JS_OBJECT_EXPRESSION, | ||||
|           properties: [ | ||||
| @ -297,7 +284,8 @@ describe('compiler: transform <slot> outlets', () => { | ||||
|       type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|       callee: `_${RENDER_SLOT}`, | ||||
|       arguments: [ | ||||
|         `$slots.foo`, | ||||
|         `$slots`, | ||||
|         `"foo"`, | ||||
|         { | ||||
|           type: NodeTypes.JS_OBJECT_EXPRESSION, | ||||
|           properties: [ | ||||
|  | ||||
| @ -360,7 +360,23 @@ describe('compiler: v-if', () => { | ||||
|       expect(branch1).toMatchObject({ | ||||
|         type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|         callee: `_${RENDER_SLOT}`, | ||||
|         arguments: ['$slots.default', createObjectMatcher({ key: `[0]` })] | ||||
|         arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })] | ||||
|       }) | ||||
|       expect(generate(root).code).toMatchSnapshot() | ||||
|     }) | ||||
| 
 | ||||
|     test('v-if on <slot/>', () => { | ||||
|       const { | ||||
|         root, | ||||
|         node: { codegenNode } | ||||
|       } = parseWithIfTransform(`<slot v-if="ok"></slot>`) | ||||
|       // assertSharedCodegen(codegenNode)
 | ||||
|       const branch1 = (codegenNode.expressions[1] as ConditionalExpression) | ||||
|         .consequent as CallExpression | ||||
|       expect(branch1).toMatchObject({ | ||||
|         type: NodeTypes.JS_CALL_EXPRESSION, | ||||
|         callee: `_${RENDER_SLOT}`, | ||||
|         arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })] | ||||
|       }) | ||||
|       expect(generate(root).code).toMatchSnapshot() | ||||
|     }) | ||||
|  | ||||
| @ -1,12 +1,11 @@ | ||||
| import { NodeTransform } from '../transform' | ||||
| import { | ||||
|   NodeTypes, | ||||
|   CompoundExpressionNode, | ||||
|   createCompoundExpression, | ||||
|   CallExpression, | ||||
|   createCallExpression | ||||
|   createCallExpression, | ||||
|   ExpressionNode | ||||
| } from '../ast' | ||||
| import { isSimpleIdentifier, isSlotOutlet } from '../utils' | ||||
| import { isSlotOutlet } from '../utils' | ||||
| import { buildProps } from './transformElement' | ||||
| import { createCompilerError, ErrorCodes } from '../errors' | ||||
| import { RENDER_SLOT } from '../runtimeConstants' | ||||
| @ -15,7 +14,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => { | ||||
|   if (isSlotOutlet(node)) { | ||||
|     const { props, children, loc } = node | ||||
|     const $slots = context.prefixIdentifiers ? `_ctx.$slots` : `$slots` | ||||
|     let slot: string | CompoundExpressionNode = $slots + `.default` | ||||
|     let slotName: string | ExpressionNode = `"default"` | ||||
| 
 | ||||
|     // check for <slot name="xxx" OR :name="xxx" />
 | ||||
|     let nameIndex: number = -1 | ||||
| @ -24,11 +23,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => { | ||||
|       if (prop.type === NodeTypes.ATTRIBUTE) { | ||||
|         if (prop.name === `name` && prop.value) { | ||||
|           // static name="xxx"
 | ||||
|           const name = prop.value.content | ||||
|           const accessor = isSimpleIdentifier(name) | ||||
|             ? `.${name}` | ||||
|             : `[${JSON.stringify(name)}]` | ||||
|           slot = `${$slots}${accessor}` | ||||
|           slotName = JSON.stringify(prop.value.content) | ||||
|           nameIndex = i | ||||
|           break | ||||
|         } | ||||
| @ -42,20 +37,14 @@ export const transformSlotOutlet: NodeTransform = (node, context) => { | ||||
|           arg.content === `name` | ||||
|         ) { | ||||
|           // dynamic :name="xxx"
 | ||||
|           slot = createCompoundExpression([ | ||||
|             $slots + `[`, | ||||
|             ...(exp.type === NodeTypes.SIMPLE_EXPRESSION | ||||
|               ? [exp] | ||||
|               : exp.children), | ||||
|             `]` | ||||
|           ]) | ||||
|           slotName = exp | ||||
|           nameIndex = i | ||||
|           break | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     const slotArgs: CallExpression['arguments'] = [slot] | ||||
|     const slotArgs: CallExpression['arguments'] = [$slots, slotName] | ||||
|     const propsWithoutName = | ||||
|       nameIndex > -1 | ||||
|         ? props.slice(0, nameIndex).concat(props.slice(nameIndex + 1)) | ||||
|  | ||||
| @ -118,11 +118,12 @@ export const transformFor = createStructuralDirectiveTransform( | ||||
|             if (isTemplate && keyProperty) { | ||||
|               // <template v-for="..." :key="..."><slot/></template>
 | ||||
|               // we need to inject the key to the renderSlot() call.
 | ||||
|               const existingProps = childBlock.arguments[1] as | ||||
|               // the props for renderSlot is passed as the 3rd argument.
 | ||||
|               const existingProps = childBlock.arguments[2] as | ||||
|                 | PropsExpression | ||||
|                 | undefined | ||||
|                 | 'null' | ||||
|               childBlock.arguments[1] = injectProp( | ||||
|               childBlock.arguments[2] = injectProp( | ||||
|                 existingProps, | ||||
|                 keyProperty, | ||||
|                 context | ||||
|  | ||||
| @ -27,7 +27,8 @@ import { | ||||
|   EMPTY, | ||||
|   FRAGMENT, | ||||
|   APPLY_DIRECTIVES, | ||||
|   CREATE_VNODE | ||||
|   CREATE_VNODE, | ||||
|   RENDER_SLOT | ||||
| } from '../runtimeConstants' | ||||
| import { injectProp } from '../utils' | ||||
| import { PropsExpression } from './transformElement' | ||||
| @ -185,18 +186,24 @@ function createChildrenCodegenNode( | ||||
|       vnodeCall = vnodeCall.arguments[0] as CallExpression | ||||
|     } | ||||
|     // Change createVNode to createBlock.
 | ||||
|     // It's possible to have renderSlot() here as well - which already produces
 | ||||
|     // a block, so no need to change the callee. renderSlot() also accepts props
 | ||||
|     // as the 2nd argument, so the key injection logic below works for it too.
 | ||||
|     if (vnodeCall.callee.includes(CREATE_VNODE)) { | ||||
|       vnodeCall.callee = helper(CREATE_BLOCK) | ||||
|     } | ||||
|     // It's possible to have renderSlot() here as well - which already produces
 | ||||
|     // a block, so no need to change the callee. However it accepts props at
 | ||||
|     // a different arg index so make sure to check for so that the key injection
 | ||||
|     // logic below works for it too.
 | ||||
|     const propsIndex = vnodeCall.callee.includes(RENDER_SLOT) ? 2 : 1 | ||||
|     // inject branch key
 | ||||
|     const existingProps = vnodeCall.arguments[1] as | ||||
|     const existingProps = vnodeCall.arguments[propsIndex] as | ||||
|       | PropsExpression | ||||
|       | undefined | ||||
|       | 'null' | ||||
|     vnodeCall.arguments[1] = injectProp(existingProps, keyProperty, context) | ||||
|     vnodeCall.arguments[propsIndex] = injectProp( | ||||
|       existingProps, | ||||
|       keyProperty, | ||||
|       context | ||||
|     ) | ||||
|     return childCodegen | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -8,12 +8,14 @@ import { | ||||
| } from '../vnode' | ||||
| 
 | ||||
| export function renderSlot( | ||||
|   slot: Slot | undefined, | ||||
|   slots: Record<string, Slot>, | ||||
|   key: string, | ||||
|   props: any = {}, | ||||
|   // this is not a user-facing function, so the fallback is always generated by
 | ||||
|   // the compiler and gurunteed to be an array
 | ||||
|   fallback?: VNodeChildren | ||||
| ): VNode { | ||||
|   const slot = slots[key] | ||||
|   return ( | ||||
|     openBlock(), | ||||
|     createBlock( | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user