script: Refer to DOM interfaces with generic types in generated bindings. (#35457)

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2025-02-21 06:10:00 -05:00 committed by GitHub
parent 14db055d46
commit 1192ae32b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 627 additions and 167 deletions

View file

@ -397,14 +397,14 @@ pub(crate) unsafe fn call_html_constructor<T: DerivedFrom<Element> + DomObject>(
.is_ok()
}
pub(crate) unsafe fn call_default_constructor(
pub(crate) unsafe fn call_default_constructor<D: crate::DomTypes>(
cx: JSContext,
args: &CallArgs,
global: &GlobalScope,
global: &D::GlobalScope,
proto_id: PrototypeList::ID,
ctor_name: &str,
creator: unsafe fn(JSContext, HandleObject, *mut ProtoOrIfaceArray),
constructor: impl FnOnce(JSContext, &CallArgs, &GlobalScope, HandleObject) -> bool,
constructor: impl FnOnce(JSContext, &CallArgs, &D::GlobalScope, HandleObject) -> bool,
) -> bool {
if !args.is_constructing() {
throw_constructor_without_new(cx, ctor_name);

View file

@ -58,7 +58,6 @@ use crate::dom::htmlcollection::HTMLCollection;
use crate::dom::htmlformcontrolscollection::HTMLFormControlsCollection;
use crate::dom::htmloptionscollection::HTMLOptionsCollection;
use crate::dom::nodelist::NodeList;
use crate::dom::windowproxy::WindowProxy;
impl<T: Float + ToJSValConvertible> ToJSValConvertible for Finite<T> {
#[inline]
@ -425,10 +424,10 @@ where
/// Get a `DomRoot<T>` for a WindowProxy accessible from a `HandleValue`.
/// Caller is responsible for throwing a JS exception if needed in case of error.
pub(crate) unsafe fn windowproxy_from_handlevalue(
pub(crate) unsafe fn windowproxy_from_handlevalue<D: crate::DomTypes>(
v: HandleValue,
_cx: *mut JSContext,
) -> Result<DomRoot<WindowProxy>, ()> {
) -> Result<DomRoot<D::WindowProxy>, ()> {
if !v.get().is_object() {
return Err(());
}
@ -438,6 +437,6 @@ pub(crate) unsafe fn windowproxy_from_handlevalue(
}
let mut value = UndefinedValue();
GetProxyReservedSlot(object, 0, &mut value);
let ptr = value.to_private() as *const WindowProxy;
let ptr = value.to_private() as *const D::WindowProxy;
Ok(DomRoot::from_ref(&*ptr))
}

View file

@ -26,7 +26,7 @@ pub(crate) mod base {
ChannelInterpretationValues,
};
pub(crate) use crate::dom::bindings::codegen::DomTypes::DomTypes;
pub(crate) use crate::dom::bindings::codegen::UnionTypes;
pub(crate) use crate::dom::bindings::codegen::{GenericUnionTypes, UnionTypes};
pub(crate) use crate::dom::bindings::conversions::{
root_from_handlevalue, ConversionBehavior, ConversionResult, FromJSValConvertible,
StringificationBehavior, ToJSValConvertible,
@ -35,14 +35,15 @@ pub(crate) mod base {
pub(crate) use crate::dom::bindings::error::{throw_dom_exception, Fallible};
pub(crate) use crate::dom::bindings::num::Finite;
pub(crate) use crate::dom::bindings::proxyhandler::CrossOriginProperties;
pub(crate) use crate::dom::bindings::reflector::{DomGlobal, DomObject};
pub(crate) use crate::dom::bindings::reflector::{DomGlobalGeneric, DomObject};
pub(crate) use crate::dom::bindings::root::DomRoot;
pub(crate) use crate::dom::bindings::str::{ByteString, DOMString, USVString};
pub(crate) use crate::dom::bindings::trace::RootedTraceableBox;
pub(crate) use crate::dom::bindings::utils::{
get_dictionary_property, set_dictionary_property, ThreadUnsafeOnceLock,
get_dictionary_property, set_dictionary_property, DomHelpers, ThreadUnsafeOnceLock,
};
pub(crate) use crate::dom::globalscope::GlobalScope;
pub(crate) use crate::dom::globalscope::{GlobalScope, GlobalScopeHelpers};
pub(crate) use crate::dom::promise::PromiseHelpers;
pub(crate) use crate::script_runtime::JSContext as SafeJSContext;
}

View file

@ -7,6 +7,7 @@
//! Implementation of `iterable<...>` and `iterable<..., ...>` WebIDL declarations.
use std::cell::Cell;
use std::marker::PhantomData;
use std::ptr;
use std::ptr::NonNull;
@ -15,18 +16,20 @@ use js::conversions::ToJSValConvertible;
use js::jsapi::{Heap, JSObject};
use js::jsval::UndefinedValue;
use js::rust::{HandleObject, HandleValue, MutableHandleObject};
use script_bindings::conversions::IDLInterface;
use script_bindings::utils::DOMClass;
use crate::dom::bindings::codegen::Bindings::IterableIteratorBinding::{
IterableKeyAndValueResult, IterableKeyOrValueResult,
};
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{
reflect_dom_object, DomGlobal, DomObjectIteratorWrap, DomObjectWrap, Reflector,
reflect_dom_object, DomGlobalGeneric, DomObjectIteratorWrap, DomObjectWrap, Reflector,
};
use crate::dom::bindings::root::{Dom, DomRoot, Root};
use crate::dom::bindings::trace::{JSTraceable, RootedTraceableBox};
use crate::dom::globalscope::GlobalScope;
use crate::dom::bindings::trace::{JSTraceable, NoTrace, RootedTraceableBox};
use crate::script_runtime::{CanGc, JSContext};
use crate::DomTypes;
/// The values that an iterator will iterate over.
#[derive(JSTraceable, MallocSizeOf)]
@ -55,14 +58,41 @@ pub(crate) trait Iterable {
/// An iterator over the iterable entries of a given DOM interface.
#[dom_struct]
pub(crate) struct IterableIterator<T: DomObjectIteratorWrap + JSTraceable + Iterable> {
pub(crate) struct IterableIterator<
D: DomTypes,
T: DomObjectIteratorWrap<D> + JSTraceable + Iterable + DomGlobalGeneric<D>,
> {
reflector: Reflector,
iterable: Dom<T>,
type_: IteratorType,
index: Cell<u32>,
_marker: NoTrace<PhantomData<D>>,
}
impl<T: DomObjectIteratorWrap + JSTraceable + Iterable> IterableIterator<T> {
impl<D: DomTypes, T: DomObjectIteratorWrap<D> + JSTraceable + Iterable> IterableIterator<D, T> {
pub fn global(&self) -> DomRoot<D::GlobalScope> {
<Self as DomGlobalGeneric<D>>::global(self)
}
}
impl<
D: DomTypes,
T: DomObjectIteratorWrap<D>
+ JSTraceable
+ Iterable
+ DomGlobalGeneric<D>
+ IDLInterface
+ IteratorDerives,
> IDLInterface for IterableIterator<D, T>
{
fn derives(class: &'static DOMClass) -> bool {
<T as IteratorDerives>::derives(class)
}
}
impl<D: DomTypes, T: DomObjectIteratorWrap<D> + JSTraceable + Iterable + DomGlobalGeneric<D>>
IterableIterator<D, T>
{
/// Create a new iterator instance for the provided iterable DOM interface.
pub(crate) fn new(iterable: &T, type_: IteratorType) -> DomRoot<Self> {
let iterator = Box::new(IterableIterator {
@ -70,6 +100,7 @@ impl<T: DomObjectIteratorWrap + JSTraceable + Iterable> IterableIterator<T> {
type_,
iterable: Dom::from_ref(iterable),
index: Cell::new(0),
_marker: NoTrace(PhantomData),
});
reflect_dom_object(iterator, &*iterable.global(), CanGc::note())
}
@ -119,16 +150,26 @@ impl<T: DomObjectIteratorWrap + JSTraceable + Iterable> IterableIterator<T> {
}
}
impl<T: DomObjectIteratorWrap + JSTraceable + Iterable> DomObjectWrap for IterableIterator<T> {
impl<D: DomTypes, T: DomObjectIteratorWrap<D> + JSTraceable + Iterable + DomGlobalGeneric<D>>
DomObjectWrap<D> for IterableIterator<D, T>
{
const WRAP: unsafe fn(
JSContext,
&GlobalScope,
&D::GlobalScope,
Option<HandleObject>,
Box<Self>,
CanGc,
) -> Root<Dom<Self>> = T::ITER_WRAP;
}
/// A version of the [IDLInterface] trait that is specific to types that have
/// iterators defined for them. This allows the `script` crate to define the
/// derives check for the concrete interface type, while the [IteratableIterator]
/// type defined in this module can be parameterized over an unknown generic.
pub trait IteratorDerives {
fn derives(class: &'static DOMClass) -> bool;
}
fn dict_return(
cx: JSContext,
mut result: MutableHandleObject,

View file

@ -179,9 +179,16 @@ pub(crate) mod codegen {
include!(concat!(env!("BINDINGS_OUT_DIR"), "/DomTypes.rs"));
}
#[allow(dead_code)]
pub(crate) mod Bindings {
pub(crate) mod GenericBindings {
include!(concat!(env!("BINDINGS_OUT_DIR"), "/Bindings/mod.rs"));
}
#[allow(dead_code)]
pub(crate) mod Bindings {
include!(concat!(
env!("BINDINGS_OUT_DIR"),
"/ConcreteBindings/mod.rs"
));
}
pub(crate) mod InterfaceObjectMap {
include!(concat!(env!("BINDINGS_OUT_DIR"), "/InterfaceObjectMap.rs"));
pub(crate) use script_bindings::codegen::Globals::Globals;
@ -206,6 +213,10 @@ pub(crate) mod codegen {
clippy::upper_case_acronyms,
clippy::enum_variant_names
)]
pub(crate) mod GenericUnionTypes {
include!(concat!(env!("BINDINGS_OUT_DIR"), "/GenericUnionTypes.rs"));
}
#[allow(dead_code)]
pub(crate) mod UnionTypes {
include!(concat!(env!("BINDINGS_OUT_DIR"), "/UnionTypes.rs"));
}

View file

@ -10,59 +10,74 @@ use crate::dom::bindings::conversions::DerivedFrom;
use crate::dom::bindings::iterable::{Iterable, IterableIterator};
use crate::dom::bindings::root::{Dom, DomRoot, Root};
use crate::dom::bindings::trace::JSTraceable;
use crate::dom::globalscope::GlobalScope;
use crate::dom::globalscope::{GlobalScope, GlobalScopeHelpers};
use crate::realms::AlreadyInRealm;
use crate::script_runtime::{CanGc, JSContext};
use crate::DomTypes;
/// Create the reflector for a new DOM object and yield ownership to the
/// reflector.
pub(crate) fn reflect_dom_object<T, U>(obj: Box<T>, global: &U, can_gc: CanGc) -> DomRoot<T>
pub(crate) fn reflect_dom_object<D, T, U>(obj: Box<T>, global: &U, can_gc: CanGc) -> DomRoot<T>
where
T: DomObject + DomObjectWrap,
U: DerivedFrom<GlobalScope>,
D: DomTypes,
T: DomObject + DomObjectWrap<D>,
U: DerivedFrom<D::GlobalScope>,
{
let global_scope = global.upcast();
unsafe { T::WRAP(GlobalScope::get_cx(), global_scope, None, obj, can_gc) }
unsafe { T::WRAP(D::GlobalScope::get_cx(), global_scope, None, obj, can_gc) }
}
pub(crate) fn reflect_dom_object_with_proto<T, U>(
pub(crate) fn reflect_dom_object_with_proto<D, T, U>(
obj: Box<T>,
global: &U,
proto: Option<HandleObject>,
can_gc: CanGc,
) -> DomRoot<T>
where
T: DomObject + DomObjectWrap,
U: DerivedFrom<GlobalScope>,
D: DomTypes,
T: DomObject + DomObjectWrap<D>,
U: DerivedFrom<D::GlobalScope>,
{
let global_scope = global.upcast();
unsafe { T::WRAP(GlobalScope::get_cx(), global_scope, proto, obj, can_gc) }
unsafe { T::WRAP(D::GlobalScope::get_cx(), global_scope, proto, obj, can_gc) }
}
pub trait DomGlobal: DomObject {
pub(crate) trait DomGlobalGeneric<D: DomTypes>: DomObject {
/// Returns the [`GlobalScope`] of the realm that the [`DomObject`] was created in. If this
/// object is a `Node`, this will be different from it's owning `Document` if adopted by. For
/// `Node`s it's almost always better to use `NodeTraits::owning_global`.
fn global(&self) -> DomRoot<GlobalScope>
fn global(&self) -> DomRoot<D::GlobalScope>
where
Self: Sized,
{
let realm = AlreadyInRealm::assert_for_cx(GlobalScope::get_cx());
GlobalScope::from_reflector(self, &realm)
let realm = AlreadyInRealm::assert_for_cx(D::GlobalScope::get_cx());
D::GlobalScope::from_reflector(self, &realm)
}
}
impl<T: DomObject> DomGlobal for T {}
impl<D: DomTypes, T: DomObject> DomGlobalGeneric<D> for T {}
pub(crate) trait DomGlobal {
fn global(&self) -> DomRoot<GlobalScope>;
}
impl<T: DomGlobalGeneric<crate::DomTypeHolder>> DomGlobal for T {
fn global(&self) -> DomRoot<GlobalScope> {
<Self as DomGlobalGeneric<crate::DomTypeHolder>>::global(self)
}
}
pub(crate) use script_bindings::reflector::{DomObject, MutDomObject, Reflector};
/// A trait to provide a function pointer to wrap function for DOM objects.
pub(crate) trait DomObjectWrap: Sized + DomObject {
pub(crate) trait DomObjectWrap<D: DomTypes>:
Sized + DomObject + DomGlobalGeneric<D>
{
/// Function pointer to the general wrap function type
#[allow(clippy::type_complexity)]
const WRAP: unsafe fn(
JSContext,
&GlobalScope,
&D::GlobalScope,
Option<HandleObject>,
Box<Self>,
CanGc,
@ -71,14 +86,16 @@ pub(crate) trait DomObjectWrap: Sized + DomObject {
/// A trait to provide a function pointer to wrap function for
/// DOM iterator interfaces.
pub(crate) trait DomObjectIteratorWrap: DomObjectWrap + JSTraceable + Iterable {
pub(crate) trait DomObjectIteratorWrap<D: DomTypes>:
DomObjectWrap<D> + JSTraceable + Iterable
{
/// Function pointer to the wrap function for `IterableIterator<T>`
#[allow(clippy::type_complexity)]
const ITER_WRAP: unsafe fn(
JSContext,
&GlobalScope,
&D::GlobalScope,
Option<HandleObject>,
Box<IterableIterator<Self>>,
Box<IterableIterator<D, Self>>,
CanGc,
) -> Root<Dom<IterableIterator<Self>>>;
) -> Root<Dom<IterableIterator<D, Self>>>;
}

View file

@ -37,15 +37,18 @@ use js::rust::{
use js::JS_CALLEE;
use crate::dom::bindings::codegen::InterfaceObjectMap;
use crate::dom::bindings::codegen::PrototypeList::PROTO_OR_IFACE_LENGTH;
use crate::dom::bindings::codegen::PrototypeList::{self, PROTO_OR_IFACE_LENGTH};
use crate::dom::bindings::constructor::call_html_constructor;
use crate::dom::bindings::conversions::{
jsstring_to_str, private_from_proto_check, PrototypeCheck,
jsstring_to_str, private_from_proto_check, DerivedFrom, PrototypeCheck,
};
use crate::dom::bindings::error::throw_invalid_this;
use crate::dom::bindings::error::{throw_dom_exception, throw_invalid_this, Error};
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::trace_object;
use crate::dom::windowproxy::WindowProxyHandler;
use crate::script_runtime::JSContext as SafeJSContext;
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
use crate::DomTypes;
/// A OnceLock wrapping a type that is not considered threadsafe by the Rust compiler, but
/// will be used in a threadsafe manner (it will not be mutated, after being initialized).
@ -660,3 +663,40 @@ pub(crate) unsafe fn exception_to_promise(cx: *mut JSContext, rval: RawMutableHa
false
}
}
/// Operations that must be invoked from the generated bindings.
pub(crate) trait DomHelpers<D: DomTypes> {
fn throw_dom_exception(cx: SafeJSContext, global: &D::GlobalScope, result: Error);
unsafe fn call_html_constructor<T: DerivedFrom<D::Element> + DomObject>(
cx: SafeJSContext,
args: &CallArgs,
global: &D::GlobalScope,
proto_id: crate::dom::bindings::codegen::PrototypeList::ID,
creator: unsafe fn(SafeJSContext, HandleObject, *mut ProtoOrIfaceArray),
can_gc: CanGc,
) -> bool;
}
impl DomHelpers<crate::DomTypeHolder> for crate::DomTypeHolder {
fn throw_dom_exception(
cx: SafeJSContext,
global: &<crate::DomTypeHolder as DomTypes>::GlobalScope,
result: Error,
) {
throw_dom_exception(cx, global, result)
}
unsafe fn call_html_constructor<
T: DerivedFrom<<crate::DomTypeHolder as DomTypes>::Element> + DomObject,
>(
cx: SafeJSContext,
args: &CallArgs,
global: &<crate::DomTypeHolder as DomTypes>::GlobalScope,
proto_id: PrototypeList::ID,
creator: unsafe fn(SafeJSContext, HandleObject, *mut ProtoOrIfaceArray),
can_gc: CanGc,
) -> bool {
call_html_constructor::<T>(cx, args, global, proto_id, creator, can_gc)
}
}

View file

@ -14,8 +14,9 @@ use super::bindings::codegen::Bindings::FunctionBinding::Function;
use super::bindings::codegen::Bindings::QueuingStrategyBinding::{
ByteLengthQueuingStrategyMethods, QueuingStrategyInit,
};
use super::bindings::import::module::{DomGlobal, DomRoot, Fallible, Reflector};
use super::bindings::reflector::reflect_dom_object_with_proto;
use super::bindings::error::Fallible;
use super::bindings::reflector::{reflect_dom_object_with_proto, DomGlobal, Reflector};
use super::bindings::root::DomRoot;
use super::types::GlobalScope;
use crate::dom::bindings::import::module::get_dictionary_property;
use crate::native_fn;

View file

@ -13,8 +13,9 @@ use super::bindings::codegen::Bindings::FunctionBinding::Function;
use super::bindings::codegen::Bindings::QueuingStrategyBinding::{
CountQueuingStrategyMethods, QueuingStrategy, QueuingStrategyInit, QueuingStrategySize,
};
use super::bindings::import::module::{DomGlobal, DomRoot, Error, Fallible, Reflector};
use super::bindings::reflector::reflect_dom_object_with_proto;
use super::bindings::error::{Error, Fallible};
use super::bindings::reflector::{reflect_dom_object_with_proto, DomGlobal, Reflector};
use super::bindings::root::DomRoot;
use super::types::GlobalScope;
use crate::script_runtime::CanGc;
use crate::{native_fn, native_raw_obj_fn};

View file

@ -3331,9 +3331,23 @@ unsafe fn global_scope_from_global_static(global: *mut JSObject) -> DomRoot<Glob
root_from_object_static(global).unwrap()
}
/// Operations that must be invoked from the generated bindings.
#[allow(unsafe_code)]
pub(crate) trait GlobalScopeHelpers<D: crate::DomTypes> {
unsafe fn from_context(cx: *mut JSContext, realm: InRealm) -> DomRoot<D::GlobalScope>;
fn get_cx() -> SafeJSContext;
unsafe fn from_object(obj: *mut JSObject) -> DomRoot<D::GlobalScope>;
fn from_reflector(
reflector: &impl DomObject,
realm: &AlreadyInRealm,
) -> DomRoot<D::GlobalScope>;
unsafe fn from_object_maybe_wrapped(
obj: *mut JSObject,
cx: *mut JSContext,
) -> DomRoot<D::GlobalScope>;
fn origin(&self) -> &MutableOrigin;
}
#[allow(unsafe_code)]
@ -3341,4 +3355,24 @@ impl GlobalScopeHelpers<crate::DomTypeHolder> for GlobalScope {
unsafe fn from_context(cx: *mut JSContext, realm: InRealm) -> DomRoot<Self> {
GlobalScope::from_context(cx, realm)
}
fn get_cx() -> SafeJSContext {
GlobalScope::get_cx()
}
unsafe fn from_object(obj: *mut JSObject) -> DomRoot<Self> {
GlobalScope::from_object(obj)
}
fn from_reflector(reflector: &impl DomObject, realm: &AlreadyInRealm) -> DomRoot<Self> {
GlobalScope::from_reflector(reflector, realm)
}
unsafe fn from_object_maybe_wrapped(obj: *mut JSObject, cx: *mut JSContext) -> DomRoot<Self> {
GlobalScope::from_object_maybe_wrapped(obj, cx)
}
fn origin(&self) -> &MutableOrigin {
GlobalScope::origin(self)
}
}

View file

@ -1925,7 +1925,7 @@ fn as_uintptr<T>(t: &T) -> uintptr_t {
impl Node {
pub(crate) fn reflect_node<N>(node: Box<N>, document: &Document, can_gc: CanGc) -> DomRoot<N>
where
N: DerivedFrom<Node> + DomObject + DomObjectWrap,
N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
{
Self::reflect_node_with_proto(node, document, None, can_gc)
}
@ -1937,7 +1937,7 @@ impl Node {
can_gc: CanGc,
) -> DomRoot<N>
where
N: DerivedFrom<Node> + DomObject + DomObjectWrap,
N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
{
let window = document.window();
reflect_dom_object_with_proto(node, window, proto, can_gc)

View file

@ -384,3 +384,22 @@ fn create_native_handler_function(
obj.get()
}
}
/// Operations that must be invoked from the generated bindings.
pub(crate) trait PromiseHelpers<D: crate::DomTypes> {
fn new_resolved(
global: &D::GlobalScope,
cx: SafeJSContext,
value: impl ToJSValConvertible,
) -> Rc<D::Promise>;
}
impl PromiseHelpers<crate::DomTypeHolder> for Promise {
fn new_resolved(
global: &GlobalScope,
cx: SafeJSContext,
value: impl ToJSValConvertible,
) -> Rc<Promise> {
Promise::new_resolved(global, cx, value)
}
}

View file

@ -26,7 +26,7 @@ use crate::dom::bindings::codegen::Bindings::UnderlyingSourceBinding::Underlying
use crate::dom::bindings::conversions::{ConversionBehavior, ConversionResult};
use crate::dom::bindings::error::Error;
use crate::dom::bindings::import::module::Fallible;
use crate::dom::bindings::import::module::UnionTypes::ReadableStreamDefaultReaderOrReadableStreamBYOBReader as ReadableStreamReader;
use crate::dom::bindings::codegen::UnionTypes::ReadableStreamDefaultReaderOrReadableStreamBYOBReader as ReadableStreamReader;
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::{DomRoot, MutNullableDom, Dom};
use crate::dom::bindings::trace::RootedTraceableBox;
@ -666,13 +666,13 @@ impl ReadableStream {
// If stream.[[state]] is "closed", return a promise resolved with undefined.
if self.is_closed() {
let promise = Promise::new(&self.reflector_.global(), can_gc);
let promise = Promise::new(&self.global(), can_gc);
promise.resolve_native(&());
return promise;
}
// If stream.[[state]] is "errored", return a promise rejected with stream.[[storedError]].
if self.is_errored() {
let promise = Promise::new(&self.reflector_.global(), can_gc);
let promise = Promise::new(&self.global(), can_gc);
unsafe {
let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut rval = UndefinedValue());
@ -708,7 +708,7 @@ impl ReadableStream {
// Create a new promise,
// and setup a handler in order to react to the fulfillment of sourceCancelPromise.
let global = self.reflector_.global();
let global = self.global();
let result_promise = Promise::new(&global, can_gc);
let fulfillment_handler = Box::new(SourceCancelPromiseFulfillmentHandler {
result: result_promise.clone(),
@ -784,7 +784,7 @@ impl ReadableStream {
// Let reason2 be undefined.
let reason_2 = Rc::new(Heap::boxed(UndefinedValue()));
// Let cancelPromise be a new promise.
let cancel_promise = Promise::new(&self.reflector_.global(), can_gc);
let cancel_promise = Promise::new(&self.global(), can_gc);
let tee_source_1 = DefaultTeeUnderlyingSource::new(
&reader,
@ -824,7 +824,7 @@ impl ReadableStream {
// Set branch_1 to ! CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm).
let branch_1 = create_readable_stream(
&self.reflector_.global(),
&self.global(),
underlying_source_type_branch_1,
QueuingStrategy::empty(),
can_gc,
@ -834,7 +834,7 @@ impl ReadableStream {
// Set branch_2 to ! CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm).
let branch_2 = create_readable_stream(
&self.reflector_.global(),
&self.global(),
underlying_source_type_branch_2,
QueuingStrategy::empty(),
can_gc,

View file

@ -19,7 +19,7 @@ use super::bindings::root::Dom;
use crate::dom::bindings::buffer_source::create_buffer_source;
use crate::dom::bindings::callback::ExceptionHandling;
use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultControllerBinding::ReadableStreamDefaultControllerMethods;
use crate::dom::bindings::import::module::UnionTypes::ReadableStreamDefaultControllerOrReadableByteStreamController as Controller;
use crate::dom::bindings::codegen::UnionTypes::ReadableStreamDefaultControllerOrReadableByteStreamController as Controller;
use crate::dom::bindings::import::module::{throw_dom_exception, Error, Fallible};
use crate::dom::bindings::reflector::{reflect_dom_object, DomGlobal, Reflector};
use crate::dom::bindings::root::{DomRoot, MutNullableDom};

View file

@ -374,7 +374,7 @@ impl ReadableStreamDefaultReaderMethods<crate::DomTypeHolder> for ReadableStream
return Promise::new_rejected(&self.global(), cx, error.handle());
}
// Let promise be a new promise.
let promise = Promise::new(&self.reflector_.global(), can_gc);
let promise = Promise::new(&self.global(), can_gc);
// Let readRequest be a new read request with the following items:
// chunk steps, given chunk

View file

@ -1069,14 +1069,15 @@ pub(crate) fn handle_get_property(
property.handle_mut(),
)
} {
Ok(_) => match unsafe {
jsval_to_webdriver(*cx, &node.reflector().global(), property.handle())
} {
Ok(_) => {
match unsafe { jsval_to_webdriver(*cx, &node.global(), property.handle()) }
{
Ok(property) => property,
Err(_) => WebDriverJSValue::Undefined,
}
},
Err(error) => {
throw_dom_exception(cx, &node.reflector().global(), error);
throw_dom_exception(cx, &node.global(), error);
WebDriverJSValue::Undefined
},
}

View file

@ -414,6 +414,7 @@ DOMInterfaces = {
'Promise': {
'spiderMonkeyInterface': True,
'additionalTraits': ["crate::dom::promise::PromiseHelpers<Self>"]
},
'Range': {

File diff suppressed because it is too large Load diff

View file

@ -209,10 +209,12 @@ class Descriptor(DescriptorProvider):
# nativeType of the iterable interface. That way we can have a
# templated implementation for all the duplicated iterator
# functionality.
prefix = "D::"
if self.interface.isIteratorInterface():
itrName = self.interface.iterableInterface.identifier.name
itrDesc = self.getDescriptor(itrName)
nativeTypeDefault = iteratorNativeType(itrDesc)
prefix = ""
typeName = desc.get('nativeType', nativeTypeDefault)
@ -232,15 +234,15 @@ class Descriptor(DescriptorProvider):
self.argumentType = "???"
self.nativeType = ty
else:
self.returnType = "DomRoot<%s>" % typeName
self.argumentType = "&%s" % typeName
self.nativeType = "*const %s" % typeName
self.returnType = "DomRoot<%s%s>" % (prefix, typeName)
self.argumentType = "&%s%s" % (prefix, typeName)
self.nativeType = "*const %s%s" % (prefix, typeName)
if self.interface.isIteratorInterface():
pathDefault = 'crate::dom::bindings::iterable::IterableIterator'
else:
pathDefault = 'crate::dom::types::%s' % MakeNativeName(typeName)
self.concreteType = typeName
self.concreteType = "%s%s" % (prefix, typeName)
self.register = desc.get('register', True)
self.path = desc.get('path', pathDefault)
self.inRealmMethods = [name for name in desc.get('inRealms', [])]
@ -489,7 +491,7 @@ def getIdlFileName(object):
def getModuleFromObject(object):
return ('crate::dom::bindings::codegen::Bindings::' + getIdlFileName(object) + 'Binding')
return ('crate::dom::bindings::codegen::GenericBindings::' + getIdlFileName(object) + 'Binding')
def getTypesFromDescriptor(descriptor):
@ -547,7 +549,7 @@ def iteratorNativeType(descriptor, infer=False):
iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
assert (iterableDecl.isIterable() and iterableDecl.isPairIterator()) \
or iterableDecl.isSetlike() or iterableDecl.isMaplike()
res = "IterableIterator%s" % ("" if infer else '<%s>' % descriptor.interface.identifier.name)
res = "IterableIterator%s" % ("" if infer else '<D, D::%s>' % descriptor.interface.identifier.name)
# todo: this hack is telling us that something is still wrong in codegen
if iterableDecl.isSetlike() or iterableDecl.isMaplike():
res = f"crate::dom::bindings::iterable::{res}"

View file

@ -28,7 +28,7 @@ def main():
import WebIDL
from Configuration import Configuration
from CodegenRust import CGBindingRoot
from CodegenRust import CGBindingRoot, CGConcreteBindingRoot
parser = WebIDL.Parser(make_dir(os.path.join(out_dir, "cache")))
webidls = [name for name in os.listdir(webidls_dir) if name.endswith(".webidl")]
@ -48,6 +48,7 @@ def main():
parser_results = parser.finish()
config = Configuration(config_file, parser_results)
make_dir(os.path.join(out_dir, "Bindings"))
make_dir(os.path.join(out_dir, "ConcreteBindings"))
for name, filename in [
("PrototypeList", "PrototypeList.rs"),
@ -59,7 +60,9 @@ def main():
("InheritTypes", "InheritTypes.rs"),
("ConcreteInheritTypes", "ConcreteInheritTypes.rs"),
("Bindings", "Bindings/mod.rs"),
("UnionTypes", "UnionTypes.rs"),
("Bindings", "ConcreteBindings/mod.rs"),
("UnionTypes", "GenericUnionTypes.rs"),
("ConcreteUnionTypes", "UnionTypes.rs"),
("DomTypes", "DomTypes.rs"),
("DomTypeHolder", "DomTypeHolder.rs"),
]:
@ -74,6 +77,11 @@ def main():
if module:
with open(os.path.join(out_dir, prefix + ".rs"), "wb") as f:
f.write(module.encode("utf-8"))
prefix = "ConcreteBindings/%sBinding" % webidl[:-len(".webidl")]
module = CGConcreteBindingRoot(config, prefix, filename).define()
if module:
with open(os.path.join(out_dir, prefix + ".rs"), "wb") as f:
f.write(module.encode("utf-8"))
def make_dir(path):