mithril-lynx 2.0.0 → 2.0.2

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.
@@ -70,7 +70,7 @@ y los `.d.ts` reales instalados en
70
70
  `fetch` está declarado como método del objeto `Lynx` dentro de
71
71
  `types/background-thread/` — **solo existe en el hilo background**, no
72
72
  en `common/` ni `main-thread/`. Encaja con la arquitectura entera de
73
- `mithril-lynx-v2` (toda la vista corre en background) — no hace falta
73
+ `mithril-lynx` (toda la vista corre en background) — no hace falta
74
74
  ningún puente cross-thread para esto.
75
75
 
76
76
  ### 2.2 La firma real, completa, sin recortar
@@ -290,7 +290,7 @@ cancelación y timeout reales, que en la primera pasada de esta
290
290
  investigación parecían imposibles — funciona.
291
291
 
292
292
  **Recomendación**: implementar el subconjunto confirmado como
293
- `mithril-lynx-v2/request`, documentando explícitamente (no escondiendo)
293
+ `mithril-lynx/request`, documentando explícitamente (no escondiendo)
294
294
  los 4-5 puntos sin equivalente, con una sugerencia directa de usar
295
295
  `lynx.fetch` nativo para esos casos puntuales.
296
296
 
package/README.md CHANGED
@@ -53,6 +53,14 @@ renderApp({ root: () => m(Counter) });
53
53
 
54
54
  `m.request`, reimplemented as a wrapper over Lynx's own `fetch`. See [`REQUEST.md`](./REQUEST.md) for the full API, and [`FETCH_INVESTIGATION.md`](./FETCH_INVESTIGATION.md) for the complete option-by-option gap analysis against the real `m.request` spec, backed by real-device evidence rather than docs/types alone (which were wrong twice during that investigation).
55
55
 
