/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom_struct::dom_struct; use js::gc::CustomAutoRooterGuard; use js::typedarray::{ArrayBufferView, ArrayBufferViewU8}; use super::bindings::buffer_source::HeapBufferSource; use super::bindings::cell::DomRefCell; use super::bindings::reflector::reflect_dom_object; use super::bindings::root::DomRoot; use crate::dom::bindings::codegen::Bindings::ReadableStreamBYOBRequestBinding::ReadableStreamBYOBRequestMethods; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::reflector::Reflector; use crate::dom::bindings::root::MutNullableDom; use crate::dom::readablebytestreamcontroller::ReadableByteStreamController; use crate::dom::types::GlobalScope; use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; /// #[dom_struct] pub(crate) struct ReadableStreamBYOBRequest { reflector_: Reflector, controller: MutNullableDom, #[ignore_malloc_size_of = "mozjs"] view: DomRefCell>, } impl ReadableStreamBYOBRequest { fn new_inherited() -> ReadableStreamBYOBRequest { ReadableStreamBYOBRequest { reflector_: Reflector::new(), controller: MutNullableDom::new(None), view: DomRefCell::new(HeapBufferSource::::default()), } } pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot { reflect_dom_object(Box::new(Self::new_inherited()), global, can_gc) } pub(crate) fn set_controller(&self, controller: Option<&ReadableByteStreamController>) { self.controller.set(controller); } pub(crate) fn set_view(&self, view: Option>) { match view { Some(view) => { *self.view.borrow_mut() = view; }, None => { *self.view.borrow_mut() = HeapBufferSource::::default(); }, } } } impl ReadableStreamBYOBRequestMethods for ReadableStreamBYOBRequest { /// fn GetView(&self, _cx: SafeJSContext) -> Option { // Return this.[[view]]. self.view.borrow().typed_array_to_option() } /// fn Respond(&self, bytes_written: u64, can_gc: CanGc) -> Fallible<()> { let cx = GlobalScope::get_cx(); // If this.[[controller]] is undefined, throw a TypeError exception. let controller = if let Some(controller) = self.controller.get() { controller } else { return Err(Error::Type("controller is undefined".to_owned())); }; { let view = self.view.borrow(); // If ! IsDetachedBuffer(this.[[view]].[[ArrayBuffer]]) is true, throw a TypeError exception. if view.get_array_buffer_view_buffer(cx).is_detached_buffer(cx) { return Err(Error::Type("buffer is detached".to_owned())); } // Assert: this.[[view]].[[ByteLength]] > 0. assert!(view.byte_length() > 0); // Assert: this.[[view]].[[ViewedArrayBuffer]].[[ByteLength]] > 0. assert!(view.viewed_buffer_array_byte_length(cx) > 0); } // Perform ? ReadableByteStreamControllerRespond(this.[[controller]], bytesWritten). controller.respond(cx, bytes_written, can_gc) } /// fn RespondWithNewView( &self, view: CustomAutoRooterGuard, can_gc: CanGc, ) -> Fallible<()> { let cx = GlobalScope::get_cx(); let view = HeapBufferSource::::from_view(view); // If this.[[controller]] is undefined, throw a TypeError exception. let controller = if let Some(controller) = self.controller.get() { controller } else { return Err(Error::Type("controller is undefined".to_owned())); }; // If ! IsDetachedBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception. if view.is_detached_buffer(cx) { return Err(Error::Type("buffer is detached".to_owned())); } // Return ? ReadableByteStreamControllerRespondWithNewView(this.[[controller]], view). controller.respond_with_new_view(cx, view, can_gc) } }