mirror of
https://github.com/python/cpython.git
synced 2026-05-10 14:41:01 -04:00
bfb0788bfc
Moves the Emscripten web example into a standalone folder, and updates Makefile targets to build the web example. Instructions for usage have also been added.
105 lines
3.0 KiB
JavaScript
105 lines
3.0 KiB
JavaScript
import createEmscriptenModule from "./python.mjs";
|
|
|
|
class StdinBuffer {
|
|
constructor() {
|
|
this.sab = new SharedArrayBuffer(128 * Int32Array.BYTES_PER_ELEMENT)
|
|
this.buffer = new Int32Array(this.sab)
|
|
this.readIndex = 1;
|
|
this.numberOfCharacters = 0;
|
|
this.sentNull = true
|
|
}
|
|
|
|
prompt() {
|
|
this.readIndex = 1
|
|
Atomics.store(this.buffer, 0, -1)
|
|
postMessage({
|
|
type: 'stdin',
|
|
buffer: this.sab
|
|
})
|
|
Atomics.wait(this.buffer, 0, -1)
|
|
this.numberOfCharacters = this.buffer[0]
|
|
}
|
|
|
|
stdin = () => {
|
|
while (this.numberOfCharacters + 1 === this.readIndex) {
|
|
if (!this.sentNull) {
|
|
// Must return null once to indicate we're done for now.
|
|
this.sentNull = true
|
|
return null
|
|
}
|
|
this.sentNull = false
|
|
// Prompt will reset this.readIndex to 1
|
|
this.prompt()
|
|
}
|
|
const char = this.buffer[this.readIndex]
|
|
this.readIndex += 1
|
|
return char
|
|
}
|
|
}
|
|
|
|
const stdout = (charCode) => {
|
|
if (charCode) {
|
|
postMessage({
|
|
type: 'stdout',
|
|
stdout: charCode,
|
|
})
|
|
} else {
|
|
console.log(typeof charCode, charCode)
|
|
}
|
|
}
|
|
|
|
const stderr = (charCode) => {
|
|
if (charCode) {
|
|
postMessage({
|
|
type: 'stderr',
|
|
stderr: charCode,
|
|
})
|
|
} else {
|
|
console.log(typeof charCode, charCode)
|
|
}
|
|
}
|
|
|
|
const stdinBuffer = new StdinBuffer()
|
|
|
|
const emscriptenSettings = {
|
|
noInitialRun: true,
|
|
stdin: stdinBuffer.stdin,
|
|
stdout: stdout,
|
|
stderr: stderr,
|
|
onRuntimeInitialized: () => {
|
|
postMessage({type: 'ready', stdinBuffer: stdinBuffer.sab})
|
|
},
|
|
async preRun(Module) {
|
|
const versionHex = Module.HEAPU32[Module._Py_Version/4].toString(16);
|
|
const versionTuple = versionHex.padStart(8, "0").match(/.{1,2}/g).map((x) => parseInt(x, 16));
|
|
const [major, minor, ..._] = versionTuple;
|
|
// Prevent complaints about not finding exec-prefix by making a lib-dynload directory
|
|
Module.FS.mkdirTree(`/lib/python${major}.${minor}/lib-dynload/`);
|
|
Module.addRunDependency("install-stdlib");
|
|
const resp = await fetch(`python${major}.${minor}.zip`);
|
|
const stdlibBuffer = await resp.arrayBuffer();
|
|
Module.FS.writeFile(`/lib/python${major}${minor}.zip`, new Uint8Array(stdlibBuffer), { canOwn: true });
|
|
Module.removeRunDependency("install-stdlib");
|
|
}
|
|
}
|
|
|
|
const modulePromise = createEmscriptenModule(emscriptenSettings);
|
|
|
|
|
|
onmessage = async (event) => {
|
|
if (event.data.type === 'run') {
|
|
const Module = await modulePromise;
|
|
if (event.data.files) {
|
|
for (const [filename, contents] of Object.entries(event.data.files)) {
|
|
Module.FS.writeFile(filename, contents)
|
|
}
|
|
}
|
|
const ret = Module.callMain(event.data.args);
|
|
postMessage({
|
|
type: 'finished',
|
|
returnCode: ret
|
|
})
|
|
}
|
|
}
|
|
|