diff --git a/packages/compiler-core/__tests__/transforms/vSlot.spec.ts b/packages/compiler-core/__tests__/transforms/vSlot.spec.ts index 4d11e9e0..d7a36196 100644 --- a/packages/compiler-core/__tests__/transforms/vSlot.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vSlot.spec.ts @@ -3,7 +3,8 @@ import { parse, transform, ElementNode, - NodeTypes + NodeTypes, + generate } from '../../src' import { transformElement } from '../../src/transforms/transformElement' import { transformOn } from '../../src/transforms/vOn' @@ -320,4 +321,10 @@ describe('compiler: transform slots', () => { ] }) }) + + test('generate slot', () => { + const ast = parseWithSlots(`
`) + const { code } = generate(ast) + console.log(code) + }) }) diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts index 4bfb4bea..d86b325a 100644 --- a/packages/compiler-core/src/ast.ts +++ b/packages/compiler-core/src/ast.ts @@ -27,7 +27,8 @@ export const enum NodeTypes { JS_CALL_EXPRESSION, JS_OBJECT_EXPRESSION, JS_PROPERTY, - JS_ARRAY_EXPRESSION + JS_ARRAY_EXPRESSION, + JS_SLOT_FUNCTION } export const enum ElementTypes { @@ -157,6 +158,7 @@ export type JSChildNode = | ObjectExpression | ArrayExpression | ExpressionNode + | SlotFunctionExpression export interface CallExpression extends Node { type: NodeTypes.JS_CALL_EXPRESSION @@ -180,6 +182,12 @@ export interface ArrayExpression extends Node { elements: Array } +export interface SlotFunctionExpression extends Node { + type: NodeTypes.JS_SLOT_FUNCTION + params: ExpressionNode | undefined + returns: ChildNode[] +} + export function createArrayExpression( elements: ArrayExpression['elements'], loc: SourceLocation @@ -264,3 +272,16 @@ export function createCallExpression( arguments: args } } + +export function createFunctionExpression( + params: ExpressionNode | undefined, + returns: ChildNode[], + loc: SourceLocation +): SlotFunctionExpression { + return { + type: NodeTypes.JS_SLOT_FUNCTION, + params, + returns, + loc + } +} diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index 9405587f..a2700bbf 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -18,7 +18,8 @@ import { InterpolationNode, CompoundExpressionNode, SimpleExpressionNode, - ElementTypes + ElementTypes, + SlotFunctionExpression } from './ast' import { SourceMapGenerator, RawSourceMap } from 'source-map' import { @@ -364,10 +365,17 @@ function genNode(node: CodegenNode, context: CodegenContext) { case NodeTypes.JS_ARRAY_EXPRESSION: genArrayExpression(node, context) break + case NodeTypes.JS_SLOT_FUNCTION: + genSlotFunction(node, context) + break default: - /* istanbul ignore next */ - __DEV__ && + /* istanbul ignore if */ + if (__DEV__) { assert(false, `unhandled codegen node type: ${(node as any).type}`) + // make sure we exhaust all possible types + const exhaustiveCheck: never = node + return exhaustiveCheck + } } } @@ -568,3 +576,14 @@ function genObjectExpression(node: ObjectExpression, context: CodegenContext) { function genArrayExpression(node: ArrayExpression, context: CodegenContext) { genNodeListAsArray(node.elements, context) } + +function genSlotFunction( + node: SlotFunctionExpression, + context: CodegenContext +) { + context.push(`(`, node) + if (node.params) genNode(node.params, context) + context.push(`) => `) + // pre-normalized slots should always return arrays + genNodeListAsArray(node.returns, context) +} diff --git a/packages/compiler-core/src/errors.ts b/packages/compiler-core/src/errors.ts index a3de21fc..8efb901b 100644 --- a/packages/compiler-core/src/errors.ts +++ b/packages/compiler-core/src/errors.ts @@ -69,6 +69,10 @@ export const enum ErrorCodes { X_V_BIND_NO_EXPRESSION, X_V_ON_NO_EXPRESSION, X_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET, + X_NAMED_SLOT_ON_COMPONENT, + X_MIXED_SLOT_USAGE, + X_DUPLICATE_SLOT_NAMES, + X_EXTRANEOUS_NON_SLOT_CHILDREN, // generic errors X_PREFIX_ID_NOT_SUPPORTED, @@ -133,14 +137,24 @@ export const errorMessages: { [code: number]: string } = { 'Note that dynamic directive argument connot contain spaces.', // transform errors - [ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF]: `v-else-if has no adjacent v-if`, - [ErrorCodes.X_ELSE_NO_ADJACENT_IF]: `v-else has no adjacent v-if`, - [ErrorCodes.X_FOR_NO_EXPRESSION]: `v-for has no expression`, - [ErrorCodes.X_FOR_MALFORMED_EXPRESSION]: `v-for has invalid expression`, - [ErrorCodes.X_V_BIND_NO_EXPRESSION]: `v-bind is missing expression`, - [ErrorCodes.X_V_ON_NO_EXPRESSION]: `v-on is missing expression`, - [ErrorCodes.X_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET]: `unexpected custom directive on outlet`, - + [ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF]: `v-else-if has no adjacent v-if.`, + [ErrorCodes.X_ELSE_NO_ADJACENT_IF]: `v-else has no adjacent v-if.`, + [ErrorCodes.X_FOR_NO_EXPRESSION]: `v-for has no expression.`, + [ErrorCodes.X_FOR_MALFORMED_EXPRESSION]: `v-for has invalid expression.`, + [ErrorCodes.X_V_BIND_NO_EXPRESSION]: `v-bind is missing expression.`, + [ErrorCodes.X_V_ON_NO_EXPRESSION]: `v-on is missing expression.`, + [ErrorCodes.X_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET]: `Unexpected custom directive on outlet.`, + [ErrorCodes.X_NAMED_SLOT_ON_COMPONENT]: + `Named v-slot on component. ` + + `Named slots should use