aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py84
-rw-r--r--components/script/dom/bindings/error.rs109
-rw-r--r--components/script/dom/bindings/interface.rs92
-rw-r--r--components/script/dom/bindings/proxyhandler.rs21
-rw-r--r--components/script/dom/bluetooth.rs18
-rw-r--r--components/script/dom/bluetoothremotegattcharacteristic.rs16
-rw-r--r--components/script/dom/bluetoothremotegattdescriptor.rs6
-rw-r--r--components/script/dom/bluetoothremotegattserver.rs10
-rw-r--r--components/script/dom/bluetoothremotegattservice.rs10
-rw-r--r--components/script/dom/browsingcontext.rs25
-rw-r--r--components/script/dom/document.rs21
-rw-r--r--components/script/dom/htmlcollection.rs2
-rw-r--r--components/script/dom/htmltableelement.rs60
-rw-r--r--components/script/dom/node.rs50
-rw-r--r--components/script/dom/webidls/HTMLTableElement.webidl2
-rw-r--r--components/script/dom/window.rs16
16 files changed, 349 insertions, 193 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 8360dfc322a..2e0dc2415dd 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -1872,56 +1872,31 @@ class CGDOMJSClass(CGThing):
elif self.descriptor.weakReferenceable:
args["slots"] = "2"
return """\
+static CLASS_OPS: js::jsapi::ClassOps = js::jsapi::ClassOps {
+ addProperty: None,
+ delProperty: None,
+ getProperty: None,
+ setProperty: None,
+ enumerate: %(enumerateHook)s,
+ resolve: %(resolveHook)s,
+ mayResolve: None,
+ finalize: Some(%(finalizeHook)s),
+ call: None,
+ hasInstance: None,
+ construct: None,
+ trace: Some(%(traceHook)s),
+};
+
static Class: DOMJSClass = DOMJSClass {
base: js::jsapi::Class {
name: %(name)s as *const u8 as *const libc::c_char,
flags: JSCLASS_IS_DOMJSCLASS | %(flags)s |
(((%(slots)s) & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT)
/* JSCLASS_HAS_RESERVED_SLOTS(%(slots)s) */,
- addProperty: None,
- delProperty: None,
- getProperty: None,
- setProperty: None,
- enumerate: %(enumerateHook)s,
- resolve: %(resolveHook)s,
- mayResolve: None,
- finalize: Some(%(finalizeHook)s),
- call: None,
- hasInstance: None,
- construct: None,
- trace: Some(%(traceHook)s),
-
- spec: js::jsapi::ClassSpec {
- createConstructor_: None,
- createPrototype_: None,
- constructorFunctions_: 0 as *const js::jsapi::JSFunctionSpec,
- constructorProperties_: 0 as *const js::jsapi::JSPropertySpec,
- prototypeFunctions_: 0 as *const js::jsapi::JSFunctionSpec,
- prototypeProperties_: 0 as *const js::jsapi::JSPropertySpec,
- finishInit_: None,
- flags: 0,
- },
-
- ext: js::jsapi::ClassExtension {
- isWrappedNative: false,
- weakmapKeyDelegateOp: None,
- objectMovedOp: None,
- },
-
- ops: js::jsapi::ObjectOps {
- lookupProperty: None,
- defineProperty: None,
- hasProperty: None,
- getProperty: None,
- setProperty: None,
- getOwnPropertyDescriptor: None,
- deleteProperty: None,
- watch: None,
- unwatch: None,
- getElements: None,
- enumerate: None,
- funToString: None,
- },
+ cOps: &CLASS_OPS,
+ spec: ptr::null(),
+ ext: ptr::null(),
+ oOps: ptr::null(),
},
dom_class: %(domClass)s
};""" % args
@@ -1947,19 +1922,8 @@ static PrototypeClass: JSClass = JSClass {
flags:
// JSCLASS_HAS_RESERVED_SLOTS(%(slotCount)s)
(%(slotCount)s & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT,
- addProperty: None,
- delProperty: None,
- getProperty: None,
- setProperty: None,
- enumerate: None,
- resolve: None,
- mayResolve: None,
- finalize: None,
- call: None,
- hasInstance: None,
- construct: None,
- trace: None,
- reserved: [0 as *mut os::raw::c_void; 23]
+ cOps: 0 as *const _,
+ reserved: [0 as *mut os::raw::c_void; 3]
};
""" % {'name': name, 'slotCount': slotCount}
@@ -1983,9 +1947,12 @@ class CGInterfaceObjectJSClass(CGThing):
"depth": self.descriptor.prototypeDepth
}
return """\
+static INTERFACE_OBJECT_OPS: js::jsapi::ClassOps =
+ NonCallbackInterfaceObjectClass::ops(%(constructorBehavior)s);
+
static InterfaceObjectClass: NonCallbackInterfaceObjectClass =
NonCallbackInterfaceObjectClass::new(
- %(constructorBehavior)s,
+ &INTERFACE_OBJECT_OPS,
%(representation)s,
PrototypeList::ID::%(id)s,
%(depth)s);
@@ -2772,6 +2739,7 @@ let traps = ProxyTraps {
ownPropertyKeys: Some(own_property_keys),
delete_: Some(%(delete)s),
enumerate: None,
+ getPrototypeIfOrdinary: Some(proxyhandler::get_prototype_if_ordinary),
preventExtensions: Some(proxyhandler::prevent_extensions),
isExtensible: Some(proxyhandler::is_extensible),
has: None,
diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs
index d0074335c23..bd63ba84fb1 100644
--- a/components/script/dom/bindings/error.rs
+++ b/components/script/dom/bindings/error.rs
@@ -4,15 +4,26 @@
//! Utilities to throw exceptions from Rust bindings.
+use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
use dom::bindings::codegen::PrototypeList::proto_id_to_name;
-use dom::bindings::conversions::ToJSValConvertible;
+use dom::bindings::conversions::root_from_object;
+use dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible};
use dom::bindings::global::GlobalRef;
+use dom::bindings::str::USVString;
use dom::domexception::{DOMErrorName, DOMException};
use js::error::{throw_range_error, throw_type_error};
+use js::jsapi::HandleObject;
use js::jsapi::JSAutoCompartment;
-use js::jsapi::{JSContext, JSObject};
-use js::jsapi::{JS_IsExceptionPending, JS_ReportPendingException, JS_SetPendingException};
+use js::jsapi::JSContext;
+use js::jsapi::JSObject;
+use js::jsapi::JS_ClearPendingException;
+use js::jsapi::JS_ErrorFromException;
+use js::jsapi::JS_GetPendingException;
+use js::jsapi::JS_IsExceptionPending;
+use js::jsapi::JS_SetPendingException;
use js::jsval::UndefinedValue;
+use libc::c_uint;
+use std::slice::from_raw_parts;
/// DOM exceptions that can be thrown by a native DOM method.
#[derive(Debug, Clone, HeapSizeOf)]
@@ -123,11 +134,101 @@ pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: GlobalRef, result:
JS_SetPendingException(cx, thrown.handle());
}
+struct ErrorInfo {
+ filename: String,
+ message: String,
+ lineno: c_uint,
+ column: c_uint,
+}
+
+impl ErrorInfo {
+ unsafe fn from_native_error(cx: *mut JSContext, object: HandleObject)
+ -> Option<ErrorInfo> {
+ let report = JS_ErrorFromException(cx, object);
+ if report.is_null() {
+ return None;
+ }
+
+ let filename = {
+ let filename = (*report).filename as *const u8;
+ if !filename.is_null() {
+ let length = (0..).find(|idx| *filename.offset(*idx) == 0).unwrap();
+ let filename = from_raw_parts(filename, length as usize);
+ String::from_utf8_lossy(filename).into_owned()
+ } else {
+ "none".to_string()
+ }
+ };
+
+ let lineno = (*report).lineno;
+ let column = (*report).column;
+
+ let message = {
+ let message = (*report).ucmessage;
+ let length = (0..).find(|idx| *message.offset(*idx) == 0).unwrap();
+ let message = from_raw_parts(message, length as usize);
+ String::from_utf16_lossy(message)
+ };
+
+ Some(ErrorInfo {
+ filename: filename,
+ message: message,
+ lineno: lineno,
+ column: column,
+ })
+ }
+
+ fn from_dom_exception(cx: *mut JSContext, object: HandleObject) -> Option<ErrorInfo> {
+ let exception = match root_from_object::<DOMException>(object.get()) {
+ Ok(exception) => exception,
+ Err(_) => return None,
+ };
+
+ Some(ErrorInfo {
+ filename: "".to_string(),
+ message: exception.Stringifier().into(),
+ lineno: 0,
+ column: 0,
+ })
+ }
+}
+
/// Report a pending exception, thereby clearing it.
pub unsafe fn report_pending_exception(cx: *mut JSContext, obj: *mut JSObject) {
if JS_IsExceptionPending(cx) {
let _ac = JSAutoCompartment::new(cx, obj);
- JS_ReportPendingException(cx);
+ rooted!(in(cx) let mut value = UndefinedValue());
+ if !JS_GetPendingException(cx, value.handle_mut()) {
+ JS_ClearPendingException(cx);
+ error!("Uncaught exception: JS_GetPendingException failed");
+ return;
+ }
+
+ JS_ClearPendingException(cx);
+ if !value.is_object() {
+ match USVString::from_jsval(cx, value.handle(), ()) {
+ Ok(USVString(string)) => error!("Uncaught exception: {}", string),
+ Err(_) => error!("Uncaught exception: failed to stringify primitive"),
+ }
+ return;
+ }
+
+ rooted!(in(cx) let object = value.to_object());
+ let error_info = ErrorInfo::from_native_error(cx, object.handle())
+ .or_else(|| ErrorInfo::from_dom_exception(cx, object.handle()));
+ let error_info = match error_info {
+ Some(error_info) => error_info,
+ None => {
+ error!("Uncaught exception: failed to extract information");
+ return;
+ }
+ };
+
+ error!("Error at {}:{}:{} {}",
+ error_info.filename,
+ error_info.lineno,
+ error_info.column,
+ error_info.message);
}
}
diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs
index 4e2c630a453..3b2b5dbde36 100644
--- a/components/script/dom/bindings/interface.rs
+++ b/components/script/dom/bindings/interface.rs
@@ -11,7 +11,7 @@ use dom::bindings::guard::Guard;
use dom::bindings::utils::get_proto_or_iface_array;
use js::error::throw_type_error;
use js::glue::{RUST_SYMBOL_TO_JSID, UncheckedUnwrapObject};
-use js::jsapi::{Class, ClassExtension, ClassSpec, GetGlobalForObjectCrossCompartment};
+use js::jsapi::{Class, ClassOps, GetGlobalForObjectCrossCompartment};
use js::jsapi::{GetWellKnownSymbol, HandleObject, HandleValue, JSClass, JSContext};
use js::jsapi::{JSFunctionSpec, JSNative, JSFUN_CONSTRUCTOR, JSPROP_ENUMERATE};
use js::jsapi::{JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_RESOLVING, JSPropertySpec};
@@ -101,6 +101,21 @@ unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext,
ret
}
+const OBJECT_OPS: ObjectOps = ObjectOps {
+ lookupProperty: None,
+ defineProperty: None,
+ hasProperty: None,
+ getProperty: None,
+ setProperty: None,
+ getOwnPropertyDescriptor: None,
+ deleteProperty: None,
+ watch: None,
+ unwatch: None,
+ getElements: None,
+ enumerate: None,
+ funToString: Some(fun_to_string_hook),
+};
+
/// The class of a non-callback interface object.
#[derive(Copy, Clone)]
pub struct NonCallbackInterfaceObjectClass {
@@ -117,58 +132,39 @@ pub struct NonCallbackInterfaceObjectClass {
unsafe impl Sync for NonCallbackInterfaceObjectClass {}
impl NonCallbackInterfaceObjectClass {
+ /// Create `ClassOps` for a `NonCallbackInterfaceObjectClass`.
+ pub const fn ops(constructor_behavior: InterfaceConstructorBehavior)
+ -> ClassOps {
+ ClassOps {
+ addProperty: None,
+ delProperty: None,
+ getProperty: None,
+ setProperty: None,
+ enumerate: None,
+ resolve: None,
+ mayResolve: None,
+ finalize: None,
+ call: constructor_behavior.call,
+ construct: constructor_behavior.construct,
+ hasInstance: Some(has_instance_hook),
+ trace: None,
+ }
+ }
+
/// Create a new `NonCallbackInterfaceObjectClass` structure.
- pub const fn new(
- constructor_behavior: InterfaceConstructorBehavior,
- string_rep: &'static [u8],
- proto_id: PrototypeList::ID,
- proto_depth: u16)
- -> NonCallbackInterfaceObjectClass {
+ pub const fn new(ops: &'static ClassOps,
+ string_rep: &'static [u8],
+ proto_id: PrototypeList::ID,
+ proto_depth: u16)
+ -> NonCallbackInterfaceObjectClass {
NonCallbackInterfaceObjectClass {
class: Class {
name: b"Function\0" as *const _ as *const libc::c_char,
flags: 0,
- addProperty: None,
- delProperty: None,
- getProperty: None,
- setProperty: None,
- enumerate: None,
- resolve: None,
- mayResolve: None,
- finalize: None,
- call: constructor_behavior.call,
- construct: constructor_behavior.construct,
- hasInstance: Some(has_instance_hook),
- trace: None,
- spec: ClassSpec {
- createConstructor_: None,
- createPrototype_: None,
- constructorFunctions_: ptr::null(),
- constructorProperties_: ptr::null(),
- prototypeFunctions_: ptr::null(),
- prototypeProperties_: ptr::null(),
- finishInit_: None,
- flags: 0,
- },
- ext: ClassExtension {
- isWrappedNative: false,
- weakmapKeyDelegateOp: None,
- objectMovedOp: None,
- },
- ops: ObjectOps {
- lookupProperty: None,
- defineProperty: None,
- hasProperty: None,
- getProperty: None,
- setProperty: None,
- getOwnPropertyDescriptor: None,
- deleteProperty: None,
- watch: None,
- unwatch: None,
- getElements: None,
- enumerate: None,
- funToString: Some(fun_to_string_hook),
- }
+ cOps: ops,
+ spec: ptr::null(),
+ ext: ptr::null(),
+ oOps: &OBJECT_OPS,
},
proto_id: proto_id,
proto_depth: proto_depth,
diff --git a/components/script/dom/bindings/proxyhandler.rs b/components/script/dom/bindings/proxyhandler.rs
index 9db30d8835c..c863cc31994 100644
--- a/components/script/dom/bindings/proxyhandler.rs
+++ b/components/script/dom/bindings/proxyhandler.rs
@@ -12,7 +12,9 @@ use js::glue::GetProxyExtra;
use js::glue::InvokeGetOwnPropertyDescriptor;
use js::glue::{GetProxyHandler, SetProxyExtra};
use js::jsapi::GetObjectProto;
+use js::jsapi::GetStaticPrototype;
use js::jsapi::JS_GetPropertyDescriptorById;
+use js::jsapi::MutableHandleObject;
use js::jsapi::{Handle, HandleId, HandleObject, MutableHandle, ObjectOpResult};
use js::jsapi::{JSContext, JSObject, JSPROP_GETTER, PropertyDescriptor};
use js::jsapi::{JSErrNum, JS_StrictPropertyStub};
@@ -103,6 +105,25 @@ pub unsafe extern "C" fn is_extensible(_cx: *mut JSContext,
true
}
+/// If `proxy` (underneath any functionally-transparent wrapper proxies) has as
+/// its `[[GetPrototypeOf]]` trap the ordinary `[[GetPrototypeOf]]` behavior
+/// defined for ordinary objects, set `*is_ordinary` to true and store `obj`'s
+/// prototype in `proto`. Otherwise set `*isOrdinary` to false. In case of
+/// error, both outparams have unspecified value.
+///
+/// This implementation always handles the case of the ordinary
+/// `[[GetPrototypeOf]]` behavior. An alternative implementation will be
+/// necessary for the Location object.
+pub unsafe extern "C" fn get_prototype_if_ordinary(_: *mut JSContext,
+ proxy: HandleObject,
+ is_ordinary: *mut bool,
+ proto: MutableHandleObject)
+ -> bool {
+ *is_ordinary = true;
+ proto.set(GetStaticPrototype(proxy.get()));
+ true
+}
+
/// Get the expando object, or null if there is none.
pub fn get_expando_object(obj: HandleObject) -> *mut JSObject {
unsafe {
diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs
index 7deca26c9d3..c86fa0150a3 100644
--- a/components/script/dom/bluetooth.rs
+++ b/components/script/dom/bluetooth.rs
@@ -7,7 +7,7 @@ use core::clone::Clone;
use dom::bindings::codegen::Bindings::BluetoothBinding;
use dom::bindings::codegen::Bindings::BluetoothBinding::RequestDeviceOptions;
use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothScanFilter, BluetoothMethods};
-use dom::bindings::error::Error::{Security, Type};
+use dom::bindings::error::Error::{self, Security, Type};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
@@ -19,7 +19,7 @@ use dom::bluetoothuuid::BluetoothUUID;
use ipc_channel::ipc::{self, IpcSender};
use net_traits::bluetooth_scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence};
use net_traits::bluetooth_scanfilter::{RequestDeviceoptions, ServiceUUIDSequence};
-use net_traits::bluetooth_thread::BluetoothMethodMsg;
+use net_traits::bluetooth_thread::{BluetoothError, BluetoothMethodMsg};
const FILTER_EMPTY_ERROR: &'static str = "'filters' member must be non - empty to find any devices.";
const FILTER_ERROR: &'static str = "A filter must restrict the devices in some way.";
@@ -135,6 +135,18 @@ fn convert_request_device_options(options: &RequestDeviceOptions,
ServiceUUIDSequence::new(optional_services)))
}
+impl From<BluetoothError> for Error {
+ fn from(error: BluetoothError) -> Self {
+ match error {
+ BluetoothError::Type(message) => Error::Type(message),
+ BluetoothError::Network => Error::Network,
+ BluetoothError::NotFound => Error::NotFound,
+ BluetoothError::NotSupported => Error::NotSupported,
+ BluetoothError::Security => Error::Security,
+ }
+ }
+}
+
impl BluetoothMethods for Bluetooth {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
fn RequestDevice(&self, option: &RequestDeviceOptions) -> Fallible<Root<BluetoothDevice>> {
@@ -154,7 +166,7 @@ impl BluetoothMethods for Bluetooth {
&ad_data))
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs
index e3e17b4a0f9..0c27097625c 100644
--- a/components/script/dom/bluetoothremotegattcharacteristic.rs
+++ b/components/script/dom/bluetoothremotegattcharacteristic.rs
@@ -12,7 +12,7 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding::
BluetoothRemoteGATTCharacteristicMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
-use dom::bindings::error::Error::{InvalidModification, Network, NotSupported, Security, Type};
+use dom::bindings::error::Error::{self, InvalidModification, Network, NotSupported, Security};
use dom::bindings::error::{Fallible, ErrorResult};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutHeap, Root};
@@ -115,7 +115,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
descriptor.instance_id))
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
@@ -147,7 +147,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
.collect())
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
@@ -177,7 +177,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
ByteString::new(val)
},
Err(error) => {
- return Err(Type(error))
+ return Err(Error::from(error))
},
};
*self.value.borrow_mut() = Some(value.clone());
@@ -195,6 +195,12 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
if !self.Service().Device().Gatt().Connected() {
return Err(Network)
}
+
+ if !(self.Properties().Write() ||
+ self.Properties().WriteWithoutResponse() ||
+ self.Properties().AuthenticatedSignedWrites()) {
+ return Err(NotSupported)
+ }
let (sender, receiver) = ipc::channel().unwrap();
self.get_bluetooth_thread().send(
BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap();
@@ -202,7 +208,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
match result {
Ok(_) => Ok(()),
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs
index f821d4aca2d..0ba52181b48 100644
--- a/components/script/dom/bluetoothremotegattdescriptor.rs
+++ b/components/script/dom/bluetoothremotegattdescriptor.rs
@@ -11,7 +11,7 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding::BluetoothRemoteGATTDescriptorMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
-use dom::bindings::error::Error::{InvalidModification, Network, Security, Type};
+use dom::bindings::error::Error::{self, InvalidModification, Network, Security};
use dom::bindings::error::{Fallible, ErrorResult};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutHeap, Root};
@@ -101,7 +101,7 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
ByteString::new(val)
},
Err(error) => {
- return Err(Type(error))
+ return Err(Error::from(error))
},
};
*self.value.borrow_mut() = Some(value.clone());
@@ -126,7 +126,7 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
match result {
Ok(_) => Ok(()),
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs
index 56aad1b8bf6..f4b1e532f10 100644
--- a/components/script/dom/bluetoothremotegattserver.rs
+++ b/components/script/dom/bluetoothremotegattserver.rs
@@ -6,7 +6,7 @@ use bluetooth_blacklist::{Blacklist, uuid_is_blacklisted};
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
-use dom::bindings::error::Error::{Security, Type};
+use dom::bindings::error::Error::{self, Security};
use dom::bindings::error::{Fallible, ErrorResult};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutHeap, Root};
@@ -72,7 +72,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
Ok(Root::from_ref(self))
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
@@ -89,7 +89,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
Ok(())
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
@@ -113,7 +113,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
service.instance_id))
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
@@ -146,7 +146,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
.collect())
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs
index f0954a1c76f..5b80bc6afc0 100644
--- a/components/script/dom/bluetoothremotegattservice.rs
+++ b/components/script/dom/bluetoothremotegattservice.rs
@@ -5,7 +5,7 @@
use bluetooth_blacklist::{Blacklist, uuid_is_blacklisted};
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
-use dom::bindings::error::Error::{Security, Type};
+use dom::bindings::error::Error::{self, Security};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutHeap, Root};
@@ -115,7 +115,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
characteristic.instance_id))
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
@@ -160,7 +160,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
Ok(characteristics)
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
@@ -188,7 +188,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
service.instance_id))
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
@@ -223,7 +223,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
.collect())
},
Err(error) => {
- Err(Type(error))
+ Err(Error::from(error))
},
}
}
diff --git a/components/script/dom/browsingcontext.rs b/components/script/dom/browsingcontext.rs
index 4c0914ddf3c..878d376ca66 100644
--- a/components/script/dom/browsingcontext.rs
+++ b/components/script/dom/browsingcontext.rs
@@ -22,7 +22,7 @@ use js::jsapi::{Handle, HandleId, HandleObject, HandleValue, JSAutoCompartment};
use js::jsapi::{JSContext, JSPROP_READONLY, JSErrNum, JSObject, PropertyDescriptor, JS_DefinePropertyById};
use js::jsapi::{JS_ForwardGetPropertyTo, JS_ForwardSetPropertyTo, JS_GetClass, JSTracer, FreeOp};
use js::jsapi::{JS_GetOwnPropertyDescriptorById, JS_HasPropertyById, MutableHandle};
-use js::jsapi::{MutableHandleValue, ObjectOpResult};
+use js::jsapi::{MutableHandleObject, MutableHandleValue, ObjectOpResult};
use js::jsval::{UndefinedValue, PrivateValue};
use msg::constellation_msg::{PipelineId, SubpageId};
use std::cell::Cell;
@@ -354,6 +354,28 @@ unsafe extern "C" fn set(cx: *mut JSContext,
res)
}
+#[allow(unsafe_code)]
+unsafe extern "C" fn get_prototype_if_ordinary(_: *mut JSContext,
+ _: HandleObject,
+ is_ordinary: *mut bool,
+ _: MutableHandleObject)
+ -> bool {
+ // Window's [[GetPrototypeOf]] trap isn't the ordinary definition:
+ //
+ // https://html.spec.whatwg.org/multipage/#windowproxy-getprototypeof
+ //
+ // We nonetheless can implement it with a static [[Prototype]], because
+ // wrapper-class handlers (particularly, XOW in FilteringWrapper.cpp) supply
+ // all non-ordinary behavior.
+ //
+ // But from a spec point of view, it's the exact same object in both cases --
+ // only the observer's changed. So this getPrototypeIfOrdinary trap on the
+ // non-wrapper object *must* report non-ordinary, even if static [[Prototype]]
+ // usually means ordinary.
+ *is_ordinary = false;
+ return true;
+}
+
static PROXY_HANDLER: ProxyTraps = ProxyTraps {
enter: None,
getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor),
@@ -361,6 +383,7 @@ static PROXY_HANDLER: ProxyTraps = ProxyTraps {
ownPropertyKeys: None,
delete_: None,
enumerate: None,
+ getPrototypeIfOrdinary: Some(get_prototype_if_ordinary),
preventExtensions: None,
isExtensible: None,
has: Some(has),
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 28edce553ad..78ccbbdf1f5 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -376,6 +376,7 @@ impl Document {
// that workable.
match self.GetDocumentElement() {
Some(root) => {
+ root.upcast::<Node>().is_dirty() ||
root.upcast::<Node>().has_dirty_descendants() ||
!self.modified_elements.borrow().is_empty()
}
@@ -1371,6 +1372,7 @@ impl Document {
}
pub fn finish_load(&self, load: LoadType) {
+ debug!("Document got finish_load: {:?}", load);
// The parser might need the loader, so restrict the lifetime of the borrow.
{
let mut loader = self.loader.borrow_mut();
@@ -1396,9 +1398,9 @@ impl Document {
// If we don't have a parser, and the reflow timer has been reset, explicitly
// trigger a reflow.
if let LoadType::Stylesheet(_) = load {
- self.window().reflow(ReflowGoal::ForDisplay,
- ReflowQueryType::NoQuery,
- ReflowReason::StylesheetLoaded);
+ self.window.reflow(ReflowGoal::ForDisplay,
+ ReflowQueryType::NoQuery,
+ ReflowReason::StylesheetLoaded);
}
}
@@ -1487,24 +1489,25 @@ impl Document {
return;
}
self.domcontentloaded_dispatched.set(true);
+ assert!(self.ReadyState() != DocumentReadyState::Complete,
+ "Complete before DOMContentLoaded?");
update_with_current_time_ms(&self.dom_content_loaded_event_start);
let window = self.window();
window.dom_manipulation_task_source().queue_event(self.upcast(), atom!("DOMContentLoaded"),
EventBubbles::Bubbles, EventCancelable::NotCancelable, window);
+
window.reflow(ReflowGoal::ForDisplay,
ReflowQueryType::NoQuery,
ReflowReason::DOMContentLoaded);
-
update_with_current_time_ms(&self.dom_content_loaded_event_end);
}
pub fn notify_constellation_load(&self) {
let pipeline_id = self.window.pipeline();
- let event = ConstellationMsg::DOMLoad(pipeline_id);
- self.window.constellation_chan().send(event).unwrap();
-
+ let load_event = ConstellationMsg::LoadComplete(pipeline_id);
+ self.window.constellation_chan().send(load_event).unwrap();
}
pub fn set_current_parser(&self, script: Option<ParserRef>) {
@@ -2908,16 +2911,18 @@ impl DocumentProgressHandler {
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventStart
update_with_current_time_ms(&document.load_event_start);
+ debug!("About to dispatch load for {:?}", document.url());
let _ = wintarget.dispatch_event_with_target(document.upcast(), &event);
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventEnd
update_with_current_time_ms(&document.load_event_end);
- document.notify_constellation_load();
window.reflow(ReflowGoal::ForDisplay,
ReflowQueryType::NoQuery,
ReflowReason::DocumentLoaded);
+
+ document.notify_constellation_load();
}
}
diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs
index 798d0731b2c..95134556bc0 100644
--- a/components/script/dom/htmlcollection.rs
+++ b/components/script/dom/htmlcollection.rs
@@ -248,7 +248,7 @@ impl<'a> Iterator for HTMLCollectionElementsIter<'a> {
.filter_map(Root::downcast)
.filter(|element| filter.filter(&element, root))
.next()
- }
+ }
}
impl HTMLCollectionMethods for HTMLCollection {
diff --git a/components/script/dom/htmltableelement.rs b/components/script/dom/htmltableelement.rs
index 4cff33b78a1..1d189f4a21f 100644
--- a/components/script/dom/htmltableelement.rs
+++ b/components/script/dom/htmltableelement.rs
@@ -34,6 +34,20 @@ pub struct HTMLTableElement {
tbodies: MutNullableHeap<JS<HTMLCollection>>,
}
+#[allow(unrooted_must_root)]
+#[derive(JSTraceable, HeapSizeOf)]
+struct TableRowFilter {
+ sections: Vec<JS<Node>>,
+}
+
+impl CollectionFilter for TableRowFilter {
+ fn filter(&self, elem: &Element, root: &Node) -> bool {
+ elem.is::<HTMLTableRowElement>() &&
+ (root.is_parent_of(elem.upcast())
+ || self.sections.iter().any(|ref section| section.is_parent_of(elem.upcast())))
+ }
+}
+
impl HTMLTableElement {
fn new_inherited(localName: Atom, prefix: Option<DOMString>, document: &Document)
-> HTMLTableElement {
@@ -120,32 +134,22 @@ impl HTMLTableElement {
thead.upcast::<Node>().remove_self();
}
}
-}
-
-impl HTMLTableElementMethods for HTMLTableElement {
- // https://html.spec.whatwg.org/multipage/#dom-table-rows
- fn Rows(&self) -> Root<HTMLCollection> {
- #[allow(unrooted_must_root)]
- #[derive(JSTraceable, HeapSizeOf)]
- struct TableRowFilter {
- sections: Vec<JS<Node>>
- }
-
- impl CollectionFilter for TableRowFilter {
- fn filter(&self, elem: &Element, root: &Node) -> bool {
- elem.is::<HTMLTableRowElement>() &&
- (root.is_parent_of(elem.upcast())
- || self.sections.iter().any(|ref section| section.is_parent_of(elem.upcast())))
- }
- }
- let filter = TableRowFilter {
+ fn get_rows(&self) -> TableRowFilter {
+ TableRowFilter {
sections: self.upcast::<Node>()
.children()
.filter_map(|ref node|
node.downcast::<HTMLTableSectionElement>().map(|_| JS::from_ref(&**node)))
.collect()
- };
+ }
+ }
+}
+
+impl HTMLTableElementMethods for HTMLTableElement {
+ // https://html.spec.whatwg.org/multipage/#dom-table-rows
+ fn Rows(&self) -> Root<HTMLCollection> {
+ let filter = self.get_rows();
HTMLCollection::new(window_from_node(self).r(), self.upcast(), box filter)
}
@@ -338,6 +342,22 @@ impl HTMLTableElementMethods for HTMLTableElement {
Ok(new_row)
}
+ // https://html.spec.whatwg.org/multipage/#dom-table-deleterow
+ fn DeleteRow(&self, mut index: i32) -> Fallible<()> {
+ let rows = self.Rows();
+ // Step 1.
+ if index == -1 {
+ index = rows.Length() as i32 - 1;
+ }
+ // Step 2.
+ if index < 0 || index as u32 >= rows.Length() {
+ return Err(Error::IndexSize);
+ }
+ // Step 3.
+ Root::upcast::<Node>(rows.Item(index as u32).unwrap()).remove_self();
+ Ok(())
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
make_getter!(BgColor, "bgcolor");
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 37495be3ba3..2769b7503bc 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -479,19 +479,7 @@ impl Node {
return
}
- // 2. Dirty descendants.
- fn dirty_subtree(node: &Node) {
- // Stop if this subtree is already dirty.
- if node.is_dirty() { return }
-
- node.set_flag(IS_DIRTY | HAS_DIRTY_DESCENDANTS, true);
-
- for kid in node.children() {
- dirty_subtree(kid.r());
- }
- }
-
- dirty_subtree(self);
+ self.set_flag(IS_DIRTY, true);
// 4. Dirty ancestors.
for ancestor in self.ancestors() {
@@ -1299,22 +1287,17 @@ impl TreeIterator {
depth: 0,
}
}
-}
-impl Iterator for TreeIterator {
- type Item = Root<Node>;
-
- // https://dom.spec.whatwg.org/#concept-tree-order
- fn next(&mut self) -> Option<Root<Node>> {
+ pub fn next_skipping_children(&mut self) -> Option<Root<Node>> {
let current = match self.current.take() {
None => return None,
Some(current) => current,
};
- if let Some(first_child) = current.GetFirstChild() {
- self.current = Some(first_child);
- self.depth += 1;
- return Some(current);
- };
+
+ self.next_skipping_children_impl(current)
+ }
+
+ fn next_skipping_children_impl(&mut self, current: Root<Node>) -> Option<Root<Node>> {
for ancestor in current.inclusive_ancestors() {
if self.depth == 0 {
break;
@@ -1331,6 +1314,25 @@ impl Iterator for TreeIterator {
}
}
+impl Iterator for TreeIterator {
+ type Item = Root<Node>;
+
+ // https://dom.spec.whatwg.org/#concept-tree-order
+ fn next(&mut self) -> Option<Root<Node>> {
+ let current = match self.current.take() {
+ None => return None,
+ Some(current) => current,
+ };
+ if let Some(first_child) = current.GetFirstChild() {
+ self.current = Some(first_child);
+ self.depth += 1;
+ return Some(current);
+ };
+
+ self.next_skipping_children_impl(current)
+ }
+}
+
/// Specifies whether children must be recursively cloned or not.
#[derive(Copy, Clone, PartialEq, HeapSizeOf)]
pub enum CloneChildrenFlag {
diff --git a/components/script/dom/webidls/HTMLTableElement.webidl b/components/script/dom/webidls/HTMLTableElement.webidl
index 596f5abd188..f0d8e19d0eb 100644
--- a/components/script/dom/webidls/HTMLTableElement.webidl
+++ b/components/script/dom/webidls/HTMLTableElement.webidl
@@ -19,7 +19,7 @@ interface HTMLTableElement : HTMLElement {
HTMLTableSectionElement createTBody();
readonly attribute HTMLCollection rows;
[Throws] HTMLTableRowElement insertRow(optional long index = -1);
- //void deleteRow(long index);
+ [Throws] void deleteRow(long index);
// also has obsolete members
};
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index f28f823dab4..ebd9550d117 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -450,13 +450,15 @@ impl WindowMethods for Window {
// Right now, just print to the console
// Ensure that stderr doesn't trample through the alert() we use to
// communicate test results (see executorservo.py in wptrunner).
- let stderr = stderr();
- let mut stderr = stderr.lock();
- let stdout = stdout();
- let mut stdout = stdout.lock();
- writeln!(&mut stdout, "ALERT: {}", s).unwrap();
- stdout.flush().unwrap();
- stderr.flush().unwrap();
+ {
+ let stderr = stderr();
+ let mut stderr = stderr.lock();
+ let stdout = stdout();
+ let mut stdout = stdout.lock();
+ writeln!(&mut stdout, "ALERT: {}", s).unwrap();
+ stdout.flush().unwrap();
+ stderr.flush().unwrap();
+ }
let (sender, receiver) = ipc::channel().unwrap();
self.constellation_chan().send(ConstellationMsg::Alert(self.pipeline(), s.to_string(), sender)).unwrap();