@reckona/mreact-compiler 0.0.145 → 0.0.146
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-compat.js +53 -4
- package/dist/emit-compat.js.map +1 -1
- package/dist/emit-server-stream.js +10 -6
- package/dist/emit-server-stream.js.map +1 -1
- package/dist/emit-server.js +7 -3
- package/dist/emit-server.js.map +1 -1
- package/package.json +2 -2
- package/src/emit-compat.ts +71 -4
- package/src/emit-server-stream.ts +12 -7
- package/src/emit-server.ts +17 -1
package/src/emit-compat.ts
CHANGED
|
@@ -322,7 +322,7 @@ function emitComponent(
|
|
|
322
322
|
helperNames: CompatHelperNames,
|
|
323
323
|
dev: boolean,
|
|
324
324
|
): string {
|
|
325
|
-
const directTextBindings = collectDirectTextBindings(component);
|
|
325
|
+
const directTextBindings = collectDirectTextBindings(component, helperNames);
|
|
326
326
|
const body = component.bodyStatements.map((statement) =>
|
|
327
327
|
` ${rewriteDirectTextBindingStatement(statement, directTextBindings, helperNames)}`
|
|
328
328
|
);
|
|
@@ -560,8 +560,12 @@ function emitComponentProps(
|
|
|
560
560
|
return `{ ${entries.join(", ")} }`;
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
function collectDirectTextBindings(
|
|
563
|
+
function collectDirectTextBindings(
|
|
564
|
+
component: ComponentIr,
|
|
565
|
+
helperNames?: CompatHelperNames,
|
|
566
|
+
): DirectTextBinding[] {
|
|
564
567
|
const candidates: DirectTextBinding[] = [];
|
|
568
|
+
const allocator = createNameAllocator(collectReservedComponentLocalNames(component, helperNames));
|
|
565
569
|
|
|
566
570
|
for (const statement of component.bodyStatements) {
|
|
567
571
|
const match = statement.match(
|
|
@@ -575,14 +579,27 @@ function collectDirectTextBindings(component: ComponentIr): DirectTextBinding[]
|
|
|
575
579
|
|
|
576
580
|
candidates.push({
|
|
577
581
|
stateName,
|
|
578
|
-
tupleName: `_${stateName}StateTuple
|
|
579
|
-
bindingName: `_${stateName}TextBinding
|
|
582
|
+
tupleName: allocator(`_${stateName}StateTuple`),
|
|
583
|
+
bindingName: allocator(`_${stateName}TextBinding`),
|
|
580
584
|
});
|
|
581
585
|
}
|
|
582
586
|
|
|
583
587
|
return candidates.filter((candidate) => directTextBindingIsSafe(component, candidate));
|
|
584
588
|
}
|
|
585
589
|
|
|
590
|
+
function collectReservedComponentLocalNames(
|
|
591
|
+
component: ComponentIr,
|
|
592
|
+
helperNames?: CompatHelperNames,
|
|
593
|
+
): string[] {
|
|
594
|
+
return [
|
|
595
|
+
component.name,
|
|
596
|
+
component.exportName,
|
|
597
|
+
...component.parameters,
|
|
598
|
+
...component.bindingNames,
|
|
599
|
+
...Object.values(helperNames ?? {}).filter((name): name is string => name !== undefined),
|
|
600
|
+
];
|
|
601
|
+
}
|
|
602
|
+
|
|
586
603
|
function directTextBindingIsSafe(
|
|
587
604
|
component: ComponentIr,
|
|
588
605
|
candidate: DirectTextBinding,
|
|
@@ -601,6 +618,11 @@ function directTextBindingIsSafe(
|
|
|
601
618
|
return;
|
|
602
619
|
}
|
|
603
620
|
|
|
621
|
+
if (nodeHasStructuralIdentifierUse(node, candidate.stateName)) {
|
|
622
|
+
unsafe = true;
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
|
|
604
626
|
if (node.kind === "element") {
|
|
605
627
|
for (const attr of node.attributes) {
|
|
606
628
|
if (attr.kind === "static-attr") {
|
|
@@ -627,6 +649,51 @@ function directTextBindingIsSafe(
|
|
|
627
649
|
return directTextUses === 1 && !unsafe && hasDirectTextBindingHost(component.root, candidate);
|
|
628
650
|
}
|
|
629
651
|
|
|
652
|
+
function nodeHasStructuralIdentifierUse(node: JsxNodeIr, stateName: string): boolean {
|
|
653
|
+
if (node.kind === "conditional") {
|
|
654
|
+
return containsIdentifier(node.conditionCode, stateName);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
if (node.kind === "list") {
|
|
658
|
+
return [
|
|
659
|
+
node.itemsCode,
|
|
660
|
+
node.keyCode,
|
|
661
|
+
...(node.bodyStatements ?? []),
|
|
662
|
+
].some((code) => code !== undefined && containsIdentifier(code, stateName));
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
if (node.kind === "component") {
|
|
666
|
+
return (
|
|
667
|
+
(node.keyCode !== undefined && containsIdentifier(node.keyCode, stateName)) ||
|
|
668
|
+
node.props.some((prop) => {
|
|
669
|
+
if (prop.kind === "render-prop") {
|
|
670
|
+
return false;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
return containsIdentifier(prop.code, stateName);
|
|
674
|
+
})
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
if (node.kind === "element") {
|
|
679
|
+
return node.keyCode !== undefined && containsIdentifier(node.keyCode, stateName);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (node.kind === "async-boundary") {
|
|
683
|
+
return [
|
|
684
|
+
node.valueCode,
|
|
685
|
+
node.placeholderTagCode,
|
|
686
|
+
node.catchName,
|
|
687
|
+
].some((code) => code !== undefined && containsIdentifier(code, stateName));
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
if (node.kind === "fragment") {
|
|
691
|
+
return (node.bodyStatements ?? []).some((statement) => containsIdentifier(statement, stateName));
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
|
|
630
697
|
function isDirectTextBindingDeclaration(statement: string, stateName: string): boolean {
|
|
631
698
|
return new RegExp(
|
|
632
699
|
`^\\s*const\\s+\\[\\s*${stateName}\\s*,\\s*[A-Za-z_$][\\w$]*\\s*\\]\\s*=\\s*useState\\(.+\\);\\s*$`,
|
|
@@ -625,7 +625,7 @@ function emitAppendStatements(
|
|
|
625
625
|
);
|
|
626
626
|
}
|
|
627
627
|
|
|
628
|
-
return ` await ${part.name}(${sinkName}, ${emitPropsObject(part.props, part.children, part.escapeHelperName)});`;
|
|
628
|
+
return ` await ${part.name}(${sinkName}, ${emitPropsObject(part.props, part.children, part.escapeHelperName, part.name)});`;
|
|
629
629
|
}
|
|
630
630
|
|
|
631
631
|
if (part.kind === "react-node") {
|
|
@@ -721,7 +721,7 @@ function emitSyncPartAsAppendStatement(
|
|
|
721
721
|
);
|
|
722
722
|
}
|
|
723
723
|
|
|
724
|
-
return `${indent}await ${part.name}(${sinkName}, ${emitPropsObject(part.props, part.children, part.escapeHelperName)});`;
|
|
724
|
+
return `${indent}await ${part.name}(${sinkName}, ${emitPropsObject(part.props, part.children, part.escapeHelperName, part.name)});`;
|
|
725
725
|
}
|
|
726
726
|
|
|
727
727
|
if (part.kind === "react-node") {
|
|
@@ -868,7 +868,7 @@ function tryEmitPartAsStringExpression(
|
|
|
868
868
|
}
|
|
869
869
|
if (part.kind === "component" && part.hydrationId === undefined) {
|
|
870
870
|
return emitRenderableHtmlExpression(
|
|
871
|
-
`${part.name}(${emitPropsObject(part.props, part.children, part.escapeHelperName)})`,
|
|
871
|
+
`${part.name}(${emitPropsObject(part.props, part.children, part.escapeHelperName, part.name)})`,
|
|
872
872
|
);
|
|
873
873
|
}
|
|
874
874
|
// Non-compat component parts require `await sink-write`; lists with
|
|
@@ -2491,6 +2491,7 @@ function emitPropsObject(
|
|
|
2491
2491
|
props: ComponentPropIr[],
|
|
2492
2492
|
children: JsxNodeIr[] = [],
|
|
2493
2493
|
escapeHelperName = "_escapeHtml",
|
|
2494
|
+
componentName?: string,
|
|
2494
2495
|
): string {
|
|
2495
2496
|
const entries = props.map((prop) => {
|
|
2496
2497
|
if (prop.kind === "spread-prop") {
|
|
@@ -2505,17 +2506,21 @@ function emitPropsObject(
|
|
|
2505
2506
|
});
|
|
2506
2507
|
|
|
2507
2508
|
if (children.length > 0) {
|
|
2509
|
+
const childrenExpression =
|
|
2510
|
+
emitStreamRendererFromChildren(children, escapeHelperName) ??
|
|
2511
|
+
emitHtmlExpressionFromChildren(children, escapeHelperName);
|
|
2508
2512
|
entries.push(
|
|
2509
|
-
`children: ${
|
|
2510
|
-
emitStreamRendererFromChildren(children, escapeHelperName) ??
|
|
2511
|
-
emitHtmlExpressionFromChildren(children, escapeHelperName)
|
|
2512
|
-
}`,
|
|
2513
|
+
`children: ${isRouterLinkComponentName(componentName) ? `${componentName}.trustedHtml(${childrenExpression})` : childrenExpression}`,
|
|
2513
2514
|
);
|
|
2514
2515
|
}
|
|
2515
2516
|
|
|
2516
2517
|
return `{ ${entries.join(", ")} }`;
|
|
2517
2518
|
}
|
|
2518
2519
|
|
|
2520
|
+
function isRouterLinkComponentName(name: string | undefined): name is string {
|
|
2521
|
+
return name !== undefined && (name === "Link" || name.endsWith(".Link"));
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2519
2524
|
function emitCompatRuntimePropsObject(
|
|
2520
2525
|
props: ComponentPropIr[],
|
|
2521
2526
|
children: JsxNodeIr[] = [],
|
package/src/emit-server.ts
CHANGED
|
@@ -559,6 +559,7 @@ function collectHtmlStatements(
|
|
|
559
559
|
contextProviderHelperName,
|
|
560
560
|
contextConsumerHelperName,
|
|
561
561
|
reactNodeRenderHelperName,
|
|
562
|
+
node.name,
|
|
562
563
|
),
|
|
563
564
|
asyncComponentNames,
|
|
564
565
|
)};`,
|
|
@@ -1467,6 +1468,7 @@ function emitPropsObject(
|
|
|
1467
1468
|
contextProviderHelperName?: string,
|
|
1468
1469
|
contextConsumerHelperName?: string,
|
|
1469
1470
|
reactNodeRenderHelperName?: string,
|
|
1471
|
+
componentName?: string,
|
|
1470
1472
|
): string {
|
|
1471
1473
|
const entries = props.map((prop) => {
|
|
1472
1474
|
if (prop.kind === "spread-prop") {
|
|
@@ -1481,14 +1483,28 @@ function emitPropsObject(
|
|
|
1481
1483
|
});
|
|
1482
1484
|
|
|
1483
1485
|
if (children.length > 0) {
|
|
1486
|
+
const childrenExpression = emitHtmlExpressionFromChildren(
|
|
1487
|
+
children,
|
|
1488
|
+
escapeHelperName,
|
|
1489
|
+
escapeBatchHelperName,
|
|
1490
|
+
asyncComponentNames,
|
|
1491
|
+
dynamicAttributes,
|
|
1492
|
+
contextProviderHelperName,
|
|
1493
|
+
contextConsumerHelperName,
|
|
1494
|
+
reactNodeRenderHelperName,
|
|
1495
|
+
);
|
|
1484
1496
|
entries.push(
|
|
1485
|
-
`children: ${
|
|
1497
|
+
`children: ${isRouterLinkComponentName(componentName) ? `${componentName}.trustedHtml(${childrenExpression})` : childrenExpression}`,
|
|
1486
1498
|
);
|
|
1487
1499
|
}
|
|
1488
1500
|
|
|
1489
1501
|
return `{ ${entries.join(", ")} }`;
|
|
1490
1502
|
}
|
|
1491
1503
|
|
|
1504
|
+
function isRouterLinkComponentName(name: string | undefined): name is string {
|
|
1505
|
+
return name !== undefined && (name === "Link" || name.endsWith(".Link"));
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1492
1508
|
function emitCompatRuntimePropsObject(
|
|
1493
1509
|
props: ComponentPropIr[],
|
|
1494
1510
|
children: JsxNodeIr[] = [],
|