Embedded JavaScript

Powerful, productive, portable

As the language of the internet, JavaScript is ubiquitous, powering websites, mobile apps, and cloud services. Its widespread use can be attributed to its versatility, popularity, speed, and safety. To ensure interoperability between IoT products and other platforms, it makes sense to employ the same language across all systems. With its origins in web development, JavaScript is well-suited for network communication and user interface in IoT products. Additionally, JavaScript delivers security guarantees that are necessary for protecting user privacy and securing financial transactions, as demanded by the web. The TypeScript language layers type-checking onto standard JavaScript to increase developer productivity and make it easier for teams to collaborate on projects.

Embedded JavaScript Basics

Overview of Embedded JavaScript

Embedded JavaScript is essentially the same JavaScript language you are familiar with from the web, but it runs on embedded devices. This means that all the modern features, such as modules, async-await, and BigInt, are available. Moreover, the Embedded JavaScript in the Moddable SDK adheres to the same Ecma standard as JavaScript on the web.

However, there are a couple of differences to keep in mind. First, the hardware of embedded devices typically has less memory and lower CPU performance. Therefore, developers may need to prioritize performance earlier in the development process. Thankfully, the Moddable SDK offers various tools and techniques to assist with this challenge. Second, there are some new APIs to learn since the APIs designed for web browsers are not always optimal for embedded use.

Comparison with other programming languages

JavaScript is not intended to replace embedded C; rather, it is meant to complement it. The JavaScript engine in the Moddable SDK is written in C, allowing projects to easily switch between JavaScript and functions implemented in C/C++.

Embedded C is a robust language, but it requires significantly more time and expertise from developers than JavaScript. On the other hand, there are several other scripting languages available to embedded developers, such as Lua and Python, which are appealing to hobbyists familiar with these languages. However, these languages are not standard and cannot guarantee long-term code compatibility. They also lack interoperability with the web ecosystem and are not intended for commercial products, making support challenging.


Benefits of using Embedded JavaScript

  • Accelerated development process
  • Rapid deployment of modular updates, not full firmware images
  • Consistent APIs and tools across all microcontrollers
  • Grow your own developer ecosystem with end-user scripting
  • 365/24/7 reliability
  • More secure with less effort
  • Connect to the vast web ecosystem for tools, code, and developers

Applying Embedded JavaScript in IoT

Selected IoT products written in Embedded JavaScript using the Moddable SDK

Card image cap

Appliances

by Whirlpool and Maytag

Smart, connected home appliances with integrated display

Card image cap

SprayScan mSM

by Spraying Systems

Sustainability monitor for manufacturing

Card image cap

Lyric

by Addaday

Consumer therapeutic massager

Card image cap

TLC300

by Brinno

Time-lapse camera for construction sites

Setting up the Development Environment

Hardware and software requirements

The Moddable SDK supports macOS, Windows, and Linux on your development machine, with no additional hardware required to get started. You can use the built-in simulator to run projects on your computer during the development phase.

Once you're ready to test your project on embedded hardware, a wide range of devices are supported, including ESP32 family, ESP8266, Raspberry Pi Pico, Qualcomm QCA4020, and Silicon Labs Gecko series.

Qualcomm Logo

To set up the Moddable SDK, you'll need to install the necessary software, which includes the core Moddable SDK tools and the manufacturer's SDK for the chipsets you're developing for.


Setting up the development environment

The fastest way to get set-up is to use xs-dev, which automates setting-up and updating.

npm install -g xs-dev
xs-dev setup

If you want to customize your development environment, detailed instructions are provided for the core Moddable SDK set-up and for each supported chipset.


Choosing an IDE for Embedded JavaScript

Developers often have a preferred editor, and with the Moddable SDK, you can use whichever editor you prefer to develop Embedded JavaScript code.

If you're using Visual Studio Code (VS Code), you'll be pleased to know that it offers excellent support for standard JavaScript. Additionally, VS Code offers great support for TypeScript, including real-time type checking as you edit and auto-suggest. The Moddable SDK also provides a comprehensive set of type declarations for embedded JavaScript, which supports these TypeScript features.

