diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 15ea249..0e43b7f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,7 +15,10 @@ jobs: with: build-artifact-name: none build-artifact-path: none - pyodide-versions: "0.29.3,0.28.3,0.27.2,0.26.4" + # 0.29.4 and 0.29.5 ship a broken coverage wheel (unresolved symbol + # MyFrame_BorrowCode in tracer.so) which crashes run_in_pyodide_coverage, + # so stay on 0.29.3 for the 0.29.x line. + pyodide-versions: "314.0.7,0.29.3,0.28.3,0.27.8,0.26.4" deploy: runs-on: ubuntu-24.04 diff --git a/.github/workflows/testall.yaml b/.github/workflows/testall.yaml index 0381345..d200805 100644 --- a/.github/workflows/testall.yaml +++ b/.github/workflows/testall.yaml @@ -53,7 +53,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 with: - python-version: 3.12 # keep this in sync with Pyodide's Python version + python-version: 3.12 - name: Build test matrix id: build-matrix run: | diff --git a/pytest_pyodide/runner.py b/pytest_pyodide/runner.py index bc48f97..c569682 100644 --- a/pytest_pyodide/runner.py +++ b/pytest_pyodide/runner.py @@ -438,8 +438,6 @@ class SeleniumFirefoxRunner(_SeleniumBaseRunner): browser = "firefox" def get_driver(self, jspi=False): - if jspi: - raise NotImplementedError("JSPI not supported in Firefox") from selenium.webdriver import Firefox from selenium.webdriver.firefox.options import Options from selenium.webdriver.firefox.service import Service @@ -462,9 +460,6 @@ def get_driver(self, jspi=False): options = Options() options.add_argument("--headless") options.add_argument("--no-sandbox") - if jspi: - options.add_argument("--enable-features=WebAssemblyExperimentalJSPI") - options.add_argument("--enable-experimental-webassembly-features") for flag in self._config.get_flags("chrome"): options.add_argument(flag) return Chrome(options=options) @@ -662,10 +657,13 @@ def init_node(self, jspi=False): ) extra_args = self._config.get_flags("node")[:] - # Node v14 require the --experimental-wasm-bigint which - # produces errors on later versions if jspi: - extra_args.append("--experimental-wasm-stack-switching") + if node_major <= 21: + raise RuntimeError( + f"Node version {node_version} is too old for jspi, please use node >= 22" + ) + if node_major <= 24: + extra_args.append("--experimental-wasm-jspi") self.p.sendline( f"node --expose-gc {' '.join(extra_args)} {curdir}/node_test_driver.js {self.base_url} {self.dist_dir}", diff --git a/tests/test_decorator.py b/tests/test_decorator.py index 2d479e0..a05a9d9 100644 --- a/tests/test_decorator.py +++ b/tests/test_decorator.py @@ -293,22 +293,29 @@ def check_refcount(selenium, n): import __main__ - assert sys.getrefcount(__main__.o) == n + # Don't call getrefcount inside the assert statement: pytest's assertion + # rewriting stores subexpressions in temporary locals, which adds an extra + # reference on Python <= 3.13 but not on 3.14+ (where locals are pushed to + # the stack as borrowed references). + refcount = sys.getrefcount(__main__.o) + assert refcount == n def test_selenium_handle(selenium): handle = returns_handle(selenium) - check_refcount(selenium, 4) + # References to __main__.o: the __main__ module dict, the _Py_IncRef done + # when the PyodideHandle was pickled, and the getrefcount argument. + check_refcount(selenium, 3) set_handle(selenium, handle, 7, 2) set_handle(selenium, handle, "b", 1) assert_get_handle(selenium, handle, "a", 6) assert_get_handle(selenium, handle, 7, 2) assert_get_handle(selenium, handle, "b", 1) - check_refcount(selenium, 4) + check_refcount(selenium, 3) # FIXME: refcount not decremented when deleting handle del handle - # check_refcount(selenium, 3) + # check_refcount(selenium, 2) def test_pytest_dot_skip(selenium): diff --git a/tests/test_fixture.py b/tests/test_fixture.py index 0200740..351ce11 100644 --- a/tests/test_fixture.py +++ b/tests/test_fixture.py @@ -33,7 +33,7 @@ def test_playwright_browsers(playwright_browsers, request): def test_jspi(selenium_jspi): from js import WebAssembly - assert hasattr(WebAssembly, "Suspender") + assert hasattr(WebAssembly, "Suspending") @run_in_pyodide diff --git a/utils/build_test_matrix.py b/utils/build_test_matrix.py index a874f16..598302d 100644 --- a/utils/build_test_matrix.py +++ b/utils/build_test_matrix.py @@ -12,9 +12,9 @@ DEFAULT_BROWSER = "chrome, firefox, node, safari, host" # at the time of writing, chrome latest (>131) times out. # xref: https://github.com/pyodide/pytest-pyodide/pull/146 -DEFAULT_CHROME_VERSION = "125" +DEFAULT_CHROME_VERSION = "153" DEFAULT_FIREFOX_VERSION = "latest" -DEFAULT_NODE_VERSION = "22" +DEFAULT_NODE_VERSION = "26" DEFAULT_PLAYWRIGHT_VERSION = "1.44.0" @@ -33,6 +33,10 @@ class VersionPair: def python_version_for_pyodide(pyodide_version: str) -> str: pyodide_ver = tuple(int(x) for x in pyodide_version.split(".")[:2]) + if pyodide_ver[0] > 0: + minor = str(pyodide_ver[0])[1:] + return f"3.{minor}" + for pair in PYODIDE_TO_PYTHON_VERSION: if pyodide_ver >= pair.pyodide_version: return pair.python_version