tc39 / proposal-shadowrealm

ECMAScript Proposal, specs, and reference implementation for Realms
https://tc39.es/proposal-shadowrealm/
1.41k stars 67 forks source link

ScriptEvaluation semantics for ShadowRealm #379

Open mhofman opened 1 year ago

mhofman commented 1 year ago

It looks like PerformShadowRealmEval is based off PerformEval, which means there is no way to have the ScriptEvaluation semantics in ShadowRealms, namely the behavior of GlobalDeclarationInstantiation to create global object properties for var and function declarations.

I'm wondering if this option was ever discussed. While it'd be easy to add a new API later (e.g. ShadowRealm.prototype.executeScript()) with the ScriptEvaluation semantics, I also don't think there'd be harm in changing the semantics of PerformShadowRealmEval before shipping. It's always possible to go from ScriptEvaluation to PerformEval (const evaluate = shadowRealm.executeScript('eval')), but not the other way around.

caridy commented 5 months ago

Let's discuss this next week at SES meeting. @erights and @nicolo-ribaudo might have opinions here as well.

ptomato commented 5 months ago

Tomorrow's there is no SES meeting due to TG3. I've put it on the agenda for 2024-02-21.

nicolo-ribaudo commented 4 months ago

We discussed this during today's SES meeting -- we didn't come to a conclusion, but there were to points in favor of the two different options.

To recap, the observable difference is that realm.evaluate("var foo = 1") would create a global configurable property under PerformEval semantics, and a global non-configurable property under ScriptEvaluation semantics.

In addition to this, @mhofman notes that const evaluate = shadowRealm.executeScript('eval') doesn't actually work when considering TrustedTypes, because that eval would be behind the callable boundary and thus it can only accept strings (while shadowRealm.executeScript(trustedTypesObject) would work).

nicolo-ribaudo commented 4 months ago

Also, I realized that there is another difference we didn't explicitly talk about during the SES meeting (but maybe it's a consequence of the configurability of properties). The following code:

realm.evaluate("var a = 1");
realm.evaluate("let a = 2");

will work under PerformEval semantics, and throw under ScriptEvaluation semantics.

Test cases:

<!-- ScriptEvaluation -->
<script>var a = 1;</script>
<script>let a = 2;</script>
<!-- PerformEval -->
<script>
  eval("var a = 1;");
  eval("let a = 1;");
</script>