Skip to content

Commit

Permalink
Re-throw evaluation errors on deferred namespace property access
Browse files Browse the repository at this point in the history
This commit changes the behavior of namespaces obtained through
`import defer` to re-throw evaluation errors even if the module
is fully evaluated:

```js
import defer * as ns from "module-that-throws";
try { ns.foo } catch { console.log("Error!") }
try { ns.foo } catch { console.log("Error!") }
```

The code above is now guaranteed to print `"Error!"` twice,
and it doesn't depend on whether other modules already evaluated
`"module-that-throws"`.

This is different from the existing behavior of namespace objects,
so we have to use a _different_ namespace object for deferred import:

```js
import defer * as ns1 from "module-that-throws";
import * as ns2 from "module-that-throws";

Promise.resolve().then(() => {
  try { ns1.foo } catch { console.log("Error1!") }
  try { ns2.foo } catch { console.log("Error2!") }
});
```

Assuming that this module's body is evaluated due to
a cycle, the code above will print `"Error1!"` and not
`"Error2!"`. This means that `ns1` !== `ns2`.
Namespace objects are still cached, so if you `import defer`
the same module twice you will get the same namespace object.

Thanks to this change, we can now also make "trying to evaluate
a deferred module in a cycle" an error, rather than silently
skipping its evaluation as done in tc39#39. This ensures that a binding
cannot be accessed _during evaluation_ to then disappear as soon
as the module is done evaluating with an error.

Fixes tc39#41 cc @guybedford
  • Loading branch information
nicolo-ribaudo committed Apr 24, 2024
1 parent faa4154 commit 715c0da
Show file tree
Hide file tree
Showing 2 changed files with 565 additions and 203 deletions.
Loading

0 comments on commit 715c0da

Please sign in to comment.