From af4aa0dc00112dc9cbc9ba3f9c0e7a3453d94aaa Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Wed, 2 Jul 2025 11:50:51 -0400 Subject: [PATCH 01/21] EMSCRIPTEN BUILD: export HEAPU32 from emscripten build so that python.worker.mjs can use it --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 9df366697b8546..a0521964b69993 100755 --- a/configure +++ b/configure @@ -9601,7 +9601,7 @@ fi as_fn_append LDFLAGS_NODIST " -sWASM_BIGINT" as_fn_append LINKFORSHARED " -sFORCE_FILESYSTEM -lidbfs.js -lnodefs.js -lproxyfs.js -lworkerfs.js" - as_fn_append LINKFORSHARED " -sEXPORTED_RUNTIME_METHODS=FS,callMain,ENV" + as_fn_append LINKFORSHARED " -sEXPORTED_RUNTIME_METHODS=FS,callMain,ENV,HEAPU32" as_fn_append LINKFORSHARED " -sEXPORTED_FUNCTIONS=_main,_Py_Version,__PyRuntime,__PyEM_EMSCRIPTEN_COUNT_ARGS_OFFSET,_PyGILState_GetThisThreadState,__Py_DumpTraceback" as_fn_append LINKFORSHARED " -sSTACK_SIZE=5MB" From 394815eb59f3ee7b41f7706caf1ddd12e98a776a Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Wed, 2 Jul 2025 12:08:33 -0400 Subject: [PATCH 02/21] WASM REPL: fix loading xterm.js (broken in 2f1cee8477) --- Tools/wasm/emscripten/web_example/python.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/wasm/emscripten/web_example/python.html b/Tools/wasm/emscripten/web_example/python.html index 078f86eb764419..73d2ad0ac6be60 100644 --- a/Tools/wasm/emscripten/web_example/python.html +++ b/Tools/wasm/emscripten/web_example/python.html @@ -4,7 +4,7 @@ - + wasm-python terminal + > +

Simple REPL for Python WASM

- +
print('Welcome to WASM!')
From b6886630b92e0082f68d0fb52a2602c853689c4f Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Wed, 2 Jul 2025 18:32:16 -0400 Subject: [PATCH 07/21] WASM REPL: some organization, refactoring, fixes for history --- Tools/wasm/emscripten/web_example/python.html | 155 ++++++++++-------- 1 file changed, 83 insertions(+), 72 deletions(-) diff --git a/Tools/wasm/emscripten/web_example/python.html b/Tools/wasm/emscripten/web_example/python.html index 2bcf2e9a247c19..e7be6faff8aeea 100644 --- a/Tools/wasm/emscripten/web_example/python.html +++ b/Tools/wasm/emscripten/web_example/python.html @@ -167,6 +167,7 @@ this.cursorPosition = 0; this.history = []; + this.historyBuffer = []; this.historyIndex = -1; this.beforeHistoryNav = ""; } @@ -219,10 +220,10 @@ this.cursorLeft(); break; case '[H': // home key - this.cursorHome(); + this.cursorHome(true); break; case '[F': // end key - this.cursorEnd(); + this.cursorEnd(true); break; case '[3~': // delete key this.deleteAtCursor(); @@ -248,7 +249,6 @@ case "\x03": // CTRL+C this.input = ""; this.xterm.write("\n") - // this is a real hack. the hard-coded 4... :\ this.xterm.write('\x1b[' + (this.cursorPosition + 4) + 'D'); this.cursorPosition = 0; this.resolveInput("" + '\n'); @@ -270,9 +270,14 @@ } } else { this.handleCursorInsert(data); + this.updateHistory(); } }; + clearLine(){ + this.xterm.write('\x1b[K') + } + writeLine(line) { this.xterm.write(line.slice(0, -1)); this.xterm.write("\r\n"); @@ -288,6 +293,25 @@ this.xterm.write(trailing); this.xterm.write('\x1b[' + trailing.length + 'D'); } + this.updateHistory(); + } + + handleTab() { + // handle tabs: from the current position, add spaces until + // this.cursorPosition is a multiple of 4. + const prefix = this.input.slice(0, this.cursorPosition); + const suffix = this.input.slice(this.cursorPosition); + const count = 4 - (this.cursorPosition % 4); + const toAdd = " ".repeat(count); + this.input = prefix + toAdd + suffix + this.cursorHome(false); + this.clearLine(); + this.xterm.write(this.input); + if (suffix){ + this.xterm.write('\x1b[' + suffix.length + 'D'); + } + this.cursorPosition += count; + this.updateHistory(false); } handleCursorErase() { @@ -300,24 +324,63 @@ } const trailing = this.input.slice(this.cursorPosition); this.input = this.input.slice(0, this.cursorPosition - 1) + trailing; - this.cursorPosition -= 1; - this.xterm.write("\x1B[D"); - this.xterm.write("\x1B[K"); - if (trailing){ + this.cursorLeft(); + this.clearLine(); + if (trailing.length !== 0){ this.xterm.write(trailing); this.xterm.write('\x1b[' + trailing.length + 'D'); } + this.updateHistory(); } deleteAtCursor(){ if (this.cursorPosition < this.input.length){ const trailing = this.input.slice(this.cursorPosition + 1); this.input = this.input.slice(0, this.cursorPosition) + trailing; - this.xterm.write("\x1B[K"); - if (trailing){ + this.clearLine(); + if (trailing.length !== 0){ this.xterm.write(trailing); this.xterm.write('\x1b[' + trailing.length + 'D'); } + this.updateHistory(); + } + } + + cursorRight(){ + if (this.cursorPosition < this.input.length){ + this.cursorPosition += 1; + this.xterm.write('\x1b[C'); + } + } + + cursorLeft(){ + if (this.cursorPosition > 0){ + this.cursorPosition -= 1; + this.xterm.write('\x1b[D'); + } + } + + cursorHome(updatePosition) { + if (this.cursorPosition > 0){ + this.xterm.write('\x1b[' + this.cursorPosition + 'D'); + if (updatePosition) { + this.cursorPosition = 0; + } + } + } + + cursorEnd() { + if (this.cursorPosition < this.input.length){ + this.xterm.write('\x1b[' + (this.input.length - this.cursorPosition) + 'C'); + this.cursorPosition = this.input.length; + } + } + + updateHistory(){ + if (this.historyIndex !== -1){ + this.historyBuffer[this.historyIndex] = this.input; + }else{ + this.beforeHistoryNav = this.input; } } @@ -333,13 +396,9 @@ }else if (this.historyIndex > 0){ this.historyIndex -= 1; } - this.input = this.history[this.historyIndex]; - // jump back to the start of the line - if (this.cursorPosition > 0){ - this.xterm.write('\x1b[' + (this.cursorPosition) + 'D'); - } - // clear the line - this.xterm.write('\x1b[K') + this.input = this.historyBuffer[this.historyIndex]; + this.cursorHome(false); + this.clearLine(); this.xterm.write(this.input); this.cursorPosition = this.input.length; } @@ -350,7 +409,7 @@ return; }else if (this.historyIndex < this.history.length - 1){ this.historyIndex += 1; - this.input = this.history[this.historyIndex]; + this.input = this.historyBuffer[this.historyIndex]; }else if (this.historyIndex == this.history.length - 1){ // we're coming back from the last history value; reset // the input to whatever it was when we started going @@ -358,64 +417,12 @@ this.input = this.beforeHistoryNav; this.historyIndex = -1; } - // jump back to the start of the line - if (this.cursorPosition > 0){ - this.xterm.write('\x1b[' + (this.cursorPosition) + 'D'); - } - // clear the line - this.xterm.write('\x1b[K') + this.cursorHome(false); + this.clearLine(); this.xterm.write(this.input); this.cursorPosition = this.input.length; } - cursorRight(){ - if (this.cursorPosition < this.input.length){ - this.cursorPosition += 1; - this.xterm.write('\x1b[C'); - } - } - - cursorLeft(){ - if (this.cursorPosition > 0){ - this.cursorPosition -= 1; - this.xterm.write('\x1b[D'); - } - } - - cursorHome() { - if (this.cursorPosition > 0){ - this.xterm.write('\x1b[' + this.cursorPosition + 'D'); - this.cursorPosition = 0; - } - } - - cursorEnd() { - if (this.cursorPosition < this.input.length){ - this.xterm.write('\x1b[' + (this.input.length - this.cursorPosition) + 'C'); - this.cursorPosition = this.input.length; - } - } - - handleTab() { - // handle tabs: from the current position, add spaces until - // this.cursorPosition is a multiple of 4. - const prefix = this.input.slice(0, this.cursorPosition); - const suffix = this.input.slice(this.cursorPosition); - const count = 4 - (this.cursorPosition % 4); - const toAdd = " ".repeat(count); - this.input = prefix + toAdd + suffix; - if (this.cursorPosition > 0){ - this.xterm.write('\x1b[' + (this.cursorPosition) + 'D'); - } - // clear the line - this.xterm.write('\x1b[K') - this.xterm.write(this.input); - if (suffix){ - this.xterm.write('\x1b[' + suffix.length + 'D'); - } - this.cursorPosition += count; - } - prompt = async () => { this.activeInput = true; // Hack to allow stdout/stderr to finish before we figure out where input starts @@ -442,8 +449,12 @@ } return new Promise((resolve, reject) => { this.resolveInput = (value) => { - if (value !== ""){ + if (value.replace(/\s/g, '').length != 0){ + if (this.historyIndex !== -1){ + this.historyBuffer[this.historyIndex] = this.history[this.historyIndex]; + } this.history.push(value.slice(0, -1)); + this.historyBuffer.push(value.slice(0, -1)); this.historyIndex = -1; this.cursorPosition = 0; } From 43a47dc0d891442848c1d701c2db845b113ba598 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Thu, 3 Jul 2025 13:25:36 -0400 Subject: [PATCH 08/21] WASM REPL: put demo at index.html and change text of the 'Run Code' button --- Makefile.pre.in | 4 ++-- Tools/wasm/emscripten/web_example/{python.html => index.html} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename Tools/wasm/emscripten/web_example/{python.html => index.html} (99%) diff --git a/Makefile.pre.in b/Makefile.pre.in index 66b34b779f27cb..fae5e384d3245f 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1096,7 +1096,7 @@ $(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS) # wasm32-emscripten browser web example WEBEX_DIR=$(srcdir)/Tools/wasm/emscripten/web_example/ -web_example/python.html: $(WEBEX_DIR)/python.html +web_example/index.html: $(WEBEX_DIR)/index.html @mkdir -p web_example @cp $< $@ @@ -1124,7 +1124,7 @@ web_example/python.mjs web_example/python.wasm: $(BUILDPYTHON) cp python.wasm web_example/python.wasm .PHONY: web_example -web_example: web_example/python.mjs web_example/python.worker.mjs web_example/python.html web_example/server.py $(WEB_STDLIB) +web_example: web_example/python.mjs web_example/python.worker.mjs web_example/index.html web_example/server.py $(WEB_STDLIB) ############################################################################ # Header files diff --git a/Tools/wasm/emscripten/web_example/python.html b/Tools/wasm/emscripten/web_example/index.html similarity index 99% rename from Tools/wasm/emscripten/web_example/python.html rename to Tools/wasm/emscripten/web_example/index.html index e7be6faff8aeea..c713d227ba4cca 100644 --- a/Tools/wasm/emscripten/web_example/python.html +++ b/Tools/wasm/emscripten/web_example/index.html @@ -604,7 +604,7 @@

Simple REPL for Python WASM

print('Welcome to WASM!')
- + From 6d5f6984bcf0b21d1c825c4d059d321a14f9581e Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Thu, 3 Jul 2025 13:52:06 -0400 Subject: [PATCH 09/21] WASM REPL: update README.md to account for demo location moving --- Tools/wasm/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tools/wasm/README.md b/Tools/wasm/README.md index 232321c515721e..9288598a0abc29 100644 --- a/Tools/wasm/README.md +++ b/Tools/wasm/README.md @@ -22,7 +22,7 @@ https://github.com/psf/webassembly for more information. ### Build To cross compile to the ``wasm32-emscripten`` platform you need -[the Emscripten compiler toolchain](https://emscripten.org/), +[the Emscripten compiler toolchain](https://emscripten.org/), a Python interpreter, and an installation of Node version 18 or newer. Emscripten version 4.0.2 is recommended; newer versions may also work, but all official testing is performed with that version. All commands below are relative @@ -86,11 +86,11 @@ CLI you will need to write your own alternative to `node_entry.mjs`. ### The Web Example -When building for Emscripten, the web example will be built automatically. It is -in the ``web_example`` directory. To run the web example, ``cd`` into the +When building for Emscripten, the web example will be built automatically. It +is in the ``web_example`` directory. To run the web example, ``cd`` into the ``web_example`` directory, then run ``python server.py``. This will start a web -server; you can then visit ``http://localhost:8000/python.html`` in a browser to -see a simple REPL example. +server; you can then visit ``http://localhost:8000/`` in a browser to see a +simple REPL example. The web example relies on a bug fix in Emscripten version 3.1.73 so if you build with earlier versions of Emscripten it may not work. The web example uses From 16cfea22b3fd62427de65d16146c912e815630b3 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Thu, 3 Jul 2025 14:01:37 -0400 Subject: [PATCH 10/21] WASM REPL: add HEAPU32 to exports in configure.ac --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cb7f2144345b37..2b7516e74ca960 100644 --- a/configure.ac +++ b/configure.ac @@ -2334,7 +2334,7 @@ AS_CASE([$ac_sys_system], dnl Include file system support AS_VAR_APPEND([LINKFORSHARED], [" -sFORCE_FILESYSTEM -lidbfs.js -lnodefs.js -lproxyfs.js -lworkerfs.js"]) - AS_VAR_APPEND([LINKFORSHARED], [" -sEXPORTED_RUNTIME_METHODS=FS,callMain,ENV"]) + AS_VAR_APPEND([LINKFORSHARED], [" -sEXPORTED_RUNTIME_METHODS=FS,callMain,ENV,HEAPU32"]) AS_VAR_APPEND([LINKFORSHARED], [" -sEXPORTED_FUNCTIONS=_main,_Py_Version,__PyRuntime,__PyEM_EMSCRIPTEN_COUNT_ARGS_OFFSET,_PyGILState_GetThisThreadState,__Py_DumpTraceback"]) AS_VAR_APPEND([LINKFORSHARED], [" -sSTACK_SIZE=5MB"]) From faf2ba498a5a25f061f2dc7bdae0181685d8cbfa Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Thu, 3 Jul 2025 14:16:22 -0400 Subject: [PATCH 11/21] WASM REPL: fix for ACE setup in Chromium --- Tools/wasm/emscripten/web_example/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/wasm/emscripten/web_example/index.html b/Tools/wasm/emscripten/web_example/index.html index c713d227ba4cca..c4f40d055fd4fc 100644 --- a/Tools/wasm/emscripten/web_example/index.html +++ b/Tools/wasm/emscripten/web_example/index.html @@ -594,6 +594,7 @@ finishedCallback, ); }; + var editor; document.addEventListener('DOMContentLoaded', () => { editor = ace.edit("editor"); editor.session.setMode("ace/mode/python"); From 70d4a171caaaa2fdb5b028059e514dedd4048651 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Thu, 3 Jul 2025 18:20:57 -0400 Subject: [PATCH 12/21] WASM REPL: run prettier on index.html --- Tools/wasm/emscripten/web_example/index.html | 140 ++++++++++--------- 1 file changed, 77 insertions(+), 63 deletions(-) diff --git a/Tools/wasm/emscripten/web_example/index.html b/Tools/wasm/emscripten/web_example/index.html index c4f40d055fd4fc..773f7a652bb806 100644 --- a/Tools/wasm/emscripten/web_example/index.html +++ b/Tools/wasm/emscripten/web_example/index.html @@ -20,7 +20,7 @@ margin: 0 auto; } #editor { - padding:5px; + padding: 5px; border: 1px solid black; width: 100%; height: 300px; @@ -139,7 +139,7 @@ class WasmTerminal { constructor() { - this.reset() + this.reset(); this.xterm = new Terminal({ scrollback: 10000, @@ -158,7 +158,7 @@ this.xterm.onData(this.handleTermData); } - reset(){ + reset() { this.inputBuffer = new BufferQueue(); this.input = ""; this.resolveInput = null; @@ -203,29 +203,29 @@ if (!(ord === 0x1b || ord == 0x7f || ord < 32)) { this.inputBuffer.addData(data); } - // TODO: Handle more escape sequences? + // TODO: Handle more escape sequences? } else if (ord === 0x1b) { // Handle special characters - switch(data.slice(1)){ - case '[A': // up + switch (data.slice(1)) { + case "[A": // up this.historyBack(); break; - case '[B': // down + case "[B": // down this.historyForward(); break; - case '[C': // right + case "[C": // right this.cursorRight(); break; - case '[D': // left + case "[D": // left this.cursorLeft(); break; - case '[H': // home key + case "[H": // home key this.cursorHome(true); break; - case '[F': // end key + case "[F": // end key this.cursorEnd(true); break; - case '[3~': // delete key + case "[3~": // delete key this.deleteAtCursor(); break; default: @@ -248,10 +248,12 @@ break; case "\x03": // CTRL+C this.input = ""; - this.xterm.write("\n") - this.xterm.write('\x1b[' + (this.cursorPosition + 4) + 'D'); + this.xterm.write("\n"); + this.xterm.write( + "\x1b[" + (this.cursorPosition + 4) + "D", + ); this.cursorPosition = 0; - this.resolveInput("" + '\n'); + this.resolveInput("" + "\n"); break; case "\x09": // TAB this.handleTab(); @@ -274,8 +276,8 @@ } }; - clearLine(){ - this.xterm.write('\x1b[K') + clearLine() { + this.xterm.write("\x1b[K"); } writeLine(line) { @@ -286,12 +288,15 @@ handleCursorInsert(data) { const trailing = this.input.slice(this.cursorPosition); - this.input = this.input.slice(0, this.cursorPosition) + data + trailing; + this.input = + this.input.slice(0, this.cursorPosition) + + data + + trailing; this.cursorPosition += data.length; this.xterm.write(data); - if (trailing.length !== 0){ + if (trailing.length !== 0) { this.xterm.write(trailing); - this.xterm.write('\x1b[' + trailing.length + 'D'); + this.xterm.write("\x1b[" + trailing.length + "D"); } this.updateHistory(); } @@ -303,12 +308,12 @@ const suffix = this.input.slice(this.cursorPosition); const count = 4 - (this.cursorPosition % 4); const toAdd = " ".repeat(count); - this.input = prefix + toAdd + suffix + this.input = prefix + toAdd + suffix; this.cursorHome(false); this.clearLine(); this.xterm.write(this.input); - if (suffix){ - this.xterm.write('\x1b[' + suffix.length + 'D'); + if (suffix) { + this.xterm.write("\x1b[" + suffix.length + "D"); } this.cursorPosition += count; this.updateHistory(false); @@ -323,46 +328,50 @@ return; } const trailing = this.input.slice(this.cursorPosition); - this.input = this.input.slice(0, this.cursorPosition - 1) + trailing; + this.input = + this.input.slice(0, this.cursorPosition - 1) + trailing; this.cursorLeft(); this.clearLine(); - if (trailing.length !== 0){ + if (trailing.length !== 0) { this.xterm.write(trailing); - this.xterm.write('\x1b[' + trailing.length + 'D'); + this.xterm.write("\x1b[" + trailing.length + "D"); } this.updateHistory(); } - deleteAtCursor(){ - if (this.cursorPosition < this.input.length){ - const trailing = this.input.slice(this.cursorPosition + 1); - this.input = this.input.slice(0, this.cursorPosition) + trailing; + deleteAtCursor() { + if (this.cursorPosition < this.input.length) { + const trailing = this.input.slice( + this.cursorPosition + 1, + ); + this.input = + this.input.slice(0, this.cursorPosition) + trailing; this.clearLine(); - if (trailing.length !== 0){ + if (trailing.length !== 0) { this.xterm.write(trailing); - this.xterm.write('\x1b[' + trailing.length + 'D'); + this.xterm.write("\x1b[" + trailing.length + "D"); } this.updateHistory(); } } - cursorRight(){ - if (this.cursorPosition < this.input.length){ - this.cursorPosition += 1; - this.xterm.write('\x1b[C'); - } + cursorRight() { + if (this.cursorPosition < this.input.length) { + this.cursorPosition += 1; + this.xterm.write("\x1b[C"); + } } - cursorLeft(){ - if (this.cursorPosition > 0){ + cursorLeft() { + if (this.cursorPosition > 0) { this.cursorPosition -= 1; - this.xterm.write('\x1b[D'); + this.xterm.write("\x1b[D"); } } cursorHome(updatePosition) { - if (this.cursorPosition > 0){ - this.xterm.write('\x1b[' + this.cursorPosition + 'D'); + if (this.cursorPosition > 0) { + this.xterm.write("\x1b[" + this.cursorPosition + "D"); if (updatePosition) { this.cursorPosition = 0; } @@ -370,30 +379,34 @@ } cursorEnd() { - if (this.cursorPosition < this.input.length){ - this.xterm.write('\x1b[' + (this.input.length - this.cursorPosition) + 'C'); + if (this.cursorPosition < this.input.length) { + this.xterm.write( + "\x1b[" + + (this.input.length - this.cursorPosition) + + "C", + ); this.cursorPosition = this.input.length; } } - updateHistory(){ - if (this.historyIndex !== -1){ + updateHistory() { + if (this.historyIndex !== -1) { this.historyBuffer[this.historyIndex] = this.input; - }else{ + } else { this.beforeHistoryNav = this.input; } } - historyBack(){ - if (this.history.length === 0){ + historyBack() { + if (this.history.length === 0) { return; - }else if (this.historyIndex === -1){ + } else if (this.historyIndex === -1) { // we're not currently navigating the history; store // the current command and then look at the end of our // history buffer this.beforeHistoryNav = this.input; this.historyIndex = this.history.length - 1; - }else if (this.historyIndex > 0){ + } else if (this.historyIndex > 0) { this.historyIndex -= 1; } this.input = this.historyBuffer[this.historyIndex]; @@ -403,14 +416,14 @@ this.cursorPosition = this.input.length; } - historyForward(){ - if (this.history.length === 0 || this.historyIndex === -1){ + historyForward() { + if (this.history.length === 0 || this.historyIndex === -1) { // we're not currently navigating the history; NOP. return; - }else if (this.historyIndex < this.history.length - 1){ + } else if (this.historyIndex < this.history.length - 1) { this.historyIndex += 1; this.input = this.historyBuffer[this.historyIndex]; - }else if (this.historyIndex == this.history.length - 1){ + } else if (this.historyIndex == this.history.length - 1) { // we're coming back from the last history value; reset // the input to whatever it was when we started going // through the history @@ -449,9 +462,10 @@ } return new Promise((resolve, reject) => { this.resolveInput = (value) => { - if (value.replace(/\s/g, '').length != 0){ - if (this.historyIndex !== -1){ - this.historyBuffer[this.historyIndex] = this.history[this.historyIndex]; + if (value.replace(/\s/g, "").length != 0) { + if (this.historyIndex !== -1) { + this.historyBuffer[this.historyIndex] = + this.history[this.historyIndex]; } this.history.push(value.slice(0, -1)); this.historyBuffer.push(value.slice(0, -1)); @@ -594,11 +608,11 @@ finishedCallback, ); }; - var editor; - document.addEventListener('DOMContentLoaded', () => { - editor = ace.edit("editor"); - editor.session.setMode("ace/mode/python"); - }); + var editor; + document.addEventListener("DOMContentLoaded", () => { + editor = ace.edit("editor"); + editor.session.setMode("ace/mode/python"); + }); From ce5ebca98cc1f43083cda06eb104b91a6da2cff1 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Thu, 3 Jul 2025 18:27:56 -0400 Subject: [PATCH 13/21] WASM REPL: lower-case 'code' on 'Run code' button --- Tools/wasm/emscripten/web_example/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/wasm/emscripten/web_example/index.html b/Tools/wasm/emscripten/web_example/index.html index 773f7a652bb806..e0e07525224933 100644 --- a/Tools/wasm/emscripten/web_example/index.html +++ b/Tools/wasm/emscripten/web_example/index.html @@ -619,7 +619,7 @@

Simple REPL for Python WASM

print('Welcome to WASM!')
- + From 66cf49db5a2ed1ba106ec5028be3114e86e040e9 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 5 Jul 2025 15:11:24 -0400 Subject: [PATCH 14/21] WASM REPL: remove trailing slashes from void tags in index.html --- Tools/wasm/emscripten/web_example/index.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tools/wasm/emscripten/web_example/index.html b/Tools/wasm/emscripten/web_example/index.html index e0e07525224933..29791eca206fe0 100644 --- a/Tools/wasm/emscripten/web_example/index.html +++ b/Tools/wasm/emscripten/web_example/index.html @@ -1,18 +1,18 @@ - - - - - + + + + + wasm-python terminal + >