Skip to content

Commit f5a44fb

Browse files
committed
First batch of fixes
1 parent 001c85b commit f5a44fb

File tree

5 files changed

+39
-89
lines changed

5 files changed

+39
-89
lines changed

plans/wasm32-todo.md

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,53 @@
11
# wasm32 TODO (priority focus)
22

3+
Last local validation: 2026-02-19 (Pyodide cp313, Emscripten-4.0.9-wasm32).
4+
35
Scope for this list:
46
- DSL control-flow stability on wasm32 (runtime OOB risk).
57
- miniexpr fast-path enablement/coverage on wasm32.
68

79
## P0: unblock core DSL JIT stability (runtime safety)
810

9-
1. Remove the unconditional Emscripten skip in the wasm smoke test.
10-
- `tests/ndarray/test_wasm_dsl_jit.py:22`
11-
- Current blocker: `tests/ndarray/test_wasm_dsl_jit.py:24` skips on Emscripten.
12-
- Exit criteria: smoke runs and passes on Pyodide in CI (no skip).
11+
1. [x] Remove the unconditional Emscripten skip in the wasm smoke test.
12+
- Target: `tests/ndarray/test_wasm_dsl_jit.py::test_wasm_dsl_tcc_jit_smoke`
13+
- Result: skip removed, test now runs and passes on local Pyodide.
1314

14-
2. Stabilize full-control-flow DSL kernels on wasm32.
15-
- `tests/ndarray/test_dsl_kernels.py:350`
16-
- Current reason: "full DSL control-flow kernel is unstable on wasm32 (can trigger runtime OOB)".
17-
- Exit criteria: unskip and pass consistently.
15+
2. [x] Stabilize full-control-flow DSL kernels on wasm32.
16+
- Target: `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_full_control_flow_kept_as_dsl_function`
17+
- Result: skip removed, test now runs and passes on local Pyodide.
1818

19-
3. Stabilize while-loop DSL kernels on wasm32.
20-
- `tests/ndarray/test_dsl_kernels.py:376`
21-
- Current reason: "while-loop DSL kernel is unstable on wasm32 (can trigger runtime OOB)".
22-
- Exit criteria: unskip and pass consistently.
19+
3. [x] Stabilize while-loop DSL kernels on wasm32.
20+
- Target: `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_while_kept_as_dsl_function`
21+
- Result: skip removed, test now runs and passes on local Pyodide.
2322

24-
4. Stabilize scalar-parameter loop DSL kernels on wasm32.
25-
- `tests/ndarray/test_dsl_kernels.py:398`
26-
- Current reason: "scalar-param DSL loop kernel is unstable on wasm32 (can trigger runtime OOB)".
27-
- Exit criteria: unskip and pass consistently.
23+
4. [x] Stabilize scalar-parameter loop DSL kernels on wasm32.
24+
- Target: `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_accepts_scalar_param_per_call`
25+
- Result: skip removed, test now runs and passes on local Pyodide.
2826

2927
## P1: recover miniexpr fast-path coverage on wasm32
3028

