makeAtomicsTrapGuest = transferBuffer => {
  const { statusbuf, lenbuf, databuf } = splitTransferBuffer(transferBuffer);

  return ({ startTrap }) => {
    // Start by sending the trap call to the host.
    const it = startTrap();

    /** @type {Uint8Array | undefined} */
    let encoded;
    let i = 0;
    let done = false;
    while (!done) {
      // Tell that we are ready for another buffer.
      statusbuf[0] = STATUS_WAITING;
      const { done: itDone } = it.next();
      !itDone || Fail`Internal error; it.next() returned done=${itDone}`;

      // Wait for the host to wake us.
      Atomics.wait(statusbuf, 0, STATUS_WAITING);

      // Determine whether this is the last buffer.
      // eslint-disable-next-line no-bitwise
      done = (statusbuf[0] & STATUS_FLAG_DONE) !== 0;

      // Accumulate the encoded buffer.
      const remaining = Number(lenbuf[0]);
      const datalen = Math.min(remaining, databuf.byteLength);
      if (!encoded) {
        if (done) {
          // Special case: we are done on first try, so we don't need to copy
          // anything.
          encoded = databuf.subarray(0, datalen);
          break;
        }
        // Allocate our buffer for the remaining data.
        encoded = new Uint8Array(remaining);
      }

      // Copy the next buffer.
      encoded.set(databuf.subarray(0, datalen), i);
      i += datalen;
    }

    // This throw is harmless if the host iterator has already finished, and
    // if not finished, captp will correctly raise an error.
    //
    // TODO: It would be nice to use an error type, but captp is just too
    // noisy with spurious "Temporary logging of sent error" messages.
    // it.throw(makeError(X`Trap host has not finished`));
    it.throw(null);

    // eslint-disable-next-line no-bitwise
    const isReject = !!(statusbuf[0] & STATUS_FLAG_REJECT);

    // Decode the accumulated encoded buffer.
    const td = new TextDecoder('utf-8');
    const json = td.decode(encoded);

    // Parse the JSON data into marshalled form.
    const serialized = JSON.parse(json);
    return [isReject, serialized];
  };
}
Create a trapGuest that can be paired with makeAtomicsTrapHost.

This guest iterates through the consecutive slices of the JSON-encoded data,
then returns it.

@param {SharedArrayBuffer} transferBuffer
@returns {import('./types.js').TrapGuest}