web-streams.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. /* eslint-env browser */
  2. import { parseChunked } from './parse-chunked.js';
  3. import { stringifyChunked } from './stringify-chunked.js';
  4. import { isIterable } from './utils.js';
  5. export function parseFromWebStream(stream) {
  6. // 2024/6/17: currently, an @@asyncIterator on a ReadableStream is not widely supported,
  7. // therefore use a fallback using a reader
  8. // https://caniuse.com/mdn-api_readablestream_--asynciterator
  9. return parseChunked(isIterable(stream) ? stream : async function*() {
  10. const reader = stream.getReader();
  11. try {
  12. while (true) {
  13. const { value, done } = await reader.read();
  14. if (done) {
  15. break;
  16. }
  17. yield value;
  18. }
  19. } finally {
  20. reader.releaseLock();
  21. }
  22. });
  23. }
  24. export function createStringifyWebStream(value, replacer, space) {
  25. // 2024/6/17: the ReadableStream.from() static method is supported
  26. // in Node.js 20.6+ and Firefox only
  27. if (typeof ReadableStream.from === 'function') {
  28. return ReadableStream.from(stringifyChunked(value, replacer, space));
  29. }
  30. // emulate ReadableStream.from()
  31. return new ReadableStream({
  32. start() {
  33. this.generator = stringifyChunked(value, replacer, space);
  34. },
  35. pull(controller) {
  36. const { value, done } = this.generator.next();
  37. if (done) {
  38. controller.close();
  39. } else {
  40. controller.enqueue(value);
  41. }
  42. },
  43. cancel() {
  44. this.generator = null;
  45. }
  46. });
  47. };