@reckona/mreact-compiler 0.0.82 → 0.0.83

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/types.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- export type CompileTarget = "client" | "server";
2
- export type ServerOutputMode = "string" | "stream";
3
- export type ServerBootstrapMode = "none" | "out-of-order-reorder";
1
+ import type { ClientReferenceMetadata as SharedClientReferenceMetadata, CompileTarget as SharedCompileTarget, CompilerFrontend as SharedCompilerFrontend, ComponentMetadata as SharedComponentMetadata, Diagnostic as SharedDiagnostic, DiagnosticSuggestion as SharedDiagnosticSuggestion, EventHydrationEntryMetadata as SharedEventHydrationEntryMetadata, EventHydrationManifestMetadata as SharedEventHydrationManifestMetadata, ModuleMetadata as SharedModuleMetadata, RuntimeImport as SharedRuntimeImport, ServerBootstrapMode as SharedServerBootstrapMode, ServerOutputMode as SharedServerOutputMode, SourceLocation as SharedSourceLocation, TransformOutput as SharedTransformOutput } from "@reckona/mreact-shared/compiler-contract";
2
+ export type CompileTarget = SharedCompileTarget;
3
+ export type ServerOutputMode = SharedServerOutputMode;
4
+ export type ServerBootstrapMode = SharedServerBootstrapMode;
4
5
  export type ParserMode = "oxc";
5
- export type CompilerFrontend = "oxc";
6
+ export type CompilerFrontend = SharedCompilerFrontend;
6
7
  export type BodyStatementJsxMode = "dom-node" | "compat-object" | "server-string" | "unsupported";
