Skip to content

An experiment with defining and using a SafeResolve operation #7

@mgaudet

Description

@mgaudet

Here's an exploration .

Add a new operation SafeResolvePromise(p, val) defined as follows (this isn’t spec language, but should be followable; in specification this would be an alternative [[Resolve]] internal slot for a promise capability)

SafeResolvePromise(p, resolutionVal): 
  if RequiresDefer(resolutionVal):
    job = new DeferJob(promise, resolutionVal)
    HostEnqueuePromiseJob(job, job.realm());
    return

  FulfillPromise(promise, resolution)
  return

RequiresDefer(resolutionVal): 
  // Traps could run
  if IsProxy(resolutionVal):
    return true

  if HasThenProperty(resolutionVal):
    return true

  if HasGetterConstructor(resolutionVal):
    return true

  return false

Basically, if a resolution value could be expected to run script, rather than running the script synchronously, enqueue a job in the microtask queue to do resolution, potentially running script, in a future microtask.

Experiment: WebIDL

Q: Can we use SafeResolve to replace the promise resolution steps in WebIDL?

Experiment (slightly more broad): Run WPT with the Firefox DOM Promise resolve steps replaced with SafeResolve.

Results:

The vast majority of tests (as expected) pass.

Timeout Failures:

  1. /css/css-overflow/scroll-marker-in-display-none-column-crash.html This is the only test where I'm not entirely sure what's going on.
  2. /custom-elements/when-defined-reentry-crash.html -- this one is using a then on Object.prototype for nefarious aims. In a sense this is exactly the kind of issue we’re trying to address. https://issues.chromium.org/issues/40061097

Unexpected Pass:

  1. /fetch/api/response/response-body-read-task-handling.html - This test is using then to get insight into execution order. The test no longer tests what it thinks it is testing anymore; however the test -also- was created to address this kind of thennable issue.

Test Failures

  1. /streams/readable-byte-streams/patched-global.any.js -- Explicitly using then to peek into execution state we’d probably prefer to not be observable.
  2. /document-picture-in-picture/returns-window-with-document.https.html | requestWindow timing - assert\_equals: Got the expected order of actions expected "requestWindow,microtask,enter" but got "microtask,requestWindow,enter" -- The job timing changes because it’s resolving a promise with a window (WindowProxy) object, which causes an extra tick.
  3. /web-animations/interfaces/Animation/cancel.html; observing event timing with thenable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions