Skip to content

Commit fafa83d

Browse files
committed
fix: split jquery import in widgets
1 parent 3950049 commit fafa83d

3 files changed

Lines changed: 36 additions & 12 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Side-effect-only module: seed `globalThis.jQuery` / `$` BEFORE any
2+
// downstream code (jquery-ui via @jupyter-widgets/controls/slider) tries
3+
// to detect them.
4+
//
5+
// ES module evaluation is post-order across the dep graph. By isolating
6+
// this in its own file and importing it FIRST in runtime.ts, jquery
7+
// itself + this body run to completion before @jupyter-widgets/html-manager
8+
// (and the jquery-ui graph it pulls) start evaluating. If we kept this
9+
// inline in runtime.ts, all `import` statements would hoist together and
10+
// the assignment below would race jquery-ui's init.
11+
// @ts-expect-error — jquery has no bundled .d.ts
12+
import jquery from 'jquery';
13+
14+
const g = globalThis as unknown as { jQuery?: unknown; $?: unknown };
15+
if (!g.jQuery) g.jQuery = jquery;
16+
if (!g.$) g.$ = jquery;

packages/widgets/src/runtime.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
import type { CommProvider } from '@jupyter-kit/comm';
22

3-
// `@jupyter-widgets/controls` slider widgets transitively depend on
4-
// jquery-ui, which expects `jQuery` / `$` on the global scope at module
5-
// init. Browser bundlers don't auto-expose CJS-style globals, so we
6-
// must seed `globalThis` before the html-manager module loads (its
7-
// import graph reaches jquery-ui synchronously).
8-
// @ts-expect-error — jquery has no bundled .d.ts
9-
import jquery from 'jquery';
10-
const g = globalThis as unknown as { jQuery?: unknown; $?: unknown };
11-
if (!g.jQuery) g.jQuery = jquery;
12-
if (!g.$) g.$ = jquery;
13-
3+
// MUST be imported before @jupyter-widgets/html-manager. The shim sets
4+
// `globalThis.jQuery` (required by jquery-ui's slider init, which
5+
// @jupyter-widgets/controls pulls in synchronously). ES module imports
6+
// hoist together within a file, so inlining the assignment here would
7+
// race html-manager's evaluation. Keeping it as a separate side-effect
8+
// import puts jquery + the assignment fully ahead in the eval order.
9+
import './jquery-shim';
1410
import { HTMLManager } from '@jupyter-widgets/html-manager';
1511

1612
// Widget CSS is shipped with `@jupyter-widgets/controls` but html-manager only

packages/widgets/tsup.config.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
import { defineConfig } from 'tsup';
22

33
export default defineConfig({
4-
entry: ['src/index.ts', 'src/runtime.ts'],
4+
// jquery-shim is a separate entry (rather than inlined into runtime.ts)
5+
// so the consuming JS engine evaluates it as its own module — ES module
6+
// post-order then guarantees `globalThis.jQuery = ...` completes before
7+
// any html-manager import body (and the jquery-ui graph it pulls)
8+
// begins evaluating. Inlining loses that ordering because all `import`s
9+
// within a single file hoist above the body.
10+
entry: ['src/index.ts', 'src/runtime.ts', 'src/jquery-shim.ts'],
511
format: ['esm'],
612
dts: true,
713
sourcemap: true,
814
clean: true,
915
target: 'es2020',
16+
// @jupyter-widgets/* and friends stay external — bundling them in
17+
// surfaces esbuild's __require/__commonJS shims into the published dist,
18+
// and those break in some browser scenarios (Proxy traps trip on init,
19+
// Node-only branches throw). Downstream bundlers (Vite/webpack) handle
20+
// the upstream CJS-flavoured ESM without our intervention; we only need
21+
// to document the one Vite-specific config tweak (commonjsOptions).
1022
external: [
1123
'@jupyter-kit/core',
1224
'@jupyter-kit/comm',

0 commit comments

Comments
 (0)