Skip to content

Moddable SDK 10.0.0

Pre-release
Pre-release

Choose a tag to compare

@mkellner mkellner released this 09 Oct 18:13
· 48 commits to public since this release

Moddable SDK 10.0 contains improvements made between September 4, 2026 and October 8, 2026.

Special thank you to @d01c2, whose reports led to another round of JavaScript conformance improvements. These reports are on edges of the language that even test262 doesn't cover, so developers are unlikely to notice a change.

ECMA-419 Migration Nearly Complete

The Moddable SDK has been on a path to use industry standard ECMA-419 APIs by default where possible. That work is nearly complete, deprecating the original pins, files, and networking modules. Projects using these APIs should migrate to ECMA-419 soon.

The device global is now assembled at build time to include only the IO your project requires. Device targets no longer pull in every IO class, which makes many builds smaller and faster. If you build with mcpack, it automatically includes the IO your project uses. Every device target was simplified as part of this change.

We also fixed several ECMA-419 conformance mistakes. In some cases, a compatibility shim is in place, but you should update your code.

  • Bus names on the Host Provider Instance are lowercase: device.i2c, device.serial, device.spi
  • The real-time clock is device.rtc
  • The HTTP and HTTPS clients are now at device.network.http.client and device.network.https.client (introduced in Moddable SDK 9.5.0)
  • Humidity sensors return a value from 0 to 1, not 0 to 100

The new System object, proposed for ECMA-419 5th Edition, replaces the ad-hoc System global for restart and sleep.

TypeScript – device Knows Your Device

The ECMA-419 device global is different on every board and even between different projects on the same board. The pins, buses, peripherals, and network protocol support can all change. The TypeScript typings can now describe these differences, giving you deeper type checking. The typings are assembled from the modules included in the manifest. For TypeScript to know about the pins and peripherals of your board, it needs a typings file at $MODDABLE/typings/host/. We've added those for selected devices and look forward to working with the community to expand them to more devices.

Our typings were thoroughly reviewed for correctness by type-checking over a hundred examples and every code snippet in the Guides, and fixing the issues found. To support our ECMA-419 migration, typings for the original pins, files, and network APIs are marked @deprecated, so your editor points you to the ECMA-419 replacement.

Location

There are new sensors for GPS / GNSS sensors connected over serial or I²C, using the NMEA and UBX protocols. For the simulator, there's also location sensor implementation that needs no special hardware: it estimates location from the device's IP address. See the readme to get started.

The sensors implement the proposed Location Sensor for ECMA-419 5th Edition. This API already used by Alloy on Pebble watches.

FAT and SD Cards on ESP32

The ECMA-419 Files API can now be backed by the ESP-IDF virtual file system. That brings FAT file systems to ESP32, including SD cards connected by SPI or SDMMC. The Files Guide explains how to choose the file system, with LittleFS remaining the default on ESP32.

xsdb Runs Unit Tests

Our xsdb command line debugger now runs unit tests on devices and in the simulator. This is useful for automating testing, and for LLMs creating new unit tests and regression testing changes. It works with the testmc and test262 test harnesses. See the documentation for details.

Immutable ArrayBuffer

The Immutable ArrayBuffer ECMAScript proposal is now enabled on Moddable SDK builds (it was already available in xst). This proposal, co-championed by Mark Miller of Agoric and Peter Hoddie of Moddable, is particularly important to Embedded JavaScript developers as it fully standardizes how read-only ArrayBuffers are handled throughout the language, including read-only buffers stored in flash memory. Our Immutable ArrayBuffer Guide provides practical advice on using this new feature in your code.

Simplified Manifest Includes

A manifest include can omit manifest.json to specify an include with only a directory path. This makes reading and writing manifests easier.

"include": [
	"$(MODULES)/io/wifi"
]

