@@ -20,6 +20,7 @@ use std::mem;
use std::ops::Index;
use std::path::PathBuf;
use uuid::Uuid;
use typeholder::TypeHolderTrait;

/// File-based blob
#[derive(JSTraceable)]
@@ -34,7 +35,7 @@ pub struct FileBlob {
/// Different backends of Blob
#[must_root]
#[derive(JSTraceable)]
pub enum BlobImpl {
pub enum BlobImpl<TH: TypeHolderTrait + 'static> {
/// File-based blob, whose content lives in the net process
File(FileBlob),
/// Memory-based blob, whose content lives in the script process
@@ -43,18 +44,18 @@ pub enum BlobImpl {
/// relative positions of current slicing range,
/// IMPORTANT: The depth of tree is only two, i.e. the parent Blob must be
/// either File-based or Memory-based
Sliced(Dom<Blob>, RelativePos)
Sliced(Dom<Blob<TH>>, RelativePos)
}

impl BlobImpl {
impl<TH: TypeHolderTrait> BlobImpl<TH> {
/// Construct memory-backed BlobImpl
#[allow(unrooted_must_root)]
pub fn new_from_bytes(bytes: Vec<u8>) -> BlobImpl {
pub fn new_from_bytes(bytes: Vec<u8>) -> BlobImpl<TH> {
BlobImpl::Memory(bytes)
}

/// Construct file-backed BlobImpl from File ID
pub fn new_from_file(file_id: Uuid, name: PathBuf, size: u64) -> BlobImpl {
pub fn new_from_file(file_id: Uuid, name: PathBuf, size: u64) -> BlobImpl<TH> {
BlobImpl::File(FileBlob {
id: file_id,
name: Some(name),
@@ -66,25 +67,25 @@ impl BlobImpl {

// https://w3c.github.io/FileAPI/#blob
#[dom_struct]
pub struct Blob {
reflector_: Reflector,
pub struct Blob<TH: TypeHolderTrait + 'static> {
reflector_: Reflector<TH>,
#[ignore_malloc_size_of = "No clear owner"]
blob_impl: DomRefCell<BlobImpl>,
blob_impl: DomRefCell<BlobImpl<TH>>,
/// content-type string
type_string: String,
}

impl Blob {
impl<TH: TypeHolderTrait> Blob<TH> {
#[allow(unrooted_must_root)]
pub fn new(
global: &GlobalScope, blob_impl: BlobImpl, typeString: String)
-> DomRoot<Blob> {
global: &GlobalScope<TH>, blob_impl: BlobImpl<TH>, typeString: String)
-> DomRoot<Blob<TH>> {
let boxed_blob = Box::new(Blob::new_inherited(blob_impl, typeString));
reflect_dom_object(boxed_blob, global, BlobBinding::Wrap)
}

#[allow(unrooted_must_root)]
pub fn new_inherited(blob_impl: BlobImpl, type_string: String) -> Blob {
pub fn new_inherited(blob_impl: BlobImpl<TH>, type_string: String) -> Blob<TH> {
Blob {
reflector_: Reflector::new(),
blob_impl: DomRefCell::new(blob_impl),
@@ -95,8 +96,8 @@ impl Blob {
}

#[allow(unrooted_must_root)]
fn new_sliced(parent: &Blob, rel_pos: RelativePos,
relative_content_type: DOMString) -> DomRoot<Blob> {
fn new_sliced(parent: &Blob<TH>, rel_pos: RelativePos,
relative_content_type: DOMString) -> DomRoot<Blob<TH>> {
let blob_impl = match *parent.blob_impl.borrow() {
BlobImpl::File(_) => {
// Create new parent node
@@ -116,10 +117,10 @@ impl Blob {
}

// https://w3c.github.io/FileAPI/#constructorBlob
pub fn Constructor(global: &GlobalScope,
blobParts: Option<Vec<ArrayBufferOrArrayBufferViewOrBlobOrString>>,
pub fn Constructor(global: &GlobalScope<TH>,
blobParts: Option<Vec<ArrayBufferOrArrayBufferViewOrBlobOrString<TH>>>,
blobPropertyBag: &BlobBinding::BlobPropertyBag)
-> Fallible<DomRoot<Blob>> {
-> Fallible<DomRoot<Blob<TH>>> {
// TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView
let bytes: Vec<u8> = match blobParts {
None => Vec::new(),
@@ -295,13 +296,13 @@ impl Blob {
}
}

impl Drop for Blob {
impl<TH: TypeHolderTrait> Drop for Blob<TH> {
fn drop(&mut self) {
self.clean_up_file_resource();
}
}

fn read_file(global: &GlobalScope, id: Uuid) -> Result<Vec<u8>, ()> {
fn read_file<TH: TypeHolderTrait>(global: &GlobalScope<TH>, id: Uuid) -> Result<Vec<u8>, ()> {
let resource_threads = global.resource_threads();
let (chan, recv) = ipc::channel(global.time_profiler_chan().clone()).map_err(|_|())?;
let origin = get_blob_origin(&global.get_url());
@@ -330,7 +331,7 @@ fn read_file(global: &GlobalScope, id: Uuid) -> Result<Vec<u8>, ()> {
/// Extract bytes from BlobParts, used by Blob and File constructor
/// <https://w3c.github.io/FileAPI/#constructorBlob>
#[allow(unsafe_code)]
pub fn blob_parts_to_bytes(mut blobparts: Vec<ArrayBufferOrArrayBufferViewOrBlobOrString>) -> Result<Vec<u8>, ()> {
pub fn blob_parts_to_bytes<TH: TypeHolderTrait>(mut blobparts: Vec<ArrayBufferOrArrayBufferViewOrBlobOrString<TH>>) -> Result<Vec<u8>, ()> {
let mut ret = vec![];
for blobpart in &mut blobparts {
match blobpart {
@@ -355,7 +356,7 @@ pub fn blob_parts_to_bytes(mut blobparts: Vec<ArrayBufferOrArrayBufferViewOrBlob
Ok(ret)
}

impl BlobMethods for Blob {
impl<TH: TypeHolderTrait> BlobMethods<TH> for Blob<TH> {
// https://w3c.github.io/FileAPI/#dfn-size
fn Size(&self) -> u64 {
match *self.blob_impl.borrow() {
@@ -376,7 +377,7 @@ impl BlobMethods for Blob {
start: Option<i64>,
end: Option<i64>,
content_type: Option<DOMString>)
-> DomRoot<Blob> {
-> DomRoot<Blob<TH>> {
let rel_pos = RelativePos::from_opts(start, end);
Blob::new_sliced(self, rel_pos, content_type.unwrap_or(DOMString::from("")))
}
@@ -41,6 +41,7 @@ use std::rc::Rc;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use task::TaskOnce;
use typeholder::TypeHolderTrait;

const KEY_CONVERSION_ERROR: &'static str = "This `manufacturerData` key can not be parsed as unsigned short:";
const FILTER_EMPTY_ERROR: &'static str = "'filters' member, if present, must be nonempty to find any devices.";
@@ -88,18 +89,19 @@ impl BluetoothExtraPermissionData {
}
}

struct BluetoothContext<T: AsyncBluetoothListener + DomObject> {
promise: Option<TrustedPromise>,
struct BluetoothContext<T: AsyncBluetoothListener<TH> + DomObject, TH: TypeHolderTrait> {
promise: Option<TrustedPromise<TH>>,
receiver: Trusted<T>,
}

pub trait AsyncBluetoothListener {
fn handle_response(&self, result: BluetoothResponse, promise: &Rc<Promise>);
pub trait AsyncBluetoothListener<TH: TypeHolderTrait> {
fn handle_response(&self, result: BluetoothResponse, promise: &Rc<Promise<TH>>);
}

impl<T> BluetoothContext<T>
impl<T, TH> BluetoothContext<T, TH>
where
T: AsyncBluetoothListener + DomObject,
T: AsyncBluetoothListener<TH> + DomObject,
TH: TypeHolderTrait
{
#[allow(unrooted_must_root)]
fn response(&mut self, response: BluetoothResponseResult) {
@@ -118,20 +120,20 @@ where

// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth
#[dom_struct]
pub struct Bluetooth {
eventtarget: EventTarget,
device_instance_map: DomRefCell<HashMap<String, Dom<BluetoothDevice>>>,
pub struct Bluetooth<TH: TypeHolderTrait + 'static> {
eventtarget: EventTarget<TH>,
device_instance_map: DomRefCell<HashMap<String, Dom<BluetoothDevice<TH>>>>,
}

impl Bluetooth {
pub fn new_inherited() -> Bluetooth {
impl<TH: TypeHolderTrait> Bluetooth<TH> {
pub fn new_inherited() -> Bluetooth<TH> {
Bluetooth {
eventtarget: EventTarget::new_inherited(),
device_instance_map: DomRefCell::new(HashMap::new()),
}
}

pub fn new(global: &GlobalScope) -> DomRoot<Bluetooth> {
pub fn new(global: &GlobalScope<TH>) -> DomRoot<Bluetooth<TH>> {
reflect_dom_object(Box::new(Bluetooth::new_inherited()),
global,
BluetoothBinding::Wrap)
@@ -141,13 +143,13 @@ impl Bluetooth {
self.global().as_window().bluetooth_thread()
}

pub fn get_device_map(&self) -> &DomRefCell<HashMap<String, Dom<BluetoothDevice>>> {
pub fn get_device_map(&self) -> &DomRefCell<HashMap<String, Dom<BluetoothDevice<TH>>>> {
&self.device_instance_map
}

// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
fn request_bluetooth_devices(&self,
p: &Rc<Promise>,
p: &Rc<Promise<TH>>,
filters: &Option<Vec<BluetoothLEScanFilterInit>>,
optional_services: &Option<Vec<BluetoothServiceUUID>>,
sender: IpcSender<BluetoothResponseResult>) {
@@ -168,7 +170,7 @@ impl Bluetooth {
// Step 2.4.
for filter in filters {
// Step 2.4.1.
match canonicalize_filter(&filter) {
match canonicalize_filter::<TH>(&filter) {
// Step 2.4.2.
Ok(f) => uuid_filters.push(f),
Err(e) => {
@@ -184,7 +186,7 @@ impl Bluetooth {
if let &Some(ref opt_services) = optional_services {
for opt_service in opt_services {
// Step 2.5 - 2.6.
let uuid = match BluetoothUUID::service(opt_service.clone()) {
let uuid = match BluetoothUUID::<TH>::service(opt_service.clone()) {
Ok(u) => u.to_string(),
Err(e) => {
p.reject_error(e);
@@ -205,7 +207,7 @@ impl Bluetooth {
ServiceUUIDSequence::new(optional_services_uuids));

// Step 4 - 5.
if let PermissionState::Denied = get_descriptor_permission_state(PermissionName::Bluetooth, None) {
if let PermissionState::Denied = get_descriptor_permission_state::<TH>(PermissionName::Bluetooth, None) {
return p.reject_error(Error::NotFound);
}

@@ -215,24 +217,25 @@ impl Bluetooth {
}
}

pub fn response_async<T: AsyncBluetoothListener + DomObject + 'static>(
promise: &Rc<Promise>,
pub fn response_async<T: AsyncBluetoothListener<TH> + DomObject + 'static, TH: TypeHolderTrait>(
promise: &Rc<Promise<TH>>,
receiver: &T) -> IpcSender<BluetoothResponseResult> {
let (action_sender, action_receiver) = ipc::channel().unwrap();
let task_source = receiver.global().networking_task_source();
let context = Arc::new(Mutex::new(BluetoothContext {
promise: Some(TrustedPromise::new(promise.clone())),
promise: Some(TrustedPromise::<TH>::new(promise.clone())),
receiver: Trusted::new(receiver),
}));
ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| {
struct ListenerTask<T: AsyncBluetoothListener + DomObject> {
context: Arc<Mutex<BluetoothContext<T>>>,
struct ListenerTask<T: AsyncBluetoothListener<TH> + DomObject, TH: TypeHolderTrait> {
context: Arc<Mutex<BluetoothContext<T, TH>>>,
action: BluetoothResponseResult,
}

impl<T> TaskOnce for ListenerTask<T>
impl<T, TH> TaskOnce for ListenerTask<T, TH>
where
T: AsyncBluetoothListener + DomObject,
T: AsyncBluetoothListener<TH> + DomObject,
TH: TypeHolderTrait
{
fn run_once(self) {
let mut context = self.context.lock().unwrap();
@@ -255,18 +258,18 @@ pub fn response_async<T: AsyncBluetoothListener + DomObject + 'static>(

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
pub fn get_gatt_children<T, F> (
pub fn get_gatt_children<T, F, TH: TypeHolderTrait> (
attribute: &T,
single: bool,
uuid_canonicalizer: F,
uuid: Option<StringOrUnsignedLong>,
instance_id: String,
connected: bool,
child_type: GATTType)
-> Rc<Promise>
where T: AsyncBluetoothListener + DomObject + 'static,
-> Rc<Promise<TH>>
where T: AsyncBluetoothListener<TH> + DomObject<TypeHolder=TH> + 'static,
F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID> {
let p = Promise::new(&attribute.global());
let p= Promise::<TH>::new(&attribute.global());

let result_uuid = if let Some(u) = uuid {
// Step 1.
@@ -304,7 +307,7 @@ pub fn get_gatt_children<T, F> (
}

// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothlescanfilterinit-canonicalizing
fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<BluetoothScanfilter> {
fn canonicalize_filter<TH: TypeHolderTrait>(filter: &BluetoothLEScanFilterInit) -> Fallible<BluetoothScanfilter> {
// Step 1.
if filter.services.is_none() &&
filter.name.is_none() &&
@@ -329,7 +332,7 @@ fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<Bluetooth

for service in services {
// Step 3.2 - 3.3.
let uuid = BluetoothUUID::service(service.clone())?.to_string();
let uuid = BluetoothUUID::<TH>::service(service.clone())?.to_string();

// Step 3.4.
if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) {
@@ -418,7 +421,7 @@ fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<Bluetooth
};

// Step 9.3 - 9.4.
let service = BluetoothUUID::service(service_name)?.to_string();
let service = BluetoothUUID::<TH>::service(service_name)?.to_string();

// Step 9.5.
if uuid_is_blocklisted(service.as_ref(), Blocklist::All) {
@@ -479,11 +482,11 @@ impl From<BluetoothError> for Error {
}
}

impl BluetoothMethods for Bluetooth {
impl<TH: TypeHolderTrait> BluetoothMethods<TH> for Bluetooth<TH> {
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
fn RequestDevice(&self, option: &RequestDeviceOptions) -> Rc<Promise> {
let p = Promise::new(&self.global());
fn RequestDevice(&self, option: &RequestDeviceOptions) -> Rc<Promise<TH>> {
let p = Promise::<TH>::new(&self.global());
// Step 1.
if (option.filters.is_some() && option.acceptAllDevices) ||
(option.filters.is_none() && !option.acceptAllDevices) {
@@ -500,8 +503,8 @@ impl BluetoothMethods for Bluetooth {

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability
fn GetAvailability(&self) -> Rc<Promise> {
let p = Promise::new(&self.global());
fn GetAvailability(&self) -> Rc<Promise<TH>> {
let p = Promise::<TH>::new(&self.global());
// Step 1. We did not override the method
// Step 2 - 3. in handle_response
let sender = response_async(&p, self);
@@ -514,8 +517,8 @@ impl BluetoothMethods for Bluetooth {
event_handler!(availabilitychanged, GetOnavailabilitychanged, SetOnavailabilitychanged);
}

impl AsyncBluetoothListener for Bluetooth {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>) {
impl<TH: TypeHolderTrait> AsyncBluetoothListener<TH> for Bluetooth<TH> {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise<TH>>) {
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
// Step 11, 13 - 14.
@@ -550,9 +553,9 @@ impl AsyncBluetoothListener for Bluetooth {
}
}

impl PermissionAlgorithm for Bluetooth {
impl<TH: TypeHolderTrait> PermissionAlgorithm<TH> for Bluetooth<TH> {
type Descriptor = BluetoothPermissionDescriptor;
type Status = BluetoothPermissionResult;
type Status = BluetoothPermissionResult<TH>;

#[allow(unsafe_code)]
fn create_descriptor(cx: *mut JSContext,
@@ -572,14 +575,14 @@ impl PermissionAlgorithm for Bluetooth {
// https://webbluetoothcg.github.io/web-bluetooth/#query-the-bluetooth-permission
fn permission_query(
_cx: *mut JSContext,
promise: &Rc<Promise>,
promise: &Rc<Promise<TH>>,
descriptor: &BluetoothPermissionDescriptor,
status: &BluetoothPermissionResult,
status: &BluetoothPermissionResult<TH>,
) {
// Step 1: We are not using the `global` variable.

// Step 2.
status.set_state(get_descriptor_permission_state(status.get_query(), None));
status.set_state(get_descriptor_permission_state::<TH>(status.get_query(), None));

// Step 3.
if let PermissionState::Denied = status.get_state() {
@@ -613,7 +616,7 @@ impl PermissionAlgorithm for Bluetooth {

// Step 6.2.1.
for filter in filters {
match canonicalize_filter(&filter) {
match canonicalize_filter::<TH>(&filter) {
Ok(f) => scan_filters.push(f),
Err(error) => return promise.reject_error(error),
}
@@ -654,9 +657,9 @@ impl PermissionAlgorithm for Bluetooth {
// https://webbluetoothcg.github.io/web-bluetooth/#request-the-bluetooth-permission
fn permission_request(
_cx: *mut JSContext,
promise: &Rc<Promise>,
promise: &Rc<Promise<TH>>,
descriptor: &BluetoothPermissionDescriptor,
status: &BluetoothPermissionResult,
status: &BluetoothPermissionResult<TH>,
) {
// Step 1.
if descriptor.filters.is_some() == descriptor.acceptAllDevices {
@@ -673,7 +676,7 @@ impl PermissionAlgorithm for Bluetooth {

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#revoke-bluetooth-access
fn permission_revoke(_descriptor: &BluetoothPermissionDescriptor, status: &BluetoothPermissionResult) {
fn permission_revoke(_descriptor: &BluetoothPermissionDescriptor, status: &BluetoothPermissionResult<TH>) {
// Step 1.
let global = status.global();
let allowed_devices = global.as_window().bluetooth_extra_permission_data().get_allowed_devices();
@@ -16,25 +16,26 @@ use dom::globalscope::GlobalScope;
use dom::window::Window;
use dom_struct::dom_struct;
use servo_atoms::Atom;
use typeholder::TypeHolderTrait;

// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothadvertisingevent
#[dom_struct]
pub struct BluetoothAdvertisingEvent {
event: Event,
device: Dom<BluetoothDevice>,
pub struct BluetoothAdvertisingEvent<TH: TypeHolderTrait + 'static> {
event: Event<TH>,
device: Dom<BluetoothDevice<TH>>,
name: Option<DOMString>,
appearance: Option<u16>,
tx_power: Option<i8>,
rssi: Option<i8>,
}

impl BluetoothAdvertisingEvent {
pub fn new_inherited(device: &BluetoothDevice,
impl<TH: TypeHolderTrait> BluetoothAdvertisingEvent<TH> {
pub fn new_inherited(device: &BluetoothDevice<TH>,
name: Option<DOMString>,
appearance: Option<u16>,
tx_power: Option<i8>,
rssi: Option<i8>)
-> BluetoothAdvertisingEvent {
-> BluetoothAdvertisingEvent<TH> {
BluetoothAdvertisingEvent {
event: Event::new_inherited(),
device: Dom::from_ref(device),
@@ -45,16 +46,15 @@ impl BluetoothAdvertisingEvent {
}
}

pub fn new(global: &GlobalScope,
type_: Atom,
pub fn new(global: &GlobalScope<TH>, type_: Atom,
bubbles: EventBubbles,
cancelable: EventCancelable,
device: &BluetoothDevice,
device: &BluetoothDevice<TH>,
name: Option<DOMString>,
appearance: Option<u16>,
txPower: Option<i8>,
rssi: Option<i8>)
-> DomRoot<BluetoothAdvertisingEvent> {
-> DomRoot<BluetoothAdvertisingEvent<TH>> {
let ev = reflect_dom_object(
Box::new(BluetoothAdvertisingEvent::new_inherited(
device,
@@ -67,18 +67,18 @@ impl BluetoothAdvertisingEvent {
BluetoothAdvertisingEventBinding::Wrap
);
{
let event = ev.upcast::<Event>();
let event = ev.upcast::<Event<TH>>();
event.init_event(type_, bool::from(bubbles), bool::from(cancelable));
}
ev
}

// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingevent-bluetoothadvertisingevent
pub fn Constructor(window: &Window,
pub fn Constructor(window: &Window<TH>,
type_: DOMString,
init: &BluetoothAdvertisingEventInit)
-> Fallible<DomRoot<BluetoothAdvertisingEvent>> {
let global = window.upcast::<GlobalScope>();
init: &BluetoothAdvertisingEventInit<TH>)
-> Fallible<DomRoot<BluetoothAdvertisingEvent<TH>>> {
let global = window.upcast::<GlobalScope<TH>>();
let device = init.device.r();
let name = init.name.clone();
let appearance = init.appearance.clone();
@@ -98,9 +98,9 @@ impl BluetoothAdvertisingEvent {
}
}

impl BluetoothAdvertisingEventMethods for BluetoothAdvertisingEvent {
impl<TH: TypeHolderTrait> BluetoothAdvertisingEventMethods<TH> for BluetoothAdvertisingEvent<TH> {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingevent-device
fn Device(&self) -> DomRoot<BluetoothDevice> {
fn Device(&self) -> DomRoot<BluetoothDevice<TH>> {
DomRoot::from_ref(&*self.device)
}

@@ -9,11 +9,13 @@ use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::root::DomRoot;
use dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use typeholder::TypeHolderTrait;
use std::marker::PhantomData;

// https://webbluetoothcg.github.io/web-bluetooth/#characteristicproperties
#[dom_struct]
pub struct BluetoothCharacteristicProperties {
reflector_: Reflector,
pub struct BluetoothCharacteristicProperties<TH: TypeHolderTrait + 'static> {
reflector_: Reflector<TH>,
broadcast: bool,
read: bool,
write_without_response: bool,
@@ -23,9 +25,10 @@ pub struct BluetoothCharacteristicProperties {
authenticated_signed_writes: bool,
reliable_write: bool,
writable_auxiliaries: bool,
_p: PhantomData<TH>,
}

impl BluetoothCharacteristicProperties {
impl<TH: TypeHolderTrait> BluetoothCharacteristicProperties<TH> {
pub fn new_inherited(broadcast: bool,
read: bool,
write_without_response: bool,
@@ -35,7 +38,7 @@ impl BluetoothCharacteristicProperties {
authenticated_signed_writes: bool,
reliable_write: bool,
writable_auxiliaries: bool)
-> BluetoothCharacteristicProperties {
-> BluetoothCharacteristicProperties<TH> {
BluetoothCharacteristicProperties {
reflector_: Reflector::new(),
broadcast: broadcast,
@@ -47,10 +50,11 @@ impl BluetoothCharacteristicProperties {
authenticated_signed_writes: authenticated_signed_writes,
reliable_write: reliable_write,
writable_auxiliaries: writable_auxiliaries,
_p: Default::default(),
}
}

pub fn new(global: &GlobalScope,
pub fn new(global: &GlobalScope<TH>,
broadcast: bool,
read: bool,
writeWithoutResponse: bool,
@@ -60,7 +64,7 @@ impl BluetoothCharacteristicProperties {
authenticatedSignedWrites: bool,
reliableWrite: bool,
writableAuxiliaries: bool)
-> DomRoot<BluetoothCharacteristicProperties> {
-> DomRoot<BluetoothCharacteristicProperties<TH>> {
reflect_dom_object(
Box::new(BluetoothCharacteristicProperties::new_inherited(
broadcast,
@@ -79,7 +83,7 @@ impl BluetoothCharacteristicProperties {
}
}

impl BluetoothCharacteristicPropertiesMethods for BluetoothCharacteristicProperties {
impl<TH: TypeHolderTrait> BluetoothCharacteristicPropertiesMethods for BluetoothCharacteristicProperties<TH> {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothcharacteristicproperties-broadcast
fn Broadcast(&self) -> bool {
self.broadcast
@@ -29,26 +29,27 @@ use profile_traits::ipc;
use std::cell::Cell;
use std::collections::HashMap;
use std::rc::Rc;
use typeholder::TypeHolderTrait;

// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothdevice
#[dom_struct]
pub struct BluetoothDevice {
eventtarget: EventTarget,
pub struct BluetoothDevice<TH: TypeHolderTrait + 'static> {
eventtarget: EventTarget<TH>,
id: DOMString,
name: Option<DOMString>,
gatt: MutNullableDom<BluetoothRemoteGATTServer>,
context: Dom<Bluetooth>,
attribute_instance_map: (DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTService>>>,
DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTCharacteristic>>>,
DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTDescriptor>>>),
gatt: MutNullableDom<BluetoothRemoteGATTServer<TH>>,
context: Dom<Bluetooth<TH>>,
attribute_instance_map: (DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTService<TH>>>>,
DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTCharacteristic<TH>>>>,
DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTDescriptor<TH>>>>),
watching_advertisements: Cell<bool>,
}

impl BluetoothDevice {
impl<TH: TypeHolderTrait> BluetoothDevice<TH> {
pub fn new_inherited(id: DOMString,
name: Option<DOMString>,
context: &Bluetooth)
-> BluetoothDevice {
context: &Bluetooth<TH>)
-> BluetoothDevice<TH> {
BluetoothDevice {
eventtarget: EventTarget::new_inherited(),
id: id,
@@ -62,30 +63,30 @@ impl BluetoothDevice {
}
}

pub fn new(global: &GlobalScope,
pub fn new(global: &GlobalScope<TH>,
id: DOMString,
name: Option<DOMString>,
context: &Bluetooth)
-> DomRoot<BluetoothDevice> {
context: &Bluetooth<TH>)
-> DomRoot<BluetoothDevice<TH>> {
reflect_dom_object(Box::new(BluetoothDevice::new_inherited(id, name, context)),
global,
BluetoothDeviceBinding::Wrap)
}

pub fn get_gatt(&self) -> DomRoot<BluetoothRemoteGATTServer> {
pub fn get_gatt(&self) -> DomRoot<BluetoothRemoteGATTServer<TH>> {
self.gatt.or_init(|| {
BluetoothRemoteGATTServer::new(&self.global(), self)
})
}

fn get_context(&self) -> DomRoot<Bluetooth> {
fn get_context(&self) -> DomRoot<Bluetooth<TH>> {
DomRoot::from_ref(&self.context)
}

pub fn get_or_create_service(&self,
service: &BluetoothServiceMsg,
server: &BluetoothRemoteGATTServer)
-> DomRoot<BluetoothRemoteGATTService> {
server: &BluetoothRemoteGATTServer<TH>)
-> DomRoot<BluetoothRemoteGATTService<TH>> {
let (ref service_map_ref, _, _) = self.attribute_instance_map;
let mut service_map = service_map_ref.borrow_mut();
if let Some(existing_service) = service_map.get(&service.instance_id) {
@@ -102,8 +103,8 @@ impl BluetoothDevice {

pub fn get_or_create_characteristic(&self,
characteristic: &BluetoothCharacteristicMsg,
service: &BluetoothRemoteGATTService)
-> DomRoot<BluetoothRemoteGATTCharacteristic> {
service: &BluetoothRemoteGATTService<TH>)
-> DomRoot<BluetoothRemoteGATTCharacteristic<TH>> {
let (_, ref characteristic_map_ref, _) = self.attribute_instance_map;
let mut characteristic_map = characteristic_map_ref.borrow_mut();
if let Some(existing_characteristic) = characteristic_map.get(&characteristic.instance_id) {
@@ -138,8 +139,8 @@ impl BluetoothDevice {

pub fn get_or_create_descriptor(&self,
descriptor: &BluetoothDescriptorMsg,
characteristic: &BluetoothRemoteGATTCharacteristic)
-> DomRoot<BluetoothRemoteGATTDescriptor> {
characteristic: &BluetoothRemoteGATTCharacteristic<TH>)
-> DomRoot<BluetoothRemoteGATTDescriptor<TH>> {
let (_, _, ref descriptor_map_ref) = self.attribute_instance_map;
let mut descriptor_map = descriptor_map_ref.borrow_mut();
if let Some(existing_descriptor) = descriptor_map.get(&descriptor.instance_id) {
@@ -184,7 +185,7 @@ impl BluetoothDevice {
BluetoothRequest::SetRepresentedToNull(service_ids, characteristic_ids, descriptor_ids));

// Step 8.
self.upcast::<EventTarget>().fire_bubbling_event(atom!("gattserverdisconnected"));
self.upcast::<EventTarget<TH>>().fire_bubbling_event(atom!("gattserverdisconnected"));
}

// https://webbluetoothcg.github.io/web-bluetooth/#garbage-collect-the-connection
@@ -212,7 +213,7 @@ impl BluetoothDevice {
}
}

impl BluetoothDeviceMethods for BluetoothDevice {
impl<TH: TypeHolderTrait> BluetoothDeviceMethods<TH> for BluetoothDevice<TH> {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-id
fn Id(&self) -> DOMString {
self.id.clone()
@@ -224,7 +225,7 @@ impl BluetoothDeviceMethods for BluetoothDevice {
}

// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-gatt
fn GetGatt(&self) -> Option<DomRoot<BluetoothRemoteGATTServer>> {
fn GetGatt(&self) -> Option<DomRoot<BluetoothRemoteGATTServer<TH>>> {
// Step 1.
if self.global().as_window().bluetooth_extra_permission_data()
.allowed_devices_contains_id(self.id.clone()) && !self.is_represented_device_null() {
@@ -236,8 +237,8 @@ impl BluetoothDeviceMethods for BluetoothDevice {

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements
fn WatchAdvertisements(&self) -> Rc<Promise> {
let p = Promise::new(&self.global());
fn WatchAdvertisements(&self) -> Rc<Promise<TH>> {
let p = Promise::<TH>::new(&self.global());
let sender = response_async(&p, self);
// TODO: Step 1.
// Note: Steps 2 - 3 are implemented in components/bluetooth/lib.rs in watch_advertisements function
@@ -263,8 +264,8 @@ impl BluetoothDeviceMethods for BluetoothDevice {
event_handler!(gattserverdisconnected, GetOngattserverdisconnected, SetOngattserverdisconnected);
}

impl AsyncBluetoothListener for BluetoothDevice {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>) {
impl<TH: TypeHolderTrait> AsyncBluetoothListener<TH> for BluetoothDevice<TH> {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise<TH>>) {
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-unwatchadvertisements
BluetoothResponse::WatchAdvertisements(_result) => {
@@ -21,17 +21,18 @@ use dom::promise::Promise;
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
use std::rc::Rc;
use typeholder::TypeHolderTrait;

// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothpermissionresult
#[dom_struct]
pub struct BluetoothPermissionResult {
status: PermissionStatus,
devices: DomRefCell<Vec<Dom<BluetoothDevice>>>,
pub struct BluetoothPermissionResult<TH: TypeHolderTrait + 'static> {
status: PermissionStatus<TH>,
devices: DomRefCell<Vec<Dom<BluetoothDevice<TH>>>>,
}

impl BluetoothPermissionResult {
impl<TH: TypeHolderTrait> BluetoothPermissionResult<TH> {
#[allow(unrooted_must_root)]
fn new_inherited(status: &PermissionStatus) -> BluetoothPermissionResult {
fn new_inherited(status: &PermissionStatus<TH>) -> BluetoothPermissionResult<TH> {
let result = BluetoothPermissionResult {
status: PermissionStatus::new_inherited(status.get_query()),
devices: DomRefCell::new(Vec::new()),
@@ -40,13 +41,13 @@ impl BluetoothPermissionResult {
result
}

pub fn new(global: &GlobalScope, status: &PermissionStatus) -> DomRoot<BluetoothPermissionResult> {
pub fn new(global: &GlobalScope<TH>,status: &PermissionStatus<TH>) -> DomRoot<BluetoothPermissionResult<TH>> {
reflect_dom_object(Box::new(BluetoothPermissionResult::new_inherited(status)),
global,
BluetoothPermissionResultBinding::Wrap)
}

pub fn get_bluetooth(&self) -> DomRoot<Bluetooth> {
pub fn get_bluetooth(&self) -> DomRoot<Bluetooth<TH>> {
self.global().as_window().Navigator().Bluetooth()
}

@@ -67,22 +68,22 @@ impl BluetoothPermissionResult {
}

#[allow(unrooted_must_root)]
pub fn set_devices(&self, devices: Vec<Dom<BluetoothDevice>>) {
pub fn set_devices(&self, devices: Vec<Dom<BluetoothDevice<TH>>>) {
*self.devices.borrow_mut() = devices;
}
}

impl BluetoothPermissionResultMethods for BluetoothPermissionResult {
impl<TH: TypeHolderTrait> BluetoothPermissionResultMethods<TH> for BluetoothPermissionResult<TH> {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothpermissionresult-devices
fn Devices(&self) -> Vec<DomRoot<BluetoothDevice>> {
let device_vec: Vec<DomRoot<BluetoothDevice>> =
fn Devices(&self) -> Vec<DomRoot<BluetoothDevice<TH>>> {
let device_vec: Vec<DomRoot<BluetoothDevice<TH>>> =
self.devices.borrow().iter().map(|d| DomRoot::from_ref(&**d)).collect();
device_vec
}
}

impl AsyncBluetoothListener for BluetoothPermissionResult {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>) {
impl<TH: TypeHolderTrait> AsyncBluetoothListener<TH> for BluetoothPermissionResult<TH> {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise<TH>>) {
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
// Step 3, 11, 13 - 14.
@@ -28,28 +28,29 @@ use dom::promise::Promise;
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
use std::rc::Rc;
use typeholder::TypeHolderTrait;

// Maximum length of an attribute value.
// https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 (Vol. 3, page 2169)
pub const MAXIMUM_ATTRIBUTE_LENGTH: usize = 512;

// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattcharacteristic
#[dom_struct]
pub struct BluetoothRemoteGATTCharacteristic {
eventtarget: EventTarget,
service: Dom<BluetoothRemoteGATTService>,
pub struct BluetoothRemoteGATTCharacteristic<TH: TypeHolderTrait + 'static> {
eventtarget: EventTarget<TH>,
service: Dom<BluetoothRemoteGATTService<TH>>,
uuid: DOMString,
properties: Dom<BluetoothCharacteristicProperties>,
properties: Dom<BluetoothCharacteristicProperties<TH>>,
value: DomRefCell<Option<ByteString>>,
instance_id: String,
}

impl BluetoothRemoteGATTCharacteristic {
pub fn new_inherited(service: &BluetoothRemoteGATTService,
impl<TH: TypeHolderTrait> BluetoothRemoteGATTCharacteristic<TH> {
pub fn new_inherited(service: &BluetoothRemoteGATTService<TH>,
uuid: DOMString,
properties: &BluetoothCharacteristicProperties,
properties: &BluetoothCharacteristicProperties<TH>,
instance_id: String)
-> BluetoothRemoteGATTCharacteristic {
-> BluetoothRemoteGATTCharacteristic<TH> {
BluetoothRemoteGATTCharacteristic {
eventtarget: EventTarget::new_inherited(),
service: Dom::from_ref(service),
@@ -60,12 +61,12 @@ impl BluetoothRemoteGATTCharacteristic {
}
}

pub fn new(global: &GlobalScope,
service: &BluetoothRemoteGATTService,
pub fn new(global: &GlobalScope<TH>,
service: &BluetoothRemoteGATTService<TH>,
uuid: DOMString,
properties: &BluetoothCharacteristicProperties,
properties: &BluetoothCharacteristicProperties<TH>,
instanceID: String)
-> DomRoot<BluetoothRemoteGATTCharacteristic> {
-> DomRoot<BluetoothRemoteGATTCharacteristic<TH>> {
reflect_dom_object(
Box::new(BluetoothRemoteGATTCharacteristic::new_inherited(
service, uuid, properties, instanceID
@@ -84,14 +85,14 @@ impl BluetoothRemoteGATTCharacteristic {
}
}

impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteristic {
impl<TH: TypeHolderTrait> BluetoothRemoteGATTCharacteristicMethods<TH> for BluetoothRemoteGATTCharacteristic<TH> {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-properties
fn Properties(&self) -> DomRoot<BluetoothCharacteristicProperties> {
fn Properties(&self) -> DomRoot<BluetoothCharacteristicProperties<TH>> {
DomRoot::from_ref(&self.properties)
}

// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-service
fn Service(&self) -> DomRoot<BluetoothRemoteGATTService> {
fn Service(&self) -> DomRoot<BluetoothRemoteGATTService<TH>> {
DomRoot::from_ref(&self.service)
}

@@ -102,17 +103,17 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc<Promise> {
get_gatt_children(self, true, BluetoothUUID::descriptor, Some(descriptor), self.get_instance_id(),
fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc<Promise<TH>> {
get_gatt_children(self, true, BluetoothUUID::<TH>::descriptor, Some(descriptor), self.get_instance_id(),
self.Service().Device().get_gatt().Connected(), GATTType::Descriptor)
}

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors
fn GetDescriptors(&self,
descriptor: Option<BluetoothDescriptorUUID>)
-> Rc<Promise> {
get_gatt_children(self, false, BluetoothUUID::descriptor, descriptor, self.get_instance_id(),
-> Rc<Promise<TH>> {
get_gatt_children(self, false, BluetoothUUID::<TH>::descriptor, descriptor, self.get_instance_id(),
self.Service().Device().get_gatt().Connected(), GATTType::Descriptor)
}

@@ -123,8 +124,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue
fn ReadValue(&self) -> Rc<Promise> {
let p = Promise::new(&self.global());
fn ReadValue(&self) -> Rc<Promise<TH>> {
let p = Promise::<TH>::new(&self.global());

// Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
@@ -156,8 +157,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer) -> Rc<Promise> {
let p = Promise::new(&self.global());
fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer) -> Rc<Promise<TH>> {
let p = Promise::<TH>::new(&self.global());

// Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) {
@@ -202,8 +203,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications
fn StartNotifications(&self) -> Rc<Promise> {
let p = Promise::new(&self.global());
fn StartNotifications(&self) -> Rc<Promise<TH>> {
let p = Promise::<TH>::new(&self.global());

// Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
@@ -238,8 +239,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-stopnotifications
fn StopNotifications(&self) -> Rc<Promise> {
let p = Promise::new(&self.global());
fn StopNotifications(&self) -> Rc<Promise<TH>> {
let p = Promise::<TH>::new(&self.global());
let sender = response_async(&p, self);

// TODO: Step 3 - 4: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic,
@@ -257,8 +258,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
event_handler!(characteristicvaluechanged, GetOncharacteristicvaluechanged, SetOncharacteristicvaluechanged);
}

impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>) {
impl<TH: TypeHolderTrait> AsyncBluetoothListener<TH> for BluetoothRemoteGATTCharacteristic<TH> {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise<TH>>) {
let device = self.Service().Device();
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
@@ -285,7 +286,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
*self.value.borrow_mut() = Some(value.clone());

// Step 5.5.3.
self.upcast::<EventTarget>().fire_bubbling_event(atom!("characteristicvaluechanged"));
self.upcast::<EventTarget<TH>>().fire_bubbling_event(atom!("characteristicvaluechanged"));

// Step 5.5.4.
promise.resolve_native(&value);
@@ -23,22 +23,23 @@ use dom::promise::Promise;
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
use std::rc::Rc;
use typeholder::TypeHolderTrait;

// http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor
#[dom_struct]
pub struct BluetoothRemoteGATTDescriptor {
reflector_: Reflector,
characteristic: Dom<BluetoothRemoteGATTCharacteristic>,
pub struct BluetoothRemoteGATTDescriptor<TH: TypeHolderTrait + 'static> {
reflector_: Reflector<TH>,
characteristic: Dom<BluetoothRemoteGATTCharacteristic<TH>>,
uuid: DOMString,
value: DomRefCell<Option<ByteString>>,
instance_id: String,
}

impl BluetoothRemoteGATTDescriptor {
pub fn new_inherited(characteristic: &BluetoothRemoteGATTCharacteristic,
impl<TH: TypeHolderTrait> BluetoothRemoteGATTDescriptor<TH> {
pub fn new_inherited(characteristic: &BluetoothRemoteGATTCharacteristic<TH>,
uuid: DOMString,
instance_id: String)
-> BluetoothRemoteGATTDescriptor {
-> BluetoothRemoteGATTDescriptor<TH> {
BluetoothRemoteGATTDescriptor {
reflector_: Reflector::new(),
characteristic: Dom::from_ref(characteristic),
@@ -48,11 +49,11 @@ impl BluetoothRemoteGATTDescriptor {
}
}

pub fn new(global: &GlobalScope,
characteristic: &BluetoothRemoteGATTCharacteristic,
pub fn new(global: &GlobalScope<TH>,
characteristic: &BluetoothRemoteGATTCharacteristic<TH>,
uuid: DOMString,
instanceID: String)
-> DomRoot<BluetoothRemoteGATTDescriptor>{
-> DomRoot<BluetoothRemoteGATTDescriptor<TH>>{
reflect_dom_object(
Box::new(BluetoothRemoteGATTDescriptor::new_inherited(
characteristic, uuid, instanceID
@@ -71,9 +72,9 @@ impl BluetoothRemoteGATTDescriptor {
}
}

impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
impl<TH: TypeHolderTrait> BluetoothRemoteGATTDescriptorMethods<TH> for BluetoothRemoteGATTDescriptor<TH> {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-characteristic
fn Characteristic(&self) -> DomRoot<BluetoothRemoteGATTCharacteristic> {
fn Characteristic(&self) -> DomRoot<BluetoothRemoteGATTCharacteristic<TH>> {
DomRoot::from_ref(&self.characteristic)
}

@@ -89,8 +90,8 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
fn ReadValue(&self) -> Rc<Promise> {
let p = Promise::new(&self.global());
fn ReadValue(&self) -> Rc<Promise<TH>> {
let p = Promise::<TH>::new(&self.global());

// Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
@@ -115,8 +116,8 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer) -> Rc<Promise> {
let p = Promise::new(&self.global());
fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer) -> Rc<Promise<TH>> {
let p = Promise::<TH>::new(&self.global());

// Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) {
@@ -150,8 +151,8 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
}
}

impl AsyncBluetoothListener for BluetoothRemoteGATTDescriptor {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>) {
impl<TH: TypeHolderTrait> AsyncBluetoothListener<TH> for BluetoothRemoteGATTDescriptor<TH> {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise<TH>>) {
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
BluetoothResponse::ReadValue(result) => {
@@ -19,25 +19,26 @@ use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
use std::cell::Cell;
use std::rc::Rc;
use typeholder::TypeHolderTrait;

// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattserver
#[dom_struct]
pub struct BluetoothRemoteGATTServer {
reflector_: Reflector,
device: Dom<BluetoothDevice>,
pub struct BluetoothRemoteGATTServer<TH: TypeHolderTrait + 'static> {
reflector_: Reflector<TH>,
device: Dom<BluetoothDevice<TH>>,
connected: Cell<bool>,
}

impl BluetoothRemoteGATTServer {
pub fn new_inherited(device: &BluetoothDevice) -> BluetoothRemoteGATTServer {
impl<TH: TypeHolderTrait> BluetoothRemoteGATTServer<TH> {
pub fn new_inherited(device: &BluetoothDevice<TH>) -> BluetoothRemoteGATTServer<TH> {
BluetoothRemoteGATTServer {
reflector_: Reflector::new(),
device: Dom::from_ref(device),
connected: Cell::new(false),
}
}

pub fn new(global: &GlobalScope, device: &BluetoothDevice) -> DomRoot<BluetoothRemoteGATTServer> {
pub fn new(global: &GlobalScope<TH>, device: &BluetoothDevice<TH>) -> DomRoot<BluetoothRemoteGATTServer<TH>> {
reflect_dom_object(Box::new(BluetoothRemoteGATTServer::new_inherited(device)),
global,
BluetoothRemoteGATTServerBinding::Wrap)
@@ -52,9 +53,9 @@ impl BluetoothRemoteGATTServer {
}
}

impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
impl<TH: TypeHolderTrait> BluetoothRemoteGATTServerMethods<TH> for BluetoothRemoteGATTServer<TH> {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-device
fn Device(&self) -> DomRoot<BluetoothDevice> {
fn Device(&self) -> DomRoot<BluetoothDevice<TH>> {
DomRoot::from_ref(&self.device)
}

@@ -65,9 +66,9 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
fn Connect(&self) -> Rc<Promise> {
fn Connect(&self) -> Rc<Promise<TH>> {
// Step 1.
let p = Promise::new(&self.global());
let p = Promise::<TH>::new(&self.global());
let sender = response_async(&p, self);

// TODO: Step 3: Check if the UA is currently using the Bluetooth system.
@@ -102,24 +103,24 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise> {
fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise<TH>> {
// Step 1 - 2.
get_gatt_children(self, true, BluetoothUUID::service, Some(service), String::from(self.Device().Id()),
get_gatt_children(self, true, BluetoothUUID::<TH>::service, Some(service), String::from(self.Device().Id()),
self.Device().get_gatt().Connected(), GATTType::PrimaryService)
}

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
fn GetPrimaryServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> {
fn GetPrimaryServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise<TH>> {
// Step 1 - 2.
get_gatt_children(self, false, BluetoothUUID::service, service, String::from(self.Device().Id()),
get_gatt_children(self, false, BluetoothUUID::<TH>::service, service, String::from(self.Device().Id()),
self.Connected(), GATTType::PrimaryService)

}
}

impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>) {
impl<TH: TypeHolderTrait> AsyncBluetoothListener<TH> for BluetoothRemoteGATTServer<TH> {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise<TH>>) {
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
BluetoothResponse::GATTServerConnect(connected) => {
@@ -18,23 +18,24 @@ use dom::globalscope::GlobalScope;
use dom::promise::Promise;
use dom_struct::dom_struct;
use std::rc::Rc;
use typeholder::TypeHolderTrait;

// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
#[dom_struct]
pub struct BluetoothRemoteGATTService {
eventtarget: EventTarget,
device: Dom<BluetoothDevice>,
pub struct BluetoothRemoteGATTService<TH: TypeHolderTrait + 'static> {
eventtarget: EventTarget<TH>,
device: Dom<BluetoothDevice<TH>>,
uuid: DOMString,
is_primary: bool,
instance_id: String,
}

impl BluetoothRemoteGATTService {
pub fn new_inherited(device: &BluetoothDevice,
impl<TH: TypeHolderTrait> BluetoothRemoteGATTService<TH> {
pub fn new_inherited(device: &BluetoothDevice<TH>,
uuid: DOMString,
is_primary: bool,
instance_id: String)
-> BluetoothRemoteGATTService {
-> BluetoothRemoteGATTService<TH> {
BluetoothRemoteGATTService {
eventtarget: EventTarget::new_inherited(),
device: Dom::from_ref(device),
@@ -44,12 +45,12 @@ impl BluetoothRemoteGATTService {
}
}

pub fn new(global: &GlobalScope,
device: &BluetoothDevice,
pub fn new(global: &GlobalScope<TH>,
device: &BluetoothDevice<TH>,
uuid: DOMString,
isPrimary: bool,
instanceID: String)
-> DomRoot<BluetoothRemoteGATTService> {
-> DomRoot<BluetoothRemoteGATTService<TH>> {
reflect_dom_object(
Box::new(BluetoothRemoteGATTService::new_inherited(
device, uuid, isPrimary, instanceID
@@ -64,9 +65,9 @@ impl BluetoothRemoteGATTService {
}
}

impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
impl<TH: TypeHolderTrait> BluetoothRemoteGATTServiceMethods<TH> for BluetoothRemoteGATTService<TH> {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-device
fn Device(&self) -> DomRoot<BluetoothDevice> {
fn Device(&self) -> DomRoot<BluetoothDevice<TH>> {
DomRoot::from_ref(&self.device)
}

@@ -84,26 +85,26 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic
fn GetCharacteristic(&self,
characteristic: BluetoothCharacteristicUUID)
-> Rc<Promise> {
get_gatt_children(self, true, BluetoothUUID::characteristic, Some(characteristic), self.get_instance_id(),
-> Rc<Promise<TH>> {
get_gatt_children(self, true, BluetoothUUID::<TH>::characteristic, Some(characteristic), self.get_instance_id(),
self.Device().get_gatt().Connected(), GATTType::Characteristic)
}

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
fn GetCharacteristics(&self,
characteristic: Option<BluetoothCharacteristicUUID>)
-> Rc<Promise> {
get_gatt_children(self, false, BluetoothUUID::characteristic, characteristic, self.get_instance_id(),
-> Rc<Promise<TH>> {
get_gatt_children(self, false, BluetoothUUID::<TH>::characteristic, characteristic, self.get_instance_id(),
self.Device().get_gatt().Connected(), GATTType::Characteristic)
}

#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice
fn GetIncludedService(&self,
service: BluetoothServiceUUID)
-> Rc<Promise> {
get_gatt_children(self, false, BluetoothUUID::service, Some(service), self.get_instance_id(),
-> Rc<Promise<TH>> {
get_gatt_children(self, false, BluetoothUUID::<TH>::service, Some(service), self.get_instance_id(),
self.Device().get_gatt().Connected(), GATTType::IncludedService)
}

@@ -112,8 +113,8 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
fn GetIncludedServices(&self,
service: Option<BluetoothServiceUUID>)
-> Rc<Promise> {
get_gatt_children(self, false, BluetoothUUID::service, service, self.get_instance_id(),
-> Rc<Promise<TH>> {
get_gatt_children(self, false, BluetoothUUID::<TH>::service, service, self.get_instance_id(),
self.Device().get_gatt().Connected(), GATTType::IncludedService)
}

@@ -127,8 +128,8 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
event_handler!(serviceremoved, GetOnserviceremoved, SetOnserviceremoved);
}

impl AsyncBluetoothListener for BluetoothRemoteGATTService {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>) {
impl<TH: TypeHolderTrait> AsyncBluetoothListener<TH> for BluetoothRemoteGATTService<TH> {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise<TH>>) {
let device = self.Device();
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
@@ -10,6 +10,8 @@ use dom::bindings::str::DOMString;
use dom::window::Window;
use dom_struct::dom_struct;
use regex::Regex;
use typeholder::TypeHolderTrait;
use std::marker::PhantomData;

pub type UUID = DOMString;
pub type BluetoothServiceUUID = StringOrUnsignedLong;
@@ -18,8 +20,8 @@ pub type BluetoothDescriptorUUID = StringOrUnsignedLong;

// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothuuid
#[dom_struct]
pub struct BluetoothUUID {
reflector_: Reflector,
pub struct BluetoothUUID<TH: TypeHolderTrait + 'static> {
reflector_: Reflector<TH>,
}

//https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
@@ -282,29 +284,29 @@ const CHARACTERISTIC_ERROR_MESSAGE: &'static str = "https://developer.bluetooth.
const DESCRIPTOR_ERROR_MESSAGE: &'static str = "https://developer.bluetooth.org/gatt/descriptors/Pages/\
DescriptorsHomePage.aspx\ne.g. 'gatt.characteristic_presentation_format'.";

impl BluetoothUUID {
impl<TH: TypeHolderTrait> BluetoothUUID<TH> {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-canonicaluuid
pub fn CanonicalUUID(_: &Window, alias: u32) -> UUID {
pub fn CanonicalUUID(_: &Window<TH>, alias: u32) -> UUID {
canonical_uuid(alias)
}

// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getservice
pub fn GetService(_: &Window, name: BluetoothServiceUUID) -> Fallible<UUID> {
pub fn GetService(_: &Window<TH>, name: BluetoothServiceUUID) -> Fallible<UUID> {
Self::service(name)
}

// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getcharacteristic
pub fn GetCharacteristic(_: &Window, name: BluetoothCharacteristicUUID) -> Fallible<UUID> {
pub fn GetCharacteristic(_: &Window<TH>, name: BluetoothCharacteristicUUID) -> Fallible<UUID> {
Self::characteristic(name)
}

// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getdescriptor
pub fn GetDescriptor(_: &Window, name: BluetoothDescriptorUUID) -> Fallible<UUID> {
pub fn GetDescriptor(_: &Window<TH>, name: BluetoothDescriptorUUID) -> Fallible<UUID> {
Self::descriptor(name)
}
}

impl BluetoothUUID {
impl<TH: TypeHolderTrait> BluetoothUUID<TH> {
pub fn service(name: BluetoothServiceUUID) -> Fallible<UUID> {
resolve_uuid_name(name, BLUETOOTH_ASSIGNED_SERVICES, SERVICE_PREFIX)
}
@@ -15,13 +15,16 @@ use dom::bindings::root::DomRoot;
use dom::bindings::str::DOMString;
use dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use typeholder::TypeHolderTrait;
use std::marker::PhantomData;

// https://html.spec.whatwg.org/multipage/#canvasgradient
#[dom_struct]
pub struct CanvasGradient {
reflector_: Reflector,
pub struct CanvasGradient<TH: TypeHolderTrait + 'static> {
reflector_: Reflector<TH>,
style: CanvasGradientStyle,
stops: DomRefCell<Vec<CanvasGradientStop>>,
_p: PhantomData<TH>,
}

#[derive(Clone, JSTraceable, MallocSizeOf)]
@@ -30,23 +33,24 @@ pub enum CanvasGradientStyle {
Radial(RadialGradientStyle),
}

impl CanvasGradient {
fn new_inherited(style: CanvasGradientStyle) -> CanvasGradient {
impl<TH: TypeHolderTrait> CanvasGradient<TH> {
fn new_inherited(style: CanvasGradientStyle) -> CanvasGradient<TH> {
CanvasGradient {
reflector_: Reflector::new(),
style: style,
stops: DomRefCell::new(Vec::new()),
_p: Default::default(),
}
}

pub fn new(global: &GlobalScope, style: CanvasGradientStyle) -> DomRoot<CanvasGradient> {
pub fn new(global: &GlobalScope<TH>, style: CanvasGradientStyle) -> DomRoot<CanvasGradient<TH>> {
reflect_dom_object(Box::new(CanvasGradient::new_inherited(style)),
global,
CanvasGradientBinding::Wrap)
}
}

impl CanvasGradientMethods for CanvasGradient {
impl<TH: TypeHolderTrait> CanvasGradientMethods for CanvasGradient<TH> {
// https://html.spec.whatwg.org/multipage/#dom-canvasgradient-addcolorstop
fn AddColorStop(&self, offset: Finite<f64>, color: DOMString) -> ErrorResult {
if *offset < 0f64 || *offset > 1f64 {
@@ -78,7 +82,7 @@ pub trait ToFillOrStrokeStyle {
fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle;
}

impl<'a> ToFillOrStrokeStyle for &'a CanvasGradient {
impl<'a, TH: TypeHolderTrait> ToFillOrStrokeStyle for &'a CanvasGradient<TH> {
fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle {
let gradient_stops = self.stops.borrow().clone();
match self.style {
@@ -10,24 +10,27 @@ use dom::canvasgradient::ToFillOrStrokeStyle;
use dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use euclid::Size2D;
use typeholder::TypeHolderTrait;
use std::marker::PhantomData;

// https://html.spec.whatwg.org/multipage/#canvaspattern
#[dom_struct]
pub struct CanvasPattern {
reflector_: Reflector,
pub struct CanvasPattern<TH: TypeHolderTrait + 'static> {
reflector_: Reflector<TH>,
surface_data: Vec<u8>,
surface_size: Size2D<i32>,
repeat_x: bool,
repeat_y: bool,
origin_clean: bool,
_p: PhantomData<TH>,
}

impl CanvasPattern {
impl<TH: TypeHolderTrait> CanvasPattern<TH> {
fn new_inherited(surface_data: Vec<u8>,
surface_size: Size2D<i32>,
repeat: RepetitionStyle,
origin_clean: bool)
-> CanvasPattern {
-> CanvasPattern<TH> {
let (x, y) = match repeat {
RepetitionStyle::Repeat => (true, true),
RepetitionStyle::RepeatX => (true, false),
@@ -42,14 +45,15 @@ impl CanvasPattern {
repeat_x: x,
repeat_y: y,
origin_clean: origin_clean,
_p: Default::default(),
}
}
pub fn new(global: &GlobalScope,
pub fn new(global: &GlobalScope<TH>,
surface_data: Vec<u8>,
surface_size: Size2D<i32>,
repeat: RepetitionStyle,
origin_clean: bool)
-> DomRoot<CanvasPattern> {
-> DomRoot<CanvasPattern<TH>> {
reflect_dom_object(
Box::new(CanvasPattern::new_inherited(
surface_data, surface_size, repeat, origin_clean
@@ -63,7 +67,7 @@ impl CanvasPattern {
}
}

impl<'a> ToFillOrStrokeStyle for &'a CanvasPattern {
impl<'a, TH: TypeHolderTrait> ToFillOrStrokeStyle for &'a CanvasPattern<TH> {
fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle {
FillOrStrokeStyle::Surface(SurfaceStyle::new(self.surface_data.clone(),
self.surface_size,
@@ -49,46 +49,47 @@ use std::cell::Cell;
use std::str::FromStr;
use std::sync::Arc;
use unpremultiplytable::UNPREMULTIPLY_TABLE;
use typeholder::TypeHolderTrait;

#[must_root]
#[derive(Clone, JSTraceable, MallocSizeOf)]
#[allow(dead_code)]
enum CanvasFillOrStrokeStyle {
enum CanvasFillOrStrokeStyle<TH: TypeHolderTrait + 'static> {
Color(RGBA),
Gradient(Dom<CanvasGradient>),
Pattern(Dom<CanvasPattern>),
Gradient(Dom<CanvasGradient<TH>>),
Pattern(Dom<CanvasPattern<TH>>),
}

// https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d
#[dom_struct]
pub struct CanvasRenderingContext2D {
reflector_: Reflector,
pub struct CanvasRenderingContext2D<TH: TypeHolderTrait + 'static> {
reflector_: Reflector<TH>,
#[ignore_malloc_size_of = "Defined in ipc-channel"]
ipc_renderer: IpcSender<CanvasMsg>,
/// For rendering contexts created by an HTML canvas element, this is Some,
/// for ones created by a paint worklet, this is None.
canvas: Option<Dom<HTMLCanvasElement>>,
canvas: Option<Dom<HTMLCanvasElement<TH>>>,
#[ignore_malloc_size_of = "Arc"]
image_cache: Arc<ImageCache>,
/// Any missing image URLs.
missing_image_urls: DomRefCell<Vec<ServoUrl>>,
/// The base URL for resolving CSS image URL values.
/// Needed because of https://github.com/servo/servo/issues/17625
base_url: ServoUrl,
state: DomRefCell<CanvasContextState>,
saved_states: DomRefCell<Vec<CanvasContextState>>,
state: DomRefCell<CanvasContextState<TH>>,
saved_states: DomRefCell<Vec<CanvasContextState<TH>>>,
origin_clean: Cell<bool>,
canvas_id: CanvasId,
}

#[must_root]
#[derive(Clone, JSTraceable, MallocSizeOf)]
struct CanvasContextState {
struct CanvasContextState<TH: TypeHolderTrait + 'static> {
global_alpha: f64,
global_composition: CompositionOrBlending,
image_smoothing_enabled: bool,
fill_style: CanvasFillOrStrokeStyle,
stroke_style: CanvasFillOrStrokeStyle,
fill_style: CanvasFillOrStrokeStyle<TH>,
stroke_style: CanvasFillOrStrokeStyle<TH>,
line_width: f64,
line_cap: LineCapStyle,
line_join: LineJoinStyle,
@@ -100,8 +101,8 @@ struct CanvasContextState {
shadow_color: RGBA,
}

impl CanvasContextState {
fn new() -> CanvasContextState {
impl<TH: TypeHolderTrait> CanvasContextState<TH> {
fn new() -> CanvasContextState<TH> {
let black = RGBA::new(0, 0, 0, 255);
CanvasContextState {
global_alpha: 1.0,
@@ -122,13 +123,13 @@ impl CanvasContextState {
}
}

impl CanvasRenderingContext2D {
pub fn new_inherited(global: &GlobalScope,
canvas: Option<&HTMLCanvasElement>,
impl<TH: TypeHolderTrait> CanvasRenderingContext2D<TH> {
pub fn new_inherited(global: &GlobalScope<TH>,
canvas: Option<&HTMLCanvasElement<TH>>,
image_cache: Arc<ImageCache>,
base_url: ServoUrl,
size: Size2D<i32>)
-> CanvasRenderingContext2D {
-> Self {
debug!("Creating new canvas rendering context.");
let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
let script_to_constellation_chan = global.script_to_constellation_chan();
@@ -150,10 +151,10 @@ impl CanvasRenderingContext2D {
}
}

pub fn new(global: &GlobalScope,
canvas: &HTMLCanvasElement,
pub fn new(global: &GlobalScope<TH>,
canvas: &HTMLCanvasElement<TH>,
size: Size2D<i32>)
-> DomRoot<CanvasRenderingContext2D> {
-> DomRoot<Self> {
let window = window_from_node(canvas);
let image_cache = window.image_cache();
let base_url = window.get_url();
@@ -179,7 +180,7 @@ impl CanvasRenderingContext2D {

fn mark_as_dirty(&self) {
if let Some(ref canvas) = self.canvas {
canvas.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
canvas.upcast::<Node<TH>>().dirty(NodeDamage::OtherNodeDamage);
}
}

@@ -240,7 +241,7 @@ impl CanvasRenderingContext2D {

// https://html.spec.whatwg.org/multipage/#the-image-argument-is-not-origin-clean
fn is_origin_clean(&self,
image: CanvasImageSource)
image: CanvasImageSource<TH>)
-> bool {
match image {
CanvasImageSource::HTMLCanvasElement(canvas) => {
@@ -250,7 +251,7 @@ impl CanvasRenderingContext2D {
image.origin_is_clean(),
CanvasImageSource::HTMLImageElement(image) => {
let image_origin = image.get_origin().expect("Image's origin is missing");
image_origin.same_origin(GlobalScope::entry().origin())
image_origin.same_origin(GlobalScope::<TH>::entry().origin())
}
CanvasImageSource::CSSStyleValue(_) => true,
}
@@ -278,7 +279,7 @@ impl CanvasRenderingContext2D {
//
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn draw_image(&self,
image: CanvasImageSource,
image: CanvasImageSource<TH>,
sx: f64,
sy: f64,
sw: Option<f64>,
@@ -323,7 +324,7 @@ impl CanvasRenderingContext2D {
}

fn draw_html_canvas_element(&self,
canvas: &HTMLCanvasElement,
canvas: &HTMLCanvasElement<TH>,
sx: f64,
sy: f64,
sw: Option<f64>,
@@ -543,7 +544,7 @@ impl CanvasRenderingContext2D {
Some(ref canvas) => &**canvas,
};

let canvas_element = canvas.upcast::<Element>();
let canvas_element = canvas.upcast::<Element<TH>>();

match canvas_element.style() {
Some(ref s) if canvas_element.has_css_layout_box() => Ok(s.get_color().color),
@@ -585,7 +586,7 @@ pub trait LayoutCanvasRenderingContext2DHelpers {
unsafe fn get_canvas_id(&self) -> CanvasId;
}

impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<CanvasRenderingContext2D> {
impl<TH: TypeHolderTrait> LayoutCanvasRenderingContext2DHelpers for LayoutDom<CanvasRenderingContext2D<TH>> {
#[allow(unsafe_code)]
unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
(*self.unsafe_get()).ipc_renderer.clone()
@@ -606,9 +607,9 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<CanvasRenderingContext2
// Restricted values are guarded in glue code. Therefore we need not add a guard.
//
// FIXME: this behavior should might be generated by some annotattions to idl.
impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
impl<TH: TypeHolderTrait> CanvasRenderingContext2DMethods<TH> for CanvasRenderingContext2D<TH> {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas
fn Canvas(&self) -> DomRoot<HTMLCanvasElement> {
fn Canvas(&self) -> DomRoot<HTMLCanvasElement<TH>> {
// This method is not called from a paint worklet rendering context,
// so it's OK to panic if self.canvas is None.
DomRoot::from_ref(self.canvas.as_ref().expect("No canvas."))
@@ -804,7 +805,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {

// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage(&self,
image: CanvasImageSource,
image: CanvasImageSource<TH>,
dx: f64,
dy: f64)
-> ErrorResult {
@@ -817,7 +818,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {

// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage_(&self,
image: CanvasImageSource,
image: CanvasImageSource<TH>,
dx: f64,
dy: f64,
dw: f64,
@@ -832,7 +833,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {

// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage__(&self,
image: CanvasImageSource,
image: CanvasImageSource<TH>,
sx: f64,
sy: f64,
sw: f64,
@@ -971,7 +972,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern<TH> {
match self.state.borrow().stroke_style {
CanvasFillOrStrokeStyle::Color(ref rgba) => {
let mut result = String::new();
@@ -988,7 +989,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern<TH>) {
match value {
StringOrCanvasGradientOrCanvasPattern::String(string) => {
if let Ok(rgba) = self.parse_color(&string) {
@@ -1014,7 +1015,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern<TH> {
match self.state.borrow().fill_style {
CanvasFillOrStrokeStyle::Color(ref rgba) => {
let mut result = String::new();
@@ -1031,7 +1032,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern<TH>) {
match value {
StringOrCanvasGradientOrCanvasPattern::String(string) => {
if let Ok(rgba) = self.parse_color(&string) {
@@ -1057,7 +1058,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
fn CreateImageData(&self, sw: Finite<f64>, sh: Finite<f64>) -> Fallible<DomRoot<ImageData>> {
fn CreateImageData(&self, sw: Finite<f64>, sh: Finite<f64>) -> Fallible<DomRoot<ImageData<TH>>> {
if *sw == 0.0 || *sh == 0.0 {
return Err(Error::IndexSize);
}
@@ -1068,7 +1069,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible<DomRoot<ImageData>> {
fn CreateImageData_(&self, imagedata: &ImageData<TH>) -> Fallible<DomRoot<ImageData<TH>>> {
ImageData::new(&self.global(),
imagedata.Width(),
imagedata.Height(),
@@ -1081,7 +1082,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
sy: Finite<f64>,
sw: Finite<f64>,
sh: Finite<f64>)
-> Fallible<DomRoot<ImageData>> {
-> Fallible<DomRoot<ImageData<TH>>> {
if !self.origin_is_clean() {
return Err(Error::Security)
}
@@ -1127,7 +1128,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
fn PutImageData(&self, imagedata: &ImageData, dx: Finite<f64>, dy: Finite<f64>) {
fn PutImageData(&self, imagedata: &ImageData<TH>, dx: Finite<f64>, dy: Finite<f64>) {
self.PutImageData_(imagedata,
dx,
dy,
@@ -1139,7 +1140,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {

// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
fn PutImageData_(&self,
imagedata: &ImageData,
imagedata: &ImageData<TH>,
dx: Finite<f64>,
dy: Finite<f64>,
dirty_x: Finite<f64>,
@@ -1165,7 +1166,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
y0: Finite<f64>,
x1: Finite<f64>,
y1: Finite<f64>)
-> DomRoot<CanvasGradient> {
-> DomRoot<CanvasGradient<TH>> {
CanvasGradient::new(&self.global(),
CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0,
*y0,
@@ -1182,7 +1183,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
x1: Finite<f64>,
y1: Finite<f64>,
r1: Finite<f64>)
-> Fallible<DomRoot<CanvasGradient>> {
-> Fallible<DomRoot<CanvasGradient<TH>>> {
if *r0 < 0. || *r1 < 0. {
return Err(Error::IndexSize);
}
@@ -1199,9 +1200,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {

// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
fn CreatePattern(&self,
image: CanvasImageSource,
image: CanvasImageSource<TH>,
mut repetition: DOMString)
-> Fallible<DomRoot<CanvasPattern>> {
-> Fallible<DomRoot<CanvasPattern<TH>>> {
let (image_data, image_size) = match image {
CanvasImageSource::HTMLImageElement(ref image) => {
// https://html.spec.whatwg.org/multipage/#img-error
@@ -1374,7 +1375,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}
}

impl Drop for CanvasRenderingContext2D {
impl<TH: TypeHolderTrait> Drop for CanvasRenderingContext2D<TH> {
fn drop(&mut self) {
if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close(self.get_canvas_id())) {
warn!("Could not close canvas: {}", err)
@@ -24,29 +24,30 @@ use dom::virtualmethods::vtable_for;
use dom_struct::dom_struct;
use servo_config::opts;
use std::cell::Ref;
use typeholder::TypeHolderTrait;

// https://dom.spec.whatwg.org/#characterdata
#[dom_struct]
pub struct CharacterData {
node: Node,
pub struct CharacterData<TH: TypeHolderTrait + 'static> {
node: Node<TH>,
data: DomRefCell<DOMString>,
}

impl CharacterData {
pub fn new_inherited(data: DOMString, document: &Document) -> CharacterData {
impl<TH: TypeHolderTrait> CharacterData<TH> {
pub fn new_inherited(data: DOMString, document: &Document<TH>) -> Self {
CharacterData {
node: Node::new_inherited(document),
node: Node::<TH>::new_inherited(document),
data: DomRefCell::new(data),
}
}

pub fn clone_with_data(&self, data: DOMString, document: &Document) -> DomRoot<Node> {
match self.upcast::<Node>().type_id() {
pub fn clone_with_data(&self, data: DOMString, document: &Document<TH>) -> DomRoot<Node<TH>> {
match self.upcast::<Node<TH>>().type_id() {
NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => {
DomRoot::upcast(Comment::new(data, &document))
}
NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
let pi = self.downcast::<ProcessingInstruction>().unwrap();
let pi = self.downcast::<ProcessingInstruction<TH>>().unwrap();
DomRoot::upcast(ProcessingInstruction::new(pi.Target(), data, &document))
},
NodeTypeId::CharacterData(CharacterDataTypeId::Text) => {
@@ -68,13 +69,13 @@ impl CharacterData {
}

fn content_changed(&self) {
let node = self.upcast::<Node>();
let node = self.upcast::<Node<TH>>();
node.dirty(NodeDamage::OtherNodeDamage);

// If this is a Text node, we might need to re-parse (say, if our parent
// is a <style> element.) We don't need to if this is a Comment or
// ProcessingInstruction.
if self.is::<Text>() {
if self.is::<Text<TH>>() {
if let Some(parent_node) = node.GetParentNode() {
let mutation = ChildrenMutation::ChangeText;
vtable_for(&parent_node).children_changed(&mutation);
@@ -83,7 +84,7 @@ impl CharacterData {
}
}

impl CharacterDataMethods for CharacterData {
impl<TH: TypeHolderTrait> CharacterDataMethods<TH> for CharacterData<TH> {
// https://dom.spec.whatwg.org/#dom-characterdata-data
fn Data(&self) -> DOMString {
self.data.borrow().clone()
@@ -95,7 +96,7 @@ impl CharacterDataMethods for CharacterData {
let new_length = data.encode_utf16().count() as u32;
*self.data.borrow_mut() = data;
self.content_changed();
let node = self.upcast::<Node>();
let node = self.upcast::<Node<TH>>();
node.ranges().replace_code_units(node, 0, old_length, new_length);
}

@@ -209,41 +210,41 @@ impl CharacterDataMethods for CharacterData {
*self.data.borrow_mut() = DOMString::from(new_data);
self.content_changed();
// Steps 8-11.
let node = self.upcast::<Node>();
let node = self.upcast::<Node<TH>>();
node.ranges().replace_code_units(
node, offset, count, arg.encode_utf16().count() as u32);
Ok(())
}

// https://dom.spec.whatwg.org/#dom-childnode-before
fn Before(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
self.upcast::<Node>().before(nodes)
fn Before(&self, nodes: Vec<NodeOrString<TH>>) -> ErrorResult {
self.upcast::<Node<TH>>().before(nodes)
}

// https://dom.spec.whatwg.org/#dom-childnode-after
fn After(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
self.upcast::<Node>().after(nodes)
fn After(&self, nodes: Vec<NodeOrString<TH>>) -> ErrorResult {
self.upcast::<Node<TH>>().after(nodes)
}

// https://dom.spec.whatwg.org/#dom-childnode-replacewith
fn ReplaceWith(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
self.upcast::<Node>().replace_with(nodes)
fn ReplaceWith(&self, nodes: Vec<NodeOrString<TH>>) -> ErrorResult {
self.upcast::<Node<TH>>().replace_with(nodes)
}

// https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(&self) {
let node = self.upcast::<Node>();
let node = self.upcast::<Node<TH>>();
node.remove_self();
}

// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling
fn GetPreviousElementSibling(&self) -> Option<DomRoot<Element>> {
self.upcast::<Node>().preceding_siblings().filter_map(DomRoot::downcast).next()
fn GetPreviousElementSibling(&self) -> Option<DomRoot<Element<TH>>> {
self.upcast::<Node<TH>>().preceding_siblings().filter_map(DomRoot::downcast).next()
}

// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling
fn GetNextElementSibling(&self) -> Option<DomRoot<Element>> {
self.upcast::<Node>().following_siblings().filter_map(DomRoot::downcast).next()
fn GetNextElementSibling(&self) -> Option<DomRoot<Element<TH>>> {
self.upcast::<Node<TH>>().following_siblings().filter_map(DomRoot::downcast).next()
}
}

@@ -253,7 +254,7 @@ pub trait LayoutCharacterDataHelpers {
}

#[allow(unsafe_code)]
impl LayoutCharacterDataHelpers for LayoutDom<CharacterData> {
impl<TH: TypeHolderTrait> LayoutCharacterDataHelpers for LayoutDom<CharacterData<TH>> {
#[inline]
unsafe fn data_for_layout(&self) -> &str {
&(*self.unsafe_get()).data.borrow_for_layout()
@@ -13,19 +13,20 @@ use dom_struct::dom_struct;
use servo_url::ServoUrl;
use std::default::Default;
use uuid::Uuid;
use typeholder::TypeHolderTrait;

#[dom_struct]
pub struct Client {
reflector_: Reflector,
active_worker: MutNullableDom<ServiceWorker>,
pub struct Client<TH: TypeHolderTrait + 'static> {
reflector_: Reflector<TH>,
active_worker: MutNullableDom<ServiceWorker<TH>>,
url: ServoUrl,
frame_type: FrameType,
#[ignore_malloc_size_of = "Defined in uuid"]
id: Uuid
}

impl Client {
fn new_inherited(url: ServoUrl) -> Client {
impl<TH: TypeHolderTrait> Client<TH> {
fn new_inherited(url: ServoUrl) -> Client<TH> {
Client {
reflector_: Reflector::new(),
active_worker: Default::default(),
@@ -35,7 +36,7 @@ impl Client {
}
}

pub fn new(window: &Window) -> DomRoot<Client> {
pub fn new(window: &Window<TH>) -> DomRoot<Client<TH>> {
reflect_dom_object(Box::new(Client::new_inherited(window.get_url())),
window,
Wrap)
@@ -45,16 +46,16 @@ impl Client {
self.url.clone()
}

pub fn get_controller(&self) -> Option<DomRoot<ServiceWorker>> {
pub fn get_controller(&self) -> Option<DomRoot<ServiceWorker<TH>>> {
self.active_worker.get()
}

pub fn set_controller(&self, worker: &ServiceWorker) {
pub fn set_controller(&self, worker: &ServiceWorker<TH>) {
self.active_worker.set(Some(worker));
}
}

impl ClientMethods for Client {
impl<TH: TypeHolderTrait> ClientMethods for Client<TH> {
// https://w3c.github.io/ServiceWorker/#client-url-attribute
fn Url(&self) -> USVString {
USVString(self.url.as_str().to_owned())
@@ -14,17 +14,18 @@ use dom::event::{Event, EventBubbles, EventCancelable};
use dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use servo_atoms::Atom;
use typeholder::TypeHolderTrait;

#[dom_struct]
pub struct CloseEvent {
event: Event,
pub struct CloseEvent<TH: TypeHolderTrait + 'static> {
event: Event<TH>,
was_clean: bool,
code: u16,
reason: DOMString,
}

impl CloseEvent {
pub fn new_inherited(was_clean: bool, code: u16, reason: DOMString) -> CloseEvent {
impl<TH: TypeHolderTrait> CloseEvent<TH> {
pub fn new_inherited(was_clean: bool, code: u16, reason: DOMString) -> CloseEvent<TH> {
CloseEvent {
event: Event::new_inherited(),
was_clean: was_clean,
@@ -33,35 +34,35 @@ impl CloseEvent {
}
}

pub fn new_uninitialized(global: &GlobalScope) -> DomRoot<CloseEvent> {
pub fn new_uninitialized(global: &GlobalScope<TH>) -> DomRoot<CloseEvent<TH>> {
reflect_dom_object(Box::new(CloseEvent::new_inherited(false, 0, DOMString::new())),
global,
CloseEventBinding::Wrap)
}

pub fn new(global: &GlobalScope,
pub fn new(global: &GlobalScope<TH>,
type_: Atom,
bubbles: EventBubbles,
cancelable: EventCancelable,
wasClean: bool,
code: u16,
reason: DOMString)
-> DomRoot<CloseEvent> {
-> DomRoot<CloseEvent<TH>> {
let event = Box::new(CloseEvent::new_inherited(wasClean, code, reason));
let ev = reflect_dom_object(event, global, CloseEventBinding::Wrap);
{
let event = ev.upcast::<Event>();
let event = ev.upcast::<Event<TH>>();
event.init_event(type_,
bool::from(bubbles),
bool::from(cancelable));
}
ev
}

pub fn Constructor(global: &GlobalScope,
pub fn Constructor(global: &GlobalScope<TH>,
type_: DOMString,
init: &CloseEventBinding::CloseEventInit)
-> Fallible<DomRoot<CloseEvent>> {
-> Fallible<DomRoot<CloseEvent<TH>>> {
let bubbles = EventBubbles::from(init.parent.bubbles);
let cancelable = EventCancelable::from(init.parent.cancelable);
Ok(CloseEvent::new(global,
@@ -75,7 +76,7 @@ impl CloseEvent {

}

impl CloseEventMethods for CloseEvent {
impl<TH: TypeHolderTrait> CloseEventMethods for CloseEvent<TH> {
// https://html.spec.whatwg.org/multipage/#dom-closeevent-wasclean
fn WasClean(&self) -> bool {
self.was_clean
@@ -12,27 +12,28 @@ use dom::document::Document;
use dom::node::Node;
use dom::window::Window;
use dom_struct::dom_struct;
use typeholder::TypeHolderTrait;

/// An HTML comment.
#[dom_struct]
pub struct Comment {
characterdata: CharacterData,
pub struct Comment<TH: TypeHolderTrait + 'static> {
characterdata: CharacterData<TH>,
}

impl Comment {
fn new_inherited(text: DOMString, document: &Document) -> Comment {
impl<TH: TypeHolderTrait> Comment<TH> {
fn new_inherited(text: DOMString, document: &Document<TH>) -> Self {
Comment {
characterdata: CharacterData::new_inherited(text, document),
}
}

pub fn new(text: DOMString, document: &Document) -> DomRoot<Comment> {
Node::reflect_node(Box::new(Comment::new_inherited(text, document)),
pub fn new(text: DOMString, document: &Document<TH>) -> DomRoot<Self> {
Node::<TH>::reflect_node(Box::new(Comment::new_inherited(text, document)),
document,
CommentBinding::Wrap)
}

pub fn Constructor(window: &Window, data: DOMString) -> Fallible<DomRoot<Comment>> {
pub fn Constructor(window: &Window<TH>, data: DOMString) -> Fallible<DomRoot<Self>> {
let document = window.Document();
Ok(Comment::new(data, &document))
}
@@ -11,21 +11,22 @@ use dom::bindings::str::DOMString;
use dom::uievent::UIEvent;
use dom::window::Window;
use dom_struct::dom_struct;
use typeholder::TypeHolderTrait;

#[dom_struct]
pub struct CompositionEvent {
uievent: UIEvent,
pub struct CompositionEvent<TH: TypeHolderTrait + 'static> {
uievent: UIEvent<TH>,
data: DOMString,
}

impl CompositionEvent {
pub fn new(window: &Window,
impl<TH: TypeHolderTrait> CompositionEvent<TH> {
pub fn new(window: &Window<TH>,
type_: DOMString,
can_bubble: bool,
cancelable: bool,
view: Option<&Window>,
view: Option<&Window<TH>>,
detail: i32,
data: DOMString) -> DomRoot<CompositionEvent> {
data: DOMString) -> DomRoot<Self> {
let ev = reflect_dom_object(Box::new(CompositionEvent {
uievent: UIEvent::new_inherited(),
data: data,
@@ -36,10 +37,10 @@ impl CompositionEvent {
ev
}

pub fn Constructor(window: &Window,
pub fn Constructor(window: &Window<TH>,
type_: DOMString,
init: &CompositionEventBinding::CompositionEventInit)
-> Fallible<DomRoot<CompositionEvent>> {
init: &CompositionEventBinding::CompositionEventInit<TH>)
-> Fallible<DomRoot<Self>> {
let event = CompositionEvent::new(window,
type_,
init.parent.parent.bubbles,
@@ -51,7 +52,7 @@ impl CompositionEvent {
}
}

impl CompositionEventMethods for CompositionEvent {
impl<TH: TypeHolderTrait> CompositionEventMethods for CompositionEvent<TH> {
// https://w3c.github.io/uievents/#dom-compositionevent-data
fn Data(&self) -> DOMString {
self.data.clone()
@@ -8,15 +8,17 @@ use dom::bindings::str::DOMString;
use dom::globalscope::GlobalScope;
use dom::workerglobalscope::WorkerGlobalScope;
use std::io;
use typeholder::TypeHolderTrait;
use std::marker::PhantomData;

// https://developer.mozilla.org/en-US/docs/Web/API/Console
pub struct Console(());
pub struct Console<TH: TypeHolderTrait + 'static>((), PhantomData<TH>,);

impl Console {
fn send_to_devtools(global: &GlobalScope, level: LogLevel, message: DOMString) {
impl<TH: TypeHolderTrait> Console<TH> {
fn send_to_devtools(global: &GlobalScope<TH>, level: LogLevel, message: DOMString) {
if let Some(chan) = global.devtools_chan() {
let console_message = prepare_message(level, message);
let worker_id = global.downcast::<WorkerGlobalScope>().map(|worker| {
let worker_id = global.downcast::<WorkerGlobalScope<TH>>().map(|worker| {
worker.get_worker_id()
});
let devtools_message = ScriptToDevtoolsControlMsg::ConsoleAPI(
@@ -39,9 +41,9 @@ fn with_stderr_lock<F>(f: F) where F: FnOnce() {
f()
}

impl Console {
impl<TH: TypeHolderTrait> Console<TH> {
// https://developer.mozilla.org/en-US/docs/Web/API/Console/log
pub fn Log(global: &GlobalScope, messages: Vec<DOMString>) {
pub fn Log(global: &GlobalScope<TH>, messages: Vec<DOMString>) {
with_stderr_lock(move || {
for message in messages {
println!("{}", message);
@@ -51,7 +53,7 @@ impl Console {
}

// https://developer.mozilla.org/en-US/docs/Web/API/Console
pub fn Debug(global: &GlobalScope, messages: Vec<DOMString>) {
pub fn Debug(global: &GlobalScope<TH>, messages: Vec<DOMString>) {
with_stderr_lock(move || {
for message in messages {
println!("{}", message);
@@ -61,7 +63,7 @@ impl Console {
}

// https://developer.mozilla.org/en-US/docs/Web/API/Console/info
pub fn Info(global: &GlobalScope, messages: Vec<DOMString>) {
pub fn Info(global: &GlobalScope<TH>, messages: Vec<DOMString>) {
with_stderr_lock(move || {
for message in messages {
println!("{}", message);
@@ -71,7 +73,7 @@ impl Console {
}

// https://developer.mozilla.org/en-US/docs/Web/API/Console/warn
pub fn Warn(global: &GlobalScope, messages: Vec<DOMString>) {
pub fn Warn(global: &GlobalScope<TH>, messages: Vec<DOMString>) {
with_stderr_lock(move || {
for message in messages {
println!("{}", message);
@@ -81,7 +83,7 @@ impl Console {
}

// https://developer.mozilla.org/en-US/docs/Web/API/Console/error
pub fn Error(global: &GlobalScope, messages: Vec<DOMString>) {
pub fn Error(global: &GlobalScope<TH>, messages: Vec<DOMString>) {
with_stderr_lock(move || {
for message in messages {
println!("{}", message);
@@ -91,7 +93,7 @@ impl Console {
}

// https://developer.mozilla.org/en-US/docs/Web/API/Console/assert
pub fn Assert(global: &GlobalScope, condition: bool, message: Option<DOMString>) {
pub fn Assert(global: &GlobalScope<TH>, condition: bool, message: Option<DOMString>) {
with_stderr_lock(move || {
if !condition {
let message = message.unwrap_or_else(|| DOMString::from("no message"));
@@ -102,7 +104,7 @@ impl Console {
}

// https://developer.mozilla.org/en-US/docs/Web/API/Console/time
pub fn Time(global: &GlobalScope, label: DOMString) {
pub fn Time(global: &GlobalScope<TH>, label: DOMString) {
with_stderr_lock(move || {
if let Ok(()) = global.time(label.clone()) {
let message = DOMString::from(format!("{}: timer started", label));
@@ -113,7 +115,7 @@ impl Console {
}

// https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd
pub fn TimeEnd(global: &GlobalScope, label: DOMString) {
pub fn TimeEnd(global: &GlobalScope<TH>, label: DOMString) {
with_stderr_lock(move || {
if let Ok(delta) = global.time_end(&label) {
let message = DOMString::from(
@@ -83,11 +83,12 @@ use html5ever::{LocalName, Prefix, QualName};
use js::jsapi::JSAutoCompartment;
use script_thread::ScriptThread;
use servo_config::prefs::PREFS;
use typeholder::TypeHolderTrait;

fn create_svg_element(name: QualName,
fn create_svg_element<TH: TypeHolderTrait>(name: QualName,
prefix: Option<Prefix>,
document: &Document)
-> DomRoot<Element> {
document: &Document<TH>)
-> DomRoot<Element<TH>> {
assert_eq!(name.ns, ns!(svg));

macro_rules! make(
@@ -113,13 +114,13 @@ fn create_svg_element(name: QualName,

// https://dom.spec.whatwg.org/#concept-create-element
#[allow(unsafe_code)]
fn create_html_element(name: QualName,
fn create_html_element<TH: TypeHolderTrait>(name: QualName,
prefix: Option<Prefix>,
is: Option<LocalName>,
document: &Document,
document: &Document<TH>,
creator: ElementCreator,
mode: CustomElementCreationMode)
-> DomRoot<Element> {
-> DomRoot<Element<TH>> {
assert_eq!(name.ns, ns!(html));

// Step 4
@@ -129,10 +130,10 @@ fn create_html_element(name: QualName,
if definition.is_autonomous() {
match mode {
CustomElementCreationMode::Asynchronous => {
let result = DomRoot::upcast::<Element>(
let result = DomRoot::upcast::<Element<TH>>(
HTMLElement::new(name.local.clone(), prefix.clone(), document));
result.set_custom_element_state(CustomElementState::Undefined);
ScriptThread::enqueue_upgrade_reaction(&*result, definition);
ScriptThread::<TH>::enqueue_upgrade_reaction(&*result, definition);
return result;
},
CustomElementCreationMode::Synchronous => {
@@ -144,18 +145,18 @@ fn create_html_element(name: QualName,
},
Err(error) => {
// Step 6. Recovering from exception.
let global = GlobalScope::current().unwrap_or_else(|| document.global());
let global = GlobalScope::<TH>::current().unwrap_or_else(|| document.global());
let cx = global.get_cx();

// Step 6.1.1
unsafe {
let _ac = JSAutoCompartment::new(cx, global.reflector().get_jsobject().get());
throw_dom_exception(cx, &global, error);
report_pending_exception(cx, true);
report_pending_exception::<TH>(cx, true);
}

// Step 6.1.2
let element = DomRoot::upcast::<Element>(
let element = DomRoot::upcast::<Element<TH>>(
HTMLUnknownElement::new(local_name, prefix, document));
element.set_custom_element_state(CustomElementState::Failed);
element
@@ -174,7 +175,7 @@ fn create_html_element(name: QualName,
upgrade_element(definition, &*element),
// Step 5.4
CustomElementCreationMode::Asynchronous =>
ScriptThread::enqueue_upgrade_reaction(&*element, definition),
ScriptThread::<TH>::enqueue_upgrade_reaction(&*element, definition),
}
return element;
}
@@ -191,12 +192,12 @@ fn create_html_element(name: QualName,
result
}

pub fn create_native_html_element(
pub fn create_native_html_element<TH: TypeHolderTrait>(
name: QualName,
prefix: Option<Prefix>,
document: &Document,
document: &Document<TH>,
creator: ElementCreator,
) -> DomRoot<Element> {
) -> DomRoot<Element<TH>> {
assert_eq!(name.ns, ns!(html));

macro_rules! make(
@@ -360,12 +361,12 @@ pub fn create_native_html_element(
}
}

pub fn create_element(name: QualName,
pub fn create_element<TH: TypeHolderTrait>(name: QualName,
is: Option<LocalName>,
document: &Document,
document: &Document<TH>,
creator: ElementCreator,
mode: CustomElementCreationMode)
-> DomRoot<Element> {
-> DomRoot<Element<TH>> {
let prefix = name.prefix.clone();
match name.ns {
ns!(html) => create_html_element(name, prefix, is, document, creator, mode),
Oops, something went wrong.