Skip to content

Instantly share code, notes, and snippets.

@domenic
Last active August 29, 2015 14:08
Show Gist options
  • Save domenic/d421643d95cdec9a9b5b to your computer and use it in GitHub Desktop.
Save domenic/d421643d95cdec9a9b5b to your computer and use it in GitHub Desktop.
Readable stream locks proposal expanded

abstract operation: ReadFromReadableStream(stream) contains most of what we have now.

ReadableStreamLock class

Has a [[stream]] internal slot.

Present as an intrinsic named %ReadableStreamLock%.

new ReadableStreamLock(stream)

  • Brand-check that stream is a real ReadableStream.
  • If stream@[[locked]] is true, throw TypeError
  • Set this@[[stream]] to stream
  • Set stream@[[locked]] to true

ReadableStreamLock.prototype.read()

  • If this@[[stream]] is undefined, throw TypeError
  • Return ReadFromReadableStream(this.[[stream]])

ReadableStreamLock.prototype.release()

  • If this@[[stream]] is undefined, return.
  • Set this@[[stream]]@[[locked]] to false.
  • Set this@[[stream]] to undefined.

ReadableStream class modifications

new ReadableStream(...)

  • Set this@[[locked]] to false.

ReadableStream.prototype.read()

  • If this@[[locked]] is true, throw a TypeError.
  • Return ReadFromReadableStream(this).

ReadableStream.prototype.pipeTo(...)

  • Add var lock = new %ReadableStreamLock%(this)
  • Use lock.read() throughout instead of this.read()
  • One each branch that denotes a "finish" of the piping, i.e. each place that we fulfill or reject the return-value promise, call lock.release().
  • May need some try { ... } finally { ... }s.

[optionally add] get ReadableStream.prototype.isLocked

  • Return this@[[locked]].

Static %ReadableStreamLocks% "weak set" exists.

ReadableStreamLock class

Has a [[stream]] internal slot.

Present as an intrinsic named %ReadableStreamLock%.

new ReadableStreamLock(stream)

  • If %ReadableStreamLocks% has stream (the stream is already locked), throw TypeError
  • Set this@[[stream]] to stream
  • Add this@[[stream]] to %ReadableStreamLocks%

ReadableStreamLock.isLocked(stream)

  • Return true if %ReadableStreamLocks% has stream; false otherwise

ReadableStreamLock.prototype.read()

  • If this@[[stream]] is undefined, throw TypeError
  • Remove this@[[stream]] from %ReadableStreamLocks%
  • Execute the equivalent of:
try {
  return this@[[stream]].read();
} finally {
  // Add this@[[stream]] back to %ReadableStreamLocks%
}

ReadableStreamLock.prototype.release()

  • If this@[[stream]] is undefined, return.
  • Remove this@[[stream]] from %ReadableStreamLocks%.
  • Set this@[[stream]] to undefined.

ReadableStream class modifications

ReadableStream.prototype.read()

  • If %ReadableStreamLocks% has this, throw a TypeError.
  • ... rest of the existing algorithm goes here.

ReadableStream.prototype.pipeTo(...)

  • Add var lock = new %ReadableStreamLock%(this)
  • Use lock.read() throughout instead of this.read()
  • One each branch that denotes a "finish" of the piping, i.e. each place that we fulfill or reject the return-value promise, call lock.release().
  • May need some try { ... } finally { ... }s.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment