# Scoped/Bound Eval

**URL:** <https://es.discourse.group/t/scoped-bound-eval/1752>\
**Category:** 💡 Ideas\
**Created:** [July 17, 2023, 8:09pm UTC](https://es.discourse.group/t/scoped-bound-eval/1752 "2023-07-17T20:09:29Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jithujoshyjy](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jithujoshyjy/32/399_2.png) [@jithujoshyjy](https://es.discourse.group/u/jithujoshyjy)\
**Post date:** [July 17, 2023, 8:09pm UTC](https://es.discourse.group/t/scoped-bound-eval/1752/1 "2023-07-17T20:09:29Z")

</div>

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.

```javascript
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:

```typescript
eval(scope, code)

```

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [July 17, 2023, 8:59pm UTC](https://es.discourse.group/t/scoped-bound-eval/1752/2 "2023-07-17T20:59:35Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [July 17, 2023, 9:08pm UTC](https://es.discourse.group/t/scoped-bound-eval/1752/3 "2023-07-17T21:08:25Z")

</div>

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

```javascript
function unsafeEvalWithScope(scope, code) {
  const f = new Function(...Object.keys(scope), `return (${code})`);
  return f(...Object.values(scope));
}

```

```javascript
unsafeEvalWithScope({ a: 1, b: 2 }, "a + b"); // 3

```

---

<div class="post-metadata">

**Author:** ![jithujoshyjy](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jithujoshyjy/32/399_2.png) [@jithujoshyjy](https://es.discourse.group/u/jithujoshyjy)\
**Post date:** [July 17, 2023, 9:26pm UTC](https://es.discourse.group/t/scoped-bound-eval/1752/4 "2023-07-17T21:26:09Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [July 17, 2023, 11:43pm UTC](https://es.discourse.group/t/scoped-bound-eval/1752/5 "2023-07-17T23:43:23Z")

</div>

No. It's more performant than `with`.

---

<div class="post-metadata">

**Author:** ![mhofman](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@mhofman](https://es.discourse.group/u/mhofman)\
**Post date:** [July 18, 2023, 1:08pm UTC](https://es.discourse.group/t/scoped-bound-eval/1752/6 "2023-07-18T13:08:07Z")

</div>

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](https://github.com/endojs/endo/blob/ea9c286ebda3bd71bb995aafd879d775fc055e34/packages/ses/src/make-evaluate.js#L92-L107) is used as part of the [SES shim](https://github.com/endojs/endo/tree/master/packages/ses). 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](https://github.com/tc39/proposal-compartments/blob/7e60fdbce66ef2d97370007afeb807192c653333/3-evaluator.md) building block, which is currently sitting as phase 3 of the [Module Harmony proposal](https://github.com/tc39/proposal-compartments) (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 [`harden`ing](https://github.com/endojs/endo/tree/master/packages/ses#harden) (recursively freezing) all intrinsics during [`lockdown`](https://github.com/endojs/endo/tree/master/packages/ses#lockdown).
