2019-09-27 23:42:02 +08:00
|
|
|
import { isString } from '@vue/shared'
|
2019-10-03 11:10:41 +08:00
|
|
|
import { ForParseResult } from './transforms/vFor'
|
2019-10-06 10:47:20 +08:00
|
|
|
import {
|
|
|
|
RENDER_SLOT,
|
|
|
|
CREATE_SLOTS,
|
|
|
|
RENDER_LIST,
|
|
|
|
OPEN_BLOCK,
|
|
|
|
CREATE_BLOCK,
|
2020-02-12 07:12:56 +08:00
|
|
|
FRAGMENT,
|
|
|
|
CREATE_VNODE,
|
|
|
|
WITH_DIRECTIVES
|
2019-10-06 10:47:20 +08:00
|
|
|
} from './runtimeHelpers'
|
|
|
|
import { PropsExpression } from './transforms/transformElement'
|
2020-02-12 07:12:56 +08:00
|
|
|
import { ImportItem, TransformContext } from './transform'
|
2019-09-27 23:42:02 +08:00
|
|
|
|
2019-09-17 23:07:46 +08:00
|
|
|
// Vue template is a platform-agnostic superset of HTML (syntax only).
|
|
|
|
// More namespaces like SVG and MathML are declared by platform specific
|
|
|
|
// compilers.
|
|
|
|
export type Namespace = number
|
|
|
|
|
|
|
|
export const enum Namespaces {
|
|
|
|
HTML
|
|
|
|
}
|
|
|
|
|
2019-09-17 02:43:29 +08:00
|
|
|
export const enum NodeTypes {
|
2019-09-18 07:08:47 +08:00
|
|
|
ROOT,
|
|
|
|
ELEMENT,
|
2019-09-17 02:43:29 +08:00
|
|
|
TEXT,
|
|
|
|
COMMENT,
|
2019-09-27 23:42:02 +08:00
|
|
|
SIMPLE_EXPRESSION,
|
|
|
|
INTERPOLATION,
|
2019-09-18 07:08:47 +08:00
|
|
|
ATTRIBUTE,
|
2019-09-17 02:43:29 +08:00
|
|
|
DIRECTIVE,
|
2019-09-22 03:47:26 +08:00
|
|
|
// containers
|
2019-09-23 14:52:54 +08:00
|
|
|
COMPOUND_EXPRESSION,
|
2019-09-18 07:08:47 +08:00
|
|
|
IF,
|
|
|
|
IF_BRANCH,
|
2019-09-22 03:47:26 +08:00
|
|
|
FOR,
|
2019-10-22 03:52:29 +08:00
|
|
|
TEXT_CALL,
|
2019-09-22 03:47:26 +08:00
|
|
|
// codegen
|
2020-02-12 07:12:56 +08:00
|
|
|
VNODE_CALL,
|
2019-09-23 04:50:57 +08:00
|
|
|
JS_CALL_EXPRESSION,
|
|
|
|
JS_OBJECT_EXPRESSION,
|
|
|
|
JS_PROPERTY,
|
2019-09-28 10:25:32 +08:00
|
|
|
JS_ARRAY_EXPRESSION,
|
2019-10-02 04:48:20 +08:00
|
|
|
JS_FUNCTION_EXPRESSION,
|
2019-10-19 09:51:34 +08:00
|
|
|
JS_CONDITIONAL_EXPRESSION,
|
2020-02-02 13:05:27 +08:00
|
|
|
JS_CACHE_EXPRESSION,
|
|
|
|
|
|
|
|
// ssr codegen
|
|
|
|
JS_BLOCK_STATEMENT,
|
|
|
|
JS_TEMPLATE_LITERAL,
|
2020-02-05 11:49:47 +08:00
|
|
|
JS_IF_STATEMENT,
|
2020-02-07 14:06:51 +08:00
|
|
|
JS_ASSIGNMENT_EXPRESSION,
|
2020-03-17 06:14:49 +08:00
|
|
|
JS_SEQUENCE_EXPRESSION,
|
2020-02-07 14:06:51 +08:00
|
|
|
JS_RETURN_STATEMENT
|
2019-09-17 02:43:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export const enum ElementTypes {
|
|
|
|
ELEMENT,
|
|
|
|
COMPONENT,
|
2019-09-18 07:08:47 +08:00
|
|
|
SLOT,
|
2019-11-05 23:26:36 +08:00
|
|
|
TEMPLATE
|
2019-09-17 02:43:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface Node {
|
|
|
|
type: NodeTypes
|
|
|
|
loc: SourceLocation
|
|
|
|
}
|
|
|
|
|
2019-09-22 03:47:26 +08:00
|
|
|
// The node's range. The `start` is inclusive and `end` is exclusive.
|
|
|
|
// [start, end)
|
|
|
|
export interface SourceLocation {
|
|
|
|
start: Position
|
|
|
|
end: Position
|
|
|
|
source: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface Position {
|
|
|
|
offset: number // from start of file
|
|
|
|
line: number
|
|
|
|
column: number
|
|
|
|
}
|
|
|
|
|
2019-09-18 07:08:47 +08:00
|
|
|
export type ParentNode = RootNode | ElementNode | IfBranchNode | ForNode
|
2019-09-22 03:47:26 +08:00
|
|
|
|
2019-09-27 23:42:02 +08:00
|
|
|
export type ExpressionNode = SimpleExpressionNode | CompoundExpressionNode
|
|
|
|
|
2019-10-01 21:27:34 +08:00
|
|
|
export type TemplateChildNode =
|
2019-09-18 07:08:47 +08:00
|
|
|
| ElementNode
|
2019-09-27 23:42:02 +08:00
|
|
|
| InterpolationNode
|
2019-10-01 02:51:55 +08:00
|
|
|
| CompoundExpressionNode
|
2019-09-18 07:08:47 +08:00
|
|
|
| TextNode
|
|
|
|
| CommentNode
|
|
|
|
| IfNode
|
2020-02-15 04:57:14 +08:00
|
|
|
| IfBranchNode
|
2019-09-18 07:08:47 +08:00
|
|
|
| ForNode
|
2019-10-22 03:52:29 +08:00
|
|
|
| TextCallNode
|
2019-09-18 07:08:47 +08:00
|
|
|
|
2019-09-17 02:43:29 +08:00
|
|
|
export interface RootNode extends Node {
|
|
|
|
type: NodeTypes.ROOT
|
2019-10-01 21:27:34 +08:00
|
|
|
children: TemplateChildNode[]
|
2019-10-11 06:02:51 +08:00
|
|
|
helpers: symbol[]
|
2019-10-06 05:18:25 +08:00
|
|
|
components: string[]
|
|
|
|
directives: string[]
|
2019-09-26 02:13:33 +08:00
|
|
|
hoists: JSChildNode[]
|
2019-12-11 01:53:26 +08:00
|
|
|
imports: ImportItem[]
|
2019-10-19 09:51:34 +08:00
|
|
|
cached: number
|
2020-02-05 11:49:47 +08:00
|
|
|
temps: number
|
2020-02-04 06:47:06 +08:00
|
|
|
ssrHelpers?: symbol[]
|
2020-02-05 11:49:47 +08:00
|
|
|
codegenNode?: TemplateChildNode | JSChildNode | BlockStatement | undefined
|
2019-09-17 02:43:29 +08:00
|
|
|
}
|
|
|
|
|
2019-10-06 10:47:20 +08:00
|
|
|
export type ElementNode =
|
|
|
|
| PlainElementNode
|
|
|
|
| ComponentNode
|
|
|
|
| SlotOutletNode
|
|
|
|
| TemplateNode
|
|
|
|
|
|
|
|
export interface BaseElementNode extends Node {
|
2019-09-17 02:43:29 +08:00
|
|
|
type: NodeTypes.ELEMENT
|
2019-09-17 23:07:46 +08:00
|
|
|
ns: Namespace
|
2019-09-17 02:43:29 +08:00
|
|
|
tag: string
|
|
|
|
tagType: ElementTypes
|
|
|
|
isSelfClosing: boolean
|
2019-09-22 05:42:12 +08:00
|
|
|
props: Array<AttributeNode | DirectiveNode>
|
2019-10-01 21:27:34 +08:00
|
|
|
children: TemplateChildNode[]
|
2019-09-17 02:43:29 +08:00
|
|
|
}
|
|
|
|
|
2019-10-06 10:47:20 +08:00
|
|
|
export interface PlainElementNode extends BaseElementNode {
|
2019-10-06 05:18:25 +08:00
|
|
|
tagType: ElementTypes.ELEMENT
|
2019-10-24 05:57:40 +08:00
|
|
|
codegenNode:
|
2020-02-12 07:12:56 +08:00
|
|
|
| VNodeCall
|
2019-10-24 05:57:40 +08:00
|
|
|
| SimpleExpressionNode // when hoisted
|
|
|
|
| CacheExpression // when cached by v-once
|
2020-01-21 03:48:19 +08:00
|
|
|
| undefined
|
2020-02-02 13:05:27 +08:00
|
|
|
ssrCodegenNode?: TemplateLiteral
|
2019-10-06 05:18:25 +08:00
|
|
|
}
|
|
|
|
|
2019-10-06 10:47:20 +08:00
|
|
|
export interface ComponentNode extends BaseElementNode {
|
2019-10-06 05:18:25 +08:00
|
|
|
tagType: ElementTypes.COMPONENT
|
2020-01-21 03:48:19 +08:00
|
|
|
codegenNode:
|
2020-02-12 07:12:56 +08:00
|
|
|
| VNodeCall
|
2020-01-21 03:48:19 +08:00
|
|
|
| CacheExpression // when cached by v-once
|
|
|
|
| undefined
|
2020-02-06 10:04:40 +08:00
|
|
|
ssrCodegenNode?: CallExpression
|
2019-10-06 05:18:25 +08:00
|
|
|
}
|
|
|
|
|
2019-10-06 10:47:20 +08:00
|
|
|
export interface SlotOutletNode extends BaseElementNode {
|
2019-10-06 05:18:25 +08:00
|
|
|
tagType: ElementTypes.SLOT
|
2020-02-12 07:12:56 +08:00
|
|
|
codegenNode:
|
|
|
|
| RenderSlotCall
|
|
|
|
| CacheExpression // when cached by v-once
|
|
|
|
| undefined
|
2020-02-06 10:04:40 +08:00
|
|
|
ssrCodegenNode?: CallExpression
|
2019-10-06 05:18:25 +08:00
|
|
|
}
|
|
|
|
|
2019-10-06 10:47:20 +08:00
|
|
|
export interface TemplateNode extends BaseElementNode {
|
|
|
|
tagType: ElementTypes.TEMPLATE
|
2020-02-02 13:05:27 +08:00
|
|
|
// TemplateNode is a container type that always gets compiled away
|
2020-02-12 07:12:56 +08:00
|
|
|
codegenNode: undefined
|
2019-10-06 05:18:25 +08:00
|
|
|
}
|
|
|
|
|
2019-09-17 02:43:29 +08:00
|
|
|
export interface TextNode extends Node {
|
|
|
|
type: NodeTypes.TEXT
|
|
|
|
content: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface CommentNode extends Node {
|
|
|
|
type: NodeTypes.COMMENT
|
|
|
|
content: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface AttributeNode extends Node {
|
|
|
|
type: NodeTypes.ATTRIBUTE
|
|
|
|
name: string
|
|
|
|
value: TextNode | undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DirectiveNode extends Node {
|
|
|
|
type: NodeTypes.DIRECTIVE
|
|
|
|
name: string
|
|
|
|
exp: ExpressionNode | undefined
|
|
|
|
arg: ExpressionNode | undefined
|
|
|
|
modifiers: string[]
|
2019-10-03 11:10:41 +08:00
|
|
|
// optional property to cache the expression parse result for v-for
|
|
|
|
parseResult?: ForParseResult
|
2019-09-17 02:43:29 +08:00
|
|
|
}
|
|
|
|
|
2019-09-27 23:42:02 +08:00
|
|
|
export interface SimpleExpressionNode extends Node {
|
|
|
|
type: NodeTypes.SIMPLE_EXPRESSION
|
2019-09-17 02:43:29 +08:00
|
|
|
content: string
|
|
|
|
isStatic: boolean
|
2019-10-15 23:41:24 +08:00
|
|
|
isConstant: boolean
|
2019-09-28 12:19:24 +08:00
|
|
|
// an expression parsed as the params of a function will track
|
|
|
|
// the identifiers declared inside the function body.
|
|
|
|
identifiers?: string[]
|
2019-09-27 23:42:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface InterpolationNode extends Node {
|
|
|
|
type: NodeTypes.INTERPOLATION
|
|
|
|
content: ExpressionNode
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface CompoundExpressionNode extends Node {
|
|
|
|
type: NodeTypes.COMPOUND_EXPRESSION
|
2019-10-06 05:18:25 +08:00
|
|
|
children: (
|
|
|
|
| SimpleExpressionNode
|
2020-02-06 03:23:03 +08:00
|
|
|
| CompoundExpressionNode
|
2019-10-06 05:18:25 +08:00
|
|
|
| InterpolationNode
|
|
|
|
| TextNode
|
|
|
|
| string
|
2019-10-11 06:02:51 +08:00
|
|
|
| symbol)[]
|
2019-09-28 12:19:24 +08:00
|
|
|
// an expression parsed as the params of a function will track
|
|
|
|
// the identifiers declared inside the function body.
|
|
|
|
identifiers?: string[]
|
2019-09-17 02:43:29 +08:00
|
|
|
}
|
|
|
|
|
2019-09-18 07:08:47 +08:00
|
|
|
export interface IfNode extends Node {
|
|
|
|
type: NodeTypes.IF
|
|
|
|
branches: IfBranchNode[]
|
2020-02-12 07:12:56 +08:00
|
|
|
codegenNode?: IfConditionalExpression
|
2019-09-18 07:08:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface IfBranchNode extends Node {
|
|
|
|
type: NodeTypes.IF_BRANCH
|
|
|
|
condition: ExpressionNode | undefined // else
|
2019-10-01 21:27:34 +08:00
|
|
|
children: TemplateChildNode[]
|
2019-09-18 07:08:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface ForNode extends Node {
|
|
|
|
type: NodeTypes.FOR
|
|
|
|
source: ExpressionNode
|
2019-09-29 04:02:08 +08:00
|
|
|
valueAlias: ExpressionNode | undefined
|
|
|
|
keyAlias: ExpressionNode | undefined
|
|
|
|
objectIndexAlias: ExpressionNode | undefined
|
2020-02-04 07:30:56 +08:00
|
|
|
parseResult: ForParseResult
|
2019-10-01 21:27:34 +08:00
|
|
|
children: TemplateChildNode[]
|
2020-02-04 04:51:41 +08:00
|
|
|
codegenNode?: ForCodegenNode
|
2019-09-18 07:08:47 +08:00
|
|
|
}
|
|
|
|
|
2019-10-22 03:52:29 +08:00
|
|
|
export interface TextCallNode extends Node {
|
|
|
|
type: NodeTypes.TEXT_CALL
|
|
|
|
content: TextNode | InterpolationNode | CompoundExpressionNode
|
2020-02-11 07:32:11 +08:00
|
|
|
codegenNode: CallExpression | SimpleExpressionNode // when hoisted
|
2019-10-22 03:52:29 +08:00
|
|
|
}
|
|
|
|
|
2020-02-12 07:12:56 +08:00
|
|
|
export type TemplateTextChildNode =
|
|
|
|
| TextNode
|
|
|
|
| InterpolationNode
|
|
|
|
| CompoundExpressionNode
|
|
|
|
|
|
|
|
export interface VNodeCall extends Node {
|
|
|
|
type: NodeTypes.VNODE_CALL
|
|
|
|
tag: string | symbol | CallExpression
|
|
|
|
props: PropsExpression | undefined
|
|
|
|
children:
|
|
|
|
| TemplateChildNode[] // multiple children
|
|
|
|
| TemplateTextChildNode // single text child
|
|
|
|
| SlotsExpression // component slots
|
|
|
|
| ForRenderListExpression // v-for fragment call
|
|
|
|
| undefined
|
|
|
|
patchFlag: string | undefined
|
|
|
|
dynamicProps: string | undefined
|
|
|
|
directives: DirectiveArguments | undefined
|
|
|
|
isBlock: boolean
|
|
|
|
isForBlock: boolean
|
|
|
|
}
|
|
|
|
|
2020-02-02 13:05:27 +08:00
|
|
|
// JS Node Types ---------------------------------------------------------------
|
|
|
|
|
2019-09-23 04:50:57 +08:00
|
|
|
// We also include a number of JavaScript AST nodes for code generation.
|
2019-10-05 22:23:25 +08:00
|
|
|
// The AST is an intentionally minimal subset just to meet the exact needs of
|
2019-09-22 03:47:26 +08:00
|
|
|
// Vue render function generation.
|
2020-02-02 13:05:27 +08:00
|
|
|
|
2019-09-23 04:50:57 +08:00
|
|
|
export type JSChildNode =
|
2020-02-12 07:12:56 +08:00
|
|
|
| VNodeCall
|
2019-09-22 03:47:26 +08:00
|
|
|
| CallExpression
|
|
|
|
| ObjectExpression
|
|
|
|
| ArrayExpression
|
|
|
|
| ExpressionNode
|
2019-10-02 04:48:20 +08:00
|
|
|
| FunctionExpression
|
2019-10-01 21:27:34 +08:00
|
|
|
| ConditionalExpression
|
2019-10-19 09:51:34 +08:00
|
|
|
| CacheExpression
|
2020-02-05 11:49:47 +08:00
|
|
|
| AssignmentExpression
|
2020-03-17 06:14:49 +08:00
|
|
|
| SequenceExpression
|
2019-09-22 03:47:26 +08:00
|
|
|
|
|
|
|
export interface CallExpression extends Node {
|
2019-09-23 04:50:57 +08:00
|
|
|
type: NodeTypes.JS_CALL_EXPRESSION
|
2019-10-11 06:02:51 +08:00
|
|
|
callee: string | symbol
|
2019-10-06 05:18:25 +08:00
|
|
|
arguments: (
|
|
|
|
| string
|
2019-10-11 06:02:51 +08:00
|
|
|
| symbol
|
2019-10-06 05:18:25 +08:00
|
|
|
| JSChildNode
|
2020-02-02 13:05:27 +08:00
|
|
|
| SSRCodegenNode
|
2019-10-06 05:18:25 +08:00
|
|
|
| TemplateChildNode
|
|
|
|
| TemplateChildNode[])[]
|
2019-09-17 02:43:29 +08:00
|
|
|
}
|
|
|
|
|
2019-09-22 03:47:26 +08:00
|
|
|
export interface ObjectExpression extends Node {
|
2019-09-23 04:50:57 +08:00
|
|
|
type: NodeTypes.JS_OBJECT_EXPRESSION
|
2019-09-22 03:47:26 +08:00
|
|
|
properties: Array<Property>
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface Property extends Node {
|
2019-09-23 04:50:57 +08:00
|
|
|
type: NodeTypes.JS_PROPERTY
|
2019-09-22 03:47:26 +08:00
|
|
|
key: ExpressionNode
|
2019-09-26 00:39:46 +08:00
|
|
|
value: JSChildNode
|
2019-09-22 03:47:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface ArrayExpression extends Node {
|
2019-09-23 04:50:57 +08:00
|
|
|
type: NodeTypes.JS_ARRAY_EXPRESSION
|
|
|
|
elements: Array<string | JSChildNode>
|
2019-09-17 02:43:29 +08:00
|
|
|
}
|
2019-09-22 05:42:12 +08:00
|
|
|
|
2019-10-02 04:48:20 +08:00
|
|
|
export interface FunctionExpression extends Node {
|
|
|
|
type: NodeTypes.JS_FUNCTION_EXPRESSION
|
2020-02-07 01:07:25 +08:00
|
|
|
params: ExpressionNode | string | (ExpressionNode | string)[] | undefined
|
2020-02-02 13:05:27 +08:00
|
|
|
returns?: TemplateChildNode | TemplateChildNode[] | JSChildNode
|
2020-02-07 14:06:51 +08:00
|
|
|
body?: BlockStatement | IfStatement
|
2019-10-02 04:48:20 +08:00
|
|
|
newline: boolean
|
2020-02-02 13:05:27 +08:00
|
|
|
// so that codegen knows it needs to generate ScopeId wrapper
|
2019-12-17 01:11:51 +08:00
|
|
|
isSlot: boolean
|
2019-10-01 21:27:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface ConditionalExpression extends Node {
|
|
|
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION
|
2020-02-05 05:47:12 +08:00
|
|
|
test: JSChildNode
|
2019-10-01 21:27:34 +08:00
|
|
|
consequent: JSChildNode
|
|
|
|
alternate: JSChildNode
|
2020-02-05 05:47:12 +08:00
|
|
|
newline: boolean
|
2019-09-28 10:25:32 +08:00
|
|
|
}
|
|
|
|
|
2019-10-19 09:51:34 +08:00
|
|
|
export interface CacheExpression extends Node {
|
|
|
|
type: NodeTypes.JS_CACHE_EXPRESSION
|
|
|
|
index: number
|
|
|
|
value: JSChildNode
|
2019-10-24 05:57:40 +08:00
|
|
|
isVNode: boolean
|
2019-10-19 09:51:34 +08:00
|
|
|
}
|
|
|
|
|
2020-02-02 13:05:27 +08:00
|
|
|
// SSR-specific Node Types -----------------------------------------------------
|
|
|
|
|
2020-02-07 14:06:51 +08:00
|
|
|
export type SSRCodegenNode =
|
|
|
|
| BlockStatement
|
|
|
|
| TemplateLiteral
|
|
|
|
| IfStatement
|
|
|
|
| AssignmentExpression
|
|
|
|
| ReturnStatement
|
2020-03-17 06:14:49 +08:00
|
|
|
| SequenceExpression
|
2020-02-02 13:05:27 +08:00
|
|
|
|
|
|
|
export interface BlockStatement extends Node {
|
|
|
|
type: NodeTypes.JS_BLOCK_STATEMENT
|
|
|
|
body: (JSChildNode | IfStatement)[]
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface TemplateLiteral extends Node {
|
|
|
|
type: NodeTypes.JS_TEMPLATE_LITERAL
|
|
|
|
elements: (string | JSChildNode)[]
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface IfStatement extends Node {
|
|
|
|
type: NodeTypes.JS_IF_STATEMENT
|
|
|
|
test: ExpressionNode
|
|
|
|
consequent: BlockStatement
|
2020-02-07 14:06:51 +08:00
|
|
|
alternate: IfStatement | BlockStatement | ReturnStatement | undefined
|
2020-02-02 13:05:27 +08:00
|
|
|
}
|
|
|
|
|
2020-02-05 11:49:47 +08:00
|
|
|
export interface AssignmentExpression extends Node {
|
|
|
|
type: NodeTypes.JS_ASSIGNMENT_EXPRESSION
|
|
|
|
left: SimpleExpressionNode
|
|
|
|
right: JSChildNode
|
|
|
|
}
|
|
|
|
|
2020-03-17 06:14:49 +08:00
|
|
|
export interface SequenceExpression extends Node {
|
|
|
|
type: NodeTypes.JS_SEQUENCE_EXPRESSION
|
|
|
|
expressions: JSChildNode[]
|
|
|
|
}
|
|
|
|
|
2020-02-07 14:06:51 +08:00
|
|
|
export interface ReturnStatement extends Node {
|
|
|
|
type: NodeTypes.JS_RETURN_STATEMENT
|
|
|
|
returns: TemplateChildNode | TemplateChildNode[] | JSChildNode
|
|
|
|
}
|
|
|
|
|
2019-10-06 10:47:20 +08:00
|
|
|
// Codegen Node Types ----------------------------------------------------------
|
|
|
|
|
2020-02-12 07:12:56 +08:00
|
|
|
export interface DirectiveArguments extends ArrayExpression {
|
|
|
|
elements: DirectiveArgumentNode[]
|
2019-10-06 10:47:20 +08:00
|
|
|
}
|
|
|
|
|
2020-02-12 07:12:56 +08:00
|
|
|
export interface DirectiveArgumentNode extends ArrayExpression {
|
|
|
|
elements: // dir, exp, arg, modifiers
|
|
|
|
| [string]
|
|
|
|
| [string, ExpressionNode]
|
|
|
|
| [string, ExpressionNode, ExpressionNode]
|
|
|
|
| [string, ExpressionNode, ExpressionNode, ObjectExpression]
|
|
|
|
}
|
2019-10-06 10:47:20 +08:00
|
|
|
|
2020-02-12 07:12:56 +08:00
|
|
|
// renderSlot(...)
|
|
|
|
export interface RenderSlotCall extends CallExpression {
|
|
|
|
callee: typeof RENDER_SLOT
|
|
|
|
arguments: // $slots, name, props, fallback
|
|
|
|
| [string, string | ExpressionNode]
|
|
|
|
| [string, string | ExpressionNode, PropsExpression]
|
2019-10-06 10:47:20 +08:00
|
|
|
| [
|
|
|
|
string,
|
2020-02-12 07:12:56 +08:00
|
|
|
string | ExpressionNode,
|
|
|
|
PropsExpression | '{}',
|
|
|
|
TemplateChildNode[]
|
2019-10-06 10:47:20 +08:00
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
export type SlotsExpression = SlotsObjectExpression | DynamicSlotsExpression
|
|
|
|
|
|
|
|
// { foo: () => [...] }
|
|
|
|
export interface SlotsObjectExpression extends ObjectExpression {
|
|
|
|
properties: SlotsObjectProperty[]
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface SlotsObjectProperty extends Property {
|
|
|
|
value: SlotFunctionExpression
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface SlotFunctionExpression extends FunctionExpression {
|
|
|
|
returns: TemplateChildNode[]
|
|
|
|
}
|
|
|
|
|
|
|
|
// createSlots({ ... }, [
|
|
|
|
// foo ? () => [] : undefined,
|
|
|
|
// renderList(list, i => () => [i])
|
|
|
|
// ])
|
|
|
|
export interface DynamicSlotsExpression extends CallExpression {
|
|
|
|
callee: typeof CREATE_SLOTS
|
|
|
|
arguments: [SlotsObjectExpression, DynamicSlotEntries]
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DynamicSlotEntries extends ArrayExpression {
|
2019-10-10 22:26:03 +08:00
|
|
|
elements: (ConditionalDynamicSlotNode | ListDynamicSlotNode)[]
|
2019-10-06 10:47:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface ConditionalDynamicSlotNode extends ConditionalExpression {
|
|
|
|
consequent: DynamicSlotNode
|
|
|
|
alternate: DynamicSlotNode | SimpleExpressionNode
|
|
|
|
}
|
|
|
|
|
2019-10-10 22:26:03 +08:00
|
|
|
export interface ListDynamicSlotNode extends CallExpression {
|
2019-10-06 10:47:20 +08:00
|
|
|
callee: typeof RENDER_LIST
|
2019-10-11 21:59:52 +08:00
|
|
|
arguments: [ExpressionNode, ListDynamicSlotIterator]
|
2019-10-06 10:47:20 +08:00
|
|
|
}
|
|
|
|
|
2019-10-11 21:59:52 +08:00
|
|
|
export interface ListDynamicSlotIterator extends FunctionExpression {
|
2019-10-06 10:47:20 +08:00
|
|
|
returns: DynamicSlotNode
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DynamicSlotNode extends ObjectExpression {
|
|
|
|
properties: [Property, DynamicSlotFnProperty]
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DynamicSlotFnProperty extends Property {
|
|
|
|
value: SlotFunctionExpression
|
|
|
|
}
|
|
|
|
|
2020-02-12 07:12:56 +08:00
|
|
|
export type BlockCodegenNode = VNodeCall | RenderSlotCall
|
2019-10-06 10:47:20 +08:00
|
|
|
|
|
|
|
export interface IfConditionalExpression extends ConditionalExpression {
|
|
|
|
consequent: BlockCodegenNode
|
|
|
|
alternate: BlockCodegenNode | IfConditionalExpression
|
|
|
|
}
|
|
|
|
|
2020-02-12 07:12:56 +08:00
|
|
|
export interface ForCodegenNode extends VNodeCall {
|
|
|
|
isBlock: true
|
|
|
|
tag: typeof FRAGMENT
|
|
|
|
props: undefined
|
|
|
|
children: ForRenderListExpression
|
|
|
|
patchFlag: string
|
|
|
|
isForBlock: true
|
2019-10-06 10:47:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface ForRenderListExpression extends CallExpression {
|
|
|
|
callee: typeof RENDER_LIST
|
|
|
|
arguments: [ExpressionNode, ForIteratorExpression]
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface ForIteratorExpression extends FunctionExpression {
|
|
|
|
returns: BlockCodegenNode
|
|
|
|
}
|
|
|
|
|
2019-10-02 00:25:13 +08:00
|
|
|
// AST Utilities ---------------------------------------------------------------
|
|
|
|
|
|
|
|
// Some expressions, e.g. sequence and conditional expressions, are never
|
|
|
|
// associated with template nodes, so their source locations are just a stub.
|
|
|
|
// Container types like CompoundExpression also don't need a real location.
|
2019-10-02 03:43:59 +08:00
|
|
|
export const locStub: SourceLocation = {
|
2019-10-02 00:25:13 +08:00
|
|
|
source: '',
|
|
|
|
start: { line: 1, column: 1, offset: 0 },
|
|
|
|
end: { line: 1, column: 1, offset: 0 }
|
|
|
|
}
|
|
|
|
|
2020-02-08 02:56:18 +08:00
|
|
|
export function createRoot(
|
|
|
|
children: TemplateChildNode[],
|
|
|
|
loc = locStub
|
|
|
|
): RootNode {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.ROOT,
|
|
|
|
children,
|
|
|
|
helpers: [],
|
|
|
|
components: [],
|
|
|
|
directives: [],
|
|
|
|
hoists: [],
|
|
|
|
imports: [],
|
|
|
|
cached: 0,
|
|
|
|
temps: 0,
|
|
|
|
codegenNode: undefined,
|
|
|
|
loc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-12 07:12:56 +08:00
|
|
|
export function createVNodeCall(
|
2020-02-12 07:40:21 +08:00
|
|
|
context: TransformContext | null,
|
2020-02-12 07:12:56 +08:00
|
|
|
tag: VNodeCall['tag'],
|
|
|
|
props?: VNodeCall['props'],
|
|
|
|
children?: VNodeCall['children'],
|
|
|
|
patchFlag?: VNodeCall['patchFlag'],
|
|
|
|
dynamicProps?: VNodeCall['dynamicProps'],
|
|
|
|
directives?: VNodeCall['directives'],
|
|
|
|
isBlock: VNodeCall['isBlock'] = false,
|
|
|
|
isForBlock: VNodeCall['isForBlock'] = false,
|
|
|
|
loc = locStub
|
|
|
|
): VNodeCall {
|
2020-02-12 07:40:21 +08:00
|
|
|
if (context) {
|
|
|
|
if (isBlock) {
|
|
|
|
context.helper(OPEN_BLOCK)
|
|
|
|
context.helper(CREATE_BLOCK)
|
|
|
|
} else {
|
|
|
|
context.helper(CREATE_VNODE)
|
|
|
|
}
|
|
|
|
if (directives) {
|
|
|
|
context.helper(WITH_DIRECTIVES)
|
|
|
|
}
|
2020-02-12 07:12:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
type: NodeTypes.VNODE_CALL,
|
|
|
|
tag,
|
|
|
|
props,
|
|
|
|
children,
|
|
|
|
patchFlag,
|
|
|
|
dynamicProps,
|
|
|
|
directives,
|
|
|
|
isBlock,
|
|
|
|
isForBlock,
|
|
|
|
loc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-22 05:42:12 +08:00
|
|
|
export function createArrayExpression(
|
|
|
|
elements: ArrayExpression['elements'],
|
2019-10-02 00:25:13 +08:00
|
|
|
loc: SourceLocation = locStub
|
2019-09-22 05:42:12 +08:00
|
|
|
): ArrayExpression {
|
|
|
|
return {
|
2019-09-23 04:50:57 +08:00
|
|
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
2019-09-22 05:42:12 +08:00
|
|
|
loc,
|
|
|
|
elements
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createObjectExpression(
|
2019-10-02 04:48:20 +08:00
|
|
|
properties: ObjectExpression['properties'],
|
2019-10-02 00:25:13 +08:00
|
|
|
loc: SourceLocation = locStub
|
2019-09-22 05:42:12 +08:00
|
|
|
): ObjectExpression {
|
|
|
|
return {
|
2019-09-23 04:50:57 +08:00
|
|
|
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
2019-09-22 05:42:12 +08:00
|
|
|
loc,
|
|
|
|
properties
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createObjectProperty(
|
2019-10-03 11:10:41 +08:00
|
|
|
key: Property['key'] | string,
|
2019-10-02 04:48:20 +08:00
|
|
|
value: Property['value']
|
2019-09-22 05:42:12 +08:00
|
|
|
): Property {
|
|
|
|
return {
|
2019-09-23 04:50:57 +08:00
|
|
|
type: NodeTypes.JS_PROPERTY,
|
2019-10-02 00:25:13 +08:00
|
|
|
loc: locStub,
|
2019-10-03 11:10:41 +08:00
|
|
|
key: isString(key) ? createSimpleExpression(key, true) : key,
|
2019-09-22 05:42:12 +08:00
|
|
|
value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-27 23:42:02 +08:00
|
|
|
export function createSimpleExpression(
|
2019-10-02 04:48:20 +08:00
|
|
|
content: SimpleExpressionNode['content'],
|
|
|
|
isStatic: SimpleExpressionNode['isStatic'],
|
2019-10-15 23:41:24 +08:00
|
|
|
loc: SourceLocation = locStub,
|
|
|
|
isConstant: boolean = false
|
2019-09-27 23:42:02 +08:00
|
|
|
): SimpleExpressionNode {
|
2019-09-22 05:42:12 +08:00
|
|
|
return {
|
2019-09-27 23:42:02 +08:00
|
|
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
2019-09-22 05:42:12 +08:00
|
|
|
loc,
|
2019-10-15 23:41:24 +08:00
|
|
|
isConstant,
|
2019-09-22 05:42:12 +08:00
|
|
|
content,
|
2019-09-27 23:42:02 +08:00
|
|
|
isStatic
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createInterpolation(
|
2019-10-02 04:48:20 +08:00
|
|
|
content: InterpolationNode['content'] | string,
|
2019-09-27 23:42:02 +08:00
|
|
|
loc: SourceLocation
|
|
|
|
): InterpolationNode {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.INTERPOLATION,
|
|
|
|
loc,
|
|
|
|
content: isString(content)
|
|
|
|
? createSimpleExpression(content, false, loc)
|
|
|
|
: content
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createCompoundExpression(
|
2019-10-10 23:15:24 +08:00
|
|
|
children: CompoundExpressionNode['children'],
|
|
|
|
loc: SourceLocation = locStub
|
2019-09-27 23:42:02 +08:00
|
|
|
): CompoundExpressionNode {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
2019-10-10 23:15:24 +08:00
|
|
|
loc,
|
2019-09-27 23:42:02 +08:00
|
|
|
children
|
2019-09-22 05:42:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-12 07:12:56 +08:00
|
|
|
type InferCodegenNodeType<T> = T extends typeof RENDER_SLOT
|
|
|
|
? RenderSlotCall
|
|
|
|
: CallExpression
|
2019-10-06 10:47:20 +08:00
|
|
|
|
|
|
|
export function createCallExpression<T extends CallExpression['callee']>(
|
|
|
|
callee: T,
|
2019-10-02 00:25:13 +08:00
|
|
|
args: CallExpression['arguments'] = [],
|
|
|
|
loc: SourceLocation = locStub
|
2019-10-06 10:47:20 +08:00
|
|
|
): InferCodegenNodeType<T> {
|
2019-09-22 05:42:12 +08:00
|
|
|
return {
|
2019-09-23 04:50:57 +08:00
|
|
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
2019-09-22 05:42:12 +08:00
|
|
|
loc,
|
|
|
|
callee,
|
|
|
|
arguments: args
|
2019-10-06 10:47:20 +08:00
|
|
|
} as any
|
2019-09-22 05:42:12 +08:00
|
|
|
}
|
2019-09-28 10:25:32 +08:00
|
|
|
|
|
|
|
export function createFunctionExpression(
|
2019-10-02 04:48:20 +08:00
|
|
|
params: FunctionExpression['params'],
|
2020-02-04 07:30:56 +08:00
|
|
|
returns: FunctionExpression['returns'] = undefined,
|
2019-10-02 04:48:20 +08:00
|
|
|
newline: boolean = false,
|
2019-12-17 01:11:51 +08:00
|
|
|
isSlot: boolean = false,
|
2019-10-02 00:25:13 +08:00
|
|
|
loc: SourceLocation = locStub
|
2019-10-02 04:48:20 +08:00
|
|
|
): FunctionExpression {
|
2019-09-28 10:25:32 +08:00
|
|
|
return {
|
2019-10-02 04:48:20 +08:00
|
|
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
2019-09-28 10:25:32 +08:00
|
|
|
params,
|
|
|
|
returns,
|
2019-10-02 04:48:20 +08:00
|
|
|
newline,
|
2019-12-17 01:11:51 +08:00
|
|
|
isSlot,
|
2019-09-28 10:25:32 +08:00
|
|
|
loc
|
|
|
|
}
|
|
|
|
}
|
2019-10-01 21:27:34 +08:00
|
|
|
|
|
|
|
export function createConditionalExpression(
|
2019-10-02 04:48:20 +08:00
|
|
|
test: ConditionalExpression['test'],
|
|
|
|
consequent: ConditionalExpression['consequent'],
|
2020-02-05 05:47:12 +08:00
|
|
|
alternate: ConditionalExpression['alternate'],
|
|
|
|
newline = true
|
2019-10-02 00:25:13 +08:00
|
|
|
): ConditionalExpression {
|
2019-10-01 21:27:34 +08:00
|
|
|
return {
|
|
|
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
|
|
|
test,
|
|
|
|
consequent,
|
|
|
|
alternate,
|
2020-02-05 05:47:12 +08:00
|
|
|
newline,
|
2019-10-01 21:27:34 +08:00
|
|
|
loc: locStub
|
|
|
|
}
|
|
|
|
}
|
2019-10-19 09:51:34 +08:00
|
|
|
|
|
|
|
export function createCacheExpression(
|
|
|
|
index: number,
|
2019-10-24 05:57:40 +08:00
|
|
|
value: JSChildNode,
|
|
|
|
isVNode: boolean = false
|
2019-10-19 09:51:34 +08:00
|
|
|
): CacheExpression {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
|
|
|
index,
|
|
|
|
value,
|
2019-10-24 05:57:40 +08:00
|
|
|
isVNode,
|
2019-10-19 09:51:34 +08:00
|
|
|
loc: locStub
|
|
|
|
}
|
|
|
|
}
|
2020-02-02 13:05:27 +08:00
|
|
|
|
2020-02-03 10:35:28 +08:00
|
|
|
export function createBlockStatement(
|
|
|
|
body: BlockStatement['body']
|
|
|
|
): BlockStatement {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.JS_BLOCK_STATEMENT,
|
|
|
|
body,
|
|
|
|
loc: locStub
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-02 13:05:27 +08:00
|
|
|
export function createTemplateLiteral(
|
|
|
|
elements: TemplateLiteral['elements']
|
|
|
|
): TemplateLiteral {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.JS_TEMPLATE_LITERAL,
|
|
|
|
elements,
|
|
|
|
loc: locStub
|
|
|
|
}
|
|
|
|
}
|
2020-02-03 10:35:28 +08:00
|
|
|
|
|
|
|
export function createIfStatement(
|
|
|
|
test: IfStatement['test'],
|
|
|
|
consequent: IfStatement['consequent'],
|
|
|
|
alternate?: IfStatement['alternate']
|
|
|
|
): IfStatement {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.JS_IF_STATEMENT,
|
|
|
|
test,
|
|
|
|
consequent,
|
|
|
|
alternate,
|
|
|
|
loc: locStub
|
|
|
|
}
|
|
|
|
}
|
2020-02-05 11:49:47 +08:00
|
|
|
|
|
|
|
export function createAssignmentExpression(
|
|
|
|
left: AssignmentExpression['left'],
|
|
|
|
right: AssignmentExpression['right']
|
|
|
|
): AssignmentExpression {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.JS_ASSIGNMENT_EXPRESSION,
|
|
|
|
left,
|
|
|
|
right,
|
|
|
|
loc: locStub
|
|
|
|
}
|
|
|
|
}
|
2020-02-07 14:06:51 +08:00
|
|
|
|
2020-03-17 06:14:49 +08:00
|
|
|
export function createSequenceExpression(
|
|
|
|
expressions: SequenceExpression['expressions']
|
|
|
|
): SequenceExpression {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
|
|
|
|
expressions,
|
|
|
|
loc: locStub
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-07 14:06:51 +08:00
|
|
|
export function createReturnStatement(
|
|
|
|
returns: ReturnStatement['returns']
|
|
|
|
): ReturnStatement {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.JS_RETURN_STATEMENT,
|
|
|
|
returns,
|
|
|
|
loc: locStub
|
|
|
|
}
|
|
|
|
}
|