Skip to content

Commit eb54a96

Browse files
wusyongpewsheen
andauthored
Add QueuingStrategy and UnderlyingSource (servo#32572)
--------- Co-authored-by: Jason Tsai <[email protected]>
1 parent 256c55e commit eb54a96

15 files changed

+608
-7
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
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+
5+
use std::ffi::c_char;
6+
use std::rc::Rc;
7+
8+
use dom_struct::dom_struct;
9+
use js::gc::{HandleValue, MutableHandleValue};
10+
use js::jsapi::{CallArgs, JSContext, JS_GetFunctionObject, JS_NewFunction};
11+
use js::jsval::JSVal;
12+
use js::rust::HandleObject;
13+
14+
use super::bindings::codegen::Bindings::FunctionBinding::Function;
15+
use super::bindings::codegen::Bindings::QueuingStrategyBinding::{
16+
ByteLengthQueuingStrategyMethods, QueuingStrategyInit,
17+
};
18+
use super::bindings::import::module::{
19+
get_dictionary_property, DomObject, DomRoot, Fallible, Reflector,
20+
};
21+
use super::bindings::reflector::reflect_dom_object_with_proto;
22+
use super::types::GlobalScope;
23+
24+
#[dom_struct]
25+
pub struct ByteLengthQueuingStrategy {
26+
reflector_: Reflector,
27+
high_water_mark: f64,
28+
}
29+
30+
#[allow(non_snake_case)]
31+
impl ByteLengthQueuingStrategy {
32+
/// <https://streams.spec.whatwg.org/#blqs-constructor>
33+
pub fn Constructor(
34+
global: &GlobalScope,
35+
proto: Option<HandleObject>,
36+
init: &QueuingStrategyInit,
37+
) -> DomRoot<Self> {
38+
Self::new(global, proto, init.highWaterMark)
39+
}
40+
41+
pub fn new_inherited(init: f64) -> Self {
42+
Self {
43+
reflector_: Reflector::new(),
44+
high_water_mark: init,
45+
}
46+
}
47+
48+
pub fn new(global: &GlobalScope, proto: Option<HandleObject>, init: f64) -> DomRoot<Self> {
49+
reflect_dom_object_with_proto(Box::new(Self::new_inherited(init)), global, proto)
50+
}
51+
}
52+
53+
impl ByteLengthQueuingStrategyMethods for ByteLengthQueuingStrategy {
54+
/// <https://streams.spec.whatwg.org/#blqs-high-water-mark>
55+
fn HighWaterMark(&self) -> f64 {
56+
self.high_water_mark
57+
}
58+
59+
#[allow(unsafe_code)]
60+
/// <https://streams.spec.whatwg.org/#blqs-size>
61+
fn GetSize(&self) -> Fallible<Rc<Function>> {
62+
let global = self.reflector_.global();
63+
let cx = GlobalScope::get_cx();
64+
// Return this's relevant global object's byte length queuing strategy
65+
// size function.
66+
if let Some(fun) = global.get_byte_length_queuing_strategy_size() {
67+
return Ok(fun);
68+
}
69+
70+
// Step 1. Let steps be the following steps, given chunk
71+
// Note: See ByteLengthQueuingStrategySize instead.
72+
73+
unsafe {
74+
// Step 2. Let F be !CreateBuiltinFunction(steps, 1, "size", « »,
75+
// globalObject’s relevant Realm).
76+
let raw_fun = JS_NewFunction(
77+
*cx,
78+
Some(byte_length_queuing_strategy_size),
79+
1,
80+
0,
81+
b"size\0".as_ptr() as *const c_char,
82+
);
83+
assert!(!raw_fun.is_null());
84+
85+
// Step 3. Set globalObject’s byte length queuing strategy size function to
86+
// a Function that represents a reference to F,
87+
// with callback context equal to globalObject’s relevant settings object.
88+
let fun_obj = JS_GetFunctionObject(raw_fun);
89+
let fun = Function::new(cx, fun_obj);
90+
global.set_byte_length_queuing_strategy_size(fun.clone());
91+
Ok(fun)
92+
}
93+
}
94+
}
95+
96+
/// <https://streams.spec.whatwg.org/#byte-length-queuing-strategy-size-function>
97+
#[allow(unsafe_code)]
98+
unsafe extern "C" fn byte_length_queuing_strategy_size(
99+
cx: *mut JSContext,
100+
argc: u32,
101+
vp: *mut JSVal,
102+
) -> bool {
103+
let args = CallArgs::from_vp(vp, argc);
104+
// Step 1.1: Return ? GetV(chunk, "byteLength").
105+
rooted!(in(cx) let object = HandleValue::from_raw(args.get(0)).to_object());
106+
get_dictionary_property(
107+
cx,
108+
object.handle(),
109+
"byteLength",
110+
MutableHandleValue::from_raw(args.rval()),
111+
)
112+
.unwrap_or(false)
113+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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+
5+
use std::ffi::c_char;
6+
use std::rc::Rc;
7+
8+
use dom_struct::dom_struct;
9+
use js::jsapi::{CallArgs, JSContext, JS_GetFunctionObject, JS_NewFunction};
10+
use js::jsval::{Int32Value, JSVal};
11+
use js::rust::HandleObject;
12+
13+
use super::bindings::codegen::Bindings::FunctionBinding::Function;
14+
use super::bindings::codegen::Bindings::QueuingStrategyBinding::{
15+
CountQueuingStrategyMethods, QueuingStrategy, QueuingStrategyInit, QueuingStrategySize,
16+
};
17+
use super::bindings::import::module::{DomObject, DomRoot, Error, Fallible, Reflector};
18+
use super::bindings::reflector::reflect_dom_object_with_proto;
19+
use super::types::GlobalScope;
20+
21+
#[dom_struct]
22+
pub struct CountQueuingStrategy {
23+
reflector_: Reflector,
24+
high_water_mark: f64,
25+
}
26+
27+
#[allow(non_snake_case)]
28+
impl CountQueuingStrategy {
29+
/// <https://streams.spec.whatwg.org/#cqs-constructor>
30+
pub fn Constructor(
31+
global: &GlobalScope,
32+
proto: Option<HandleObject>,
33+
init: &QueuingStrategyInit,
34+
) -> DomRoot<Self> {
35+
Self::new(global, proto, init.highWaterMark)
36+
}
37+
38+
pub fn new_inherited(init: f64) -> Self {
39+
Self {
40+
reflector_: Reflector::new(),
41+
high_water_mark: init,
42+
}
43+
}
44+
45+
pub fn new(global: &GlobalScope, proto: Option<HandleObject>, init: f64) -> DomRoot<Self> {
46+
reflect_dom_object_with_proto(Box::new(Self::new_inherited(init)), global, proto)
47+
}
48+
}
49+
50+
impl CountQueuingStrategyMethods for CountQueuingStrategy {
51+
/// <https://streams.spec.whatwg.org/#cqs-high-water-mark>
52+
fn HighWaterMark(&self) -> f64 {
53+
self.high_water_mark
54+
}
55+
56+
#[allow(unsafe_code)]
57+
/// <https://streams.spec.whatwg.org/#cqs-size>
58+
fn GetSize(&self) -> Fallible<Rc<Function>> {
59+
let global = self.reflector_.global();
60+
let cx = GlobalScope::get_cx();
61+
// Return this's relevant global object's count queuing strategy
62+
// size function.
63+
if let Some(fun) = global.get_count_queuing_strategy_size() {
64+
return Ok(fun);
65+
}
66+
67+
// Step 1. Let steps be the following steps:
68+
// Note: See count_queuing_strategy_size instead.
69+
70+
unsafe {
71+
// Step 2. Let F be
72+
// ! CreateBuiltinFunction(steps, 0, "size", « »,
73+
// globalObject’s relevant Realm).
74+
let raw_fun = JS_NewFunction(
75+
*cx,
76+
Some(count_queuing_strategy_size),
77+
0,
78+
0,
79+
b"size\0".as_ptr() as *const c_char,
80+
);
81+
assert!(!raw_fun.is_null());
82+
83+
// Step 3. Set globalObject’s count queuing strategy size function to
84+
// a Function that represents a reference to F,
85+
// with callback context equal to globalObject’s relevant settings object.
86+
let fun_obj = JS_GetFunctionObject(raw_fun);
87+
let fun = Function::new(cx, fun_obj);
88+
global.set_count_queuing_strategy_size(fun.clone());
89+
Ok(fun)
90+
}
91+
}
92+
}
93+
94+
/// <https://streams.spec.whatwg.org/#count-queuing-strategy-size-function>
95+
#[allow(unsafe_code)]
96+
unsafe extern "C" fn count_queuing_strategy_size(
97+
_cx: *mut JSContext,
98+
argc: u32,
99+
vp: *mut JSVal,
100+
) -> bool {
101+
let args = CallArgs::from_vp(vp, argc);
102+
// Step 1.1. Return 1.
103+
args.rval().set(Int32Value(1));
104+
true
105+
}
106+
107+
/// Extract the high water mark from a QueuingStrategy.
108+
/// If the high water mark is not set, return the default value.
109+
///
110+
/// <https://streams.spec.whatwg.org/#validate-and-normalize-high-water-mark>
111+
pub fn extract_high_water_mark(strategy: &QueuingStrategy, default_hwm: f64) -> Result<f64, Error> {
112+
if strategy.highWaterMark.is_none() {
113+
return Ok(default_hwm);
114+
}
115+
116+
let high_water_mark = strategy.highWaterMark.unwrap();
117+
if high_water_mark.is_nan() || high_water_mark < 0.0 {
118+
return Err(Error::Range(
119+
"High water mark must be a non-negative number.".to_string(),
120+
));
121+
}
122+
123+
Ok(high_water_mark)
124+
}
125+
126+
/// Extract the size algorithm from a QueuingStrategy.
127+
/// If the size algorithm is not set, return a fallback function which always returns 1.
128+
///
129+
/// <https://streams.spec.whatwg.org/#make-size-algorithm-from-size-function>
130+
pub fn extract_size_algorithm(strategy: &QueuingStrategy) -> Rc<QueuingStrategySize> {
131+
if strategy.size.is_none() {
132+
#[allow(unsafe_code)]
133+
unsafe extern "C" fn fallback_strategy_size(
134+
_cx: *mut JSContext,
135+
argc: u32,
136+
vp: *mut JSVal,
137+
) -> bool {
138+
let args = CallArgs::from_vp(vp, argc);
139+
args.rval().set(Int32Value(1));
140+
true
141+
}
142+
#[allow(unsafe_code)]
143+
unsafe {
144+
let cx = GlobalScope::get_cx();
145+
let raw_fun = JS_NewFunction(
146+
*cx,
147+
Some(fallback_strategy_size),
148+
0,
149+
0,
150+
b"size\0".as_ptr() as *const c_char,
151+
);
152+
assert!(!raw_fun.is_null());
153+
let fun_obj = JS_GetFunctionObject(raw_fun);
154+
return QueuingStrategySize::new(cx, fun_obj).clone();
155+
}
156+
}
157+
strategy.size.as_ref().unwrap().clone()
158+
}

components/script/dom/globalscope.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
44

55
use std::borrow::Cow;
6-
use std::cell::Cell;
6+
use std::cell::{Cell, OnceCell};
77
use std::collections::hash_map::Entry;
88
use std::collections::{HashMap, VecDeque};
99
use std::ops::Index;
@@ -63,6 +63,7 @@ use super::bindings::trace::HashMapTracedValues;
6363
use crate::dom::bindings::cell::{DomRefCell, RefMut};
6464
use crate::dom::bindings::codegen::Bindings::BroadcastChannelBinding::BroadcastChannelMethods;
6565
use crate::dom::bindings::codegen::Bindings::EventSourceBinding::EventSource_Binding::EventSourceMethods;
66+
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
6667
use crate::dom::bindings::codegen::Bindings::ImageBitmapBinding::{
6768
ImageBitmapOptions, ImageBitmapSource,
6869
};
@@ -81,6 +82,7 @@ use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
8182
use crate::dom::bindings::settings_stack::{entry_global, incumbent_global, AutoEntryScript};
8283
use crate::dom::bindings::str::DOMString;
8384
use crate::dom::bindings::structuredclone;
85+
use crate::dom::bindings::trace::CustomTraceable;
8486
use crate::dom::bindings::utils::to_frozen_array;
8587
use crate::dom::bindings::weakref::{DOMTracker, WeakRef};
8688
use crate::dom::blob::Blob;
@@ -345,6 +347,20 @@ pub struct GlobalScope {
345347

346348
/// Is considered in a secure context
347349
inherited_secure_context: Option<bool>,
350+
351+
/// The byte length queuing strategy size function that will be initialized once
352+
/// `size` getter of `ByteLengthQueuingStrategy` is called.
353+
///
354+
/// <https://streams.spec.whatwg.org/#byte-length-queuing-strategy-size-function>
355+
#[ignore_malloc_size_of = "Rc<T> is hard"]
356+
byte_length_queuing_strategy_size_function: OnceCell<Rc<Function>>,
357+
358+
/// The count queuing strategy size function that will be initialized once
359+
/// `size` getter of `CountQueuingStrategy` is called.
360+
///
361+
/// <https://streams.spec.whatwg.org/#count-queuing-strategy-size-function>
362+
#[ignore_malloc_size_of = "Rc<T> is hard"]
363+
count_queuing_strategy_size_function: OnceCell<Rc<Function>>,
348364
}
349365

350366
/// A wrapper for glue-code between the ipc router and the event-loop.
@@ -805,6 +821,8 @@ impl GlobalScope {
805821
console_count_map: Default::default(),
806822
dynamic_modules: DomRefCell::new(DynamicModuleList::new()),
807823
inherited_secure_context,
824+
byte_length_queuing_strategy_size_function: OnceCell::new(),
825+
count_queuing_strategy_size_function: OnceCell::new(),
808826
}
809827
}
810828

@@ -3275,6 +3293,33 @@ impl GlobalScope {
32753293
pub(crate) fn dynamic_module_list(&self) -> RefMut<DynamicModuleList> {
32763294
self.dynamic_modules.borrow_mut()
32773295
}
3296+
3297+
pub(crate) fn set_byte_length_queuing_strategy_size(&self, function: Rc<Function>) {
3298+
if let Err(_) = self
3299+
.byte_length_queuing_strategy_size_function
3300+
.set(function)
3301+
{
3302+
warn!("byte length queuing strategy size function is set twice.");
3303+
};
3304+
}
3305+
3306+
pub(crate) fn get_byte_length_queuing_strategy_size(&self) -> Option<Rc<Function>> {
3307+
self.byte_length_queuing_strategy_size_function
3308+
.get()
3309+
.map(|s| s.clone())
3310+
}
3311+
3312+
pub(crate) fn set_count_queuing_strategy_size(&self, function: Rc<Function>) {
3313+
if let Err(_) = self.count_queuing_strategy_size_function.set(function) {
3314+
warn!("count queuing strategy size function is set twice.");
3315+
};
3316+
}
3317+
3318+
pub(crate) fn get_count_queuing_strategy_size(&self) -> Option<Rc<Function>> {
3319+
self.count_queuing_strategy_size_function
3320+
.get()
3321+
.map(|s| s.clone())
3322+
}
32783323
}
32793324

32803325
/// Returns the Rust global scope from a JS global object.

components/script/dom/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ pub mod bluetoothremotegattserver;
242242
pub mod bluetoothremotegattservice;
243243
pub mod bluetoothuuid;
244244
pub mod broadcastchannel;
245+
pub mod bytelengthqueuingstrategy;
245246
pub mod canvasgradient;
246247
pub mod canvaspattern;
247248
pub mod canvasrenderingcontext2d;
@@ -255,6 +256,7 @@ pub mod comment;
255256
pub mod compositionevent;
256257
pub mod console;
257258
pub mod constantsourcenode;
259+
pub mod countqueuingstrategy;
258260
mod create;
259261
pub mod crypto;
260262
pub mod css;
@@ -505,7 +507,10 @@ pub mod promiserejectionevent;
505507
pub mod radionodelist;
506508
pub mod range;
507509
pub mod raredata;
510+
pub mod readablebytestreamcontroller;
508511
pub mod readablestream;
512+
pub mod readablestreambyobrequest;
513+
pub mod readablestreamdefaultcontroller;
509514
pub mod request;
510515
pub mod resizeobserver;
511516
pub mod resizeobserverentry;

0 commit comments

Comments
 (0)