Details

  • ECMA-419
    • Host provider
      • device built from config/* modules at preload, frozen by lockdown/device
      • IO classes, sockets, and storage (files, flash, keyValue, update) register themselves
      • Bus names are lowercase for conformance (temporary compatibility for uppercase)
      • device.rtc for conformance
    • System
      • Migrate to proposed ECMA-419 System object
      • restart() accepts type of "soft" or "hard" on ESP32
      • restart() in simulator
    • Files
      • ESP-IDF VFS for ESP32 – SPIFFS, FAT, LittleFS, and SD cards over SPI and SDMMC (see above)
    • TCP Socket
      • Listener on Mac and Linux calls xsForget on construct failure (contributed by @cmidgley) #1694
    • TLS Socket
      • Add remoteAddress and remotePort to match TCP socket
    • WebSocket Client
      • Fix masking of frames split across TCP reads and of control frames (contributed by @cmidgley) #1695
    • Humidity sensors return 0 to 1 for ECMA-419 conformance
    • Add ECMA-419 MAG3110 magnetometer driver and example – embedded:sensor/Magnetometer/MAG3110
    • Add ECMA-419 CST9217 capacitive touch driver
  • Modules
    • Location sensors – GPS over serial and I²C with NMEA and UBX, and by IP address (see above)
    • listen preserves query parameters (reported and contributed by @stc1988) #1692 #1693
    • URL – searchParams synchronized when setting search and href (contributed by @stc1988) #1693
    • fetch() (streaming version) – no exception thrown on abort after response completes
    • Worker – remove legacy allocation, stackCount, slotCount, and keyCount options
    • Backlight – add fade option
    • FreeType fonts render more precisely with option to enable auto-hinter. This is especially useful at smaller font sizes and with fonts with thin strokes. Include the manifest_cfeft_autohint.json manifest to enable the auto-hinter.
    • Piu
      • Add RoundRect and SVGImage content modules, built on Outline (piu/RoundRect, piu/SVGImage)
    • Web Bluetooth – startNotifications() and stopNotifications() resolve to the characteristic to match specification
  • Devices
    • Device builds require a subplatform (e.g. -p esp/nodemcu, not -p esp)
    • Added boards
      • Lilygo T-Display-S3 AMOLED – esp32/lilygo_tdisplay_s3_amoled
      • M5NanoH2 – esp32/m5nanoh2 (contributed by @stc1988) #1676
      • M5DualKey – esp32/m5dualkey (contributed by @stc1988) #1728
      • Seeed Studio XIAO ESP32-C5 – esp32/xiao_esp32c5
      • Seeed Studio XIAO ESP32-C6 – esp32/xiao_esp32c6
      • Waveshare ESP32-C6-Zero – esp32/ws_esp32c6_zero
      • Waveshare ESP32-S3-LCD-1.3 – esp32/ws_esp32s3_1_3
      • Waveshare ESP32-S3-Touch-AMOLED-1.75 – esp32/waveshare_amoled_175
    • ESP32
      • Fix Windows build for ESP32-S3 with USE_USB=2 (contributed by @mshioji) #1709
    • Raspberry Pi Pico
      • Updated to Pico SDK 2.3.1
    • Zephyr
      • Updated to Zephyr 4.4.2
    • Pebble
      • Heart rate variability health events (contributed by @jplexer) #1740
      • @moddable/pebbleproxy 0.2.1 handles leading slash in path correctly (reported by @RP1-MVac) #1738
      • update platform glue for current Pebble OS APIs (contributed by @gmarull, @jplexer) #1741, #1748
  • Examples
    • Add update/httpdownload – OTA firmware update over HTTPS
    • piu/preferences example uses Key-Value storage in place of Preference
    • Many small corrections found during type-checking review (see above)
  • Tools
    • xsdb runs unit tests (see above)
    • Manifest include of a directory uses its manifest.json (see above)
    • xsl strips config/* and lockdown/* modules after preload. This allows config/* modules to be used to build the host provider module incrementally based on the manifest content with no impact on firmware size.
    • mcpack includes IO, sockets, and storage from uses of device (e.g. device.io.Digital, device.i2c, device.keyValue)
    • mcrun supports Pebble builds with spaces in the SDK path (contributed by @jplexer) #1744
    • test-examples
      • Validate --example and --dir paths
      • IP address detection ignores build output
  • XS JavaScript engine
    • Release builds on macOS and Linux use -fno-strict-float-cast-overflow to avoid clang 21 clamping number literals above 2**31 - 1 (reported by @markwharton) #1713
    • Math.round rounds subnormal numbers (reported by @d01c2) #1698
    • charAt and charCodeAt do not truncate position to 32 bits (reported by @d01c2) #1699
    • setFromHex checks bounds before odd length (reported by @d01c2) #1700
    • Revoked Proxy accepted where IsCallable is required (reported by @d01c2) #1702
    • TypedArray.prototype.set validates offset before detached check (reported by @d01c2) #1703
    • Proxy newTarget with revoked target (reported by @d01c2) #1704
    • String.prototype.repeat of empty string with large count (reported by @d01c2) #1705
    • Symbol.for with no argument (reported by @d01c2) #1706
    • String search methods with omitted argument (reported by @d01c2) #1708
    • TypedArray.prototype.fill converts value first (reported by @d01c2) #1711
    • Array.from applies ToLength to array-like length (reported by @d01c2) #1715
    • String.prototype.replace calls Proxy replacer (reported by @d01c2) #1716
    • Reflect.apply and Reflect.construct read arguments before Proxy trap (reported by @d01c2) #1717
    • TypedArray constructors convert length before reading newTarget prototype (reported by @d01c2) #1718
    • Array.from checks iterator is callable before constructing result (reported by @d01c2) #1720
    • Object.prototype.toString reads Symbol.toStringTag through Proxy handler (reported by @d01c2) #1721
    • Array.fromAsync rejects when next returns a non-object (reported by @d01c2) #1722
    • TypedArray species creation checks content type (reported by @d01c2) #1723
    • ArrayBuffer.prototype.resize rejects non-resizable buffer before converting argument (reported by @d01c2) #1724
    • Set methods handle size above 2**31 - 1 (reported by @d01c2) #1725
    • TypedArray.prototype.set reads source before rejecting large offset (reported by @d01c2) #1726
    • Fix sliceToImmutable in snapshot callbacks (contributed by @markwharton) #1712
    • switch with labelled break and continue stack leak fixed
    • String.prototype.replace gets each $<name> capture group once (conformance and memory safety vulnerability) (reported by @orenyomtov)
    • Atomics.wait fixes leak and deadlock with reorganized error checks
    • Math.irandom uses only integer math
    • SyntaxError too many variables when a function, module, or program exceeds 65535 scope slots (found by OSS-Fuzz)
    • Eliminate some C undefined behaviors on integer overflow
  • TypeScript
    • TypeScript 6 is now minimum required version
    • device typed per build (see above)
    • Legacy typings marked @deprecated
    • typings/config for each module that contributes to device
    • typings/host for host providers, starting with Moddable Two, Moddable Six, and simulators
    • Zephyr typings generated by mcdevicetree contribute to device like other hosts
    • Hosts can type their pin specifiers and hardware options (HostSpecifiers, HostOptions)
    • Typings for embedded:network (contributed by @cmidgley) #1696
    • New typings for System, HTTP Server routes (static, WebDAV, Server-Sent Events, WebSocket handshake), DNS server, camera, Web Bluetooth, Web Serial, streaming fetch(), RoundRect, and SVGImage
    • read() return type follows format named in constructor options for TCP, TLS, Serial, WebSocket Client, Key-Value, and camera
    • Piu typings improved
    • Typings for onewire, DS18X20, ResourceIterator, pococolorcell, pocoqrcode, and pocostatic moved from modules to typings so they work from the npm package

Contact Us

If you have questions or suggestions about anything here, please reach out: