Skip to content
Proposal for syntax to import ES modules with attributes
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
README.md Add myself as co-champion Dec 6, 2019
content-type-vs-file-extension.md Update stats.md Oct 29, 2019

README.md

ES Module Attributes

Champions: Sven Sauleau (@xtuc), Daniel Ehrenberg (@littledan), Myles Borins (@MylesBorins), and Dan Clark (@dandclark)

Status: Stage 1

The ES Module Attributes proposal is an investigation into providing inline syntax for module import statements to pass on more information alongside the module specifier, with an initial aim to support non-JS ESM module types.

Motivation

As one example of an application: standards-track JSON ESM modules were proposed to allow JavaScript modules to easily import JSON data files, similarly to how they are supported in many nonstandard JavaScript module systems. This idea quickly got broad support from web developers and browsers, and was merged into HTML, with an implementation created by Microsoft.

However, in an issue, Ryosuke Niwa (Apple) and Anne van Kesteren (Mozilla) proposed that security would be improved if some syntactic marker were required when importing JSON modules and similar module types which cannot execute code, to prevent a scenario where the responding server unexpectedly provides a different MIME type, causing code to be unexpectedly executed. The solution was to somehow indicate that a module was JSON, or in general, not to be executed, somewhere in addition to the MIME type.

Some developers have the intuition that the file extension could be used to determine the module type, as it is in many existing non-standard module systems. However, it's a deep web architectural principle that the suffix of the URL (which you might think of as the "file extension" outside of the web) does not lead to semantics of how the page is interpreted. In practice, on the web, there is a widespread mistmatch between file extension and the HTTP Content Type header. All of this sums up to it being infeasible to depend on file extensions/suffixes included in the module specifier to be the basis for this checking.

There are other possible pieces of metadata which could be associated with modules, see #8 for futher discussion.

Proposed ES module types that are blocked by this security concern, in addition to JSON modules, include CSS modules and potentially HTML modules if the HTML module proposal is restricted to not allow script.

Rationale

There are three places where this data could be provided:

  • As part of the module specifier (e.g., as a pseudo-scheme)
    • Challenges: Adds complexity to URLs or other module specifier syntaxes, and risks being confusing to developers (further discussion: #11)
  • Separately, out of band (e.g., a separate resource file)
    • Challenges: How to load that resource file; what should the format be; unergonomic to have to jump between files during development (further discussion: #13)
  • In the JavaScript source text
    • Challenges: Requires a change at the JavaScript language level (this proposal)

This proposal pursues the third option, as we expect it to lead to the best developer experience, and are hopeful that language design/standardization issues can be resolved.

Early draft syntax

Module attributes have to be made available in several different contexts. This section contains one possible syntax, but there are other options, discussed in #6.

Here, a key-value syntax is used, with the key type used as an example indicating the module type. Such key-value syntax can be used in various different contexts. Another option is to have just a single string (discussion in #11).

The JavaScript standard would basically be responsible for passing the options bag up to the host environment, which could then decide how to interpret it. Issues #24 and #25 discuss the Web and Node.js feature and semantic requirements respectively, and issue #10 discusses how to allow different JavaScript environments to have interoperability.

import statements

The ImportDeclaration would allow any arbitrary attributes after the with keyword.

For example, in some environments a type key could be mandatory to load a module that isn't JavaScript (json, css, html, ...).

import json from "./foo.json" with type: "json";

dynamic import()

The import function will allow to provide arbitrary attributes as its second arguments.

import("foo.json", { type: "json" })

Integration Example

A host environment may wish to have type or similar apply to loading WebAssembly. WebAssembly's validation would fail if the magic number is not correct, but we'd assert that the mimetype matches the type before even before running the WebAssembly validation.

Note, this is an example; it's still uncertain whether importing WebAssembly modules would need to be marked specially, or could use type="module" just like JavaScript (and no special with type: in import statements). Further discussion in #19.

From there, a host environment could integrate with its own APIs or even other languages:

Worker instantiation

new Worker("foo.wasm", { type: "webassembly" });

HTML

<script src="foo.wasm" type="webassembly"></script>

WebAssembly

For imports of other module types from within a WebAssembly module, this proposal would introduce a new custom section (named importattributes) that will annotate with attributes each imported module (which is listed in the import section).

Status and plan for standardization

This proposal has not yet been presented in a standards body. It's considered Stage 0 in TC39's process because we plan to present it to the committee. The plan is to collect feedback in issues, and present for Stage 1 in the December 2019 TC39 meeting.

Standardization here would consist of building consensus not just in TC39 but also in WHATWG HTML as well as the Node.js ESM effort and a general audit of semantic requirements across various host environments (#10, #24 and #25). Stage 2 will also require that we have a strong initial answer for the surface syntax (#6), including the choice of whether we use a single string or key/value pairs (#12).

Please leave any feedback you have in the issues!

You can’t perform that action at this time.