@reckona/mreact-compiler 0.0.87 → 0.0.88
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/emit-server-stream.js +15 -14
- package/dist/emit-server-stream.js.map +1 -1
- package/dist/emit-server.js +1 -4
- package/dist/emit-server.js.map +1 -1
- package/dist/oxc-component-references.d.ts +2 -0
- package/dist/oxc-component-references.d.ts.map +1 -1
- package/dist/oxc-component-references.js +98 -0
- package/dist/oxc-component-references.js.map +1 -1
- package/dist/oxc.d.ts.map +1 -1
- package/dist/oxc.js +7 -1
- package/dist/oxc.js.map +1 -1
- package/package.json +2 -2
- package/src/emit-server-stream.ts +21 -14
- package/src/emit-server.ts +1 -5
- package/src/oxc-component-references.ts +144 -0
- package/src/oxc.ts +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reckona/mreact-compiler",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"description": "Compiler passes and OXC-backed JSX analysis for mreact.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compiler",
|
|
@@ -50,6 +50,6 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"oxc-parser": "0.129.0",
|
|
52
52
|
"oxc-transform": "0.129.0",
|
|
53
|
-
"@reckona/mreact-shared": "0.0.
|
|
53
|
+
"@reckona/mreact-shared": "0.0.88"
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -74,7 +74,7 @@ export function emitServerStream(
|
|
|
74
74
|
);
|
|
75
75
|
const compatRenderToStringHelperName = allocateHelperName(ir, "_renderCompatToString");
|
|
76
76
|
const streamNodeHelperName = allocateHelperName(ir, "_renderStreamNode");
|
|
77
|
-
const clientBoundaryHelperName = usesClientBoundary(ir)
|
|
77
|
+
const clientBoundaryHelperName = usesClientBoundary(ir, options.serverHydration === true)
|
|
78
78
|
? allocateHelperName(ir, "_renderClientBoundary")
|
|
79
79
|
: undefined;
|
|
80
80
|
const spreadAttributesHelperName = allocateHelperName(ir, "_renderSpreadAttributes");
|
|
@@ -258,8 +258,8 @@ function hasRawJsxDynamicRender(ir: ModuleIr): boolean {
|
|
|
258
258
|
return ir.components.some((component) => containsRawJsxDynamicRender(component.root));
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
-
function usesClientBoundary(ir: ModuleIr): boolean {
|
|
262
|
-
return ir.components.some((component) => containsClientBoundary(component.root));
|
|
261
|
+
function usesClientBoundary(ir: ModuleIr, serverHydration: boolean): boolean {
|
|
262
|
+
return ir.components.some((component) => containsClientBoundary(component.root, serverHydration));
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
function emitClientBoundaryHelper(name: string): string {
|
|
@@ -1374,7 +1374,7 @@ function collectHtmlParts(
|
|
|
1374
1374
|
];
|
|
1375
1375
|
}
|
|
1376
1376
|
|
|
1377
|
-
if (isClientBoundaryPlaceholder(node)) {
|
|
1377
|
+
if (isClientBoundaryPlaceholder(node, state.hydration)) {
|
|
1378
1378
|
const helperName = currentClientBoundaryHelperName;
|
|
1379
1379
|
if (helperName !== undefined) {
|
|
1380
1380
|
return [
|
|
@@ -2272,30 +2272,34 @@ function containsCompatComponent(node: JsxNodeIr): boolean {
|
|
|
2272
2272
|
return false;
|
|
2273
2273
|
}
|
|
2274
2274
|
|
|
2275
|
-
function containsClientBoundary(node: JsxNodeIr): boolean {
|
|
2276
|
-
if (node.kind === "component" && isClientBoundaryPlaceholder(node)) {
|
|
2275
|
+
function containsClientBoundary(node: JsxNodeIr, serverHydration: boolean): boolean {
|
|
2276
|
+
if (node.kind === "component" && isClientBoundaryPlaceholder(node, serverHydration)) {
|
|
2277
2277
|
return true;
|
|
2278
2278
|
}
|
|
2279
2279
|
|
|
2280
2280
|
if (node.kind === "component") {
|
|
2281
2281
|
return (
|
|
2282
|
-
node.children.some(containsClientBoundary) ||
|
|
2282
|
+
node.children.some((child) => containsClientBoundary(child, serverHydration)) ||
|
|
2283
2283
|
node.props.some(
|
|
2284
|
-
(prop) =>
|
|
2284
|
+
(prop) =>
|
|
2285
|
+
prop.kind === "render-prop" &&
|
|
2286
|
+
prop.children.some((child) => containsClientBoundary(child, serverHydration)),
|
|
2285
2287
|
)
|
|
2286
2288
|
);
|
|
2287
2289
|
}
|
|
2288
2290
|
|
|
2289
2291
|
if (node.kind === "conditional") {
|
|
2290
|
-
return [...node.whenTrue, ...node.whenFalse].some(
|
|
2292
|
+
return [...node.whenTrue, ...node.whenFalse].some((child) =>
|
|
2293
|
+
containsClientBoundary(child, serverHydration),
|
|
2294
|
+
);
|
|
2291
2295
|
}
|
|
2292
2296
|
|
|
2293
2297
|
if (node.kind === "list") {
|
|
2294
|
-
return node.children.some(containsClientBoundary);
|
|
2298
|
+
return node.children.some((child) => containsClientBoundary(child, serverHydration));
|
|
2295
2299
|
}
|
|
2296
2300
|
|
|
2297
2301
|
if (node.kind === "element" || node.kind === "fragment") {
|
|
2298
|
-
return node.children.some(containsClientBoundary);
|
|
2302
|
+
return node.children.some((child) => containsClientBoundary(child, serverHydration));
|
|
2299
2303
|
}
|
|
2300
2304
|
|
|
2301
2305
|
if (node.kind === "async-boundary") {
|
|
@@ -2303,7 +2307,7 @@ function containsClientBoundary(node: JsxNodeIr): boolean {
|
|
|
2303
2307
|
...node.children,
|
|
2304
2308
|
...(node.placeholderChildren ?? []),
|
|
2305
2309
|
...(node.catchChildren ?? []),
|
|
2306
|
-
].some(containsClientBoundary);
|
|
2310
|
+
].some((child) => containsClientBoundary(child, serverHydration));
|
|
2307
2311
|
}
|
|
2308
2312
|
|
|
2309
2313
|
return false;
|
|
@@ -2420,8 +2424,11 @@ function emitPropName(name: string): string {
|
|
|
2420
2424
|
return /^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name);
|
|
2421
2425
|
}
|
|
2422
2426
|
|
|
2423
|
-
function isClientBoundaryPlaceholder(
|
|
2424
|
-
|
|
2427
|
+
function isClientBoundaryPlaceholder(
|
|
2428
|
+
node: Extract<JsxNodeIr, { kind: "component" }>,
|
|
2429
|
+
serverHydration = true,
|
|
2430
|
+
): boolean {
|
|
2431
|
+
return node.clientReference !== undefined && (!serverHydration || !isCompatClientReference(node));
|
|
2425
2432
|
}
|
|
2426
2433
|
|
|
2427
2434
|
function isCompatClientReference(node: Extract<JsxNodeIr, { kind: "component" }>): boolean {
|
package/src/emit-server.ts
CHANGED
|
@@ -1416,11 +1416,7 @@ function emitComponentCallExpression(
|
|
|
1416
1416
|
}
|
|
1417
1417
|
|
|
1418
1418
|
function isClientBoundaryPlaceholder(node: Extract<JsxNodeIr, { kind: "component" }>): boolean {
|
|
1419
|
-
return node.clientReference !== undefined
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
function isCompatClientReference(node: Extract<JsxNodeIr, { kind: "component" }>): boolean {
|
|
1423
|
-
return node.clientReference !== undefined && /\.(?:compat)\.[cm]?[jt]sx?$/.test(node.clientReference.moduleId);
|
|
1419
|
+
return node.clientReference !== undefined;
|
|
1424
1420
|
}
|
|
1425
1421
|
|
|
1426
1422
|
function clientBoundaryPlaceholder(node: Extract<JsxNodeIr, { kind: "component" }>): string {
|
|
@@ -120,6 +120,19 @@ export function collectOxcCompatRuntimeImportComponents(
|
|
|
120
120
|
return names;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
export function collectOxcCompatReactNodeComponentReferences(
|
|
124
|
+
program: unknown,
|
|
125
|
+
): Map<string, ClientReferenceIr> {
|
|
126
|
+
const names = new Map<string, ClientReferenceIr>();
|
|
127
|
+
|
|
128
|
+
for (const statement of readArray(readObject(program).body)) {
|
|
129
|
+
collectOxcCompatReactNodeImportReferences(statement, names);
|
|
130
|
+
collectOxcCompatReactNodeClassReferences(statement, names);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return names;
|
|
134
|
+
}
|
|
135
|
+
|
|
123
136
|
export function markOxcAsyncComponentReferences(
|
|
124
137
|
node: JsxNodeIr,
|
|
125
138
|
asyncComponentNames: Set<string>,
|
|
@@ -166,6 +179,21 @@ export function markOxcCompatRuntimeReferences(
|
|
|
166
179
|
});
|
|
167
180
|
}
|
|
168
181
|
|
|
182
|
+
export function markOxcCompatReactNodeReferences(
|
|
183
|
+
node: JsxNodeIr,
|
|
184
|
+
references: ReadonlyMap<string, ClientReferenceIr>,
|
|
185
|
+
): void {
|
|
186
|
+
visitOxcNode(node, (child) => {
|
|
187
|
+
if (child.kind !== "component") {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (findOxcCompatReactNodeReference(child.name, references) !== undefined) {
|
|
192
|
+
child.runtime = "compat";
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
169
197
|
function isOxcClientBoundaryImport(
|
|
170
198
|
statement: Record<string, unknown>,
|
|
171
199
|
inferredBoundaryImports: ReadonlySet<string>,
|
|
@@ -197,6 +225,99 @@ function findOxcClientReference(
|
|
|
197
225
|
};
|
|
198
226
|
}
|
|
199
227
|
|
|
228
|
+
function collectOxcCompatReactNodeImportReferences(
|
|
229
|
+
statement: unknown,
|
|
230
|
+
names: Map<string, ClientReferenceIr>,
|
|
231
|
+
): void {
|
|
232
|
+
const object = readObject(statement);
|
|
233
|
+
|
|
234
|
+
if (object.type !== "ImportDeclaration" || object.importKind === "type") {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const moduleId = String(readObject(object.source).value ?? "");
|
|
239
|
+
|
|
240
|
+
for (const specifier of readArray(object.specifiers)) {
|
|
241
|
+
const specifierObject = readObject(specifier);
|
|
242
|
+
|
|
243
|
+
if (specifierObject.importKind === "type") {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const local = readObject(specifierObject.local);
|
|
248
|
+
const localName = typeof local.name === "string" ? local.name : undefined;
|
|
249
|
+
|
|
250
|
+
if (localName === undefined || !/^[A-Z]/.test(localName)) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (specifierObject.type === "ImportDefaultSpecifier") {
|
|
255
|
+
names.set(localName, { moduleId, exportName: "default" });
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (specifierObject.type === "ImportNamespaceSpecifier") {
|
|
260
|
+
names.set(localName, { moduleId, exportName: "*" });
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (specifierObject.type === "ImportSpecifier") {
|
|
265
|
+
const imported = readObject(specifierObject.imported);
|
|
266
|
+
names.set(localName, {
|
|
267
|
+
moduleId,
|
|
268
|
+
exportName: String(imported.name ?? localName),
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function collectOxcCompatReactNodeClassReferences(
|
|
275
|
+
statement: unknown,
|
|
276
|
+
names: Map<string, ClientReferenceIr>,
|
|
277
|
+
): void {
|
|
278
|
+
const object = readObject(statement);
|
|
279
|
+
const declaration =
|
|
280
|
+
object.type === "ExportNamedDeclaration" || object.type === "ExportDefaultDeclaration"
|
|
281
|
+
? readOptionalObject(object.declaration)
|
|
282
|
+
: object;
|
|
283
|
+
const className = readOxcClassComponentName(declaration);
|
|
284
|
+
|
|
285
|
+
if (className !== undefined) {
|
|
286
|
+
names.set(className, { moduleId: "", exportName: className });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function readOxcClassComponentName(
|
|
291
|
+
node: Record<string, unknown> | undefined,
|
|
292
|
+
): string | undefined {
|
|
293
|
+
if (node?.type === "ClassDeclaration" || node?.type === "ClassExpression") {
|
|
294
|
+
const id = readOptionalObject(node.id);
|
|
295
|
+
const name = typeof id?.name === "string" ? id.name : undefined;
|
|
296
|
+
return name !== undefined && /^[A-Z]/.test(name) ? name : undefined;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (node?.type !== "VariableDeclaration") {
|
|
300
|
+
return undefined;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
for (const declarationValue of readArray(node.declarations)) {
|
|
304
|
+
const declaration = readOptionalObject(declarationValue);
|
|
305
|
+
const id = readOptionalObject(declaration?.id);
|
|
306
|
+
const init = readOptionalObject(declaration?.init);
|
|
307
|
+
const name = typeof id?.name === "string" ? id.name : undefined;
|
|
308
|
+
|
|
309
|
+
if (
|
|
310
|
+
name !== undefined &&
|
|
311
|
+
/^[A-Z]/.test(name) &&
|
|
312
|
+
(init?.type === "ClassExpression" || init?.type === "ClassDeclaration")
|
|
313
|
+
) {
|
|
314
|
+
return name;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return undefined;
|
|
319
|
+
}
|
|
320
|
+
|
|
200
321
|
function collectOxcClientReferenceAliases(
|
|
201
322
|
node: unknown,
|
|
202
323
|
references: Map<string, ClientReferenceIr>,
|
|
@@ -547,6 +668,29 @@ function findOxcCompatRuntimeReference(
|
|
|
547
668
|
: undefined;
|
|
548
669
|
}
|
|
549
670
|
|
|
671
|
+
function findOxcCompatReactNodeReference(
|
|
672
|
+
name: string,
|
|
673
|
+
references: ReadonlyMap<string, ClientReferenceIr>,
|
|
674
|
+
): ClientReferenceIr | undefined {
|
|
675
|
+
const direct = references.get(name);
|
|
676
|
+
|
|
677
|
+
if (direct !== undefined) {
|
|
678
|
+
return direct;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
const [rootName, ...memberNames] = name.split(".");
|
|
682
|
+
const rootReference = rootName === undefined ? undefined : references.get(rootName);
|
|
683
|
+
|
|
684
|
+
if (rootReference === undefined || rootReference.exportName !== "*" || memberNames.length === 0) {
|
|
685
|
+
return undefined;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
return {
|
|
689
|
+
moduleId: rootReference.moduleId,
|
|
690
|
+
exportName: memberNames.join("."),
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
|
|
550
694
|
function compatRuntimeExports(moduleId: string): ReadonlySet<string> | undefined {
|
|
551
695
|
if (moduleId === "@reckona/mreact-router") {
|
|
552
696
|
return routerEntryCompatRuntimeExports;
|
package/src/oxc.ts
CHANGED
|
@@ -57,9 +57,11 @@ import {
|
|
|
57
57
|
} from "./oxc-component-detection.js";
|
|
58
58
|
import {
|
|
59
59
|
collectOxcClientBoundaryImportComponents,
|
|
60
|
+
collectOxcCompatReactNodeComponentReferences,
|
|
60
61
|
collectOxcCompatRuntimeImportComponents,
|
|
61
62
|
markOxcAsyncComponentReferences,
|
|
62
63
|
markOxcClientReferences,
|
|
64
|
+
markOxcCompatReactNodeReferences,
|
|
63
65
|
markOxcCompatRuntimeReferences,
|
|
64
66
|
} from "./oxc-component-references.js";
|
|
65
67
|
import { normalizeOxcExpressionCode, stripOxcGeneratedImports } from "./oxc-code-utils.js";
|
|
@@ -236,6 +238,10 @@ function analyzeOxcToIr(
|
|
|
236
238
|
new Set(options?.clientBoundaryImports ?? []),
|
|
237
239
|
);
|
|
238
240
|
const compatRuntimeImports = collectOxcCompatRuntimeImportComponents(program);
|
|
241
|
+
const compatReactNodeReferences =
|
|
242
|
+
options?.compatReactNodeReturnRenderMode === "react-node"
|
|
243
|
+
? collectOxcCompatReactNodeComponentReferences(program)
|
|
244
|
+
: undefined;
|
|
239
245
|
const bodyLowerers = createOxcBodyLowerers(compatRuntimeImports);
|
|
240
246
|
const moduleRenderValueBindings = collectOxcBodyJsxBindingNames(body);
|
|
241
247
|
const reactiveDerivedFunctionNames = collectOxcReactiveDerivedFunctionNames(body);
|
|
@@ -334,6 +340,9 @@ function analyzeOxcToIr(
|
|
|
334
340
|
markOxcAsyncComponentReferences(component.root, asyncComponentNames);
|
|
335
341
|
markOxcClientReferences(component.root, clientBoundaryImports);
|
|
336
342
|
markOxcCompatRuntimeReferences(component.root, compatRuntimeImports);
|
|
343
|
+
if (compatReactNodeReferences !== undefined) {
|
|
344
|
+
markOxcCompatReactNodeReferences(component.root, compatReactNodeReferences);
|
|
345
|
+
}
|
|
337
346
|
validateOxcNestedAwait(component.root, diagnostics);
|
|
338
347
|
validateOxcAwaitCompatComponents(component.root, diagnostics, {
|
|
339
348
|
allowCompatComponents: options?.awaitCompatComponents === "lower",
|