Open Bug 2085834 Opened 19 days ago Updated 4 days ago

With dom.promise.experimental_safe_resolve, a callback's returned thenable still has its "then" getter run synchronously

Categories

(Core :: DOM: Core & HTML, defect)

defect

Tracking

()

People

(Reporter: mgaudet, Unassigned)

References

Details

With dom.promise.experimental_safe_resolve enabled, Promise::MaybeResolve routes through JS::SafeResolve (bug 2033913), so the WebIDL "resolve" steps defer any user code (a then getter, a Proxy trap, or a call to then) to a microtask.

Minimal test case (Nightly, with dom.promise.experimental_safe_resolve set to true):

<script>
const reader = new ReadableStream({
  pull() { return { get then() { console.log("get then"); } }; }
}, { highWaterMark: 0 }).getReader();
setTimeout(() => {
  reader.read();
  console.log("read returned");
});
</script>

Expected: "read returned", then "get then".
Actual: "get then", then "read returned".

The conversion is hidden in the IDL type of pull. The Streams spec declares it as:

callback UnderlyingSourcePullCallback = Promise<undefined> (ReadableStreamController controller);
  1. reader.read() finds no queued chunk, so it calls the stream's pull algorithm. That algorithm invokes pull as a Web IDL callback function.
  2. The last step of Web IDL's "invoke a callback function" converts the JS return value to the callback's declared return type. Here that type is Promise<undefined>.
  3. Converting a JS value to Promise<T> creates a new promise and resolves it with the value. That resolve step reads value.then, so it runs the getter. whatwg/webidl#1645 changes this step to SafePromiseResolve, which defers the read.
    The bindings (Codegen.py) do that conversion with Promise::Resolve, which calls JS::CallOriginalPromiseResolve. That path never reaches MaybeSafeResolve, so the then getter on the returned value still runs synchronously.

The severity field is not set for this bug.
:zcorpan, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(zcorpan)
Severity: -- → S3
Flags: needinfo?(zcorpan)
You need to log in before you can comment on or make changes to this bug.