Re: [whatwg/dom] Allow postMessage-ing AbortSignal (#948)

Just to clarify how I'd imagine this working, if `AbortSignal` were implemented in pure js I would imagine doing something like this.

I've added an explicit `synchronizeAborted` method to this example, rather than having `.aborted` do this implictly (previously I was thinking `.aborted` getter would trigger `.synchronizationSteps()`, but it adds work for code paths that don't need it).

```js
// Structured serialize steps
function serializeAbortSignal(abortSignal) {
  if (abortSignal.aborted) {
    return { type: "AbortSignal", aborted: true };
  } else {
    const messageChannel = new MessageChannel();
    abortSignal.addEventListener("abort", () => {
      // Update so aborted can be observed synchronously
      Atomics.store(sharedAbort, 0, 1));
      // And send it in case it's listening asynchronously
      messageChannel.port1.postMessage("aborted");
      messageChannel.port1.close();
    });
    const sharedAborted = new Uint8Array(new SharedArrayBuffer(1));
    return { 
      type: "AbortSignal", 
      aborted: false, 
      abortPort: messageChannel.port2,
      sharedAborted,
    };
  }
}

// Structured deserialize steps
function deserializeAbortSignal(serializedAbortSignal) {
  const abortSignal = new AbortSignal();
  
  if (serializedAbortSignal.aborted) {
    abortSignal.[[aborted]] = true;
    return abortSignal;
  }
  
  const { abortPort, sharedAborted } = serializedAbortSignal;
  // When a request to synchronize abort state with the main thread
  // happens we need to potentially fire "abort", and return 
  abortSignal.[[synchronizeSteps]] = () => {
    if (Atomics.load(sharedAborted, 0)) { // If aborted is set
      // Set the aborted flag synchronously
      abortSignal.[[aborted]] = true;
      // Fire the abort event and run any handlers synchronously
      abortSignal.dispatchEvent(new Event("abort"));
    }
  };
}

class AbortSignal extends EventTarget {
  [[aborted]] = false;
  [[synchronizeSteps]] = () => void;

  get aborted() {
    return this.[[aborted]];
  }
  
  // This asks the abort signal to synchronize with the other thread
  // by default the synchronize steps are to do nothing, this is the
  // case today and would remain the case when the abort signal does
  // not come from another thread
  synchronizeAborted() {
    if (this.[[aborted]]) {
      return true;
    }
    this.[[synchronizeSteps]]();
    return this.[[aborted]];
  }
}
```

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/948#issuecomment-787222182

Received on Sunday, 28 February 2021 02:33:12 UTC