Commit 661c576
Phase 3: bump Electron 27 to 42 and adapt the changed APIs (#988)
* feat: bump Electron 27 to 42 and adapt the changed APIs
Electron 42 (Node 24, Chromium 148). Empirically the breaking surface is small
for this app (launched the built app on 42 and read the real failures):
- update-electron-app 2 to 3: v3 dropped the callable default export for a named
updateElectronApp; the old require('update-electron-app')() threw "require(...)
is not a function" at startup. Use the named import.
- File.path was removed in Electron 32: the welcome drag-drop handler now resolves
paths through webUtils.getPathForFile, exposed via the welcomeview preload
(webUtils is not available in the page world).
- @electron/notarize 3 (was electron-notarize 1): ESM, imported dynamically from
the CJS afterSign hook; the v2 tool and appBundleId keys are gone.
- electron-builder 24 to 26, electron-log 4 to 5: no source change needed
(electron-log's root export still carries transports.file; BrowserView is still
present at runtime on 42, so the WebContentsView migration is deferred, not
forced by the bump).
Note: AI-assisted (Claude Code). Manually verified: probed BrowserView and
File.path presence inside Electron 42 directly (BrowserView is still a function,
File.path is gone from the typings); tsc 0 errors, build clean, the app launches
on 42 with no runtime errors, 430 unit tests pass.
* build: set mac minimumSystemVersion to 12.0.0 for Electron 42
Electron raised its macOS floor to 12 at v38, so declare it in the builder mac
config. The electron-builder electronFuses hardening is intentionally not here;
it is tracked separately.
Note: AI-assisted (Claude Code). Manually verified: package.json parses.
* refactor: migrate BrowserView to WebContentsView
BrowserView is deprecated and slated for removal. Migrate the four view classes
(themed, lab, titlebar, welcome) to WebContentsView and the session window's
composition calls: addBrowserView to contentView.addChildView, removeBrowserView
to contentView.removeChildView, getBrowserViews() to contentView.children.
setBounds/setBackgroundColor/webContents are unchanged.
WebContentsView, unlike BrowserView, does not destroy its webContents when
removed from the window, so close it explicitly where a view is disposed rather
than reused: LabView.dispose() now closes its webContents (covering both the
session-stop and the switch-to-welcome paths), and the welcome view is closed
when it is swapped out for the lab view. The reused progress and env-select
popup views are removed without closing. _openDevTools now guards on
instanceof WebContentsView since contentView.children is typed View[].
Note: AI-assisted (Claude Code). Manually verified on the Electron 42 build:
tsc 0 errors, eslint clean, the app launches, the multi-view composition and
clean-shutdown e2e pass, the welcome-to-lab switch (python-env e2e) works, and
432 unit tests pass.
* deps: bump outdated dependencies, adapting which v7 and pinning ESM at last CJS
Patch/minor bumps (no API change): @playwright/test, @types/*, vitest +
coverage, typescript-eslint, webpack, js-yaml, semver, winreg, shx,
fast-xml-parser (5.9, XMLParser news parse re-verified), @leeoniya/ufuzzy.
Majors that are CJS-safe with stable API for this usage: @lumino/signaling 2
(Signal/ISignal unchanged), ejs 6 (render unchanged), fs-extra 11 + tar 7 +
istextorbinary 9 (build/extract APIs unchanged, still expose a require export).
which 2 to 7: v7 removed the callback API, so _getExecutableInstances is
rewritten to the promise form with nothrow.
ESM-only packages: pinned to their last CJS-capable major instead of the ESM
latest, since the main process is still CJS (require). yargs to 17.7.2 (18 is
ESM-only), meow to 9 (10+ ESM; flags schema unchanged so buildutil.js needs no
change), rimraf to 4.4.1 (5+ ESM; added --glob to the two conda-lock scripts
since rimraf 4 no longer globs by default). fix-path stays at 3 (4+ ESM).
Still deferred: @types/node (pinned to 24 to match Electron 42's Node), prettier
3 (reflows the whole repo, its own PR), webpack-cli 7 (moves with webpack core).
Note: AI-assisted (Claude Code). Manually verified: tsc 0, eslint clean, build,
432 unit tests, e2e against the Electron 42 dev build; probed each major's
runtime API (tar.x, ejs.render, Signal, which, isBinary, XMLParser.parse), ran
buildutil.js under meow 9 and a rimraf 4 removal.
* test: cover the news-feed parse and isolate the fast-xml-parser usage
Extract the RSS-to-news-items transform from WelcomeView into a pure
parseNewsFeed(xml) so the fast-xml-parser usage (which the project re-verifies
on every parser bump) is unit-tested instead of only eyeballed against the live
blog feed. Tests cover the title/link mapping, percent-encoded links, the
maxNewsToShow cap, the single-item isArray case, and empty/malformed feeds.
Note: AI-assisted (Claude Code). Manually verified: 6 parse tests pass, the
welcome view still renders in the e2e smoke, tsc 0, eslint clean.
* test: cover the bundled-env tarball extract and isolate the tar usage
Pull the tar.x call out of installCondaPackEnvironment into extractTarball(tar,
dest) so the tar usage (re-verified on every tar bump, now at v7) is unit-tested
against a real gzipped tarball roundtrip rather than only run during a full conda
env install. Tests assert nested files and contents extract, and that a missing
tarball rejects.
Note: AI-assisted (Claude Code). Manually verified: 2 extract tests pass against
a real tar.c/tar.x roundtrip, tsc 0, eslint clean.
* deps: refresh electron to 42.4.1 patch within range
Lockfile-only bump of electron from 42.4.0 to 42.4.1, inside the
^42.4.0 already declared in package.json. Part of landing Electron 42,
not a separate dependency-maintenance change: the patch clears the
remaining low-severity electron alerts on top of the 27 to 42 jump.
The only other movement is electron's own transitive subtree
re-resolving (a transitive semver lifts to 7.8.5).
Note: AI-assisted (Claude Code). Manually verified: lockfile diff is electron + its transitive closure only (no devDep or unrelated direct-dep movement); frozen install self-consistent; type-check 0, unit 440, build ok; e2e 4 pass / 1 skip was confirmed on electron 42.4.1.
* ci: run yarn jobs on Node 24 so which v7 installs
which v7 (pulled in by the Electron 42 dep bump) declares an engines
range of ^22.22.2 || ^24.15.0 || >=26.0.0, so the Node 20 install steps
fail with an incompatible-engine error before any test runs. Move the
three jobs that run yarn install (unit tests and the installer matrix in
publish.yml, the version-sync bot in sync_lab_release.yml) to Node 24,
which matches Electron 42's bundled Node. typecheck.yml and e2e.yml were
already on 24.
Note: AI-assisted (Claude Code). Manually verified: which engines range confirmed via its package.json; grepped all workflows so no yarn-install job is left on Node 20; local unit suite (440) runs on Node 24.
* refactor: tighten WebContentsView teardown comments
The lifecycle comments around the explicit webContents.close() calls were
imprecise. One claimed Electron destroys the child webContents for us when
the window is gone, which is the opposite of the actual behavior: a
WebContentsView's webContents is not destroyed on detach or window close,
which is why the close() is there in the first place. Reword both sites to
state that and point at electron/electron#42884. No code change.
Note: AI-assisted (Claude Code). Manually verified against electron/electron#42884 and the electron 42.4.1 typings (WebContentsView exposes only a readonly webContents, no destroy/close of its own; webContents has close/destroy/isDestroyed); the callers drop the view reference after closing so the renderer is reclaimed. tsc 0 errors, lint clean.
* Respect max number set to 0
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix: dispose the labView for remote sessions and guard re-dispose
_disposeSession's remote branch dereferenced this._labView without a
guard and only cleared the session, while the local branch already
guarded and disposed the view. After a remote non-persistent session is
closed, the window switches back to Welcome and nulls _labView; closing
the window then runs _disposeSession again and the remote branch threw a
TypeError on this._labView.view, so dispose rejected.
Fold the two branches so the labView teardown is shared and guarded.
LabView.dispose already clears the session for a non-persistent remote
session and closes the webContents, so routing remote sessions through
it fixes the crash, also closes the webContents the remote path used to
leak after the WebContentsView move (electron/electron#42884), and drops
the now-duplicated clearSession. Awaited so a non-persistent remote
session is cleared before the window goes away.
Note: AI-assisted (Claude Code). Manually verified: new regression test reproduces the null deref on the pre-fix code and passes after; full unit suite 441 green; tsc 0 errors; lint clean; traced the five _disposeSession callers and the close-to-Welcome path that leaves _labView null.
* deps: bump electron to 42.5.0 and refresh in-range deps
Lockfile-only refresh, all within the carets already in package.json:
electron 42.4.1 to 42.5.0, @playwright/test 1.61.1, fast-xml-parser
5.9.3, js-yaml 4.3.0, semver 7.8.5, tar 7.5.19, webpack 5.108.1. Left
the eslint toolchain (typescript-eslint, globals, eslint) to dependabot
since it belongs to the flat-config work, not this bump.
Note: AI-assisted (Claude Code). Manually verified: each resolved version moved as intended and the excluded toolchain deps did not; frozen install self-consistent; tsc 0, unit 441 (incl newsfeed and tar isolation tests), lint, build, e2e 4 pass / 1 skip on electron 42.5.0.
---------
Co-authored-by: Michał Krassowski <5832902+krassowski@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>1 parent a8cf84b commit 661c576
19 files changed
Lines changed: 1800 additions & 1153 deletions
File tree
- .github/workflows
- scripts
- src/main
- dialog
- labview
- sessionwindow
- titlebarview
- welcomeview
- test/unit
- preload
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
| 26 | + | |
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
62 | | - | |
| 62 | + | |
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
96 | | - | |
| 96 | + | |
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
34 | | - | |
| 33 | + | |
| 34 | + | |
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| |||
157 | 157 | | |
158 | 158 | | |
159 | 159 | | |
| 160 | + | |
160 | 161 | | |
161 | 162 | | |
162 | 163 | | |
| |||
182 | 183 | | |
183 | 184 | | |
184 | 185 | | |
| 186 | + | |
185 | 187 | | |
186 | 188 | | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
191 | 193 | | |
192 | | - | |
193 | | - | |
194 | | - | |
195 | | - | |
196 | | - | |
197 | | - | |
198 | | - | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
199 | 200 | | |
200 | 201 | | |
201 | 202 | | |
202 | | - | |
| 203 | + | |
203 | 204 | | |
204 | | - | |
205 | | - | |
| 205 | + | |
| 206 | + | |
206 | 207 | | |
207 | 208 | | |
208 | 209 | | |
209 | | - | |
210 | | - | |
| 210 | + | |
| 211 | + | |
211 | 212 | | |
212 | | - | |
213 | | - | |
214 | | - | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
215 | 216 | | |
216 | 217 | | |
217 | 218 | | |
218 | 219 | | |
219 | 220 | | |
220 | 221 | | |
221 | 222 | | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
226 | 227 | | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
233 | | - | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
234 | 235 | | |
235 | 236 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
5 | 3 | | |
6 | 4 | | |
7 | 5 | | |
| |||
11 | 9 | | |
12 | 10 | | |
13 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
14 | 17 | | |
15 | 18 | | |
16 | 19 | | |
17 | | - | |
18 | 20 | | |
19 | 21 | | |
20 | 22 | | |
21 | | - | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
567 | 568 | | |
568 | 569 | | |
569 | 570 | | |
570 | | - | |
| 571 | + | |
571 | 572 | | |
572 | 573 | | |
573 | 574 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
| 22 | + | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
122 | | - | |
| 122 | + | |
123 | 123 | | |
124 | 124 | | |
125 | 125 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | 5 | | |
7 | 6 | | |
8 | 7 | | |
9 | | - | |
| 8 | + | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
59 | | - | |
| 59 | + | |
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| |||
126 | 126 | | |
127 | 127 | | |
128 | 128 | | |
129 | | - | |
| 129 | + | |
130 | 130 | | |
131 | 131 | | |
132 | 132 | | |
| |||
305 | 305 | | |
306 | 306 | | |
307 | 307 | | |
308 | | - | |
| 308 | + | |
309 | 309 | | |
310 | 310 | | |
311 | 311 | | |
312 | 312 | | |
313 | 313 | | |
314 | | - | |
| 314 | + | |
| 315 | + | |
315 | 316 | | |
316 | | - | |
317 | | - | |
318 | | - | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
323 | 324 | | |
324 | 325 | | |
325 | 326 | | |
| |||
547 | 548 | | |
548 | 549 | | |
549 | 550 | | |
550 | | - | |
| 551 | + | |
551 | 552 | | |
552 | 553 | | |
553 | 554 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
992 | 992 | | |
993 | 993 | | |
994 | 994 | | |
995 | | - | |
| 995 | + | |
996 | 996 | | |
997 | 997 | | |
998 | 998 | | |
999 | | - | |
1000 | | - | |
1001 | | - | |
1002 | | - | |
1003 | | - | |
1004 | | - | |
1005 | | - | |
1006 | | - | |
1007 | | - | |
1008 | | - | |
1009 | | - | |
1010 | | - | |
1011 | | - | |
1012 | | - | |
1013 | | - | |
1014 | | - | |
1015 | | - | |
1016 | | - | |
1017 | | - | |
1018 | | - | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
1019 | 1005 | | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
1020 | 1010 | | |
1021 | 1011 | | |
1022 | 1012 | | |
| |||
0 commit comments