@@ -23,9 +23,9 @@ https://github.com/psf/webassembly for more information.
2323
2424To cross compile to the `` wasm32-emscripten `` platform you need
2525[ the Emscripten compiler toolchain] ( https://emscripten.org/ ) ,
26- a Python interpreter, and an installation of Node version 18 or newer. Emscripten
27- version 3.1.42 or newer is recommended. All commands below are relative to a checkout
28- of the Python repository.
26+ a Python interpreter, and an installation of Node version 18 or newer.
27+ Emscripten version 3.1.73 or newer is recommended. All commands below are
28+ relative to a checkout of the Python repository.
2929
3030#### Install [ the Emscripten compiler toolchain] ( https://emscripten.org/docs/getting_started/downloads.html )
3131
@@ -50,7 +50,7 @@ sourced. Otherwise the source script removes the environment variable.
5050export EM_COMPILER_WRAPPER=ccache
5151```
5252
53- ### Compile and build Python interpreter
53+ #### Compile and build Python interpreter
5454
5555You can use ` python Tools/wasm/emscripten ` to compile and build targetting
5656Emscripten. You can do everything at once with:
@@ -70,6 +70,88 @@ instance, to do a debug build, you can use:
7070python Tools/wasm/emscripten build --with-py-debug
7171```
7272
73+ ### Running from node
74+
75+ If you want to run the normal Python CLI, you can use ` python.sh ` . It takes the
76+ same options as the normal Python CLI entrypoint, though the REPL does not
77+ function and will crash.
78+
79+ ` python.sh ` invokes ` node_entry.mjs ` which imports the Emscripten module for the
80+ Python process and starts it up with the appropriate settings. If you wish to
81+ make a node application that "embeds" the interpreter instead of acting like the
82+ CLI you will need to write your own alternative to ` node_entry.mjs ` .
83+
84+
85+ ### The Web Example
86+
87+ When building for Emscripten, the web example will be built automatically. It is
88+ in the `` web_example `` directory. To run the web example, `` cd `` into the
89+ `` web_example `` directory, then run `` python server.py `` . This will start a web
90+ server; you can then visit `` http://localhost:8000/python.html `` in a browser to
91+ see a simple REPL example.
92+
93+ The web example relies on a bug fix in Emscripten version 3.1.73 so if you build
94+ with earlier versions of Emscripten it may not work. The web example uses
95+ `` SharedArrayBuffer `` . For security reasons browsers only provide
96+ `` SharedArrayBuffer `` in secure environments with cross-origin isolation. The
97+ webserver must send cross-origin headers and correct MIME types for the
98+ JavaScript and WebAssembly files. Otherwise the terminal will fail to load with
99+ an error message like `` ReferenceError: SharedArrayBuffer is not defined `` . See
100+ more information here:
101+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements
102+
103+ Note that `` SharedArrayBuffer `` is _ not required_ to use Python itself, only the
104+ web example. If cross-origin isolation is not appropriate for your use case you
105+ may make your own application embedding ` python.mjs ` which does not use
106+ `` SharedArrayBuffer `` and serve it without the cross-origin isolation headers.
107+
108+ ### Embedding Python in a custom JavaScript application
109+
110+ You can look at ` python.worker.mjs ` and ` node_entry.mjs ` for inspiration. At a
111+ minimum you must import `` createEmscriptenModule `` and you need to call
112+ `` createEmscriptenModule `` with an appropriate settings object. This settings
113+ object will need a prerun hook that installs the Python standard library into
114+ the Emscripten file system.
115+
116+ #### NodeJs
117+
118+ In Node, you can use the NodeFS to mount the standard library in your native
119+ file system into the Emscripten file system:
120+ ``` js
121+ import createEmscriptenModule from " ./python.mjs" ;
122+
123+ await createEmscriptenModule ({
124+ preRun (Module ) {
125+ Module .FS .mount (
126+ Module .FS .filesystems .NODEFS ,
127+ { root: " /path/to/python/stdlib" },
128+ " /lib/" ,
129+ );
130+ },
131+ });
132+ ```
133+
134+ #### Browser
135+
136+ In the browser, the simplest approach is to put the standard library in a zip
137+ file it and install it. With Python 3.14 this could look like:
138+ ``` js
139+ import createEmscriptenModule from " ./python.mjs" ;
140+
141+ await createEmscriptenModule ({
142+ async preRun (Module ) {
143+ Module .FS .mkdirTree (" /lib/python3.14/lib-dynload/" );
144+ Module .addRunDependency (" install-stdlib" );
145+ const resp = await fetch (" python3.14.zip" );
146+ const stdlibBuffer = await resp .arrayBuffer ();
147+ Module .FS .writeFile (` /lib/python314.zip` , new Uint8Array (stdlibBuffer), {
148+ canOwn: true ,
149+ });
150+ Module .removeRunDependency (" install-stdlib" );
151+ },
152+ });
153+ ```
154+
73155### Limitations and issues
74156
75157#### Network stack
@@ -151,38 +233,6 @@ python Tools/wasm/emscripten build --with-py-debug
151233- Test modules are disabled by default. Use `` --enable-test-modules `` build
152234 test modules like `` _testcapi `` .
153235
154- ### wasm32-emscripten in node
155-
156- Node builds use `` NODERAWFS `` .
157-
158- - Node RawFS allows direct access to the host file system without need to
159- perform `` FS.mount() `` call.
160-
161- ### Hosting Python WASM builds
162-
163- The simple REPL terminal uses SharedArrayBuffer. For security reasons
164- browsers only provide the feature in secure environments with cross-origin
165- isolation. The webserver must send cross-origin headers and correct MIME types
166- for the JavaScript and WASM files. Otherwise the terminal will fail to load
167- with an error message like `` Browsers disable shared array buffer `` .
168-
169- #### Apache HTTP .htaccess
170-
171- Place a `` .htaccess `` file in the same directory as `` python.wasm `` .
172-
173- ```
174- # .htaccess
175- Header set Cross-Origin-Opener-Policy same-origin
176- Header set Cross-Origin-Embedder-Policy require-corp
177-
178- AddType application/javascript js
179- AddType application/wasm wasm
180-
181- <IfModule mod_deflate.c>
182- AddOutputFilterByType DEFLATE text/html application/javascript application/wasm
183- </IfModule>
184- ```
185-
186236## WASI (wasm32-wasi)
187237
188238See [ the devguide on how to build and run for WASI] ( https://devguide.python.org/getting-started/setup-building/#wasi ) .
0 commit comments