Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WriteableStream support #9

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

YourFin
Copy link

@YourFin YourFin commented Jul 6, 2022

Description of the change

Clearly and concisely describe the purpose of the pull request. If this PR relates to an existing issue or change proposal, please link to it. Include any other background context that would help reviewers understand the motivation for this PR.


Adds support for the WriteableStream api

https://developer.mozilla.org/en-US/docs/Web/API/WritableStream

Checklist:

  • Added the change to the changelog's "Unreleased" section with a reference to this PR (e.g. "- Made a change (#0000)")
  • [ N/A ] Linked any existing issues or proposals that this pull request should close
  • [ N/A (?) ] Updated or added relevant documentation
  • [ N/A (?) ] Added a test for the contribution (if applicable)

@YourFin
Copy link
Author

YourFin commented Jul 6, 2022

Draft for now as I haven't had time to test this yet.

Comment on lines 28 to 31
foreign import _abort :: forall chunk. EffectFn2 (WriteableStream chunk) Error (Promise Unit)

abort :: forall chunk. WriteableStream chunk -> Error -> Effect (Promise Unit)
abort = runEffectFn2 _abort
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MDN disagrees with the spec on type that should be passed to abort; MDN claims that a string should be provided, but the spec is fine with any javascript value. I went with error as that seems to be the pattern elsewhere, but I don't have a strong opinion on what should end up here.

@YourFin YourFin force-pushed the master branch 2 times, most recently from c3c13a5 to ae0a869 Compare July 9, 2022 23:36
@JordanMartinez
Copy link
Contributor

We refer to the spec, not what MDN says. So, I'd do whatever https://streams.spec.whatwg.org/#ws-class says.


foreign import _new :: forall chunk. EffectFn2 (Sink chunk) (Nullable (QueuingStrategy chunk)) (WritableStream chunk)

new :: forall chunk. Sink chunk -> Maybe (QueuingStrategy chunk) -> Effect (WritableStream chunk)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's 4 different ways a WriteableStream can be constructed. Could you clarify why you only support one way?

Copy link
Author

@YourFin YourFin Jul 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Err I think I'm missing something here. As far as I can tell the constructor (MDN) has two options for arguments:

new WritableStream(underlyingSink)
new WritableStream(underlyingSink, queuingStrategy)

Which are covered by the Maybe on the second argument. I'm happy to cover more cases (or change the style here - right now I'm matching the ReadableStream implementation) but you'll have to point me to them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry. You support two ways to construct it via the Maybe arg.

To clarify, I'm looking at https://streams.spec.whatwg.org/#ws-class-definition:

constructor(optional object underlyingSink , optional QueuingStrategy strategy = {});

I presume that the following code would all create a WritableStream:

  • new WritableStream()
  • new WritableStream(sink)
  • new WritableStream(null, strategy)
  • new WritableStream(sink, strategy)


foreign import _abort :: forall chunk. EffectFn2 (WritableStream chunk) Error (Promise Unit)

abort :: forall chunk. WritableStream chunk -> Error -> Effect (Promise Unit)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abort has an optional reason. Could you add another variant where the reason is optional? For example abort has no reason requirement whereas abortErr does?


type Optional chunk =
( start :: WritableStreamController chunk -> Effect (Promise Unit)
, write :: WritableStreamController chunk -> chunk -> Effect (Promise Unit)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the chunk arg come before the controller arg?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to swap them, although I would like to know what style guide I'm missing the memo on so I can reference it in the future :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't recall the term used for it, but generally the "thing being operated on" is the last arg in a function. This allows one to use >=> to compose monadic functions (e.g. new sink strategy >=> write chunk >=> close)

The other reason is that the order done here write(stream, chunk) doesn't match the order used in the FFI / spec write(chunk, stream): https://streams.spec.whatwg.org/#underlying-sink-api

callback UnderlyingSinkWriteCallback = Promise (any chunk , WritableStreamDefaultController controller );

import Prelude (Unit)

foreign import data WritableStreamController :: Type -> Type

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the readonly attribute signal is missing here. If it's not added in this PR, we should open an issue tracking that.

Copy link
Author

@YourFin YourFin Jul 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my other comment on filling out the spec

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah; it appears that the returned AbortSignal type is currently defined in the web-fetch package, and it needs be moved to somewhere more centralized to avoid a circular dependency. A new "web-abort-signal" package seems somewhat overkill, but given its inclusion in the DOM standard rather than the fetch or stream standard I'm not sure what the best course of action would be. I'll leave this out of the next revision for now.

write = runEffectFn2 _write

foreign import ready :: forall chunk. Writer chunk -> Effect (Promise Unit)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

closed, desiredSize, abort, and releaseLock are all not implemented here. If you don't want to add those now, could you open an issue after this PR is merged to track that?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to add them; do we want to backfill the full spec on Reader too? I noticed that the implementation here is missing a few methods/properties.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean https://streams.spec.whatwg.org/#default-reader-class? Perhaps as a separate PR.

@YourFin
Copy link
Author

YourFin commented Jul 13, 2022

We refer to the spec, not what MDN says. So, I'd do whatever https://streams.spec.whatwg.org/#ws-class says.

Would you prefer Foreign to Error then?

@JordanMartinez
Copy link
Contributor

I'd prefer Error for the time being.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants