@backtickjs/bundler 0.1.8 → 0.1.9

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/README.md CHANGED
@@ -16,10 +16,14 @@ For React Native, write CommonJS and serve it; the app fetches it and runs it wi
16
16
  import { bundler } from "@backtickjs/bundler";
17
17
  import { Home } from "./Home.js";
18
18
 
19
- const packageVersions = { react: "19.2.3", "react-native": "0.86.3" };
19
+ const modules = {
20
+ react: "19.2.3",
21
+ "react/jsx-runtime": "19.2.3",
22
+ "react-native": "0.86.3",
23
+ };
20
24
 
21
25
  // In a request handler:
22
- const bundle = await bundler.build({ input: <Home />, packageVersions });
26
+ const bundle = await bundler.build({ input: <Home />, modules });
23
27
  const { code } = bundle.generate({ format: "cjs" });
24
28
  response.setHeader("content-type", "text/javascript");
25
29
  response.end(code);
@@ -36,14 +40,20 @@ import { Home } from "./Home.js";
36
40
  const element = <Home />;
37
41
  const bundle = await bundler.build({
38
42
  input: cs`$createRoot(document.getElementById("app")!).render($element)`,
39
- packageVersions: { react: "19.2.3", "react-dom": "19.2.3" },
43
+ modules: {
44
+ react: "19.2.3",
45
+ "react/jsx-runtime": "19.2.3",
46
+ "react-dom/client": "19.2.3",
47
+ },
40
48
  });
41
49
  const { code } = bundle.generate({ format: "es", sourcemap: "inline" });