7
8
  export interface AnalyzeModuleOptions {
8
9
  topLevelJsx?: "diagnostic" | "compat-object" | "server-string";
@@ -35,69 +36,15 @@ export interface ServerEscapeOptions {
35
36
  batchImportName: string;
36
37
  batchImportSource: string;
37
38
  }
38
- export interface TransformOutput {
39
- code: string;
40
- map?: string | null;
41
- diagnostics: Diagnostic[];
42
- metadata: ModuleMetadata;
43
- }
44
- export interface Diagnostic {
45
- level: "info" | "warn" | "error";
46
- code: string;
47
- message: string;
48
- loc?: SourceLocation;
49
- suggestion?: DiagnosticSuggestion;
50
- }
51
- export interface DiagnosticSuggestion {
52
- title: string;
53
- replacement?: string;
54
- link?: string;
55
- }
56
- export interface SourceLocation {
57
- line: number;
58
- column: number;
59
- }
60
- export interface ModuleMetadata {
61
- filename: string;
62
- target: CompileTarget;
63
- compiler: CompilerMetadata;
64
- serverOutput?: ServerOutputMode;
65
- serverBootstrap?: ServerBootstrapMode;
66
- serverBootstrapNonce?: string;
67
- serverBootstrapSrc?: string;
68
- serverHydration?: boolean;
69
- reactSuspenseRevealScriptSrc?: string;
70
- components: ComponentMetadata[];
71
- imports: RuntimeImport[];
72
- clientReferences?: string[];
73
- clientReferenceManifest?: ClientReferenceMetadata[];
74
- serverReferences?: string[];
75
- eventHydrationManifest?: EventHydrationManifestMetadata;
76
- }
77
- export interface CompilerMetadata {
78
- frontend: CompilerFrontend;
79
- typescriptFallback: boolean;
80
- }
81
- export interface ClientReferenceMetadata {
82
- name: string;
83
- moduleId: string;
84
- exportName: string;
85
- }
86
- export interface ComponentMetadata {
87
- name: string;
88
- exportName: string;
89
- }
90
- export interface RuntimeImport {
91
- source: string;
92
- specifiers: string[];
93
- }
94
- export interface EventHydrationManifestMetadata {
95
- version: 1;
96
- events: EventHydrationEntryMetadata[];
97
- }
98
- export interface EventHydrationEntryMetadata {
99
- id: string;
100
- event: string;
101
- handler: string;
102
- }
39
+ export type TransformOutput = SharedTransformOutput;
40
+ export type Diagnostic = SharedDiagnostic;
41
+ export type DiagnosticSuggestion = SharedDiagnosticSuggestion;
42
+ export type SourceLocation = SharedSourceLocation;
43
+ export type ModuleMetadata = SharedModuleMetadata;
44
+ export type CompilerMetadata = SharedModuleMetadata["compiler"];
45
+ export type ClientReferenceMetadata = SharedClientReferenceMetadata;
46
+ export type ComponentMetadata = SharedComponentMetadata;
47
+ export type RuntimeImport = SharedRuntimeImport;
48
+ export type EventHydrationManifestMetadata = SharedEventHydrationManifestMetadata;
49
+ export type EventHydrationEntryMetadata = SharedEventHydrationEntryMetadata;
103
50
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type CompileTarget = \"client\" | \"server\";\nexport type ServerOutputMode = \"string\" | \"stream\";\nexport type ServerBootstrapMode = \"none\" | \"out-of-order-reorder\";\nexport type ParserMode = \"oxc\";\nexport type CompilerFrontend = \"oxc\";\n\nexport type BodyStatementJsxMode = \"dom-node\" | \"compat-object\" | \"server-string\" | \"unsupported\";\n\nexport interface AnalyzeModuleOptions {\n topLevelJsx?: \"diagnostic\" | \"compat-object\" | \"server-string\";\n bodyStatementJsx?: BodyStatementJsxMode;\n serverOutput?: ServerOutputMode;\n awaitCompatComponents?: \"diagnostic\" | \"lower\";\n clientBoundaryImports?: readonly string[];\n compatReactNodeReturn?: boolean;\n compatReactNodeReturnRenderMode?: \"react-node\";\n}\n\nexport interface TransformInput {\n code: string;\n filename: string;\n target: CompileTarget;\n dev: boolean;\n sourceMap?: boolean;\n mode?: \"auto\" | \"reactive\" | \"compat\";\n parser?: ParserMode;\n serverOutput?: ServerOutputMode;\n serverBootstrap?: ServerBootstrapMode;\n serverBootstrapNonce?: string;\n serverBootstrapSrc?: string;\n serverHydration?: boolean;\n serverAwaitHydration?: boolean;\n clientBoundaryImports?: readonly string[];\n serverEscape?: ServerEscapeOptions;\n reactSuspenseRevealScriptSrc?: string;\n}\n\nexport interface ServerEscapeOptions {\n batchImportName: string;\n batchImportSource: string;\n}\n\nexport interface TransformOutput {\n code: string;\n map?: string | null;\n diagnostics: Diagnostic[];\n metadata: ModuleMetadata;\n}\n\nexport interface Diagnostic {\n level: \"info\" | \"warn\" | \"error\";\n code: string;\n message: string;\n loc?: SourceLocation;\n suggestion?: DiagnosticSuggestion;\n}\n\nexport interface DiagnosticSuggestion {\n title: string;\n replacement?: string;\n link?: string;\n}\n\nexport interface SourceLocation {\n line: number;\n column: number;\n}\n\nexport interface ModuleMetadata {\n filename: string;\n target: CompileTarget;\n compiler: CompilerMetadata;\n serverOutput?: ServerOutputMode;\n serverBootstrap?: ServerBootstrapMode;\n serverBootstrapNonce?: string;\n serverBootstrapSrc?: string;\n serverHydration?: boolean;\n reactSuspenseRevealScriptSrc?: string;\n components: ComponentMetadata[];\n imports: RuntimeImport[];\n clientReferences?: string[];\n clientReferenceManifest?: ClientReferenceMetadata[];\n serverReferences?: string[];\n eventHydrationManifest?: EventHydrationManifestMetadata;\n}\n\nexport interface CompilerMetadata {\n frontend: CompilerFrontend;\n typescriptFallback: boolean;\n}\n\nexport interface ClientReferenceMetadata {\n name: string;\n moduleId: string;\n exportName: string;\n}\n\nexport interface ComponentMetadata {\n name: string;\n exportName: string;\n}\n\nexport interface RuntimeImport {\n source: string;\n specifiers: string[];\n}\n\nexport interface EventHydrationManifestMetadata {\n version: 1;\n events: EventHydrationEntryMetadata[];\n}\n\nexport interface EventHydrationEntryMetadata {\n id: string;\n event: string;\n handler: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n ClientReferenceMetadata as SharedClientReferenceMetadata,\n CompileTarget as SharedCompileTarget,\n CompilerFrontend as SharedCompilerFrontend,\n ComponentMetadata as SharedComponentMetadata,\n Diagnostic as SharedDiagnostic,\n DiagnosticSuggestion as SharedDiagnosticSuggestion,\n EventHydrationEntryMetadata as SharedEventHydrationEntryMetadata,\n EventHydrationManifestMetadata as SharedEventHydrationManifestMetadata,\n ModuleMetadata as SharedModuleMetadata,\n RuntimeImport as SharedRuntimeImport,\n ServerBootstrapMode as SharedServerBootstrapMode,\n ServerOutputMode as SharedServerOutputMode,\n SourceLocation as SharedSourceLocation,\n TransformOutput as SharedTransformOutput,\n} from \"@reckona/mreact-shared/compiler-contract\";\n\nexport type CompileTarget = SharedCompileTarget;\nexport type ServerOutputMode = SharedServerOutputMode;\nexport type ServerBootstrapMode = SharedServerBootstrapMode;\nexport type ParserMode = \"oxc\";\nexport type CompilerFrontend = SharedCompilerFrontend;\n\nexport type BodyStatementJsxMode = \"dom-node\" | \"compat-object\" | \"server-string\" | \"unsupported\";\n\nexport interface AnalyzeModuleOptions {\n topLevelJsx?: \"diagnostic\" | \"compat-object\" | \"server-string\";\n bodyStatementJsx?: BodyStatementJsxMode;\n serverOutput?: ServerOutputMode;\n awaitCompatComponents?: \"diagnostic\" | \"lower\";\n clientBoundaryImports?: readonly string[];\n compatReactNodeReturn?: boolean;\n compatReactNodeReturnRenderMode?: \"react-node\";\n}\n\nexport interface TransformInput {\n code: string;\n filename: string;\n target: CompileTarget;\n dev: boolean;\n sourceMap?: boolean;\n mode?: \"auto\" | \"reactive\" | \"compat\";\n parser?: ParserMode;\n serverOutput?: ServerOutputMode;\n serverBootstrap?: ServerBootstrapMode;\n serverBootstrapNonce?: string;\n serverBootstrapSrc?: string;\n serverHydration?: boolean;\n serverAwaitHydration?: boolean;\n clientBoundaryImports?: readonly string[];\n serverEscape?: ServerEscapeOptions;\n reactSuspenseRevealScriptSrc?: string;\n}\n\nexport interface ServerEscapeOptions {\n batchImportName: string;\n batchImportSource: string;\n}\n\nexport type TransformOutput = SharedTransformOutput;\nexport type Diagnostic = SharedDiagnostic;\nexport type DiagnosticSuggestion = SharedDiagnosticSuggestion;\nexport type SourceLocation = SharedSourceLocation;\nexport type ModuleMetadata = SharedModuleMetadata;\nexport type CompilerMetadata = SharedModuleMetadata[\"compiler\"];\nexport type ClientReferenceMetadata = SharedClientReferenceMetadata;\nexport type ComponentMetadata = SharedComponentMetadata;\nexport type RuntimeImport = SharedRuntimeImport;\nexport type EventHydrationManifestMetadata = SharedEventHydrationManifestMetadata;\nexport type EventHydrationEntryMetadata = SharedEventHydrationEntryMetadata;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reckona/mreact-compiler",
3
- "version": "0.0.82",
3
+ "version": "0.0.83",
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.82"
53
+ "@reckona/mreact-shared": "0.0.83"
54
54
  }
