ReadableStreamDefaultController.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/SafeFunction.h>
  7. #include <LibWeb/Bindings/Intrinsics.h>
  8. #include <LibWeb/Bindings/ReadableStreamDefaultControllerPrototype.h>
  9. #include <LibWeb/Streams/AbstractOperations.h>
  10. #include <LibWeb/Streams/ReadableStream.h>
  11. #include <LibWeb/Streams/ReadableStreamDefaultController.h>
  12. #include <LibWeb/Streams/ReadableStreamDefaultReader.h>
  13. #include <LibWeb/WebIDL/ExceptionOr.h>
  14. #include <LibWeb/WebIDL/Promise.h>
  15. namespace Web::Streams {
  16. JS_DEFINE_ALLOCATOR(ReadableStreamDefaultController);
  17. ReadableStreamDefaultController::ReadableStreamDefaultController(JS::Realm& realm)
  18. : Bindings::PlatformObject(realm)
  19. {
  20. }
  21. // https://streams.spec.whatwg.org/#rs-default-controller-desired-size
  22. Optional<double> ReadableStreamDefaultController::desired_size()
  23. {
  24. // 1. Return ! ReadableStreamDefaultControllerGetDesiredSize(this).
  25. return readable_stream_default_controller_get_desired_size(*this);
  26. }
  27. // https://streams.spec.whatwg.org/#rs-default-controller-close
  28. WebIDL::ExceptionOr<void> ReadableStreamDefaultController::close()
  29. {
  30. // 1. If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(this) is false, throw a TypeError exception.
  31. if (!readable_stream_default_controller_can_close_or_enqueue(*this)) {
  32. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Stream is not closable"sv };
  33. }
  34. // 2. Perform ! ReadableStreamDefaultControllerClose(this).
  35. readable_stream_default_controller_close(*this);
  36. return {};
  37. }
  38. // https://streams.spec.whatwg.org/#rs-default-controller-enqueue
  39. WebIDL::ExceptionOr<void> ReadableStreamDefaultController::enqueue(JS::Value chunk)
  40. {
  41. // 1. If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(this) is false, throw a TypeError exception.
  42. if (!readable_stream_default_controller_can_close_or_enqueue(*this))
  43. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot enqueue chunk to stream"sv };
  44. // 2. Perform ? ReadableStreamDefaultControllerEnqueue(this, chunk).
  45. TRY(readable_stream_default_controller_enqueue(*this, chunk));
  46. return {};
  47. }
  48. // https://streams.spec.whatwg.org/#rs-default-controller-error
  49. void ReadableStreamDefaultController::error(JS::Value error)
  50. {
  51. // 1. Perform ! ReadableStreamDefaultControllerError(this, e).
  52. readable_stream_default_controller_error(*this, error);
  53. }
  54. // https://streams.spec.whatwg.org/#rs-default-controller-private-cancel
  55. WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> ReadableStreamDefaultController::cancel_steps(JS::Value reason)
  56. {
  57. // 1. Perform ! ResetQueue(this).
  58. reset_queue(*this);
  59. // 2. Let result be the result of performing this.[[cancelAlgorithm]], passing reason.
  60. auto result = cancel_algorithm()->function()(reason);
  61. // 3. Perform ! ReadableStreamDefaultControllerClearAlgorithms(this).
  62. readable_stream_default_controller_clear_algorithms(*this);
  63. // 4. Return result.
  64. return result;
  65. }
  66. // https://streams.spec.whatwg.org/#rs-default-controller-private-pull
  67. WebIDL::ExceptionOr<void> ReadableStreamDefaultController::pull_steps(Web::Streams::ReadRequest& read_request)
  68. {
  69. // 1. Let stream be this.[[stream]].
  70. auto& stream = *m_stream;
  71. // 2. If this.[[queue]] is not empty,
  72. if (!m_queue.is_empty()) {
  73. // 1. Let chunk be ! DequeueValue(this).
  74. auto chunk = dequeue_value(*this);
  75. // 2. If this.[[closeRequested]] is true and this.[[queue]] is empty,
  76. if (m_close_requested && m_queue.is_empty()) {
  77. // 1. Perform ! ReadableStreamDefaultControllerClearAlgorithms(this).
  78. readable_stream_default_controller_clear_algorithms(*this);
  79. // 2. Perform ! ReadableStreamClose(stream).
  80. readable_stream_close(stream);
  81. }
  82. // 3. Otherwise, perform ! ReadableStreamDefaultControllerCallPullIfNeeded(this).
  83. else {
  84. TRY(readable_stream_default_controller_can_pull_if_needed(*this));
  85. }
  86. // 4. Perform readRequest’s chunk steps, given chunk.
  87. read_request.on_chunk(chunk);
  88. }
  89. // 3. Otherwise,
  90. else {
  91. // 1. Perform ! ReadableStreamAddReadRequest(stream, readRequest).
  92. readable_stream_add_read_request(stream, read_request);
  93. // 2. Perform ! ReadableStreamDefaultControllerCallPullIfNeeded(this).
  94. TRY(readable_stream_default_controller_can_pull_if_needed(*this));
  95. }
  96. return {};
  97. }
  98. // https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultcontroller-releasesteps
  99. WebIDL::ExceptionOr<void> ReadableStreamDefaultController::release_steps()
  100. {
  101. // 1. Return.
  102. return {};
  103. }
  104. void ReadableStreamDefaultController::initialize(JS::Realm& realm)
  105. {
  106. Base::initialize(realm);
  107. WEB_SET_PROTOTYPE_FOR_INTERFACE(ReadableStreamDefaultController);
  108. }
  109. void ReadableStreamDefaultController::visit_edges(Cell::Visitor& visitor)
  110. {
  111. Base::visit_edges(visitor);
  112. for (auto const& item : m_queue)
  113. visitor.visit(item.value);
  114. visitor.visit(m_stream);
  115. visitor.visit(m_cancel_algorithm);
  116. visitor.visit(m_pull_algorithm);
  117. visitor.visit(m_strategy_size_algorithm);
  118. }
  119. }