@@ -68,9 +68,11 @@ def do_GET(self) -> bytes | None:
6868 }
6969 }
7070 function startPyWorker() {
71+ window.pyworker_failed = false;
7172 window.pyworker = new Worker("worker.js");
7273 window.pyworker.onmessage = capturelogs;
7374 window.pyworker.onerror = (evt) => {
75+ window.pyworker_failed = true;
7476 window.python_logs.push(...new TextEncoder().encode(
7577 `Worker error: ${evt.message}\n `));
7678 if (window.python_done_callback) {
@@ -99,25 +101,17 @@ def do_GET(self) -> bytes | None:
99101 self.postMessage({print:databytes});
100102 return databytes.length;
101103 }
102- function log(message) {
103- do_print(new TextEncoder().encode(`[worker] ${message}\n `));
104- }
105104 onmessage = async function (e) {
106105 const data = e.data;
107106 try {
108107 if (!self.pyodide) {
109- log("loading Pyodide");
110108 self.pyodide = await loadPyodide();
111- log("loaded Pyodide");
112109 }
113110 self.pyodide.setStdout({write:do_print,isatty:data.isatty});
114111 self.pyodide.setStderr({write:do_print,isatty:data.isatty});
115112
116- log("loading packages from imports");
117113 await self.pyodide.loadPackagesFromImports(data.python);
118- log("running Python");
119114 let results = await self.pyodide.runPythonAsync(data.python);
120- log("Python completed");
121115 self.postMessage({results});
122116 } catch (error) {
123117 do_print(new TextEncoder().encode(
@@ -228,8 +222,6 @@ class BrowserDriver:
228222 def __init__ (self , hostname , port , driver ):
229223 self .driver = driver
230224 self .driver .get (f"http://{ hostname } :{ port } /test.html" )
231- # Chrome on CI takes longer than locally to compile.
232- self .driver .set_script_timeout (1200 )
233225
234226 def load_pyodide (self , dist_dir ):
235227 pass
@@ -239,7 +231,12 @@ def load_arrow(self):
239231 f"await pjs.loadPackage('{ PYARROW_WHEEL_PATH .name } ')\n " )
240232 for attempt in range (3 ):
241233 try :
242- return self .execute_python (code , timeout = 300 )
234+ result = self .execute_python (code , timeout = 300 )
235+ if result :
236+ raise RuntimeError (
237+ "PyArrow wheel failed to load in browser "
238+ f"(exit status { result } ), see log above" )
239+ return result
243240 except TimeoutError :
244241 if attempt == 2 :
245242 raise TimeoutError (
@@ -274,18 +271,23 @@ def wait_for_done(self, timeout=None):
274271 start = last_heartbeat = time .monotonic ()
275272 while True :
276273 # poll for console.log messages from our webworker
277- # which are the output of pytest
278- lines = self .driver .execute_script (
279- "let temp = window.python_logs;window.python_logs=[];return temp;"
274+ # (output of pytest), completion and worker death
275+ state = self .driver .execute_script (
276+ "let logs = window.python_logs; window.python_logs = [];"
277+ "return {logs: logs, done: window.python_script_done,"
278+ " failed: window.pyworker_failed === true};"
280279 )
280+ lines = state .get ("logs" ) or []
281281 if len (lines ) > 0 :
282282 sys .stdout .buffer .write (bytes (lines ))
283283 sys .stdout .buffer .flush ()
284- done = self . driver . execute_script ( "return window.python_script_done; " )
284+ done = state . get ( "done " )
285285 if done is not None :
286- value = done ["result" ]
287286 self .driver .execute_script ("delete window.python_script_done;" )
288- return value
287+ return done ["result" ]
288+ if state .get ("failed" ):
289+ raise RuntimeError (
290+ "Browser-side worker died. See 'Worker error:' in log above" )
289291 now = time .monotonic ()
290292 if timeout is not None and now - start > timeout :
291293 raise TimeoutError
0 commit comments