Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 93 additions & 4 deletions components/script/dom/readablestreamdefaultcontroller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,38 @@ impl Callback for PullAlgorithmRejectionHandler {
}
}

/// The fulfillment handler for
/// <https://streams.spec.whatwg.org/#dom-underlyingsource-start>
#[derive(Clone, JSTraceable, MallocSizeOf)]
#[allow(crown::unrooted_must_root)]
struct StartAlgorithmFulfillmentHandler {
// TODO: check the validity of using Dom here.
controller: Dom<ReadableStreamDefaultController>,
}

impl Callback for StartAlgorithmFulfillmentHandler {
/// Handle fufillment of pull algo promise.
fn callback(&self, _cx: JSContext, _v: HandleValue, _realm: InRealm) {
todo!();
}
}

/// The rejection handler for
/// <https://streams.spec.whatwg.org/#dom-underlyingsource-start>
#[derive(Clone, JSTraceable, MallocSizeOf)]
#[allow(crown::unrooted_must_root)]
struct StartAlgorithmRejectionHandler {
// TODO: check the validity of using Dom here.
controller: Dom<ReadableStreamDefaultController>,
}

impl Callback for StartAlgorithmRejectionHandler {
/// Handle rejection of pull algo promise.
fn callback(&self, _cx: JSContext, _v: HandleValue, _realm: InRealm) {
todo!();
}
}

/// <https://streams.spec.whatwg.org/#value-with-size>
#[derive(JSTraceable)]
pub struct ValueWithSize {
Expand Down Expand Up @@ -172,9 +204,13 @@ pub struct ReadableStreamDefaultController {

/// <https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-closerequested>
close_requested: Cell<bool>,

/// <https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-started>
started: Cell<bool>,
}

impl ReadableStreamDefaultController {
/// <https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller>
fn new_inherited(
global: &GlobalScope,
underlying_source_type: UnderlyingSourceType,
Expand All @@ -192,6 +228,8 @@ impl ReadableStreamDefaultController {
strategy_hwm,
strategy_size: RefCell::new(Some(strategy_size)),
close_requested: Default::default(),
// TODO: set to true when start algo promise resolves.
started: Default::default(),
}
}
pub fn new(
Expand All @@ -200,15 +238,38 @@ impl ReadableStreamDefaultController {
strategy_hwm: f64,
strategy_size: Rc<QueuingStrategySize>,
) -> DomRoot<ReadableStreamDefaultController> {
reflect_dom_object(
let rooted_default_controller = reflect_dom_object(
Box::new(ReadableStreamDefaultController::new_inherited(
global,
underlying_source,
strategy_hwm,
strategy_size,
)),
global,
)
);

if let Some(underlying_source) = rooted_default_controller.underlying_source.get() {
let promise = underlying_source.call_start_algorithm(
Controller::ReadableStreamDefaultController(rooted_default_controller.clone()),
);
let fulfillment_handler = Box::new(StartAlgorithmFulfillmentHandler {
controller: Dom::from_ref(&*rooted_default_controller),
});
let rejection_handler = Box::new(StartAlgorithmRejectionHandler {
controller: Dom::from_ref(&*rooted_default_controller),
});
Comment on lines +255 to +260
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There are some stuff need to do upon fulfillment and rejection.Do they go to the todo!() in Callback trait implementations?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yes.

let handler = PromiseNativeHandler::new(
&global,
Some(fulfillment_handler),
Some(rejection_handler),
);

let realm = enter_realm(&*global);
let comp = InRealm::Entered(&realm);
promise.append_native_handler(&handler, comp);
};

rooted_default_controller
}

pub fn set_stream(&self, stream: &ReadableStream) {
Expand All @@ -223,8 +284,36 @@ impl ReadableStreamDefaultController {

/// <https://streams.spec.whatwg.org/#readable-stream-default-controller-should-call-pull>
fn should_pull(&self) -> bool {
// TODO: implement the algo.
true
let stream = self
.stream
.get()
.expect("Controller must have a stream when the should pull algo is called into.");

// If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) is false, return.
if !self.can_close_or_enqueue() {
return false;
}

// If controller.[[started]] is false, return false.
if !self.started.get() {
return false;
}

// If ! IsReadableStreamLocked(stream) is true
// and ! ReadableStreamGetNumReadRequests(stream) > 0, return true.
if stream.is_locked() && stream.get_num_read_requests() > 0 {
return true;
}

// Let desiredSize be ! ReadableStreamDefaultControllerGetDesiredSize(controller).
// Assert: desiredSize is not null.
let desired_size = self.get_desired_size().expect("desiredSize is not null.");

if desired_size > 0. {
return true;
}

false
}

/// <https://streams.spec.whatwg.org/#readable-stream-default-controller-call-pull-if-needed>
Expand Down
53 changes: 52 additions & 1 deletion components/script/dom/underlyingsourcecontainer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use std::ptr;
use std::rc::Rc;

use dom_struct::dom_struct;
use js::jsapi::JSObject;
use js::jsapi::{IsPromiseObject, JSObject};
use js::jsval::UndefinedValue;
use js::rust::IntoHandle;

use crate::dom::bindings::callback::ExceptionHandling;
use crate::dom::bindings::codegen::Bindings::UnderlyingSourceBinding::UnderlyingSource as JsUnderlyingSource;
Expand Down Expand Up @@ -111,6 +112,56 @@ impl UnderlyingSourceContainer {
None
}

/// <https://streams.spec.whatwg.org/#dom-underlyingsource-start>
///
/// Note: The algorithm can return any value, including a promise,
/// we always transform the result into a promise for convenience,
/// and it is also how to spec deals with the situation.
/// see "Let startPromise be a promise resolved with startResult."
/// at <https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller>
#[allow(unsafe_code)]
pub fn call_start_algorithm(&self, controller: Controller) -> Rc<Promise> {
if let UnderlyingSourceType::Js(source) = &self.underlying_source_type {
let global = self.global();
let promise = if let Some(start) = &source.start {
let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut this_object = ptr::null_mut::<JSObject>());
unsafe {
source.to_jsobject(*cx, this_object.handle_mut());
}
let this_handle = this_object.handle();
rooted!(in(*cx) let mut result_object = ptr::null_mut::<JSObject>());
let result = start
.Call_(&this_handle, controller, ExceptionHandling::Report)
.expect("Start algorithm call failed");
let is_promise = unsafe {
result_object.set(result.to_object());
IsPromiseObject(result_object.handle().into_handle())
};
// Let startPromise be a promise resolved with startResult.
if is_promise {
let promise = Promise::new_with_js_promise(result_object.handle(), cx);
promise
} else {
let promise = Promise::new(&*global);
promise.resolve_native(&result);
promise
}
} else {
let promise = Promise::new(&*global);
promise.resolve_native(&());
promise
};
promise
} else {
// Native sources start immediately.
let global = self.global();
let promise = Promise::new(&*global);
promise.resolve_native(&());
promise
}
}

/// Does the source have all data in memory?
pub fn in_memory(&self) -> bool {
self.underlying_source_type.in_memory()
Expand Down