tc39 / proposal-shadowrealm

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

WrappedFunction.[[Call]] throw errors associated with callerRealm #330

Closed legendecas closed 2 years ago

legendecas commented 2 years ago

GetWrappedValue may throw TypeError when the value been wrapped is an object but not callable. WrappedFunctions may be called outside of the creation realm. This PR makes it clear that step GetWrappedValue in WrappedFunction.[[Call]] should throw a TypeError associated with the callerRealm but not the current realm.

WrappedFunction is the only place in the proposal spec that defines exotic [[Call]] and should clarify the throwing realm.

leobalter commented 2 years ago

Thanks, @legendecas!

Let me put this clear: I really appreciate the througout review you've been doing and the many PRs here. This PR is a bit confusing, I'm not sure it helps clarifying anything and I believe either the current draft or the proposed change from this PR will go through the editors review when we make the PR to ECMA-262.

Let's give a check with some other champions about this PR. cc @caridy @erights @rwaldron WDYT?

legendecas commented 2 years ago

@leobalter the item I'm trying to clarify is in which realm are the errors created in GetWrappedValue in WrappedFunction.[[Call]].

For example, in realmA:

const shadowRealm = new ShadowRealm()
const wrappedFunction = shadowRealm.eval('() => ({})')

Then we call the wrappedFunction in realmB:

wrappedFunction({}) // call the wrapped function with un-wrappable value
// => TypeError from realmA or realmB?

For function objects, the spec handles the call in following steps:

And at this step the javascript functions takes a different spec steps from the WrappedFunction. They should goes https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist:

But for WrappedFunction.[[Call]], there is only one such clarification on https://tc39.es/proposal-shadowrealm/#sec-wrapped-function-exotic-objects-call-thisargument-argumentslist: step 10.a. And for GetWrappedValue of steps 6.a and step 7, there is no such clarification for that. So the TypeError created on step 2.a of GetWrappedValue, I'd assume it is created in the realm of the current execution context, which can differ each time when the WrappedFunction is been called. However, if I understand correctly, this should not be the expected behavior since it acts like dynamic scoping.

rwaldron commented 2 years ago

I don't think the current specification is unclear at all.

Then we call the wrappedFunction in realmB:


wrappedFunction({}) // call the wrapped function with un-wrappable value

// => TypeError from realmA or realmB?

The validation of the arguments list occurs in the parent realm, not the child realm, which is what the current proposal spec describes at [[Call]] ( thisArgument, argumentsList ) Step 6.a.

// Realm A
const wrappedFunction = (new ShadowRealm()).eval(`
    // Realm B
    () => ({})
`);

// evaluation occurs in Realm A
wrappedFunction({}); // Throws a Realm A TypeError

After Step 8. Let result be the Completion Record of Call(target, wrappedThisArgument, wrappedArgs), the outcome of some operations executed in Realm B are stored in result, and if the completions are not "normal" or "return", then the exception must be attributed Realm B (step 10.a), because that's where it occurred.

legendecas commented 2 years ago

@rwaldron I'm afraid I'm not clear about the term realm references here.

For example, in realmA:

const shadowRealm = new ShadowRealm()
const wrappedFunction = shadowRealm.eval('() => ({})')

Then we call the wrappedFunction in realmB:

wrappedFunction({}) // call the wrapped function with un-wrappable value
// => TypeError from realmA or realmB?

The realms involving in these examples are:

So when the wrappedFunction is been called in realmB, an arbitrary realm, the TypeError for validation of argument list or validation of result in current spec is created in realmB. This is the topic I'm trying to clarify with the PR.

rwaldron commented 2 years ago

Ok, I see now. I apologize: I thought were were discussing strictly shadow realms interactions. In that case, your changes actually make complete sense!

leobalter commented 2 years ago

you're on roll, @legendecas, thank you!