()
| 140 | } |
| 141 | |
| 142 | async function main() { |
| 143 | let py; |
| 144 | try { |
| 145 | py = await loadPyodide({ |
| 146 | args, |
| 147 | _sysExecutable, |
| 148 | env: Object.assign( |
| 149 | { |
| 150 | PYTHONINSPECT: "", |
| 151 | // In Windows, passing _sysExecutable doesn't seem to set sys.executable to python.bat |
| 152 | // since the python.bat batch file is not a real executable that Python interpreter can inspect. |
| 153 | // Therefore, we force set PYTHONEXECUTABLE here to ensure sys.executable is correct. |
| 154 | PYTHONEXECUTABLE: windowsPathToUnix(_sysExecutable), |
| 155 | }, |
| 156 | process.env, |
| 157 | { HOME: windowsPathToUnix(process.cwd()) }, |
| 158 | ), |
| 159 | fsInit, |
| 160 | }); |
| 161 | } catch (e) { |
| 162 | if (e.constructor.name !== "ExitStatus") { |
| 163 | throw e; |
| 164 | } |
| 165 | // If the user passed `--help`, `--version`, or a set of command line |
| 166 | // arguments that is invalid in some way, we will exit here. |
| 167 | process.exit(e.status); |
| 168 | } |
| 169 | py.setStdout(); |
| 170 | py.setStderr(); |
| 171 | let sideGlobals = py.runPython("{}"); |
| 172 | function handleExit(code) { |
| 173 | if (code === undefined) { |
| 174 | code = 0; |
| 175 | } |
| 176 | |
| 177 | // Workaround: some native extensions don't implement |
| 178 | // tp_traverse, so Py_FinalizeEx may destroy type objects before their |
| 179 | // instances, crashing on stale function pointers in Wasm. |
| 180 | // Force-clearing modules and running GC here while types are still alive to |
| 181 | // avoid fatal errors during finalization. |
| 182 | // See: |
| 183 | // 1. https://pyo3.rs/v0.24.2/class/protocols.html#garbage-collector-integration |
| 184 | // 2. tp_traverse: https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse |
| 185 | // 3. https://github.com/pyodide/pyodide/issues/6234 |
| 186 | try { |
| 187 | py.runPython("import sys, gc; sys.modules.clear(); gc.collect()"); |
| 188 | } catch (e) { |
| 189 | // Best-effort — proceed to finalization even if this fails. |
| 190 | } |
| 191 | try { |
| 192 | if (py._module._Py_FinalizeEx() < 0) { |
| 193 | code = 120; |
| 194 | } |
| 195 | } catch (e) { |
| 196 | // During interpreter finalization, Python modules are being torn down. |
| 197 | // If a remaining live object triggers an error, we try to format it via sys.excepthook. |
| 198 | // However when there is a fatal error that we cannot process (e.g. function signature mismatch) |
| 199 | // excephook itself will fail and we cannot recover. |
no test coverage detected
searching dependent graphs…