v1.5.0-beta.0
Pre-releasePrerelease. This is the first public beta of v1.5.0. Installed via npm install @mjayb/sonicpijs@beta; the default latest tag still points to v1.4.0. Bug reports welcome on GitHub issues — the in-app Report Bug button pre-fills the version, browser, and current code.
Engine audit — 33 bugs fixed
Found during a multi-round audit against MagPi book chapters, official Sonic Pi wizard/sorcerer/magician examples, and community forum compositions. Per-bug rationale in the engine audit PR (#155) and synth alias cleanup (#157).
Critical engine:
randomSuffix()wasconst f = (): string => f()— infinite recursion on top-levelin_thread/atProgramBuilderchildren (in_thread/with_fx/at) not inheriting_transpose,_synthDefaults,_sampleDefaultswrapBareCodedidn't trackloop do/.times do/.each do—use_synthhoisted out of loopsnormalizeSampleParamsmissingexpandSlideParam—sample :x, slide:silently ignorednormalizeFxParamsresolved symbols AFTER injecting defaults (wrong order)with_bpmdidn't restore previous BPMresumeTick()race condition on rapid pause/resume
Bridge / runtime:
in_threadinsidewith_fxnot inheritingoutBus— thread audio bypassed FX entirely- Sample/SynthDef lazy-load race conditions (buffer leaks, duplicate loads)
freeBus()allowed duplicate frees — bus collisionfetchSampleDurationsilently swallowed errors, breakingbeat_stretch
DSL / tutorial parity:
use_sample_bpm— wrapper arounduse_bpm(60 / sample_duration(name))midishorthand —midi 60, sustain: 0.5(note_on + auto note_off)use_osc/oscshorthand — state variable for default host/portwith_fx reps:— FX body now loops N times within same FX instancewith_synth_defaults/with_sample_defaults— scoped variantsuse_density— permanent density setteruse_debug— exposed in sandbox as no-op (was causing crashes).take(n)— transpiler was emitting.slice()but Ring uses.take()Ring.line(steps=1)returned[NaN](division by zero) — now returns[start]
Public API additions:
- Exported:
hzToMidi,chord_degree,degree,knit,range,line
Sandbox fixes:
get()was defined as anew Proxy(...)not a function —get(:key)crashedwith_random_seed,with_octave,with_density,with_synth_defaults,with_sample_defaultsweren't intranspileWithBlockhandler — blocks transpiled without callback wrapperTOP_LEVEL_SETTINGSmissinguse_arg_bpm_scaling
Architectural fix — b shadowing:
- User variable
bshadowedProgramBuildercallback parameter via Proxysettrap. Renamed internal parameter frombto__bacross all transpiler output sites (callback params, method prefixes,__checkBudget,stop,lastRef,density,definefuncs,atcallbacks). Documented in KNOWN_LIMITATIONS.
wrapBareCode regex expansion:
- Regex only matched
/^\s*(play|sleep|sample)\s/— missedplay_chord,play_pattern_timed,use_synth_defaults,synth,control,cue,sync, etc. Expanded to cover all bare DSL callables that need__bscope.
Synth aliases:
- Removed
dark_sea_hornandsingerfromSYNTH_NAMES— no corresponding.scsyndefon the SuperSonic CDN (silent failure trap).
Verified compatibility
56 real-world compositions run end-to-end in Chromium capture:
- 18 E2E tests (covering 122 DSL functions)
- 7 MagPi Essentials chapter examples
- 15 official Sonic Pi examples (wizard/sorcerer/magician tiers from
etc/examples/) - 13 community forum compositions from in-thread.sonic-pi.net
- 3 edge cases
Test coverage
- 703 unit tests pass
- Zero TypeScript errors
UI
- Version label in the menu bar displays
v1.5.0-beta.0(top-right, muted). Click to copy the fullSonicPi.js v1.5.0-beta.0string to clipboard. Pre-filled into the Report Bug URL so every bug report is tagged to a specific build.
Release engineering
- This is the first release following the new release-cycle criteria: single version string across all surfaces, npm
--tag betato protectlatest, UI footer as the load-bearing signal for the prerelease channel, explicit beta → RC → stable gate criteria documented in the release runbook.
Known limitations
See KNOWN_LIMITATIONS.md for the current list. The limitations file is the single source of truth; it is intentionally NOT duplicated per-release in this changelog. Noteworthy feasible-but-not-built items tracked for post-beta work: external sample upload (#159), OSC receive via WebSocket bridge (#150), synth :sound_in via getUserMedia (#152), use_real_time MIDI latency bypass (#149), .zip/.each_with_index Array methods (#154).