Closed legendecas closed 3 years ago
This is good and makes a good distinction from the wrapped functions vs the instances of shadowrealm. Thanks!
@erights this doesn't look like dynamic scoping. I believe the change reflects what we are already doing today:
const srealm = new ShadowRealm();
const wrapped = srealm.evaluate('() => {}');
The wrapped
function is created outside of the srealm
. The value for srealm.[[Realm]]
internal is the Realm Record where wrapped was created and it is visible.
To what does the PR description's phrase
"or the current execution realm record will be returned instead, which can differ from the creation realm."
apply?
Let me expand the example using the spec steps creating the wrapped function:
const realm = new ShadowRealm();
const wrapped = realm.evaluate('x => x * 2');
realm.evaluate
will run the PerformShadowRealmEval
:
PerformShadowRealmEval ( sourceText, callerRealm, evalRealm )
callerRealm
is the realm where realm.evaluate
is called, evalRealm
is where the code inside the shadowRealm runs. We can roughly say that callerRealm
is the same value in realm.evaluate.[[Realm]]
.
This abstraction will see the evaluation completion is a callable (x => x *2
) and will wrap it with the following abstraction, and using the callerRealm
:
WrappedFunctionCreate ( _callerRealm_, _targetFunction_ )
Assert: _callerRealm_ is a Realm Record.
Assert: IsCallable(_targetFunction_) is *true*.
...
Let _obj_ be ! MakeBasicObject(_internalSlotsList_).
Set _obj_.[[Prototype]] to _callerRealm_.[[Intrinsics]].[[%Function.prototype%]].
Set _obj_.[[Call]] as described in <emu-xref href="#sec-wrapped-function-exotic-objects-call-thisargument-argumentslist"></emu-xref>.
Set _obj_.[[WrappedTargetFunction]] to _targetFunction_.
Set _obj_.[[Realm]] to _callerRealm_.
...
This abstraction will create the wrapped function exotic that has the exotic [[Call]] and targets the completion x => x * 2
as the value for wrapped.[[WrappedTargetFunction]]
.
The callerRealm
is set to the wrapped.[[Realm]]
, without touching the value of the wrapped.[[WrappedTargetFunction]].[[Realm]]
. They are always pointing to different Realm Records.
This PR is important otherwise the wrapped function might be a hazard with dynamic scoping, i.e. execution of Promises and thenables.
and it seems like the same pointed out by @mhofman. I believe we're all on the same page here.
This is good! We had that at some point, on my original spec.
It was removed in https://github.com/tc39/proposal-shadowrealm/commit/33017f50e3d889622881e8efa7b6add1fc28571a
I take the blame for removing [[Realm]] in an earlier iteration. I'll get this merged to end this issue.
GetFunctionRealm
in Step 4 of #sec-wrapped-function-exotic-objects-call-thisargument-argumentslist requires the function object to own an internal slot of [[Realm]] or the current execution realm record will be returned instead, which can differ from the creation realm.