15.MODULE-SYSTEM.md 4.3 KB
Newer Older
1 2
# ES6 module support for JerryScript

3
The module system allows users to write import and export statements in scripts, which can be used to separate the logic of the application into custom modules.
4
The standard's relevant part can be found [here](https://www.ecma-international.org/ecma-262/6.0/#sec-modules).
5
Embedders wishing to use native builtin modules with ES6 imports can use the [Port API](05.PORT-API.md#es2015-module-system) to do so.
6 7 8

## General

9 10
If a script contains import statements, then JerryScript will open and evaluate the the referenced modules before the main script runs, resolving and creating bindings for the referenced identifiers in the process.
It is not necessary to use any specific filename extensions for modules, JerryScript will try to open the given file paths as they are, but will try to normalize them before doing so. The exact normalization process is dependant on the port implementation provided. It is the user's responsibility to verify that the given files are valid EcmaScript modules.
11 12 13 14

main.js

```js
15
import { exported_value } from "./module.js"
16

17
print (exported_value);
18 19 20 21 22
```

module.js

```js
23
var exported_value = 42;
24

25
export exported_value;
26 27 28 29
```

## Supported features

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
* exporting identifiers from the module's lexical environment
  * specifying export names for the exported values
* importing exported identifiers from a module
  * specifying local binding names for the imported values
* module namespace imports
  * `import * as module from 'module.js`
* indirect export statements
  * `export {variable} from 'module.js'`
* star export statements
  * `export * from 'module.js'`
* importing a module for side-effects
  * `import 'module.js'`
* default import and export statements
  * `export default local_identifier`
  * `import def from 'module.js'`
* anonymous default exports
  * `export default function () {}`
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

### Example

```js
import {
  engine,
  version as v
} from "./module.js"

import { getFeatureDetails } from "./module_2.js"

var version = "v3.1415";

print("> main.js");

print(">> Engine: " + engine);
print(">> Version: " + v);

print (">> " + getFeatureDetails());
print (">> Script version: " + version);
```

```js
// module.js
var _engine = "JerryScript";
export _engine as engine;

export var version = "1.0 (e92ae0fb)";
```

```js
// module_2.js
var featureName = "EcmaScript 2015 modules";
var year = 2018;

export function getFeatureDetails() {
  return "Feature name: " + featureName + " | developed in " + year;
}
```

87
### Module namespace import statements
88

89 90 91 92 93 94 95 96
A module namespace object can be imported. In this case the local binding will contain an object holding the exported values of the module, including local exports and all indirect exports. Ambiguous exported names are exluded from the namespace object.

```js
import * as module from './module.js';

print(">> Engine: " + module.engine);
print(">> Version: " + module.version);
```
97

98
### Indirect export statements
99

100
An export statement can transitively export variables from another module, either via named indirect exports or a star export statement. In this case the resolving process will follow the chain until it reaches a module containing a local binding for that export name. If there are multiple modules which satisfy the export, that means the export is ambiguous, and will result in a SyntaxError.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120

```js
import { a, b } from 'module.js'

print (a + b);
```

```js
// module.js
export var a = 2;
export { b } from 'module2.js'
```

```js
// module2.js
export var b = 40;
```

### Default imports and exports

121
Each module can optionally provide a single default export by using the `export default` statement. Default exports can either reference identifiers in the module's lexical environment, or be an anonymous default export, in which case they will only be accessible by an importing script.
122

123 124
```js
import defaultExport, { b as c } from 'module.js'
125

126 127 128
print (defaultExport); // 2
print (c ()); // 42
```
129 130

```js
131 132 133 134 135 136 137 138 139 140
// module.js
export default 2;
export function b () {
  return 42;
}
```

### Importing modules for side-effects

Evaluate a module without importing anything. Any errors encountered in the module will be propagated.
141

142 143 144 145
```js
import 'module.js' // > module.js
// "> module.js" is printed
b (); // (ReferenceError) b is not defined
146 147 148 149
```

```js
// module.js
150 151 152
export function b () {
  print ("> module.js");
  return 42;
153
}
154
b ();
155
```
156 157 158 159

## Unsupported features

* **snapshot**