The WASM runner executes programs with CPython through Pyodide. This gives Web VPython real Python semantics in the browser, but a few older GlowScript/RapydScript conveniences are intentionally different.
In classic GlowScript/RapydScript, this pattern often worked even though the function was defined later:
scene.bind('mousedown', clicked)
def clicked(event):
print(event.pos)In the WASM runner, names are resolved using standard Python rules. Define the function before it is referenced:
def clicked(event):
print(event.pos)
scene.bind('mousedown', clicked)The same rule applies to other callbacks, button bindings, and ordinary function calls.
The WASM runner uses CPython's built-in range(), which only accepts integer start, stop, and step values:
for x in range(1, 10, 0.9): # TypeError in CPython / WASM
print(x)For non-integer steps, use an explicit floating-point loop or a library helper such as NumPy:
import numpy as np
for x in np.arange(1, 10, 0.9):
print(x)As with normal Python floating-point arithmetic, decimal steps such as 0.1 may produce values with small binary floating-point roundoff. Use round(...) when displaying values if exact decimal formatting is important.
Classic GlowScript/RapydScript programs sometimes include JavaScript syntax directly, for example:
audioCtx = new window.AudioContext();The WASM runner parses programs as CPython, so JavaScript-only syntax such as new ... is a Python SyntaxError. Use Pyodide's JavaScript proxy syntax instead. For example, Web Audio constructors can be called with .new():
audioCtx = window.AudioContext.new()
def playFreq(freq, time):
toneGen = audioCtx.createOscillator()
toneGen.frequency.value = freq
toneGen.type = "sine"
toneGen.connect(audioCtx.destination)
toneGen.start()
toneGen.stop(audioCtx.currentTime + time)As noted above, callback functions still need to be defined before they are passed to scene.bind(...), button(bind=...), and similar APIs.