@backtickjs/bundler 0.1.7 → 0.1.8
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/bundle/buildBundle.js +18 -46
- package/dist/bundle/buildBundle.js.map +1 -1
- package/dist/bundle/expandServerComponents.d.ts +6 -0
- package/dist/bundle/expandServerComponents.js +62 -0
- package/dist/bundle/expandServerComponents.js.map +1 -0
- package/package.json +2 -2
- package/src/bundle/buildBundle.ts +21 -58
- package/src/bundle/expandServerComponents.ts +79 -0
- package/dist/bundle/expandJsxElement.d.ts +0 -2
- package/dist/bundle/expandJsxElement.js +0 -8
- package/dist/bundle/expandJsxElement.js.map +0 -1
- package/src/bundle/expandJsxElement.ts +0 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isClientImport, isClientScript, isJsxElement, } from "@backtickjs/core";
|
|
2
|
-
import {
|
|
2
|
+
import { expandServerComponents } from "./expandServerComponents.js";
|
|
3
3
|
import { bindingsOf, capturesOf } from "./params.js";
|
|
4
4
|
import { sourceName } from "./bindingKey.js";
|
|
5
5
|
import { array, arrow, call, createNames, imported, literal, object, } from "../print/code.js";
|
|
@@ -100,9 +100,9 @@ export async function buildBundle(value, packageVersions) {
|
|
|
100
100
|
// `write` renders a closure's code in a scope that records what it reads:
|
|
101
101
|
// a constant's label if it read nothing of `scope` beyond `own`, its
|
|
102
102
|
// parameters, or else the code, written where it's used.
|
|
103
|
-
const closure =
|
|
103
|
+
const closure = (scope, own, write, name) => {
|
|
104
104
|
const read = new Set();
|
|
105
|
-
const code =
|
|
105
|
+
const code = write({
|
|
106
106
|
bindings: new Set([...scope.bindings, ...own]),
|
|
107
107
|
read,
|
|
108
108
|
});
|
|
@@ -123,38 +123,17 @@ export async function buildBundle(value, packageVersions) {
|
|
|
123
123
|
// a bundle is. A script reference is a call naming which script and
|
|
124
124
|
// what to hand it; everything else is its literal form. Rendered in order,
|
|
125
125
|
// one value after the other, so the table follows the order rendering first
|
|
126
|
-
// reached each script.
|
|
127
|
-
|
|
128
|
-
// itself, which written out would never end. A value used in two places
|
|
129
|
-
// isn't one: it's left before it's met again.
|
|
130
|
-
const path = new Set();
|
|
131
|
-
const render = async (value, scope = rootScope()) => {
|
|
132
|
-
if (typeof value !== "object" || value === null) {
|
|
133
|
-
return renderValue(value, scope);
|
|
134
|
-
}
|
|
135
|
-
if (path.has(value)) {
|
|
136
|
-
throw new Error("Can't splice a value that contains itself: a bundle writes each " +
|
|
137
|
-
"value out in full, so a cycle never ends. Break the cycle before " +
|
|
138
|
-
"splicing it.");
|
|
139
|
-
}
|
|
140
|
-
path.add(value);
|
|
141
|
-
try {
|
|
142
|
-
return await renderValue(value, scope);
|
|
143
|
-
}
|
|
144
|
-
finally {
|
|
145
|
-
path.delete(value);
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
const renderValue = async (value, scope) => {
|
|
126
|
+
// reached each script. Expansion has refused cycles, so it ends.
|
|
127
|
+
const render = (value, scope = rootScope()) => {
|
|
149
128
|
if (isClientScript(value)) {
|
|
150
129
|
const target = scriptFor(value);
|
|
151
130
|
if (target.module.kind !== "function") {
|
|
152
|
-
return call(labelOf(target),
|
|
131
|
+
return call(labelOf(target), exprCallArgs(value, scope));
|
|
153
132
|
}
|
|
154
|
-
return closure(scope, [],
|
|
133
|
+
return closure(scope, [], (inner) => call(labelOf(target), exprCallArgs(value, inner)), "$function");
|
|
155
134
|
}
|
|
156
135
|
if (isJsxElement(value)) {
|
|
157
|
-
return renderJsx(value
|
|
136
|
+
return renderJsx(value);
|
|
158
137
|
}
|
|
159
138
|
if (isClientImport(value)) {
|
|
160
139
|
return imported(names, value);
|
|
@@ -170,7 +149,7 @@ export async function buildBundle(value, packageVersions) {
|
|
|
170
149
|
if (Array.isArray(value)) {
|
|
171
150
|
const elements = [];
|
|
172
151
|
for (const element of value) {
|
|
173
|
-
elements.push(
|
|
152
|
+
elements.push(render(element, scope));
|
|
174
153
|
}
|
|
175
154
|
return array(elements);
|
|
176
155
|
}
|
|
@@ -205,7 +184,7 @@ export async function buildBundle(value, packageVersions) {
|
|
|
205
184
|
}
|
|
206
185
|
const entries = [];
|
|
207
186
|
for (const [key, entry] of Object.entries(value)) {
|
|
208
|
-
entries.push([key,
|
|
187
|
+
entries.push([key, render(entry, scope)]);
|
|
209
188
|
}
|
|
210
189
|
return object(entries);
|
|
211
190
|
};
|
|
@@ -228,7 +207,7 @@ export async function buildBundle(value, packageVersions) {
|
|
|
228
207
|
};
|
|
229
208
|
// The arguments of a call of a script: a thunk per splice, then its
|
|
230
209
|
// captures.
|
|
231
|
-
const exprCallArgs =
|
|
210
|
+
const exprCallArgs = (ref, scope) => {
|
|
232
211
|
const target = scriptFor(ref);
|
|
233
212
|
const parts = [];
|
|
234
213
|
// The splices lead the parameters, one `arg` each.
|
|
@@ -238,25 +217,17 @@ export async function buildBundle(value, packageVersions) {
|
|
|
238
217
|
// nested inside it.
|
|
239
218
|
const passed = [...passKeys(target, index), ...capturesOf(target)];
|
|
240
219
|
// A thunk taking them, the splice rendered inside it.
|
|
241
|
-
parts.push(
|
|
220
|
+
parts.push(closure(scope, passed, (inner) => arrow(passed.map(displayName), render(arg, inner)), "$thunk"));
|
|
242
221
|
}
|
|
243
222
|
for (const key of capturesOf(target)) {
|
|
244
223
|
parts.push(capExpr(key, scope));
|
|
245
224
|
}
|
|
246
225
|
return parts;
|
|
247
226
|
};
|
|
248
|
-
// A tag
|
|
249
|
-
//
|
|
250
|
-
|
|
251
|
-
//
|
|
252
|
-
// A prop that is `undefined` is left out, as JSX and TypeScript's optional
|
|
253
|
-
// props read it: a component forwarding an optional prop it wasn't given
|
|
254
|
-
// writes nothing.
|
|
255
|
-
const renderJsx = async (jsx, scope) => {
|
|
227
|
+
// A tag left after expansion, which ran every server component's: one the
|
|
228
|
+
// client draws.
|
|
229
|
+
const renderJsx = (jsx) => {
|
|
256
230
|
const type = jsx.type;
|
|
257
|
-
if (typeof type === "function" && !isClientImport(type)) {
|
|
258
|
-
return render(await expandJsxElement(jsx, type), scope);
|
|
259
|
-
}
|
|
260
231
|
// An element and a client component (an import, or a script answering
|
|
261
232
|
// one) are client code, so on the host they can't be tags: they are tags
|
|
262
233
|
// in a script.
|
|
@@ -268,8 +239,9 @@ export async function buildBundle(value, packageVersions) {
|
|
|
268
239
|
throw new Error(`${tag} is a client component, so it can't be a tag on the host. ` +
|
|
269
240
|
"Use it as a tag in a script.");
|
|
270
241
|
};
|
|
271
|
-
//
|
|
272
|
-
|
|
242
|
+
// Every server component first, so siblings run at once; then the drawing,
|
|
243
|
+
// in order. Nothing encloses the root, so nothing it holds can capture.
|
|
244
|
+
const root = render(await expandServerComponents(value));
|
|
273
245
|
// In table order, which is the order rendering first reached each script.
|
|
274
246
|
const modules = [...numbers.keys()].map((script) => [labelOf(script), script.module]);
|
|
275
247
|
return { modules, constants, root, names };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildBundle.js","sourceRoot":"","sources":["../../src/bundle/buildBundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,cAAc,EACd,cAAc,EACd,YAAY,GAEb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"buildBundle.js","sourceRoot":"","sources":["../../src/bundle/buildBundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { isClientImport, isClientScript, isJsxElement } from "@backtickjs/core";
|
|
2
|
+
const CYCLE_ERROR = "Can't splice a value that contains itself: a bundle writes each value " +
|
|
3
|
+
"out in full, so a cycle never ends. Break the cycle before splicing it.";
|
|
4
|
+
const contains = (ancestors, value) => {
|
|
5
|
+
for (let at = ancestors; at !== null; at = at.parent) {
|
|
6
|
+
if (at.value === value) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return false;
|
|
11
|
+
};
|
|
12
|
+
// Runs every server component in a value and answers with the value as drawn:
|
|
13
|
+
// each element of one replaced by what its component drew, expanded in turn.
|
|
14
|
+
// Siblings expand at once, so two components awaiting data wait together.
|
|
15
|
+
//
|
|
16
|
+
// A component runs each time its element is drawn, as React renders an element
|
|
17
|
+
// each place it stands: the component itself never leaves the host, and only
|
|
18
|
+
// the client code it bottoms out in reaches the bundle. A value holding no
|
|
19
|
+
// server component comes back as the same object.
|
|
20
|
+
export async function expandServerComponents(value, ancestors = null) {
|
|
21
|
+
if (typeof value !== "object" || value === null) {
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
if (contains(ancestors, value)) {
|
|
25
|
+
throw new Error(CYCLE_ERROR);
|
|
26
|
+
}
|
|
27
|
+
const inside = { value, parent: ancestors };
|
|
28
|
+
const all = (values) => Promise.all(values.map((entry) => expandServerComponents(entry, inside)));
|
|
29
|
+
if (isJsxElement(value)) {
|
|
30
|
+
const { type } = value;
|
|
31
|
+
// A tag the client draws is left for rendering to refuse.
|
|
32
|
+
if (typeof type !== "function" || isClientImport(type)) {
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
return expandServerComponents(await type(value.props), inside);
|
|
36
|
+
}
|
|
37
|
+
if (isClientScript(value)) {
|
|
38
|
+
const args = await all(value.args);
|
|
39
|
+
return args.every((arg, index) => arg === value.args[index])
|
|
40
|
+
? value
|
|
41
|
+
: { ...value, args };
|
|
42
|
+
}
|
|
43
|
+
if (Array.isArray(value)) {
|
|
44
|
+
const elements = await all(value);
|
|
45
|
+
return elements.every((element, index) => element === value[index])
|
|
46
|
+
? value
|
|
47
|
+
: elements;
|
|
48
|
+
}
|
|
49
|
+
// Only plain objects cross; rendering refuses anything else.
|
|
50
|
+
const prototype = Object.getPrototypeOf(value);
|
|
51
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
const entries = Object.entries(value);
|
|
55
|
+
const expanded = await all(entries.map(([, entry]) => entry));
|
|
56
|
+
if (expanded.every((entry, index) => entry === entries[index][1])) {
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
// Defined, not assigned, so a `__proto__` key stays a key.
|
|
60
|
+
return Object.fromEntries(entries.map(([key], index) => [key, expanded[index]]));
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=expandServerComponents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expandServerComponents.js","sourceRoot":"","sources":["../../src/bundle/expandServerComponents.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtickjs/bundler",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Runs Backtick server components and bundles a screen per request: one JavaScript file for the client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"backtick",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"semver": "^7.8.1",
|
|
43
|
-
"@backtickjs/core": "0.1.
|
|
43
|
+
"@backtickjs/core": "0.1.8"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/semver": "^7.8.0",
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type JsxElement,
|
|
8
8
|
} from "@backtickjs/core";
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { expandServerComponents } from "./expandServerComponents.js";
|
|
11
11
|
import { bindingsOf, capturesOf } from "./params.js";
|
|
12
12
|
import { sourceName } from "./bindingKey.js";
|
|
13
13
|
import {
|
|
@@ -150,14 +150,14 @@ export async function buildBundle(
|
|
|
150
150
|
// `write` renders a closure's code in a scope that records what it reads:
|
|
151
151
|
// a constant's label if it read nothing of `scope` beyond `own`, its
|
|
152
152
|
// parameters, or else the code, written where it's used.
|
|
153
|
-
const closure =
|
|
153
|
+
const closure = (
|
|
154
154
|
scope: Scope,
|
|
155
155
|
own: readonly string[],
|
|
156
|
-
write: (inner: Scope) =>
|
|
156
|
+
write: (inner: Scope) => string,
|
|
157
157
|
name: string,
|
|
158
|
-
):
|
|
158
|
+
): string => {
|
|
159
159
|
const read = new Set<string>();
|
|
160
|
-
const code =
|
|
160
|
+
const code = write({
|
|
161
161
|
bindings: new Set([...scope.bindings, ...own]),
|
|
162
162
|
read,
|
|
163
163
|
});
|
|
@@ -181,48 +181,22 @@ export async function buildBundle(
|
|
|
181
181
|
// a bundle is. A script reference is a call naming which script and
|
|
182
182
|
// what to hand it; everything else is its literal form. Rendered in order,
|
|
183
183
|
// one value after the other, so the table follows the order rendering first
|
|
184
|
-
// reached each script.
|
|
185
|
-
|
|
186
|
-
// itself, which written out would never end. A value used in two places
|
|
187
|
-
// isn't one: it's left before it's met again.
|
|
188
|
-
const path = new Set<object>();
|
|
189
|
-
const render = async (
|
|
190
|
-
value: unknown,
|
|
191
|
-
scope: Scope = rootScope(),
|
|
192
|
-
): Promise<string> => {
|
|
193
|
-
if (typeof value !== "object" || value === null) {
|
|
194
|
-
return renderValue(value, scope);
|
|
195
|
-
}
|
|
196
|
-
if (path.has(value)) {
|
|
197
|
-
throw new Error(
|
|
198
|
-
"Can't splice a value that contains itself: a bundle writes each " +
|
|
199
|
-
"value out in full, so a cycle never ends. Break the cycle before " +
|
|
200
|
-
"splicing it.",
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
path.add(value);
|
|
204
|
-
try {
|
|
205
|
-
return await renderValue(value, scope);
|
|
206
|
-
} finally {
|
|
207
|
-
path.delete(value);
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
const renderValue = async (value: unknown, scope: Scope): Promise<string> => {
|
|
184
|
+
// reached each script. Expansion has refused cycles, so it ends.
|
|
185
|
+
const render = (value: unknown, scope: Scope = rootScope()): string => {
|
|
211
186
|
if (isClientScript(value)) {
|
|
212
187
|
const target = scriptFor(value);
|
|
213
188
|
if (target.module.kind !== "function") {
|
|
214
|
-
return call(labelOf(target),
|
|
189
|
+
return call(labelOf(target), exprCallArgs(value, scope));
|
|
215
190
|
}
|
|
216
191
|
return closure(
|
|
217
192
|
scope,
|
|
218
193
|
[],
|
|
219
|
-
|
|
220
|
-
call(labelOf(target), await exprCallArgs(value, inner)),
|
|
194
|
+
(inner) => call(labelOf(target), exprCallArgs(value, inner)),
|
|
221
195
|
"$function",
|
|
222
196
|
);
|
|
223
197
|
}
|
|
224
198
|
if (isJsxElement(value)) {
|
|
225
|
-
return renderJsx(value
|
|
199
|
+
return renderJsx(value);
|
|
226
200
|
}
|
|
227
201
|
if (isClientImport(value)) {
|
|
228
202
|
return imported(names, value);
|
|
@@ -240,7 +214,7 @@ export async function buildBundle(
|
|
|
240
214
|
if (Array.isArray(value)) {
|
|
241
215
|
const elements: string[] = [];
|
|
242
216
|
for (const element of value) {
|
|
243
|
-
elements.push(
|
|
217
|
+
elements.push(render(element, scope));
|
|
244
218
|
}
|
|
245
219
|
return array(elements);
|
|
246
220
|
}
|
|
@@ -281,7 +255,7 @@ export async function buildBundle(
|
|
|
281
255
|
}
|
|
282
256
|
const entries: [string, string][] = [];
|
|
283
257
|
for (const [key, entry] of Object.entries(value)) {
|
|
284
|
-
entries.push([key,
|
|
258
|
+
entries.push([key, render(entry, scope)]);
|
|
285
259
|
}
|
|
286
260
|
return object(entries);
|
|
287
261
|
};
|
|
@@ -308,10 +282,7 @@ export async function buildBundle(
|
|
|
308
282
|
|
|
309
283
|
// The arguments of a call of a script: a thunk per splice, then its
|
|
310
284
|
// captures.
|
|
311
|
-
const exprCallArgs =
|
|
312
|
-
ref: ClientScript,
|
|
313
|
-
scope: Scope,
|
|
314
|
-
): Promise<string[]> => {
|
|
285
|
+
const exprCallArgs = (ref: ClientScript, scope: Scope): string[] => {
|
|
315
286
|
const target = scriptFor(ref);
|
|
316
287
|
const parts: string[] = [];
|
|
317
288
|
// The splices lead the parameters, one `arg` each.
|
|
@@ -322,11 +293,10 @@ export async function buildBundle(
|
|
|
322
293
|
const passed = [...passKeys(target, index), ...capturesOf(target)];
|
|
323
294
|
// A thunk taking them, the splice rendered inside it.
|
|
324
295
|
parts.push(
|
|
325
|
-
|
|
296
|
+
closure(
|
|
326
297
|
scope,
|
|
327
298
|
passed,
|
|
328
|
-
|
|
329
|
-
arrow(passed.map(displayName), await render(arg, inner)),
|
|
299
|
+
(inner) => arrow(passed.map(displayName), render(arg, inner)),
|
|
330
300
|
"$thunk",
|
|
331
301
|
),
|
|
332
302
|
);
|
|
@@ -337,18 +307,10 @@ export async function buildBundle(
|
|
|
337
307
|
return parts;
|
|
338
308
|
};
|
|
339
309
|
|
|
340
|
-
// A tag
|
|
341
|
-
//
|
|
342
|
-
|
|
343
|
-
//
|
|
344
|
-
// A prop that is `undefined` is left out, as JSX and TypeScript's optional
|
|
345
|
-
// props read it: a component forwarding an optional prop it wasn't given
|
|
346
|
-
// writes nothing.
|
|
347
|
-
const renderJsx = async (jsx: JsxElement, scope: Scope): Promise<string> => {
|
|
310
|
+
// A tag left after expansion, which ran every server component's: one the
|
|
311
|
+
// client draws.
|
|
312
|
+
const renderJsx = (jsx: JsxElement): never => {
|
|
348
313
|
const type = jsx.type;
|
|
349
|
-
if (typeof type === "function" && !isClientImport(type)) {
|
|
350
|
-
return render(await expandJsxElement(jsx, type), scope);
|
|
351
|
-
}
|
|
352
314
|
// An element and a client component (an import, or a script answering
|
|
353
315
|
// one) are client code, so on the host they can't be tags: they are tags
|
|
354
316
|
// in a script.
|
|
@@ -365,8 +327,9 @@ export async function buildBundle(
|
|
|
365
327
|
);
|
|
366
328
|
};
|
|
367
329
|
|
|
368
|
-
//
|
|
369
|
-
|
|
330
|
+
// Every server component first, so siblings run at once; then the drawing,
|
|
331
|
+
// in order. Nothing encloses the root, so nothing it holds can capture.
|
|
332
|
+
const root = render(await expandServerComponents(value));
|
|
370
333
|
// In table order, which is the order rendering first reached each script.
|
|
371
334
|
const modules = [...numbers.keys()].map(
|
|
372
335
|
(script) => [labelOf(script), script.module] as const,
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { isClientImport, isClientScript, isJsxElement } from "@backtickjs/core";
|
|
2
|
+
|
|
3
|
+
const CYCLE_ERROR =
|
|
4
|
+
"Can't splice a value that contains itself: a bundle writes each value " +
|
|
5
|
+
"out in full, so a cycle never ends. Break the cycle before splicing it.";
|
|
6
|
+
|
|
7
|
+
// The objects a value is inside of, innermost first. Each branch has its own,
|
|
8
|
+
// so siblings expanding at once never see each other's.
|
|
9
|
+
interface Ancestors {
|
|
10
|
+
readonly value: object;
|
|
11
|
+
readonly parent: Ancestors | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const contains = (ancestors: Ancestors | null, value: object): boolean => {
|
|
15
|
+
for (let at = ancestors; at !== null; at = at.parent) {
|
|
16
|
+
if (at.value === value) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Runs every server component in a value and answers with the value as drawn:
|
|
24
|
+
// each element of one replaced by what its component drew, expanded in turn.
|
|
25
|
+
// Siblings expand at once, so two components awaiting data wait together.
|
|
26
|
+
//
|
|
27
|
+
// A component runs each time its element is drawn, as React renders an element
|
|
28
|
+
// each place it stands: the component itself never leaves the host, and only
|
|
29
|
+
// the client code it bottoms out in reaches the bundle. A value holding no
|
|
30
|
+
// server component comes back as the same object.
|
|
31
|
+
export async function expandServerComponents(
|
|
32
|
+
value: unknown,
|
|
33
|
+
ancestors: Ancestors | null = null,
|
|
34
|
+
): Promise<unknown> {
|
|
35
|
+
if (typeof value !== "object" || value === null) {
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
if (contains(ancestors, value)) {
|
|
39
|
+
throw new Error(CYCLE_ERROR);
|
|
40
|
+
}
|
|
41
|
+
const inside: Ancestors = { value, parent: ancestors };
|
|
42
|
+
const all = (values: readonly unknown[]) =>
|
|
43
|
+
Promise.all(values.map((entry) => expandServerComponents(entry, inside)));
|
|
44
|
+
|
|
45
|
+
if (isJsxElement(value)) {
|
|
46
|
+
const { type } = value;
|
|
47
|
+
// A tag the client draws is left for rendering to refuse.
|
|
48
|
+
if (typeof type !== "function" || isClientImport(type)) {
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
return expandServerComponents(await type(value.props as never), inside);
|
|
52
|
+
}
|
|
53
|
+
if (isClientScript(value)) {
|
|
54
|
+
const args = await all(value.args);
|
|
55
|
+
return args.every((arg, index) => arg === value.args[index])
|
|
56
|
+
? value
|
|
57
|
+
: { ...value, args };
|
|
58
|
+
}
|
|
59
|
+
if (Array.isArray(value)) {
|
|
60
|
+
const elements = await all(value);
|
|
61
|
+
return elements.every((element, index) => element === value[index])
|
|
62
|
+
? value
|
|
63
|
+
: elements;
|
|
64
|
+
}
|
|
65
|
+
// Only plain objects cross; rendering refuses anything else.
|
|
66
|
+
const prototype = Object.getPrototypeOf(value);
|
|
67
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
const entries = Object.entries(value);
|
|
71
|
+
const expanded = await all(entries.map(([, entry]) => entry));
|
|
72
|
+
if (expanded.every((entry, index) => entry === entries[index]![1])) {
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
// Defined, not assigned, so a `__proto__` key stays a key.
|
|
76
|
+
return Object.fromEntries(
|
|
77
|
+
entries.map(([key], index) => [key, expanded[index]]),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
// Runs a host component and answers with what it drew, each time an element
|
|
2
|
-
// is drawn, as React renders an element each place it stands. The component
|
|
3
|
-
// itself never leaves the host: a server component expands away here, and
|
|
4
|
-
// only the client component it bottoms out in reaches the bundle.
|
|
5
|
-
export async function expandJsxElement(jsx, component) {
|
|
6
|
-
return component(jsx.props);
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=expandJsxElement.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"expandJsxElement.js","sourceRoot":"","sources":["../../src/bundle/expandJsxElement.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,4EAA4E;AAC5E,0EAA0E;AAC1E,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAe,EACf,SAAoC;IAEpC,OAAO,SAAS,CAAC,GAAG,CAAC,KAAc,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { JsxElement } from "@backtickjs/core";
|
|
2
|
-
|
|
3
|
-
// Runs a host component and answers with what it drew, each time an element
|
|
4
|
-
// is drawn, as React renders an element each place it stands. The component
|
|
5
|
-
// itself never leaves the host: a server component expands away here, and
|
|
6
|
-
// only the client component it bottoms out in reaches the bundle.
|
|
7
|
-
export async function expandJsxElement(
|
|
8
|
-
jsx: JsxElement,
|
|
9
|
-
component: (props: never) => unknown,
|
|
10
|
-
): Promise<unknown> {
|
|
11
|
-
return component(jsx.props as never);
|
|
12
|
-
}
|