@reckona/mreact-compiler 0.0.161 → 0.0.162
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.d.ts.map +1 -1
- package/dist/emit-server-stream.js +70 -4
- package/dist/emit-server-stream.js.map +1 -1
- package/dist/oxc-compat-create-element.d.ts +2 -0
- package/dist/oxc-compat-create-element.d.ts.map +1 -1
- package/dist/oxc-compat-create-element.js +93 -18
- package/dist/oxc-compat-create-element.js.map +1 -1
- package/dist/oxc.d.ts.map +1 -1
- package/dist/oxc.js +177 -21
- package/dist/oxc.js.map +1 -1
- package/package.json +2 -2
- package/src/emit-server-stream.ts +103 -8
- package/src/oxc-compat-create-element.ts +132 -25
- package/src/oxc.ts +326 -12
|
@@ -8,6 +8,7 @@ import { readArray, readObject, readSource, unwrapOxcParentheses } from "./oxc-n
|
|
|
8
8
|
// interpreter semantics never get half-applied.
|
|
9
9
|
|
|
10
10
|
const COMPAT_CREATE_ELEMENT_SOURCES = new Set(["react", "@reckona/mreact-compat"]);
|
|
11
|
+
const COMPAT_RENDER_TO_STRING_SOURCES = new Set(["@reckona/mreact-compat"]);
|
|
11
12
|
|
|
12
13
|
export function collectCompatCreateElementNames(program: unknown): Set<string> {
|
|
13
14
|
const names = new Set<string>();
|
|
@@ -44,6 +45,41 @@ export function collectCompatCreateElementNames(program: unknown): Set<string> {
|
|
|
44
45
|
return names;
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
export function collectCompatRenderToStringNames(program: unknown): Set<string> {
|
|
49
|
+
const names = new Set<string>();
|
|
50
|
+
|
|
51
|
+
for (const statement of readArray(readObject(program).body)) {
|
|
52
|
+
const declaration = readObject(statement);
|
|
53
|
+
|
|
54
|
+
if (declaration.type !== "ImportDeclaration") {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const source = readObject(declaration.source);
|
|
59
|
+
|
|
60
|
+
if (typeof source.value !== "string" || !COMPAT_RENDER_TO_STRING_SOURCES.has(source.value)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (const specifier of readArray(declaration.specifiers)) {
|
|
65
|
+
const specifierObject = readObject(specifier);
|
|
66
|
+
|
|
67
|
+
if (specifierObject.type !== "ImportSpecifier") {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const imported = readObject(specifierObject.imported);
|
|
72
|
+
const local = readObject(specifierObject.local);
|
|
73
|
+
|
|
74
|
+
if (imported.name === "renderToString" && typeof local.name === "string") {
|
|
75
|
+
names.add(local.name);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return names;
|
|
81
|
+
}
|
|
82
|
+
|
|
47
83
|
// Mirrors packages/react-compat/src/server-render.ts attribute serialization
|
|
48
84
|
// for compile-time-known prop values. Keep these tables in sync with the
|
|
49
85
|
// interpreter; parity tests compare emitted bytes against renderToString.
|
|
@@ -363,6 +399,40 @@ export function analyzeCompatCreateElementRoot(
|
|
|
363
399
|
return lowerCreateElementCall(code, unwrapOxcParentheses(expression), scope);
|
|
364
400
|
}
|
|
365
401
|
|
|
402
|
+
export function analyzeCompatCreateElementFunctionRoot(
|
|
403
|
+
code: string,
|
|
404
|
+
functionLike: Record<string, unknown>,
|
|
405
|
+
names: ReadonlySet<string>,
|
|
406
|
+
): JsxNodeIr | undefined {
|
|
407
|
+
if (names.size === 0) {
|
|
408
|
+
return undefined;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const shadowed = collectFunctionShadowedNames(functionLike, names);
|
|
412
|
+
const scope: CompatCreateElementScope = { names, shadowed };
|
|
413
|
+
const body = unwrapOxcParentheses(readObject(functionLike.body));
|
|
414
|
+
|
|
415
|
+
if (body.type !== "BlockStatement") {
|
|
416
|
+
return lowerCreateElementCall(code, body, scope);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
for (const statement of readArray(body.body)) {
|
|
420
|
+
const statementObject = readObject(statement);
|
|
421
|
+
|
|
422
|
+
if (statementObject.type !== "ReturnStatement") {
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return lowerCreateElementCall(
|
|
427
|
+
code,
|
|
428
|
+
unwrapOxcParentheses(readObject(statementObject.argument)),
|
|
429
|
+
scope,
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return undefined;
|
|
434
|
+
}
|
|
435
|
+
|
|
366
436
|
function lowerCreateElementCall(
|
|
367
437
|
code: string,
|
|
368
438
|
expression: Record<string, unknown>,
|
|
@@ -493,6 +563,45 @@ function lowerCreateElementChild(
|
|
|
493
563
|
}
|
|
494
564
|
}
|
|
495
565
|
|
|
566
|
+
if (child.type === "ConditionalExpression") {
|
|
567
|
+
const whenTrue = lowerCreateElementDynamicBranch(code, readObject(child.consequent), scope);
|
|
568
|
+
const whenFalse = lowerCreateElementDynamicBranch(code, readObject(child.alternate), scope);
|
|
569
|
+
|
|
570
|
+
if (whenTrue !== undefined && whenFalse !== undefined) {
|
|
571
|
+
return [
|
|
572
|
+
{
|
|
573
|
+
kind: "conditional",
|
|
574
|
+
conditionCode: readSource(code, readObject(child.test)),
|
|
575
|
+
whenTrue,
|
|
576
|
+
whenFalse,
|
|
577
|
+
},
|
|
578
|
+
];
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
if (child.type === "LogicalExpression" && child.operator === "&&") {
|
|
583
|
+
const whenTrue = lowerCreateElementDynamicBranch(code, readObject(child.right), scope);
|
|
584
|
+
|
|
585
|
+
if (whenTrue !== undefined) {
|
|
586
|
+
const conditionValueName = logicalConditionValueName(readObject(child.left));
|
|
587
|
+
|
|
588
|
+
return [
|
|
589
|
+
{
|
|
590
|
+
kind: "conditional",
|
|
591
|
+
conditionCode: readSource(code, readObject(child.left)),
|
|
592
|
+
conditionValueName,
|
|
593
|
+
whenTrue,
|
|
594
|
+
whenFalse: [
|
|
595
|
+
{
|
|
596
|
+
kind: "expr",
|
|
597
|
+
code: renderableFalsyConditionValueCode(conditionValueName),
|
|
598
|
+
},
|
|
599
|
+
],
|
|
600
|
+
},
|
|
601
|
+
];
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
496
605
|
// Provably-string expressions escape directly (and stay batchable); the
|
|
497
606
|
// interpreter would emit the same escaped bytes for them.
|
|
498
607
|
if (isProvablyStringExpression(child, scope)) {
|
|
@@ -505,6 +614,28 @@ function lowerCreateElementChild(
|
|
|
505
614
|
return [{ kind: "expr", code: readSource(code, child), renderMode: "compat-child" }];
|
|
506
615
|
}
|
|
507
616
|
|
|
617
|
+
function lowerCreateElementDynamicBranch(
|
|
618
|
+
code: string,
|
|
619
|
+
expression: Record<string, unknown>,
|
|
620
|
+
scope: CompatCreateElementScope,
|
|
621
|
+
): JsxNodeIr[] | undefined {
|
|
622
|
+
const unwrapped = unwrapOxcParentheses(expression);
|
|
623
|
+
|
|
624
|
+
if (unwrapped.type === "Literal" && (unwrapped.value === null || unwrapped.value === false)) {
|
|
625
|
+
return [];
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
return lowerCreateElementChild(code, unwrapped, scope);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
function logicalConditionValueName(expression: Record<string, unknown>): string {
|
|
632
|
+
return `__mreactLogical_${typeof expression.start === "number" ? expression.start : "value"}`;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
function renderableFalsyConditionValueCode(name: string): string {
|
|
636
|
+
return `((typeof ${name} === "number" || typeof ${name} === "bigint") ? ${name} : null)`;
|
|
637
|
+
}
|
|
638
|
+
|
|
508
639
|
function isProvablyStringExpression(
|
|
509
640
|
expression: Record<string, unknown>,
|
|
510
641
|
scope: CompatCreateElementScope,
|
|
@@ -623,31 +754,7 @@ export function hasLowerableCompatCreateElementReturn(
|
|
|
623
754
|
functionLike: Record<string, unknown>,
|
|
624
755
|
names: ReadonlySet<string>,
|
|
625
756
|
): boolean {
|
|
626
|
-
|
|
627
|
-
return false;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
const shadowed = collectFunctionShadowedNames(functionLike, names);
|
|
631
|
-
const scope: CompatCreateElementScope = { names, shadowed };
|
|
632
|
-
const body = unwrapOxcParentheses(readObject(functionLike.body));
|
|
633
|
-
|
|
634
|
-
if (body.type !== "BlockStatement") {
|
|
635
|
-
return lowerCreateElementCall(code, body, scope) !== undefined;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
for (const statement of readArray(body.body)) {
|
|
639
|
-
const statementObject = readObject(statement);
|
|
640
|
-
|
|
641
|
-
if (statementObject.type !== "ReturnStatement") {
|
|
642
|
-
continue;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
const argument = unwrapOxcParentheses(readObject(statementObject.argument));
|
|
646
|
-
|
|
647
|
-
return lowerCreateElementCall(code, argument, scope) !== undefined;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
return false;
|
|
757
|
+
return analyzeCompatCreateElementFunctionRoot(code, functionLike, names) !== undefined;
|
|
651
758
|
}
|
|
652
759
|
|
|
653
760
|
export function collectFunctionShadowedNames(
|
package/src/oxc.ts
CHANGED
|
@@ -71,8 +71,10 @@ import {
|
|
|
71
71
|
type OxcChildAnalysisContext,
|
|
72
72
|
} from "./oxc-child-analysis.js";
|
|
73
73
|
import {
|
|
74
|
+
analyzeCompatCreateElementFunctionRoot,
|
|
74
75
|
analyzeCompatCreateElementRoot,
|
|
75
76
|
collectCompatCreateElementNames,
|
|
77
|
+
collectCompatRenderToStringNames,
|
|
76
78
|
collectFunctionShadowedNames,
|
|
77
79
|
hasLowerableCompatCreateElementReturn,
|
|
78
80
|
} from "./oxc-compat-create-element.js";
|
|
@@ -249,11 +251,23 @@ function analyzeOxcToIr(
|
|
|
249
251
|
: undefined;
|
|
250
252
|
const localJsxReturnFunctionNames =
|
|
251
253
|
target === "server" ? collectOxcLocalJsxReturnFunctionNames(program) : new Set<string>();
|
|
252
|
-
// Stream emit keeps interpreting compat trees for now; only the string
|
|
253
|
-
// pipeline lowers createElement calls.
|
|
254
254
|
const compatCreateElementNames =
|
|
255
|
-
target === "server"
|
|
256
|
-
|
|
255
|
+
target === "server" ? collectCompatCreateElementNames(program) : new Set<string>();
|
|
256
|
+
const compatRenderToStringNames =
|
|
257
|
+
target === "server" ? collectCompatRenderToStringNames(program) : new Set<string>();
|
|
258
|
+
const compatCreateElementLocalFunctionLikes =
|
|
259
|
+
target === "server"
|
|
260
|
+
? collectCompatCreateElementLocalFunctionLikes(program)
|
|
261
|
+
: new Map<string, Record<string, unknown>>();
|
|
262
|
+
const compatRenderToStringLowerableTargets =
|
|
263
|
+
target === "server"
|
|
264
|
+
? collectCompatRenderToStringLowerableTargets(
|
|
265
|
+
code,
|
|
266
|
+
body,
|
|
267
|
+
compatCreateElementNames,
|
|
268
|
+
compatRenderToStringNames,
|
|
269
|
+
compatCreateElementLocalFunctionLikes,
|
|
270
|
+
)
|
|
257
271
|
: new Set<string>();
|
|
258
272
|
const localJsxHelperHtmlParameters =
|
|
259
273
|
target === "server"
|
|
@@ -281,7 +295,15 @@ function analyzeOxcToIr(
|
|
|
281
295
|
|
|
282
296
|
if (
|
|
283
297
|
isOxcJsxComponentStatement(statement, localJsxReturnFunctionNames) ||
|
|
284
|
-
isCompatCreateElementComponentStatement(
|
|
298
|
+
isCompatCreateElementComponentStatement(
|
|
299
|
+
code,
|
|
300
|
+
statement,
|
|
301
|
+
compatCreateElementNames,
|
|
302
|
+
compatRenderToStringNames,
|
|
303
|
+
compatCreateElementLocalFunctionLikes,
|
|
304
|
+
compatRenderToStringLowerableTargets,
|
|
305
|
+
options?.serverOutput,
|
|
306
|
+
) ||
|
|
285
307
|
(options?.compatReactNodeReturn === true && isOxcExportedFunctionLike(statement))
|
|
286
308
|
) {
|
|
287
309
|
const declaration = readObject(readObject(statement).declaration);
|
|
@@ -346,6 +368,9 @@ function analyzeOxcToIr(
|
|
|
346
368
|
diagnostics,
|
|
347
369
|
options?.bodyStatementJsx ?? "dom-node",
|
|
348
370
|
compatCreateElementNames,
|
|
371
|
+
compatRenderToStringNames,
|
|
372
|
+
compatCreateElementLocalFunctionLikes,
|
|
373
|
+
compatRenderToStringLowerableTargets,
|
|
349
374
|
moduleRenderValueBindings,
|
|
350
375
|
options?.compatReactNodeReturn === true,
|
|
351
376
|
options?.serverOutput,
|
|
@@ -557,32 +582,292 @@ function readCompatCreateElementPlainComponent(
|
|
|
557
582
|
return undefined;
|
|
558
583
|
}
|
|
559
584
|
|
|
585
|
+
function collectCompatCreateElementLocalFunctionLikes(
|
|
586
|
+
program: unknown,
|
|
587
|
+
): Map<string, Record<string, unknown>> {
|
|
588
|
+
const functionLikes = new Map<string, Record<string, unknown>>();
|
|
589
|
+
|
|
590
|
+
for (const statement of readArray(readObject(program).body)) {
|
|
591
|
+
const object = readObject(statement);
|
|
592
|
+
const declaration =
|
|
593
|
+
object.type === "ExportNamedDeclaration" ? readObject(object.declaration) : object;
|
|
594
|
+
|
|
595
|
+
if (declaration.type === "FunctionDeclaration") {
|
|
596
|
+
const id = readObject(declaration.id);
|
|
597
|
+
|
|
598
|
+
if (typeof id.name === "string") {
|
|
599
|
+
functionLikes.set(id.name, declaration);
|
|
600
|
+
}
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (declaration.type !== "VariableDeclaration") {
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
for (const declarator of readArray(declaration.declarations)) {
|
|
609
|
+
const declaratorObject = readObject(declarator);
|
|
610
|
+
const id = readObject(declaratorObject.id);
|
|
611
|
+
const initializer = unwrapOxcComponentFunctionLikeInitializer(
|
|
612
|
+
readObject(declaratorObject.init),
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
if (typeof id.name === "string" && initializer !== undefined) {
|
|
616
|
+
functionLikes.set(id.name, initializer);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
return functionLikes;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function collectCompatRenderToStringLowerableTargets(
|
|
625
|
+
code: string,
|
|
626
|
+
body: readonly unknown[],
|
|
627
|
+
createElementNames: ReadonlySet<string>,
|
|
628
|
+
renderToStringNames: ReadonlySet<string>,
|
|
629
|
+
localFunctionLikes: ReadonlyMap<string, Record<string, unknown>>,
|
|
630
|
+
): Set<string> {
|
|
631
|
+
const targets = new Set<string>();
|
|
632
|
+
|
|
633
|
+
if (createElementNames.size === 0 || renderToStringNames.size === 0) {
|
|
634
|
+
return targets;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
for (const statement of body) {
|
|
638
|
+
const functionLike = unwrapOxcStatementFunctionLike(statement);
|
|
639
|
+
|
|
640
|
+
if (functionLike === undefined) {
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
const targetName = readCompatRenderToStringWrapperTargetName(
|
|
645
|
+
code,
|
|
646
|
+
functionLike,
|
|
647
|
+
renderToStringNames,
|
|
648
|
+
);
|
|
649
|
+
const targetFunctionLike =
|
|
650
|
+
targetName === undefined ? undefined : localFunctionLikes.get(targetName);
|
|
651
|
+
|
|
652
|
+
if (
|
|
653
|
+
targetName !== undefined &&
|
|
654
|
+
targetFunctionLike !== undefined &&
|
|
655
|
+
analyzeCompatCreateElementFunctionRoot(code, targetFunctionLike, createElementNames) !==
|
|
656
|
+
undefined
|
|
657
|
+
) {
|
|
658
|
+
targets.add(targetName);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
return targets;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function unwrapOxcStatementFunctionLike(statement: unknown): Record<string, unknown> | undefined {
|
|
666
|
+
const object = readObject(statement);
|
|
667
|
+
const declaration =
|
|
668
|
+
object.type === "ExportNamedDeclaration" || object.type === "ExportDefaultDeclaration"
|
|
669
|
+
? readObject(object.declaration)
|
|
670
|
+
: object;
|
|
671
|
+
|
|
672
|
+
if (declaration.type === "FunctionDeclaration") {
|
|
673
|
+
return declaration;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
if (declaration.type !== "VariableDeclaration") {
|
|
677
|
+
return unwrapOxcComponentFunctionLikeInitializer(declaration);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
for (const declarator of readArray(declaration.declarations)) {
|
|
681
|
+
const initializer = unwrapOxcComponentFunctionLikeInitializer(
|
|
682
|
+
readObject(readObject(declarator).init),
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
if (initializer !== undefined) {
|
|
686
|
+
return initializer;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
return undefined;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function readCompatRenderToStringWrapperTargetName(
|
|
694
|
+
code: string,
|
|
695
|
+
functionLike: Record<string, unknown>,
|
|
696
|
+
renderToStringNames: ReadonlySet<string>,
|
|
697
|
+
): string | undefined {
|
|
698
|
+
const expression = readCompatRenderToStringWrapperReturnExpression(functionLike);
|
|
699
|
+
|
|
700
|
+
if (expression === undefined) {
|
|
701
|
+
return undefined;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
return readCompatRenderToStringTargetName(
|
|
705
|
+
expression,
|
|
706
|
+
renderToStringNames,
|
|
707
|
+
collectFunctionShadowedNames(functionLike, renderToStringNames),
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
function readCompatRenderToStringWrapperReturnExpression(
|
|
712
|
+
functionLike: Record<string, unknown>,
|
|
713
|
+
): Record<string, unknown> | undefined {
|
|
714
|
+
const body = unwrapOxcParentheses(readObject(functionLike.body));
|
|
715
|
+
|
|
716
|
+
if (body.type !== "BlockStatement") {
|
|
717
|
+
return body;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
for (const statement of readArray(body.body)) {
|
|
721
|
+
const statementObject = readObject(statement);
|
|
722
|
+
|
|
723
|
+
if (statementObject.type === "ReturnStatement") {
|
|
724
|
+
return unwrapOxcParentheses(readObject(statementObject.argument));
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
return undefined;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
function readCompatRenderToStringTargetName(
|
|
732
|
+
expression: Record<string, unknown>,
|
|
733
|
+
renderToStringNames: ReadonlySet<string>,
|
|
734
|
+
shadowedNames: ReadonlySet<string>,
|
|
735
|
+
): string | undefined {
|
|
736
|
+
if (
|
|
737
|
+
renderToStringNames.size === 0 ||
|
|
738
|
+
expression.type !== "CallExpression" ||
|
|
739
|
+
expression.optional === true
|
|
740
|
+
) {
|
|
741
|
+
return undefined;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
const callee = unwrapOxcParentheses(readObject(expression.callee));
|
|
745
|
+
|
|
746
|
+
if (
|
|
747
|
+
callee.type !== "Identifier" ||
|
|
748
|
+
typeof callee.name !== "string" ||
|
|
749
|
+
!renderToStringNames.has(callee.name) ||
|
|
750
|
+
shadowedNames.has(callee.name)
|
|
751
|
+
) {
|
|
752
|
+
return undefined;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
const args = readArray(expression.arguments);
|
|
756
|
+
|
|
757
|
+
if (args.length !== 1) {
|
|
758
|
+
return undefined;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
const target = unwrapOxcParentheses(readObject(args[0]));
|
|
762
|
+
|
|
763
|
+
return target.type === "Identifier" && typeof target.name === "string" ? target.name : undefined;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
function hasCompatRenderToStringWrapperReturn(
|
|
767
|
+
code: string,
|
|
768
|
+
functionLike: Record<string, unknown>,
|
|
769
|
+
renderToStringNames: ReadonlySet<string>,
|
|
770
|
+
): boolean {
|
|
771
|
+
return (
|
|
772
|
+
readCompatRenderToStringWrapperTargetName(code, functionLike, renderToStringNames) !== undefined
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
function analyzeCompatRenderToStringWrapperRoot(
|
|
777
|
+
code: string,
|
|
778
|
+
functionLike: Record<string, unknown>,
|
|
779
|
+
returnExpression: Record<string, unknown>,
|
|
780
|
+
createElementNames: ReadonlySet<string>,
|
|
781
|
+
renderToStringNames: ReadonlySet<string>,
|
|
782
|
+
localFunctionLikes: ReadonlyMap<string, Record<string, unknown>>,
|
|
783
|
+
): ComponentIr["root"] | undefined {
|
|
784
|
+
const targetName = readCompatRenderToStringTargetName(
|
|
785
|
+
returnExpression,
|
|
786
|
+
renderToStringNames,
|
|
787
|
+
collectFunctionShadowedNames(functionLike, renderToStringNames),
|
|
788
|
+
);
|
|
789
|
+
|
|
790
|
+
if (targetName === undefined) {
|
|
791
|
+
return undefined;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
const targetFunctionLike = localFunctionLikes.get(targetName);
|
|
795
|
+
const lowered =
|
|
796
|
+
targetFunctionLike === undefined
|
|
797
|
+
? undefined
|
|
798
|
+
: analyzeCompatCreateElementFunctionRoot(code, targetFunctionLike, createElementNames);
|
|
799
|
+
|
|
800
|
+
if (lowered !== undefined) {
|
|
801
|
+
return lowered;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
return {
|
|
805
|
+
kind: "expr",
|
|
806
|
+
code: normalizeOxcExpressionCode(readSource(code, returnExpression)),
|
|
807
|
+
renderMode: "html",
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
|
|
560
811
|
function isCompatCreateElementComponentStatement(
|
|
561
812
|
code: string,
|
|
562
813
|
statement: unknown,
|
|
563
814
|
names: ReadonlySet<string>,
|
|
815
|
+
renderToStringNames: ReadonlySet<string>,
|
|
816
|
+
localFunctionLikes: ReadonlyMap<string, Record<string, unknown>>,
|
|
817
|
+
renderToStringLowerableTargets: ReadonlySet<string>,
|
|
818
|
+
serverOutput?: AnalyzeModuleOptions["serverOutput"],
|
|
564
819
|
): boolean {
|
|
565
|
-
if (names.size === 0) {
|
|
820
|
+
if (names.size === 0 && renderToStringNames.size === 0) {
|
|
566
821
|
return false;
|
|
567
822
|
}
|
|
568
823
|
|
|
569
824
|
const object = readObject(statement);
|
|
570
825
|
|
|
571
826
|
if (object.type === "ExportDefaultDeclaration") {
|
|
572
|
-
|
|
827
|
+
const functionLike = unwrapOxcComponentFunctionLikeInitializer(readObject(object.declaration));
|
|
828
|
+
|
|
829
|
+
return (
|
|
830
|
+
readCompatCreateElementFunctionLike(code, readObject(object.declaration), names) !==
|
|
831
|
+
undefined ||
|
|
832
|
+
(functionLike !== undefined &&
|
|
833
|
+
hasCompatRenderToStringWrapperReturn(code, functionLike, renderToStringNames))
|
|
834
|
+
);
|
|
573
835
|
}
|
|
574
836
|
|
|
575
837
|
if (object.type === "ExportNamedDeclaration") {
|
|
576
838
|
const declaration = readObject(object.declaration);
|
|
577
839
|
|
|
578
840
|
if (declaration.type === "FunctionDeclaration") {
|
|
579
|
-
return
|
|
841
|
+
return (
|
|
842
|
+
hasLowerableCompatCreateElementReturn(code, declaration, names) ||
|
|
843
|
+
hasCompatRenderToStringWrapperReturn(code, declaration, renderToStringNames)
|
|
844
|
+
);
|
|
580
845
|
}
|
|
581
846
|
|
|
582
847
|
return readCompatCreateElementPlainComponent(code, declaration, names) !== undefined;
|
|
583
848
|
}
|
|
584
849
|
|
|
585
|
-
|
|
850
|
+
const plainComponent = readCompatCreateElementPlainComponent(code, statement, names);
|
|
851
|
+
|
|
852
|
+
if (serverOutput === "stream") {
|
|
853
|
+
return (
|
|
854
|
+
plainComponent !== undefined &&
|
|
855
|
+
renderToStringLowerableTargets.has(plainComponent.name) &&
|
|
856
|
+
localFunctionLikes.get(plainComponent.name) === plainComponent.initializer
|
|
857
|
+
);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
if (plainComponent !== undefined) {
|
|
861
|
+
return true;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
const functionLike = unwrapOxcStatementFunctionLike(statement);
|
|
865
|
+
|
|
866
|
+
if (functionLike === undefined) {
|
|
867
|
+
return false;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
return hasCompatRenderToStringWrapperReturn(code, functionLike, renderToStringNames);
|
|
586
871
|
}
|
|
587
872
|
|
|
588
873
|
function analyzeOxcComponent(
|
|
@@ -593,6 +878,9 @@ function analyzeOxcComponent(
|
|
|
593
878
|
diagnostics: Diagnostic[],
|
|
594
879
|
bodyStatementJsx: OxcBodyStatementJsxMode,
|
|
595
880
|
compatCreateElementNames: ReadonlySet<string>,
|
|
881
|
+
compatRenderToStringNames: ReadonlySet<string>,
|
|
882
|
+
compatCreateElementLocalFunctionLikes: ReadonlyMap<string, Record<string, unknown>>,
|
|
883
|
+
compatRenderToStringLowerableTargets: ReadonlySet<string>,
|
|
596
884
|
moduleRenderValueBindings: Set<string>,
|
|
597
885
|
compatReactNodeReturn: boolean,
|
|
598
886
|
serverOutput: AnalyzeModuleOptions["serverOutput"],
|
|
@@ -610,7 +898,8 @@ function analyzeOxcComponent(
|
|
|
610
898
|
if (
|
|
611
899
|
declaration === undefined ||
|
|
612
900
|
(!hasOxcFunctionLikeComponentReturn(declaration) &&
|
|
613
|
-
!hasLowerableCompatCreateElementReturn(code, declaration, compatCreateElementNames)
|
|
901
|
+
!hasLowerableCompatCreateElementReturn(code, declaration, compatCreateElementNames) &&
|
|
902
|
+
!hasCompatRenderToStringWrapperReturn(code, declaration, compatRenderToStringNames))
|
|
614
903
|
) {
|
|
615
904
|
return [];
|
|
616
905
|
}
|
|
@@ -628,6 +917,8 @@ function analyzeOxcComponent(
|
|
|
628
917
|
diagnostics,
|
|
629
918
|
bodyStatementJsx,
|
|
630
919
|
compatCreateElementNames,
|
|
920
|
+
compatRenderToStringNames,
|
|
921
|
+
compatCreateElementLocalFunctionLikes,
|
|
631
922
|
moduleRenderValueBindings,
|
|
632
923
|
compatReactNodeReturn,
|
|
633
924
|
serverOutput,
|
|
@@ -644,12 +935,18 @@ function analyzeOxcComponent(
|
|
|
644
935
|
if (object.type !== "ExportNamedDeclaration") {
|
|
645
936
|
const plainComponent =
|
|
646
937
|
readOxcPlainComponent(statement) ??
|
|
647
|
-
|
|
938
|
+
(serverOutput === "stream"
|
|
939
|
+
? undefined
|
|
940
|
+
: readCompatCreateElementPlainComponent(code, statement, compatCreateElementNames));
|
|
648
941
|
|
|
649
942
|
if (plainComponent === undefined) {
|
|
650
943
|
return [];
|
|
651
944
|
}
|
|
652
945
|
|
|
946
|
+
if (compatRenderToStringLowerableTargets.has(plainComponent.name)) {
|
|
947
|
+
return [];
|
|
948
|
+
}
|
|
949
|
+
|
|
653
950
|
return [
|
|
654
951
|
{
|
|
655
952
|
...analyzeOxcFunctionLikeComponent(
|
|
@@ -662,6 +959,8 @@ function analyzeOxcComponent(
|
|
|
662
959
|
diagnostics,
|
|
663
960
|
bodyStatementJsx,
|
|
664
961
|
compatCreateElementNames,
|
|
962
|
+
compatRenderToStringNames,
|
|
963
|
+
compatCreateElementLocalFunctionLikes,
|
|
665
964
|
moduleRenderValueBindings,
|
|
666
965
|
compatReactNodeReturn,
|
|
667
966
|
serverOutput,
|
|
@@ -698,6 +997,8 @@ function analyzeOxcComponent(
|
|
|
698
997
|
diagnostics,
|
|
699
998
|
bodyStatementJsx,
|
|
700
999
|
compatCreateElementNames,
|
|
1000
|
+
compatRenderToStringNames,
|
|
1001
|
+
compatCreateElementLocalFunctionLikes,
|
|
701
1002
|
moduleRenderValueBindings,
|
|
702
1003
|
compatReactNodeReturn,
|
|
703
1004
|
serverOutput,
|
|
@@ -715,7 +1016,8 @@ function analyzeOxcComponent(
|
|
|
715
1016
|
(!compatReactNodeReturn &&
|
|
716
1017
|
!hasComponentReturn(declaration.body) &&
|
|
717
1018
|
!hasLocalJsxHelperCallReturn(declaration.body, localJsxReturnFunctionNames) &&
|
|
718
|
-
!hasLowerableCompatCreateElementReturn(code, declaration, compatCreateElementNames)
|
|
1019
|
+
!hasLowerableCompatCreateElementReturn(code, declaration, compatCreateElementNames) &&
|
|
1020
|
+
!hasCompatRenderToStringWrapperReturn(code, declaration, compatRenderToStringNames))
|
|
719
1021
|
) {
|
|
720
1022
|
return [];
|
|
721
1023
|
}
|
|
@@ -737,6 +1039,8 @@ function analyzeOxcComponent(
|
|
|
737
1039
|
diagnostics,
|
|
738
1040
|
bodyStatementJsx,
|
|
739
1041
|
compatCreateElementNames,
|
|
1042
|
+
compatRenderToStringNames,
|
|
1043
|
+
compatCreateElementLocalFunctionLikes,
|
|
740
1044
|
moduleRenderValueBindings,
|
|
741
1045
|
compatReactNodeReturn,
|
|
742
1046
|
serverOutput,
|
|
@@ -787,6 +1091,8 @@ function analyzeOxcFunctionLikeComponent(
|
|
|
787
1091
|
diagnostics: Diagnostic[],
|
|
788
1092
|
bodyStatementJsx: OxcBodyStatementJsxMode,
|
|
789
1093
|
compatCreateElementNames: ReadonlySet<string>,
|
|
1094
|
+
compatRenderToStringNames: ReadonlySet<string>,
|
|
1095
|
+
compatCreateElementLocalFunctionLikes: ReadonlyMap<string, Record<string, unknown>>,
|
|
790
1096
|
moduleRenderValueBindings: Set<string>,
|
|
791
1097
|
compatReactNodeReturn: boolean,
|
|
792
1098
|
serverOutput: AnalyzeModuleOptions["serverOutput"],
|
|
@@ -873,6 +1179,14 @@ function analyzeOxcFunctionLikeComponent(
|
|
|
873
1179
|
names: compatCreateElementNames,
|
|
874
1180
|
shadowed: collectFunctionShadowedNames(functionLike, compatCreateElementNames),
|
|
875
1181
|
})) ??
|
|
1182
|
+
analyzeCompatRenderToStringWrapperRoot(
|
|
1183
|
+
code,
|
|
1184
|
+
functionLike,
|
|
1185
|
+
returnExpression,
|
|
1186
|
+
compatCreateElementNames,
|
|
1187
|
+
compatRenderToStringNames,
|
|
1188
|
+
compatCreateElementLocalFunctionLikes,
|
|
1189
|
+
) ??
|
|
876
1190
|
(isJsxRoot(returnExpression.type) || returnExpression.type === "JSXFragment"
|
|
877
1191
|
? analyzeOxcJsxNode(code, returnExpression, childAnalysisContext)
|
|
878
1192
|
: isOxcComponentCallExpression(returnExpression)
|