ast.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. import { isString } from '@vue/shared'
  2. import { ForParseResult } from './transforms/vFor'
  3. import {
  4. RENDER_SLOT,
  5. CREATE_SLOTS,
  6. RENDER_LIST,
  7. OPEN_BLOCK,
  8. CREATE_BLOCK,
  9. FRAGMENT,
  10. CREATE_VNODE,
  11. WITH_DIRECTIVES
  12. } from './runtimeHelpers'
  13. import { PropsExpression } from './transforms/transformElement'
  14. import { ImportItem, TransformContext } from './transform'
  15. // Vue template is a platform-agnostic superset of HTML (syntax only).
  16. // More namespaces like SVG and MathML are declared by platform specific
  17. // compilers.
  18. export type Namespace = number
  19. export const enum Namespaces {
  20. HTML
  21. }
  22. export const enum NodeTypes {
  23. ROOT,
  24. ELEMENT,
  25. TEXT,
  26. COMMENT,
  27. SIMPLE_EXPRESSION,
  28. INTERPOLATION,
  29. ATTRIBUTE,
  30. DIRECTIVE,
  31. // containers
  32. COMPOUND_EXPRESSION,
  33. IF,
  34. IF_BRANCH,
  35. FOR,
  36. TEXT_CALL,
  37. // codegen
  38. VNODE_CALL,
  39. JS_CALL_EXPRESSION,
  40. JS_OBJECT_EXPRESSION,
  41. JS_PROPERTY,
  42. JS_ARRAY_EXPRESSION,
  43. JS_FUNCTION_EXPRESSION,
  44. JS_CONDITIONAL_EXPRESSION,
  45. JS_CACHE_EXPRESSION,
  46. // ssr codegen
  47. JS_BLOCK_STATEMENT,
  48. JS_TEMPLATE_LITERAL,
  49. JS_IF_STATEMENT,
  50. JS_ASSIGNMENT_EXPRESSION,
  51. JS_SEQUENCE_EXPRESSION,
  52. JS_RETURN_STATEMENT
  53. }
  54. export const enum ElementTypes {
  55. ELEMENT,
  56. COMPONENT,
  57. SLOT,
  58. TEMPLATE
  59. }
  60. export interface Node {
  61. type: NodeTypes
  62. loc: SourceLocation
  63. }
  64. // The node's range. The `start` is inclusive and `end` is exclusive.
  65. // [start, end)
  66. export interface SourceLocation {
  67. start: Position
  68. end: Position
  69. source: string
  70. }
  71. export interface Position {
  72. offset: number // from start of file
  73. line: number
  74. column: number
  75. }
  76. export type ParentNode = RootNode | ElementNode | IfBranchNode | ForNode
  77. export type ExpressionNode = SimpleExpressionNode | CompoundExpressionNode
  78. export type TemplateChildNode =
  79. | ElementNode
  80. | InterpolationNode
  81. | CompoundExpressionNode
  82. | TextNode
  83. | CommentNode
  84. | IfNode
  85. | IfBranchNode
  86. | ForNode
  87. | TextCallNode
  88. export interface RootNode extends Node {
  89. type: NodeTypes.ROOT
  90. children: TemplateChildNode[]
  91. helpers: symbol[]
  92. components: string[]
  93. directives: string[]
  94. hoists: (JSChildNode | null)[]
  95. imports: ImportItem[]
  96. cached: number
  97. temps: number
  98. ssrHelpers?: symbol[]
  99. codegenNode?: TemplateChildNode | JSChildNode | BlockStatement | undefined
  100. }
  101. export type ElementNode =
  102. | PlainElementNode
  103. | ComponentNode
  104. | SlotOutletNode
  105. | TemplateNode
  106. export interface BaseElementNode extends Node {
  107. type: NodeTypes.ELEMENT
  108. ns: Namespace
  109. tag: string
  110. tagType: ElementTypes
  111. isSelfClosing: boolean
  112. props: Array<AttributeNode | DirectiveNode>
  113. children: TemplateChildNode[]
  114. }
  115. export interface PlainElementNode extends BaseElementNode {
  116. tagType: ElementTypes.ELEMENT
  117. codegenNode:
  118. | VNodeCall
  119. | SimpleExpressionNode // when hoisted
  120. | CacheExpression // when cached by v-once
  121. | undefined
  122. ssrCodegenNode?: TemplateLiteral
  123. }
  124. export interface ComponentNode extends BaseElementNode {
  125. tagType: ElementTypes.COMPONENT
  126. codegenNode:
  127. | VNodeCall
  128. | CacheExpression // when cached by v-once
  129. | undefined
  130. ssrCodegenNode?: CallExpression
  131. }
  132. export interface SlotOutletNode extends BaseElementNode {
  133. tagType: ElementTypes.SLOT
  134. codegenNode:
  135. | RenderSlotCall
  136. | CacheExpression // when cached by v-once
  137. | undefined
  138. ssrCodegenNode?: CallExpression
  139. }
  140. export interface TemplateNode extends BaseElementNode {
  141. tagType: ElementTypes.TEMPLATE
  142. // TemplateNode is a container type that always gets compiled away
  143. codegenNode: undefined
  144. }
  145. export interface TextNode extends Node {
  146. type: NodeTypes.TEXT
  147. content: string
  148. }
  149. export interface CommentNode extends Node {
  150. type: NodeTypes.COMMENT
  151. content: string
  152. }
  153. export interface AttributeNode extends Node {
  154. type: NodeTypes.ATTRIBUTE
  155. name: string
  156. value: TextNode | undefined
  157. }
  158. export interface DirectiveNode extends Node {
  159. type: NodeTypes.DIRECTIVE
  160. name: string
  161. exp: ExpressionNode | undefined
  162. arg: ExpressionNode | undefined
  163. modifiers: string[]
  164. /**
  165. * optional property to cache the expression parse result for v-for
  166. */
  167. parseResult?: ForParseResult
  168. }
  169. export interface SimpleExpressionNode extends Node {
  170. type: NodeTypes.SIMPLE_EXPRESSION
  171. content: string
  172. isStatic: boolean
  173. isConstant: boolean
  174. /**
  175. * Indicates this is an identifier for a hoist vnode call and points to the
  176. * hoisted node.
  177. */
  178. hoisted?: JSChildNode
  179. /**
  180. * an expression parsed as the params of a function will track
  181. * the identifiers declared inside the function body.
  182. */
  183. identifiers?: string[]
  184. /**
  185. * some expressions (e.g. transformAssetUrls import identifiers) are constant,
  186. * but cannot be stringified because they must be first evaluated at runtime.
  187. */
  188. isRuntimeConstant?: boolean
  189. }
  190. export interface InterpolationNode extends Node {
  191. type: NodeTypes.INTERPOLATION
  192. content: ExpressionNode
  193. }
  194. export interface CompoundExpressionNode extends Node {
  195. type: NodeTypes.COMPOUND_EXPRESSION
  196. children: (
  197. | SimpleExpressionNode
  198. | CompoundExpressionNode
  199. | InterpolationNode
  200. | TextNode
  201. | string
  202. | symbol)[]
  203. /**
  204. * an expression parsed as the params of a function will track
  205. * the identifiers declared inside the function body.
  206. */
  207. identifiers?: string[]
  208. }
  209. export interface IfNode extends Node {
  210. type: NodeTypes.IF
  211. branches: IfBranchNode[]
  212. codegenNode?: IfConditionalExpression
  213. }
  214. export interface IfBranchNode extends Node {
  215. type: NodeTypes.IF_BRANCH
  216. condition: ExpressionNode | undefined // else
  217. children: TemplateChildNode[]
  218. }
  219. export interface ForNode extends Node {
  220. type: NodeTypes.FOR
  221. source: ExpressionNode
  222. valueAlias: ExpressionNode | undefined
  223. keyAlias: ExpressionNode | undefined
  224. objectIndexAlias: ExpressionNode | undefined
  225. parseResult: ForParseResult
  226. children: TemplateChildNode[]
  227. codegenNode?: ForCodegenNode
  228. }
  229. export interface TextCallNode extends Node {
  230. type: NodeTypes.TEXT_CALL
  231. content: TextNode | InterpolationNode | CompoundExpressionNode
  232. codegenNode: CallExpression | SimpleExpressionNode // when hoisted
  233. }
  234. export type TemplateTextChildNode =
  235. | TextNode
  236. | InterpolationNode
  237. | CompoundExpressionNode
  238. export interface VNodeCall extends Node {
  239. type: NodeTypes.VNODE_CALL
  240. tag: string | symbol | CallExpression
  241. props: PropsExpression | undefined
  242. children:
  243. | TemplateChildNode[] // multiple children
  244. | TemplateTextChildNode // single text child
  245. | SlotsExpression // component slots
  246. | ForRenderListExpression // v-for fragment call
  247. | undefined
  248. patchFlag: string | undefined
  249. dynamicProps: string | undefined
  250. directives: DirectiveArguments | undefined
  251. isBlock: boolean
  252. isForBlock: boolean
  253. }
  254. // JS Node Types ---------------------------------------------------------------
  255. // We also include a number of JavaScript AST nodes for code generation.
  256. // The AST is an intentionally minimal subset just to meet the exact needs of
  257. // Vue render function generation.
  258. export type JSChildNode =
  259. | VNodeCall
  260. | CallExpression
  261. | ObjectExpression
  262. | ArrayExpression
  263. | ExpressionNode
  264. | FunctionExpression
  265. | ConditionalExpression
  266. | CacheExpression
  267. | AssignmentExpression
  268. | SequenceExpression
  269. export interface CallExpression extends Node {
  270. type: NodeTypes.JS_CALL_EXPRESSION
  271. callee: string | symbol
  272. arguments: (
  273. | string
  274. | symbol
  275. | JSChildNode
  276. | SSRCodegenNode
  277. | TemplateChildNode
  278. | TemplateChildNode[])[]
  279. }
  280. export interface ObjectExpression extends Node {
  281. type: NodeTypes.JS_OBJECT_EXPRESSION
  282. properties: Array<Property>
  283. }
  284. export interface Property extends Node {
  285. type: NodeTypes.JS_PROPERTY
  286. key: ExpressionNode
  287. value: JSChildNode
  288. }
  289. export interface ArrayExpression extends Node {
  290. type: NodeTypes.JS_ARRAY_EXPRESSION
  291. elements: Array<string | JSChildNode>
  292. }
  293. export interface FunctionExpression extends Node {
  294. type: NodeTypes.JS_FUNCTION_EXPRESSION
  295. params: ExpressionNode | string | (ExpressionNode | string)[] | undefined
  296. returns?: TemplateChildNode | TemplateChildNode[] | JSChildNode
  297. body?: BlockStatement | IfStatement
  298. newline: boolean
  299. /**
  300. * This flag is for codegen to determine whether it needs to generate the
  301. * withScopeId() wrapper
  302. */
  303. isSlot: boolean
  304. }
  305. export interface ConditionalExpression extends Node {
  306. type: NodeTypes.JS_CONDITIONAL_EXPRESSION
  307. test: JSChildNode
  308. consequent: JSChildNode
  309. alternate: JSChildNode
  310. newline: boolean
  311. }
  312. export interface CacheExpression extends Node {
  313. type: NodeTypes.JS_CACHE_EXPRESSION
  314. index: number
  315. value: JSChildNode
  316. isVNode: boolean
  317. }
  318. // SSR-specific Node Types -----------------------------------------------------
  319. export type SSRCodegenNode =
  320. | BlockStatement
  321. | TemplateLiteral
  322. | IfStatement
  323. | AssignmentExpression
  324. | ReturnStatement
  325. | SequenceExpression
  326. export interface BlockStatement extends Node {
  327. type: NodeTypes.JS_BLOCK_STATEMENT
  328. body: (JSChildNode | IfStatement)[]
  329. }
  330. export interface TemplateLiteral extends Node {
  331. type: NodeTypes.JS_TEMPLATE_LITERAL
  332. elements: (string | JSChildNode)[]
  333. }
  334. export interface IfStatement extends Node {
  335. type: NodeTypes.JS_IF_STATEMENT
  336. test: ExpressionNode
  337. consequent: BlockStatement
  338. alternate: IfStatement | BlockStatement | ReturnStatement | undefined
  339. }
  340. export interface AssignmentExpression extends Node {
  341. type: NodeTypes.JS_ASSIGNMENT_EXPRESSION
  342. left: SimpleExpressionNode
  343. right: JSChildNode
  344. }
  345. export interface SequenceExpression extends Node {
  346. type: NodeTypes.JS_SEQUENCE_EXPRESSION
  347. expressions: JSChildNode[]
  348. }
  349. export interface ReturnStatement extends Node {
  350. type: NodeTypes.JS_RETURN_STATEMENT
  351. returns: TemplateChildNode | TemplateChildNode[] | JSChildNode
  352. }
  353. // Codegen Node Types ----------------------------------------------------------
  354. export interface DirectiveArguments extends ArrayExpression {
  355. elements: DirectiveArgumentNode[]
  356. }
  357. export interface DirectiveArgumentNode extends ArrayExpression {
  358. elements: // dir, exp, arg, modifiers
  359. | [string]
  360. | [string, ExpressionNode]
  361. | [string, ExpressionNode, ExpressionNode]
  362. | [string, ExpressionNode, ExpressionNode, ObjectExpression]
  363. }
  364. // renderSlot(...)
  365. export interface RenderSlotCall extends CallExpression {
  366. callee: typeof RENDER_SLOT
  367. arguments: // $slots, name, props, fallback
  368. | [string, string | ExpressionNode]
  369. | [string, string | ExpressionNode, PropsExpression]
  370. | [
  371. string,
  372. string | ExpressionNode,
  373. PropsExpression | '{}',
  374. TemplateChildNode[]
  375. ]
  376. }
  377. export type SlotsExpression = SlotsObjectExpression | DynamicSlotsExpression
  378. // { foo: () => [...] }
  379. export interface SlotsObjectExpression extends ObjectExpression {
  380. properties: SlotsObjectProperty[]
  381. }
  382. export interface SlotsObjectProperty extends Property {
  383. value: SlotFunctionExpression
  384. }
  385. export interface SlotFunctionExpression extends FunctionExpression {
  386. returns: TemplateChildNode[]
  387. }
  388. // createSlots({ ... }, [
  389. // foo ? () => [] : undefined,
  390. // renderList(list, i => () => [i])
  391. // ])
  392. export interface DynamicSlotsExpression extends CallExpression {
  393. callee: typeof CREATE_SLOTS
  394. arguments: [SlotsObjectExpression, DynamicSlotEntries]
  395. }
  396. export interface DynamicSlotEntries extends ArrayExpression {
  397. elements: (ConditionalDynamicSlotNode | ListDynamicSlotNode)[]
  398. }
  399. export interface ConditionalDynamicSlotNode extends ConditionalExpression {
  400. consequent: DynamicSlotNode
  401. alternate: DynamicSlotNode | SimpleExpressionNode
  402. }
  403. export interface ListDynamicSlotNode extends CallExpression {
  404. callee: typeof RENDER_LIST
  405. arguments: [ExpressionNode, ListDynamicSlotIterator]
  406. }
  407. export interface ListDynamicSlotIterator extends FunctionExpression {
  408. returns: DynamicSlotNode
  409. }
  410. export interface DynamicSlotNode extends ObjectExpression {
  411. properties: [Property, DynamicSlotFnProperty]
  412. }
  413. export interface DynamicSlotFnProperty extends Property {
  414. value: SlotFunctionExpression
  415. }
  416. export type BlockCodegenNode = VNodeCall | RenderSlotCall
  417. export interface IfConditionalExpression extends ConditionalExpression {
  418. consequent: BlockCodegenNode
  419. alternate: BlockCodegenNode | IfConditionalExpression
  420. }
  421. export interface ForCodegenNode extends VNodeCall {
  422. isBlock: true
  423. tag: typeof FRAGMENT
  424. props: undefined
  425. children: ForRenderListExpression
  426. patchFlag: string
  427. isForBlock: true
  428. }
  429. export interface ForRenderListExpression extends CallExpression {
  430. callee: typeof RENDER_LIST
  431. arguments: [ExpressionNode, ForIteratorExpression]
  432. }
  433. export interface ForIteratorExpression extends FunctionExpression {
  434. returns: BlockCodegenNode
  435. }
  436. // AST Utilities ---------------------------------------------------------------
  437. // Some expressions, e.g. sequence and conditional expressions, are never
  438. // associated with template nodes, so their source locations are just a stub.
  439. // Container types like CompoundExpression also don't need a real location.
  440. export const locStub: SourceLocation = {
  441. source: '',
  442. start: { line: 1, column: 1, offset: 0 },
  443. end: { line: 1, column: 1, offset: 0 }
  444. }
  445. export function createRoot(
  446. children: TemplateChildNode[],
  447. loc = locStub
  448. ): RootNode {
  449. return {
  450. type: NodeTypes.ROOT,
  451. children,
  452. helpers: [],
  453. components: [],
  454. directives: [],
  455. hoists: [],
  456. imports: [],
  457. cached: 0,
  458. temps: 0,
  459. codegenNode: undefined,
  460. loc
  461. }
  462. }
  463. export function createVNodeCall(
  464. context: TransformContext | null,
  465. tag: VNodeCall['tag'],
  466. props?: VNodeCall['props'],
  467. children?: VNodeCall['children'],
  468. patchFlag?: VNodeCall['patchFlag'],
  469. dynamicProps?: VNodeCall['dynamicProps'],
  470. directives?: VNodeCall['directives'],
  471. isBlock: VNodeCall['isBlock'] = false,
  472. isForBlock: VNodeCall['isForBlock'] = false,
  473. loc = locStub
  474. ): VNodeCall {
  475. if (context) {
  476. if (isBlock) {
  477. context.helper(OPEN_BLOCK)
  478. context.helper(CREATE_BLOCK)
  479. } else {
  480. context.helper(CREATE_VNODE)
  481. }
  482. if (directives) {
  483. context.helper(WITH_DIRECTIVES)
  484. }
  485. }
  486. return {
  487. type: NodeTypes.VNODE_CALL,
  488. tag,
  489. props,
  490. children,
  491. patchFlag,
  492. dynamicProps,
  493. directives,
  494. isBlock,
  495. isForBlock,
  496. loc
  497. }
  498. }
  499. export function createArrayExpression(
  500. elements: ArrayExpression['elements'],
  501. loc: SourceLocation = locStub
  502. ): ArrayExpression {
  503. return {
  504. type: NodeTypes.JS_ARRAY_EXPRESSION,
  505. loc,
  506. elements
  507. }
  508. }
  509. export function createObjectExpression(
  510. properties: ObjectExpression['properties'],
  511. loc: SourceLocation = locStub
  512. ): ObjectExpression {
  513. return {
  514. type: NodeTypes.JS_OBJECT_EXPRESSION,
  515. loc,
  516. properties
  517. }
  518. }
  519. export function createObjectProperty(
  520. key: Property['key'] | string,
  521. value: Property['value']
  522. ): Property {
  523. return {
  524. type: NodeTypes.JS_PROPERTY,
  525. loc: locStub,
  526. key: isString(key) ? createSimpleExpression(key, true) : key,
  527. value
  528. }
  529. }
  530. export function createSimpleExpression(
  531. content: SimpleExpressionNode['content'],
  532. isStatic: SimpleExpressionNode['isStatic'],
  533. loc: SourceLocation = locStub,
  534. isConstant: boolean = false
  535. ): SimpleExpressionNode {
  536. return {
  537. type: NodeTypes.SIMPLE_EXPRESSION,
  538. loc,
  539. isConstant,
  540. content,
  541. isStatic
  542. }
  543. }
  544. export function createInterpolation(
  545. content: InterpolationNode['content'] | string,
  546. loc: SourceLocation
  547. ): InterpolationNode {
  548. return {
  549. type: NodeTypes.INTERPOLATION,
  550. loc,
  551. content: isString(content)
  552. ? createSimpleExpression(content, false, loc)
  553. : content
  554. }
  555. }
  556. export function createCompoundExpression(
  557. children: CompoundExpressionNode['children'],
  558. loc: SourceLocation = locStub
  559. ): CompoundExpressionNode {
  560. return {
  561. type: NodeTypes.COMPOUND_EXPRESSION,
  562. loc,
  563. children
  564. }
  565. }
  566. type InferCodegenNodeType<T> = T extends typeof RENDER_SLOT
  567. ? RenderSlotCall
  568. : CallExpression
  569. export function createCallExpression<T extends CallExpression['callee']>(
  570. callee: T,
  571. args: CallExpression['arguments'] = [],
  572. loc: SourceLocation = locStub
  573. ): InferCodegenNodeType<T> {
  574. return {
  575. type: NodeTypes.JS_CALL_EXPRESSION,
  576. loc,
  577. callee,
  578. arguments: args
  579. } as any
  580. }
  581. export function createFunctionExpression(
  582. params: FunctionExpression['params'],
  583. returns: FunctionExpression['returns'] = undefined,
  584. newline: boolean = false,
  585. isSlot: boolean = false,
  586. loc: SourceLocation = locStub
  587. ): FunctionExpression {
  588. return {
  589. type: NodeTypes.JS_FUNCTION_EXPRESSION,
  590. params,
  591. returns,
  592. newline,
  593. isSlot,
  594. loc
  595. }
  596. }
  597. export function createConditionalExpression(
  598. test: ConditionalExpression['test'],
  599. consequent: ConditionalExpression['consequent'],
  600. alternate: ConditionalExpression['alternate'],
  601. newline = true
  602. ): ConditionalExpression {
  603. return {
  604. type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
  605. test,
  606. consequent,
  607. alternate,
  608. newline,
  609. loc: locStub
  610. }
  611. }
  612. export function createCacheExpression(
  613. index: number,
  614. value: JSChildNode,
  615. isVNode: boolean = false
  616. ): CacheExpression {
  617. return {
  618. type: NodeTypes.JS_CACHE_EXPRESSION,
  619. index,
  620. value,
  621. isVNode,
  622. loc: locStub
  623. }
  624. }
  625. export function createBlockStatement(
  626. body: BlockStatement['body']
  627. ): BlockStatement {
  628. return {
  629. type: NodeTypes.JS_BLOCK_STATEMENT,
  630. body,
  631. loc: locStub
  632. }
  633. }
  634. export function createTemplateLiteral(
  635. elements: TemplateLiteral['elements']
  636. ): TemplateLiteral {
  637. return {
  638. type: NodeTypes.JS_TEMPLATE_LITERAL,
  639. elements,
  640. loc: locStub
  641. }
  642. }
  643. export function createIfStatement(
  644. test: IfStatement['test'],
  645. consequent: IfStatement['consequent'],
  646. alternate?: IfStatement['alternate']
  647. ): IfStatement {
  648. return {
  649. type: NodeTypes.JS_IF_STATEMENT,
  650. test,
  651. consequent,
  652. alternate,
  653. loc: locStub
  654. }
  655. }
  656. export function createAssignmentExpression(
  657. left: AssignmentExpression['left'],
  658. right: AssignmentExpression['right']
  659. ): AssignmentExpression {
  660. return {
  661. type: NodeTypes.JS_ASSIGNMENT_EXPRESSION,
  662. left,
  663. right,
  664. loc: locStub
  665. }
  666. }
  667. export function createSequenceExpression(
  668. expressions: SequenceExpression['expressions']
  669. ): SequenceExpression {
  670. return {
  671. type: NodeTypes.JS_SEQUENCE_EXPRESSION,
  672. expressions,
  673. loc: locStub
  674. }
  675. }
  676. export function createReturnStatement(
  677. returns: ReturnStatement['returns']
  678. ): ReturnStatement {
  679. return {
  680. type: NodeTypes.JS_RETURN_STATEMENT,
  681. returns,
  682. loc: locStub
  683. }
  684. }