-
Notifications
You must be signed in to change notification settings - Fork 439
Expand file tree
/
Copy pathir-to-es.ts
More file actions
115 lines (103 loc) · 3.53 KB
/
ir-to-es.ts
File metadata and controls
115 lines (103 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import { inspect } from 'util';
import { is, builders as b } from 'estree-toolkit';
import { esTemplate } from '../estemplate';
import { Comment } from './transformers/comment';
import { Component, LwcComponent } from './transformers/component';
import { Element } from './transformers/element';
import { ForEach } from './transformers/for-each';
import { ForOf } from './transformers/for-of';
import { LegacyIf } from './transformers/legacyIf';
import { Slot } from './transformers/slot';
import { Text } from './transformers/text';
import { createNewContext } from './context';
import { IfBlock } from './transformers/lwcIf';
import type {
ChildNode as IrChildNode,
Node as IrNode,
Root as IrRoot,
} from '@lwc/template-compiler';
import type { Statement as EsStatement, ThrowStatement as EsThrowStatement } from 'estree';
import type { TemplateOpts, Transformer, TransformerContext } from './types';
const bThrowError = esTemplate`
throw new Error(${is.literal});
`<EsThrowStatement>;
const Root: Transformer<IrRoot> = function Root(node, cxt): EsStatement[] {
return irChildrenToEs(node.children, cxt);
};
type Transformers = {
[K in IrNode['type']]: IrNode extends infer T
? T extends IrNode & { type: K }
? Transformer<T>
: never
: never;
};
const defaultTransformer: Transformer = (node: IrNode) => {
throw new Error(`Unimplemented IR node: ${inspect(node)}`);
};
const transformers: Transformers = {
Comment,
Component,
Element,
ExternalComponent: Element,
ForEach,
ForOf,
If: LegacyIf,
IfBlock,
Root,
Text,
// lwc:elseif cannot exist without an lwc:if (IfBlock); this gets handled by that transformer
ElseifBlock: defaultTransformer,
// lwc:elseif cannot exist without an lwc:elseif (IfBlock); this gets handled by that transformer
ElseBlock: defaultTransformer,
ScopedSlotFragment: defaultTransformer,
Slot,
Lwc: LwcComponent,
};
export function irChildrenToEs(
children: IrChildNode[],
cxt: TransformerContext,
cb?: (child: IrChildNode) => (() => void) | void
): EsStatement[] {
const result: EsStatement[] = [];
for (let i = 0; i < children.length; i++) {
// must set the siblings inside the for loop due to nested children
cxt.siblings = children;
cxt.currentNodeIndex = i;
const cleanUp = cb?.(children[i]);
result.push(...irToEs(children[i], cxt));
cleanUp?.();
}
// reset the context
cxt.siblings = undefined;
cxt.currentNodeIndex = undefined;
return result;
}
export function irToEs<T extends IrNode>(node: T, cxt: TransformerContext): EsStatement[] {
if ('directives' in node && node.directives.some((d) => d.name === 'Dynamic')) {
return [
bThrowError(
b.literal(
'The lwc:dynamic directive is not supported for SSR. Use <lwc:component> instead.'
)
),
];
}
const transformer = transformers[node.type] as Transformer<T>;
return transformer(node, cxt);
}
export function templateIrToEsTree(node: IrNode, contextOpts: TemplateOpts) {
const { getImports, cxt } = createNewContext(contextOpts);
const statements = irToEs(node, cxt);
return {
addImport: cxt.import,
getImports,
statements,
cxt,
};
}