SES 1.9.0 introduces immutable ArrayBuffer, exposes its console shim, and permits
a global ModuleSource in the shared intrinsics.
Immutable ArrayBuffer
JavaScript strings are immutable, but JavaScript lacks an immutable analog for
ArrayBuffer.
So, one can have a string of text and send it without making a copy to defend
its invariance, but not a string of bytes.
Agoric’s Mark Millerpresented a
proposal at the
October plenary meeting of the JavaScript standard committee, ECMA TC39.
The committee adopted Immutable Array Buffers into the body of problems under
consideration for a solution in a future standard, called “Stage 1”.
SES 1.9.0 is the first release to introduce an emulation of the proposed
immutable ArrayBuffer.
On platforms without
Array.prototype.transfer
but with a global structuredClone, the ses shim’s lockdown will now install
an emulation of Array.prototype.transfer.
On platforms with neither, ses will currently not install such an
emulation.
However, once we verify that ses is not intended to support platforms without
both, we may change lockdown to throw, failing to lock down.
XS and Node >= 22 already have Array.prototype.transfer.
Node 18, Node 20, and all browsers have structuredClone
Node <= 16 have neither, but are also no longer supported by ses.
Console Shim
The ses shim consists of mostly separable layers:
ses/assert-shim.js
ses/lockdown-shim.js
ses/compartment-shim.js
ses/console-shim.js
Version 1.9.0 is the first release to expose an entry point for
ses/console-shim.js so the user can choose whether to wrap and replace the
global console from the hardened JavaScript realm with a version that can
unredact error messages.
ModuleSource
Agoric champions a number of JavaScript standard proposals under the umbrellas
of Hardened JavaScript,
Compartments,
and a broad effort toward “Module Harmony”.
These include a proposal for a global ModuleSource that takes the source code
of a JavaScript module and prepares it for evaluation.
The package @endo/module-source provides an emulation of a ModuleSource
constructor suitable for use in combination with ses and Moddable’s
XS
provides a native implementation.
The module @endo/module-source/shim.js can install the emulated ModuleSource
in global scope so it becomes available as a shared intrinsic.
Version 1.9.0 adds ModuleSource to the shared intrinsics that lockdown will
repair if necessary and then harden, which consequently is available by default
in every new Compartment.
Agoric has released ses version
1.8.0 with more
implementation-specific options to Hardened JavaScript’s lockdown() function
to improve ecosystem compatibility.
Regenerator Runtime Compatibility
Old versions of some npm packages used
regenerator to anticipate
JavaScript’s async functions before language support was ubiquitous.
These rely on
regenerator-runtime to
approximate the language feature.
However, in the few cases where a dependency on versions 0.10.5 to 0.13.7 of
regenerator-runtime persist, applications are incompatible with ses due to
misalignment of the global objects the runtime introduces and the environment
that Hardened JavaScript expects from the base language.
With SES 1.8.0, lockdown accepts a new option
legacyRegeneratorRuntimeTaming: 'unsafe-ignore' that repairs the intrinsics
shared by all compartments so that lockdown will allow them.
This remediation is not strictly safe because it converts
Iterator.prototype[Symbol.iterator] to a getter and setter, such that all
assignments to it are ignored.
This could cause code to procede on false assumption that it successfully
overwrote the Iterator.prototype[Symbol.iterator] instead of throwing an
error.
Error Trapping: Report
Starting with SES 1.8.0, the 'report' mode for the errorTrapping option to
lockdown will write errors to standard error with the new
"SES_UNCAUGHT_EXCEPTION: " prefix.
The 'report' mode is sometimes implied by 'platform', 'exit', or 'abort'.
This is intended to give valuable context to users of the system, especially
when an uncaught exception is not an Error object, and therefore its origin
may be hard to find in source code.
This is not likely to affect most systems built with SES, as stderr is
generally reserved for user-only messages.
If your SES system sends its stderr to a program which parses it, you may need
to adapt that program to be tolerant of the SES_UNCAUGHT_EXCEPTION: prefix.
Even for such programs, it is unlikely they are that sensitive to stderr
formatting.
Agoric has released ses version
1.6.0 with changes that
improve compatibility with Moddable’s XS.
The version maintains backward-compatibility with existing usage and
some usage becomes deprecated, for which support will be removed in a future,
major version.
__options__
With this change, the Compartment constructor now has a preferred
single-argument form, which will become the only accepted form in a future,
major version.
Until then, Compartment accepts both the old and new signatures.
The deprecated form accepts three optional arguments:
The new form accepts a single options bag, and currently requires the
__options__ option to distinguish the global endowments from an options
object.
This is technically a breaking change, but we expect that it is vanishingly
rare for a compartment to be endowed with an __options__ global.
If such code exists, it will need to adopt the new form.
In a future, major version, the __options__ field will become vestigial and the
three-argument form will be an error.
__noNamespaceBox__
Likewise, the import method of compartments currently returns a promise
for an object with a namespace property, which is the namespace.
This differs from XS and the behavior of standard, dynamic import.
The import method should simply return a promise for the module namespace
object, just like dynamic import and XS.
Version 1.6.0 introduces a __noNamespaceBox__ option that makes the eventual
correct behavior available today.
This will become the only supported behavior in a future, major version.
Module descriptors
Version 1.6.0 increases module descriptor parity with XS.
Module descriptors appear in several places in the Compartment interface.
The modules option is an object that maps module specifiers to their
corresponding module descriptor.
These modules are “pre-loaded” at time of construction.
The moduleMapHook is a function that accepts a module specifier and may
return a module descriptor if import or importNow cannot complete without
it.
The importHookNowHook accepts a module specifier and may return a module
descriptor if importNow cannot complete without it.
The importHook accepts a module specifier and may return a module
descriptor or a promise for a module descriptor if import cannot complete
without it.
With version 1.6.0, module descriptors can take most of the forms accepted by XS
and code should begin migrating to prefer those forms.
Prior to version 1.6.0, a StaticModuleRecord, ModuleSource, virtual
static module record, or virtual module source could be used in place of
a module descriptor.
These should now be boxed in a module descriptor with a source property.
(Relatedly, we have renamed the @endo/static-module-record package to
@endo/module-source to better reflect the direction of movement in the
ECMAScript standardization process.)
Prior to version 1.6.0, a module namespace object could be used in place
of a module descriptor.
Particularly, the Compartment implementation included a module method
that could be used to acquire the module namespace object of a module that
has not yet been loaded, such that a module namespace could be used to link
compartments or settle cyclic dependencies.
This practice is deprecated now in favor of using a namespace module
descriptor.
Module descriptors with the source key will construct a fresh instance
of the source in this compartment.
Module descriptors with the namespace key will link to a module instance in
the designated compartment.
Prior to version 1.6.0, a module descriptor with record property
could be used to instantiate a module with a different import.meta.url than
the associated module specifier.
These descriptors should migrate to namespace module descriptors and
must explicitly designate the compartment property if they previously
relied on the default compartment.
The default compartment for namespace and source descriptors is the
“parent compartment”: the compartment for which Compartment is
the initial, intrinsic compartment.globalThis.Compartment.
The default compartment for record descriptors is child compartment.
Because you can otherwise only refer to a compartment with a reference
to that compartment, source and namespace descriptors that refer back to
their own compartment, instead of the default parent compartment, are not
expressible in the modules option and must move to a hook like
moduleMapHook, importHook, or importNowHook.
Support for the deprecated forms will be removed in a future, major version.
Line numbers
When running transpiled code on Node, the SES error taming
gives line-numbers into the generated JavaScript, which often don’t match the
the original lines. This happens even with the normal development-time
lockdown options setting,
or setting the environment variable
To get the original line numbers, this release
adds 'unsafe-debug'.
This errorTaming: 'unsafe-debug' setting should be used during development
only when you can sacrifice more security for a better debugging experience,
as explained at
errorTaming Options.
With this setting, when running transpiled code on Node (e.g. tests written in
TypeScript), the stacktrace line-numbers point back into the original source,
as they do on Node without SES.