| 34 | } |
| 35 | |
| 36 | async function boot() { |
| 37 | self.postMessage({ type: "loading", text: "Downloading Python runtime…" }); |
| 38 | pyodide = await loadPyodide(); |
| 39 | pyodide.setStdout({ |
| 40 | write: (buf) => { |
| 41 | self.postMessage({ type: "stdout", text: decoder.decode(buf) }); |
| 42 | return buf.length; |
| 43 | }, |
| 44 | }); |
| 45 | pyodide.setStderr({ |
| 46 | write: (buf) => { |
| 47 | self.postMessage({ type: "stderr", text: decoder.decode(buf) }); |
| 48 | return buf.length; |
| 49 | }, |
| 50 | }); |
| 51 | // autoEOF:true — each input() invokes blockingStdin exactly once and treats |
| 52 | // its returned newline-terminated string as one complete line. |
| 53 | // (autoEOF:false makes Pyodide call stdin repeatedly until null → hangs.) |
| 54 | pyodide.setStdin({ stdin: blockingStdin, autoEOF: true }); |
| 55 | |
| 56 | // Syntax checker for the editor's lint squiggles. |
| 57 | pyodide.runPython(` |
| 58 | import json as _json |
| 59 | def _pybegin_lint(src): |
| 60 | try: |
| 61 | compile(src, "<editor>", "exec") |
| 62 | return "[]" |
| 63 | except SyntaxError as e: |
| 64 | return _json.dumps([{ |
| 65 | "line": e.lineno or 1, |
| 66 | "col": e.offset or 1, |
| 67 | "endLine": getattr(e, "end_lineno", None) or (e.lineno or 1), |
| 68 | "endCol": getattr(e, "end_offset", None) or ((e.offset or 1) + 1), |
| 69 | "msg": e.msg or "Syntax error", |
| 70 | }]) |
| 71 | except Exception as e: |
| 72 | return _json.dumps([{"line": 1, "col": 1, "endLine": 1, "endCol": 2, |
| 73 | "msg": type(e).__name__ + ": " + str(e)}]) |
| 74 | `); |
| 75 | self.postMessage({ type: "ready" }); |
| 76 | } |
| 77 | |
| 78 | const bootPromise = boot(); |
| 79 | |