31-
5. Re-enable DSL miniexpr fast-path instrumentation tests.
32-
- `tests/ndarray/test_dsl_kernels.py:202`
33-
- `tests/ndarray/test_dsl_kernels.py:259`
34-
- `tests/ndarray/test_dsl_kernels.py:284`
35-
- `tests/ndarray/test_dsl_kernels.py:422`
36-
- `tests/ndarray/test_dsl_kernels.py:467`
37-
- `tests/ndarray/test_dsl_kernels.py:505`
38-
- `tests/ndarray/test_dsl_kernels.py:531`
39-
- Current reason: "miniexpr fast path is not available on WASM".
40-
- Exit criteria: tests run (no skip) and validate `_set_pref_expr`/policy behavior on wasm.
41-
42-
6. Re-enable lazyexpr miniexpr fast-path behavior tests on wasm32.
43-
- `tests/ndarray/test_lazyexpr.py:1488`
44-
- `tests/ndarray/test_lazyexpr.py:1523`
45-
- `tests/ndarray/test_lazyexpr.py:1559`
46-
- `tests/ndarray/test_lazyexpr.py:1582`
47-
- Current reason: "miniexpr fast path is not available on WASM".
48-
- Exit criteria: tests run (no skip), fallback/strict semantics match non-wasm expectations.
49-
50-
7. Revisit int-cast DSL behavior currently expected to fail on wasm.
51-
- `tests/ndarray/test_dsl_kernels.py:312`
52-
- Current behavior on wasm: expects `RuntimeError("DSL kernels require miniexpr")`.
53-
- Exit criteria: either (a) supported and validated, or (b) explicitly documented as out-of-scope with rationale.
54-
55-
## Suggested validation order
56-
57-
1. `tests/ndarray/test_wasm_dsl_jit.py`
58-
2. `tests/ndarray/test_dsl_kernels.py -k "control_flow or while or scalar_param"`
59-
3. `tests/ndarray/test_dsl_kernels.py -k "miniexpr_fast_path or jit_policy_forwarding"`
60-
4. `tests/ndarray/test_lazyexpr.py -k "miniexpr_fast_path or strict_miniexpr or unary_negative_literal"`
29+
5. [x] Re-enable DSL miniexpr fast-path instrumentation tests.
30+
- Targets:
31+
- `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_index_symbols_keep_full_kernel`
32+
- `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_with_no_inputs_handles_windows_dtype_policy`
33+
- `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_index_symbols_float_cast_uses_miniexpr_fast_path`
34+
- `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_scalar_param_keeps_miniexpr_fast_path`
35+
- `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_scalar_float_cast_inlined_without_float_call`
36+
- `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_miniexpr_failure_raises_even_with_strict_disabled`
37+
- `tests/ndarray/test_dsl_kernels.py::test_lazyudf_jit_policy_forwarding`
38+
- Result: wasm skips removed and tests pass on local Pyodide.
39+
40+
6. [x] Re-enable lazyexpr miniexpr fast-path behavior tests on wasm32.
41+
- Targets:
42+
- `tests/ndarray/test_lazyexpr.py::test_lazyexpr_string_scalar_keeps_miniexpr_fast_path`
43+
- `tests/ndarray/test_lazyexpr.py::test_lazyexpr_unary_negative_literal_matches_subtraction`
44+
- `tests/ndarray/test_lazyexpr.py::test_lazyexpr_miniexpr_failure_falls_back_by_default`
45+
- `tests/ndarray/test_lazyexpr.py::test_lazyexpr_miniexpr_failure_raises_when_strict`
46+
- Fix applied: removed wasm-only non-DSL miniexpr gate in `src/blosc2/lazyexpr.py` (`fast_eval`).
47+
- Result: skips removed and all four tests pass on local Pyodide.
48+
49+
7. [ ] Revisit int-cast DSL behavior currently expected to fail on wasm.
50+
- Target: `tests/ndarray/test_dsl_kernels.py::test_dsl_kernel_index_symbols_int_cast_matches_expected_ramp`
51+
- Current local behavior (still expected): raises `RuntimeError` on wasm (`DSL kernels require miniexpr ... miniexpr compilation or execution failed`).
52+
- Rationale for keeping open: int-cast DSL/miniexpr on wasm remains unsupported in current runtime/backend.
53+
- Exit criteria: either (a) support `int(...)` casts in wasm miniexpr path, or (b) keep explicit unsupported policy with doc note.

