Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ We propose to expose an explicit synchronous import function for ES modules, as
const ns = import.sync('./mod.js');
```

The major design of the proposal is a new `Error` which is thrown when a module is not synchronously
available, or uses top-level await.
When a module is not synchronously available (e.g. it requires async I/O to fetch, or uses top-level
await), `import.sync` returns `null` rather than throwing an error.

Whether a module is synchronously available would otherwise be a host-determined property.
Whether a module is synchronously available is a host-determined property.

## Use Cases

Expand All @@ -66,16 +66,17 @@ const app = import.sync('app');

### Conditional Loading

Just like with dynamic import, with a synchronous import, it's possible to check if a module or builtin is available, but synchronously.

For example, checking if host builtins are available:
Because `import.sync` returns `null` when a module is not synchronously available, optional chaining
can be used to conditionally access features:

```js
let fs;
try {
fs = import.sync('node:fs');
} catch {}
import.sync('lib')?.feature();
```

More generally, it's possible to check if a module or builtin is available synchronously:

```js
const fs = import.sync('node:fs');
if (fs) {
// Use node:fs, only if it is available
}
Expand All @@ -84,11 +85,7 @@ if (fs) {
Or a library that conditionally binds to a framework dependency:

```js
let react;
try {
react = import.sync('react');
} catch {}

const react = import.sync('react');
if (react) {
// Bind to the React framework, if available
}
Expand Down
13 changes: 8 additions & 5 deletions spec.emu
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ contributors: Guy Bedford
<h1>
<ins>ImportCallSync (
_arguments_: a Parse Node
): either a normal completion or an abrupt completion</ins>
): either a normal completion containing either a Module Namespace Object or *null*, or an abrupt completion</ins>
</h1>
<dl class="header"></dl>
<emu-alg>
Expand Down Expand Up @@ -94,10 +94,13 @@ contributors: Guy Bedford
1. Let _moduleCompletion_ be NormalCompletion(~empty~).
1. Perform HostLoadImportedModule(_referrer_, _moduleRequest_, ~empty~, _moduleCompletion_).
1. NOTE: HostLoadImportedModule will update _moduleCompletion_ synchronously either updating its value to be a Module Record, or setting it to be a throw completion.
1. Let _module_ be ? _moduleCompletion_.
1. Perform ? _module_.LoadRequestedModulesSync().
1. Perform ? _module_.Link().
1. If ReadyForSyncExecution(_module_) is *false*, throw a *TypeError* exception.
1. If _moduleCompletion_ is a throw completion, return *null*.
1. Let _module_ be _moduleCompletion_.[[Value]].
1. Let _loadResult_ be Completion(_module_.LoadRequestedModulesSync()).
1. If _loadResult_ is a throw completion, return *null*.
1. Let _linkResult_ be Completion(_module_.Link()).
1. If _linkResult_ is a throw completion, return *null*.
1. If ReadyForSyncExecution(_module_) is *false*, return *null*.
1. Perform ? EvaluateModuleSync(_module_).
1. Return GetModuleNamespace(_module_, ~evaluation~).
</emu-alg>
Expand Down
Loading