@reckona/mreact-compiler 0.0.66 → 0.0.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compiler-module-context.js.map +1 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/emit-client.js.map +1 -1
- package/dist/emit-compat.js.map +1 -1
- package/dist/emit-escape-helper.js.map +1 -1
- package/dist/emit-server-shared.js.map +1 -1
- package/dist/emit-server-stream.js.map +1 -1
- package/dist/emit-server.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/ir.js.map +1 -1
- package/dist/oxc-analysis-types.js.map +1 -1
- package/dist/oxc-await-analysis.js.map +1 -1
- package/dist/oxc-await-ids.js.map +1 -1
- package/dist/oxc-await-validation.js.map +1 -1
- package/dist/oxc-bindings.js.map +1 -1
- package/dist/oxc-body-lowering.js.map +1 -1
- package/dist/oxc-child-analysis.js.map +1 -1
- package/dist/oxc-code-utils.js.map +1 -1
- package/dist/oxc-component-detection.js.map +1 -1
- package/dist/oxc-component-props.js.map +1 -1
- package/dist/oxc-component-references.js.map +1 -1
- package/dist/oxc-dom-lowering.js.map +1 -1
- package/dist/oxc-expression-utils.js.map +1 -1
- package/dist/oxc-jsx-attributes.js.map +1 -1
- package/dist/oxc-jsx-text.js.map +1 -1
- package/dist/oxc-nested-lowering.js.map +1 -1
- package/dist/oxc-node-utils.js.map +1 -1
- package/dist/oxc-raw-jsx.js.map +1 -1
- package/dist/oxc-render-values.js.map +1 -1
- package/dist/oxc-runtime-emit.js.map +1 -1
- package/dist/oxc-transform.js.map +1 -1
- package/dist/oxc.js.map +1 -1
- package/dist/transform.js.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +4 -3
- package/src/compiler-module-context.ts +31 -0
- package/src/diagnostics.ts +184 -0
- package/src/emit-client.ts +837 -0
- package/src/emit-compat.ts +567 -0
- package/src/emit-escape-helper.ts +45 -0
- package/src/emit-server-shared.ts +384 -0
- package/src/emit-server-stream.ts +2558 -0
- package/src/emit-server.ts +1827 -0
- package/src/index.ts +44 -0
- package/src/internal.ts +1905 -0
- package/src/ir.ts +151 -0
- package/src/oxc-analysis-types.ts +5 -0
- package/src/oxc-await-analysis.ts +165 -0
- package/src/oxc-await-ids.ts +62 -0
- package/src/oxc-await-validation.ts +117 -0
- package/src/oxc-bindings.ts +70 -0
- package/src/oxc-body-lowering.ts +430 -0
- package/src/oxc-child-analysis.ts +791 -0
- package/src/oxc-code-utils.ts +19 -0
- package/src/oxc-component-detection.ts +459 -0
- package/src/oxc-component-props.ts +170 -0
- package/src/oxc-component-references.ts +613 -0
- package/src/oxc-dom-lowering.ts +127 -0
- package/src/oxc-expression-utils.ts +42 -0
- package/src/oxc-jsx-attributes.ts +110 -0
- package/src/oxc-jsx-text.ts +84 -0
- package/src/oxc-nested-lowering.ts +319 -0
- package/src/oxc-node-utils.ts +65 -0
- package/src/oxc-raw-jsx.ts +239 -0
- package/src/oxc-render-values.ts +620 -0
- package/src/oxc-runtime-emit.ts +212 -0
- package/src/oxc-transform.ts +77 -0
- package/src/oxc.ts +932 -0
- package/src/transform.ts +634 -0
- package/src/types.ts +117 -0
package/src/ir.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type { SourceLocation } from "./types.js";
|
|
2
|
+
|
|
3
|
+
export interface ModuleIr {
|
|
4
|
+
userImports: string[];
|
|
5
|
+
moduleStatements: string[];
|
|
6
|
+
moduleBindingNames: string[];
|
|
7
|
+
components: ComponentIr[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ComponentIr {
|
|
11
|
+
name: string;
|
|
12
|
+
exportName: string;
|
|
13
|
+
exported?: boolean;
|
|
14
|
+
exportDefault?: boolean;
|
|
15
|
+
async?: boolean;
|
|
16
|
+
parameters: string[];
|
|
17
|
+
bodyStatements: string[];
|
|
18
|
+
bindingNames: string[];
|
|
19
|
+
root: JsxNodeIr;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type JsxNodeIr =
|
|
23
|
+
| JsxElementIr
|
|
24
|
+
| ComponentRefIr
|
|
25
|
+
| JsxFragmentIr
|
|
26
|
+
| ConditionalIr
|
|
27
|
+
| ListIr
|
|
28
|
+
| TextIr
|
|
29
|
+
| ExprIr
|
|
30
|
+
| AsyncBoundaryIr;
|
|
31
|
+
|
|
32
|
+
export interface JsxElementIr {
|
|
33
|
+
kind: "element";
|
|
34
|
+
tagName: string;
|
|
35
|
+
keyCode?: string;
|
|
36
|
+
attributes: AttributeIr[];
|
|
37
|
+
children: JsxNodeIr[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ComponentRefIr {
|
|
41
|
+
kind: "component";
|
|
42
|
+
name: string;
|
|
43
|
+
loc?: SourceLocation;
|
|
44
|
+
runtime?: "compat";
|
|
45
|
+
async?: boolean;
|
|
46
|
+
clientReference?: ClientReferenceIr;
|
|
47
|
+
keyCode?: string;
|
|
48
|
+
props: ComponentPropIr[];
|
|
49
|
+
children: JsxNodeIr[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ClientReferenceIr {
|
|
53
|
+
moduleId: string;
|
|
54
|
+
exportName: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type ComponentPropIr = ComponentNamedPropIr | ComponentRenderPropIr | ComponentSpreadPropIr;
|
|
58
|
+
|
|
59
|
+
export interface ComponentNamedPropIr {
|
|
60
|
+
kind: "prop";
|
|
61
|
+
name: string;
|
|
62
|
+
code: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface ComponentRenderPropIr {
|
|
66
|
+
kind: "render-prop";
|
|
67
|
+
name: string;
|
|
68
|
+
valueName?: string;
|
|
69
|
+
children: JsxNodeIr[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface ComponentSpreadPropIr {
|
|
73
|
+
kind: "spread-prop";
|
|
74
|
+
code: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface JsxFragmentIr {
|
|
78
|
+
kind: "fragment";
|
|
79
|
+
children: JsxNodeIr[];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ConditionalIr {
|
|
83
|
+
kind: "conditional";
|
|
84
|
+
conditionCode: string;
|
|
85
|
+
whenTrue: JsxNodeIr[];
|
|
86
|
+
whenFalse: JsxNodeIr[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface ListIr {
|
|
90
|
+
kind: "list";
|
|
91
|
+
itemsCode: string;
|
|
92
|
+
itemName: string;
|
|
93
|
+
indexName?: string;
|
|
94
|
+
keyCode?: string;
|
|
95
|
+
bodyStatements?: string[];
|
|
96
|
+
children: JsxNodeIr[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface TextIr {
|
|
100
|
+
kind: "text";
|
|
101
|
+
value: string;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface ExprIr {
|
|
105
|
+
kind: "expr";
|
|
106
|
+
code: string;
|
|
107
|
+
renderMode?: "dynamic" | "html" | "react-node" | "stream-node";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface AsyncBoundaryIr {
|
|
111
|
+
kind: "async-boundary";
|
|
112
|
+
loc?: SourceLocation;
|
|
113
|
+
valueCode: string;
|
|
114
|
+
valueName: string;
|
|
115
|
+
children: JsxNodeIr[];
|
|
116
|
+
placeholderChildren?: JsxNodeIr[];
|
|
117
|
+
placeholderTagCode?: string;
|
|
118
|
+
catchName?: string;
|
|
119
|
+
catchChildren?: JsxNodeIr[];
|
|
120
|
+
awaitId?: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export type AttributeIr =
|
|
124
|
+
| StaticAttributeIr
|
|
125
|
+
| DynamicAttributeIr
|
|
126
|
+
| EventAttributeIr
|
|
127
|
+
| SpreadAttributeIr;
|
|
128
|
+
|
|
129
|
+
export interface StaticAttributeIr {
|
|
130
|
+
kind: "static-attr";
|
|
131
|
+
name: string;
|
|
132
|
+
value: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface DynamicAttributeIr {
|
|
136
|
+
kind: "dynamic-attr";
|
|
137
|
+
name: string;
|
|
138
|
+
code: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface EventAttributeIr {
|
|
142
|
+
kind: "event";
|
|
143
|
+
name: string;
|
|
144
|
+
eventName: string;
|
|
145
|
+
code: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface SpreadAttributeIr {
|
|
149
|
+
kind: "spread-attr";
|
|
150
|
+
code: string;
|
|
151
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { readArray, readObject, readSource, unwrapOxcParentheses } from "./oxc-node-utils.js";
|
|
2
|
+
|
|
3
|
+
const UNSERIALIZABLE_CONSTRUCTORS = new Set([
|
|
4
|
+
"Date",
|
|
5
|
+
"Map",
|
|
6
|
+
"Set",
|
|
7
|
+
"WeakMap",
|
|
8
|
+
"WeakSet",
|
|
9
|
+
"RegExp",
|
|
10
|
+
"Error",
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
const UNSERIALIZABLE_CALLEES = new Set(["Symbol", "BigInt"]);
|
|
14
|
+
|
|
15
|
+
export function detectUnserializableAwaitValueReason(
|
|
16
|
+
expression: Record<string, unknown>,
|
|
17
|
+
bindings: ReadonlyMap<string, Record<string, unknown>> | undefined = undefined,
|
|
18
|
+
visited: Set<string> = new Set(),
|
|
19
|
+
): string | undefined {
|
|
20
|
+
const type = String(expression.type ?? "");
|
|
21
|
+
|
|
22
|
+
if (type === "Identifier") {
|
|
23
|
+
if (bindings === undefined) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const name = String(expression.name ?? "");
|
|
28
|
+
|
|
29
|
+
if (name === "" || visited.has(name)) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const initializer = bindings.get(name);
|
|
34
|
+
|
|
35
|
+
if (initializer === undefined) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
visited.add(name);
|
|
40
|
+
return detectUnserializableAwaitValueReason(initializer, bindings, visited);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (type === "NewExpression") {
|
|
44
|
+
const callee = readObject(expression.callee);
|
|
45
|
+
const calleeName = String(callee.name ?? "");
|
|
46
|
+
|
|
47
|
+
if (UNSERIALIZABLE_CONSTRUCTORS.has(calleeName)) {
|
|
48
|
+
return `new ${calleeName}() is not JSON-serializable`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (type === "CallExpression") {
|
|
53
|
+
const callee = readObject(expression.callee);
|
|
54
|
+
|
|
55
|
+
if (callee.type === "Identifier" && UNSERIALIZABLE_CALLEES.has(String(callee.name ?? ""))) {
|
|
56
|
+
return `${String(callee.name)}(...) returns a non-JSON-serializable primitive`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (
|
|
60
|
+
callee.type === "MemberExpression" &&
|
|
61
|
+
String(readObject(callee.object).name ?? "") === "Promise"
|
|
62
|
+
) {
|
|
63
|
+
const property = readObject(callee.property);
|
|
64
|
+
const propertyName = String(property.name ?? "");
|
|
65
|
+
|
|
66
|
+
if (propertyName === "resolve" || propertyName === "all" || propertyName === "allSettled") {
|
|
67
|
+
const args = readArray(expression.arguments);
|
|
68
|
+
const firstArg = args[0];
|
|
69
|
+
|
|
70
|
+
if (firstArg !== undefined) {
|
|
71
|
+
const reason = detectUnserializableAwaitValueReason(
|
|
72
|
+
readObject(firstArg),
|
|
73
|
+
bindings,
|
|
74
|
+
visited,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
if (reason !== undefined) {
|
|
78
|
+
return reason;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (type === "FunctionExpression" || type === "ArrowFunctionExpression") {
|
|
86
|
+
return "function expressions cannot be JSON-serialized";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function collectOxcVariableInitializers(
|
|
93
|
+
bodyStatements: readonly unknown[],
|
|
94
|
+
): Map<string, Record<string, unknown>> {
|
|
95
|
+
const bindings = new Map<string, Record<string, unknown>>();
|
|
96
|
+
|
|
97
|
+
for (const statement of bodyStatements) {
|
|
98
|
+
const stmt = readObject(statement);
|
|
99
|
+
|
|
100
|
+
if (stmt.type !== "VariableDeclaration") {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
for (const declarator of readArray(stmt.declarations)) {
|
|
105
|
+
const decl = readObject(declarator);
|
|
106
|
+
|
|
107
|
+
if (decl.type !== "VariableDeclarator") {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const id = readObject(decl.id);
|
|
112
|
+
|
|
113
|
+
if (id.type !== "Identifier") {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const init = decl.init;
|
|
118
|
+
|
|
119
|
+
if (init === null || init === undefined) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const initObject = unwrapOxcParentheses(readObject(init));
|
|
124
|
+
const name = String(id.name ?? "");
|
|
125
|
+
|
|
126
|
+
if (name === "") {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
bindings.set(name, initObject);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return bindings;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function readOxcExpressionAttribute(
|
|
138
|
+
code: string,
|
|
139
|
+
attributes: readonly unknown[],
|
|
140
|
+
name: string,
|
|
141
|
+
): string | undefined {
|
|
142
|
+
const expression = readOxcExpressionAttributeNode(attributes, name);
|
|
143
|
+
return expression === undefined ? undefined : readSource(code, expression);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function readOxcExpressionAttributeNode(
|
|
147
|
+
attributes: readonly unknown[],
|
|
148
|
+
name: string,
|
|
149
|
+
): Record<string, unknown> | undefined {
|
|
150
|
+
for (const attr of attributes) {
|
|
151
|
+
const object = readObject(attr);
|
|
152
|
+
|
|
153
|
+
if (object.type !== "JSXAttribute" || String(readObject(object.name).name) !== name) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const value = readObject(object.value);
|
|
158
|
+
|
|
159
|
+
if (value.type === "JSXExpressionContainer") {
|
|
160
|
+
return unwrapOxcParentheses(readObject(value.expression));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { JsxNodeIr, ModuleIr } from "./ir.js";
|
|
2
|
+
|
|
3
|
+
export function assignOxcAwaitIds(ir: ModuleIr): void {
|
|
4
|
+
let counter = 0;
|
|
5
|
+
|
|
6
|
+
for (const component of ir.components) {
|
|
7
|
+
counter = walkForAwaitIds(component.root, counter);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function walkForAwaitIds(node: JsxNodeIr, counter: number): number {
|
|
12
|
+
let next = counter;
|
|
13
|
+
|
|
14
|
+
if (node.kind === "async-boundary") {
|
|
15
|
+
node.awaitId = `await${next.toString(36)}`;
|
|
16
|
+
next += 1;
|
|
17
|
+
|
|
18
|
+
for (const child of node.children) {
|
|
19
|
+
next = walkForAwaitIds(child, next);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (node.placeholderChildren !== undefined) {
|
|
23
|
+
for (const child of node.placeholderChildren) {
|
|
24
|
+
next = walkForAwaitIds(child, next);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (node.catchChildren !== undefined) {
|
|
29
|
+
for (const child of node.catchChildren) {
|
|
30
|
+
next = walkForAwaitIds(child, next);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return next;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (node.kind === "element" || node.kind === "fragment" || node.kind === "component") {
|
|
38
|
+
for (const child of node.children) {
|
|
39
|
+
next = walkForAwaitIds(child, next);
|
|
40
|
+
}
|
|
41
|
+
return next;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (node.kind === "conditional") {
|
|
45
|
+
for (const child of node.whenTrue) {
|
|
46
|
+
next = walkForAwaitIds(child, next);
|
|
47
|
+
}
|
|
48
|
+
for (const child of node.whenFalse) {
|
|
49
|
+
next = walkForAwaitIds(child, next);
|
|
50
|
+
}
|
|
51
|
+
return next;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (node.kind === "list") {
|
|
55
|
+
for (const child of node.children) {
|
|
56
|
+
next = walkForAwaitIds(child, next);
|
|
57
|
+
}
|
|
58
|
+
return next;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return next;
|
|
62
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import {
|
|
2
|
+
unsupportedAwaitInnerComponentDiagnostic,
|
|
3
|
+
unsupportedNestedAwaitDiagnostic,
|
|
4
|
+
} from "./diagnostics.js";
|
|
5
|
+
import type { JsxNodeIr } from "./ir.js";
|
|
6
|
+
import type { Diagnostic } from "./types.js";
|
|
7
|
+
|
|
8
|
+
export function validateOxcAwaitCompatComponents(
|
|
9
|
+
node: JsxNodeIr,
|
|
10
|
+
diagnostics: Diagnostic[],
|
|
11
|
+
options: { allowCompatComponents?: boolean } = {},
|
|
12
|
+
insideAwait = false,
|
|
13
|
+
): void {
|
|
14
|
+
if (node.kind === "component") {
|
|
15
|
+
if (insideAwait && node.runtime === "compat" && options.allowCompatComponents !== true) {
|
|
16
|
+
diagnostics.push(unsupportedAwaitInnerComponentDiagnostic(node.name, node.loc));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
for (const prop of node.props) {
|
|
20
|
+
if (prop.kind === "render-prop") {
|
|
21
|
+
for (const child of prop.children) {
|
|
22
|
+
validateOxcAwaitCompatComponents(child, diagnostics, options, insideAwait);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
for (const child of node.children) {
|
|
27
|
+
validateOxcAwaitCompatComponents(child, diagnostics, options, insideAwait);
|
|
28
|
+
}
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (node.kind === "async-boundary") {
|
|
33
|
+
for (const child of [
|
|
34
|
+
...node.children,
|
|
35
|
+
...(node.placeholderChildren ?? []),
|
|
36
|
+
...(node.catchChildren ?? []),
|
|
37
|
+
]) {
|
|
38
|
+
validateOxcAwaitCompatComponents(child, diagnostics, options, true);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (node.kind === "conditional") {
|
|
44
|
+
for (const child of [...node.whenTrue, ...node.whenFalse]) {
|
|
45
|
+
validateOxcAwaitCompatComponents(child, diagnostics, options, insideAwait);
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (node.kind === "list") {
|
|
51
|
+
for (const child of node.children) {
|
|
52
|
+
validateOxcAwaitCompatComponents(child, diagnostics, options, insideAwait);
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (node.kind === "element" || node.kind === "fragment") {
|
|
58
|
+
for (const child of node.children) {
|
|
59
|
+
validateOxcAwaitCompatComponents(child, diagnostics, options, insideAwait);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function validateOxcNestedAwait(
|
|
65
|
+
node: JsxNodeIr,
|
|
66
|
+
diagnostics: Diagnostic[],
|
|
67
|
+
insideAwait = false,
|
|
68
|
+
): void {
|
|
69
|
+
if (node.kind === "async-boundary") {
|
|
70
|
+
if (insideAwait) {
|
|
71
|
+
diagnostics.push(unsupportedNestedAwaitDiagnostic(node.loc));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (const child of [
|
|
75
|
+
...node.children,
|
|
76
|
+
...(node.placeholderChildren ?? []),
|
|
77
|
+
...(node.catchChildren ?? []),
|
|
78
|
+
]) {
|
|
79
|
+
validateOxcNestedAwait(child, diagnostics, true);
|
|
80
|
+
}
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (node.kind === "component") {
|
|
85
|
+
for (const prop of node.props) {
|
|
86
|
+
if (prop.kind === "render-prop") {
|
|
87
|
+
for (const child of prop.children) {
|
|
88
|
+
validateOxcNestedAwait(child, diagnostics, insideAwait);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
for (const child of node.children) {
|
|
93
|
+
validateOxcNestedAwait(child, diagnostics, insideAwait);
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (node.kind === "conditional") {
|
|
99
|
+
for (const child of [...node.whenTrue, ...node.whenFalse]) {
|
|
100
|
+
validateOxcNestedAwait(child, diagnostics, insideAwait);
|
|
101
|
+
}
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (node.kind === "list") {
|
|
106
|
+
for (const child of node.children) {
|
|
107
|
+
validateOxcNestedAwait(child, diagnostics, insideAwait);
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (node.kind === "element" || node.kind === "fragment") {
|
|
113
|
+
for (const child of node.children) {
|
|
114
|
+
validateOxcNestedAwait(child, diagnostics, insideAwait);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { stripTypeScriptWithOxc } from "./oxc-transform.js";
|
|
2
|
+
import { readArray, readObject, readSource } from "./oxc-node-utils.js";
|
|
3
|
+
|
|
4
|
+
export function formatStatement(code: string, statement: unknown): string {
|
|
5
|
+
const source = readSource(code, statement);
|
|
6
|
+
return stripTypeScriptWithOxc(source).replace("() => {}", "() => { }");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function collectBindingNames(statement: unknown): string[] {
|
|
10
|
+
const object = readObject(statement);
|
|
11
|
+
|
|
12
|
+
if (object.type === "ExportNamedDeclaration") {
|
|
13
|
+
return collectBindingNames(object.declaration);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (object.type === "ExportDefaultDeclaration") {
|
|
17
|
+
return collectBindingNames(object.declaration);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (object.type === "FunctionDeclaration" || object.type === "ClassDeclaration") {
|
|
21
|
+
const id = readObject(object.id);
|
|
22
|
+
return typeof id.name === "string" ? [id.name] : [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (object.type === "ForStatement") {
|
|
26
|
+
return collectBindingNames(object.init);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (object.type === "IfStatement") {
|
|
30
|
+
return [...collectBindingNames(object.consequent), ...collectBindingNames(object.alternate)];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (object.type === "BlockStatement") {
|
|
34
|
+
return readArray(object.body).flatMap(collectBindingNames);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (object.type !== "VariableDeclaration") {
|
|
38
|
+
return readArray(object.body).flatMap(collectBindingNames);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return readArray(object.declarations).flatMap((declaration) => {
|
|
42
|
+
const id = readObject(readObject(declaration).id);
|
|
43
|
+
return typeof id.name === "string" ? [id.name] : [];
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function collectImportBindingNames(statement: unknown): string[] {
|
|
48
|
+
return readArray(readObject(statement).specifiers).flatMap((specifier) => {
|
|
49
|
+
const local = readObject(readObject(specifier).local);
|
|
50
|
+
return typeof local.name === "string" ? [local.name] : [];
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function readOxcParameterName(code: string, parameter: unknown): string {
|
|
55
|
+
const object = readObject(parameter);
|
|
56
|
+
|
|
57
|
+
if (typeof object.name === "string") {
|
|
58
|
+
return object.name;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (object.type === "AssignmentPattern") {
|
|
62
|
+
return readOxcParameterName(code, object.left);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (object.type === "RestElement") {
|
|
66
|
+
return `...${readOxcParameterName(code, object.argument)}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return readSource(code, parameter);
|
|
70
|
+
}
|