endo icon indicating copy to clipboard operation
endo copied to clipboard

Externalize Eventual Send in Endo Bundles

Open kriskowal opened this issue 2 years ago • 10 comments

Most Endo applications currently need to import @endo/far to get E and Far. The Endo runtime could instead inject these as global variables, but linters, type checkers, and the language server all like these to be imported for various reasons. We can reduce the weight of bundles and also keep these imports, using Compartment Mapper tricks.

  • Ensure that @endo/bundle-source uses the endo tag by default, or create a new endo:far bundle tag to indicate the external dependency on endo:far.
  • Alter the @endo/import-bundle importBundle such that it provides an endo:far builtin module that exports E and Far and ensure that it uses the endo tag.
  • And an entry to @endo/far’s package.json like { "exports": { "endo": "endo:far" } }.

kriskowal avatar Jun 08 '23 21:06 kriskowal

cc @mfig for design review

kriskowal avatar Jun 08 '23 21:06 kriskowal

Why? Generally globals are an anti-pattern.

OTOH, if these were global, could we avoid the Eval Twin problem https://github.com/endojs/endo/issues/1583 , and know that @endo/pass-style (the origin of Far) is instantiated exactly once? Could passStyleOf then safely recognize fars its Far made simply by brand check in its own WeakMap, which would then no longer need to be only an unobservable memo?

erights avatar Jun 09 '23 00:06 erights

At #1583 I imagined we could solve the Eval Twin problem with compartments without using globals. Is that as easy?

erights avatar Jun 09 '23 00:06 erights

Oh, I’ll edit above. The globals are not necessary in this design. Just threading an exit for builtin modules is. Also would degrade gracefully for other environments.

kriskowal avatar Jun 09 '23 00:06 kriskowal

As for motivation, this would remove a copy of far from every contract bundle and also reduce instances to one. I do not think this is sufficient to completely eliminate the need to mitigate Eval Twins.

kriskowal avatar Jun 09 '23 00:06 kriskowal

And the reason this is not sufficient to eliminate the need to anticipate encountering eval twins is that Endo is not the only environment we need to support. Eventual Send should work on stock node with npm eval twins as well.

kriskowal avatar Jun 09 '23 00:06 kriskowal

At #1583 I imagined we could solve the Eval Twin problem with compartments without using globals. Is that as easy?

This solution would certainly be applicable to other cases. The big deal is that these modules would fall thru to making eval twins on other platforms. I think we should still design these modules to anticipate encountering eval twins.

kriskowal avatar Jun 09 '23 00:06 kriskowal

I'm not sure how exports play a role. I would expect something more along the lines of:

  • User code imports @endo/pass-style
  • The @endo/pass-style package.json uses a subpath import:
    "imports": {
      "#pass-style-impl": {
        "endo": "endo:pass-style",
        "default": "./pass-style.js"
      }
    },
    
  • The index.js of @endo/pass-style does something like:
    export { passStyleOf } from '#pass-style-impl';
    
  • The bundler automatically considers any endo:* package as an exit module
  • The bundle loader is responsible to provide a virtual module for the endo:pass-style exit module.

mhofman avatar Jun 26 '23 22:06 mhofman

I’ve created a general issue for surfacing host modules. https://github.com/endojs/endo/issues/1653

kriskowal avatar Jun 26 '23 22:06 kriskowal

Demonstration https://github.com/endojs/endo/pull/2422

kriskowal avatar Aug 20 '24 23:08 kriskowal