ESMification: Lazy Getters FAQ

64 views
Skip to first unread message

Yulia Startsev

unread,
Jun 8, 2022, 2:36:07 PM6/8/22
to dev-pl...@lists.mozilla.org

Hey folks,

As many of you know, there is an ongoing project to make it possible to write standard ESMs in the Firefox codebase. We are currently in the preparatory phase, and are gradually massaging the codebase into an adequate state where the transition can happen. As issues come up, we will be sending out updates and requests for feedback. Most recently We’ve been circulating a couple of documents to teams that will be directly affected [1]. However, this did not reach everyone and given the scale of the preparatory changes there were some surprises. In particular, we’ve had a few people reach out regarding the `lazy.` prefix.

 The goal of this email is to give context more broadly about this decision and invite feedback.


Why are we introducing a `lazy.` prefix?

 


As we prepare to make the move to ESMs, we are transitioning as much of the codebase as possible into a form that is syntactically legal as ESMs. Other work in this direction has been ongoing, but has not had as significant impact on the codebase.


The incompatibility we are currently addressing between JSMs and ESMs is two fold. The first is that JSMs have a `this` referring to the local global, standard JS modules do not. As a result, the old pattern of installing lazy getters on a local global via `this` will no longer be possible. In addition, this pattern cannot be fully deprecated and maintain performance [2]. The second is that our culture of writing JSMs has been to export a single named symbol, and we have no concept of a default export in JSMs. That said, it is possible to lazily import a module in a more ergonomic way, but this gets in the way of lessening the burden via automatically rewriting JSMs into ESMs. It is a bit of a “chicken or the egg” problem, there are two changes that need to be made.


Eventually, you will be able to do this:




```

// module.js

export default MyModule;


// main.js

const MyModule = ChromeUtils.importLazyModule(“module.sys.mjs”);

```


For multiple exports, you will still need to do the following for now:


```

// module.sys.mjs

export { MyModule, MyOtherModule };


// main.js

const lazy = {};

ChromeUtils.defineModuleGetters(

  lazy,

  { MyModule: ”module.sys.mjs” }

);

```


It was determined that in order to enable laziness with these exposed symbols and maintain performance, we need an intermediary object. We cannot allow the destructuring pattern, as it will eagerly load the modules in place. Alternatives were also ruled out for performance reasons are detailed in [2].


`lazy.` was chosen as the prefix as it is short, preserves performance, and enables the transition.


Are we stuck with this forever?


It depends on the code. Many modules can be updated to the more ergonomic pattern. In the next phase, when we transition to ESM syntax, You will be able to determine if existing files need to be broken up (enabling the default export pattern), or if there are any other changes that need to be made.


As both the call site and the module need to be transitioned at the same time, you will be able to gradually transition your ESMs to use default export syntax like so:


```

// module.js

export default MyModule;


// main.js

const MyModule = ChromeUtils.importLazyModule(“module.mjs”); // new API that allows installing a lazy getter on a module global

```



What do the phases look like? 



We will be sending a general update on the ESMification project. For now, in the context of how this impacts Lazy Getters:


Preparation


Make all files use only syntax that is legal in ESMs. This is handled by the SpiderMonkey team (along with providing the APIs). Individual teams will need to review, but no other work is expected.


This requires the introduction of the `lazy.` prefix. For the time being, you will see the following:




```

// module.js

var EXPORTED_SYMBOLS = [“MyModule”];

// once ESMification automatic rewriting starts this will become: export { MyModule };


// main.js

const lazy = {};

ChromeUtils.defineModuleGetter(

  lazy,

  ”MyModule”,

);

```


Phase 1


Team-based Semi-automatic JSM-to-ESM translation. This will be the culmination of the preparatory work, and bring us into the active part of ESMification. We will send a more detailed email about this work in the near future. 


Phase 2


Team-based inspection and updating of edge case ESMs. This can be done simultaneously with Phase 1 per the team’s preference.


Focusing on the Lazy Getter work: if your component is affected, you will get a list of files to check. After reviewing the files, you may be able to transition to the following pattern:


```

// module.js

export default MyModule;


// main.js

const MyModule = ChromeUtils.importLazyModule(“module.mjs”);

```


Timeline?


We are looking at a few cycles, with a longer tail to finish the transition completely.


---


Note: The semantics of the APIs are more or less fixed however the names are still subject to change.




We will be posting an update shortly, with more information about the general ESMification work. For now, on the `lazy.` prefix,  we welcome any feedback you might have.


[1]: https://docs.google.com/document/d/1a71rnNTNr-VZFEQaCNixaohuegNe1UUQkYuC3JykcW4/edit

[2]: https://docs.google.com/document/d/1LjKkl-hSnXy82r0QO6XWg-A7TbJ9EkCvaQOqP_YgwtQ/edit#heading=h.ev7iv5bj670a




Fabrice Desré

unread,
Jun 8, 2022, 5:59:01 PM6/8/22
to Yulia Startsev, dev-pl...@lists.mozilla.org
Hi Yulia,

Can you make the document [1] public? As a maintainer of a gecko fork,
it would help to know if the current JSM support will be removed at some
point, and if so, when.

Thanks!
> <https://docs.google.com/document/d/1LjKkl-hSnXy82r0QO6XWg-A7TbJ9EkCvaQOqP_YgwtQ/edit#heading=h.ev7iv5bj670a>
>
>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "dev-pl...@mozilla.org" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to dev-platform...@mozilla.org
> <mailto:dev-platform...@mozilla.org>.
> To view this discussion on the web visit
> https://groups.google.com/a/mozilla.org/d/msgid/dev-platform/CAPxDkP_e896mCXq93NRiOONG6WraLyb8WTv%2BMHekrakSwjZnRQ%40mail.gmail.com
> <https://groups.google.com/a/mozilla.org/d/msgid/dev-platform/CAPxDkP_e896mCXq93NRiOONG6WraLyb8WTv%2BMHekrakSwjZnRQ%40mail.gmail.com?utm_medium=email&utm_source=footer>.

Yulia Startsev

unread,
Jun 9, 2022, 6:55:59 AM6/9/22
to Fabrice Desré, dev-pl...@lists.mozilla.org
Hi Fabrice,

Thanks for bringing that up. That document isn't quite ready to be public but will be published soon. For now, to answer your question: Currently,  some in-tree JSMs may need to be kept as they are (we anticipate some difficult edge cases). Therefore the removal of ChromeUtils.import is not planned yet. We are planning on either removing Cu.Import or making it an alias of ChromeUtils.import. Ideally, at some point in the future we would like to migrate fully away from JSMs but this is not yet concrete. We will inform dev-platform if this takes place.

For now, if you are using Cu.Import, please consider migrating away from it soon.

best,
Yulia
Reply all
Reply to author
Forward
0 new messages