Skip to content

Commit be011c2

Browse files
hamishwilleeJosh-Cenagithub-actions[bot]
authored
Restructure import assertions description to ease maintainability (mdn#42309)
* Restructure import assertions description to ease maintainability * Apply suggestions from code review * Clarify ECMAScript supports type of json * Apply suggestions from code review * Apply suggestions from code review Co-authored-by: Joshua Chen <sidachen2003@gmail.com> * minor cleanup * Description intro - attempt to match original flow * Update files/en-us/web/javascript/reference/statements/import/with/index.md * Update files/en-us/web/javascript/reference/statements/import/with/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update files/en-us/web/javascript/reference/statements/import/with/index.md --------- Co-authored-by: Joshua Chen <sidachen2003@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 23dc2a1 commit be011c2

File tree

1 file changed

+59
-14
lines changed
  • files/en-us/web/javascript/reference/statements/import/with

1 file changed

+59
-14
lines changed

files/en-us/web/javascript/reference/statements/import/with/index.md

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ export { names } from "module-name" with { key: "data", key2: "data2", /* …, *
3434
- `"dataN"`
3535
- : An attribute value. Must be a string literal.
3636

37+
### Exceptions
38+
39+
- {{jsxref("SyntaxError")}}
40+
- : An unsupported `key` was specified in a _static import_.
41+
42+
- {{jsxref("TypeError")}}
43+
- : An unsupported `key` was specified in a _dynamic import_.
44+
45+
Note that specifying an unsupported value for a supported key may also result in an exception in some cases, depending on the key.
46+
3747
## Description
3848

3949
Import attributes tell the runtime how a particular module should be loaded.
@@ -53,36 +63,73 @@ Content-Type: application/json; charset=utf-8
5363
{"name":"Maria"}
5464
```
5565

56-
Modules are identified and parsed only according to their served [MIME type](/en-US/docs/Web/HTTP/Guides/MIME_types) — the file extension in the URL cannot be used to identify a file's type. In this case, the MIME type is `application/json`, which tells the browser that the file is JSON and must be parsed as JSON. If, for some reason (e.g., the server is hijacked or bogus), the MIME type in the server response is set to `text/javascript` (for JavaScript source), then the file would be parsed and executed as code. If the "JSON" file actually contains malicious code, the `import` declaration would unintentionally execute external code, posing a serious security threat.
66+
Modules are identified and parsed only according to their served [media type (MIME type)](/en-US/docs/Web/HTTP/Guides/MIME_types) — the file extension in the URL cannot be used to identify a file's type. In this case, the MIME type is `application/json`, which tells the browser that the file is JSON and must be parsed as JSON. If, for some reason (e.g., the server is hijacked or bogus), the media type in the server response is set to `text/javascript` (for JavaScript source), then the file would be parsed and executed as code. If the "JSON" file actually contains malicious code, the `import` declaration would unintentionally execute external code, posing a serious security threat.
5767

58-
Import attributes fix this problem by allowing the author to explicitly specify how a module should be validated. For example, the import statement above, which lacks an attribute, would actually fail:
68+
Import attributes fix this problem by allowing the author to explicitly specify how a module should be validated.
69+
In particular, the `type` attribute allows you to validate that the file is served with a particular media type, and fails the import if a different media type is used.
5970

60-
```plain
61-
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/json". Strict MIME type checking is enforced for module scripts per HTML spec.
71+
For example, the code above can be written to specify that the expected type is `"json"` and the import would fail if it was served with the `text/javascript` (or any media type other than `application/json`):
72+
73+
```js
74+
import data from "https://example.com/data.json" with { type: "json" };
6275
```
6376

64-
Instead, you must provide an attribute to tell the runtime that this file must contain JSON. To validate the module's type (via MIME type), you use the attribute key called `type`. To validate that the module is a JSON module, the value is `"json"`.
77+
The `type` attribute allows you to specify that modules are served as JSON or CSS (and implicitly as JavaScript).
6578

66-
> [!NOTE]
67-
> The actual `type` attribute value does not correspond directly to the MIME type. It's separately specified by the [HTML specification](https://html.spec.whatwg.org/multipage/webappapis.html#module-type-allowed).
79+
Other attributes may also be supported, and [can affect the behaviour of different parts of the loading process](#intended_semantics_for_import_attributes).
80+
A syntax error is thrown if an unknown attribute is used.
81+
82+
### Standard attributes
83+
84+
The available attributes depend on the language and runtime environment.
85+
The ECMAScript standard [defines the `type` attribute with the value of `"json"`](https://tc39.es/ecma262/multipage/ecmascript-language-scripts-and-modules.html#sec-HostLoadImportedModule).
86+
87+
The HTML specification also [defines the `type` attribute with values `"json"` and `"css"`](https://html.spec.whatwg.org/multipage/webappapis.html#module-type-allowed) — these are the attributes that are supported in browser environments.
88+
89+
#### JSON Modules (`{ type: "json" }`)
6890

69-
Therefore, the code above should be re-written as:
91+
The `json` type indicates that the imported file must contain JSON.
92+
You can load JSON from a file into the `data` object using the following code:
7093

7194
```js
7295
import data from "https://example.com/data.json" with { type: "json" };
7396
```
7497

98+
If the file is served with any other media type than `"application/json"`, the import will fail.
99+
75100
The `type` attribute changes how the module is fetched (the browser sends the request with `{{HTTPHeader("Accept")}}: application/json` header), but does _not_ change how the module is parsed or evaluated. The runtime already knows to parse the module as JSON given the response MIME type. It only uses the attribute to do _after-the-fact_ checking that the `data.json` module is, in fact, a JSON module. For example, if the response header changes to `Content-Type: text/javascript` instead, the program will fail with a similar error as above.
76101

77-
The specification explicitly calls out `type: "json"` to be supported — if a module is asserted to be `type: "json"` and the runtime does not fail this import, then it must be parsed as JSON. However, there's no behavior requirement otherwise: for imports without a `type: "json"` attribute, the runtime may still parse it as JSON if security is not an issue in this environment. Browsers, on the other hand, implicitly assume that the module is JavaScript, and fail if the module is not JavaScript (for example, JSON). This ensures that module types are always strictly validated and prevents any security risks. In reality, non-browser runtimes such as Node and Deno align with browser semantics and enforce `type` for JSON modules.
102+
The specification explicitly calls out `type: "json"` to be supported — if a module is asserted to be `type: "json"` and the runtime does not fail this import, then it must be parsed as JSON.
103+
104+
However, there's no behavior requirement otherwise: for imports without a `type: "json"` attribute, the runtime may still parse it as JSON if security is not an issue in this environment.
105+
106+
Browsers, on the other hand, implicitly assume that the module is JavaScript if the `type` is not specified, and fail if the module is not JavaScript (for example, JSON). This ensures that module types are always strictly validated and prevents any security risks.
107+
Non-browser runtimes such as Node and Deno align with browser semantics and enforce `type` for JSON modules.
108+
109+
In other words, if you omit the `type` and attempt to import a file as `"application/json"` you will usually get an error like the following:
110+
111+
```plain
112+
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/json". Strict MIME type checking is enforced for module scripts per HTML spec.
113+
```
114+
115+
#### CSS Modules (`{ type: "css" }`)
78116

79-
The `type` attribute also supports other module types. For example, the HTML spec also defines the `css` type, which imports a {{domxref("CSSStyleSheet")}} object:
117+
The HTML spec defines the `css` type, which imports a stylesheet into a script as an {{domxref("CSSStyleSheet")}} object.
118+
119+
The code below shows how you might import a style and add it to your document.
120+
The import will throw an exception if `example_styles.css` is served with any media type other than `"text/css"`.
80121

81122
```js
82-
import styles from "https://example.com/styles.css" with { type: "css" };
123+
import exampleStyles from "https://example.com/example_styles.css" with { type: "css" };
124+
125+
document.adoptedStyleSheets.push(exampleStyles);
83126
```
84127

85-
The attributes syntax is designed to be extensible — although only `type` is specified by the language, the runtime can read and process other attributes. An attribute can change the runtime's behavior at every stage of the module loading process:
128+
Note that importing CSS modules into workers is usually not supported, because the CSSOM specification only exposes `CSSStyleSheet` in the window context.
129+
130+
### Intended semantics for import attributes
131+
132+
An attribute can change the runtime's behavior at every stage of the module loading process:
86133

87134
- Resolution: the attribute is part of the module specifier (the string in the `from` clause). Therefore, given the same string path, different attributes may lead to entirely different modules being loaded. For example, [TypeScript supports the `resolution-mode` attribute](https://devblogs.microsoft.com/typescript/announcing-typescript-5-3/#stable-support-resolution-mode-in-import-types).
88135

@@ -95,8 +142,6 @@ The attributes syntax is designed to be extensible — although only `type` is s
95142
- Fetching: for example, CSS modules are fetched with the [`destination`](/en-US/docs/Web/API/Request/destination) set to `"style"`, and JSON modules are fetched with `destination: "json"`. This means given the same destination URL, the server may still return different content.
96143
- Parsing and evaluation: the runtime may use the attribute to determine how to parse and evaluate the module.
97144

98-
However, you cannot use unknown attributes — the runtime throws an error if it encounters an unknown attribute.
99-
100145
## Examples
101146

102147
### Importing JSON modules with the type attribute

0 commit comments

Comments
 (0)