55
55
  }
@@ -0,0 +1,165 @@
1
+ export type NestedAppendEmitter<Part> = (
2
+ parts: readonly Part[],
3
+ sinkName: string,
4
+ compatRenderToStringHelperName: string,
5
+ ) => string;
6
+
7
+ export interface BoundaryLoweringContext<Part> {
8
+ compatRenderToStringHelperName: string;
9
+ emitNestedAppendStatements: NestedAppendEmitter<Part>;
10
+ sinkName: string;
11
+ }
12
+
13
+ export interface AsyncBoundaryPart<Part> {
14
+ awaitId?: string;
15
+ catchName?: string;
16
+ catchParts?: readonly Part[];
17
+ parts: readonly Part[];
18
+ valueCode: string;
19
+ valueName: string;
20
+ }
21
+
22
+ export interface OutOfOrderBoundaryPart<Part> extends AsyncBoundaryPart<Part> {
23
+ id: string;
24
+ hydration: boolean;
25
+ placeholderParts: readonly Part[];
26
+ placeholderTagCode?: string;
27
+ }
28
+
29
+ export interface ReactSuspenseBoundaryPart<Part> {
30
+ parts: readonly Part[];
31
+ }
32
+
33
+ export interface ReactSuspenseOutOfOrderBoundaryPart<Part> extends AsyncBoundaryPart<Part> {
34
+ boundaryId: string;
35
+ fallbackParts: readonly Part[];
36
+ nonce?: string;
37
+ scriptSrc?: string;
38
+ segmentId: string;
39
+ }
40
+
41
+ export function emitAsyncBoundary<Part>(
42
+ part: AsyncBoundaryPart<Part>,
43
+ context: BoundaryLoweringContext<Part> & {
44
+ asyncBoundaryHelperName: string;
45
+ },
46
+ ): string {
47
+ const optionFields: string[] = [];
48
+
49
+ if (part.catchName !== undefined && part.catchParts !== undefined) {
50
+ optionFields.push(
51
+ `catch: (${context.sinkName}, ${part.catchName}) => {\n${context.emitNestedAppendStatements(part.catchParts, context.sinkName, context.compatRenderToStringHelperName)}\n }`,
52
+ );
53
+ }
54
+
55
+ if (part.awaitId !== undefined) {
56
+ optionFields.push(`hydrationAwaitId: ${JSON.stringify(part.awaitId)}`);
57
+ }
58
+
59
+ const optionsExpression = optionFields.length === 0 ? "" : `, { ${optionFields.join(", ")} }`;
60
+
61
+ return [
62
+ ` await ${context.asyncBoundaryHelperName}(${context.sinkName}, (${part.valueCode}), async (${context.sinkName}, ${part.valueName}) => {`,
63
+ context.emitNestedAppendStatements(
64
+ part.parts,
65
+ context.sinkName,
66
+ context.compatRenderToStringHelperName,
67
+ ),
68
+ ` }${optionsExpression});`,
69
+ ].join("\n");
70
+ }
71
+
72
+ export function emitOutOfOrderBoundary<Part>(
73
+ part: OutOfOrderBoundaryPart<Part>,
74
+ context: BoundaryLoweringContext<Part> & {
75
+ outOfOrderBoundaryHelperName: string;
76
+ },
77
+ ): string {
78
+ const catchOption =
79
+ part.catchName === undefined || part.catchParts === undefined
80
+ ? ""
81
+ : `,\n catch: (${context.sinkName}, ${part.catchName}) => {\n${context.emitNestedAppendStatements(part.catchParts, context.sinkName, context.compatRenderToStringHelperName)}\n }`;
82
+
83
+ const hydrationAwaitIdOption =
84
+ part.awaitId === undefined ? "" : `,\n hydrationAwaitId: ${JSON.stringify(part.awaitId)}`;
85
+ const placeholderTagOption =
86
+ part.placeholderTagCode === undefined ? "" : `,\n placeholderTag: (${part.placeholderTagCode})`;
87
+
88
+ return [
89
+ ` ${context.outOfOrderBoundaryHelperName}(${context.sinkName}, ${JSON.stringify(part.id)}, (${part.valueCode}), async (${context.sinkName}, ${part.valueName}) => {`,
90
+ context.emitNestedAppendStatements(
91
+ part.parts,
92
+ context.sinkName,
93
+ context.compatRenderToStringHelperName,
94
+ ),
95
+ ` }, {`,
96
+ ...(part.hydration ? [` hydration: true,`] : []),
97
+ ` placeholder: (${context.sinkName}) => {`,
98
+ context.emitNestedAppendStatements(
99
+ part.placeholderParts,
100
+ context.sinkName,
101
+ context.compatRenderToStringHelperName,
102
+ ),
103
+ ` }${catchOption}${hydrationAwaitIdOption}${placeholderTagOption}`,
104
+ ` });`,
105
+ ].join("\n");
106
+ }
107
+
108
+ export function emitReactSuspenseBoundary<Part>(
109
+ part: ReactSuspenseBoundaryPart<Part>,
110
+ context: BoundaryLoweringContext<Part> & {
111
+ reactSuspenseBoundaryHelperName: string;
112
+ },
113
+ ): string {
114
+ return [
115
+ ` await ${context.reactSuspenseBoundaryHelperName}(${context.sinkName}, async (${context.sinkName}) => {`,
116
+ context.emitNestedAppendStatements(
117
+ part.parts,
118
+ context.sinkName,
119
+ context.compatRenderToStringHelperName,
120
+ ),
121
+ ` });`,
122
+ ].join("\n");
123
+ }
124
+
125
+ export function emitReactSuspenseOutOfOrderBoundary<Part>(
126
+ part: ReactSuspenseOutOfOrderBoundaryPart<Part>,
127
+ context: BoundaryLoweringContext<Part> & {
128
+ reactSuspenseOutOfOrderBoundaryHelperName: string;
129
+ },
130
+ ): string {
131
+ const options = [
132
+ ` fallback: (${context.sinkName}) => {`,
133
+ context.emitNestedAppendStatements(
134
+ part.fallbackParts,
135
+ context.sinkName,
136
+ context.compatRenderToStringHelperName,
137
+ ),
138
+ ` },`,
139
+ ...(part.catchName === undefined || part.catchParts === undefined
140
+ ? []
141
+ : [
142
+ ` catch: (${context.sinkName}, ${part.catchName}) => {`,
143
+ context.emitNestedAppendStatements(
144
+ part.catchParts,
145
+ context.sinkName,
146
+ context.compatRenderToStringHelperName,
147
+ ),
148
+ ` },`,
149
+ ]),
150
+ ...(part.nonce === undefined ? [] : [` nonce: ${JSON.stringify(part.nonce)},`]),
151
+ ...(part.scriptSrc === undefined ? [] : [` src: ${JSON.stringify(part.scriptSrc)},`]),
152
+ ];
153
+
154
+ return [
155
+ ` ${context.reactSuspenseOutOfOrderBoundaryHelperName}(${context.sinkName}, ${JSON.stringify(part.boundaryId)}, ${JSON.stringify(part.segmentId)}, (${part.valueCode}), async (${context.sinkName}, ${part.valueName}) => {`,
156
+ context.emitNestedAppendStatements(
157
+ part.parts,
158
+ context.sinkName,
159
+ context.compatRenderToStringHelperName,
160
+ ),
161
+ ` }, {`,
162
+ ...options,
163
+ ` });`,
164
+ ].join("\n");
165
+ }
@@ -0,0 +1,27 @@
1
+ export interface CodeBuilder {
2
+ section(code: string | undefined, options?: CodeBuilderSectionOptions): void;
3
+ toString(): string;
4
+ }
5
+
6
+ export interface CodeBuilderSectionOptions {
7
+ leadingBlankLines?: number;
8
+ }
9
+
10
+ export function createCodeBuilder(): CodeBuilder {
11
+ const sections: string[] = [];
12
+
13
+ return {
14
+ section(code, options = {}) {
15
+ if (code === undefined || code === "") {
16
+ return;
17
+ }
18
+
19
+ const leadingBlankLines = options.leadingBlankLines ?? 1;
20
+ const prefix = sections.length === 0 ? "" : "\n".repeat(leadingBlankLines + 1);
21
+ sections.push(`${prefix}${code}`);
22
+ },
23
+ toString() {
24
+ return sections.length === 0 ? "\n" : `${sections.join("")}\n`;
25
+ },
26
+ };
27
+ }
@@ -8,6 +8,13 @@ import type {
8
8
  } from "./ir.js";
