Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

maybe replace 'harden' import with a global #1214

Closed
warner opened this issue Jun 26, 2020 · 5 comments
Closed

maybe replace 'harden' import with a global #1214

warner opened this issue Jun 26, 2020 · 5 comments
Assignees
Labels
SwingSet package: SwingSet

Comments

@warner
Copy link
Member

warner commented Jun 26, 2020

Swingset's controller.js and kernel.js both contain functions that look somewhat like:

  function kernelRequire(what) {
    if (what === '@agoric/harden') {
      return harden;
    } else {
      throw Error(`cannot require${what}`);
    }
  }

which are provided to the kernel and to vats (respectively) as a require endowment. While reviewing #1201, @FUDCo said:

I understand this is to avoid having to change a bunch of existing code.
I hate this kind of thing, I'll volunteer to do the refactor when the new SES stuff stabilizes.

You rock!

We need to have a group decision about what SES/vat/contract code can expect on the global, what it gets by import, and what it gets by argument. And how that affects the developer experience (i.e. if you get harden as a global, your library cannot be imported by applications which aren't using SES, which might be a pain point and reduce the audience for your library, or maybe it's no big deal). But assuming we decide to go with the global, then yeah, the task is to delete the import from everything (agoric-sdk and all the dapp repos), remove it from the externals configuration in bundle-source, then remove the @agoric/harden clause from the kernelRequire and vatRequire lines. And then (probably) remove the require endowments entirely.

But, maybe, leave it in just for the purpose of revealing (in an error) the leftover unbound package name which the bundle depended upon. I was talking to @michaelfig about this today: if a contract imports some random NPM library, and that library's dependency graph happens to be well-behaved and doesn't use any Node.js builtins, then rollup will be able to find source code for everything, and the bundle will have no remaining require statements. But if something (maybe several levels deep) is not so well-behaved, rollup will be faced with some import 'fs' or import 'http' somewhere, and currently rollup emits a warning and then includes a require('fs') anyways. When that bundle finally meets importBundle, then either the require will fail (ReferenceError, or maybe "TypeError: undefined is not a function"), or the kernelRequire will fail ("cannot satisfy require('fs')"), and the latter is slightly more informative. But, what would be even better is if bundle-source rejected it in the first place, and showed the full dependency chain that resulted in attempting to bundle an unbundleable native module, so the contract author could either say "oh bummer, I can't use that library", or "oh hey I'll go bug the author of the not-so-well-behaved module to tame it nicely so I can use it from a SES-confined environment".

Originally posted by @warner in #1201

@warner
Copy link
Member Author

warner commented Jun 29, 2020

As discussed in the meeting this morning, harden is special: it is part of the SES specification. The future version of JavaScript that we're providing will include harden as a global, not a special import. So relying upon it as a global in our vat/contract environments is fine, as is removing all those import statements.

We'll separate the question of whether to remove the ability to do the import for later. The task of removing imports can proceed incrementally, one module at a time. When we've finally removed them all, then we can decide whether to get rid of vatRequire's support for @agoric/harden. We can remove kernelRequire's support much earlier, once we've removed all the imports from SwingSet/src/kernel/, because that's an internal interface.

@michaelfig
Copy link
Member

As a tangent, I would eventually like something I'd call @agoric/shim, which may be as simple as:

// Modify globals to closer emulate our desired EcmaScript future.
import './harden-shim'; // if harden is missing, complain and use Object.freeze
import './eventual-send-shim'; // Add Promise.delegate (currently HandledPromise)
import './compartment-shim'; // Add Compartment

I want to use this to shim and future-proof library code I intend to write.

@warner
Copy link
Member Author

warner commented Jul 20, 2020

As of the current trunk (4fe3c83), we're down to one import of @agoric/harden:

// Fake version of `harden` so agoric-cli can load both SES-demanding and
// SES-incompatible modules until we get around to doing without the latter.
import rawHarden from '@agoric/harden';
globalThis.harden = rawHarden;

That's @michaelfig 's domain, and I don't think it's involved in vat/contract code. So I think we can consider this ticket closable without removing that one.

We've removed harden from both the externals retained by bundle-source:

externals = [],
} = powers || {};
const resolvedPath = pathResolve(startFilename);
const bundle = await rollup({
input: resolvedPath,
treeshake: false,
preserveModules: moduleFormat === 'nestedEvaluate',
external: [...externals],

and the require provided to static and dynamic vats:

function vatRequire(what) {
throw Error(`vatRequire unprepared to satisfy require(${what})`);
}

But we still want to remove it from the names honored by the require() provided to the kernel bundle:

function kernelRequire(what) {
if (what === '@agoric/harden') {
return harden;
} else if (what === 're2') {

And then, since #362 is closed, I think we can remove support for require in static/dynamic/kernel bundles entirely.

@warner
Copy link
Member Author

warner commented Jul 20, 2020

oops, #362 isn't really done yet, I can remove the kernelRequire clause for @agoric/harden, but I can't remove the require endowments yet

warner added a commit that referenced this issue Jul 22, 2020
The kernel now gets `harden` from the globals, so we no longer need to
support it doing `require('@agoric/haren')`.

refs #1214
warner added a commit that referenced this issue Jul 22, 2020
Vats no longer get `harden` via require, and they aren't allowed to `require`
anything else either, so this removes the endowment entirely.

refs #1214
@warner
Copy link
Member Author

warner commented Jul 22, 2020

#362 is fixed, I'll make a PR to remove require from vatEndowments and kernelEndowments.

@warner warner closed this as completed in 446510f Jul 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
SwingSet package: SwingSet
Projects
None yet
Development

No branches or pull requests

3 participants