Writing Embedded JavaScript for IoT

Basic syntax of Embedded JavaScript

If you're familiar with JavaScript from working in the web ecosystem, you already know embedded JavaScript. The XS JavaScript engine for embedded provides the same JavaScript language used in web browsers and Node.js (official known as ECMAScript 2023), so there are no new language concepts to learn.

However, if you're an embedded developer without prior experience in JavaScript, the good news is that basic JavaScript syntax is similar to C. To assist C/C++ developers in learning embedded JavaScript, we've dedicated a chapter to this topic in our book. With this guide, you'll be up and running quickly, as it's the only resource specifically written for C/C++ developers looking to learn JavaScript.


Key concepts and features

The key difference between developing with Embedded JavaScript and JavaScript on the web isn't the language, but the hardware running the project. Embedded hardware may be 50 times slower with 200 times less RAM. The consequence of that is that much more of the focus is on optimizing performance and resource use.

Embedded JavaScript stores objects and data in flash memory (ROM) as much as possible to reduce RAM. As a result, many more JavaScript objects are frozen than usual. This is very familiar to developers using functional programming. There's nothing very complicated about working with frozen objects, and it is already part of standard JavaScript.

One of the most unique and powerful features of embedded JavaScript with the Moddable SDK is preloading. This runs parts of your code at build time on your computer. Execution then continues on the embedded devices. Preloading reduces start-up time on the device, allowing embedded JavaScript projects to start running in milliseconds. Preloading also reduces the RAM used by running projects, potentially allowing the use of less expensive chips (with less RAM).

Modular development is crucial for ensuring scalability, especially in the context of large, dispersed teams. To achieve this, the use of standard JavaScript modules (e.g. ESM) is encouraged with the support of Embedded JavaScript. Additionally, unit testing is recommended to reduce dependencies. Embedded JavaScript also enables the implementation of private fields and methods, which allows modules to remain fully hidden, further reducing the risk of unintended dependencies.


Writing code for common IoT devices

Within the Moddable SDK, there are hundreds of focused example applications that demonstrate the use of specific IoT device features. These examples cover a wide range of topics, from graphics to networking to data storage, making them an excellent resource for those who are just starting to explore the possibilities.

Moreover, the Moddable SDK offers consistent APIs across all chipsets, which simplifies the development process. Once a developer has learned how to work with one chipset, they have the foundation to work with all of them.

Best Practices for Writing Embedded JavaScript

Tips for efficient Embedded JavaScript development

When you're just starting out, don't worry too much about optimization. Without experience, it can be hard to know what will be inefficient, and trying to optimize too early can lead to the unnecessary effort.

Instead, a good starting point is to use the Instruments pane in the xsbug debugger. This tool shows your resource usage in real-time, including memory usage, garbage collector activity, open files, network usage, CPU load, and more. Keep an eye out for unusual spikes in resource use, as they may indicate the need for optimization.


Strategies for optimizing code performance

One of the biggest challenges in optimizing code is identifying what code needs to be optimized. Fortunately, the xsbug debugger integrates a profiler. Any time your project is running, you can profile performance at the click of a button - no extra tools to install, no special build to create. Once you know where the bottlenecks are, optimization is often straightforward. We've captured in detail an optimization session to show how it is done. The result was a 10x speed-up.

One advantage Embedded JavaScript developers have often developers working on the web is that there's always the option to implement a function or class in native C/C++. This is invaluable when a particular operation needs to squeeze every last bit of power out of the embedded hardware.


Debugging Embedded JavaScript for IoT

To aid in debugging, take advantage of the debugger's powerful features, such as the message viewer that allows you to view debugging logs as conversations.

JavaScript developers on the web commonly employ unit testing for software modules to ensure that each one functions correctly in isolation. Similarly, Embedded JavaScript supports unit testing, which may require some adjustment but is easy to learn. The unit testing approach is based on test262, the official JavaScript language test suite, and the xsbug debugger serves as the unit test runner.

