ESMification Prep 2: What is an ESM?

Skip to first unread message

Tooru Fujisawa

Jul 7, 2022, 10:50:37 AM7/7/22
to dev-platform,
Hi, everyone.

ESMification is a project to switch the Mozilla-specific JSMs in privileged code to standard ECMAScript modules (ESMs). To get everyone ready and on the same page, we have written a series of three emails to help contextualize the transition, and this is the second one.

Today, I’d like to provide a brief explanation of what an ESM is and how it’s different from a JSM, to help everyone get familiar with them and ready for the migration.

What is an ESM?

ESM, or ECMAScript Modules, is a module system provided as part of the ECMAScript standard.  It has almost the same syntax as plain non-module JavaScript, with extra `import` and `export` declarations to import and export symbols (variables) between module files. Usually `.mjs` file extensions are used.

In the web content context, each ESM is a per-document singleton, shared among all consumers in the document, including inline script, script files, and event handlers.  The ESM file is evaluated when it’s imported at the first time, and subsequent loads for the module return the cached module, just in the same way as JSM.

ESM is always in strict mode.  So you don’t need the `”use strict”;` statement at the top of the file.

What does an ESM look like?

An ESM file that exports a function looks like the following: 

export function SayHello() {
  console.log(”Hello, World!”);

The `export` keyword can be added to variable declarations and function declarations, to make them exported by the module with the variable’s and function’s name.

An ESM file that imports another module looks like the following:

import { SayHello } from ”./Hello.mjs”;

All imported modules are evaluated before the importer module gets evaluated.

Both `export` and `import` declarations are permitted only at the top-level of the module script.
To import modules conditionally, or inside functions, the dynamic import feature is provided.

async function f() {
  const { SayHello } = await import(”./Hello.mjs”);

The `await` keyword can also be used at the top-level of the module.

The ESM environment doesn’t have global `this`, and global `var` and `function` don’t become `window` object’s properties.

var SomeVariable = 10;
console.log("SomeVariable" in window); // false

What does ESMification provide?

ESMification provides the ability to use ESMs in Firefox's privileged module system. We call these “System ESMs”.  System ESMs can use `import` and `export` declarations instead of JSM’s `ChromeUtils.import` and `EXPORTED_SYMBOLS`.

System ESMs can be imported with the new `ChromeUtils.importESModules` API from regular chrome-privilege code, in the same way as `ChromeUtils.import` for JSM.

System ESM is a per-process singleton, in the same way as JSM.

In the initial phase of ESMification, neither dynamic import or top-level await are supported.  In the non-top-level code inside the system ESM, `ChromeUtils.importESModules` can be used to import other system ESMs synchronously.

Thank you for reading.
If you have questions, feel free to ask in the #esmification matrix room!
Stay tuned for the 3rd one of the preparation series that will explain the example JSM-to-ESM migration patch!
Reply all
Reply to author
0 new messages