42
50
  ```
43
51
 
44
- ### `packageVersions`
52
+ ### `modules`
45
53
 
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`.
54
+ The modules the client provides, by specifier, each at the exact version of the package it comes from: `"react-dom/client": "19.2.3"`. The server decides which to bundle for: one app version, or one per build with [`@backtickjs/builds`](https://github.com/backtickjs/backtick/tree/main/packages/builds). Those modules are left out of the bundle, which imports (`es`) or requires (`cjs`) them. `build` rejects a script that imports from any other module, 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`.
55
+
56
+ `supports(modules, specifier, range)` makes the same check, for a server choosing what to draw for a client: `supports(modules, "expo-haptics", "^15")`.
47
57
 
48
58
  ### What crosses into a script
49
59
 
@@ -60,7 +70,7 @@ Spliced values are written into the bundle as data, never as code. What can't cr
60
70
 
61
71
  ## API
62
72
 
63
- - `bundler.build({ input, packageVersions })`: runs the server components in `input` and returns a `Bundle`. Async.
73
+ - `bundler.build({ input, modules })`: runs the server components in `input` and returns a `Bundle`. Async.
64
74
  - `Bundle.generate({ format, sourcemap })`: writes the bundle; returns `{ code, map }`, where `map` is `null` without a source map.
65
75
  - Types: `BuildOptions`, `OutputOptions`, `OutputChunk`, `Bundle`.
66
76
 
@@ -68,7 +78,7 @@ Spliced values are written into the bundle as data, never as code. What can't cr
68
78
 
69
79
  - [`@backtickjs/core`](https://github.com/backtickjs/backtick/tree/main/packages/core): the `cs` tag
70
80
  - [`@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
81
+ - [`@backtickjs/react`](https://github.com/backtickjs/backtick/tree/main/adapters/react), [`@backtickjs/react-native`](https://github.com/backtickjs/backtick/tree/main/adapters/react-native), [`@backtickjs/solid-js`](https://github.com/backtickjs/backtick/tree/main/adapters/solid-js): framework adapters
72
82
  - [How it works](https://backtickjs.com/docs/how-it-works)
73
83
  - [Errors](https://backtickjs.com/docs/errors)
74
84
 
@@ -1,5 +1,6 @@
1
1
  import { type ClientModule } from "@backtickjs/core";
2
2
  import type { Names } from "../print/code.js";
3
+ import type { Modules } from "../modules.js";
3
4
  /**
4
5
  * A bundle as it is built, before it is printed: each script's module it
5
6
  * declares under its label, in the order rendering first reached it, and the
@@ -11,4 +12,4 @@ export interface BundleTree {
11
12
  readonly root: string;
12
13
  readonly names: Names;
13
14
  }
14
- export declare function buildBundle(value: unknown, packageVersions: Readonly<Record<string, string>>): Promise<BundleTree>;
15
+ export declare function buildBundle(value: unknown, provided: Modules): Promise<BundleTree>;
@@ -25,8 +25,8 @@ const rootScope = () => ({ bindings: new Set(), read: new Set() });
25
25
  // name, a capture is threaded under that one name the whole way down — an
26
26
  // intermediate script that binds a same-looking variable has a different
27
27
  // unique name, so there is nothing to disambiguate and nothing to rename.
28
- export async function buildBundle(value, packageVersions) {
29
- const names = createNames(packageVersions);
28
+ export async function buildBundle(value, provided) {
29
+ const names = createNames(provided);
30
30
  // Each script's number, in the order rendering first reaches it. Two
31
31
  // scripts written at one source location are one declaration, so the first
32
32
  // script with an id stands for all of them, and a reference to a shared
@@ -119,6 +119,23 @@ export async function buildBundle(value, packageVersions) {
119
119
  }
120
120
  return label;
121
121
  };
122
+ // A `once` script is one value: its code run at the top of the bundle,
123
+ // where nothing encloses it, and every read is that constant. One per
124
+ // script, which is one per call of `once`, not per code: two runs of a host
125
+ // function that each make a context are two contexts, as two calls of
126
+ // `createContext` are. Running code is observable, so unlike a function it
127
+ // is never shared by code.
128
+ const values = new Map();
129
+ const valueOf = (script) => {
130
+ let label = values.get(script);
131
+ if (label === undefined) {
132
+ const code = call(labelOf(scriptFor(script)), exprCallArgs(script, rootScope()));
133
+ label = `$value${constants.length}`;
134
+ values.set(script, label);
135
+ constants.push([label, code]);
136
+ }
137
+ return label;
138
+ };
122
139
  // Writes a value as the code it becomes: composition as data, which is what
123
140
  // a bundle is. A script reference is a call naming which script and
124
141
  // what to hand it; everything else is its literal form. Rendered in order,
@@ -126,6 +143,9 @@ export async function buildBundle(value, packageVersions) {
126
143
  // reached each script. Expansion has refused cycles, so it ends.
127
144
  const render = (value, scope = rootScope()) => {
128
145
  if (isClientScript(value)) {
146
+ if (value.once) {
147
+ return valueOf(value);
148
+ }
129
149
  const target = scriptFor(value);
130
150
  if (target.module.kind !== "function") {
131
151
  return call(labelOf(target), exprCallArgs(value, scope));
@@ -203,7 +223,9 @@ export async function buildBundle(value, packageVersions) {
203
223
  sourceName(key) +
204
224
  "` shadows it: the binding is still there, but no longer reachable by " +
205
225
  "name, and naming it anyway would mean emitting what the source " +
206
- "couldn't say.");
226
+ "couldn't say. A `once` script is made at the top of the bundle, " +
227
+ "outside every script, so a fragment spliced into one can't reach " +
228
+ "its binding either.");
207
229
  };
208
230
  // The arguments of a call of a script: a thunk per splice, then its
209
231
  // captures.
@@ -1 +1 @@
1
- {"version":3,"file":"buildBundle.js","sourceRoot":"","sources":["../../src/bundle/buildBundle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"buildBundle.js","sourceRoot":"","sources":["../../src/bundle/buildBundle.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
+ import { type ClientScript } from "@backtickjs/core";
1
2
  interface Ancestors {
2
3
  readonly value: object;
3
4
  readonly parent: Ancestors | null;
4
5
  }
5
- export declare function expandServerComponents(value: unknown, ancestors?: Ancestors | null): Promise<unknown>;
6
+ export declare function expandServerComponents(value: unknown, ancestors?: Ancestors | null, values?: Map<ClientScript, Promise<unknown>>): Promise<unknown>;
6
7
  export {};
@@ -1,4 +1,4 @@
1
- import { isClientImport, isClientScript, isJsxElement } from "@backtickjs/core";
1
+ import { isClientImport, isClientScript, isJsxElement, } from "@backtickjs/core";
2
2
  const CYCLE_ERROR = "Can't splice a value that contains itself: a bundle writes each value " +
3
3
  "out in full, so a cycle never ends. Break the cycle before splicing it.";
4
4
  const contains = (ancestors, value) => {
@@ -17,7 +17,11 @@ const contains = (ancestors, value) => {
17
17
  // each place it stands: the component itself never leaves the host, and only
18
18
  // the client code it bottoms out in reaches the bundle. A value holding no
19
19
  // server component comes back as the same object.
20
- export async function expandServerComponents(value, ancestors = null) {
20
+ //
21
+ // A `once` script is one value, so what it splices is expanded once, however
22
+ // many places read it: a server component inside it runs once. `values` holds
23
+ // each one's expansion for the call.
24
+ export async function expandServerComponents(value, ancestors = null, values = new Map()) {
21
25
  if (typeof value !== "object" || value === null) {
22
26
  return value;
23
27
  }
@@ -25,20 +29,31 @@ export async function expandServerComponents(value, ancestors = null) {
25
29
  throw new Error(CYCLE_ERROR);
26
30
  }
27
31
  const inside = { value, parent: ancestors };
28
- const all = (values) => Promise.all(values.map((entry) => expandServerComponents(entry, inside)));
32
+ const all = (entries) => Promise.all(entries.map((entry) => expandServerComponents(entry, inside, values)));
29
33
  if (isJsxElement(value)) {
30
34
  const { type } = value;
31
35
  // A tag the client draws is left for rendering to refuse.
32
36
  if (typeof type !== "function" || isClientImport(type)) {
33
37
  return value;
34
38
  }
35
- return expandServerComponents(await type(value.props), inside);
39
+ return expandServerComponents(await type(value.props), inside, values);
36
40
  }
37
41
  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
+ const expanded = async () => {
43
+ const args = await all(value.args);
44
+ return args.every((arg, index) => arg === value.args[index])
45
+ ? value
46
+ : { ...value, args };
47
+ };
48
+ if (!value.once) {
49
+ return expanded();
50
+ }
51
+ let made = values.get(value);
52
+ if (made === undefined) {
53
+ made = expanded();
54
+ values.set(value, made);
55
+ }
56
+ return made;
42
57
  }
43
58
  if (Array.isArray(value)) {
44
59
  const elements = await all(value);
@@ -1 +1 @@
1
- {"version":3,"file":"expandServerComponents.js","sourceRoot":"","sources":["../../src/bundle/expandServerComponents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"expandServerComponents.js","sourceRoot":"","sources":["../../src/bundle/expandServerComponents.ts"],"names":[],"mappings":"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"}
package/dist/bundler.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { Spliceable, SplicesAs } from "@backtickjs/core";
2
+ import type { Modules } from "./modules.js";
2
3
  export interface BuildOptions<T = Spliceable> {
3
4
  readonly input: T;
4
- readonly packageVersions: Readonly<Record<string, string>>;
5
+ readonly modules: Modules;
5
6
  }
6
7
  export interface OutputOptions {
7
8
  readonly format: "es" | "cjs";
@@ -20,7 +21,7 @@ export interface Bundle {
20
21
  * What runs your components and hands back what they drew, shaped as Rollup
21
22
  * is: a build, then output from it.
22
23
  *
23
- * const bundle = await bundler.build({ input: <Home />, packageVersions });
24
+ * const bundle = await bundler.build({ input: <Home />, modules });
24
25
  * const { code, map } = bundle.generate({ format: "es", sourcemap: "hidden" });
25
26
  *
26
27
  * The module's default export is the value (CommonJS: `module.exports`). A
@@ -28,5 +29,5 @@ export interface Bundle {
28
29
  * give what comes back.
29
30
  */
30
31
  export declare const bundler: {
31
- build<T extends [T] extends [SplicesAs<T>] ? unknown : Spliceable>({ input, packageVersions, }: BuildOptions<T>): Promise<Bundle>;
32
+ build<T extends [T] extends [SplicesAs<T>] ? unknown : Spliceable>({ input, modules, }: BuildOptions<T>): Promise<Bundle>;
32
33
  };
package/dist/bundler.js CHANGED
@@ -4,7 +4,7 @@ import { printBundle } from "./print/printBundle.js";
4
4
  * What runs your components and hands back what they drew, shaped as Rollup
5
5
  * is: a build, then output from it.
6
6
  *
7
- * const bundle = await bundler.build({ input: <Home />, packageVersions });
7
+ * const bundle = await bundler.build({ input: <Home />, modules });
8
8
  * const { code, map } = bundle.generate({ format: "es", sourcemap: "hidden" });
9
9
  *
10
10
  * The module's default export is the value (CommonJS: `module.exports`). A
@@ -12,10 +12,10 @@ import { printBundle } from "./print/printBundle.js";
12
12
  * give what comes back.
13
13
  */
14
14
  export const bundler = {
15
- async build({ input, packageVersions, }) {
15
+ async build({ input, modules, }) {
16
16
  // Scripts come compiled for their framework when their host was built, so
17
17
  // the bundle is only put together: nothing is compiled or parsed here.
18
- const tree = await buildBundle(input, packageVersions);
18
+ const tree = await buildBundle(input, modules);
19
19
  return {
20
20
  generate: ({ format, sourcemap = false }) => {
21
21
  const { code, map } = printBundle(tree, format);
@@ -1 +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,CAA8D,EACvE,KAAK,EACL,eAAe,GACC;QAChB,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"}
1
+ {"version":3,"file":"bundler.js","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAiCrD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,KAAK,CAAC,KAAK,CAA8D,EACvE,KAAK,EACL,OAAO,GACS;QAChB,0EAA0E;QAC1E,uEAAuE;QACvE,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC/C,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 CHANGED
@@ -1 +1,2 @@
1
1
  export { type Bundle, type BuildOptions, bundler, type OutputChunk, type OutputOptions, } from "./bundler.js";
2
+ export { type Modules, supports } from "./modules.js";
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { bundler, } from "./bundler.js";
2
+ export { supports } from "./modules.js";
2
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,OAAO,GAGR,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,OAAO,GAGR,MAAM,cAAc,CAAC;AACtB,OAAO,EAAgB,QAAQ,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The modules a client provides, by specifier, each at the exact version of
3
+ * the package it comes from: `{ "react/jsx-runtime": "19.2.3" }`.
4
+ */
5
+ export type Modules = Readonly<Record<string, string>>;
6
+ /**
7
+ * Whether a client with `modules` provides `specifier` at a version in
8
+ * `range`: the check a bundle's every import passes, so a server choosing
9
+ * what to draw for a client can ask it first.
10
+ */
11
+ export declare function supports(modules: Modules, specifier: string, range: string): boolean;
@@ -0,0 +1,11 @@
1
+ import semver from "semver";
2
+ /**
3
+ * Whether a client with `modules` provides `specifier` at a version in
4
+ * `range`: the check a bundle's every import passes, so a server choosing
5
+ * what to draw for a client can ask it first.
6
+ */
7
+ export function supports(modules, specifier, range) {
8
+ const provided = modules[specifier];
9
+ return provided !== undefined && semver.satisfies(provided, range);
10
+ }
11
+ //# sourceMappingURL=modules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modules.js","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAQ5B;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,OAAgB,EAChB,SAAiB,EACjB,KAAa;IAEb,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AACrE,CAAC"}
@@ -1,7 +1,8 @@
1
1
  import type { ClientImport } from "@backtickjs/core";
2
+ import { type Modules } from "../modules.js";
2
3
  /**
3
4
  * 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
+ * the modules it may import them from, which the client provides, by version.
5
6
  */
6
7
  export interface Names {
7
8
  readonly imports: Map<string, {
@@ -9,9 +10,9 @@ export interface Names {
9
10
  name: string;
10
11
  local: string;
11
12
  }>;
12
- readonly packageVersions: Readonly<Record<string, string>>;
13
+ readonly modules: Modules;
13
14
  }
14
- export declare function createNames(packageVersions: Readonly<Record<string, string>>): Names;
15
+ export declare function createNames(modules: Modules): Names;
15
16
  export declare function string(value: string): string;
16
17
  export declare function literal(value: string | number | bigint | boolean | null | undefined): string;
17
18
  export declare function call(callee: string, args: readonly string[]): string;
@@ -1,10 +1,10 @@
1
- import semver from "semver";
1
+ import { supports } from "../modules.js";
2
2
  // What a bundle is written as, and the one place its conventions live: how a
3
3
  // name is written, how a literal escapes, and how an element is written as JSX
4
4
  // for the framework's compiler. Everything is code, as a string.
5
5
  const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
6
- export function createNames(packageVersions) {
7
- return { imports: new Map(), packageVersions };
6
+ export function createNames(modules) {
7
+ return { imports: new Map(), modules };
8
8
  }
9
9
  // A string, as a literal: `<` escaped, so no `</script>` or `<!--` appears
10
10
  // when the bundle is inlined in a page, and the line and paragraph separators,
@@ -50,26 +50,19 @@ function member(key) {
50
50
  }
51
51
  return IDENTIFIER.test(key) ? key : string(key);
52
52
  }
53
- // The package a module is in: its specifier's first segment, or first two
54
- // when scoped (`solid-js/web` → `solid-js`, `@scope/pkg/x` → `@scope/pkg`).
55
- function packageOf(from) {
56
- const segments = from.split("/");
57
- return segments.slice(0, from.startsWith("@") ? 2 : 1).join("/");
58
- }
59
53
  /** An export of a module the client provides, imported by the bundle. */
60
54
  export function imported(names, { from, name, version }) {
61
55
  // Where a script's import is written: a plugin's own (a framework's compile
62
56
  // step) are the plugin's, trusted as it is.
63
- const pkg = packageOf(from);
64
- const provided = names.packageVersions[pkg];
57
+ const provided = names.modules[from];
65
58
  if (provided === undefined) {
66
- const packages = Object.entries(names.packageVersions).map(([provided, at]) => `${provided}@${at}`);
59
+ const listed = Object.entries(names.modules).map(([specifier, at]) => `${specifier}@${at}`);
67
60
  throw new Error(`Can't import \`${name}\` from "${from}": the client provides ` +
68
- `${packages.join(", ") || "no packages"}.`);
61
+ `${listed.join(", ") || "no modules"}.`);
69
62
  }
70
- if (!semver.satisfies(provided, version)) {
71
- throw new Error(`Can't import \`${name}\` from "${from}": it needs ${pkg}@${version}, ` +
72
- `and the client provides ${pkg}@${provided}.`);
63
+ if (!supports(names.modules, from, version)) {
64
+ throw new Error(`Can't import \`${name}\` from "${from}": it needs ${version}, and ` +
65
+ `the client provides ${from}@${provided}.`);
73
66
  }
74
67
  const key = `${from}\0${name}`;
75
68
  let entry = names.imports.get(key);
@@ -1 +1 @@
1
- {"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/print/code.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/print/code.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.8",
3
+ "version": "0.1.9",
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",
@@ -39,8 +39,8 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "semver": "^7.8.1",
43
- "@backtickjs/core": "0.1.8"
42
+ "@backtickjs/core": "^0.1.9",
43
+ "semver": "^7.8.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/semver": "^7.8.0",
@@ -20,6 +20,7 @@ import {
20
20
  object,
21
21
  } from "../print/code.js";
22
22
  import type { Names } from "../print/code.js";
23
+ import type { Modules } from "../modules.js";
23
24
 
24
25
  /**
25
26
  * A bundle as it is built, before it is printed: each script's module it
@@ -28,8 +29,8 @@ import type { Names } from "../print/code.js";
28
29
  */
29
30
  export interface BundleTree {
30
31
  readonly modules: readonly (readonly [string, ClientModule])[];
31
- // The functions the bundle makes once, each under its label, in the order
32
- // they're finished: after what they read.
32
+ // The functions and `once` values the bundle makes once, each under its
33
+ // label, in the order they're finished: after what they read.
33
34
  readonly constants: readonly (readonly [string, string])[];
34
35
  readonly root: string;
35
36
  readonly names: Names;
@@ -69,9 +70,9 @@ const rootScope = (): Scope => ({ bindings: new Set(), read: new Set() });
69
70
  // unique name, so there is nothing to disambiguate and nothing to rename.
70
71
  export async function buildBundle(
71
72
  value: unknown,
72
- packageVersions: Readonly<Record<string, string>>,
73
+ provided: Modules,
73
74
  ): Promise<BundleTree> {
74
- const names = createNames(packageVersions);
75
+ const names = createNames(provided);
75
76
  // Each script's number, in the order rendering first reaches it. Two
76
77
  // scripts written at one source location are one declaration, so the first
77
78
  // script with an id stands for all of them, and a reference to a shared
@@ -177,6 +178,27 @@ export async function buildBundle(
177
178
  return label;
178
179
  };
179
180
 
181
+ // A `once` script is one value: its code run at the top of the bundle,
182
+ // where nothing encloses it, and every read is that constant. One per
183
+ // script, which is one per call of `once`, not per code: two runs of a host
184
+ // function that each make a context are two contexts, as two calls of
185
+ // `createContext` are. Running code is observable, so unlike a function it
186
+ // is never shared by code.
187
+ const values = new Map<ClientScript, string>();
188
+ const valueOf = (script: ClientScript): string => {
189
+ let label = values.get(script);
190
+ if (label === undefined) {
191
+ const code = call(
192
+ labelOf(scriptFor(script)),
193
+ exprCallArgs(script, rootScope()),
194
+ );
195
+ label = `$value${constants.length}`;
196
+ values.set(script, label);
197
+ constants.push([label, code]);
198
+ }
199
+ return label;
200
+ };
201
+
180
202
  // Writes a value as the code it becomes: composition as data, which is what
181
203
  // a bundle is. A script reference is a call naming which script and
182
204
  // what to hand it; everything else is its literal form. Rendered in order,
@@ -184,6 +206,9 @@ export async function buildBundle(
184
206
  // reached each script. Expansion has refused cycles, so it ends.
185
207
  const render = (value: unknown, scope: Scope = rootScope()): string => {
186
208
  if (isClientScript(value)) {
209
+ if (value.once) {
210
+ return valueOf(value);
211
+ }
187
212
  const target = scriptFor(value);
188
213
  if (target.module.kind !== "function") {
189
214
  return call(labelOf(target), exprCallArgs(value, scope));
@@ -276,7 +301,9 @@ export async function buildBundle(
276
301
  sourceName(key) +
277
302
  "` shadows it: the binding is still there, but no longer reachable by " +
278
303
  "name, and naming it anyway would mean emitting what the source " +
279
- "couldn't say.",
304
+ "couldn't say. A `once` script is made at the top of the bundle, " +
305
+ "outside every script, so a fragment spliced into one can't reach " +
306
+ "its binding either.",
280
307
  );
281
308
  };
282
309
 
@@ -1,4 +1,9 @@
1
- import { isClientImport, isClientScript, isJsxElement } from "@backtickjs/core";
1
+ import {
2
+ type ClientScript,
3
+ isClientImport,
4
+ isClientScript,
5
+ isJsxElement,
6
+ } from "@backtickjs/core";
2
7
 
3
8
  const CYCLE_ERROR =
4
9
  "Can't splice a value that contains itself: a bundle writes each value " +
@@ -28,9 +33,14 @@ const contains = (ancestors: Ancestors | null, value: object): boolean => {
28
33
  // each place it stands: the component itself never leaves the host, and only
29
34
  // the client code it bottoms out in reaches the bundle. A value holding no
30
35
  // server component comes back as the same object.
36
+ //
37
+ // A `once` script is one value, so what it splices is expanded once, however
38
+ // many places read it: a server component inside it runs once. `values` holds
39
+ // each one's expansion for the call.
31
40
  export async function expandServerComponents(
32
41
  value: unknown,
33
42
  ancestors: Ancestors | null = null,
43
+ values = new Map<ClientScript, Promise<unknown>>(),
34
44
  ): Promise<unknown> {
35
45
  if (typeof value !== "object" || value === null) {
36
46
  return value;
@@ -39,8 +49,10 @@ export async function expandServerComponents(
39
49
  throw new Error(CYCLE_ERROR);
40
50
  }
41
51
  const inside: Ancestors = { value, parent: ancestors };
42
- const all = (values: readonly unknown[]) =>
43
- Promise.all(values.map((entry) => expandServerComponents(entry, inside)));
52
+ const all = (entries: readonly unknown[]) =>
53
+ Promise.all(
54
+ entries.map((entry) => expandServerComponents(entry, inside, values)),
55
+ );
44
56
 
45
57
  if (isJsxElement(value)) {
46
58
  const { type } = value;
@@ -48,13 +60,28 @@ export async function expandServerComponents(
48
60
  if (typeof type !== "function" || isClientImport(type)) {
49
61
  return value;
50
62
  }
51
- return expandServerComponents(await type(value.props as never), inside);
63
+ return expandServerComponents(
64
+ await type(value.props as never),
65
+ inside,
66
+ values,
67
+ );
52
68
  }
53
69
  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 };
70
+ const expanded = async (): Promise<unknown> => {
71
+ const args = await all(value.args);
72
+ return args.every((arg, index) => arg === value.args[index])
73
+ ? value
74
+ : { ...value, args };
75
+ };
76
+ if (!value.once) {
77
+ return expanded();
78
+ }
79
+ let made = values.get(value);
80
+ if (made === undefined) {
81
+ made = expanded();
82
+ values.set(value, made);
83
+ }
84
+ return made;
58
85
  }
59
86
  if (Array.isArray(value)) {
60
87
  const elements = await all(value);
package/src/bundler.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  import type { Spliceable, SplicesAs } from "@backtickjs/core";
2
2
  import { buildBundle } from "./bundle/buildBundle.js";
3
+ import type { Modules } from "./modules.js";
3
4
  import { printBundle } from "./print/printBundle.js";
4
5
 
5
6
  export interface BuildOptions<T = Spliceable> {
6
7
  // What to bundle: what a splice could carry, checked as a splice checks it.
7
8
  readonly input: T;
8
- // The packages the client provides, each at its exact version: left out of
9
- // the bundle, which requires them. A script's import from any other, or
10
- // needing a version it doesn't have, throws.
11
- readonly packageVersions: Readonly<Record<string, string>>;
9
+ // The modules the client provides, by specifier, each at its package's
10
+ // exact version: left out of the bundle, which requires them. A script's
11
+ // import from any other, or needing a version it doesn't have, throws.
12
+ readonly modules: Modules;
12
13
  }
13
14
 
14
15
  export interface OutputOptions {
@@ -37,7 +38,7 @@ export interface Bundle {
37
38
  * What runs your components and hands back what they drew, shaped as Rollup
38
39
  * is: a build, then output from it.
39
40
  *
40
- * const bundle = await bundler.build({ input: <Home />, packageVersions });
41
+ * const bundle = await bundler.build({ input: <Home />, modules });
41
42
  * const { code, map } = bundle.generate({ format: "es", sourcemap: "hidden" });
42
43
  *
43
44
  * The module's default export is the value (CommonJS: `module.exports`). A
@@ -47,11 +48,11 @@ export interface Bundle {
47
48
  export const bundler = {
48
49
  async build<T extends [T] extends [SplicesAs<T>] ? unknown : Spliceable>({
49
50
  input,
50
- packageVersions,
51
+ modules,
51
52
  }: BuildOptions<T>): Promise<Bundle> {
52
53
  // Scripts come compiled for their framework when their host was built, so
53
54
  // the bundle is only put together: nothing is compiled or parsed here.
54
- const tree = await buildBundle(input, packageVersions);
55
+ const tree = await buildBundle(input, modules);
55
56
  return {
56
57
  generate: ({ format, sourcemap = false }) => {
57
58
  const { code, map } = printBundle(tree, format);
package/src/index.ts CHANGED
@@ -5,3 +5,4 @@ export {
5
5
  type OutputChunk,
6
6
  type OutputOptions,
7
7
  } from "./bundler.js";
8
+ export { type Modules, supports } from "./modules.js";
package/src/modules.ts ADDED
@@ -0,0 +1,21 @@
1
+ import semver from "semver";
2
+
3
+ /**
4
+ * The modules a client provides, by specifier, each at the exact version of
5
+ * the package it comes from: `{ "react/jsx-runtime": "19.2.3" }`.
6
+ */
7
+ export type Modules = Readonly<Record<string, string>>;
8
+
9
+ /**
10
+ * Whether a client with `modules` provides `specifier` at a version in
11
+ * `range`: the check a bundle's every import passes, so a server choosing
12
+ * what to draw for a client can ask it first.
13
+ */
14
+ export function supports(
15
+ modules: Modules,
16
+ specifier: string,
17
+ range: string,
18
+ ): boolean {
19
+ const provided = modules[specifier];
20
+ return provided !== undefined && semver.satisfies(provided, range);
21
+ }
package/src/print/code.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ClientImport } from "@backtickjs/core";
2
- import semver from "semver";
2
+ import { type Modules, supports } from "../modules.js";
3
3
 
4
4
  // What a bundle is written as, and the one place its conventions live: how a
5
5
  // name is written, how a literal escapes, and how an element is written as JSX
@@ -9,17 +9,15 @@ const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
9
9
 
10
10
  /**
11
11
  * What a bundle imports, keyed by specifier and export, each bound once; and
12
- * the packages it may import them from, which the client provides, by version.
12
+ * the modules it may import them from, which the client provides, by version.
13
13
  */
14
14
  export interface Names {
15
15
  readonly imports: Map<string, { from: string; name: string; local: string }>;
16
- readonly packageVersions: Readonly<Record<string, string>>;
16
+ readonly modules: Modules;
17
17
  }
18
18
 
19
- export function createNames(
20
- packageVersions: Readonly<Record<string, string>>,
21
- ): Names {
22
- return { imports: new Map(), packageVersions };
19
+ export function createNames(modules: Modules): Names {
20
+ return { imports: new Map(), modules };
23
21
  }
24
22
 
25
23
  // A string, as a literal: `<` escaped, so no `</script>` or `<!--` appears
@@ -80,13 +78,6 @@ function member(key: string): string {
80
78
  return IDENTIFIER.test(key) ? key : string(key);
81
79
  }
82
80
 
83
- // The package a module is in: its specifier's first segment, or first two
84
- // when scoped (`solid-js/web` → `solid-js`, `@scope/pkg/x` → `@scope/pkg`).
85
- function packageOf(from: string): string {
86
- const segments = from.split("/");
87
- return segments.slice(0, from.startsWith("@") ? 2 : 1).join("/");
88
- }
89
-
90
81
  /** An export of a module the client provides, imported by the bundle. */
91
82
  export function imported(
92
83
  names: Names,
@@ -94,21 +85,20 @@ export function imported(
94
85
  ): string {
95
86
  // Where a script's import is written: a plugin's own (a framework's compile
96
87
  // step) are the plugin's, trusted as it is.
97
- const pkg = packageOf(from);
98
- const provided = names.packageVersions[pkg];
88
+ const provided = names.modules[from];
99
89
  if (provided === undefined) {
100
- const packages = Object.entries(names.packageVersions).map(
101
- ([provided, at]) => `${provided}@${at}`,
90
+ const listed = Object.entries(names.modules).map(
91
+ ([specifier, at]) => `${specifier}@${at}`,
102
92
  );
103
93
  throw new Error(
104
94
  `Can't import \`${name}\` from "${from}": the client provides ` +
105
- `${packages.join(", ") || "no packages"}.`,
95
+ `${listed.join(", ") || "no modules"}.`,
106
96
  );
107
97
  }
108
- if (!semver.satisfies(provided, version)) {
98
+ if (!supports(names.modules, from, version)) {
109
99
  throw new Error(
110
- `Can't import \`${name}\` from "${from}": it needs ${pkg}@${version}, ` +
111
- `and the client provides ${pkg}@${provided}.`,
100
+ `Can't import \`${name}\` from "${from}": it needs ${version}, and ` +
101
+ `the client provides ${from}@${provided}.`,
112
102
  );
113
103
  }
114
104
  const key = `${from}\0${name}`;