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