@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/emit-boundary-lowering.d.ts +43 -0
- package/dist/emit-boundary-lowering.d.ts.map +1 -0
- package/dist/emit-boundary-lowering.js +63 -0
- package/dist/emit-boundary-lowering.js.map +1 -0
- package/dist/emit-code-builder.d.ts +9 -0
- package/dist/emit-code-builder.d.ts.map +1 -0
- package/dist/emit-code-builder.js +17 -0
- package/dist/emit-code-builder.js.map +1 -0
- package/dist/emit-server-stream.d.ts.map +1 -1
- package/dist/emit-server-stream.js +64 -84
- package/dist/emit-server-stream.js.map +1 -1
- package/dist/emit-server.d.ts.map +1 -1
- package/dist/emit-server.js +12 -1
- package/dist/emit-server.js.map +1 -1
- package/dist/types.d.ts +16 -69
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/src/emit-boundary-lowering.ts +165 -0
- package/src/emit-code-builder.ts +27 -0
- package/src/emit-server-stream.ts +61 -152
- package/src/emit-server.ts +12 -1
- package/src/types.ts +32 -79
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
export type
|
|
3
|
-
export type
|
|
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 =
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
export
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,IAAI,6BAA6B,EACxD,aAAa,IAAI,mBAAmB,EACpC,gBAAgB,IAAI,sBAAsB,EAC1C,iBAAiB,IAAI,uBAAuB,EAC5C,UAAU,IAAI,gBAAgB,EAC9B,oBAAoB,IAAI,0BAA0B,EAClD,2BAA2B,IAAI,iCAAiC,EAChE,8BAA8B,IAAI,oCAAoC,EACtE,cAAc,IAAI,oBAAoB,EACtC,aAAa,IAAI,mBAAmB,EACpC,mBAAmB,IAAI,yBAAyB,EAChD,gBAAgB,IAAI,sBAAsB,EAC1C,cAAc,IAAI,oBAAoB,EACtC,eAAe,IAAI,qBAAqB,EACzC,MAAM,0CAA0C,CAAC;AAElD,MAAM,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAChD,MAAM,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,yBAAyB,CAAC;AAC5D,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC;AAC/B,MAAM,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAEtD,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,eAAe,GAAG,eAAe,GAAG,aAAa,CAAC;AAElG,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,YAAY,GAAG,eAAe,GAAG,eAAe,CAAC;IAC/D,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,qBAAqB,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC;IAC/C,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,+BAA+B,CAAC,EAAE,YAAY,CAAC;CAChD;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;IACtC,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,eAAe,GAAG,qBAAqB,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,gBAAgB,CAAC;AAC1C,MAAM,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAC9D,MAAM,MAAM,cAAc,GAAG,oBAAoB,CAAC;AAClD,MAAM,MAAM,cAAc,GAAG,oBAAoB,CAAC;AAClD,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;AAChE,MAAM,MAAM,uBAAuB,GAAG,6BAA6B,CAAC;AACpE,MAAM,MAAM,iBAAiB,GAAG,uBAAuB,CAAC;AACxD,MAAM,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAChD,MAAM,MAAM,8BAA8B,GAAG,oCAAoC,CAAC;AAClF,MAAM,MAAM,2BAA2B,GAAG,iCAAiC,CAAC"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["
|
|
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.
|
|
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.
|
|
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
|
-
:
|
|
174
|
+
: emitClientBoundaryHelper(clientBoundaryHelperName);
|
|
170
175
|
const spreadAttributesBlock = needsSpreadAttributesHelper
|
|
171
|
-
?
|
|
176
|
+
? emitSpreadAttributesHelper(spreadAttributesHelperName, escapeHelperName, urlSafeHelperName)
|
|
172
177
|
: "";
|
|
173
178
|
const streamNodeBlock = components.includes(streamNodeHelperName)
|
|
174
|
-
?
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
978
|
-
|
|
979
|
-
sinkName,
|
|
980
|
-
currentAsyncBoundaryHelperName,
|
|
886
|
+
return emitLoweredAsyncBoundary(part, {
|
|
887
|
+
asyncBoundaryHelperName: currentAsyncBoundaryHelperName,
|
|
981
888
|
compatRenderToStringHelperName,
|
|
982
|
-
|
|
889
|
+
emitNestedAppendStatements,
|
|
890
|
+
sinkName,
|
|
891
|
+
}).replace(/^/gm, " ");
|
|
983
892
|
}
|
|
984
893
|
|
|
985
894
|
if (part.kind === "out-of-order-boundary") {
|
|
986
|
-
return
|
|
987
|
-
part,
|
|
988
|
-
sinkName,
|
|
989
|
-
currentOutOfOrderBoundaryHelperName,
|
|
895
|
+
return emitLoweredOutOfOrderBoundary(part, {
|
|
990
896
|
compatRenderToStringHelperName,
|
|
991
|
-
|
|
897
|
+
emitNestedAppendStatements,
|
|
898
|
+
outOfOrderBoundaryHelperName: currentOutOfOrderBoundaryHelperName,
|
|
899
|
+
sinkName,
|
|
900
|
+
}).replace(/^/gm, " ");
|
|
992
901
|
}
|
|
993
902
|
|
|
994
903
|
if (part.kind === "react-suspense-boundary") {
|
|
995
|
-
return
|
|
996
|
-
part,
|
|
997
|
-
sinkName,
|
|
998
|
-
currentReactSuspenseBoundaryHelperName,
|
|
904
|
+
return emitLoweredReactSuspenseBoundary(part, {
|
|
999
905
|
compatRenderToStringHelperName,
|
|
1000
|
-
|
|
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
|
|
1005
|
-
part,
|
|
1006
|
-
sinkName,
|
|
1007
|
-
currentReactSuspenseOutOfOrderBoundaryHelperName,
|
|
913
|
+
return emitLoweredReactSuspenseOutOfOrderBoundary(part, {
|
|
1008
914
|
compatRenderToStringHelperName,
|
|
1009
|
-
|
|
915
|
+
emitNestedAppendStatements,
|
|
916
|
+
reactSuspenseOutOfOrderBoundaryHelperName: currentReactSuspenseOutOfOrderBoundaryHelperName,
|
|
917
|
+
sinkName,
|
|
918
|
+
}).replace(/^/gm, " ");
|
|
1010
919
|
}
|
|
1011
920
|
|
|
1012
921
|
return emitSyncPartAsAppendStatement(
|
package/src/emit-server.ts
CHANGED
|
@@ -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:
|
|
147
|
+
code: code.toString(),
|
|
137
148
|
imports: collectContextImports(
|
|
138
149
|
contextProviderHelperName,
|
|
139
150
|
contextConsumerHelperName,
|