ECMA-419 Fourth Edition Advances Standard APIs for Embedded JavaScript
July 22, 2026 | Peter Hoddie, Principal
ECMA-419 defines industry-standard APIs for Embedded JavaScript development. The APIs are carefully designed for efficient implementation on resource-constrained microcontrollers while providing powerful functionality. The committee creating ECMA-419 takes inspiration from embedded platforms, the Web, Node.js, Object Capabilities, and others. The result is a suite of APIs with a consistent design that feels familiar.
Bluetooth Low Energy
BLE support is the biggest new capability, supporting both Peripheral and Central roles. Let's look at some examples using the heart rate monitor service. For those of you experienced in BLE programming, notice that these examples are just a handful of lines of code, where native implementations use hundreds of lines of C code to achieve the same result.
Heart Rate Monitor Client
To connect to a heart rate monitor, you first have to discover one. The GAPClient listens for devices with support for filtering based on the advertisement's content in the onReadable() callback. This example waits for a heart rate monitor's advertisement and tries to connect.
import {GAPClient} from "embedded:io/bluetoothle/central"
new GAPClient({
services: [
"180d" // heart rate monitor
],
onReadable() {
const advertisement = this.read();
this.close();
instantiateHeartRateMonitor(advertisement.address);
}
});
Using advertisement.address, we create a GATT Client that performs the following steps:
- Connects to the heart rate monitor
- Looks up the heart rate service
180d
- Looks up the heart rate characteristic
2a37
- Subscribes to notifications for changes in the heart rate characteristic
- Traces the current heart rate to the console when it changes
function instantiateHeartRateMonitor(address) {
new GATTClient({
address,
onReady() { // connected
this.getPrimaryServices([ "180d"], (error, services) => {
this.getCharacteristics(services[0], ["2a37"], (error, characteristics) => {
this.subscribe(characteristics[0]);
});
});
},
onReadable() {
const value = this.read();
const view = new DataView(value);
const rate16Bits = view.getUint8(0) & 0x1;
const heartRate = rate16Bits ? view.getUint16(1, true) : view.getUint8(1);
trace(` Heart Rate: ${heartRate} bpm\n`);
}
});
}
Heart Rate Monitor Client using Web Bluetooth
The Moddable SDK uses the ECMA-419 Bluetooth GATTClient and GAPClient to implement the Web Bluetooth feature of Google Chrome. This API is even easier to use, though also a bit more limited. Still, it lets Embedded JavaScript developers tap into knowledge and code from the web.
const device = await bluetooth.requestDevice({
filters: [{ services: ['heart_rate'] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService('heart_rate');
const characteristic = await service.getCharacteristic('heart_rate_measurement');
await characteristic.startNotifications();
characteristic.addEventListener('characteristicvaluechanged', function(event) {
const value = event.target.value;
const rate16Bits = value.getUint8(0) & 0x1;
const heartRate = rate16Bits ? value.getUint16(1, true) : value.getUint8(1);
trace(`Heart Rate: ${heartRate} bpm\n`);
});
Heart Rate Monitor Peripheral
ECMA-419 lets you create BLE Peripherals using JavaScript. You define the peripheral with JavaScript object syntax that includes functions to implement behaviors. Here we define a peripheral with a single service, the heart rate monitor service. The initial heart rate is 65 BPM. Once a subscription request is made, random heart rates are reported at one-second intervals.
import { GATTServer} from "embedded:io/bluetoothle/peripheral"
const services = [
{
uuid: "180d", // Heart Rate Monitor Service
characteristics: [
{
uuid: "2a37", // heart rate characteristic
properties: GATTServer.properties.read | GATTServer.properties.indicate,
onRead() {
return Uint8Array.of(0, 65); // 65 BPM
},
onSubscribe(connection) {
connection.heartRateTimer ??= Timer.repeat(() => {
connection.notify(this, Uint8Array.of(0, 55 + Math.random() * 10));
}, 1000);
},
onUnsubscribe(connection) {
Timer.clear(connection.heartRateTimer);
delete connection.heartRateTimer;
}
}
]
}
];
Connect services to a GATTServer to make them available via BLE. The GATTServer includes BLE advertising.
new GATTServer({
onReady() {
this.startAdvertising({
flags: 6,
name: "419 Heart Rate",
manufacturerData: {
manufacturer: 1,
data: Uint8Array.of(255, 0, 1)
},
services: ["180d"] // heart rate monitor
});
},
onDisconnect(connection) {
Timer.clear(connection.heartRateTimer);
}
});
DNS-SD and mDNS
DNS Service Discovery is a fundamental network service for advertising and finding services on the local network. DNS-SD is a simple tool for connecting devices on the local network, one that eliminates a great deal of user interface choices or device configuration. It is used for printers, Wi-Fi speakers, and much more.
Claim
Claiming a local DNS name for your device using DNS-SD is easy. Here we claim "example" so that other devices can access our device as "example.local".
const dnssd = new (device.network.dnssd.io)(device.network.dnssd);
dnssd.claim({host: "example"});
If there's another device with the same name, you'll get an error. You could then retry with a different name.
dnssd.claim({
host: "example",
onReady() {
trace(`"example" claimed\n`);
},
onError() {
trace(`couldn't claim "example\n"`);
}
});
Advertise
You advertise services using advertise(). This example advertises an HTTP server on port 8080 running on example.local.
const ad = dnssd.advertise({
serviceType: "_http._tcp",
name: "419 Web Server",
host: "example",
port: 8080
});
To stop this advertisement, call ad.close().
Discover
You find devices on the local network advertising a particular network service using discover(). This example monitors for devices that support AirPlay.
const disc = dnssd.discover({
serviceType: "_airplay._tcp",
onFound(service) {
trace(`Found: "${service.name}" on ${service.host} @ ${service.address}:${service.port}\n`);
},
onLost(service) {
trace(`Lost: ${service.name}\n`);
},
});
To stop discovering this service, call disc.close().
And much more
In addition to several completely new modules, ECMA-419 Fourth Edition contains many refinements to existing capabilities. For example, the Digital class used for GPIOs now allows you to provide the initial value for an output to eliminate a potential momentary glitch when switching from the default output to the desired output. You can also designate a Digital instance as active low, so that all logical values are automatically inverted.
const Digital = device.io.Digital;
const enable = new Digital({
pin: 12,
mode: Digital.Output,
initialValue: 1
});
const button = new Digital({
pin: 13,
mode: Digital.InputPullUp,
edge: Digital.Rising,
activeLow: true,
onReadable() {
trace(`button pressed\n`);
}
});
Other changes include:
- I²C adds
writeRead() method to align with embedded MCU I²C stacks
- UDP socket supports multicast
- HTTP client provides the
statusText for a response
- Image In (used for cameras) adjusts image properties like contrast and brightness using
configure()
- Flash storage adds
eraseValue and writeAlign to support more types of flash
Easier to Read and Navigate
The official ECMA-419 standard document has been fully reworked in Ecmarkup, just like the JavaScript standard, ECMA-262. This makes the standard easier to navigate with integrated search, smart highlighting, hierarchical table of contents, cleaner formatting, pinning, and faster loading.
Future of ECMA-419
Work is actively underway on the Fifth Edition of ECMA-419. The committee hopes to move to an annual release cadence thanks to the adoption of Ecmarkup, which significantly reduces the effort of publishing the standard. New features under consideration include a Location sensor that can be used with GPS, cryptographic primitives, actuators, Wi-Fi access point mode, enhancements to Bluetooth Low Energy, and integration of Explicit Resource Management. If you have suggestions, you can open an issue to begin a discussion on the TC53 committee repository.
Future of ECMA-419 in the Moddable SDK
Moddable has implemented all the new features in ECMA-419 Fourth Edition in the current Moddable SDK. We will continue to deliver new capabilities as they are designed as part of the Moddable SDK, so you can try them out and provide feedback before the standard is finalized.
Moddable is actively working to retire APIs which have been supplanted by ECMA-419 standards. These include the original "pins" modules and many of the original network modules including BLE, Socket, http, MQTT, WebSocket, and DNS. We recommend developers transition to ECMA-419 APIs wherever they are available.