src/blosc2/lazyexpr.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,10 +1334,6 @@ def fast_eval( # noqa: C901
13341334
expr_string = expression.dsl_source if is_dsl else expression
13351335
dsl_disable_reason = None
13361336

1337-
if blosc2.IS_WASM and not is_dsl:
1338-
# Keep wasm miniexpr scoped to DSL kernels until generic lazyexpr miniexpr paths are stabilized.
1339-
use_miniexpr = False
1340-
13411337
# Disable miniexpr for UDFs (callable expressions), except DSL kernels
13421338
if callable(expression) and not is_dsl:
13431339
use_miniexpr = False

tests/ndarray/test_dsl_kernels.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,6 @@ def test_dsl_kernel_integer_ops_kept_as_full_dsl_function():
200200

201201

202202
def test_dsl_kernel_index_symbols_keep_full_kernel(monkeypatch):
203-
if blosc2.IS_WASM:
204-
pytest.skip("miniexpr fast path is not available on WASM")
205-
206203
assert kernel_index_ramp.dsl_source is not None
207204
assert "def kernel_index_ramp(x):" in kernel_index_ramp.dsl_source
208205

@@ -257,9 +254,6 @@ def test_dsl_kernel_with_no_inputs_requires_shape_or_out():
257254

258255

259256
def test_dsl_kernel_with_no_inputs_handles_windows_dtype_policy(monkeypatch):
260-
if blosc2.IS_WASM:
261-
pytest.skip("miniexpr fast path is not available on WASM")
262-
263257
import importlib
264258

265259
lazyexpr_mod = importlib.import_module("blosc2.lazyexpr")
@@ -282,9 +276,6 @@ def test_dsl_kernel_index_symbols_float_cast_matches_expected_ramp():
282276

283277

284278
def test_dsl_kernel_index_symbols_float_cast_uses_miniexpr_fast_path(monkeypatch):
285-
if blosc2.IS_WASM:
286-
pytest.skip("miniexpr fast path is not available on WASM")
287-
288279
original_set_pref_expr = blosc2.NDArray._set_pref_expr
289280
captured = {"calls": 0, "expr": None}
290281

@@ -348,9 +339,6 @@ def test_dsl_kernel_bool_cast_numeric_matches_expected():
348339

349340

350341
def test_dsl_kernel_full_control_flow_kept_as_dsl_function():
351-
if blosc2.IS_WASM:
352-
pytest.skip("full DSL control-flow kernel is unstable on wasm32 (can trigger runtime OOB)")
353-
354342
assert kernel_control_flow_full.dsl_source is not None
355343
assert "def kernel_control_flow_full(x, y):" in kernel_control_flow_full.dsl_source
356344
assert "for i in range(4):" in kernel_control_flow_full.dsl_source
@@ -374,9 +362,6 @@ def test_dsl_kernel_full_control_flow_kept_as_dsl_function():
374362

375363

376364
def test_dsl_kernel_while_kept_as_dsl_function():
377-
if blosc2.IS_WASM:
378-
pytest.skip("while-loop DSL kernel is unstable on wasm32 (can trigger runtime OOB)")
379-
380365
assert kernel_while_full.dsl_source is not None
381366
assert "def kernel_while_full(x, y):" in kernel_while_full.dsl_source
382367
assert "while i < 3:" in kernel_while_full.dsl_source
@@ -396,9 +381,6 @@ def test_dsl_kernel_while_kept_as_dsl_function():
396381

397382

398383
def test_dsl_kernel_accepts_scalar_param_per_call():
399-
if blosc2.IS_WASM:
400-
pytest.skip("scalar-param DSL loop kernel is unstable on wasm32 (can trigger runtime OOB)")
401-
402384
assert kernel_loop_param.dsl_source is not None
403385
assert "def kernel_loop_param(x, y, niter):" in kernel_loop_param.dsl_source
404386
assert "for _i in range(niter):" in kernel_loop_param.dsl_source
@@ -420,9 +402,6 @@ def test_dsl_kernel_accepts_scalar_param_per_call():
420402

421403

422404
def test_dsl_kernel_scalar_param_keeps_miniexpr_fast_path(monkeypatch):
423-
if blosc2.IS_WASM:
424-
pytest.skip("miniexpr fast path is not available on WASM")
425-
426405
import importlib
427406

428407
lazyexpr_mod = importlib.import_module("blosc2.lazyexpr")
@@ -465,9 +444,6 @@ def wrapped_set_pref_expr(self, expression, inputs, fp_accuracy, aux_reduc=None,
465444

466445

467446
def test_dsl_kernel_scalar_float_cast_inlined_without_float_call(monkeypatch):
468-
if blosc2.IS_WASM:
469-
pytest.skip("miniexpr fast path is not available on WASM")
470-
471447
import importlib
472448

473449
lazyexpr_mod = importlib.import_module("blosc2.lazyexpr")
@@ -503,9 +479,6 @@ def wrapped_set_pref_expr(self, expression, inputs, fp_accuracy, aux_reduc=None,
503479

504480

505481
def test_dsl_kernel_miniexpr_failure_raises_even_with_strict_disabled(monkeypatch):
506-
if blosc2.IS_WASM:
507-
pytest.skip("miniexpr fast path is not available on WASM")
508-
509482
import importlib
510483

511484
lazyexpr_mod = importlib.import_module("blosc2.lazyexpr")
@@ -529,9 +502,6 @@ def failing_set_pref_expr(self, expression, inputs, fp_accuracy, aux_reduc=None,
529502

530503

531504
def test_lazyudf_jit_policy_forwarding(monkeypatch):
532-
if blosc2.IS_WASM:
533-
pytest.skip("miniexpr fast path is not available on WASM")
534-
535505
import importlib
536506

537507
lazyexpr_mod = importlib.import_module("blosc2.lazyexpr")

tests/ndarray/test_lazyexpr.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,7 +1484,6 @@ def test_numpy_funcs(array_fixture, func):
14841484
pytest.skip("NumPy version has no cumulative_sum function.")
14851485

14861486

1487-
@pytest.mark.skipif(blosc2.IS_WASM, reason="miniexpr fast path is not available on WASM")
14881487
def test_lazyexpr_string_scalar_keeps_miniexpr_fast_path(monkeypatch):
14891488
import importlib
14901489

@@ -1519,7 +1518,6 @@ def wrapped_set_pref_expr(self, expression, inputs, fp_accuracy, aux_reduc=None,
15191518
lazyexpr_mod.try_miniexpr = old_try_miniexpr
15201519

15211520

1522-
@pytest.mark.skipif(blosc2.IS_WASM, reason="miniexpr fast path is not available on WASM")
15231521
def test_lazyexpr_unary_negative_literal_matches_subtraction(monkeypatch):
15241522
import importlib
15251523

@@ -1555,7 +1553,6 @@ def wrapped_set_pref_expr(self, expression, inputs, fp_accuracy, aux_reduc=None,
15551553
lazyexpr_mod.try_miniexpr = old_try_miniexpr
15561554

15571555

1558-
@pytest.mark.skipif(blosc2.IS_WASM, reason="miniexpr fast path is not available on WASM")
15591556
def test_lazyexpr_miniexpr_failure_falls_back_by_default(monkeypatch):
15601557
import importlib
15611558

@@ -1578,7 +1575,6 @@ def failing_set_pref_expr(self, expression, inputs, fp_accuracy, aux_reduc=None,
15781575
lazyexpr_mod.try_miniexpr = old_try_miniexpr
15791576

15801577

1581-
@pytest.mark.skipif(blosc2.IS_WASM, reason="miniexpr fast path is not available on WASM")
15821578
def test_lazyexpr_miniexpr_failure_raises_when_strict(monkeypatch):
15831579
import importlib
15841580

tests/ndarray/test_wasm_dsl_jit.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
# SPDX-License-Identifier: BSD-3-Clause
66
#######################################################################
77

8-
import platform
9-
108
import numpy as np
119
import pytest
1210

@@ -20,9 +18,6 @@ def _wasm_kernel(x, y):
2018

2119
@pytest.mark.skipif(not blosc2.IS_WASM, reason="WASM-only integration test")
2220
def test_wasm_dsl_tcc_jit_smoke():
23-
if platform.system() == "Emscripten":
24-
pytest.skip("Known unstable path on current Pyodide runtime (can trigger wasm OOB)")
25-
2621
assert getattr(blosc2, "_WASM_MINIEXPR_ENABLED", False)
2722

2823
a_np = np.linspace(-1.0, 1.0, 64, dtype=np.float64).reshape(8, 8)

0 commit comments

Comments
 (0)