9
9
  import type { RuntimeImport, ServerBootstrapMode, ServerEscapeOptions } from "./types.js";
10
10
  import { emitEscapeHtmlHelper } from "./emit-escape-helper.js";
11
+ import { createCodeBuilder } from "./emit-code-builder.js";
12
+ import {
13
+ emitAsyncBoundary as emitLoweredAsyncBoundary,
14
+ emitOutOfOrderBoundary as emitLoweredOutOfOrderBoundary,
15
+ emitReactSuspenseBoundary as emitLoweredReactSuspenseBoundary,
16
+ emitReactSuspenseOutOfOrderBoundary as emitLoweredReactSuspenseOutOfOrderBoundary,
17
+ } from "./emit-boundary-lowering.js";
11
18
  import { escapeHtmlAttribute as escapeHtml } from "@reckona/mreact-shared/html-escape";
12
19
  import {
13
20
  htmlAttributeName,
@@ -160,22 +167,28 @@ export function emitServerStream(
160
167
  const importsBlock = [importLine, escapeImport, userImports, moduleStatements].filter(Boolean).join("\n");
161
168
  const needsSpreadAttributesHelper = components.includes(spreadAttributesHelperName);
162
169
  const urlSafeBlock =
163
- components.includes(urlSafeHelperName) || needsSpreadAttributesHelper
164
- ? `\n\n${urlSafeHelper}`
165
- : "";
170
+ components.includes(urlSafeHelperName) || needsSpreadAttributesHelper ? urlSafeHelper : "";
166
171
  const clientBoundaryBlock =
167
172
  clientBoundaryHelperName === undefined || !components.includes(clientBoundaryHelperName)
168
173
  ? ""
169
- : `\n\n${emitClientBoundaryHelper(clientBoundaryHelperName)}`;
174
+ : emitClientBoundaryHelper(clientBoundaryHelperName);
170
175
  const spreadAttributesBlock = needsSpreadAttributesHelper
171
- ? `\n\n${emitSpreadAttributesHelper(spreadAttributesHelperName, escapeHelperName, urlSafeHelperName)}`
176
+ ? emitSpreadAttributesHelper(spreadAttributesHelperName, escapeHelperName, urlSafeHelperName)
172
177
  : "";
173
178
  const streamNodeBlock = components.includes(streamNodeHelperName)
174
- ? `\n\n${emitStreamNodeHelper(streamNodeHelperName)}`
179
+ ? emitStreamNodeHelper(streamNodeHelperName)
175
180
  : "";
181
+ const code = createCodeBuilder();
182
+ code.section(importsBlock);
183
+ code.section(helper);
184
+ code.section(urlSafeBlock);
185
+ code.section(clientBoundaryBlock);
186
+ code.section(spreadAttributesBlock);
187
+ code.section(streamNodeBlock);
188
+ code.section(components);
176
189
 
177
190
  return {
178
- code: `${importsBlock === "" ? "" : `${importsBlock}\n\n`}${helper}${urlSafeBlock}${clientBoundaryBlock}${spreadAttributesBlock}${streamNodeBlock}\n\n${components}\n`,
191
+ code: code.toString(),
179
192
  imports,
180
193
  };
181
194
  }
@@ -532,39 +545,39 @@ function emitAppendStatements(
532
545
  try {
533
546
  return coalesceAdjacentStaticParts(collected).map((part) => {
534
547
  if (part.kind === "async-boundary") {
535
- return emitAsyncBoundary(
536
- part,
537
- sinkName,
548
+ return emitLoweredAsyncBoundary(part, {
538
549
  asyncBoundaryHelperName,
539
550
  compatRenderToStringHelperName,
540
- );
551
+ emitNestedAppendStatements,
552
+ sinkName,
553
+ });
541
554
  }
542
555
 
543
556
  if (part.kind === "out-of-order-boundary") {
544
- return emitOutOfOrderBoundary(
545
- part,
546
- sinkName,
547
- outOfOrderBoundaryHelperName,
557
+ return emitLoweredOutOfOrderBoundary(part, {
548
558
  compatRenderToStringHelperName,
549
- );
559
+ emitNestedAppendStatements,
560
+ outOfOrderBoundaryHelperName,
561
+ sinkName,
562
+ });
550
563
  }
551
564
 
552
565
  if (part.kind === "react-suspense-boundary") {
553
- return emitReactSuspenseBoundary(
554
- part,
555
- sinkName,
556
- reactSuspenseBoundaryHelperName,
566
+ return emitLoweredReactSuspenseBoundary(part, {
557
567
  compatRenderToStringHelperName,
558
- );
568
+ emitNestedAppendStatements,
569
+ reactSuspenseBoundaryHelperName,
570
+ sinkName,
571
+ });
559
572
  }
560
573
 
561
574
  if (part.kind === "react-suspense-out-of-order-boundary") {
562
- return emitReactSuspenseOutOfOrderBoundary(
563
- part,
564
- sinkName,
565
- reactSuspenseOutOfOrderBoundaryHelperName,
575
+ return emitLoweredReactSuspenseOutOfOrderBoundary(part, {
566
576
  compatRenderToStringHelperName,
567
- );
577
+ emitNestedAppendStatements,
578
+ reactSuspenseOutOfOrderBoundaryHelperName,
579
+ sinkName,
580
+ });
568
581
  }
569
582
 
570
583
  if (part.kind === "component") {
@@ -852,116 +865,12 @@ function emitListPartAsStringExpression(
852
865
  return `(() => { const _arr = (${part.itemsCode}); let _listOut = ""; for (let _i = 0, _len = _arr.length; _i < _len; _i++) { const ${part.itemName} = _arr[_i];${part.indexName === undefined ? "" : ` const ${part.indexName} = _i;`}${part.arrayName === undefined ? "" : ` const ${part.arrayName} = _arr;`}${part.bodyStatements.length === 0 ? "" : ` ${part.bodyStatements.join(" ")}`} ${concatLines.join(" ")} } return _listOut; })()`;
853
866
  }
854
867
 
855
- function emitAsyncBoundary(
856
- part: Extract<HtmlPart, { kind: "async-boundary" }>,
857
- sinkName: string,
858
- asyncBoundaryHelperName: string,
859
- compatRenderToStringHelperName: string,
860
- ): string {
861
- const optionFields: string[] = [];
862
-
863
- if (part.catchName !== undefined && part.catchParts !== undefined) {
864
- optionFields.push(
865
- `catch: (${sinkName}, ${part.catchName}) => {\n${emitNestedAppendStatements(part.catchParts, sinkName, compatRenderToStringHelperName)}\n }`,
866
- );
867
- }
868
-
869
- if (part.awaitId !== undefined) {
870
- optionFields.push(`hydrationAwaitId: ${JSON.stringify(part.awaitId)}`);
871
- }
872
-
873
- const optionsExpression = optionFields.length === 0
874
- ? ""
875
- : `, { ${optionFields.join(", ")} }`;
876
-
877
- return [
878
- ` await ${asyncBoundaryHelperName}(${sinkName}, (${part.valueCode}), async (${sinkName}, ${part.valueName}) => {`,
879
- emitNestedAppendStatements(part.parts, sinkName, compatRenderToStringHelperName),
880
- ` }${optionsExpression});`,
881
- ].join("\n");
882
- }
883
-
884
- function emitOutOfOrderBoundary(
885
- part: Extract<HtmlPart, { kind: "out-of-order-boundary" }>,
886
- sinkName: string,
887
- outOfOrderBoundaryHelperName: string,
888
- compatRenderToStringHelperName: string,
889
- ): string {
890
- const catchOption =
891
- part.catchName === undefined || part.catchParts === undefined
892
- ? ""
893
- : `,\n catch: (${sinkName}, ${part.catchName}) => {\n${emitNestedAppendStatements(part.catchParts, sinkName, compatRenderToStringHelperName)}\n }`;
894
-
895
- const hydrationAwaitIdOption =
896
- part.awaitId === undefined
897
- ? ""
898
- : `,\n hydrationAwaitId: ${JSON.stringify(part.awaitId)}`;
899
- const placeholderTagOption =
900
- part.placeholderTagCode === undefined
901
- ? ""
902
- : `,\n placeholderTag: (${part.placeholderTagCode})`;
903
-
904
- return [
905
- ` ${outOfOrderBoundaryHelperName}(${sinkName}, ${JSON.stringify(part.id)}, (${part.valueCode}), async (${sinkName}, ${part.valueName}) => {`,
906
- emitNestedAppendStatements(part.parts, sinkName, compatRenderToStringHelperName),
907
- ` }, {`,
908
- ...(part.hydration ? [` hydration: true,`] : []),
909
- ` placeholder: (${sinkName}) => {`,
910
- emitNestedAppendStatements(part.placeholderParts, sinkName, compatRenderToStringHelperName),
911
- ` }${catchOption}${hydrationAwaitIdOption}${placeholderTagOption}`,
912
- ` });`,
913
- ].join("\n");
914
- }
915
-
916
- function emitReactSuspenseBoundary(
917
- part: Extract<HtmlPart, { kind: "react-suspense-boundary" }>,
918
- sinkName: string,
919
- reactSuspenseBoundaryHelperName: string,
920
- compatRenderToStringHelperName: string,
921
- ): string {
922
- return [
923
- ` await ${reactSuspenseBoundaryHelperName}(${sinkName}, async (${sinkName}) => {`,
924
- emitNestedAppendStatements(part.parts, sinkName, compatRenderToStringHelperName),
925
- ` });`,
926
- ].join("\n");
927
- }
928
-
929
- function emitReactSuspenseOutOfOrderBoundary(
930
- part: Extract<HtmlPart, { kind: "react-suspense-out-of-order-boundary" }>,
931
- sinkName: string,
932
- reactSuspenseOutOfOrderBoundaryHelperName: string,
933
- compatRenderToStringHelperName: string,
934
- ): string {
935
- const options = [
936
- ` fallback: (${sinkName}) => {`,
937
- emitNestedAppendStatements(part.fallbackParts, sinkName, compatRenderToStringHelperName),
938
- ` },`,
939
- ...(part.catchName === undefined || part.catchParts === undefined
940
- ? []
941
- : [
942
- ` catch: (${sinkName}, ${part.catchName}) => {`,
943
- emitNestedAppendStatements(part.catchParts, sinkName, compatRenderToStringHelperName),
944
- ` },`,
945
- ]),
946
- ...(part.nonce === undefined ? [] : [` nonce: ${stringLiteral(part.nonce)},`]),
947
- ...(part.scriptSrc === undefined ? [] : [` src: ${stringLiteral(part.scriptSrc)},`]),
948
- ];
949
-
950
- return [
951
- ` ${reactSuspenseOutOfOrderBoundaryHelperName}(${sinkName}, ${JSON.stringify(part.boundaryId)}, ${JSON.stringify(part.segmentId)}, (${part.valueCode}), async (${sinkName}, ${part.valueName}) => {`,
952
- emitNestedAppendStatements(part.parts, sinkName, compatRenderToStringHelperName),
953
- ` }, {`,
954
- ...options,
955
- ` });`,
956
- ].join("\n");
957
- }
958
-
959
868
  function emitNestedAppendStatements(
960
- parts: HtmlSyncPart[],
869
+ parts: readonly HtmlSyncPart[],
961
870
  sinkName: string,
962
871
  compatRenderToStringHelperName: string,
963
872
  ): string {
964
- return coalesceAdjacentStaticParts(parts)
873
+ return coalesceAdjacentStaticParts([...parts])
965
874
  .map((part) => emitSyncPartAsAppendStatement(part, sinkName, compatRenderToStringHelperName, " "))
966
875
  .join("\n");
967
876
  }
@@ -974,39 +883,39 @@ function emitNestedStreamAppendStatements(
974
883
  return coalesceAdjacentStaticParts(parts)
975
884
  .map((part) => {
976
885
  if (part.kind === "async-boundary") {
977
- return emitAsyncBoundary(
978
- part,
979
- sinkName,
980
- currentAsyncBoundaryHelperName,
886
+ return emitLoweredAsyncBoundary(part, {
887
+ asyncBoundaryHelperName: currentAsyncBoundaryHelperName,
981
888
  compatRenderToStringHelperName,
982
- ).replace(/^/gm, " ");
889
+ emitNestedAppendStatements,
890
+ sinkName,
891
+ }).replace(/^/gm, " ");
983
892
  }
984
893
 
985
894
  if (part.kind === "out-of-order-boundary") {
986
- return emitOutOfOrderBoundary(
987
- part,
988
- sinkName,
989
- currentOutOfOrderBoundaryHelperName,
895
+ return emitLoweredOutOfOrderBoundary(part, {
990
896
  compatRenderToStringHelperName,
991
- ).replace(/^/gm, " ");
897
+ emitNestedAppendStatements,
898
+ outOfOrderBoundaryHelperName: currentOutOfOrderBoundaryHelperName,
899
+ sinkName,
900
+ }).replace(/^/gm, " ");
992
901
  }
993
902
 
994
903
  if (part.kind === "react-suspense-boundary") {
995
- return emitReactSuspenseBoundary(
996
- part,
997
- sinkName,
998
- currentReactSuspenseBoundaryHelperName,
904
+ return emitLoweredReactSuspenseBoundary(part, {
999
905
  compatRenderToStringHelperName,
1000
- ).replace(/^/gm, " ");
906
+ emitNestedAppendStatements,
907
+ reactSuspenseBoundaryHelperName: currentReactSuspenseBoundaryHelperName,
908
+ sinkName,
909
+ }).replace(/^/gm, " ");
1001
910
  }
1002
911
 
1003
912
  if (part.kind === "react-suspense-out-of-order-boundary") {
1004
- return emitReactSuspenseOutOfOrderBoundary(
1005
- part,
1006
- sinkName,
1007
- currentReactSuspenseOutOfOrderBoundaryHelperName,
913
+ return emitLoweredReactSuspenseOutOfOrderBoundary(part, {
1008
914
  compatRenderToStringHelperName,
1009
- ).replace(/^/gm, " ");
915
+ emitNestedAppendStatements,
916
+ reactSuspenseOutOfOrderBoundaryHelperName: currentReactSuspenseOutOfOrderBoundaryHelperName,
917
+ sinkName,
918
+ }).replace(/^/gm, " ");
1010
919
  }
1011
920
 
1012
921
  return emitSyncPartAsAppendStatement(
@@ -7,6 +7,7 @@ import type {
7
7
  } from "./ir.js";
8
8
  import type { RuntimeImport, ServerEscapeOptions } from "./types.js";
9
9
  import { emitEscapeHtmlHelper } from "./emit-escape-helper.js";
10
+ import { createCodeBuilder } from "./emit-code-builder.js";
10
11
  import { escapeHtmlAttribute as escapeHtml } from "@reckona/mreact-shared/html-escape";
11
12
  import {
12
13
  htmlAttributeName,
@@ -131,9 +132,19 @@ export function emitServer(
131
132
  reactNodeRenderHelperName,
132
133
  );
133
134
  const moduleStatements = emitModuleStatements(ir);
135
+ const code = createCodeBuilder();
136
+ code.section(userImports);
137
+ code.section(escapeImport);
138
+ code.section(contextImport);
139
+ code.section(moduleStatements);
140
+ code.section(helper);
141
+ code.section(urlSafeBlock);
142
+ code.section(clientBoundaryBlock);
143
+ code.section(spreadAttributesBlock);
144
+ code.section(components);
134
145
 
135
146
  return {
136
- code: `${[userImports, escapeImport, contextImport, moduleStatements, helper, urlSafeBlock, clientBoundaryBlock, spreadAttributesBlock].filter(Boolean).join("\n\n")}\n\n${components}\n`,
147
+ code: code.toString(),
137
148
  imports: collectContextImports(
138
149
  contextProviderHelperName,
139
150
  contextConsumerHelperName,