Skip to content

Commit

Permalink
npm run fix:all
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Nov 7, 2024
1 parent 50fc619 commit b2f3406
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion meetings/2024-10/october-10.md
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ Presenter: Nicolò Ribaudo (NRO)
- [proposal](https://github.com/tc39/proposal-defer-import-eval/)
- [slides](https://docs.google.com/presentation/d/1yFbqn6px5rIwAVjBbXgrYgql1L90tKPTWZq2A5D6f5Q/edit)

NRO: Okay. Thank you. Okay, so this is our Stage 2.7 update for the deferred import evaluation. So we were running tests, and we’re in parallel working on experimental implementation. But just to make sure that these steps are all correct. And spoiler, we found some bugs. So just to very quickly recap, I’m not going to go through how it works at this point, but, like, what’s important for this presentation is to remember when a deferred module is evaluated. It’s not evaluated when you import it. That’s the whole point. It’s not evaluated when you reference the deferred namespace. It’s only evaluate when you use it. Specifically, when you try to read a string property, it always triggers evaluation regardless of whether that string is an actual export of the module or not. And reason in modules when accessing unknown export names is that tools or platforms that can skip actually loading the module don’t need to pre-collect a list of exported names, and also so that the behavior of evaluation — you can have a function that says "access this random property to trigget evaluation". When you get a symbol, that never triggers evaluation, because modules cannot export symbol key properties, so we already know that the property will not exist anyway. This can be determined without looking at the internals of modules, and this means, for example, you can get the symbol toStringTag, symbol is present on to object you have or not. For the other object operation, it depends on whether the internal calls [[Get]] or not. So by implementing this, we found that [[Get]] is called less frequently than what is assumed when writing the spec text.
NRO: Okay. Thank you. Okay, so this is our Stage 2.7 update for the deferred import evaluation. So we were running tests, and we’re in parallel working on experimental implementation. But just to make sure that these steps are all correct. And spoiler, we found some bugs. So just to very quickly recap, I’m not going to go through how it works at this point, but, like, what’s important for this presentation is to remember when a deferred module is evaluated. It’s not evaluated when you import it. That’s the whole point. It’s not evaluated when you reference the deferred namespace. It’s only evaluate when you use it. Specifically, when you try to read a string property, it always triggers evaluation regardless of whether that string is an actual export of the module or not. And reason in modules when accessing unknown export names is that tools or platforms that can skip actually loading the module don’t need to pre-collect a list of exported names, and also so that the behavior of evaluation — you can have a function that says "access this random property to trigget evaluation". When you get a symbol, that never triggers evaluation, because modules cannot export symbol key properties, so we already know that the property will not exist anyway. This can be determined without looking at the internals of modules, and this means, for example, you can get the symbol toStringTag, symbol is present on to object you have or not. For the other object operation, it depends on whether the internal calls [[Get]] or not. So by implementing this, we found that [[Get]] is called less frequently than what is assumed when writing the spec text.

NRO: So, for example, [[GetOwnProperty]] we first check if it’s an exported name and then call [[Get]]. So it behaves differently. And this means that actually only evaluating [[Get]], we don’t get the benefits because we can just use another of the object methods and we’ll assume it to nod list of expert names, so the processed solution here is always check deferred name of exported names. This means that also if, for example, you trying to `Reflect.keys` it does not trigger evaluation, while `Object.keys` triggets evaluation because it calls [[Get]] internally, but there are other ways to get list of keys from an object that do not call [[Get]] internally, so it would be to get it covered. So that the rules becomes whenever you try to query properties about the object, if this properties depend on the contents of the module, the module would be evaluated. The second problem we found was that `import.defer`, which is the dynamic form proposal, does not truly work as we were expecting it to work. So if you have this example here, when would you expect evaluation to happen? Well, it happens there, in the `import.defer` call. And not when you actually write something `await namespace`, and this is, like, completely against the proposal. There’s not deferred execution going on here. And why is this happening? Well, if we try to just, like think of how `import.defer` works and internally, we create a promise, we load the module, load the dependencies and then resolve the promise with the deferred namespace object. And how does resolve work? Well, resolves checks if the given value has a .`.then` property and if it is callable, otherwise it actually resolves the promise with the values it’s given. And it’s this check that’s causing problems. We’re performing of get of this `then` property on the namespace object, and this always triggering evaluation of the module before the promise to import the deferred is resolved.

Expand Down

0 comments on commit b2f3406

Please sign in to comment.