Skip to main content

script/dom/stream/
countqueuingstrategy.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use std::rc::Rc;
6
7use dom_struct::dom_struct;
8use js::jsapi::{CallArgs, JSContext};
9use js::jsval::{Int32Value, JSVal};
10use js::rust::HandleObject;
11use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
12
13use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
14use crate::dom::bindings::codegen::Bindings::QueuingStrategyBinding::{
15    CountQueuingStrategyMethods, QueuingStrategy, QueuingStrategyInit, QueuingStrategySize,
16};
17use crate::dom::bindings::error::{Error, Fallible};
18use crate::dom::bindings::reflector::DomGlobal;
19use crate::dom::bindings::root::DomRoot;
20use crate::dom::types::GlobalScope;
21use crate::script_runtime::CanGc;
22use crate::{native_fn, native_raw_obj_fn};
23
24#[dom_struct]
25pub(crate) struct CountQueuingStrategy {
26    reflector_: Reflector,
27    high_water_mark: f64,
28}
29
30impl CountQueuingStrategy {
31    pub(crate) fn new_inherited(init: f64) -> Self {
32        Self {
33            reflector_: Reflector::new(),
34            high_water_mark: init,
35        }
36    }
37
38    pub(crate) fn new(
39        global: &GlobalScope,
40        proto: Option<HandleObject>,
41        init: f64,
42        can_gc: CanGc,
43    ) -> DomRoot<Self> {
44        reflect_dom_object_with_proto(Box::new(Self::new_inherited(init)), global, proto, can_gc)
45    }
46}
47
48impl CountQueuingStrategyMethods<crate::DomTypeHolder> for CountQueuingStrategy {
49    /// <https://streams.spec.whatwg.org/#cqs-constructor>
50    fn Constructor(
51        global: &GlobalScope,
52        proto: Option<HandleObject>,
53        can_gc: CanGc,
54        init: &QueuingStrategyInit,
55    ) -> DomRoot<Self> {
56        Self::new(global, proto, init.highWaterMark, can_gc)
57    }
58
59    /// <https://streams.spec.whatwg.org/#cqs-high-water-mark>
60    fn HighWaterMark(&self) -> f64 {
61        self.high_water_mark
62    }
63
64    /// <https://streams.spec.whatwg.org/#cqs-size>
65    fn GetSize(&self, cx: &mut js::context::JSContext) -> Fallible<Rc<Function>> {
66        let global = self.global();
67        // Return this's relevant global object's count queuing strategy
68        // size function.
69        if let Some(fun) = global.get_count_queuing_strategy_size() {
70            return Ok(fun);
71        }
72
73        // Step 1. Let steps be the following steps, given chunk
74        // Note: See ByteLengthQueuingStrategySize instead.
75
76        // Step 2. Let F be !CreateBuiltinFunction(steps, 1, "size", « »,
77        // globalObject’s relevant Realm).
78        let fun = native_fn!(cx, count_queuing_strategy_size, c"size", 0, 0);
79        // Step 3. Set globalObject’s count queuing strategy size function to
80        // a Function that represents a reference to F,
81        // with callback context equal to globalObject’s relevant settings object.
82        global.set_count_queuing_strategy_size(fun.clone());
83        Ok(fun)
84    }
85}
86
87/// <https://streams.spec.whatwg.org/#count-queuing-strategy-size-function>
88pub(crate) fn count_queuing_strategy_size(
89    _cx: &mut js::context::JSContext,
90    args: CallArgs,
91) -> bool {
92    // Step 1.1. Return 1.
93    args.rval().set(Int32Value(1));
94    true
95}
96
97/// Extract the high water mark from a QueuingStrategy.
98/// If the high water mark is not set, return the default value.
99///
100/// <https://streams.spec.whatwg.org/#validate-and-normalize-high-water-mark>
101pub(crate) fn extract_high_water_mark(
102    strategy: &QueuingStrategy,
103    default_hwm: f64,
104) -> Result<f64, Error> {
105    if strategy.highWaterMark.is_none() {
106        return Ok(default_hwm);
107    }
108
109    let high_water_mark = strategy.highWaterMark.unwrap();
110    if high_water_mark.is_nan() || high_water_mark < 0.0 {
111        return Err(Error::Range(
112            c"High water mark must be a non-negative number.".to_owned(),
113        ));
114    }
115
116    Ok(high_water_mark)
117}
118
119/// Extract the size algorithm from a QueuingStrategy.
120/// If the size algorithm is not set, return a fallback function which always returns 1.
121///
122/// <https://streams.spec.whatwg.org/#make-size-algorithm-from-size-function>
123pub(crate) fn extract_size_algorithm(
124    strategy: &QueuingStrategy,
125    _can_gc: CanGc,
126) -> Rc<QueuingStrategySize> {
127    if strategy.size.is_none() {
128        let cx = GlobalScope::get_cx();
129        let fun_obj = native_raw_obj_fn!(cx, count_queuing_strategy_size, c"size", 0, 0);
130        #[expect(unsafe_code)]
131        unsafe {
132            return QueuingStrategySize::new(cx, fun_obj);
133        };
134    }
135    strategy.size.as_ref().unwrap().clone()
136}