@backtickjs/bundler 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +75 -2
- package/dist/bundle/bindingKey.d.ts +1 -0
- package/dist/bundle/bindingKey.js +10 -0
- package/dist/bundle/bindingKey.js.map +1 -0
- package/dist/bundle/buildBundle.d.ts +14 -0
- package/dist/bundle/buildBundle.js +270 -0
- package/dist/bundle/buildBundle.js.map +1 -0
- package/dist/bundle/expandJsxElement.d.ts +3 -0
- package/dist/bundle/expandJsxElement.js +13 -0
- package/dist/bundle/expandJsxElement.js.map +1 -0
- package/dist/bundle/params.d.ts +3 -0
- package/dist/bundle/params.js +10 -0
- package/dist/bundle/params.js.map +1 -0
- package/dist/bundler.d.ts +32 -0
- package/dist/bundler.js +34 -0
- package/dist/bundler.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/print/code.d.ts +28 -0
- package/dist/print/code.js +95 -0
- package/dist/print/code.js.map +1 -0
- package/dist/print/printBundle.d.ts +19 -0
- package/dist/print/printBundle.js +106 -0
- package/dist/print/printBundle.js.map +1 -0
- package/package.json +55 -3
- package/src/bundle/bindingKey.ts +10 -0
- package/src/bundle/buildBundle.ts +353 -0
- package/src/bundle/expandJsxElement.ts +26 -0
- package/src/bundle/params.ts +15 -0
- package/src/bundler.ts +66 -0
- package/src/index.ts +7 -0
- package/src/print/code.ts +144 -0
- package/src/print/printBundle.ts +126 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jean-François Bisson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,76 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @backtickjs/bundler
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Turns a screen into one JavaScript file for the client. On each request, your server calls `bundler.build` with a server component; the bundler runs it and the server components it draws, and combines their data with the client scripts they return into a bundle. Scripts were already compiled at build time, so nothing is compiled or parsed per request.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @backtickjs/bundler @backtickjs/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
For React Native, write CommonJS and serve it; the app fetches it and runs it with `evaluate` from `@backtickjs/react-native-client`:
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { bundler } from "@backtickjs/bundler";
|
|
17
|
+
import { Home } from "./Home.js";
|
|
18
|
+
|
|
19
|
+
const packageVersions = { react: "19.2.3", "react-native": "0.86.3" };
|
|
20
|
+
|
|
21
|
+
// In a request handler:
|
|
22
|
+
const bundle = await bundler.build({ input: <Home />, packageVersions });
|
|
23
|
+
const { code } = bundle.generate({ format: "cjs" });
|
|
24
|
+
response.setHeader("content-type", "text/javascript");
|
|
25
|
+
response.end(code);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
For the web, write an ES module whose default export is the value, and load it with `<script type="module">` and an import map for the packages the page provides:
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { bundler } from "@backtickjs/bundler";
|
|
32
|
+
import { cs } from "@backtickjs/core";
|
|
33
|
+
import { createRoot } from "@backtickjs/react/client";
|
|
34
|
+
import { Home } from "./Home.js";
|
|
35
|
+
|
|
36
|
+
const element = <Home />;
|
|
37
|
+
const bundle = await bundler.build({
|
|
38
|
+
input: cs`$createRoot(document.getElementById("app")!).render($element)`,
|
|
39
|
+
packageVersions: { react: "19.2.3", "react-dom": "19.2.3" },
|
|
40
|
+
});
|
|
41
|
+
const { code } = bundle.generate({ format: "es", sourcemap: "inline" });
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### `packageVersions`
|
|
45
|
+
|
|
46
|
+
The packages the client provides, each at its exact version. The server decides which versions to bundle for: one app version, or one per client if your server tells them apart. Those packages are left out of the bundle, which imports (`es`) or requires (`cjs`) them. `build` rejects a script that imports from any other package, or whose import needs a range that doesn't include the version given: an adapter's (`^19.2.3` for `@backtickjs/react`) or one written with `createImport`.
|
|
47
|
+
|
|
48
|
+
### What crosses into a script
|
|
49
|
+
|
|
50
|
+
Spliced values are written into the bundle as data: strings, finite numbers, booleans, `null`, `undefined`, plain objects and arrays. They are never written as code. A host function or a class instance can't be spliced, and `build` rejects one: write a client function as a script, `` cs`(n: number) => …` ``, and draw a server component through a splice, `{${<Footer />}}`.
|
|
51
|
+
|
|
52
|
+
### Formats
|
|
53
|
+
|
|
54
|
+
- `"es"`: an ES module, for a web page. Packages are imported by specifier, which the page's import map resolves.
|
|
55
|
+
- `"cjs"`: CommonJS, for a client that provides `require` itself, as a React Native app does through `evaluate`.
|
|
56
|
+
|
|
57
|
+
### Source maps
|
|
58
|
+
|
|
59
|
+
`sourcemap: "inline"` appends the map to the code as a `data:` URL; `"hidden"` doesn't. Either way, it is also returned as `map`. The map names your server files and lines, not their content. None by default.
|
|
60
|
+
|
|
61
|
+
## API
|
|
62
|
+
|
|
63
|
+
- `bundler.build({ input, packageVersions })`: runs the server components in `input` and returns a `Bundle`. Async.
|
|
64
|
+
- `Bundle.generate({ format, sourcemap })`: writes the bundle; returns `{ code, map }`, where `map` is `null` without a source map.
|
|
65
|
+
- Types: `BuildOptions`, `OutputOptions`, `OutputChunk`, `Bundle`.
|
|
66
|
+
|
|
67
|
+
## Related
|
|
68
|
+
|
|
69
|
+
- [`@backtickjs/core`](https://github.com/backtickjs/backtick/tree/main/packages/core): the `cs` tag
|
|
70
|
+
- [`@backtickjs/react-native-client`](https://github.com/backtickjs/backtick/tree/main/packages/react-native-client): runs a `cjs` bundle in a React Native app
|
|
71
|
+
- [`@backtickjs/react`](https://github.com/backtickjs/backtick/tree/main/packages/react), [`@backtickjs/react-native`](https://github.com/backtickjs/backtick/tree/main/packages/react-native), [`@backtickjs/solid-js`](https://github.com/backtickjs/backtick/tree/main/packages/solid-js): framework adapters
|
|
72
|
+
- [Documentation](https://backtickjs.com/docs)
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function sourceName(key: string): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// A binding key as the compiler writes it, `<name>$<fileHash>$<n>`. Shared by
|
|
2
|
+
// the two halves of the bundler because both have to agree on what a key means,
|
|
3
|
+
// and neither owns it.
|
|
4
|
+
// The source name a key was written under, with the uniqueness suffix dropped.
|
|
5
|
+
// Printing it is the caller's job: two distinct keys can share a source name,
|
|
6
|
+
// and whether that matters depends on whether they can meet in one scope.
|
|
7
|
+
export function sourceName(key) {
|
|
8
|
+
return key.replace(/\$[0-9a-z]+\$\d+$/, "");
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=bindingKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bindingKey.js","sourceRoot":"","sources":["../../src/bundle/bindingKey.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,gFAAgF;AAChF,uBAAuB;AAEvB,+EAA+E;AAC/E,8EAA8E;AAC9E,0EAA0E;AAC1E,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,GAAG,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ClientModule } from "@backtickjs/core";
|
|
2
|
+
import { type Spliceable } from "@backtickjs/core";
|
|
3
|
+
import type { Names } from "../print/code.js";
|
|
4
|
+
/**
|
|
5
|
+
* A bundle as it is built, before it is printed: each script's module it
|
|
6
|
+
* declares under its label, in the order rendering first reached it, and the
|
|
7
|
+
* root, as code; and what they import.
|
|
8
|
+
*/
|
|
9
|
+
export interface BundleTree {
|
|
10
|
+
readonly modules: readonly (readonly [string, ClientModule])[];
|
|
11
|
+
readonly root: string;
|
|
12
|
+
readonly names: Names;
|
|
13
|
+
}
|
|
14
|
+
export declare function buildBundle(value: Spliceable, packageVersions: Readonly<Record<string, string>>): Promise<BundleTree>;
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { isClientScript, isJsxElement, } from "@backtickjs/core";
|
|
2
|
+
import { isClientImport } from "@backtickjs/core";
|
|
3
|
+
import { expandJsxElement, } from "./expandJsxElement.js";
|
|
4
|
+
import { bindingsOf, capturesOf } from "./params.js";
|
|
5
|
+
import { sourceName } from "./bindingKey.js";
|
|
6
|
+
import { array, arrow, call, createNames, imported, literal, object, thunk, undefinedValue, } from "../print/code.js";
|
|
7
|
+
// Names a binding may not take: what strict code cannot bind. Every name the
|
|
8
|
+
// bundle introduces starts with `$`, which a script cannot bind, so none of
|
|
9
|
+
// those can meet a binding.
|
|
10
|
+
const RESERVED = ["arguments", "await", "eval", "yield"];
|
|
11
|
+
const rootScope = { bindings: new Set() };
|
|
12
|
+
// Builds the bundle `{ scripts, root }` as code, and documents how it is
|
|
13
|
+
// derived.
|
|
14
|
+
//
|
|
15
|
+
// Each script is declared once, as its compiled code under a label `$cs<n>`,
|
|
16
|
+
// and called wherever it is used. Its code takes a parameter per splice —
|
|
17
|
+
// a hole reads `$splice<i>()` — then per tag and per capture, so it is a function of the
|
|
18
|
+
// script's source alone: every call passes its own splice arguments, as
|
|
19
|
+
// thunks, and nothing from a call site is inlined.
|
|
20
|
+
//
|
|
21
|
+
// A captured variable is threaded, not resolved by name at the splice site: a
|
|
22
|
+
// fragment written in one script but spliced (via host code) into another still
|
|
23
|
+
// refers to the binding it was written under. Each script receives its live
|
|
24
|
+
// captures as parameters, and a call of it passes those captures from the
|
|
25
|
+
// enclosing scope. Because the compiler gives every binding a globally unique
|
|
26
|
+
// name, a capture is threaded under that one name the whole way down — an
|
|
27
|
+
// intermediate script that binds a same-looking variable has a different
|
|
28
|
+
// unique name, so there is nothing to disambiguate and nothing to rename.
|
|
29
|
+
export async function buildBundle(value, packageVersions) {
|
|
30
|
+
const names = createNames(packageVersions);
|
|
31
|
+
const elementExpansions = new WeakMap();
|
|
32
|
+
// Each script's number, in the order rendering first reaches it. Two
|
|
33
|
+
// scripts written at one source location are one declaration, so the first
|
|
34
|
+
// script with an id stands for all of them, and a reference to a shared
|
|
35
|
+
// script is a reference to the same object. Keyed by that script so a label
|
|
36
|
+
// is a lookup rather than a scan, and ordered by insertion, which is the
|
|
37
|
+
// order the tail declares them in.
|
|
38
|
+
const numbers = new Map();
|
|
39
|
+
const scriptById = new Map();
|
|
40
|
+
const scriptFor = (script) => {
|
|
41
|
+
const existing = scriptById.get(script.module.id);
|
|
42
|
+
if (existing !== undefined) {
|
|
43
|
+
return existing;
|
|
44
|
+
}
|
|
45
|
+
scriptById.set(script.module.id, script);
|
|
46
|
+
numbers.set(script, numbers.size);
|
|
47
|
+
return script;
|
|
48
|
+
};
|
|
49
|
+
// A binding key printed under its source name, with a numeric suffix when two
|
|
50
|
+
// distinct bindings would otherwise print the same.
|
|
51
|
+
//
|
|
52
|
+
// Disambiguated at all because these become identifiers, and identifiers nest:
|
|
53
|
+
// a hole inside a thunk puts one thunk's parameters inside another's, so two
|
|
54
|
+
// bindings sharing a source name can land in one chain and the inner would
|
|
55
|
+
// shadow what the outer was handed (`shadowing` nests three).
|
|
56
|
+
//
|
|
57
|
+
// One scope, which is the bundle root: what a drawing is written into now
|
|
58
|
+
// that structure goes where it stands. A declared script's names are the
|
|
59
|
+
// compiler's, from its own source — nothing out here reads those names,
|
|
60
|
+
// because a call hands a script its arguments positionally, and its
|
|
61
|
+
// captures arrive as numbered parameters rather than under a name.
|
|
62
|
+
const displayed = new Map();
|
|
63
|
+
const used = new Set(RESERVED);
|
|
64
|
+
const displayName = (key) => {
|
|
65
|
+
const existing = displayed.get(key);
|
|
66
|
+
if (existing !== undefined) {
|
|
67
|
+
return existing;
|
|
68
|
+
}
|
|
69
|
+
const base = sourceName(key);
|
|
70
|
+
let name = base;
|
|
71
|
+
for (let n = 2; used.has(name); n++) {
|
|
72
|
+
name = `${base}${n}`;
|
|
73
|
+
}
|
|
74
|
+
used.add(name);
|
|
75
|
+
displayed.set(key, name);
|
|
76
|
+
return name;
|
|
77
|
+
};
|
|
78
|
+
// The script-declared bindings a hole feeds its thunk, so a spliced fragment
|
|
79
|
+
// sees the bindings in scope at its hole even though the thunk is written at
|
|
80
|
+
// the call site. The body's hole call and every thunk's parameter list read
|
|
81
|
+
// this, so they agree positionally.
|
|
82
|
+
//
|
|
83
|
+
// Read off the script's own source (see `splices` in `resolveBindings`),
|
|
84
|
+
// not off what the arguments reaching that hole in this bundle happen to
|
|
85
|
+
// capture. That is what lets a script be compiled from its source alone: a
|
|
86
|
+
// second call site appearing elsewhere in a render cannot change a thunk a
|
|
87
|
+
// first one already had.
|
|
88
|
+
//
|
|
89
|
+
// It is a superset — the bindings a fragment written there *could* name, not
|
|
90
|
+
// the ones it does — because which fragment reaches a hole is a host
|
|
91
|
+
// decision. A carried fragment arrives with its own captures already bound,
|
|
92
|
+
// so the extra parameters are unused rather than wrong.
|
|
93
|
+
const passKeys = (target, hole) => bindingsOf(target.module.params[hole]);
|
|
94
|
+
// The scripts the bundle declares: those a reference calls or passes, not
|
|
95
|
+
// every one looked up on the way.
|
|
96
|
+
const declared = new Set();
|
|
97
|
+
// A declared script's label: `$cs` and its number.
|
|
98
|
+
const labelOf = (target) => `$cs${numbers.get(target)}`;
|
|
99
|
+
const declare = (script) => {
|
|
100
|
+
declared.add(script);
|
|
101
|
+
};
|
|
102
|
+
// A fragment that is one script whose parameters are exactly what this hole
|
|
103
|
+
// passes, so calling it is what a thunk around it would have done. The lists
|
|
104
|
+
// are compared rather than assumed: a hole hands over what its own script has,
|
|
105
|
+
// and a fragment wants what its own script needs, and those coincide often
|
|
106
|
+
// but not always.
|
|
107
|
+
const forwarding = (value, passed) => {
|
|
108
|
+
if (!isClientScript(value) ||
|
|
109
|
+
value.module.params.some((param) => param.kind !== "capture")) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const target = scriptFor(value);
|
|
113
|
+
const wanted = capturesOf(target);
|
|
114
|
+
if (wanted.length !== passed.length ||
|
|
115
|
+
wanted.some((key, at) => key !== passed[at])) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
declare(target);
|
|
119
|
+
return labelOf(target);
|
|
120
|
+
};
|
|
121
|
+
// Writes a value as the code it becomes: composition as data, which is what
|
|
122
|
+
// a bundle is. A script reference is a call naming which script and
|
|
123
|
+
// what to hand it; everything else is its literal form. Rendered in order,
|
|
124
|
+
// one value after the other, so the table follows the order rendering first
|
|
125
|
+
// reached each script.
|
|
126
|
+
const render = async (value, scope = rootScope) => {
|
|
127
|
+
if (isClientScript(value)) {
|
|
128
|
+
const target = scriptFor(value);
|
|
129
|
+
declare(target);
|
|
130
|
+
return call(labelOf(target), await exprCallArgs(value, scope));
|
|
131
|
+
}
|
|
132
|
+
if (isJsxElement(value)) {
|
|
133
|
+
return renderJsx(value, scope);
|
|
134
|
+
}
|
|
135
|
+
if (isClientImport(value)) {
|
|
136
|
+
return imported(names, value);
|
|
137
|
+
}
|
|
138
|
+
if (value === null) {
|
|
139
|
+
return literal(null);
|
|
140
|
+
}
|
|
141
|
+
// Checked by name, since everything past here reads the value as an object.
|
|
142
|
+
if (value === undefined) {
|
|
143
|
+
return undefinedValue;
|
|
144
|
+
}
|
|
145
|
+
if (typeof value === "number" ||
|
|
146
|
+
typeof value === "string" ||
|
|
147
|
+
typeof value === "boolean") {
|
|
148
|
+
return literal(value);
|
|
149
|
+
}
|
|
150
|
+
if (Array.isArray(value)) {
|
|
151
|
+
const elements = [];
|
|
152
|
+
for (const element of value) {
|
|
153
|
+
elements.push(await render(element, scope));
|
|
154
|
+
}
|
|
155
|
+
return array(elements);
|
|
156
|
+
}
|
|
157
|
+
// A host function is host code, which never reaches the client: client
|
|
158
|
+
// code is written in a script, and reaches another as one.
|
|
159
|
+
// A server component among them, written as a tag: `<$Rule />`.
|
|
160
|
+
if (typeof value === "function") {
|
|
161
|
+
const { name } = value;
|
|
162
|
+
throw new Error((name === ""
|
|
163
|
+
? "Can't splice a host function"
|
|
164
|
+
: `Can't splice the host function \`${name}\``) +
|
|
165
|
+
": it's host code, and only runs on the host. Write a client " +
|
|
166
|
+
"function as a script instead: cs`(n: number) => ...`; a server " +
|
|
167
|
+
`component is drawn in a braced splice: \`{\${<${name || "Name"} />}}\`.`);
|
|
168
|
+
}
|
|
169
|
+
// Only plain objects cross structurally. A class instance would land here
|
|
170
|
+
// and half-work — own fields would cross, getters and methods silently
|
|
171
|
+
// vanish — so fail loudly instead. An object with behaviour is built by a
|
|
172
|
+
// client function: `state` for what it holds, arrows for what may be done
|
|
173
|
+
// to it.
|
|
174
|
+
const prototype = Object.getPrototypeOf(value);
|
|
175
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
176
|
+
const name = value.constructor?.name ?? "an unknown class";
|
|
177
|
+
throw new Error(`Can't splice this \`${name}\` instance: only plain objects cross into ` +
|
|
178
|
+
"a client script. Build one with a client function instead.");
|
|
179
|
+
}
|
|
180
|
+
const entries = [];
|
|
181
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
182
|
+
entries.push([key, await render(entry, scope)]);
|
|
183
|
+
}
|
|
184
|
+
return object(entries);
|
|
185
|
+
};
|
|
186
|
+
// Renders a capture in JSON position: a parameter of an enclosing thunk
|
|
187
|
+
// resolves by name; anything else must be a parameter of the enclosing script.
|
|
188
|
+
// At
|
|
189
|
+
// the bundle root there is no enclosing instance, so a capture reaching it
|
|
190
|
+
// can't be threaded from anywhere.
|
|
191
|
+
const capExpr = (key, scope) => {
|
|
192
|
+
if (scope.bindings.has(key)) {
|
|
193
|
+
return displayName(key);
|
|
194
|
+
}
|
|
195
|
+
throw new Error(`Can't thread the capture \`${sourceName(key)}\`: nothing encloses ` +
|
|
196
|
+
"this reference to supply it. A fragment carries the bindings it was " +
|
|
197
|
+
"written under, so this is also what happens when one is spliced " +
|
|
198
|
+
"somewhere another `" +
|
|
199
|
+
sourceName(key) +
|
|
200
|
+
"` shadows it: the binding is still there, but no longer reachable by " +
|
|
201
|
+
"name, and naming it anyway would mean emitting what the source " +
|
|
202
|
+
"couldn't say.");
|
|
203
|
+
};
|
|
204
|
+
// The arguments of a call of a declared script: for
|
|
205
|
+
// one `#thunk` per splice ahead of the environment.
|
|
206
|
+
const exprCallArgs = async (ref, scope) => {
|
|
207
|
+
const target = scriptFor(ref);
|
|
208
|
+
const parts = [];
|
|
209
|
+
// The splices lead the parameters, one `arg` each.
|
|
210
|
+
for (const [index, arg] of ref.args.entries()) {
|
|
211
|
+
// What the hole hands over, in the order the script fixes: the bindings
|
|
212
|
+
// bound there, then the captures it forwards on behalf of whatever is
|
|
213
|
+
// nested inside it.
|
|
214
|
+
const passed = [...passKeys(target, index), ...capturesOf(target)];
|
|
215
|
+
// A fragment whose own parameters are exactly that list reads the hole's
|
|
216
|
+
// arguments as they arrive, so it is passed as it is rather than wrapped
|
|
217
|
+
// in a thunk that would only pass them along.
|
|
218
|
+
const forwarded = forwarding(arg, passed);
|
|
219
|
+
if (forwarded !== null) {
|
|
220
|
+
parts.push(forwarded);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (passed.length === 0) {
|
|
224
|
+
parts.push(thunk(await render(arg, scope)));
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
// Otherwise a thunk names them and calls the fragment with what it wants.
|
|
228
|
+
const inner = { bindings: new Set([...scope.bindings, ...passed]) };
|
|
229
|
+
parts.push(arrow(passed.map(displayName), await render(arg, inner)));
|
|
230
|
+
}
|
|
231
|
+
for (const key of capturesOf(target)) {
|
|
232
|
+
parts.push(capExpr(key, scope));
|
|
233
|
+
}
|
|
234
|
+
return parts;
|
|
235
|
+
};
|
|
236
|
+
// A tag. A component runs on the host and what it drew stands where the tag
|
|
237
|
+
// stood; an element is its own name, each prop an expression in the
|
|
238
|
+
// enclosing script's scope.
|
|
239
|
+
//
|
|
240
|
+
// A prop that is `undefined` is left out, as JSX and TypeScript's optional
|
|
241
|
+
// props read it: a component forwarding an optional prop it wasn't given
|
|
242
|
+
// writes nothing.
|
|
243
|
+
const renderJsx = async (jsx, scope) => {
|
|
244
|
+
const type = jsx.type;
|
|
245
|
+
if (typeof type === "function" && !isClientImport(type)) {
|
|
246
|
+
return render(await expandJsxElement(jsx, type, elementExpansions), scope);
|
|
247
|
+
}
|
|
248
|
+
// An element and a client component (an import, or a script answering
|
|
249
|
+
// one) are client code, so on the host they can't be tags: they are tags
|
|
250
|
+
// in a script.
|
|
251
|
+
if (typeof type === "string") {
|
|
252
|
+
throw new Error(`\`<${type}>\` is drawn by the client, so it belongs in a script: ` +
|
|
253
|
+
`cs\`<${type}>…</${type}>\`.`);
|
|
254
|
+
}
|
|
255
|
+
const tag = isClientImport(type) ? `\`<${type.name}>\`` : "A script";
|
|
256
|
+
throw new Error(`${tag} is a client component, so it can't be a tag on the host. ` +
|
|
257
|
+
"Use it as a tag in a script.");
|
|
258
|
+
};
|
|
259
|
+
// Nothing encloses the root, so nothing it holds can capture.
|
|
260
|
+
const root = await render(value);
|
|
261
|
+
// In table order, which is the order rendering first reached each script.
|
|
262
|
+
const modules = [];
|
|
263
|
+
for (const script of numbers.keys()) {
|
|
264
|
+
if (declared.has(script)) {
|
|
265
|
+
modules.push([labelOf(script), script.module]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return { modules, root, names };
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=buildBundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildBundle.js","sourceRoot":"","sources":["../../src/bundle/buildBundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { JsxElement, Spliceable } from "@backtickjs/core";
|
|
2
|
+
export type ElementExpansions = WeakMap<JsxElement, Promise<Spliceable>>;
|
|
3
|
+
export declare function expandJsxElement(jsx: JsxElement, component: (props: never) => unknown, expansions: ElementExpansions): Promise<Spliceable>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Runs a host component and answers with what it drew. The component itself
|
|
2
|
+
// never leaves the host: a server component expands away here, and only the
|
|
3
|
+
// client component it bottoms out in reaches the bundle.
|
|
4
|
+
export function expandJsxElement(jsx, component, expansions) {
|
|
5
|
+
const shared = expansions.get(jsx);
|
|
6
|
+
if (shared) {
|
|
7
|
+
return shared;
|
|
8
|
+
}
|
|
9
|
+
const expansion = Promise.resolve(component(jsx.props));
|
|
10
|
+
expansions.set(jsx, expansion);
|
|
11
|
+
return expansion;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=expandJsxElement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expandJsxElement.js","sourceRoot":"","sources":["../../src/bundle/expandJsxElement.ts"],"names":[],"mappings":"AAQA,4EAA4E;AAC5E,4EAA4E;AAC5E,yDAAyD;AACzD,MAAM,UAAU,gBAAgB,CAC9B,GAAe,EACf,SAAoC,EACpC,UAA6B;IAE7B,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAC/B,SAAS,CAAC,GAAG,CAAC,KAAc,CAAqC,CAClE,CAAC;IACF,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/B,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// What a script's module says about its parameters, the same for every run.
|
|
2
|
+
// The bindings a hole hands over. A capture hands over none.
|
|
3
|
+
export function bindingsOf(param) {
|
|
4
|
+
return param?.kind === "splice" ? param.bindings : [];
|
|
5
|
+
}
|
|
6
|
+
// The binding keys a script captures, in parameter order.
|
|
7
|
+
export function capturesOf(script) {
|
|
8
|
+
return script.module.params.flatMap((param) => param.kind === "capture" ? [param.key] : []);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=params.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"params.js","sourceRoot":"","sources":["../../src/bundle/params.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAE5E,6DAA6D;AAC7D,MAAM,UAAU,UAAU,CAAC,KAAwB;IACjD,OAAO,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,UAAU,CAAC,MAAoB;IAC7C,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAC5C,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAC5C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Spliceable } from "@backtickjs/core";
|
|
2
|
+
export interface BuildOptions {
|
|
3
|
+
readonly input: Spliceable;
|
|
4
|
+
readonly packageVersions: Readonly<Record<string, string>>;
|
|
5
|
+
}
|
|
6
|
+
export interface OutputOptions {
|
|
7
|
+
readonly format: "es" | "cjs";
|
|
8
|
+
readonly sourcemap?: false | "inline" | "hidden";
|
|
9
|
+
}
|
|
10
|
+
/** What `generate` writes: the code, and its map where one was asked for. */
|
|
11
|
+
export interface OutputChunk {
|
|
12
|
+
readonly code: string;
|
|
13
|
+
readonly map: string | null;
|
|
14
|
+
}
|
|
15
|
+
/** A built bundle, written out by `generate`. */
|
|
16
|
+
export interface Bundle {
|
|
17
|
+
generate(options: OutputOptions): OutputChunk;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* What runs your components and hands back what they drew, shaped as Rollup
|
|
21
|
+
* is: a build, then output from it.
|
|
22
|
+
*
|
|
23
|
+
* const bundle = await bundler.build({ input: <Home />, packageVersions });
|
|
24
|
+
* const { code, map } = bundle.generate({ format: "es", sourcemap: "hidden" });
|
|
25
|
+
*
|
|
26
|
+
* The module's default export is the value (CommonJS: `module.exports`). A
|
|
27
|
+
* namespace rather than a bare function, so `bundle` stays a name a caller can
|
|
28
|
+
* give what comes back.
|
|
29
|
+
*/
|
|
30
|
+
export declare const bundler: {
|
|
31
|
+
build({ input, packageVersions }: BuildOptions): Promise<Bundle>;
|
|
32
|
+
};
|
package/dist/bundler.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { buildBundle } from "./bundle/buildBundle.js";
|
|
2
|
+
import { printBundle } from "./print/printBundle.js";
|
|
3
|
+
/**
|
|
4
|
+
* What runs your components and hands back what they drew, shaped as Rollup
|
|
5
|
+
* is: a build, then output from it.
|
|
6
|
+
*
|
|
7
|
+
* const bundle = await bundler.build({ input: <Home />, packageVersions });
|
|
8
|
+
* const { code, map } = bundle.generate({ format: "es", sourcemap: "hidden" });
|
|
9
|
+
*
|
|
10
|
+
* The module's default export is the value (CommonJS: `module.exports`). A
|
|
11
|
+
* namespace rather than a bare function, so `bundle` stays a name a caller can
|
|
12
|
+
* give what comes back.
|
|
13
|
+
*/
|
|
14
|
+
export const bundler = {
|
|
15
|
+
async build({ input, packageVersions }) {
|
|
16
|
+
// Scripts come compiled for their framework when their host was built, so
|
|
17
|
+
// the bundle is only put together: nothing is compiled or parsed here.
|
|
18
|
+
const tree = await buildBundle(input, packageVersions);
|
|
19
|
+
return {
|
|
20
|
+
generate: ({ format, sourcemap = false }) => {
|
|
21
|
+
const { code, map } = printBundle(tree, format);
|
|
22
|
+
if (sourcemap === false) {
|
|
23
|
+
return { code, map: null };
|
|
24
|
+
}
|
|
25
|
+
if (sourcemap === "hidden") {
|
|
26
|
+
return { code, map };
|
|
27
|
+
}
|
|
28
|
+
const url = `data:application/json;charset=utf-8,${encodeURIComponent(map)}`;
|
|
29
|
+
return { code: `${code}\n//# sourceMappingURL=${url}`, map };
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=bundler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundler.js","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAiCrD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,eAAe,EAAgB;QAClD,0EAA0E;QAC1E,uEAAuE;QACvE,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QACvD,OAAO;YACL,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,EAAE,EAAE;gBAC1C,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAChD,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;oBACxB,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;gBAC7B,CAAC;gBACD,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;oBAC3B,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;gBACvB,CAAC;gBACD,MAAM,GAAG,GAAG,uCAAuC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7E,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,0BAA0B,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC;YAC/D,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { type Bundle, type BuildOptions, bundler, type OutputChunk, type OutputOptions, } from "./bundler.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,OAAO,GAGR,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ClientImport } from "@backtickjs/core";
|
|
2
|
+
/**
|
|
3
|
+
* What a bundle imports, keyed by specifier and export, each bound once; and
|
|
4
|
+
* the packages it may import them from, which the client provides, by version.
|
|
5
|
+
*/
|
|
6
|
+
export interface Names {
|
|
7
|
+
readonly imports: Map<string, {
|
|
8
|
+
from: string;
|
|
9
|
+
name: string;
|
|
10
|
+
local: string;
|
|
11
|
+
}>;
|
|
12
|
+
readonly packageVersions: Readonly<Record<string, string>>;
|
|
13
|
+
}
|
|
14
|
+
export declare function createNames(packageVersions: Readonly<Record<string, string>>): Names;
|
|
15
|
+
export declare function string(value: string): string;
|
|
16
|
+
export declare function literal(value: string | number | boolean | null): string;
|
|
17
|
+
export declare const undefinedValue = "void 0";
|
|
18
|
+
export declare function call(callee: string, args: readonly string[]): string;
|
|
19
|
+
export declare function arrow(params: readonly string[], body: string): string;
|
|
20
|
+
export declare function thunk(body: string): string;
|
|
21
|
+
export declare function array(elements: readonly string[]): string;
|
|
22
|
+
/** An object literal, each key bare where it can be and a string where not. */
|
|
23
|
+
export declare function object(entries: readonly (readonly [string, string])[]): string;
|
|
24
|
+
/** An export of a module the client provides, imported by the bundle. */
|
|
25
|
+
export declare function imported(names: Names, { from, name, version }: ClientImport<unknown>): string;
|
|
26
|
+
/** An import declaration of one export under its local name. */
|
|
27
|
+
export declare function importDeclaration(from: string, name: string, local: string): string;
|
|
28
|
+
export declare function requireDeclaration(from: string, name: string, local: string): string;
|