56
+ ## Custom fonts
57
+
58
+ Use a plain CSS `@font-face` rule — not `lynx.addFont()` (that JS API only fires post-mount, too late to win the first-frame race). Three gotchas, all confirmed on real hardware and inherited unchanged from the previous mithril-lynx (none of this is architecture-specific):
59
+
60
+ - **The font file must be `.ttf`, not `.woff2`** — a `.woff2` `@font-face` compiles fine but the native text renderer silently never applies it.
61
+ - **`font-family` set on `:root` (or any ancestor) does not cascade to descendants by default** — `pluginLynxConfig({ enableCSSInheritance: true })` turns that on.
62
+ - **A declarative `@font-face` resolves synchronously on the first native `__FlushElementTree()` call**, and that cost scales with how many text nodes resolve it — up to +2s of cold start on a mid/low-end device. Filed upstream as [lynx-family/lynx#9431](https://github.com/lynx-family/lynx/issues/9431). The workaround is a native-side prefetch hook, not a JS-level fix — see [`ANDROID_APK_GUIDE.md`](./ANDROID_APK_GUIDE.md) Part D for the full procedure, or scaffold it directly with `create-mithril-lynx`'s `--with-font <file.ttf>` flag.
63
+
56
64
  ## Known gaps
57
65
 
58
66
  - **`m.trust`** — not present. Stripped from `mithril-runtime` at the source, and Lynx's Element PAPI has no innerHTML-equivalent injection point to reimplement it against anyway (same permanent gap v1 documented).
@@ -72,3 +80,4 @@ Runs against `@lynx-js/testing-environment`'s real Element PAPI simulation via `
72
80
  - `.omo/plans/m-route-en-memoria.md` — how `m.route` was designed and verified for an in-memory, URL-less environment.
73
81
  - `.omo/plans/m-request-fetch-lynx.md` — the `m.request`-vs-`fetch` investigation plan and its execution log.
74
82
  - [`ROUTE.md`](./ROUTE.md), [`REQUEST.md`](./REQUEST.md), [`FETCH_INVESTIGATION.md`](./FETCH_INVESTIGATION.md) — user-facing reference docs for the two Lynx-specific reimplementations.
83
+ - [`ANDROID_APK_GUIDE.md`](./ANDROID_APK_GUIDE.md) — building a native Android host and APK from scratch, Gradle-CLI only, including the `.ttf` cold-start hack from "Custom fonts" above. Automated end to end by `create-mithril-lynx --android`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mithril-lynx",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Mithril.js on Lynx: real mithril/render/render.js driven through a Lynx-backed fake DOM, with an explicit single commit hook (no conditional global flush) and three reload modes (data-light, structural-light, full). A complete rewrite of the previous mithril-lynx (0.0.x).",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/plugin.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type { RsbuildPlugin } from "@lynx-js/rspeedy";
2
2
 
3
- export interface PluginMithrilLynxV2Options {
3
+ export interface PluginMithrilLynxOptions {
4
4
  targetSdkVersion?: string;
5
5
  liveReload?: boolean;
6
6
  }
7
7
 
8
- export function pluginMithrilLynxV2(options?: PluginMithrilLynxV2Options): RsbuildPlugin;
8
+ export function pluginMithrilLynx(options?: PluginMithrilLynxOptions): RsbuildPlugin;
package/plugin.js CHANGED
@@ -1,24 +1,26 @@
1
1
  // plugin.js
2
2
  //
3
3
  // Rspeedy/Rsbuild plugin wiring the two-bundle build (main-thread/Lepus +
4
- // background/JS) for mithril-lynx-v2 apps. Adapted from mithril-lynx v1's
5
- // plugin.js — this file is build TOOLING, not the redraw/reload mechanism
6
- // that motivated the v2 rewrite (see mithril-lynx-v2-desde-cero.md §2: v1's
7
- // bugs lived in the shim/commit/reload layer, never here), so it is reused
8
- // with fixes rather than rewritten from nothing. Two real changes from v1:
4
+ // background/JS) for mithril-lynx apps. Adapted from the previous
5
+ // mithril-lynx's plugin.js — this file is build TOOLING, not the
6
+ // redraw/reload mechanism that motivated the rewrite (see
7
+ // mithril-lynx-v2-desde-cero.md §2: the old bugs lived in the
8
+ // shim/commit/reload layer, never here), so it is reused with fixes
9
+ // rather than rewritten from nothing. Two real changes from the old one:
9
10
  //
10
11
  // 1. (F0.2 fix, the actual point of this file's existence in the plan)
11
12
  // `RuntimeWrapperWebpackPlugin`'s `test` regex now also matches
12
- // `.hot-update.js` chunks. v1's regex (`${name}/background\.js$`)
13
+ // `.hot-update.js` chunks. The old regex (`${name}/background\.js$`)
13
14
  // matched the initial background ASSET path (nested under
14
15
  // `.rspeedy/<name>/`, with a slash) but never the flat, double-
15
16
  // underscore-named hot-update chunk (`<name>__background.<hash>.hot-
16
17
  // update.js`) — confirmed with a plain regex test against both real
17
- // filenames, not a guess. That gap is the entire reason v1 needed a
18
- // runtime monkey-patch of `lynx.requireModuleAsync` in its dev-reload
19
- // client; v2's client has no such patch (see src/dev-reload-client.js).
18
+ // filenames, not a guess. That gap is the entire reason the old
19
+ // version needed a runtime monkey-patch of `lynx.requireModuleAsync`
20
+ // in its dev-reload client; this one's client has no such patch (see
21
+ // src/dev-reload-client.js).
20
22
  //
21
- // 2. Only ONE rendering mode exists (v2 plan §2 non-goals: no main-thread-
23
+ // 2. Only ONE rendering mode exists (plan §2 non-goals: no main-thread-
22
24
  // owned/data-channel modes) — so there is no mode-detection logic here,
23
25
  // `dev.hmr` is unconditionally on in dev, and every entry always gets a
24
26
  // background chunk.
@@ -31,7 +33,7 @@ import { fileURLToPath } from "node:url";
31
33
  import { RuntimeWrapperWebpackPlugin } from "@lynx-js/runtime-wrapper-webpack-plugin";
32
34
  import { LynxEncodePlugin, LynxTemplatePlugin } from "@lynx-js/template-webpack-plugin";
33
35
 
34
- const PLUGIN_NAME = "mithril-lynx-v2-template-webpack";
36
+ const PLUGIN_NAME = "mithril-lynx-template-webpack";
35
37
  const STYLE_CANDIDATES = ["style.css"];
36
38
 
37
39
  const DEV_RELOAD_CLIENT_PATH = path.join(
@@ -105,7 +107,7 @@ function packageRootOf(resolvedFile, expectedName) {
105
107
  return null;
106
108
  }
107
109
 
108
- export function pluginMithrilLynxV2(options = {}) {
110
+ export function pluginMithrilLynx(options = {}) {
109
111
  const targetSdkVersion = options.targetSdkVersion ?? "3.5";
110
112
  const liveReload = options.liveReload ?? true;
111
113
 
@@ -114,8 +116,9 @@ export function pluginMithrilLynxV2(options = {}) {
114
116
  setup(api) {
115
117
  api.expose(Symbol.for("LynxTemplatePlugin"), { LynxTemplatePlugin });
116
118
 
117
- // One mode only -> dev.hmr is unconditionally on in dev (v1 had to
118
- // detect renderer-mode-vs-not here; v2 has no "not").
119
+ // One mode only -> dev.hmr is unconditionally on in dev (the old
120
+ // version had to detect renderer-mode-vs-not here; there is no
121
+ // "not" to detect anymore).
119
122
  api.modifyRsbuildConfig({
120
123
  handler: (config, { mergeRsbuildConfig }) => mergeRsbuildConfig(config, { dev: { hmr: true } }),
121
124
  order: "post",
@@ -134,13 +137,12 @@ export function pluginMithrilLynxV2(options = {}) {
134
137
  });
135
138
 
136
139
  api.modifyBundlerChain((chain, { isDev, environment }) => {
137
- // Force a single resolved copy of "mithril-runtime" and
138
- // "mithril-lynx-v2" — a `file:`-linked local package can
139
- // otherwise resolve a second physical copy with its own
140
- // module-level state (this exact class of bug bit v1 twice:
141
- // mithril's emptyAttrs singleton, and mithril-lynx's own
142
- // per-app render state — see mithril-lynx/plugin.js's
143
- // comments for the on-device symptom).
140
+ // Force a single resolved copy of "mithril-runtime" — a
141
+ // `file:`-linked local package can otherwise resolve a
142
+ // second physical copy with its own module-level state
143
+ // (this exact class of bug bit the previous mithril-lynx:
144
+ // mithril's own emptyAttrs singleton, and that framework's
145
+ // own per-app render state).
144
146
  try {
145
147
  const appRequire = createRequire(path.join(process.cwd(), "package.json"));
146
148
  const mithrilDir = path.dirname(appRequire.resolve("mithril-runtime/package.json"));
@@ -148,17 +150,16 @@ export function pluginMithrilLynxV2(options = {}) {
148
150
  } catch {
149
151
  // App has no local "mithril-runtime" resolvable from its own root.
150
152
  }
151
- // Note: v1 also force-aliased its OWN package name here (a
152
- // second copy of mithril-lynx would mean two disconnected
153
- // renderers with separate module-level state — see
154
- // mithril-lynx/plugin.js's comment for the on-device
155
- // symptom). v2's per-app state lives inside closures created
156
- // by `renderApp()`/`setupRenderer()` calls, not module-level
157
- // variables — same class of bug can't reappear the same way,
158
- // so this dedup isn't reproduced here. Revisit if a
159
- // multi-copy scenario (npm link, a component library
160
- // nesting its own copy) turns up the same symptom in
161
- // practice.
153
+ // Note: the old mithril-lynx also force-aliased its OWN
154
+ // package name here (a second copy would mean two
155
+ // disconnected renderers with separate module-level state).
156
+ // This framework's per-app state lives inside closures
157
+ // created by `renderApp()`/`setupRenderer()` calls, not
158
+ // module-level variables — the same class of bug can't
159
+ // reappear the same way, so this dedup isn't reproduced
160
+ // here. Revisit if a multi-copy scenario (npm link, a
161
+ // component library nesting its own copy) turns up the same
162
+ // symptom in practice.
162
163
 
163
164
  const rawEntries = Object.entries(chain.entryPoints.entries() ?? {});
164
165
  chain.entryPoints.clear();
@@ -174,8 +175,8 @@ export function pluginMithrilLynxV2(options = {}) {
174
175
  const cssSource = findSibling(dir, STYLE_CANDIDATES);
175
176
  if (bgSource == null) {
176
177
  throw new Error(
177
- `[mithril-lynx-v2] entry "${name}": no sibling background.ts/background.js found next to ${mtSource}. ` +
178
- "mithril-lynx-v2 has exactly one rendering mode and it always needs a background entry — see the plan's §2 non-goals.",
178
+ `[mithril-lynx] entry "${name}": no sibling background.ts/background.js found next to ${mtSource}. ` +
179
+ "mithril-lynx has exactly one rendering mode and it always needs a background entry — see the plan's §2 non-goals.",
179
180
  );
180
181
  }
181
182
 
@@ -231,7 +232,7 @@ export function pluginMithrilLynxV2(options = {}) {
231
232
  );
232
233
 
233
234
  console.info(
234
- `[mithril-lynx-v2:build] entry="${name}" hmr=true liveReload=${liveReload} ` +
235
+ `[mithril-lynx:build] entry="${name}" hmr=true liveReload=${liveReload} ` +
235
236
  `bgEntry=${bgEntry} mtEntry=${mtEntry} targetSdk=${targetSdkVersion}`,
236
237
  );
237
238
  }
@@ -13,8 +13,8 @@
13
13
  // content) is not a guess — it's the same contract `mithril-lynx/CONTRACT.md`
14
14
  // + `mithril-lynx/src/lynx-mithril-shim.js` already validated on a real
15
15
  // device (see mithril-lynx/DEVICE_VERIFICATION.md). Reusing a validated
16
- // mapping here is exactly the kind of "concept, not code" reuse the v2 plan
17
- // allows (§2 non-goals) — the bug we're rewriting away lives in the
16
+ // mapping here is exactly the kind of "concept, not code" reuse the plan
17
+ // allows (§2 non-goals) — the bug this rewrite fixes lives in the
18
18
  // commit/reload layer (commit.js, reload/*.js), never in this mapping.
19
19
 
20
20
  import { Op } from "./patch-protocol.js";
@@ -138,7 +138,7 @@ export function createPatchApplier(pageId, { onEvent } = {}) {
138
138
  // as a test failure rather than a mystery on-device.
139
139
  if (name === "*") {
140
140
  throw new Error(
141
- "[mithril-lynx-v2] Clearing the whole `style` object at once is not implemented yet (F3 TODO) — set individual properties to \"\" instead.",
141
+ "[mithril-lynx] Clearing the whole `style` object at once is not implemented yet (F3 TODO) — set individual properties to \"\" instead.",
142
142
  );
143
143
  }
144
144
  __AddInlineStyle(handles.get(id), name, "");
@@ -169,7 +169,7 @@ export function createPatchApplier(pageId, { onEvent } = {}) {
169
169
  break;
170
170
  }
171
171
  default:
172
- throw new Error(`[mithril-lynx-v2] Unknown patch opcode: ${opcode}`);
172
+ throw new Error(`[mithril-lynx] Unknown patch opcode: ${opcode}`);
173
173
  }
174
174
  }
175
175
  __FlushElementTree();
package/src/channel.js CHANGED
@@ -15,8 +15,8 @@
15
15
  // v1's renderer/background.js and renderer/main-thread.js dispatching to
16
16
  // and listening on each other via exactly this pairing.
17
17
 
18
- export const patchEventName = "MithrilLynxV2:Patch";
19
- export const eventFromMainThreadEventName = "MithrilLynxV2:Event";
18
+ export const patchEventName = "MithrilLynx:Patch";
19
+ export const eventFromMainThreadEventName = "MithrilLynx:Event";
20
20
  export const renderPageEventName = "__RenderPage";
21
21
  export const destroyLifetimeEventName = "__DestroyLifetime";
22
22
 
package/src/commit.js CHANGED
@@ -1,24 +1,24 @@
1
1
  // src/commit.js
2
2
  //
3
3
  // The single, explicit, non-conditional flush contract — this is the actual
4
- // fix for the regression that motivated the whole v2 rewrite (see
4
+ // fix for the regression that motivated the whole rewrite (see
5
5
  // mithril-lynx-v2-desde-cero.md §3.4 and mithril-lynx/AGENTS.md's "Estado
6
- // actual" section for the v1 postmortem).
6
+ // actual" section for the old implementation's postmortem).
7
7
  //
8
- // v1's bug in one sentence: whether a redraw actually reached the main
8
+ // The old bug in one sentence: whether a redraw actually reached the main
9
9
  // thread depended on `typeof globalThis.__FlushElementTree === "function"`
10
10
  // — a question whose answer depended on thread/test/mode ordering. That is
11
11
  // a race condition baked into the architecture, not an edge case to patch.
12
12
  //
13
- // v2's rule: there is exactly one commit callback for the lifetime of one
14
- // `renderApp()` call (see background.js). It is installed explicitly, once,
15
- // by the code that owns the render — never discovered implicitly by
13
+ // The rule here: there is exactly one commit callback for the lifetime of
14
+ // one `renderApp()` call (see background.js). It is installed explicitly,
15
+ // once, by the code that owns the render — never discovered implicitly by
16
16
  // whoever happens to ask first. Asking to commit before installing one is a
17
17
  // programmer error and throws immediately and loudly, on the same tick,
18
18
  // with a message that says exactly what's missing — never a silently
19
- // frozen screen (which is what v1 did instead).
19
+ // frozen screen (which is what the old implementation did instead).
20
20
 
21
- const NOT_MOUNTED = Symbol("mithril-lynx-v2:not-mounted");
21
+ const NOT_MOUNTED = Symbol("mithril-lynx:not-mounted");
22
22
 
23
23
  export function createCommitController() {
24
24
  let commitFn = NOT_MOUNTED;
@@ -33,7 +33,7 @@ export function createCommitController() {
33
33
  install(fn) {
34
34
  if (commitFn !== NOT_MOUNTED) {
35
35
  throw new Error(
36
- "[mithril-lynx-v2] commit callback already installed. " +
36
+ "[mithril-lynx] commit callback already installed. " +
37
37
  "A shim instance is single-use: one renderApp() call, one " +
38
38
  "commit callback, for the lifetime of that background " +
39
39
  "context. If you're re-mounting for a reload, create a new " +
@@ -55,7 +55,7 @@ export function createCommitController() {
55
55
  commit() {
56
56
  if (commitFn === NOT_MOUNTED) {
57
57
  throw new Error(
58
- "[mithril-lynx-v2] commit() called before renderApp() mounted " +
58
+ "[mithril-lynx] commit() called before renderApp() mounted " +
59
59
  "the app. This is always a bug in the framework's own " +
60
60
  "wiring, never something app code can trigger by accident " +
61
61
  "— app code never calls commit() directly.",
@@ -114,7 +114,7 @@ function invokeCdpReload() {
114
114
  if (!data) return;
115
115
  try {
116
116
  var parsed = JSON.parse(data);
117
- if (parsed.error) console.error("[mithril-lynx-v2] Page.reload failed:", parsed.error.message);
117
+ if (parsed.error) console.error("[mithril-lynx] Page.reload failed:", parsed.error.message);
118
118
  } catch (e) {
119
119
  // response is not JSON — ignore
120
120
  }
@@ -129,7 +129,7 @@ function reload(reason) {
129
129
  if (socket) socket.close();
130
130
  if (!invokeCdpReload()) {
131
131
  console.warn(
132
- "[mithril-lynx-v2] Live reload unavailable: NativeModules.LynxDevToolSetModule.invokeCdp was not found.",
132
+ "[mithril-lynx] Live reload unavailable: NativeModules.LynxDevToolSetModule.invokeCdp was not found.",
133
133
  );
134
134
  }
135
135
  }
@@ -191,7 +191,7 @@ function handleMessage(rawMessage) {
191
191
  try {
192
192
  message = JSON.parse(rawMessage);
193
193
  } catch (e) {
194
- console.warn("[mithril-lynx-v2] Ignoring an invalid dev-server message.");
194
+ console.warn("[mithril-lynx] Ignoring an invalid dev-server message.");
195
195
  return;
196
196
  }
197
197
 
@@ -219,7 +219,7 @@ function handleMessage(rawMessage) {
219
219
  }
220
220
  break;
221
221
  case "errors":
222
- console.warn("[mithril-lynx-v2] Build failed; waiting for the next successful build.", message.data);
222
+ console.warn("[mithril-lynx] Build failed; waiting for the next successful build.", message.data);
223
223
  break;
224
224
  }
225
225
  }
@@ -230,11 +230,11 @@ function connect(retries) {
230
230
 
231
231
  socket = new WebSocket(socketURL(options));
232
232
  socket.onmessage = function (event) { handleMessage(event.data); };
233
- socket.onerror = function (error) { console.error("[mithril-lynx-v2] Dev server connection error:", error); };
233
+ socket.onerror = function (error) { console.error("[mithril-lynx] Dev server connection error:", error); };
234
234
  socket.onclose = function () {
235
235
  if (reloading) return;
236
236
  if (retries >= 10) {
237
- console.error("[mithril-lynx-v2] Unable to reconnect to the dev server.");
237
+ console.error("[mithril-lynx] Unable to reconnect to the dev server.");
238
238
  return;
239
239
  }
240
240
  var delay = 1000 * Math.pow(2, retries) + Math.random() * 100;
package/src/fake-dom.js CHANGED
@@ -21,7 +21,7 @@
21
21
  // Mithril's render.js at all — it only replays the recorded ops through
22
22
  // `apply-patch.js`, which calls the real Element PAPI directly. That split
23
23
  // is the point of the whole architecture (see
24
- // mithril-lynx-v2/.omo/plans/mithril-lynx-v2-desde-cero.md §3.1): only ONE
24
+ // .omo/plans/mithril-lynx-v2-desde-cero.md §3.1): only ONE
25
25
  // side needs to be "a DOM", the other side only needs to be "a PAPI patch
26
26
  // applier".
27
27
 
@@ -186,7 +186,7 @@ export class LynxElement extends LynxContainerNode {
186
186
  // CSS-text parser. Documented limitation, not a silent bug.
187
187
  if (typeof console !== "undefined") {
188
188
  console.warn(
189
- "[mithril-lynx-v2] Assigning a CSS text string to `style` is not supported; use a style object.",
189
+ "[mithril-lynx] Assigning a CSS text string to `style` is not supported; use a style object.",
190
190
  );
191
191
  }
192
192
  return;
@@ -265,7 +265,7 @@ export class LynxElement extends LynxContainerNode {
265
265
  // already-empty-or-not container.
266
266
  if (value !== "") {
267
267
  if (typeof console !== "undefined") {
268
- console.warn("[mithril-lynx-v2] Non-empty `textContent` assignment is not supported.");
268
+ console.warn("[mithril-lynx] Non-empty `textContent` assignment is not supported.");
269
269
  }
270
270
  return;
271
271
  }
@@ -280,7 +280,7 @@ export class LynxElement extends LynxContainerNode {
280
280
  // mithril-lynx/AGENTS.md history) rather than silently doing nothing
281
281
  // with no signal.
282
282
  if (typeof console !== "undefined") {
283
- console.warn("[mithril-lynx-v2] `m.trust()` / innerHTML is not supported on Lynx elements.");
283
+ console.warn("[mithril-lynx] `m.trust()` / innerHTML is not supported on Lynx elements.");
284
284
  }
285
285
  }
286
286
 
@@ -11,7 +11,7 @@
11
11
  //
12
12
  // Deliberately NOT a queue/pubsub of multiple mounted apps (real Mithril's
13
13
  // mount-redraw.js supports that because a browser page can `m.mount()`
14
- // several independent roots) — mithril-lynx-v2 has exactly one `renderApp()`
14
+ // several independent roots) — mithril-lynx has exactly one `renderApp()`
15
15
  // for the app's whole lifetime (plan §3.1), so "the current redraw
16
16
  // function" is a single slot, not a list.
17
17
  //
package/src/request.js CHANGED
@@ -36,7 +36,7 @@ function checkUnsupported(options) {
36
36
  for (const [name, matches] of UNSUPPORTED) {
37
37
  if (matches(options)) {
38
38
  throw new Error(
39
- `[mithril-lynx-v2/request] "${name}" is not supported — Lynx's fetch has no equivalent ` +
39
+ `[mithril-lynx/request] "${name}" is not supported — Lynx's fetch has no equivalent ` +
40
40
  "(see FETCH_INVESTIGATION.md for exactly why). This throws instead of silently " +
41
41
  "behaving differently from what you asked for.",
42
42
  );
@@ -78,7 +78,7 @@ export function createRequestor(fetchImpl) {
78
78
 
79
79
  if (typeof FormData !== "undefined" && options.body instanceof FormData) {
80
80
  throw new Error(
81
- "[mithril-lynx-v2/request] FormData bodies are not supported — Lynx has no FormData " +
81
+ "[mithril-lynx/request] FormData bodies are not supported — Lynx has no FormData " +
82
82
  "at runtime (confirmed absent, see FETCH_INVESTIGATION.md). Use lynx.fetch directly " +
83
83
  "if you have another way to send this data, or restructure it as plain JSON.",
84
84
  );
package/src/route.js CHANGED
@@ -13,7 +13,7 @@
13
13
  // `hasBeenResolved` gate) so porting route-using app code only requires
14
14
  // swapping the import, not relearning the control flow. The one
15
15
  // unavoidable signature change: `m.route(root, defaultRoute, routes)`
16
- // loses `root` — there is no DOM node to point it at in v2's architecture
16
+ // loses `root` — there is no DOM node to point it at in this architecture
17
17
  // (a single `renderApp()` for the app's whole lifetime, plan §3.1) — see
18
18
  // the plan §5.2 for why that's a deliberate, documented deviation rather
19
19
  // than a fake DOM node just to keep the arg count.
@@ -100,7 +100,7 @@ export function createRoute() {
100
100
  /**
101
101
  * @param {string} defaultRoute - Both the fallback for an unmatched path
102
102
  * AND the screen the app starts on — there is no browser URL to read
103
- * an initial path from, so this is the one path v2 always starts at
103
+ * an initial path from, so this is the one path the app always starts at
104
104
  * (the closest in-memory equivalent of React Router's
105
105
  * `initialEntries={["/"]}`).
106
106
  * @param {Record<string, unknown>} routes - Same shape as real
@@ -11,8 +11,8 @@ import { createPatchApplier } from "../src/apply-patch.js";
11
11
  // call anywhere in the view below) produces a second patch that updates
12
12
  // the real tree again.
13
13
  //
14
- // This is the direct replacement for mithril-lynx v1's
15
- // `test/renderer-integration.test.ts` — same intent, rewritten for the v2
14
+ // This is the direct replacement for the previous mithril-lynx's
15
+ // `test/renderer-integration.test.ts` — same intent, rewritten for this
16
16
  // architecture (see mithril-lynx-v2-desde-cero.md §F1's acceptance
17
17
  // criterion: this must pass from the first commit, never be fixed later).
18
18
 
@@ -14,7 +14,7 @@ describe("route.js + stable-host: a same-path re-resolve patches in place, never
14
14
  it("swapping the live-bound view (module.hot.accept's job) produces only a SetText, no Create/Remove", () => {
15
15
  lynxTestingEnv.switchToMainThread();
16
16
  const capturedOps: unknown[][] = [];
17
- lynx.getJSContext().addEventListener("MithrilLynxV2:Patch", (event: any) => {
17
+ lynx.getJSContext().addEventListener("MithrilLynx:Patch", (event: any) => {
18
18
  capturedOps.push(event.data);
19
19
  });
20
20
 
@@ -21,7 +21,7 @@ function setupRealTree() {
21
21
  // on the main-thread side so ops can be applied and the resulting real
22
22
  // tree inspected.
23
23
  lynxTestingEnv.switchToMainThread();
24
- lynx.getJSContext().addEventListener("MithrilLynxV2:Patch", (event: any) => {
24
+ lynx.getJSContext().addEventListener("MithrilLynx:Patch", (event: any) => {
25
25
  capturedOps.push(event.data);
26
26
  lynxTestingEnv.switchToMainThread();
27
27
  applier.applyPatch(event.data);
package/test/setup.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  // test/setup.ts
2
2
  //
3
3
  // The minimal gap-fill on top of @lynx-js/testing-environment's own PAPI
4
- // polyfill — same idea as mithril-lynx v1's testing.js, scoped down to only
5
- // what v2's apply-patch.js actually calls so far (no gestures/lists yet,
6
- // see the v2 plan's non-goals). `@lynx-js/testing-environment` already
4
+ // polyfill — same idea as the previous mithril-lynx's testing.js, scoped
5
+ // down to only what apply-patch.js actually calls so far (no gestures/lists
6
+ // yet, see the plan's non-goals). `@lynx-js/testing-environment` already
7
7
  // implements __CreateView/__CreateText/__CreateElement/__CreateRawText/
8
8
  // __AppendElement/__InsertElementBefore/__RemoveElement/__SetAttribute/
9
9
  // __SetClasses/__AddInlineStyle/__FlushElementTree/__GetElementUniqueID —
@@ -5,7 +5,7 @@ import { createVirtualBackend } from "../src/backends/virtual-backend.js";
5
5
  import { createLynxDocument } from "../src/fake-dom.js";
6
6
  import renderFactory from "mithril/render/render.js";
7
7
 
8
- // Tests the v2 plan's §3.6 hypothesis directly, WITHOUT a device: does
8
+ // Tests the plan's §3.6 hypothesis directly, WITHOUT a device: does
9
9
  // re-rendering the SAME root/document with a structurally different tree
10
10
  // (a sibling inserted next to an unrelated, focused-in-spirit node) reuse
11
11
  // the unrelated node's id — i.e. does it survive as the SAME element,
@@ -20,7 +20,7 @@ import renderFactory from "mithril/render/render.js";
20
20
  // `<input>` keeps keyboard focus and in-progress text is a device-only
21
21
  // question (F4's real acceptance criterion).
22
22
 
23
- describe("structural re-render reuses unrelated nodes (v2 plan §3.6 hypothesis)", () => {
23
+ describe("structural re-render reuses unrelated nodes (plan §3.6 hypothesis)", () => {
24
24
  it("does not recreate a sibling `input`-like node when a new node is inserted next to it", () => {
25
25
  const backend = createVirtualBackend();
26
26
  const document = createLynxDocument(backend);
@@ -35,7 +35,7 @@ describe("structural re-render reuses unrelated nodes (v2 plan §3.6 hypothesis)
35
35
  // Mithril's own (unkeyed-diff) middle-insertion trap to not apply —
36
36
  // without keys, an unkeyed diff treats "insert in the middle" as
37
37
  // "index 1 changed tag" and recreates everything from that index on,
38
- // which is a real Mithril behavior, not a v2 bug. The un-keyed case
38
+ // which is a real Mithril behavior, not a bug here. The un-keyed case
39
39
  // is deliberately NOT what this test asserts.
40
40
  let showExtra = false;
41
41
  function view() {