You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Updated 2026-08-21. Phase 0 was overtaken by ad-hoc browser runs: the _LAPACK question (#927) was answered on the public numba-ecosystem demo, the intp question (#929) was settled in the #942 review, and PR #938 (merged as 481947d) has landed the deployment config and smoke suite under ci/wasm/. The checklist below is reworded to match those findings and the upstream Numba change that removed the expected gini_coefficient failure (patch 0010, emscripten-forge/recipes#6293); items with recorded browser evidence are ticked and a results table is maintained in the comments. The original text is preserved in the edit history.
Part of #925 (Phase 0). This issue was meant to gate #927 and calibrate #929 and #930; #927 was resolved by ad-hoc browser runs and #929 by the #942 review instead (see the checklist), so its remaining gating value is the cold/warm import timing for #930 and the first full-suite browser run via #933.
Goal
Prove the stack end-to-end with zero code changes, and convert every "should work" in the audit into a known. Because quantecon is noarch: python on conda-forge, there is a real chance it installs and imports in JupyterLite today with no packaging work.
This file is now committed as ci/wasm/environment.yml (PR #938). numba is unpinned, so a fresh build resolves the current emscripten-forge-4x build — numba 0.67.0 build 1 as of 2026-08-18, which carries patch 0010 (emscripten-forge/recipes#6293) forcing @njit(parallel=True) to the serial pipeline on Emscripten. Note that the browser results recorded so far did not come from this deployment: they came from the public numba-ecosystem demo (Numba 0.66.0) and the #942 review, so the versions per result are recorded in the table.
Smoke checklist
One representative function per Numba feature class used in the library:
qe.tauchen — plain lazy @njit (_fill_tauchen); qe.rouwenhorst is pure NumPy with no Numba at all, kept as a no-JIT control case
MarkovChain.simulate — lazy @njit kernel writing into a Python-allocated array (NRT allocation inside jitted code is exercised by simplex_grid and nelder_mead below)
qe.random.probvec — exercises the parallel-ufunc → cpu fallback (emscripten patch 0007)
quantecon.util.array.searchsorted — the deprecated objmode() shim
Deliverables
Results recorded in this issue as a table: function → works / fails / notes — started in the comments on 2026-08-21 with the rows that already had evidence (import, np.linalg.solve, support_enumeration, bare generator, simplex_grid); the remaining items are not yet run
What actually runs on Emscripten today is test_jupyterlite.py (driven by the job parked in #933), and it covers 5 of the 13 checklist items: import quantecon (untimed), tauchen, bare np.linalg.solve in @njit, support_enumeration and gini_coefficient. smoke_test.py is not yet shipped into the kernel, so rouwenhorst, MarkovChain.simulate, probvec, sample_without_replacement, the three optimize routines, lemke_howson, vertex_enumeration, simplex_grid, searchsorted and the import timing have no browser test until #933 wires in-kernel execution of smoke_test.py. A first green run of the parked job therefore fills at most 5 rows of the table, not 13.
Several of the committed tests also encode expectations that are already out of date; #933 (the runner job) currently notes only the test_support_enumeration hang, so the rest are being handed to it as follow-ups: test_gini_coefficient (xfail(IS_EMSCRIPTEN, strict=True)) and test_gini_fails_on_emscripten expect a failure that patch 0010 has removed; test_support_enumeration and test_vertex_enumeration have no hang guard; test_simplex_grid cites #929 where it should cite #944.
Note
Updated 2026-08-21. Phase 0 was overtaken by ad-hoc browser runs: the
_LAPACKquestion (#927) was answered on the public numba-ecosystem demo, theintpquestion (#929) was settled in the #942 review, and PR #938 (merged as 481947d) has landed the deployment config and smoke suite underci/wasm/. The checklist below is reworded to match those findings and the upstream Numba change that removed the expectedgini_coefficientfailure (patch 0010, emscripten-forge/recipes#6293); items with recorded browser evidence are ticked and a results table is maintained in the comments. The original text is preserved in the edit history.Part of #925 (Phase 0). This issue was meant to gate #927 and calibrate #929 and #930; #927 was resolved by ad-hoc browser runs and #929 by the #942 review instead (see the checklist), so its remaining gating value is the cold/warm import timing for #930 and the first full-suite browser run via #933.
Goal
Prove the stack end-to-end with zero code changes, and convert every "should work" in the audit into a known. Because quantecon is
noarch: pythonon conda-forge, there is a real chance it installs and imports in JupyterLite today with no packaging work.Setup
Build a minimal JupyterLite deployment with jupyterlite-xeus:
This file is now committed as
ci/wasm/environment.yml(PR #938).numbais unpinned, so a fresh build resolves the current emscripten-forge-4x build — numba 0.67.0 build 1 as of 2026-08-18, which carries patch 0010 (emscripten-forge/recipes#6293) forcing@njit(parallel=True)to the serial pipeline on Emscripten. Note that the browser results recorded so far did not come from this deployment: they came from the public numba-ecosystem demo (Numba 0.66.0) and the #942 review, so the versions per result are recorded in the table.Smoke checklist
One representative function per Numba feature class used in the library:
import quantecon— works (implicitly confirmed by the_numba_linalg_solvereproducer in WASM: support_enumeration and vertex_enumeration hang in the browser — root cause is jitted generators (numba.np.linalg._LAPACK verified working) #927 and thesimplex_gridreproducer in WASM: use int64 in comb_jit for consistent overflow guards on wasm32 #942; no timing recorded)import quantecon— timed, cold cache and warm cache (feeds WASM: reduce import-time eager Numba compilation #930; WASM: reduce import-time eager Numba compilation #930's "measure first" gate and PR WASM: defer eager Numba gufunc/jit compilation to first use (#930) #943 are currently proceeding without this number)qe.tauchen— plain lazy@njit(_fill_tauchen);qe.rouwenhorstis pure NumPy with no Numba at all, kept as a no-JIT control caseMarkovChain.simulate— lazy@njitkernel writing into a Python-allocated array (NRT allocation inside jitted code is exercised bysimplex_gridandnelder_meadbelow)qe.random.probvec— exercises the parallel-ufunc → cpu fallback (emscripten patch 0007)qe.random.sample_without_replacement— eagerguvectorize, expliciti8signatureoptimize:nelder_mead,brent_max,newtongame_theory.lemke_howsongame_theory.vertex_enumeration—numba.typed.Dict; also a jitted generator (_vertex_enumeration_gen), so expected to hang for the same reason assupport_enumeration(WASM: support_enumeration and vertex_enumeration hang in the browser — root cause is jitted generators (numba.np.linalg._LAPACK verified working) #927) — not yet rungame_theory.support_enumeration— FAILS: first call never returns. The_LAPACKquestion is answered (LAPACK works, see the next two items); the cause is the jitted generator_support_enumeration_gen— emscripten-forge patch 0002 exports onlyNumba_make_generator, not the lowercasenumba_make_generatorthe generator wrapper imports (WASM: support_enumeration and vertex_enumeration hang in the browser — root cause is jitted generators (numba.np.linalg._LAPACK verified working) #927, not yet reported upstream)@njitgenerator (for i in range(n): yield i) — FAILS (hangs on first call), recorded 2026-08-19 in WASM: support_enumeration and vertex_enumeration hang in the browser — root cause is jitted generators (numba.np.linalg._LAPACK verified working) #927; isolates the generator mechanism from quantecon's codenp.linalg.solveinside a scratch@njit— works (correct result on Numba 0.66.0;_numba_linalg_solvealso works), recorded in WASM: support_enumeration and vertex_enumeration hang in the browser — root cause is jitted generators (numba.np.linalg._LAPACK verified working) #927 on 2026-08-15 and 2026-08-19qe.gini_coefficient— expected to work, serially, on emscripten-forge numba ≥ 0.67.0 build 1 (patch 0010, Fallback Numba parallel JIT to serial on Emscripten emscripten-forge/recipes#6293, 2026-08-18); the@njit(parallel=True)failure mode this item originally expected no longer exists. Confirm it runs and time it — the serial O(n²) path is why the O(n log n) rewrite in WASM: remove @njit(parallel=True) from gini_coefficient via an O(n log n) rewrite #926 / PR Rewrite Gini coefficient in O(n log n) #937 still matters. No browser run of gini is recorded anywhere yetsimplex_grid— FAILS on a warm persistent cache:RuntimeError: no compiled object yet for <Library 'comb_jit'>atqe.simplex_grid(3, 4)(WASM: cache=True functions that link a cache-restored callee fail with "no compiled object yet" (simplex_grid → num_compositions_jit → comb_jit) #944; upstream Numba:RuntimeError: no compiled object yetemscripten-forge/recipes#6309, open). The 32-bitintpboundary is now a documentation question (WASM: audit 32-bit intp behaviour on wasm32 (overflow guards, simplex_index wrapping, dtypes) #929 is doc-only); left unticked because the boundary check itself was never reached and stays blocked behind WASM: cache=True functions that link a cache-restored callee fail with "no compiled object yet" (simplex_grid → num_compositions_jit → comb_jit) #944quantecon.util.array.searchsorted— the deprecatedobjmode()shimDeliverables
np.linalg.solve,support_enumeration, bare generator,simplex_grid); the remaining items are not yet runci/wasm/environment.ymlplus the suiteci/wasm/smoke_test.py(16 tests mapping onto the 13 checklist items, all passing natively), the Playwright harnessci/wasm/test_jupyterlite.pyand a native gate in.github/workflows/ci_wasm_smoke.yml(PR WASM: JupyterLite environment config and browser smoke suite #938, merged 2026-08-21 as 481947d). The Emscripten runner job is parked in WASM: add a WebAssembly/JupyterLite smoke-test job to CI #933Coverage of the browser harness
What actually runs on Emscripten today is
test_jupyterlite.py(driven by the job parked in #933), and it covers 5 of the 13 checklist items:import quantecon(untimed),tauchen, barenp.linalg.solvein@njit,support_enumerationandgini_coefficient.smoke_test.pyis not yet shipped into the kernel, sorouwenhorst,MarkovChain.simulate,probvec,sample_without_replacement, the threeoptimizeroutines,lemke_howson,vertex_enumeration,simplex_grid,searchsortedand the import timing have no browser test until #933 wires in-kernel execution ofsmoke_test.py. A first green run of the parked job therefore fills at most 5 rows of the table, not 13.Several of the committed tests also encode expectations that are already out of date; #933 (the runner job) currently notes only the
test_support_enumerationhang, so the rest are being handed to it as follow-ups:test_gini_coefficient(xfail(IS_EMSCRIPTEN, strict=True)) andtest_gini_fails_on_emscriptenexpect a failure that patch 0010 has removed;test_support_enumerationandtest_vertex_enumerationhave no hang guard;test_simplex_gridcites #929 where it should cite #944.Related
support_enumeration,vertex_enumeration);_LAPACKverified workingsimplex_gridfails withno compiled object yet for comb_jiton a warm cache; decision is to wait for upstream (Numba:RuntimeError: no compiled object yetemscripten-forge/recipes#6309)gini_coefficientO(n log n) rewrite; the browser confirmation of gini belongs here, not in WASM: remove @njit(parallel=True) from gini_coefficient via an O(n log n) rewrite #926's acceptance criteria