From 82bd9eb1db1cfce0e1e8b632ace743bf82695cc9 Mon Sep 17 00:00:00 2001 From: Evan You Date: Sat, 5 Oct 2019 22:47:20 -0400 Subject: [PATCH] refactor(compiler): refine codegen node types --- .../__snapshots__/codegen.spec.ts.snap | 19 +- .../__snapshots__/parse.spec.ts.snap | 490 +++++++++++------- .../compiler-core/__tests__/codegen.spec.ts | 45 +- packages/compiler-core/__tests__/testUtils.ts | 6 +- packages/compiler-core/src/ast.ts | 266 +++++++++- packages/compiler-core/src/parse.ts | 5 +- .../src/transforms/hoistStatic.ts | 27 +- packages/compiler-core/src/transforms/vFor.ts | 9 +- packages/compiler-core/src/transforms/vIf.ts | 49 +- packages/compiler-core/src/utils.ts | 8 +- 10 files changed, 636 insertions(+), 288 deletions(-) diff --git a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap index 4e70c591..9f8a5b6f 100644 --- a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap @@ -1,5 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`compiler: codegen ArrayExpression 1`] = ` +" +return function render() { + with (this) { + return [ + foo, + bar(baz) + ] + } +}" +`; + exports[`compiler: codegen ConditionalExpression 1`] = ` " return function render() { @@ -13,7 +25,7 @@ return function render() { }" `; -exports[`compiler: codegen Element (callExpression + objectExpression + arrayExpression) 1`] = ` +exports[`compiler: codegen Element (callExpression + objectExpression + TemplateChildNode[]) 1`] = ` " return function render() { with (this) { @@ -23,10 +35,7 @@ return function render() { [foo + bar]: bar }, [ _createVNode(\\"p\\", { \\"some-key\\": \\"foo\\" }) - ], [ - foo, - _createVNode(\\"p\\") - ]) + ], 16) } }" `; diff --git a/packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap index 307925a3..2b733c3f 100644 --- a/packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap @@ -46,8 +46,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 27, @@ -61,7 +63,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -112,8 +113,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 28, @@ -127,7 +130,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -178,8 +180,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 29, @@ -193,7 +197,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -262,8 +265,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 35, @@ -277,7 +282,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -346,8 +350,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 34, @@ -361,7 +367,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -430,8 +435,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 36, @@ -445,7 +452,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -514,8 +520,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 35, @@ -529,7 +537,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -581,8 +588,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 27, @@ -596,7 +605,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -648,8 +656,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 26, @@ -663,7 +673,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -715,8 +724,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 28, @@ -730,7 +741,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -782,8 +792,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 27, @@ -797,7 +809,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -848,8 +859,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 39, @@ -863,7 +876,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -939,8 +951,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 50, @@ -954,7 +968,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1006,8 +1019,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 32, @@ -1021,7 +1036,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1073,8 +1087,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 29, @@ -1088,7 +1104,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1140,8 +1155,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 28, @@ -1155,7 +1172,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1283,8 +1299,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 45, @@ -1298,7 +1316,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1355,8 +1372,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 39, @@ -1370,7 +1389,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1427,8 +1445,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 34, @@ -1442,7 +1462,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1494,8 +1513,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 12, @@ -1509,7 +1530,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1561,8 +1581,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 13, @@ -1576,7 +1598,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1633,8 +1654,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 25, @@ -1648,7 +1671,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1724,8 +1746,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 30, @@ -1739,7 +1763,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1790,8 +1813,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 13, @@ -1805,7 +1830,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1856,8 +1880,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 14, @@ -1871,7 +1897,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1922,8 +1947,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 15, @@ -1937,7 +1964,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -1988,8 +2014,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 22, @@ -2003,7 +2031,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2054,8 +2081,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 16, @@ -2069,7 +2098,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2121,8 +2149,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 33, @@ -2136,7 +2166,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2188,8 +2217,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 29, @@ -2203,7 +2234,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2260,8 +2290,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 16, @@ -2275,7 +2307,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2332,8 +2363,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 15, @@ -2347,7 +2380,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2423,8 +2455,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 19, @@ -2438,7 +2472,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2514,8 +2547,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 20, @@ -2529,7 +2564,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2605,8 +2639,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 18, @@ -2620,7 +2656,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2713,8 +2748,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 23, @@ -2728,7 +2765,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2821,8 +2857,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 24, @@ -2836,7 +2874,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -2929,8 +2966,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 25, @@ -2944,7 +2983,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3037,8 +3075,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 23, @@ -3052,7 +3092,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3145,8 +3184,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 24, @@ -3160,7 +3201,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3253,8 +3293,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 25, @@ -3268,7 +3310,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3361,8 +3402,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 24, @@ -3376,7 +3419,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3469,8 +3511,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 22, @@ -3484,7 +3528,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3535,8 +3578,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 37, @@ -3550,7 +3595,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3577,8 +3621,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 16, @@ -3592,7 +3638,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3643,8 +3688,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 25, @@ -3658,7 +3705,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3709,8 +3755,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 26, @@ -3724,7 +3772,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3775,8 +3822,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 41, @@ -3790,7 +3839,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3841,8 +3889,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 26, @@ -3856,7 +3906,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3908,8 +3957,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 25, @@ -3923,7 +3974,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -3991,8 +4041,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 31, @@ -4006,7 +4058,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4058,8 +4109,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 27, @@ -4073,7 +4126,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4142,8 +4194,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 28, @@ -4157,7 +4211,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4250,8 +4303,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 39, @@ -4265,7 +4320,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4341,8 +4395,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 38, @@ -4356,7 +4412,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4432,8 +4487,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 37, @@ -4447,7 +4504,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4480,8 +4536,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 25, @@ -4495,7 +4553,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4547,8 +4604,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 26, @@ -4562,7 +4621,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4614,8 +4672,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 27, @@ -4629,7 +4689,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4681,8 +4740,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 26, @@ -4696,7 +4757,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4826,8 +4886,10 @@ class=\\"bar\\">", }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 30, @@ -4842,7 +4904,6 @@ class=\\"bar\\">", "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -4970,8 +5031,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 53, @@ -4985,7 +5048,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5036,8 +5098,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 20, @@ -5051,7 +5115,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5102,8 +5165,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 32, @@ -5117,7 +5182,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5168,8 +5232,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 40, @@ -5183,7 +5249,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5234,8 +5299,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 35, @@ -5249,7 +5316,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5301,8 +5367,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 31, @@ -5316,7 +5384,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5368,8 +5435,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 30, @@ -5383,7 +5452,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5435,8 +5503,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 29, @@ -5450,7 +5520,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5502,8 +5571,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 30, @@ -5517,7 +5588,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5610,8 +5680,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 41, @@ -5625,7 +5697,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5718,8 +5789,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 41, @@ -5733,7 +5806,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5826,8 +5898,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 41, @@ -5841,7 +5915,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -5934,8 +6007,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 42, @@ -5949,7 +6024,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6042,8 +6116,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 42, @@ -6057,7 +6133,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6150,8 +6225,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 45, @@ -6165,7 +6242,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6258,8 +6334,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 45, @@ -6273,7 +6351,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6366,8 +6443,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 42, @@ -6381,7 +6460,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6457,8 +6535,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 35, @@ -6472,7 +6552,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6565,8 +6644,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 42, @@ -6580,7 +6661,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6631,8 +6711,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 29, @@ -6646,7 +6728,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6740,8 +6821,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 37, @@ -6755,7 +6838,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6807,8 +6889,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 31, @@ -6822,7 +6906,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6874,8 +6957,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 30, @@ -6889,7 +6974,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6940,8 +7024,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 25, @@ -6955,7 +7041,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -6988,8 +7073,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 34, @@ -7003,7 +7090,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7036,8 +7122,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 28, @@ -7051,7 +7139,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7119,8 +7206,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 34, @@ -7134,7 +7223,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7186,8 +7274,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 28, @@ -7201,7 +7291,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7290,8 +7379,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 25, @@ -7305,7 +7396,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7362,8 +7452,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 16, @@ -7377,7 +7469,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7434,8 +7525,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 27, @@ -7449,7 +7542,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7477,8 +7569,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 3, @@ -7492,7 +7586,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7520,8 +7613,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 7, @@ -7535,7 +7630,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7579,8 +7673,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 5, @@ -7594,7 +7690,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7654,8 +7749,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 8, @@ -7672,7 +7769,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -7838,8 +7934,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 37, @@ -7854,7 +7952,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; @@ -8041,8 +8138,10 @@ Object { }, ], "codegenNode": undefined, + "components": Array [], + "directives": Array [], + "helpers": Array [], "hoists": Array [], - "imports": Array [], "loc": Object { "end": Object { "column": 7, @@ -8059,7 +8158,6 @@ Object { "offset": 0, }, }, - "statements": Array [], "type": 0, } `; diff --git a/packages/compiler-core/__tests__/codegen.spec.ts b/packages/compiler-core/__tests__/codegen.spec.ts index d881bea4..1b15b272 100644 --- a/packages/compiler-core/__tests__/codegen.spec.ts +++ b/packages/compiler-core/__tests__/codegen.spec.ts @@ -11,7 +11,9 @@ import { createInterpolation, createSequenceExpression, createCallExpression, - createConditionalExpression + createConditionalExpression, + IfCodegenNode, + ForCodegenNode } from '../src' import { CREATE_VNODE, @@ -22,6 +24,7 @@ import { RESOLVE_COMPONENT } from '../src/runtimeHelpers' import { createElementWithCodegen } from './testUtils' +import { PatchFlags } from 'vue' function createRoot(options: Partial = {}): RootNode { return { @@ -205,7 +208,7 @@ describe('compiler: codegen', () => { codegenNode: createSequenceExpression([ createSimpleExpression('foo', false), createSimpleExpression('bar', false) - ]) + ]) as IfCodegenNode } }) ) @@ -227,7 +230,7 @@ describe('compiler: codegen', () => { codegenNode: createSequenceExpression([ createSimpleExpression('foo', false), createSimpleExpression('bar', false) - ]) + ]) as ForCodegenNode } }) ) @@ -235,7 +238,7 @@ describe('compiler: codegen', () => { expect(code).toMatchSnapshot() }) - test('Element (callExpression + objectExpression + arrayExpression)', () => { + test('Element (callExpression + objectExpression + TemplateChildNode[])', () => { const { code } = generate( createRoot({ codegenNode: createElementWithCodegen([ @@ -283,19 +286,8 @@ describe('compiler: codegen', () => { ) ]) ], - // ArrayExpression - createArrayExpression( - [ - 'foo', - { - type: NodeTypes.JS_CALL_EXPRESSION, - loc: locStub, - callee: CREATE_VNODE, - arguments: [`"p"`] - } - ], - locStub - ) + // flag + PatchFlags.FULL_PROPS + '' ]) }) ) @@ -306,10 +298,23 @@ describe('compiler: codegen', () => { [foo + bar]: bar }, [ _${helperNameMap[CREATE_VNODE]}("p", { "some-key": "foo" }) - ], [ + ], ${PatchFlags.FULL_PROPS})`) + expect(code).toMatchSnapshot() + }) + + test('ArrayExpression', () => { + const { code } = generate( + createRoot({ + codegenNode: createArrayExpression([ + createSimpleExpression(`foo`, false), + createCallExpression(`bar`, [`baz`]) + ]) + }) + ) + expect(code).toMatch(`return [ foo, - _${helperNameMap[CREATE_VNODE]}("p") - ])`) + bar(baz) + ]`) expect(code).toMatchSnapshot() }) diff --git a/packages/compiler-core/__tests__/testUtils.ts b/packages/compiler-core/__tests__/testUtils.ts index 1ad68200..16bd554e 100644 --- a/packages/compiler-core/__tests__/testUtils.ts +++ b/packages/compiler-core/__tests__/testUtils.ts @@ -1,10 +1,10 @@ import { NodeTypes, - CallExpression, ElementNode, locStub, Namespaces, - ElementTypes + ElementTypes, + ElementCodegenNode } from '../src' import { CREATE_VNODE } from '../src/runtimeHelpers' import { isString } from '@vue/shared' @@ -39,7 +39,7 @@ export function createObjectMatcher(obj: any) { } export function createElementWithCodegen( - args: CallExpression['arguments'] + args: ElementCodegenNode['arguments'] ): ElementNode { return { type: NodeTypes.ELEMENT, diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts index 300a8f21..5fe82eae 100644 --- a/packages/compiler-core/src/ast.ts +++ b/packages/compiler-core/src/ast.ts @@ -1,6 +1,17 @@ import { isString } from '@vue/shared' import { ForParseResult } from './transforms/vFor' -import { CREATE_VNODE, RuntimeHelper } from './runtimeHelpers' +import { + CREATE_VNODE, + RuntimeHelper, + APPLY_DIRECTIVES, + RENDER_SLOT, + CREATE_SLOTS, + RENDER_LIST, + OPEN_BLOCK, + CREATE_BLOCK, + FRAGMENT +} from './runtimeHelpers' +import { PropsExpression } from './transforms/transformElement' // Vue template is a platform-agnostic superset of HTML (syntax only). // More namespaces like SVG and MathML are declared by platform specific @@ -84,7 +95,13 @@ export interface RootNode extends Node { codegenNode: TemplateChildNode | JSChildNode | undefined } -export interface ElementNode extends Node { +export type ElementNode = + | PlainElementNode + | ComponentNode + | SlotOutletNode + | TemplateNode + +export interface BaseElementNode extends Node { type: NodeTypes.ELEMENT ns: Namespace tag: string @@ -95,29 +112,32 @@ export interface ElementNode extends Node { codegenNode: CallExpression | SimpleExpressionNode | undefined } -export interface PlainElementNode extends ElementNode { +export interface PlainElementNode extends BaseElementNode { tagType: ElementTypes.ELEMENT - codegenNode: VNodeCodegenNode | VNodeWithDirectiveCodegenNode + codegenNode: + | ElementCodegenNode + | CodegenNodeWithDirective + | undefined + // | SimpleExpressionNode (only when hoisted) } -export interface ComponentNode extends ElementNode { +export interface ComponentNode extends BaseElementNode { tagType: ElementTypes.COMPONENT - codegenNode: VNodeCodegenNode | VNodeWithDirectiveCodegenNode + codegenNode: + | ComponentCodegenNode + | CodegenNodeWithDirective + | undefined } -export interface SlotOutletNode extends ElementNode { +export interface SlotOutletNode extends BaseElementNode { tagType: ElementTypes.SLOT - codegenNode: SlotOutletCodegenNode + codegenNode: SlotOutletCodegenNode | undefined } -export interface VNodeCodegenNode extends CallExpression { - callee: typeof CREATE_VNODE +export interface TemplateNode extends BaseElementNode { + tagType: ElementTypes.TEMPLATE } -export interface VNodeWithDirectiveCodegenNode extends CallExpression {} - -export interface SlotOutletCodegenNode extends CallExpression {} - export interface TextNode extends Node { type: NodeTypes.TEXT content: string @@ -179,8 +199,6 @@ export interface IfNode extends Node { codegenNode: IfCodegenNode } -export interface IfCodegenNode extends SequenceExpression {} - export interface IfBranchNode extends Node { type: NodeTypes.IF_BRANCH condition: ExpressionNode | undefined // else @@ -197,8 +215,6 @@ export interface ForNode extends Node { codegenNode: ForCodegenNode } -export interface ForCodegenNode extends SequenceExpression {} - // We also include a number of JavaScript AST nodes for code generation. // The AST is an intentionally minimal subset just to meet the exact needs of // Vue render function generation. @@ -257,6 +273,204 @@ export interface ConditionalExpression extends Node { alternate: JSChildNode } +// Codegen Node Types ---------------------------------------------------------- + +// createVNode(...) +export interface ElementCodegenNode extends CallExpression { + callee: typeof CREATE_VNODE + arguments: // tag, props, children, patchFlag, dynamicProps + + | [string | RuntimeHelper] + | [string | RuntimeHelper, PropsExpression] + | [string | RuntimeHelper, 'null' | PropsExpression, TemplateChildNode[]] + | [ + string | RuntimeHelper, + 'null' | PropsExpression, + 'null' | TemplateChildNode[], + string + ] + | [ + string | RuntimeHelper, + 'null' | PropsExpression, + 'null' | TemplateChildNode[], + string, + string + ] +} + +export type ElementCodegenNodeWithDirective = CodegenNodeWithDirective< + ElementCodegenNode +> + +// createVNode(...) +export interface ComponentCodegenNode extends CallExpression { + callee: typeof CREATE_VNODE + arguments: // Comp, props, slots, patchFlag, dynamicProps + + | [string | RuntimeHelper] + | [string | RuntimeHelper, PropsExpression] + | [string | RuntimeHelper, 'null' | PropsExpression, SlotsExpression] + | [ + string | RuntimeHelper, + 'null' | PropsExpression, + 'null' | SlotsExpression, + string + ] + | [ + string | RuntimeHelper, + 'null' | PropsExpression, + 'null' | SlotsExpression, + string, + string + ] +} + +export type CompoenntCodegenNodeWithDirective = CodegenNodeWithDirective< + ComponentCodegenNode +> + +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 { + elements: (ConditionalDynamicSlotNode | ListDyanmicSlotNode)[] +} + +export interface ConditionalDynamicSlotNode extends ConditionalExpression { + consequent: DynamicSlotNode + alternate: DynamicSlotNode | SimpleExpressionNode +} + +export interface ListDyanmicSlotNode extends CallExpression { + callee: typeof RENDER_LIST + arguments: [ExpressionNode, ListDyanmicSlotIterator] +} + +export interface ListDyanmicSlotIterator extends FunctionExpression { + returns: DynamicSlotNode +} + +export interface DynamicSlotNode extends ObjectExpression { + properties: [Property, DynamicSlotFnProperty] +} + +export interface DynamicSlotFnProperty extends Property { + value: SlotFunctionExpression +} + +// applyDirectives(createVNode(...), [ +// [_directive_foo, someValue], +// [_directive_bar, someValue, "arg", { mod: true }] +// ]) +export interface CodegenNodeWithDirective + extends CallExpression { + callee: typeof APPLY_DIRECTIVES + arguments: [T, DirectiveArguments] +} + +export interface DirectiveArguments extends ArrayExpression { + elements: DirectiveArgumentNode[] +} + +export interface DirectiveArgumentNode extends ArrayExpression { + elements: // dir, exp, arg, modifiers + + | [string] + | [string, ExpressionNode] + | [string, ExpressionNode, ExpressionNode] + | [string, ExpressionNode, ExpressionNode, ObjectExpression] +} + +// renderSlot(...) +export interface SlotOutletCodegenNode extends CallExpression { + callee: typeof RENDER_SLOT + arguments: // $slots, name, props, fallback + + | [string, string | ExpressionNode] + | [string, string | ExpressionNode, PropsExpression] + | [ + string, + string | ExpressionNode, + PropsExpression | '{}', + TemplateChildNode[] + ] +} + +export interface IfCodegenNode extends SequenceExpression { + expressions: [OpenBlockExpression, IfConditionalExpression] +} + +export interface IfConditionalExpression extends ConditionalExpression { + consequent: BlockCodegenNode + alternate: BlockCodegenNode | IfConditionalExpression +} + +export interface ForCodegenNode extends SequenceExpression { + expressions: [OpenBlockExpression, ForBlockCodegenNode] +} + +export interface ForBlockCodegenNode extends CallExpression { + callee: typeof CREATE_BLOCK + arguments: [typeof FRAGMENT, 'null', ForRenderListExpression, string] +} + +export interface ForRenderListExpression extends CallExpression { + callee: typeof RENDER_LIST + arguments: [ExpressionNode, ForIteratorExpression] +} + +export interface ForIteratorExpression extends FunctionExpression { + returns: BlockCodegenNode +} + +export interface OpenBlockExpression extends CallExpression { + callee: typeof OPEN_BLOCK + arguments: [] +} + +export type BlockCodegenNode = + | BlockElementCodegenNode + | BlockComponentCodegenNode + | BlockElementCodegenNodeWithDirective + | BlockComponentCodegenNodeWithDirective + +export type BlockElementCodegenNode = ElementCodegenNode & { + callee: typeof CREATE_BLOCK +} + +export type BlockComponentCodegenNode = ComponentCodegenNode & { + callee: typeof CREATE_BLOCK +} + +export type BlockElementCodegenNodeWithDirective = CodegenNodeWithDirective< + BlockElementCodegenNode +> + +export type BlockComponentCodegenNodeWithDirective = CodegenNodeWithDirective< + BlockComponentCodegenNode +> + // AST Utilities --------------------------------------------------------------- // Some expressions, e.g. sequence and conditional expressions, are never @@ -338,17 +552,25 @@ export function createCompoundExpression( } } -export function createCallExpression( - callee: CallExpression['callee'], +type InferCodegenNodeType = T extends typeof CREATE_VNODE + ? ElementCodegenNode | ComponentCodegenNode + : T extends typeof CREATE_BLOCK + ? BlockElementCodegenNode | BlockComponentCodegenNode + : T extends typeof APPLY_DIRECTIVES + ? CodegenNodeWithDirective + : T extends typeof RENDER_SLOT ? SlotOutletCodegenNode : CallExpression + +export function createCallExpression( + callee: T, args: CallExpression['arguments'] = [], loc: SourceLocation = locStub -): CallExpression { +): InferCodegenNodeType { return { type: NodeTypes.JS_CALL_EXPRESSION, loc, callee, arguments: args - } + } as any } export function createFunctionExpression( diff --git a/packages/compiler-core/src/parse.ts b/packages/compiler-core/src/parse.ts index 601a6e4f..7689850b 100644 --- a/packages/compiler-core/src/parse.ts +++ b/packages/compiler-core/src/parse.ts @@ -83,8 +83,9 @@ export function parse(content: string, options: ParserOptions = {}): RootNode { return { type: NodeTypes.ROOT, children: parseChildren(context, TextModes.DATA, []), - imports: [], - statements: [], + helpers: [], + components: [], + directives: [], hoists: [], codegenNode: undefined, loc: getSelection(context, start) diff --git a/packages/compiler-core/src/transforms/hoistStatic.ts b/packages/compiler-core/src/transforms/hoistStatic.ts index 164f2de3..155aa772 100644 --- a/packages/compiler-core/src/transforms/hoistStatic.ts +++ b/packages/compiler-core/src/transforms/hoistStatic.ts @@ -2,13 +2,13 @@ import { RootNode, NodeTypes, TemplateChildNode, - CallExpression, ElementNode, - ElementTypes + ElementTypes, + ElementCodegenNode, + ElementCodegenNodeWithDirective } from '../ast' import { TransformContext } from '../transform' import { APPLY_DIRECTIVES } from '../runtimeHelpers' -import { PropsExpression } from './transformElement' import { PatchFlags } from '@vue/shared' export function hoistStatic(root: RootNode, context: TransformContext) { @@ -29,7 +29,7 @@ function walk( ) { if (isStaticNode(child, resultCache)) { // whole tree is static - child.codegenNode = context.hoist(child.codegenNode!) + ;(child as any).codegenNode = context.hoist(child.codegenNode!) continue } else { // node may contain dynamic children, but its props may be eligible for @@ -40,18 +40,13 @@ function walk( flag === PatchFlags.NEED_PATCH || flag === PatchFlags.TEXT ) { - let codegenNode = child.codegenNode as CallExpression + let codegenNode = child.codegenNode! if (codegenNode.callee === APPLY_DIRECTIVES) { - codegenNode = codegenNode.arguments[0] as CallExpression + codegenNode = codegenNode.arguments[0] } - const props = codegenNode.arguments[1] as - | PropsExpression - | `null` - | undefined + const props = codegenNode.arguments[1] if (props && props !== `null`) { - ;(child.codegenNode as CallExpression).arguments[1] = context.hoist( - props - ) + codegenNode.arguments[1] = context.hoist(props) } } } @@ -67,9 +62,11 @@ function walk( } function getPatchFlag(node: ElementNode): number | undefined { - let codegenNode = node.codegenNode as CallExpression + let codegenNode = node.codegenNode as + | ElementCodegenNode + | ElementCodegenNodeWithDirective if (codegenNode.callee === APPLY_DIRECTIVES) { - codegenNode = codegenNode.arguments[0] as CallExpression + codegenNode = codegenNode.arguments[0] } const flag = codegenNode.arguments[3] return flag ? parseInt(flag as string, 10) : undefined diff --git a/packages/compiler-core/src/transforms/vFor.ts b/packages/compiler-core/src/transforms/vFor.ts index 0cf239ea..4e92e0fb 100644 --- a/packages/compiler-core/src/transforms/vFor.ts +++ b/packages/compiler-core/src/transforms/vFor.ts @@ -14,7 +14,8 @@ import { ElementTypes, createObjectExpression, createObjectProperty, - CallExpression + ForCodegenNode, + PlainElementNode } from '../ast' import { createCompilerError, ErrorCodes } from '../errors' import { @@ -66,7 +67,7 @@ export const transformFor = createStructuralDirectiveTransform( fragmentFlag + (__DEV__ ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``) ]) - ]) + ]) as ForCodegenNode context.replaceNode({ type: NodeTypes.FOR, @@ -118,7 +119,7 @@ export const transformFor = createStructuralDirectiveTransform( : null if (slotOutlet) { // or - childBlock = slotOutlet.codegenNode as CallExpression + childBlock = slotOutlet.codegenNode! if (isTemplate && keyProperty) { // // we need to inject the key to the renderSlot() call. @@ -148,7 +149,7 @@ export const transformFor = createStructuralDirectiveTransform( // Normal element v-for. Directly use the child's codegenNode // arguments, but replace createVNode() with createBlock() childBlock = createBlockExpression( - (node.codegenNode as CallExpression).arguments, + (node as PlainElementNode).codegenNode!.arguments, context ) } diff --git a/packages/compiler-core/src/transforms/vIf.ts b/packages/compiler-core/src/transforms/vIf.ts index b974943f..b1182aa8 100644 --- a/packages/compiler-core/src/transforms/vIf.ts +++ b/packages/compiler-core/src/transforms/vIf.ts @@ -17,7 +17,15 @@ import { CallExpression, createSimpleExpression, createObjectProperty, - createObjectExpression + createObjectExpression, + IfCodegenNode, + IfConditionalExpression, + BlockCodegenNode, + SlotOutletCodegenNode, + ElementCodegenNode, + ComponentCodegenNode, + ElementCodegenNodeWithDirective, + CompoenntCodegenNodeWithDirective } from '../ast' import { createCompilerError, ErrorCodes } from '../errors' import { processExpression } from './transformExpression' @@ -31,7 +39,6 @@ import { RENDER_SLOT } from '../runtimeHelpers' import { injectProp } from '../utils' -import { PropsExpression } from './transformElement' export const transformIf = createStructuralDirectiveTransform( /^(if|else|else-if)$/, @@ -57,7 +64,8 @@ export const transformIf = createStructuralDirectiveTransform( const branch = createIfBranch(node, dir) const codegenNode = createSequenceExpression([ createCallExpression(context.helper(OPEN_BLOCK)) - ]) + ]) as IfCodegenNode + context.replaceNode({ type: NodeTypes.IF, loc: node.loc, @@ -68,9 +76,11 @@ export const transformIf = createStructuralDirectiveTransform( // Exit callback. Complete the codegenNode when all children have been // transformed. return () => { - codegenNode.expressions.push( - createCodegenNodeForBranch(branch, 0, context) - ) + codegenNode.expressions.push(createCodegenNodeForBranch( + branch, + 0, + context + ) as IfConditionalExpression) } } else { // locate the adjacent v-if @@ -137,7 +147,7 @@ function createCodegenNodeForBranch( branch: IfBranchNode, index: number, context: TransformContext -): ConditionalExpression | CallExpression { +): IfConditionalExpression | BlockCodegenNode { if (branch.condition) { return createConditionalExpression( branch.condition, @@ -145,9 +155,9 @@ function createCodegenNodeForBranch( createCallExpression(context.helper(CREATE_BLOCK), [ context.helper(EMPTY) ]) - ) + ) as IfConditionalExpression } else { - return createChildrenCodegenNode(branch, index, context) + return createChildrenCodegenNode(branch, index, context) as BlockCodegenNode } } @@ -173,23 +183,27 @@ function createChildrenCodegenNode( ] if (children.length === 1 && child.type === NodeTypes.FOR) { // optimize away nested fragments when child is a ForNode - const forBlockArgs = (child.codegenNode.expressions[1] as CallExpression) - .arguments + const forBlockArgs = child.codegenNode.expressions[1].arguments // directly use the for block's children and patchFlag blockArgs[2] = forBlockArgs[2] blockArgs[3] = forBlockArgs[3] } return createCallExpression(helper(CREATE_BLOCK), blockArgs) } else { - const childCodegen = (child as ElementNode).codegenNode as CallExpression + const childCodegen = (child as ElementNode).codegenNode as + | ElementCodegenNode + | ComponentCodegenNode + | ElementCodegenNodeWithDirective + | CompoenntCodegenNodeWithDirective + | SlotOutletCodegenNode let vnodeCall = childCodegen // Element with custom directives. Locate the actual createVNode() call. if (vnodeCall.callee === APPLY_DIRECTIVES) { - vnodeCall = vnodeCall.arguments[0] as CallExpression + vnodeCall = vnodeCall.arguments[0] } // Change createVNode to createBlock. if (vnodeCall.callee === CREATE_VNODE) { - vnodeCall.callee = helper(CREATE_BLOCK) + ;(vnodeCall as any).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 @@ -197,10 +211,9 @@ function createChildrenCodegenNode( // logic below works for it too. const propsIndex = vnodeCall.callee === RENDER_SLOT ? 2 : 1 // inject branch key - const existingProps = vnodeCall.arguments[propsIndex] as - | PropsExpression - | undefined - | 'null' + const existingProps = vnodeCall.arguments[ + propsIndex + ] as ElementCodegenNode['arguments'][1] vnodeCall.arguments[propsIndex] = injectProp( existingProps, keyProperty, diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index 084cd5da..eb8eee27 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -14,7 +14,9 @@ import { ObjectExpression, Property, JSChildNode, - createObjectExpression + createObjectExpression, + SlotOutletNode, + TemplateNode } from './ast' import { parse } from 'acorn' import { walk } from 'estree-walker' @@ -180,12 +182,12 @@ export const isVSlot = (p: ElementNode['props'][0]): p is DirectiveNode => export const isTemplateNode = ( node: RootNode | TemplateChildNode -): node is ElementNode & { tagType: ElementTypes.TEMPLATE } => +): node is TemplateNode => node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.TEMPLATE export const isSlotOutlet = ( node: RootNode | TemplateChildNode -): node is ElementNode & { tagType: ElementTypes.ELEMENT } => +): node is SlotOutletNode => node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT export function injectProp(