@@ -60,71 +60,73 @@ async function loadPyodideAndPackages(baseUrl = "", packages) {
6060 }
6161}
6262
63- const actions = {
64- async init ( data ) {
65- const { packages, baseUrl, cacheFileUrl } = data ;
66- self . cacheFileUrl = cacheFileUrl ;
67- try {
68- await loadPyodideAndPackages ( baseUrl , packages ) ;
63+ // A Map, so a message's action name can only reach these handlers and never
64+ // inherited Object methods like `constructor` (Object.hasOwn needs Chrome 93)
65+ const actions = new Map (
66+ Object . entries ( {
67+ async init ( data ) {
68+ const { packages, baseUrl, cacheFileUrl } = data ;
69+ self . cacheFileUrl = cacheFileUrl ;
70+ try {
71+ await loadPyodideAndPackages ( baseUrl , packages ) ;
6972
70- // override python input
71- await self . pyodide . runPython ( `import sys
73+ // override python input
74+ await self . pyodide . runPython ( `import sys
7275def input(prompt=''):
7376 print(prompt)
7477 return sys.stdin.readline().strip()
7578
7679__builtins__.input = input
7780` ) ;
78- self . postMessage ( {
79- action : "init" ,
80- success : true ,
81- } ) ;
82- } catch ( error ) {
83- postInitError ( error ) ;
84- }
85- } ,
86- async run ( data ) {
87- const { code } = data ;
88- if ( ! self . pyodide ) {
89- self . postMessage ( {
90- action : "run" ,
91- success : false ,
92- error : "Python is not loaded yet." ,
93- } ) ;
94- return ;
95- }
96- try {
97- await self . pyodide . loadPackagesFromImports ( code , {
98- messageCallback : stdout ,
99- errorCallback : stderr ,
100- } ) ;
101- const output = await self . pyodide . runPythonAsync ( code ) ;
102- self . postMessage ( {
103- action : "run" ,
104- success : true ,
105- output : output ?. toString ( ) ?? output ?? "" ,
106- } ) ;
107- } catch ( error ) {
108- self . postMessage ( {
109- action : "run" ,
110- success : false ,
111- error : error ?. message ?? error ?. toString ( ) ,
112- } ) ;
113- }
114- } ,
115- input ( data ) {
116- const { line } = data ;
117- self . line = line ;
118- } ,
119- } ;
81+ self . postMessage ( {
82+ action : "init" ,
83+ success : true ,
84+ } ) ;
85+ } catch ( error ) {
86+ postInitError ( error ) ;
87+ }
88+ } ,
89+ async run ( data ) {
90+ const { code } = data ;
91+ if ( ! self . pyodide ) {
92+ self . postMessage ( {
93+ action : "run" ,
94+ success : false ,
95+ error : "Python is not loaded yet." ,
96+ } ) ;
97+ return ;
98+ }
99+ try {
100+ await self . pyodide . loadPackagesFromImports ( code , {
101+ messageCallback : stdout ,
102+ errorCallback : stderr ,
103+ } ) ;
104+ const output = await self . pyodide . runPythonAsync ( code ) ;
105+ self . postMessage ( {
106+ action : "run" ,
107+ success : true ,
108+ output : output ?. toString ( ) ?? output ?? "" ,
109+ } ) ;
110+ } catch ( error ) {
111+ self . postMessage ( {
112+ action : "run" ,
113+ success : false ,
114+ error : error ?. message ?? error ?. toString ( ) ,
115+ } ) ;
116+ }
117+ } ,
118+ input ( data ) {
119+ const { line } = data ;
120+ self . line = line ;
121+ } ,
122+ } ) ,
123+ ) ;
120124
121125self . onmessage = async ( e ) => {
122- const { action } = e . data ;
126+ const handler = actions . get ( e . data . action ) ;
123127
124- // only the handlers defined above, never inherited Object methods
125- // biome-ignore lint/suspicious/noPrototypeBuiltins: Object.hasOwn needs Chrome 93, the build targets Chrome 90
126- if ( Object . prototype . hasOwnProperty . call ( actions , action ) ) {
127- await actions [ action ] ( e . data ) ;
128+ if ( handler ) {
129+ await handler ( e . data ) ;
128130 }
129131} ;
130132
0 commit comments