@reckona/mreact-compiler 0.0.66 → 0.0.67
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/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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { SourceLocation } from "./types.js";
|
|
2
|
+
|
|
3
|
+
export function readObject(value: unknown): Record<string, unknown> {
|
|
4
|
+
return typeof value === "object" && value !== null ? (value as Record<string, unknown>) : {};
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function readArray(value: unknown): unknown[] {
|
|
8
|
+
return Array.isArray(value) ? value : [];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function readSource(code: string, node: unknown): string {
|
|
12
|
+
const object = readObject(node);
|
|
13
|
+
return typeof object.start === "number" && typeof object.end === "number"
|
|
14
|
+
? code.slice(object.start, object.end)
|
|
15
|
+
: "";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function unwrapOxcParentheses(
|
|
19
|
+
expression: Record<string, unknown>,
|
|
20
|
+
): Record<string, unknown> {
|
|
21
|
+
let current = expression;
|
|
22
|
+
|
|
23
|
+
while (current.type === "ParenthesizedExpression") {
|
|
24
|
+
current = readObject(current.expression);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return current;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getOxcLocation(code: string, node: unknown): SourceLocation | undefined {
|
|
31
|
+
const start = readObject(node).start;
|
|
32
|
+
|
|
33
|
+
if (typeof start !== "number") {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return getOxcLocationFromOffset(code, start);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getOxcLocationFromOffset(
|
|
41
|
+
code: string,
|
|
42
|
+
start: number,
|
|
43
|
+
): SourceLocation | undefined {
|
|
44
|
+
if (!Number.isInteger(start) || start < 0 || start > code.length) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let line = 1;
|
|
49
|
+
let column = 1;
|
|
50
|
+
|
|
51
|
+
for (let index = 0; index < start; index += 1) {
|
|
52
|
+
if (code[index] === "\n") {
|
|
53
|
+
line += 1;
|
|
54
|
+
column = 1;
|
|
55
|
+
} else {
|
|
56
|
+
column += 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { line, column };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function arraysEqual(left: readonly string[], right: readonly string[]): boolean {
|
|
64
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
65
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import type { JsxNodeIr, ModuleIr } from "./ir.js";
|
|
2
|
+
|
|
3
|
+
const rawJsxCandidatePattern = /<[A-Za-z][\w.:-]*(?:\s|>|\/)/;
|
|
4
|
+
const rawJsxCandidateGlobalPattern = /<[A-Za-z][\w.:-]*(?:\s|>|\/)/g;
|
|
5
|
+
|
|
6
|
+
export function containsRawJsxInIr(ir: ModuleIr): boolean {
|
|
7
|
+
return ir.components.some(
|
|
8
|
+
(component) =>
|
|
9
|
+
component.bodyStatements.some(containsRawJsx) || containsRawJsxInNode(component.root),
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function containsRawJsx(value: string): boolean {
|
|
14
|
+
if (rawJsxCandidatePattern.test(value)) {
|
|
15
|
+
rawJsxCandidateGlobalPattern.lastIndex = 0;
|
|
16
|
+
|
|
17
|
+
for (
|
|
18
|
+
let match = rawJsxCandidateGlobalPattern.exec(value);
|
|
19
|
+
match !== null;
|
|
20
|
+
match = rawJsxCandidateGlobalPattern.exec(value)
|
|
21
|
+
) {
|
|
22
|
+
if (isCodePosition(value, match.index) && isLikelyRawJsxStart(value, match.index)) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isCodePosition(value: string, target: number): boolean {
|
|
32
|
+
let index = 0;
|
|
33
|
+
|
|
34
|
+
while (index < target) {
|
|
35
|
+
const char = value[index];
|
|
36
|
+
if (char === '"' || char === "'") {
|
|
37
|
+
const next = skipQuotedString(value, index, char);
|
|
38
|
+
if (next > target) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
index = next;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (char === "`") {
|
|
46
|
+
const next = skipTemplateLiteral(value, index);
|
|
47
|
+
if (next > target) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
index = next;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (char === "/" && value[index + 1] === "/") {
|
|
55
|
+
const next = skipLineComment(value, index + 2);
|
|
56
|
+
if (next > target) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
index = next;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (char === "/" && value[index + 1] === "*") {
|
|
64
|
+
const next = skipBlockComment(value, index + 2);
|
|
65
|
+
if (next > target) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
index = next;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
index += 1;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function containsRawJsxInNode(node: JsxNodeIr): boolean {
|
|
79
|
+
if (node.kind === "list") {
|
|
80
|
+
return (
|
|
81
|
+
node.bodyStatements?.some(containsRawJsx) === true || node.children.some(containsRawJsxInNode)
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (node.kind === "conditional") {
|
|
86
|
+
return node.whenTrue.some(containsRawJsxInNode) || node.whenFalse.some(containsRawJsxInNode);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (node.kind === "fragment") {
|
|
90
|
+
return node.children.some(containsRawJsxInNode);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (node.kind === "component") {
|
|
94
|
+
return (
|
|
95
|
+
node.children.some(containsRawJsxInNode) ||
|
|
96
|
+
node.props.some(
|
|
97
|
+
(prop) => prop.kind === "render-prop" && prop.children.some(containsRawJsxInNode),
|
|
98
|
+
)
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (node.kind === "async-boundary") {
|
|
103
|
+
return (
|
|
104
|
+
node.children.some(containsRawJsxInNode) ||
|
|
105
|
+
node.placeholderChildren?.some(containsRawJsxInNode) === true ||
|
|
106
|
+
node.catchChildren?.some(containsRawJsxInNode) === true
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return node.kind === "element" && node.children.some(containsRawJsxInNode);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function skipQuotedString(value: string, start: number, quote: string): number {
|
|
114
|
+
let index = start + 1;
|
|
115
|
+
|
|
116
|
+
while (index < value.length) {
|
|
117
|
+
const char = value[index];
|
|
118
|
+
if (char === "\\") {
|
|
119
|
+
index += 2;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (char === quote) {
|
|
124
|
+
return index + 1;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
index += 1;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return value.length;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function skipTemplateLiteral(value: string, start: number): number {
|
|
134
|
+
let index = start + 1;
|
|
135
|
+
|
|
136
|
+
while (index < value.length) {
|
|
137
|
+
const char = value[index];
|
|
138
|
+
if (char === "\\") {
|
|
139
|
+
index += 2;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (char === "`") {
|
|
144
|
+
return index + 1;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
index += 1;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return value.length;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function skipLineComment(value: string, start: number): number {
|
|
154
|
+
const end = value.indexOf("\n", start);
|
|
155
|
+
return end === -1 ? value.length : end + 1;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function skipBlockComment(value: string, start: number): number {
|
|
159
|
+
const end = value.indexOf("*/", start);
|
|
160
|
+
return end === -1 ? value.length : end + 2;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function isLikelyRawJsxStart(value: string, start: number): boolean {
|
|
164
|
+
const next = value[start + 1];
|
|
165
|
+
if (next === ">") {
|
|
166
|
+
return hasJsxExpressionPrefix(value, start);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (next === undefined || !isAsciiLetter(next)) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let index = start + 2;
|
|
174
|
+
while (index < value.length && isJsxNameChar(value[index] ?? "")) {
|
|
175
|
+
index += 1;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const afterName = value[index];
|
|
179
|
+
if (
|
|
180
|
+
afterName !== undefined &&
|
|
181
|
+
!isWhitespace(afterName) &&
|
|
182
|
+
afterName !== ">" &&
|
|
183
|
+
afterName !== "/"
|
|
184
|
+
) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return hasJsxExpressionPrefix(value, start);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function hasJsxExpressionPrefix(value: string, start: number): boolean {
|
|
192
|
+
let index = start - 1;
|
|
193
|
+
while (index >= 0 && isWhitespace(value[index] ?? "")) {
|
|
194
|
+
index -= 1;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (index < 0) {
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const previous = value[index] ?? "";
|
|
202
|
+
if ("([{?:,=;&|!+-*~^>".includes(previous)) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (isIdentifierChar(previous)) {
|
|
207
|
+
const end = index + 1;
|
|
208
|
+
while (index >= 0 && isIdentifierChar(value[index] ?? "")) {
|
|
209
|
+
index -= 1;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const word = value.slice(index + 1, end);
|
|
213
|
+
return word === "return" || word === "yield" || word === "throw";
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function isAsciiLetter(value: string): boolean {
|
|
220
|
+
const code = value.charCodeAt(0);
|
|
221
|
+
return (code >= 65 && code <= 90) || (code >= 97 && code <= 122);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function isJsxNameChar(value: string): boolean {
|
|
225
|
+
return isIdentifierChar(value) || value === "." || value === ":" || value === "-";
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function isIdentifierChar(value: string): boolean {
|
|
229
|
+
if (value === "_" || value === "$") {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const code = value.charCodeAt(0);
|
|
234
|
+
return (code >= 65 && code <= 90) || (code >= 97 && code <= 122) || (code >= 48 && code <= 57);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function isWhitespace(value: string): boolean {
|
|
238
|
+
return value === " " || value === "\t" || value === "\n" || value === "\r";
|
|
239
|
+
}
|