Compartment support for dynamic import and importMetaHook #291
Labels
kriskowal-reviewed-2024-01
Issues that kriskowal is satisfied do not need attention from team bug review as of January, 2024
[update April 20, 2022]:
Description
SES shim should support the features of dynamic import (
import
) and import metadata (import.meta
). These must be implemented in a manner that is host neutral and afford the possibility of lazy, on-demand initialization ofimport.meta
for use cases likeimport.meta.resolve
that would be prohibitively expensive if constructed for modules that do not utterimport.meta
in their source.Design
In
@endo/static-module-record
we employ a source to source transformation that produces a “first-party static module record” thatses
understands how to load, link, and initialize when returned through theimportHook
. In SES, themodule-instance.js
module is responsible for the runtime component for evaluating modules. We must extend this calling convention to support dynamic import and import metadata.Also, because static module records are committed to archives and stored, the calling convention for modules generated by older versions of
@endo/static-module-record
must be preserved.I propose that we do this by rewriting dynamic
import(specifier)
andimport.meta
in the module-to-program transformation to forms like$h_import()
and$h_import_meta
, including the ZWJ so the hidden symbol censorship still applies. The module-instance.js linker must pass suitable values for these into the generated module functor. The dynamic import function must be a closure that applies theresolveHook
relative to the currentmoduleSpecifier
.Since creating
$h_import_meta
and$h_import
are avoidable if they were not uttered by the source, or compiled by an earlier version of@endo/static-module-record
, the newerStaticModuleRecord
constructor should add new properties to the record, like__usesImport
and__usesImportMeta
, as an indication for whether these should be made.$h_import_meta
must be an object with anull
prototype.The
importHook
(to be calledloadHook
in a future revision #420) will need to be able to return a “module record envelope” that has an optionalmeta
property. Therecord.meta
property is an object to copy to the$h_import_meta
object, either with the semantics ofObject.assign($h_import_meta, record.meta)
orObject.defineProperties($h_import_meta, Object.getOwnPropertyDescriptors(record.meta))
, on which we need consensus among the champions of the TC39 Compartment Proposal.We would, either in this change or a future change to be factored out of this issue, also implement a
importMetaHook
. TheimportMetaHook
would receive$h_import_meta
and have an opportunity to augment it and freeze it before the object is revealed to guest code. The module machinery must only call the hook ifimport.meta
is uttered in the module code. The host function must not be called on the stack of guest code.We will need consensus among the Compartments champions for the time that the
importMetaHook
function must be called, but I’m guessing that the most obvious answer would be immediately before initializing the module, without any opportunity for other events to be interleaved. So, an exception thrown inimportMetaHook
would be observed as the permanent revocation of the promise for the initialization of the module, poisoning any module that depends on it.Security Considerations
The
$h_import
internal should not be utterable by guest code except as a function call. Access to the function object should not be possible. It should be frozen by module-instance.js on the off-chance that it is accidentally exposed to guest code.The
$h_import_meta
object must be freezable by either the host or the guest. The design ofimportMetaHook
affords this possibility. I suspect that TC39 will want theimport.meta
to be mutable unless the host or guest elects to freeze it, but on this we should also get consensus from the Compartment Proposal champions and eventually reviewers.[from #303, May 11, 2020]:
Code running in a compartment needs access to a dynamic
import
expression that closes over the compartment’s module loader. This should presentimport.meta
according to whatever is returned by the compartment’simportMetaHook(specifier)
.*[original, from May 4, 2020]:
Currently, transform-module does introduce an
import
endowment (need to verify). There is a note in the code that we need to add a facility for hardening the import function. The existing code also arranges for animport.meta
andimport.meta.url
and we need to instead facilitate weaving animportMetaHook
through theCompartment
constructor options to make this behavior customizable.The text was updated successfully, but these errors were encountered: