Scoped/Bound Eval

Whenever I legitimately want to use eval() for simplifying something it always becomes a bit of security hazard and a huge pain to deal with. I have found a workaround to somewhat scope/bind eval() to an object but it also has a catch in that it uses the deprecated with() { } statement.

function scopedEval(scope, code) {
    return function() { with(this) { return eval(code) } }.call(scope)

I'm sure that most of us want a proper solution to this issue; one that actually work in strict-mode. If scoped/bound eval() becomes a thing, then it could greatly help library authors with DI and DSLs.
If overloading existing eval is possible, then I expect it to look something along the lines:

eval(scope, code)

GitHub - tc39/proposal-shadowrealm: ECMAScript Proposal, specs, and reference implementation for Realms provides an evaluate API that is scoped to a separate realm isolated by its "callable boundary".

For a simple unsafe eval with scope one approach is to use the Function constructor:

function unsafeEvalWithScope(scope, code) {
  const f = new Function(...Object.keys(scope), `return (${code})`);
  return f(...Object.values(scope));
unsafeEvalWithScope({ a: 1, b: 2 }, "a + b"); // 3

That works too; Is it anymore performant than eval()?

No. It's more performant than with.

Please note that the Function example using parameters to create scope bindings is not equivalent to the eval + with example, depending on the behavior of the scope object:

If your goal is to provide some kind of confinement, then you usually want to prevent the evaluated code to reach the global scope. That can only be accomplished with with and a scope object exhibiting exotic behavior of claiming it has all keys.

If confinement is not you goal (or you can somehow statically analyze all bindings uttered in evaluated code), then an approach similar to the Function constructor is to generate code for let and const statement to create these bindings, in which case you do not need the with anymore when using eval.

Btw, the with + direct eval trick is used as part of the SES shim. The goal is to ultimately standardize something like Compartments, which allow you to load modules and evaluate code in a new global scope but sharing the same underlying Realm (lighter weight than ShadowRealm, without a callable boundary requiring membranes). Compartments may remain a user-land API if we can standardize the Evaluators building block, which is currently sitting as phase 3 of the Module Harmony proposal (formerly Compartments proposal).

In order to justify adding such scoped Evaluators to the language, we would appreciate if you could share any use cases you may have. Some delegates are not convinced that JS should add more ways to evaluate code, and some are not convinced about the need to evaluate in different global scopes.

Finally, if you evaluate untrusted code in such compartmentalized evaluators, be mindful that such code can reach and potentially mutate the intrinsics of the realm, like the shared object prototype. If you want to ensure the integrity of your realm, you need to freeze all intrinsics. In SES / Hardened JS this is accomplished by hardening (recursively freezing) all intrinsics during lockdown.