@m4l-jweb/build 1.2.0 → 1.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m4l-jweb/build",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "m4l-jweb: the CLI that builds and packages a device repo into installable Max for Live devices.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,6 +34,6 @@
34
34
  "archiver": "^7.0.1",
35
35
  "esbuild": "^0.25.0",
36
36
  "typescript": "^5.7.0",
37
- "@m4l-jweb/wrapper": "1.2.0"
37
+ "@m4l-jweb/wrapper": "1.2.1"
38
38
  }
39
39
  }
package/src/chains.mjs CHANGED
@@ -112,42 +112,6 @@ export function claimAppMessages(ctx, routeId, unmatchedOutlet) {
112
112
  export const AUDIO_IN = "obj-plugin";
113
113
  export const AUDIO_OUT = "obj-plugout";
114
114
 
115
- /**
116
- * A [buffer~] name that is unique PER DEVICE INSTANCE.
117
- *
118
- * THE BUG THIS EXISTS TO KILL. Buffer names are GLOBAL to Max, and they used to be
119
- * generated from the device name alone (`buf-<device>-<slot>`) and frozen into the
120
- * patcher at BUILD time. So two copies of one device - a drum rack on two tracks, which
121
- * is the normal case, not an exotic one - named their buffers identically, and Max gave
122
- * both to whichever loaded last. One rack's samples silently became the other's. No
123
- * error, no console line: just the wrong sound.
124
- *
125
- * A name minted by the wrapper after load cannot reach a box frozen at build time (a
126
- * buffer takes its name from its creation argument and there is no documented runtime
127
- * rename), so the scoping has to be a load-time substitution Max itself performs.
128
- *
129
- * `#0` WAS TRIED AND DOES NOT WORK (spike run 2026-07-17 in Live; see
130
- * doc/MAX-FACTS.md). `#0` is documented for abstractions, and an .amxd device patcher turned out
131
- * not to count as one: the token stayed literal in every instance, so writer and
132
- * reader still agreed on one global name and the collision survived, silently.
133
- *
134
- * `---` IS THE MECHANISM BUILT FOR THIS. Max for Live replaces a leading `---` in a
135
- * name with an id unique to the DEVICE instance - and the scope is the whole device,
136
- * subpatchers and [poly~] voices included, not one patcher. That kills the `#0`/`#1`
137
- * hand-off the first attempt needed: the voice spells the SAME name the device does,
138
- * and no id has to travel through [poly~]'s arguments.
139
- *
140
- * OUTSIDE LIVE `---` stays literal (it is a Live-only substitution). Both writer and
141
- * reader keep agreeing, so a patcher opened in standalone Max degrades to the old
142
- * shared-name behavior instead of breaking - acceptable, since the devices only
143
- * meaningfully run in Live.
144
- */
145
- export const deviceBufName = (device, slot) => `---buf-${device?.name}-${slot}`;
146
-
147
- /** The same buffer, as a [poly~] voice spells it: identical - `---` scopes per DEVICE,
148
- * not per patcher, so the voice shares the expansion with the patcher that loaded it. */
149
- export const voiceBufName = (device, slot) => deviceBufName(device, slot);
150
-
151
115
  /**
152
116
  * How long a `remote` slot takes to slide to each new value, in ms.
153
117
  *
package/src/index.mjs CHANGED
@@ -184,6 +184,19 @@ export function composePatcher(base, d, surface) {
184
184
  const mode = d.mode ?? d.type;
185
185
  boxes.find((b) => b.box.id === "obj-js").box.text = `js wrapper.js ${mode}`;
186
186
 
187
+ /**
188
+ * The ring buffer between Chromium's audio thread and MSP, for the DEVICE PAGE's
189
+ * own `[jweb~]`.
190
+ *
191
+ * `window({ audio: true, latency })` has taken this since 1.1.0, and the device
192
+ * page could not - so a device that put its buffer at the documented maximum for
193
+ * its sounding WINDOW left its own page at the object default (~21 ms at 48 kHz)
194
+ * and went on dropping out. Two pages, one setting, and only one of them had it.
195
+ *
196
+ * Unset keeps the object's default. jweb~ clamps to 3x the minimum.
197
+ */
198
+ if (d.latency != null) boxes.find((b) => b.box.id === "obj-jweb").box.latency = d.latency;
199
+
187
200
  const unmatchedId = d.unmatchedTo === "js" ? "obj-js" : (d.unmatchedTo ?? "obj-js");
188
201
 
189
202
  /**
@@ -17,13 +17,13 @@
17
17
  "format": "prettier --write \"src/**/*.{ts,tsx,css}\" \"scripts/*.mjs\" \"patcher/*.mjs\""
18
18
  },
19
19
  "dependencies": {
20
- "@m4l-jweb/bridge": "^1.2.0",
21
- "@m4l-jweb/surface": "^1.2.0",
20
+ "@m4l-jweb/bridge": "^1.2.1",
21
+ "@m4l-jweb/surface": "^1.2.1",
22
22
  "react": "^19.0.0",
23
23
  "react-dom": "^19.0.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@m4l-jweb/build": "^1.2.0",
26
+ "@m4l-jweb/build": "^1.2.1",
27
27
  "@types/node": "^22.0.0",
28
28
  "@types/react": "^19.0.0",
29
29
  "@types/react-dom": "^19.0.0",
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "files": [],
3
- "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
3
+ "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }, { "path": "./tsconfig.test.json" }]
4
4
  }
@@ -0,0 +1,29 @@
1
+ {
2
+ // The TESTS, which nothing typechecked before.
3
+ //
4
+ // `tsconfig.app.json` covers `src`, `tsconfig.node.json` covers the scripts and the
5
+ // patcher - and `tests/` fell between them. That is fine for the `.mjs` suites, but
6
+ // a `.ts` one carrying `expectTypeOf` assertions was checking nothing at all: the
7
+ // assertion is a TYPE error or it is nothing, so an unchecked type test passes for
8
+ // the same reason a deleted one does. Referenced from the root solution, so a plain
9
+ // `tsc -b` (which the build runs first) fails on it.
10
+ "compilerOptions": {
11
+ "target": "ES2022",
12
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
13
+ "module": "ESNext",
14
+ "skipLibCheck": true,
15
+ "moduleResolution": "bundler",
16
+ "allowImportingTsExtensions": true,
17
+ "resolveJsonModule": true,
18
+ "allowJs": true,
19
+ "isolatedModules": true,
20
+ "moduleDetection": "force",
21
+ "noEmit": true,
22
+ "strict": true
23
+ },
24
+ // `vitest.config.ts` is listed alongside the tests, and not only to check it: a
25
+ // project whose include matches nothing at all is a tsc ERROR (TS18003), and a
26
+ // freshly scaffolded repo has no tests yet. One file that always exists keeps the
27
+ // project valid from the first minute.
28
+ "include": ["tests/**/*.ts", "vitest.config.ts"]
29
+ }