The Moddable SDK comes equipped with unit tests for its for its built-in modules and documentation on how to write your own.


Deployment of Projects using Embedded JavaScript in IoT

When a project is ready to be deployed to users, the initial deployment typically is delivered as the firmware of the IoT product.

Best practices include:

  • Using a release build, for optimal performance
  • Disabling all serial console output for optimal performance and to avoid leaking user secrets (this is done automatically by the Moddable SDK for release builds)
  • Enabling the watchdog timer so the product automatically restarts if the software unexpectedly hangs (again, automatically done for you with the Moddable SDK defaults for a release build)
  • Enabling manufacturer firmware protection mechanisms, including encryption and requiring signed firmware to update
  • Updates are delivered throughout the product lifetime. These may be traditional full firmware images or smaller modular updates.
  • Updates are delivered throughout the product lifetime. These may be traditional full firmware images or smaller modular updates.
  • Firmware should only be downloaded through secure channels that can guarantee it is not modified in transit (TLS connections in the Moddable SDK provide this)
  • Firmware updates should be delivered through a delivery network that is able to handle mass updates
  • Products should be implemented to recover if the firmware download does not successfully complete
  • Products should only initiate a software update when it is safe to do so. An eBike shouldn't update when in use and an oven shouldn't update while baking.

Preparing code for deployment

Before delivering code, it is a good practice to perform some essential checks.
1 Run eslint over your JavaScript source files. It does a great job of identifying latent mistakes.
2 If you are using TypeScript, make sure that all warnings have been resolved or verified as safe.
3 Review Instruments in xsbug to confirm that resource use in the new release is similar to the previous release. Any unexpected variance may indicate a potential lurking problem.
4 Make sure there are unit tests for all modules incorporated in the project, and that all unit tests pass

Some teams will perform these checks throughout the course of development, eliminating the need for special checks prior to deployment.

Future of Embedded JavaScript in IoT

Emerging trends and technologies

While Embedded JavaScript is a unique runtime environment with unique performance characteristics from the web ecosystem, a growing number of APIs from the web ecosystem are becoming available to Embedded JavaScript developers. This allows embedded JavaScript developers to benefit from knowledge and experience from the web ecosystem. Examples include Web Workers, fetch, MQTT.js, WebSocket, deepEquals, structuredClone, and many more. While the embedded versions of these APIs offer a subset of the full web versions, they are a powerful tool for building projects.

Many Embedded JavaScript developers use TypeScript. TypeScript can identify many common programming mistakes while the code is compiled instead of waiting until it is run on the device. This saves time. TypeScript is a superset of JavaScript, so JavaScript developers can start using it immediately without having to make immediate changes to their code.

The ECMA-419 Standard, the ECMAScript® embedded systems API specification, is now in its second edition. It is being adopted as the underpinning for much of the Moddable SDK. By providing APIs to access embedded hardware features that have been carefully designed for efficiency, they provide developers with a portable API. High level capabilities of ECMA-419 such as sensor classes are the foundation for an extensive suite of sensor drivers implemented in Embedded JavaScript that are compatible with all supported devices.


Predictions for the future of Embedded JavaScript in IoT

We'll continue to see the benefits of standardization:

As the JavaScript language continues to evolve, many of those capabilities will become available to Embedded JavaScript developers
A growing number of APIs will be available across the web, Node.js, and Embedded JavaScript environments
The ECMA-419 Standard will lead to a growing collection of prebuilt modules, such as sensor drivers, to jumpstart projects
Tool support will continue to evolve, making it easier to set-up and update, and to discover compatible software modules to use in your projects

Hardened JavaScript is a crucial effort aimed at bolstering security in JavaScript through the use of fine-grained, lightweight sandboxes. Thanks to XS, Embedded JavaScript developers are the first to benefit from native support for Hardened JavaScript, making it safer to incorporate third-party modules into their projects. With script isolation, Hardened JavaScript enables the secure installation of user-written scripts in IoT products, allowing for customization of behavior and connection to new network services, among other capabilities.