aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/Cargo.toml8
-rw-r--r--components/script/devtools.rs15
-rw-r--r--components/script/dom/abstractworker.rs22
-rw-r--r--components/script/dom/attr.rs2
-rw-r--r--components/script/dom/bindings/callback.rs8
-rw-r--r--components/script/dom/bindings/cell.rs139
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py1075
-rw-r--r--components/script/dom/bindings/codegen/Configuration.py58
-rw-r--r--components/script/dom/bindings/codegen/parser/WebIDL.py57
-rw-r--r--components/script/dom/bindings/codegen/parser/abstract.patch12
-rw-r--r--components/script/dom/bindings/codegen/parser/bytestring.patch29
-rw-r--r--components/script/dom/bindings/codegen/parser/callback-location.patch22
-rw-r--r--components/script/dom/bindings/codegen/parser/pref-main-thread.patch14
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_securecontext_extended_attribute.py14
-rwxr-xr-xcomponents/script/dom/bindings/codegen/parser/update.sh2
-rw-r--r--components/script/dom/bindings/constant.rs65
-rw-r--r--components/script/dom/bindings/conversions.rs50
-rw-r--r--components/script/dom/bindings/error.rs70
-rw-r--r--components/script/dom/bindings/global.rs34
-rw-r--r--components/script/dom/bindings/inheritance.rs2
-rw-r--r--components/script/dom/bindings/interface.rs395
-rw-r--r--components/script/dom/bindings/iterable.rs168
-rw-r--r--components/script/dom/bindings/js.rs10
-rw-r--r--components/script/dom/bindings/mod.rs6
-rw-r--r--components/script/dom/bindings/namespace.rs42
-rw-r--r--components/script/dom/bindings/proxyhandler.rs41
-rw-r--r--components/script/dom/bindings/refcounted.rs129
-rw-r--r--components/script/dom/bindings/reflector.rs8
-rw-r--r--components/script/dom/bindings/str.rs9
-rw-r--r--components/script/dom/bindings/trace.rs24
-rw-r--r--components/script/dom/bindings/utils.rs120
-rw-r--r--components/script/dom/blob.rs4
-rw-r--r--components/script/dom/bluetooth.rs2
-rw-r--r--components/script/dom/bluetoothremotegattcharacteristic.rs2
-rw-r--r--components/script/dom/bluetoothremotegattdescriptor.rs2
-rw-r--r--components/script/dom/bluetoothremotegattserver.rs2
-rw-r--r--components/script/dom/browsingcontext.rs16
-rw-r--r--components/script/dom/canvasgradient.rs2
-rw-r--r--components/script/dom/canvasrenderingcontext2d.rs20
-rw-r--r--components/script/dom/characterdata.rs2
-rw-r--r--components/script/dom/client.rs2
-rw-r--r--components/script/dom/console.rs111
-rw-r--r--components/script/dom/crypto.rs6
-rw-r--r--components/script/dom/cssstyledeclaration.rs35
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs61
-rw-r--r--components/script/dom/document.rs113
-rw-r--r--components/script/dom/domimplementation.rs4
-rw-r--r--components/script/dom/domparser.rs2
-rw-r--r--components/script/dom/domrectlist.rs3
-rw-r--r--components/script/dom/domstringmap.rs6
-rw-r--r--components/script/dom/domtokenlist.rs6
-rw-r--r--components/script/dom/element.rs65
-rw-r--r--components/script/dom/event.rs23
-rw-r--r--components/script/dom/eventdispatcher.rs12
-rw-r--r--components/script/dom/eventtarget.rs4
-rw-r--r--components/script/dom/filelist.rs6
-rw-r--r--components/script/dom/headers.rs55
-rw-r--r--components/script/dom/htmlbuttonelement.rs2
-rw-r--r--components/script/dom/htmlcanvaselement.rs21
-rw-r--r--components/script/dom/htmlcollection.rs12
-rw-r--r--components/script/dom/htmldataelement.rs9
-rw-r--r--components/script/dom/htmldialogelement.rs27
-rw-r--r--components/script/dom/htmlelement.rs2
-rw-r--r--components/script/dom/htmlformcontrolscollection.rs10
-rw-r--r--components/script/dom/htmlformelement.rs4
-rw-r--r--components/script/dom/htmliframeelement.rs14
-rw-r--r--components/script/dom/htmlinputelement.rs10
-rw-r--r--components/script/dom/htmllinkelement.rs3
-rw-r--r--components/script/dom/htmlmediaelement.rs28
-rw-r--r--components/script/dom/htmlmetaelement.rs2
-rw-r--r--components/script/dom/htmloptionelement.rs16
-rw-r--r--components/script/dom/htmlscriptelement.rs6
-rw-r--r--components/script/dom/htmltextareaelement.rs4
-rw-r--r--components/script/dom/imagedata.rs15
-rw-r--r--components/script/dom/mimetypearray.rs4
-rw-r--r--components/script/dom/mod.rs3
-rw-r--r--components/script/dom/namednodemap.rs12
-rw-r--r--components/script/dom/navigator.rs6
-rw-r--r--components/script/dom/node.rs12
-rw-r--r--components/script/dom/nodelist.rs6
-rw-r--r--components/script/dom/plugin.rs4
-rw-r--r--components/script/dom/pluginarray.rs4
-rw-r--r--components/script/dom/radionodelist.rs4
-rw-r--r--components/script/dom/range.rs4
-rw-r--r--components/script/dom/request.rs8
-rw-r--r--components/script/dom/response.rs290
-rw-r--r--components/script/dom/serviceworker.rs30
-rw-r--r--components/script/dom/serviceworkercontainer.rs2
-rw-r--r--components/script/dom/serviceworkerglobalscope.rs4
-rw-r--r--components/script/dom/servohtmlparser.rs4
-rw-r--r--components/script/dom/storage.rs6
-rw-r--r--components/script/dom/stylesheetlist.rs6
-rw-r--r--components/script/dom/testbinding.rs37
-rw-r--r--components/script/dom/testbindingiterable.rs41
-rw-r--r--components/script/dom/testbindingpairiterable.rs54
-rw-r--r--components/script/dom/testbindingproxy.rs4
-rw-r--r--components/script/dom/textencoder.rs10
-rw-r--r--components/script/dom/touchlist.rs6
-rw-r--r--components/script/dom/treewalker.rs2
-rw-r--r--components/script/dom/uievent.rs2
-rw-r--r--components/script/dom/url.rs4
-rw-r--r--components/script/dom/webglprogram.rs4
-rw-r--r--components/script/dom/webglrenderingcontext.rs131
-rw-r--r--components/script/dom/webidls/Console.webidl6
-rw-r--r--components/script/dom/webidls/HTMLDataElement.webidl2
-rw-r--r--components/script/dom/webidls/HTMLDialogElement.webidl2
-rw-r--r--components/script/dom/webidls/HTMLOptionElement.webidl2
-rw-r--r--components/script/dom/webidls/Headers.webidl2
-rw-r--r--components/script/dom/webidls/IterableIterator.webidl16
-rw-r--r--components/script/dom/webidls/Navigator.webidl7
-rw-r--r--components/script/dom/webidls/NodeList.webidl2
-rw-r--r--components/script/dom/webidls/Response.webidl37
-rw-r--r--components/script/dom/webidls/TestBinding.webidl3
-rw-r--r--components/script/dom/webidls/TestBindingIterable.webidl14
-rw-r--r--components/script/dom/webidls/TestBindingPairIterable.webidl12
-rw-r--r--components/script/dom/webidls/WebGLRenderingContext.webidl2
-rw-r--r--components/script/dom/webidls/Window.webidl3
-rw-r--r--components/script/dom/webidls/WorkerGlobalScope.webidl9
-rw-r--r--components/script/dom/websocket.rs10
-rw-r--r--components/script/dom/window.rs80
-rw-r--r--components/script/dom/worker.rs57
-rw-r--r--components/script/dom/workerglobalscope.rs41
-rw-r--r--components/script/dom/xmldocument.rs5
-rw-r--r--components/script/dom/xmlhttprequest.rs25
-rw-r--r--components/script/layout_wrapper.rs59
-rw-r--r--components/script/lib.rs9
-rw-r--r--components/script/network_listener.rs2
-rw-r--r--components/script/origin.rs2
-rw-r--r--components/script/parse/html.rs6
-rw-r--r--components/script/script_runtime.rs4
-rw-r--r--components/script/script_thread.rs48
-rw-r--r--components/script/serviceworker_manager.rs4
-rw-r--r--components/script/webdriver_handlers.rs17
133 files changed, 3122 insertions, 1471 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index 4645d2ce419..ee380e92854 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -23,11 +23,12 @@ tinyfiledialogs = {git = "https://github.com/jdm/tinyfiledialogs"}
[dependencies]
angle = {git = "https://github.com/servo/angle", branch = "servo"}
app_units = "0.3"
+audio-video-metadata = "0.1.2"
bitflags = "0.7"
canvas_traits = {path = "../canvas_traits"}
caseless = "0.1.0"
cookie = {version = "0.2.5", features = ["serialize-rustc"]}
-cssparser = {version = "0.5.7", features = ["heap_size", "serde-serialization"]}
+cssparser = {version = "0.7", features = ["heap_size", "serde-serialization"]}
devtools_traits = {path = "../devtools_traits"}
encoding = "0.2"
euclid = "0.10.1"
@@ -56,16 +57,15 @@ plugins = {path = "../plugins"}
profile_traits = {path = "../profile_traits"}
rand = "0.3"
range = {path = "../range"}
-ref_filter_map = "1.0"
ref_slice = "1.0"
regex = "0.1.43"
rustc-serialize = "0.3"
script_layout_interface = {path = "../script_layout_interface"}
script_traits = {path = "../script_traits"}
-selectors = {version = "0.11", features = ["heap_size"]}
+selectors = {version = "0.13", features = ["heap_size"]}
serde = "0.8"
smallvec = "0.1"
-string_cache = {version = "0.2.23", features = ["heap_size", "unstable"]}
+string_cache = {version = "0.2.26", features = ["heap_size", "unstable"]}
style = {path = "../style"}
time = "0.1.12"
url = {version = "1.2", features = ["heap_size", "query_encoding"]}
diff --git a/components/script/devtools.rs b/components/script/devtools.rs
index 024307bc696..d515d1fb99a 100644
--- a/components/script/devtools.rs
+++ b/components/script/devtools.rs
@@ -2,20 +2,21 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use devtools_traits::TimelineMarkerType;
use devtools_traits::{AutoMargins, CONSOLE_API, CachedConsoleMessage, CachedConsoleMessageTypes};
use devtools_traits::{ComputedNodeLayout, ConsoleAPI, PageError, ScriptToDevtoolsControlMsg};
use devtools_traits::{EvaluateJSReply, Modification, NodeInfo, PAGE_ERROR, TimelineMarker};
+use devtools_traits::TimelineMarkerType;
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
-use dom::bindings::conversions::{FromJSValConvertible, jsstring_to_str};
+use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, jsstring_to_str};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
+use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
use dom::browsingcontext::BrowsingContext;
use dom::element::Element;
@@ -27,9 +28,10 @@ use js::jsval::UndefinedValue;
use msg::constellation_msg::PipelineId;
use std::ffi::CStr;
use std::str;
-use style::properties::longhands::{margin_top, margin_right, margin_bottom, margin_left};
+use style::properties::longhands::{margin_bottom, margin_left, margin_right, margin_top};
use uuid::Uuid;
+
#[allow(unsafe_code)]
pub fn handle_evaluate_js(global: &GlobalRef, eval: String, reply: IpcSender<EvaluateJSReply>) {
// global.get_cx() returns a valid `JSContext` pointer, so this is safe.
@@ -45,8 +47,11 @@ pub fn handle_evaluate_js(global: &GlobalRef, eval: String, reply: IpcSender<Eva
} else if rval.is_boolean() {
EvaluateJSReply::BooleanValue(rval.to_boolean())
} else if rval.is_double() || rval.is_int32() {
- EvaluateJSReply::NumberValue(FromJSValConvertible::from_jsval(cx, rval.handle(), ())
- .unwrap())
+ EvaluateJSReply::NumberValue(
+ match FromJSValConvertible::from_jsval(cx, rval.handle(), ()) {
+ Ok(ConversionResult::Success(v)) => v,
+ _ => unreachable!(),
+ })
} else if rval.is_string() {
EvaluateJSReply::StringValue(String::from(jsstring_to_str(cx, rval.to_string())))
} else if rval.is_null() {
diff --git a/components/script/dom/abstractworker.rs b/components/script/dom/abstractworker.rs
index 28c755d4f03..6c5abd0d020 100644
--- a/components/script/dom/abstractworker.rs
+++ b/components/script/dom/abstractworker.rs
@@ -4,7 +4,6 @@
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::Reflectable;
-use dom::bindings::str::DOMString;
use dom::bindings::structuredclone::StructuredCloneData;
use js::jsapi::{JSRuntime, JS_RequestInterruptCallback};
use js::rust::Runtime;
@@ -30,27 +29,6 @@ impl<T: Reflectable> SimpleWorkerErrorHandler<T> {
}
}
-pub struct WorkerErrorHandler<T: Reflectable> {
- pub addr: Trusted<T>,
- pub msg: DOMString,
- pub file_name: DOMString,
- pub line_num: u32,
- pub col_num: u32,
-}
-
-impl<T: Reflectable> WorkerErrorHandler<T> {
- pub fn new(addr: Trusted<T>, msg: DOMString, file_name: DOMString, line_num: u32, col_num: u32)
- -> WorkerErrorHandler<T> {
- WorkerErrorHandler {
- addr: addr,
- msg: msg,
- file_name: file_name,
- line_num: line_num,
- col_num: col_num,
- }
- }
-}
-
#[derive(Copy, Clone)]
pub struct SharedRt {
pub rt: *mut JSRuntime
diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs
index d5a00e6c1fa..36de48a1f9b 100644
--- a/components/script/dom/attr.rs
+++ b/components/script/dom/attr.rs
@@ -15,10 +15,10 @@ use dom::element::{AttributeMutation, Element};
use dom::virtualmethods::vtable_for;
use dom::window::Window;
use std::borrow::ToOwned;
-use std::cell::Ref;
use std::mem;
use string_cache::{Atom, Namespace};
use style::attr::{AttrIdentifier, AttrValue};
+use style::refcell::Ref;
// https://dom.spec.whatwg.org/#interface-attr
#[dom_struct]
diff --git a/components/script/dom/bindings/callback.rs b/components/script/dom/bindings/callback.rs
index c34598a26be..7e6bb3534fb 100644
--- a/components/script/dom/bindings/callback.rs
+++ b/components/script/dom/bindings/callback.rs
@@ -7,11 +7,12 @@
use dom::bindings::error::{Error, Fallible, report_pending_exception};
use dom::bindings::global::global_root_from_object;
use dom::bindings::reflector::Reflectable;
-use js::jsapi::GetGlobalForObjectCrossCompartment;
-use js::jsapi::JS_GetProperty;
use js::jsapi::{Heap, MutableHandleObject, RootedObject};
use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject};
use js::jsapi::{JSCompartment, JS_EnterCompartment, JS_LeaveCompartment};
+use js::jsapi::GetGlobalForObjectCrossCompartment;
+use js::jsapi::JSAutoCompartment;
+use js::jsapi::JS_GetProperty;
use js::jsval::{JSVal, UndefinedValue};
use js::rust::RootedGuard;
use std::default::Default;
@@ -189,7 +190,8 @@ impl<'a> Drop for CallSetup<'a> {
unsafe {
JS_LeaveCompartment(self.cx, self.old_compartment);
if self.handling == ExceptionHandling::Report {
- report_pending_exception(self.cx, *self.exception_compartment);
+ let _ac = JSAutoCompartment::new(self.cx, *self.exception_compartment);
+ report_pending_exception(self.cx, true);
}
}
}
diff --git a/components/script/dom/bindings/cell.rs b/components/script/dom/bindings/cell.rs
deleted file mode 100644
index d1b40af5b1a..00000000000
--- a/components/script/dom/bindings/cell.rs
+++ /dev/null
@@ -1,139 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-//! A shareable mutable container for the DOM.
-
-use dom::bindings::trace::JSTraceable;
-use js::jsapi::JSTracer;
-use std::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut};
-use style::thread_state;
-use style::thread_state::SCRIPT;
-
-/// A mutable field in the DOM.
-///
-/// This extends the API of `core::cell::RefCell` to allow unsafe access in
-/// certain situations, with dynamic checking in debug builds.
-#[derive(Clone, HeapSizeOf)]
-pub struct DOMRefCell<T> {
- value: RefCell<T>,
-}
-
-// Functionality specific to Servo's `DOMRefCell` type
-// ===================================================
-
-impl<T> DOMRefCell<T> {
- /// Return a reference to the contents.
- ///
- /// For use in the layout thread only.
- #[allow(unsafe_code)]
- pub unsafe fn borrow_for_layout(&self) -> &T {
- debug_assert!(thread_state::get().is_layout());
- &*self.value.as_ptr()
- }
-
- /// Borrow the contents for the purpose of GC tracing.
- ///
- /// This succeeds even if the object is mutably borrowed,
- /// so you have to be careful in trace code!
- #[allow(unsafe_code)]
- pub unsafe fn borrow_for_gc_trace(&self) -> &T {
- // FIXME: IN_GC isn't reliable enough - doesn't catch minor GCs
- // https://github.com/servo/servo/issues/6389
- // debug_assert!(thread_state::get().contains(SCRIPT | IN_GC));
- &*self.value.as_ptr()
- }
-
- /// Borrow the contents for the purpose of script deallocation.
- ///
- #[allow(unsafe_code)]
- pub unsafe fn borrow_for_script_deallocation(&self) -> &mut T {
- debug_assert!(thread_state::get().contains(SCRIPT));
- &mut *self.value.as_ptr()
- }
-
- /// Version of the above that we use during restyle while the script thread
- /// is blocked.
- pub fn borrow_mut_for_layout(&self) -> RefMut<T> {
- debug_assert!(thread_state::get().is_layout());
- self.value.borrow_mut()
- }
-}
-
-impl<T: JSTraceable> JSTraceable for DOMRefCell<T> {
- fn trace(&self, trc: *mut JSTracer) {
- unsafe {
- (*self).borrow_for_gc_trace().trace(trc)
- }
- }
-}
-
-// Functionality duplicated with `core::cell::RefCell`
-// ===================================================
-impl<T> DOMRefCell<T> {
- /// Create a new `DOMRefCell` containing `value`.
- pub fn new(value: T) -> DOMRefCell<T> {
- DOMRefCell {
- value: RefCell::new(value),
- }
- }
-
-
- /// Immutably borrows the wrapped value.
- ///
- /// The borrow lasts until the returned `Ref` exits scope. Multiple
- /// immutable borrows can be taken out at the same time.
- ///
- /// # Panics
- ///
- /// Panics if this is called off the script thread.
- ///
- /// Panics if the value is currently mutably borrowed.
- pub fn borrow(&self) -> Ref<T> {
- self.try_borrow().expect("DOMRefCell<T> already mutably borrowed")
- }
-
- /// Mutably borrows the wrapped value.
- ///
- /// The borrow lasts until the returned `RefMut` exits scope. The value
- /// cannot be borrowed while this borrow is active.
- ///
- /// # Panics
- ///
- /// Panics if this is called off the script thread.
- ///
- /// Panics if the value is currently borrowed.
- pub fn borrow_mut(&self) -> RefMut<T> {
- self.try_borrow_mut().expect("DOMRefCell<T> already borrowed")
- }
-
- /// Attempts to immutably borrow the wrapped value.
- ///
- /// The borrow lasts until the returned `Ref` exits scope. Multiple
- /// immutable borrows can be taken out at the same time.
- ///
- /// Returns `None` if the value is currently mutably borrowed.
- ///
- /// # Panics
- ///
- /// Panics if this is called off the script thread.
- pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError<T>> {
- debug_assert!(thread_state::get().is_script());
- self.value.try_borrow()
- }
-
- /// Mutably borrows the wrapped value.
- ///
- /// The borrow lasts until the returned `RefMut` exits scope. The value
- /// cannot be borrowed while this borrow is active.
- ///
- /// Returns `None` if the value is currently borrowed.
- ///
- /// # Panics
- ///
- /// Panics if this is called off the script thread.
- pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError<T>> {
- debug_assert!(thread_state::get().is_script());
- self.value.try_borrow_mut()
- }
-}
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 8a288694431..486758182d2 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -18,17 +18,21 @@ from WebIDL import (
BuiltinTypes,
IDLBuiltinType,
IDLNullValue,
+ IDLNullableType,
IDLType,
IDLInterfaceMember,
IDLUndefinedValue,
+ IDLWrapperType,
)
from Configuration import (
+ MakeNativeName,
MemberIsUnforgeable,
getModuleFromObject,
getTypesFromCallback,
getTypesFromDescriptor,
getTypesFromDictionary,
+ iteratorNativeType
)
AUTOGENERATED_WARNING_COMMENT = \
@@ -77,7 +81,7 @@ def toStringBool(arg):
def toBindingNamespace(arg):
- return re.sub("((_workers)?$)", "Binding\\1", arg)
+ return re.sub("((_workers)?$)", "Binding\\1", MakeNativeName(arg))
def stripTrailingWhitespace(text):
@@ -93,9 +97,6 @@ def innerSequenceType(type):
return type.inner.inner if type.nullable() else type.inner
-def MakeNativeName(name):
- return name[0].upper() + name[1:]
-
builtinNames = {
IDLType.Tags.bool: 'bool',
IDLType.Tags.int8: 'i8',
@@ -719,7 +720,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
raise TypeError("Can't handle array arguments yet")
if type.isSequence():
- innerInfo = getJSToNativeConversionInfo(innerSequenceType(type), descriptorProvider)
+ innerInfo = getJSToNativeConversionInfo(innerSequenceType(type),
+ descriptorProvider,
+ isMember=isMember)
declType = CGWrapper(innerInfo.declType, pre="Vec<", post=">")
config = getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs)
@@ -727,9 +730,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
declType = CGWrapper(declType, pre="Option<", post=" >")
templateBody = ("match FromJSValConvertible::from_jsval(cx, ${val}, %s) {\n"
- " Ok(value) => value,\n"
- " Err(()) => { %s },\n"
- "}" % (config, exceptionCode))
+ " Ok(ConversionResult::Success(value)) => value,\n"
+ " Ok(ConversionResult::Failure(error)) => {\n"
+ " throw_type_error(cx, &error);\n"
+ " %s\n"
+ " }\n"
+ " _ => { %s },\n"
+ "}" % (config, exceptionCode, exceptionCode))
return handleOptional(templateBody, declType, handleDefaultNull("None"))
@@ -739,9 +746,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
declType = CGWrapper(declType, pre="Option<", post=" >")
templateBody = ("match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n"
- " Ok(value) => value,\n"
- " Err(()) => { %s },\n"
- "}" % exceptionCode)
+ " Ok(ConversionResult::Success(value)) => value,\n"
+ " Ok(ConversionResult::Failure(error)) => {\n"
+ " throw_type_error(cx, &error);\n"
+ " %s\n"
+ " }\n"
+ " _ => { %s },\n"
+ "}" % (exceptionCode, exceptionCode))
return handleOptional(templateBody, declType, handleDefaultNull("None"))
@@ -810,9 +821,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
conversionCode = (
"match FromJSValConvertible::from_jsval(cx, ${val}, %s) {\n"
- " Ok(strval) => strval,\n"
- " Err(_) => { %s },\n"
- "}" % (nullBehavior, exceptionCode))
+ " Ok(ConversionResult::Success(strval)) => strval,\n"
+ " Ok(ConversionResult::Failure(error)) => {\n"
+ " throw_type_error(cx, &error);\n"
+ " %s\n"
+ " }\n"
+ " _ => { %s },\n"
+ "}" % (nullBehavior, exceptionCode, exceptionCode))
if defaultValue is None:
default = None
@@ -836,9 +851,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
conversionCode = (
"match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n"
- " Ok(strval) => strval,\n"
- " Err(_) => { %s },\n"
- "}" % exceptionCode)
+ " Ok(ConversionResult::Success(strval)) => strval,\n"
+ " Ok(ConversionResult::Failure(error)) => {\n"
+ " throw_type_error(cx, &error);\n"
+ " %s\n"
+ " }\n"
+ " _ => { %s },\n"
+ "}" % (exceptionCode, exceptionCode))
if defaultValue is None:
default = None
@@ -862,9 +881,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
conversionCode = (
"match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n"
- " Ok(strval) => strval,\n"
- " Err(_) => { %s },\n"
- "}" % exceptionCode)
+ " Ok(ConversionResult::Success(strval)) => strval,\n"
+ " Ok(ConversionResult::Failure(error)) => {\n"
+ " throw_type_error(cx, &error);\n"
+ " %s\n"
+ " }\n"
+ " _ => { %s },\n"
+ "}" % (exceptionCode, exceptionCode))
if defaultValue is None:
default = None
@@ -922,7 +945,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
assert not type.treatNonObjectAsNull() or not type.treatNonCallableAsNull()
callback = type.unroll().callback
- declType = CGGeneric('%s::%s' % (getModuleFromObject(callback), callback.identifier.name))
+ declType = CGGeneric(callback.identifier.name)
finalDeclType = CGTemplatedType("Rc", declType)
conversion = CGCallbackTempRoot(declType.define())
@@ -1017,9 +1040,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
CGDictionary.makeDictionaryName(type.inner))
declType = CGGeneric(typeName)
template = ("match %s::new(cx, ${val}) {\n"
- " Ok(dictionary) => dictionary,\n"
- " Err(_) => { %s },\n"
- "}" % (typeName, exceptionCode))
+ " Ok(ConversionResult::Success(dictionary)) => dictionary,\n"
+ " Ok(ConversionResult::Failure(error)) => {\n"
+ " throw_type_error(cx, &error);\n"
+ " %s\n"
+ " }\n"
+ " _ => { %s },\n"
+ "}" % (typeName, exceptionCode, exceptionCode))
return handleOptional(template, declType, handleDefaultNull("%s::empty(cx)" % typeName))
@@ -1042,9 +1069,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
template = (
"match FromJSValConvertible::from_jsval(cx, ${val}, %s) {\n"
- " Ok(v) => v,\n"
- " Err(_) => { %s }\n"
- "}" % (conversionBehavior, exceptionCode))
+ " Ok(ConversionResult::Success(v)) => v,\n"
+ " Ok(ConversionResult::Failure(error)) => {\n"
+ " throw_type_error(cx, &error);\n"
+ " %s\n"
+ " }\n"
+ " _ => { %s }\n"
+ "}" % (conversionBehavior, exceptionCode, exceptionCode))
if defaultValue is not None:
if isinstance(defaultValue, IDLNullValue):
@@ -1103,20 +1134,20 @@ def instantiateJSToNativeConversionTemplate(templateBody, replacements,
def convertConstIDLValueToJSVal(value):
if isinstance(value, IDLNullValue):
- return "NullVal"
+ return "ConstantVal::NullVal"
tag = value.type.tag()
if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
IDLType.Tags.uint16, IDLType.Tags.int32]:
- return "IntVal(%s)" % (value.value)
+ return "ConstantVal::IntVal(%s)" % (value.value)
if tag == IDLType.Tags.uint32:
- return "UintVal(%s)" % (value.value)
+ return "ConstantVal::UintVal(%s)" % (value.value)
if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]:
- return "DoubleVal(%s)" % (value.value)
+ return "ConstantVal::DoubleVal(%s)" % (value.value)
if tag == IDLType.Tags.bool:
- return "BoolVal(true)" if value.value else "BoolVal(false)"
+ return "ConstantVal::BoolVal(true)" if value.value else "ConstantVal::BoolVal(false)"
if tag in [IDLType.Tags.unrestricted_float, IDLType.Tags.float,
IDLType.Tags.unrestricted_double, IDLType.Tags.double]:
- return "DoubleVal(%s)" % (value.value)
+ return "ConstantVal::DoubleVal(%s)" % (value.value)
raise TypeError("Const value of unhandled type: " + value.type)
@@ -1317,7 +1348,10 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
if returnType.isAny():
return CGGeneric("JSVal")
if returnType.isObject() or returnType.isSpiderMonkeyInterface():
- return CGGeneric("*mut JSObject")
+ result = CGGeneric("NonZero<*mut JSObject>")
+ if returnType.nullable():
+ result = CGWrapper(result, pre="Option<", post=">")
+ return result
if returnType.isSequence():
result = getRetvalDeclarationForType(innerSequenceType(returnType), descriptorProvider)
result = CGWrapper(result, pre="Vec<", post=">")
@@ -1490,6 +1524,46 @@ class MethodDefiner(PropertyDefiner):
"length": 0,
"condition": "Condition::Satisfied"})
+ # Generate the keys/values/entries aliases for value iterables.
+ maplikeOrSetlikeOrIterable = descriptor.interface.maplikeOrSetlikeOrIterable
+ if (not static and not unforgeable and
+ (maplikeOrSetlikeOrIterable and
+ maplikeOrSetlikeOrIterable.isIterable() and
+ maplikeOrSetlikeOrIterable.isValueIterator())):
+ # Add our keys/values/entries/forEach
+ self.regular.append({
+ "name": "keys",
+ "methodInfo": False,
+ "selfHostedName": "ArrayKeys",
+ "length": 0,
+ "condition": PropertyDefiner.getControllingCondition(m,
+ descriptor)
+ })
+ self.regular.append({
+ "name": "values",
+ "methodInfo": False,
+ "selfHostedName": "ArrayValues",
+ "length": 0,
+ "condition": PropertyDefiner.getControllingCondition(m,
+ descriptor)
+ })
+ self.regular.append({
+ "name": "entries",
+ "methodInfo": False,
+ "selfHostedName": "ArrayEntries",
+ "length": 0,
+ "condition": PropertyDefiner.getControllingCondition(m,
+ descriptor)
+ })
+ self.regular.append({
+ "name": "forEach",
+ "methodInfo": False,
+ "selfHostedName": "ArrayForEach",
+ "length": 0,
+ "condition": PropertyDefiner.getControllingCondition(m,
+ descriptor)
+ })
+
isUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("Unforgeable"))
if not static and unforgeable == isUnforgeableInterface:
stringifier = descriptor.operations['Stringifier']
@@ -1598,7 +1672,8 @@ class AttrDefiner(PropertyDefiner):
"native": accessor})
def setter(attr):
- if attr.readonly and not attr.getExtendedAttribute("PutForwards"):
+ if (attr.readonly and not attr.getExtendedAttribute("PutForwards")
+ and not attr.getExtendedAttribute("Replaceable")):
return "JSNativeWrapper { op: None, info: 0 as *const JSJitInfo }"
if self.static:
@@ -1710,7 +1785,7 @@ class CGImports(CGWrapper):
"""
Generates the appropriate import/use statements.
"""
- def __init__(self, child, descriptors, callbacks, imports, config, ignored_warnings=None):
+ def __init__(self, child, descriptors, callbacks, dictionaries, enums, imports, config, ignored_warnings=None):
"""
Adds a set of imports.
"""
@@ -1724,17 +1799,20 @@ class CGImports(CGWrapper):
]
def componentTypes(type):
- if type.nullable():
+ if type.isType() and type.nullable():
type = type.unroll()
if type.isUnion():
return type.flatMemberTypes
+ if type.isDictionary():
+ return [type] + getTypesFromDictionary(type)
return [type]
def isImportable(type):
if not type.isType():
- assert type.isInterface()
- return not type.isCallback()
- return type.isNonCallbackInterface() and not type.builtin
+ assert (type.isInterface() or type.isDictionary() or
+ type.isEnum() or type.isNamespace())
+ return True
+ return not (type.builtin or type.isSequence() or type.isUnion())
def relatedTypesForSignatures(method):
types = []
@@ -1746,13 +1824,30 @@ class CGImports(CGWrapper):
def getIdentifier(t):
if t.isType():
- return t.inner.identifier
- assert t.isInterface()
+ if t.nullable():
+ t = t.inner
+ if t.isCallback():
+ return t.callback.identifier
+ return t.identifier
+ assert t.isInterface() or t.isDictionary() or t.isEnum() or t.isNamespace()
return t.identifier
+ def removeWrapperAndNullableTypes(types):
+ normalized = []
+ for t in types:
+ while (t.isType() and t.nullable()) or isinstance(t, IDLWrapperType):
+ t = t.inner
+ if isImportable(t):
+ normalized += [t]
+ return normalized
+
types = []
for d in descriptors:
- types += [d.interface]
+ if not d.interface.isCallback():
+ types += [d.interface]
+
+ if d.interface.isIteratorInterface():
+ types += [d.interface.iterableInterface]
members = d.interface.members + d.interface.namedConstructors
constructor = d.interface.ctor()
@@ -1768,19 +1863,39 @@ class CGImports(CGWrapper):
elif m.isAttr():
types += componentTypes(m.type)
+ # Import the type names used in the callbacks that are being defined.
for c in callbacks:
types += relatedTypesForSignatures(c)
+ # Import the type names used in the dictionaries that are being defined.
+ for d in dictionaries:
+ types += componentTypes(d)
+
+ # Normalize the types we've collected and remove any ones which can't be imported.
+ types = removeWrapperAndNullableTypes(types)
+
descriptorProvider = config.getDescriptorProvider()
+ extras = []
for t in types:
- if isImportable(t):
+ # Importing these types in the same module that defines them is an error.
+ if t in dictionaries or t in enums:
+ continue
+ if t.isInterface() or t.isNamespace():
descriptor = descriptorProvider.getDescriptor(getIdentifier(t).name)
- imports += ['%s' % descriptor.path]
+ extras += [descriptor.path]
+ if descriptor.interface.parent:
+ parentName = getIdentifier(descriptor.interface.parent).name
+ descriptor = descriptorProvider.getDescriptor(parentName)
+ extras += [descriptor.path, descriptor.bindingPath]
+ else:
+ if t.isEnum():
+ extras += [getModuleFromObject(t) + '::' + getIdentifier(t).name + 'Values']
+ extras += [getModuleFromObject(t) + '::' + getIdentifier(t).name]
statements = []
if len(ignored_warnings) > 0:
statements.append('#![allow(%s)]' % ','.join(ignored_warnings))
- statements.extend('use %s;' % i for i in sorted(set(imports)))
+ statements.extend('use %s;' % i for i in sorted(set(imports + extras)))
CGWrapper.__init__(self, child,
pre='\n'.join(statements) + '\n\n')
@@ -1840,7 +1955,7 @@ def DOMClass(descriptor):
# padding.
protoList.extend(['PrototypeList::ID::Last'] * (descriptor.config.maxProtoChainLength - len(protoList)))
prototypeChainString = ', '.join(protoList)
- heapSizeOf = 'heap_size_of_raw_self_and_children::<%s>' % descriptor.interface.identifier.name
+ heapSizeOf = 'heap_size_of_raw_self_and_children::<%s>' % descriptor.concreteType
if descriptor.isGlobal():
globals_ = camel_to_upper_snake(descriptor.name)
else:
@@ -1883,7 +1998,7 @@ class CGDOMJSClass(CGThing):
elif self.descriptor.weakReferenceable:
args["slots"] = "2"
return """\
-static CLASS_OPS: js::jsapi::ClassOps = js::jsapi::ClassOps {
+static CLASS_OPS: js::jsapi::JSClassOps = js::jsapi::JSClassOps {
addProperty: None,
delProperty: None,
getProperty: None,
@@ -1899,15 +2014,13 @@ static CLASS_OPS: js::jsapi::ClassOps = js::jsapi::ClassOps {
};
static Class: DOMJSClass = DOMJSClass {
- base: js::jsapi::Class {
+ base: js::jsapi::JSClass {
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) */,
cOps: &CLASS_OPS,
- spec: ptr::null(),
- ext: ptr::null(),
- oOps: ptr::null(),
+ reserved: [0 as *mut _; 3],
},
dom_class: %(domClass)s
};""" % args
@@ -1946,6 +2059,17 @@ class CGInterfaceObjectJSClass(CGThing):
self.descriptor = descriptor
def define(self):
+ if self.descriptor.interface.isNamespace():
+ classString = self.descriptor.interface.getExtendedAttribute("ClassString")
+ if classString:
+ classString = classString[0]
+ else:
+ classString = "Object"
+ return """\
+static NAMESPACE_OBJECT_CLASS: NamespaceObjectClass = unsafe {
+ NamespaceObjectClass::new(%s)
+};
+""" % str_to_const_array(classString)
if self.descriptor.interface.ctor():
constructorBehavior = "InterfaceConstructorBehavior::call(%s)" % CONSTRUCT_HOOK_NAME
else:
@@ -1958,12 +2082,9 @@ class CGInterfaceObjectJSClass(CGThing):
"depth": self.descriptor.prototypeDepth
}
return """\
-static INTERFACE_OBJECT_OPS: js::jsapi::ClassOps =
- NonCallbackInterfaceObjectClass::ops(%(constructorBehavior)s);
-
-static InterfaceObjectClass: NonCallbackInterfaceObjectClass =
+static INTERFACE_OBJECT_CLASS: NonCallbackInterfaceObjectClass =
NonCallbackInterfaceObjectClass::new(
- &INTERFACE_OBJECT_OPS,
+ &%(constructorBehavior)s,
%(representation)s,
PrototypeList::ID::%(id)s,
%(depth)s);
@@ -2023,7 +2144,7 @@ class CGCallbackTempRoot(CGGeneric):
CGGeneric.__init__(self, "%s::new(${val}.get().to_object())" % name)
-def getAllTypes(descriptors, dictionaries, callbacks):
+def getAllTypes(descriptors, dictionaries, callbacks, typedefs):
"""
Generate all the types we're dealing with. For each type, a tuple
containing type, descriptor, dictionary is yielded. The
@@ -2039,15 +2160,18 @@ def getAllTypes(descriptors, dictionaries, callbacks):
for callback in callbacks:
for t in getTypesFromCallback(callback):
yield (t, None, None)
+ for typedef in typedefs:
+ yield (typedef.innerType, None, None)
-def UnionTypes(descriptors, dictionaries, callbacks, config):
+def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
"""
Returns a CGList containing CGUnionStructs for every union.
"""
imports = [
'dom::bindings::codegen::PrototypeList',
+ 'dom::bindings::conversions::ConversionResult',
'dom::bindings::conversions::FromJSValConvertible',
'dom::bindings::conversions::ToJSValConvertible',
'dom::bindings::conversions::ConversionBehavior',
@@ -2055,17 +2179,21 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
'dom::bindings::conversions::root_from_handlevalue',
'dom::bindings::error::throw_not_in_union',
'dom::bindings::js::Root',
- 'dom::bindings::str::{ByteString, DOMString, USVString}',
+ 'dom::bindings::str::ByteString',
+ 'dom::bindings::str::DOMString',
+ 'dom::bindings::str::USVString',
'dom::types::*',
+ 'js::error::throw_type_error',
+ 'js::jsapi::HandleValue',
'js::jsapi::JSContext',
- 'js::jsapi::{HandleValue, MutableHandleValue}',
+ 'js::jsapi::MutableHandleValue',
'js::jsval::JSVal',
]
# Now find all the things we'll need as arguments and return values because
# we need to wrap or unwrap them.
unionStructs = dict()
- for (t, descriptor, dictionary) in getAllTypes(descriptors, dictionaries, callbacks):
+ for (t, descriptor, dictionary) in getAllTypes(descriptors, dictionaries, callbacks, typedefs):
assert not descriptor or not dictionary
t = t.unroll()
if not t.isUnion():
@@ -2081,7 +2209,14 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
# Sort unionStructs by key, retrieve value
unionStructs = (i[1] for i in sorted(unionStructs.items(), key=operator.itemgetter(0)))
- return CGImports(CGList(unionStructs, "\n\n"), [], [], imports, config, ignored_warnings=[])
+ return CGImports(CGList(unionStructs, "\n\n"),
+ descriptors=[],
+ callbacks=[],
+ dictionaries=[],
+ enums=[],
+ imports=imports,
+ config=config,
+ ignored_warnings=[])
class Argument():
@@ -2255,9 +2390,9 @@ class CGConstructorEnabled(CGAbstractMethod):
def CreateBindingJSObject(descriptor, parent=None):
+ assert not descriptor.isGlobal()
create = "let raw = Box::into_raw(object);\nlet _rt = RootedTraceable::new(&*raw);\n"
if descriptor.proxy:
- assert not descriptor.isGlobal()
create += """
let handler = RegisterBindings::proxy_handlers[PrototypeList::Proxies::%s as usize];
rooted!(in(cx) let private = PrivateValue(raw as *const libc::c_void));
@@ -2268,18 +2403,9 @@ let obj = NewProxyObject(cx, handler,
assert!(!obj.is_null());
rooted!(in(cx) let obj = obj);\
""" % (descriptor.name, parent)
- elif descriptor.isGlobal():
- create += ("rooted!(in(cx) let obj =\n"
- " create_dom_global(\n"
- " cx,\n"
- " &Class.base as *const js::jsapi::Class as *const JSClass,\n"
- " raw as *const libc::c_void,\n"
- " Some(%s))\n"
- ");\n"
- "assert!(!obj.is_null());" % TRACE_HOOK_NAME)
else:
create += ("rooted!(in(cx) let obj = JS_NewObjectWithGivenProto(\n"
- " cx, &Class.base as *const js::jsapi::Class as *const JSClass, proto.handle()));\n"
+ " cx, &Class.base as *const JSClass, proto.handle()));\n"
"assert!(!obj.is_null());\n"
"\n"
"JS_SetReservedSlot(obj.get(), DOM_OBJECT_SLOT,\n"
@@ -2355,21 +2481,17 @@ class CGWrapMethod(CGAbstractMethod):
"""
def __init__(self, descriptor):
assert not descriptor.interface.isCallback()
- if not descriptor.isGlobal():
- args = [Argument('*mut JSContext', 'cx'), Argument('GlobalRef', 'scope'),
- Argument("Box<%s>" % descriptor.concreteType, 'object')]
- else:
- args = [Argument('*mut JSContext', 'cx'),
- Argument("Box<%s>" % descriptor.concreteType, 'object')]
+ assert not descriptor.isGlobal()
+ args = [Argument('*mut JSContext', 'cx'), Argument('GlobalRef', 'scope'),
+ Argument("Box<%s>" % descriptor.concreteType, 'object')]
retval = 'Root<%s>' % descriptor.concreteType
CGAbstractMethod.__init__(self, descriptor, 'Wrap', retval, args,
pub=True, unsafe=True)
def definition_body(self):
unforgeable = CopyUnforgeablePropertiesToInstance(self.descriptor)
- if not self.descriptor.isGlobal():
- create = CreateBindingJSObject(self.descriptor, "scope")
- return CGGeneric("""\
+ create = CreateBindingJSObject(self.descriptor, "scope")
+ return CGGeneric("""\
let scope = scope.reflector().get_jsobject();
assert!(!scope.get().is_null());
assert!(((*JS_GetClass(scope.get())).flags & JSCLASS_IS_GLOBAL) != 0);
@@ -2385,21 +2507,65 @@ assert!(!proto.is_null());
(*raw).init_reflector(obj.get());
Root::from_ref(&*raw)""" % {'copyUnforgeable': unforgeable, 'createObject': create})
- else:
- create = CreateBindingJSObject(self.descriptor)
- return CGGeneric("""\
-%(createObject)s
+
+
+class CGWrapGlobalMethod(CGAbstractMethod):
+ """
+ Class that generates the FooBinding::Wrap function for global interfaces.
+ """
+ def __init__(self, descriptor, properties):
+ assert not descriptor.interface.isCallback()
+ assert descriptor.isGlobal()
+ args = [Argument('*mut JSContext', 'cx'),
+ Argument("Box<%s>" % descriptor.concreteType, 'object')]
+ retval = 'Root<%s>' % descriptor.concreteType
+ CGAbstractMethod.__init__(self, descriptor, 'Wrap', retval, args,
+ pub=True, unsafe=True)
+ self.properties = properties
+
+ def definition_body(self):
+ values = {
+ "unforgeable": CopyUnforgeablePropertiesToInstance(self.descriptor)
+ }
+
+ pairs = [
+ ("define_guarded_properties", self.properties.attrs),
+ ("define_guarded_methods", self.properties.methods),
+ ("define_guarded_constants", self.properties.consts)
+ ]
+ members = ["%s(cx, obj.handle(), %s);" % (function, array.variableName())
+ for (function, array) in pairs if array.length() > 0]
+ values["members"] = "\n".join(members)
+
+ return CGGeneric("""\
+let raw = Box::into_raw(object);
+let _rt = RootedTraceable::new(&*raw);
+
+rooted!(in(cx) let mut obj = ptr::null_mut());
+create_global_object(
+ cx,
+ &Class.base,
+ raw as *const libc::c_void,
+ _trace,
+ obj.handle_mut());
+assert!(!obj.is_null());
+
(*raw).init_reflector(obj.get());
let _ac = JSAutoCompartment::new(cx, obj.get());
rooted!(in(cx) let mut proto = ptr::null_mut());
GetProtoObject(cx, obj.handle(), proto.handle_mut());
-JS_SetPrototype(cx, obj.handle(), proto.handle());
+assert!(JS_SplicePrototype(cx, obj.handle(), proto.handle()));
+let mut immutable = false;
+assert!(JS_SetImmutablePrototype(cx, obj.handle(), &mut immutable));
+assert!(immutable);
-%(copyUnforgeable)s
+%(members)s
+
+%(unforgeable)s
Root::from_ref(&*raw)\
-""" % {'copyUnforgeable': unforgeable, 'createObject': create})
+""" % values)
class CGIDLInterface(CGThing):
@@ -2412,7 +2578,7 @@ class CGIDLInterface(CGThing):
def define(self):
interface = self.descriptor.interface
- name = self.descriptor.name
+ name = self.descriptor.concreteType
if (interface.getUserData("hasConcreteDescendant", False) or
interface.getUserData("hasProxyDescendant", False)):
depth = self.descriptor.prototypeDepth
@@ -2503,6 +2669,28 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
def definition_body(self):
name = self.descriptor.interface.identifier.name
+ if self.descriptor.interface.isNamespace():
+ if self.descriptor.interface.getExtendedAttribute("ProtoObjectHack"):
+ proto = "JS_GetObjectPrototype(cx, global)"
+ else:
+ proto = "JS_NewPlainObject(cx)"
+ if self.properties.static_methods.length():
+ methods = self.properties.static_methods.variableName()
+ else:
+ methods = "&[]"
+ return CGGeneric("""\
+rooted!(in(cx) let proto = %(proto)s);
+assert!(!proto.is_null());
+rooted!(in(cx) let mut namespace = ptr::null_mut());
+create_namespace_object(cx, global, proto.handle(), &NAMESPACE_OBJECT_CLASS,
+ %(methods)s, %(name)s, namespace.handle_mut());
+assert!(!namespace.is_null());
+assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
+(*cache)[PrototypeList::Constructor::%(id)s as usize] = namespace.get();
+<*mut JSObject>::post_barrier((*cache).as_mut_ptr().offset(PrototypeList::Constructor::%(id)s as isize),
+ ptr::null_mut(),
+ namespace.get());
+""" % {"id": MakeNativeName(name), "methods": methods, "name": str_to_const_array(name), "proto": proto})
if self.descriptor.interface.isCallback():
assert not self.descriptor.interface.ctor() and self.descriptor.interface.hasConstants()
return CGGeneric("""\
@@ -2519,6 +2707,8 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
if len(self.descriptor.prototypeChain) == 1:
if self.descriptor.interface.getExtendedAttribute("ExceptionClass"):
getPrototypeProto = "prototype_proto.set(JS_GetErrorPrototype(cx))"
+ elif self.descriptor.interface.isIteratorInterface():
+ getPrototypeProto = "prototype_proto.set(JS_GetIteratorPrototype(cx))"
else:
getPrototypeProto = "prototype_proto.set(JS_GetObjectPrototype(cx, global))"
else:
@@ -2541,6 +2731,18 @@ assert!(!prototype_proto.is_null());""" % getPrototypeProto)]
else:
properties[arrayName] = "&[]"
+ if self.descriptor.isGlobal():
+ assert not self.haveUnscopables
+ proto_properties = {
+ "attrs": "&[]",
+ "consts": "&[]",
+ "id": name,
+ "methods": "&[]",
+ "unscopables": "&[]",
+ }
+ else:
+ proto_properties = properties
+
code.append(CGGeneric("""
rooted!(in(cx) let mut prototype = ptr::null_mut());
create_interface_prototype_object(cx,
@@ -2557,7 +2759,7 @@ assert!((*cache)[PrototypeList::ID::%(id)s as usize].is_null());
<*mut JSObject>::post_barrier((*cache).as_mut_ptr().offset(PrototypeList::ID::%(id)s as isize),
ptr::null_mut(),
prototype.get());
-""" % properties))
+""" % proto_properties))
if self.descriptor.interface.hasInterfaceObject():
properties["name"] = str_to_const_array(name)
@@ -2580,7 +2782,7 @@ rooted!(in(cx) let mut interface = ptr::null_mut());
create_noncallback_interface_object(cx,
global,
interface_proto.handle(),
- &InterfaceObjectClass,
+ &INTERFACE_OBJECT_CLASS,
%(static_methods)s,
%(static_attrs)s,
%(consts)s,
@@ -2598,15 +2800,64 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
interface.get());
""" % properties))
+ aliasedMembers = [m for m in self.descriptor.interface.members if m.isMethod() and m.aliases]
+ if aliasedMembers:
+ def defineAlias(alias):
+ if alias == "@@iterator":
+ symbolJSID = "RUST_SYMBOL_TO_JSID(GetWellKnownSymbol(cx, SymbolCode::iterator))"
+ getSymbolJSID = CGGeneric(fill("rooted!(in(cx) let iteratorId = ${symbolJSID});",
+ symbolJSID=symbolJSID))
+ defineFn = "JS_DefinePropertyById2"
+ prop = "iteratorId.handle()"
+ elif alias.startswith("@@"):
+ raise TypeError("Can't handle any well-known Symbol other than @@iterator")
+ else:
+ getSymbolJSID = None
+ defineFn = "JS_DefineProperty"
+ prop = '"%s"' % alias
+ return CGList([
+ getSymbolJSID,
+ # XXX If we ever create non-enumerable properties that can
+ # be aliased, we should consider making the aliases
+ # match the enumerability of the property being aliased.
+ CGGeneric(fill(
+ """
+ assert!(${defineFn}(cx, prototype.handle(), ${prop}, aliasedVal.handle(),
+ JSPROP_ENUMERATE, None, None));
+ """,
+ defineFn=defineFn,
+ prop=prop))
+ ], "\n")
+
+ def defineAliasesFor(m):
+ return CGList([
+ CGGeneric(fill(
+ """
+ assert!(JS_GetProperty(cx, prototype.handle(),
+ b\"${prop}\0\" as *const u8 as *const _,
+ aliasedVal.handle_mut()));
+ """,
+ prop=m.identifier.name))
+ ] + [defineAlias(alias) for alias in sorted(m.aliases)])
+
+ defineAliases = CGList([
+ CGGeneric(fill("""
+ // Set up aliases on the interface prototype object we just created.
+
+ """)),
+ CGGeneric("rooted!(in(cx) let mut aliasedVal = UndefinedValue());\n\n")
+ ] + [defineAliasesFor(m) for m in sorted(aliasedMembers)])
+ code.append(defineAliases)
+
constructors = self.descriptor.interface.namedConstructors
if constructors:
- decl = "let named_constructors: [(NonNullJSNative, &'static [u8], u32); %d]" % len(constructors)
+ decl = "let named_constructors: [(ConstructorClassHook, &'static [u8], u32); %d]" % len(constructors)
specs = []
for constructor in constructors:
hook = CONSTRUCT_HOOK_NAME + "_" + constructor.identifier.name
name = str_to_const_array(constructor.identifier.name)
length = methodLength(constructor)
- specs.append(CGGeneric("(%s as NonNullJSNative, %s, %d)" % (hook, name, length)))
+ specs.append(CGGeneric("(%s as ConstructorClassHook, %s, %d)" % (hook, name, length)))
values = CGIndenter(CGList(specs, "\n"), 4)
code.append(CGWrapper(values, pre="%s = [\n" % decl, post="\n];"))
code.append(CGGeneric("create_named_constructors(cx, global, &named_constructors, prototype.handle());"))
@@ -2627,7 +2878,7 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
holderClass = "ptr::null()"
holderProto = "HandleObject::null()"
else:
- holderClass = "&Class.base as *const js::jsapi::Class as *const JSClass"
+ holderClass = "&Class.base as *const JSClass"
holderProto = "prototype.handle()"
code.append(CGGeneric("""
rooted!(in(cx) let mut unforgeable_holder = ptr::null_mut());
@@ -2654,7 +2905,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
Argument('MutableHandleObject', 'rval')]
CGAbstractMethod.__init__(self, descriptor, name,
'void', args, pub=pub, unsafe=True)
- self.id = idPrefix + "::" + self.descriptor.name
+ self.id = idPrefix + "::" + MakeNativeName(self.descriptor.name)
def definition_body(self):
return CGGeneric("""
@@ -2679,7 +2930,7 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
"""
def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject",
- "PrototypeList::ID", pub=descriptor.hasDescendants())
+ "PrototypeList::ID", pub=True)
def definition_body(self):
return CGList([
@@ -2697,7 +2948,7 @@ class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetConstructorObject",
"PrototypeList::Constructor",
- pub=descriptor.hasDescendants())
+ pub=True)
def definition_body(self):
return CGList([
@@ -2797,7 +3048,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
return CGAbstractMethod.define(self)
def definition_body(self):
- if self.descriptor.interface.isCallback():
+ if self.descriptor.interface.isCallback() or self.descriptor.interface.isNamespace():
function = "GetConstructorObject"
else:
function = "GetProtoObject"
@@ -2828,7 +3079,7 @@ class CGCallGenerator(CGThing):
exception from the native code, or None if no error reporting is needed.
"""
def __init__(self, errorResult, arguments, argsPre, returnType,
- extendedAttributes, descriptorProvider, nativeMethodName,
+ extendedAttributes, descriptor, nativeMethodName,
static, object="this"):
CGThing.__init__(self)
@@ -2836,7 +3087,7 @@ class CGCallGenerator(CGThing):
isFallible = errorResult is not None
- result = getRetvalDeclarationForType(returnType, descriptorProvider)
+ result = getRetvalDeclarationForType(returnType, descriptor)
if isFallible:
result = CGWrapper(result, pre="Result<", post=", Error>")
@@ -2857,7 +3108,7 @@ class CGCallGenerator(CGThing):
call = CGGeneric(nativeMethodName)
if static:
- call = CGWrapper(call, pre="%s::" % descriptorProvider.interface.identifier.name)
+ call = CGWrapper(call, pre="%s::" % MakeNativeName(descriptor.interface.identifier.name))
else:
call = CGWrapper(call, pre="%s." % object)
call = CGList([call, CGWrapper(args, pre="(", post=")")])
@@ -2936,11 +3187,21 @@ class CGPerSignatureCall(CGThing):
if self.isFallible():
errorResult = " false"
- cgThings.append(CGCallGenerator(
- errorResult,
- self.getArguments(), self.argsPre, returnType,
- self.extendedAttributes, descriptor, nativeMethodName,
- static))
+ if idlNode.isMethod() and idlNode.isMaplikeOrSetlikeOrIterableMethod():
+ if idlNode.maplikeOrSetlikeOrIterable.isMaplike() or \
+ idlNode.maplikeOrSetlikeOrIterable.isSetlike():
+ raise TypeError('Maplike/Setlike methods are not supported yet')
+ else:
+ cgThings.append(CGIterableMethodGenerator(descriptor,
+ idlNode.maplikeOrSetlikeOrIterable,
+ idlNode.identifier.name))
+ else:
+ cgThings.append(CGCallGenerator(
+ errorResult,
+ self.getArguments(), self.argsPre, returnType,
+ self.extendedAttributes, descriptor, nativeMethodName,
+ static))
+
self.cgRoot = CGList(cgThings, "\n")
def getArgs(self):
@@ -3272,6 +3533,23 @@ JS_SetProperty(cx, target_obj.handle(), %s as *const u8 as *const libc::c_char,
""" % (str_to_const_array(attrName), attrName, str_to_const_array(forwardToAttrName)))
+class CGSpecializedReplaceableSetter(CGSpecializedSetter):
+ """
+ A class for generating the code for an IDL replaceable attribute setter.
+ """
+ def __init__(self, descriptor, attr):
+ CGSpecializedSetter.__init__(self, descriptor, attr)
+
+ def definition_body(self):
+ assert self.attr.readonly
+ name = str_to_const_array(self.attr.identifier.name)
+ # JS_DefineProperty can only deal with ASCII.
+ assert all(ord(c) < 128 for c in name)
+ return CGGeneric("""\
+JS_DefineProperty(cx, obj, %s as *const u8 as *const libc::c_char,
+ args.get(0), JSPROP_ENUMERATE, None, None)""" % name)
+
+
class CGMemberJITInfo(CGThing):
"""
A class for generating the JITInfo for a property that points to
@@ -3384,7 +3662,8 @@ class CGMemberJITInfo(CGThing):
isAlwaysInSlot, isLazilyCachedInSlot,
slotIndex,
[self.member.type], None)
- if (not self.member.readonly or self.member.getExtendedAttribute("PutForwards")):
+ if (not self.member.readonly or self.member.getExtendedAttribute("PutForwards")
+ or self.member.getExtendedAttribute("Replaceable")):
setterinfo = ("%s_setterinfo" % internalMemberName)
setter = ("set_%s" % internalMemberName)
# Setters are always fallible, since they have to do a typed unwrap.
@@ -3826,7 +4105,7 @@ class CGUnionConversionStruct(CGThing):
return (
"match %s::TryConvertTo%s(cx, value) {\n"
" Err(_) => return Err(()),\n"
- " Ok(Some(value)) => return Ok(%s::%s(value)),\n"
+ " Ok(Some(value)) => return Ok(ConversionResult::Success(%s::%s(value))),\n"
" Ok(None) => (),\n"
"}\n") % (self.type, name, self.type, name)
@@ -3923,7 +4202,9 @@ class CGUnionConversionStruct(CGThing):
method = CGWrapper(
CGIndenter(CGList(conversions, "\n\n")),
pre="unsafe fn from_jsval(cx: *mut JSContext,\n"
- " value: HandleValue, _option: ()) -> Result<%s, ()> {\n" % self.type,
+ " value: HandleValue,\n"
+ " _option: ())\n"
+ " -> Result<ConversionResult<%s>, ()> {\n" % self.type,
post="\n}")
return CGWrapper(
CGIndenter(CGList([
@@ -4306,6 +4587,8 @@ class CGProxySpecialOperation(CGPerSignatureCall):
signature = operation.signatures()[0]
(returnType, arguments) = signature
+ if operation.isGetter() and not returnType.nullable():
+ returnType = IDLNullableType(returnType.location, returnType)
# We pass len(arguments) as the final argument so that the
# CGPerSignatureCall won't do any argument conversion of its own.
@@ -4328,8 +4611,6 @@ class CGProxySpecialOperation(CGPerSignatureCall):
self.cgRoot.prepend(instantiateJSToNativeConversionTemplate(
template, templateValues, declType, argument.identifier.name))
self.cgRoot.prepend(CGGeneric("rooted!(in(cx) let value = desc.value);"))
- elif operation.isGetter():
- self.cgRoot.prepend(CGGeneric("let mut found = false;"))
def getArguments(self):
def process(arg):
@@ -4338,10 +4619,6 @@ class CGProxySpecialOperation(CGPerSignatureCall):
argVal += ".r()"
return argVal
args = [(a, process(a)) for a in self.arguments]
- if self.idlNode.isGetter():
- args.append((FakeArgument(BuiltinTypes[IDLBuiltinType.Types.boolean],
- self.idlNode),
- "&mut found"))
return args
def wrap_return_value(self):
@@ -4349,7 +4626,7 @@ class CGProxySpecialOperation(CGPerSignatureCall):
return ""
wrap = CGGeneric(wrapForType(**self.templateValues))
- wrap = CGIfWrapper("found", wrap)
+ wrap = CGIfWrapper("let Some(result) = result", wrap)
return "\n" + wrap.define()
@@ -4498,10 +4775,17 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
# Once we start supporting OverrideBuiltins we need to make
# ResolveOwnProperty or EnumerateOwnProperties filter out named
# properties that shadow prototype properties.
- namedGet = ("\n" +
- "if RUST_JSID_IS_STRING(id) && !has_property_on_prototype(cx, proxy, id) {\n" +
- CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" +
- "}\n")
+ namedGet = """
+if RUST_JSID_IS_STRING(id) {
+ let mut has_on_proto = false;
+ if !has_property_on_prototype(cx, proxy, id, &mut has_on_proto) {
+ return false;
+ }
+ if !has_on_proto {
+ %s
+ }
+}
+""" % CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues), 8).define()
else:
namedGet = ""
@@ -4718,7 +5002,7 @@ class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod):
" let this = UnwrapProxy(proxy);\n" +
" let this = &*this;\n" +
CGIndenter(CGProxyIndexedGetter(self.descriptor)).define() + "\n" +
- " *bp = found;\n" +
+ " *bp = result.is_some();\n" +
" return true;\n" +
"}\n\n")
else:
@@ -4726,12 +5010,20 @@ class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod):
namedGetter = self.descriptor.operations['NamedGetter']
if namedGetter:
- named = ("if RUST_JSID_IS_STRING(id) && !has_property_on_prototype(cx, proxy, id) {\n" +
- CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" +
- " *bp = found;\n"
- " return true;\n"
- "}\n" +
- "\n")
+ named = """\
+if RUST_JSID_IS_STRING(id) {
+ let mut has_on_proto = false;
+ if !has_property_on_prototype(cx, proxy, id, &mut has_on_proto) {
+ return false;
+ }
+ if !has_on_proto {
+ %s
+ *bp = result.is_some();
+ return true;
+ }
+}
+
+""" % CGIndenter(CGProxyNamedGetter(self.descriptor), 8).define()
else:
named = ""
@@ -4809,7 +5101,7 @@ if !expando.is_null() {
%s
let mut found = false;
-if !get_property_on_prototype(cx, proxy, id, &mut found, vp) {
+if !get_property_on_prototype(cx, proxy, receiver, id, &mut found, vp) {
return false;
}
@@ -4945,7 +5237,7 @@ class CGClassFinalizeHook(CGAbstractClassHook):
A hook for finalize, used to release our native object.
"""
def __init__(self, descriptor):
- args = [Argument('*mut FreeOp', '_fop'), Argument('*mut JSObject', 'obj')]
+ args = [Argument('*mut JSFreeOp', '_fop'), Argument('*mut JSObject', 'obj')]
CGAbstractClassHook.__init__(self, descriptor, FINALIZE_HOOK_NAME,
'void', args)
@@ -4976,6 +5268,7 @@ class CGInterfaceTrait(CGThing):
def members():
for m in descriptor.interface.members:
if (m.isMethod() and not m.isStatic() and
+ not m.isMaplikeOrSetlikeOrIterableMethod() and
(not m.isIdentifierLess() or m.isStringifier())):
name = CGSpecializedMethod.makeNativeName(descriptor, m)
infallible = 'infallible' in descriptor.getExtendedAttributes(m)
@@ -5009,7 +5302,9 @@ class CGInterfaceTrait(CGThing):
infallible = 'infallible' in descriptor.getExtendedAttributes(operation)
if operation.isGetter():
- arguments = method_arguments(descriptor, rettype, arguments, trailing=("found", "&mut bool"))
+ if not rettype.nullable():
+ rettype = IDLNullableType(rettype.location, rettype)
+ arguments = method_arguments(descriptor, rettype, arguments)
# If this interface 'supports named properties', then we
# should be able to access 'supported property names'
@@ -5036,6 +5331,7 @@ class CGInterfaceTrait(CGThing):
post="}")
else:
self.cgRoot = CGGeneric("")
+ self.empty = not methods
def define(self):
return self.cgRoot.define()
@@ -5051,18 +5347,261 @@ class CGWeakReferenceableTrait(CGThing):
return self.code
+def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries=None, enums=None):
+ if not callbacks:
+ callbacks = []
+ if not dictionaries:
+ dictionaries = []
+ if not enums:
+ enums = []
+
+ return CGImports(cgthings, descriptors, callbacks, dictionaries, enums, [
+ 'core::nonzero::NonZero',
+ 'js',
+ 'js::JSCLASS_GLOBAL_SLOT_COUNT',
+ 'js::JSCLASS_IS_DOMJSCLASS',
+ 'js::JSCLASS_IS_GLOBAL',
+ 'js::JSCLASS_RESERVED_SLOTS_MASK',
+ 'js::JS_CALLEE',
+ 'js::error::throw_type_error',
+ 'js::jsapi::AutoIdVector',
+ 'js::jsapi::Call',
+ 'js::jsapi::CallArgs',
+ 'js::jsapi::FreeOp',
+ 'js::jsapi::GetPropertyKeys',
+ 'js::jsapi::GetWellKnownSymbol',
+ 'js::jsapi::Handle',
+ 'js::jsapi::HandleId',
+ 'js::jsapi::HandleObject',
+ 'js::jsapi::HandleValue',
+ 'js::jsapi::HandleValueArray',
+ 'js::jsapi::INTERNED_STRING_TO_JSID',
+ 'js::jsapi::IsCallable',
+ 'js::jsapi::JSAutoCompartment',
+ 'js::jsapi::JSCLASS_RESERVED_SLOTS_SHIFT',
+ 'js::jsapi::JSClass',
+ 'js::jsapi::JSContext',
+ 'js::jsapi::JSFreeOp',
+ 'js::jsapi::JSFunctionSpec',
+ 'js::jsapi::JSITER_HIDDEN',
+ 'js::jsapi::JSITER_OWNONLY',
+ 'js::jsapi::JSITER_SYMBOLS',
+ 'js::jsapi::JSJitGetterCallArgs',
+ 'js::jsapi::JSJitInfo',
+ 'js::jsapi::JSJitInfo_AliasSet',
+ 'js::jsapi::JSJitInfo_ArgType',
+ 'js::jsapi::JSJitInfo_OpType',
+ 'js::jsapi::JSJitMethodCallArgs',
+ 'js::jsapi::JSJitSetterCallArgs',
+ 'js::jsapi::JSNative',
+ 'js::jsapi::JSNativeWrapper',
+ 'js::jsapi::JSObject',
+ 'js::jsapi::JSPROP_ENUMERATE',
+ 'js::jsapi::JSPROP_PERMANENT',
+ 'js::jsapi::JSPROP_READONLY',
+ 'js::jsapi::JSPROP_SHARED',
+ 'js::jsapi::JSPropertySpec',
+ 'js::jsapi::JSString',
+ 'js::jsapi::JSTracer',
+ 'js::jsapi::JSType',
+ 'js::jsapi::JSTypedMethodJitInfo',
+ 'js::jsapi::JSValueType',
+ 'js::jsapi::JS_AtomizeAndPinString',
+ 'js::jsapi::JS_CallFunctionValue',
+ 'js::jsapi::JS_CopyPropertiesFrom',
+ 'js::jsapi::JS_DefineProperty',
+ 'js::jsapi::JS_DefinePropertyById2',
+ 'js::jsapi::JS_ForwardGetPropertyTo',
+ 'js::jsapi::JS_GetClass',
+ 'js::jsapi::JS_GetErrorPrototype',
+ 'js::jsapi::JS_GetFunctionPrototype',
+ 'js::jsapi::JS_GetGlobalForObject',
+ 'js::jsapi::JS_GetIteratorPrototype',
+ 'js::jsapi::JS_GetObjectPrototype',
+ 'js::jsapi::JS_GetProperty',
+ 'js::jsapi::JS_GetPropertyById',
+ 'js::jsapi::JS_GetPropertyDescriptorById',
+ 'js::jsapi::JS_GetReservedSlot',
+ 'js::jsapi::JS_HasProperty',
+ 'js::jsapi::JS_HasPropertyById',
+ 'js::jsapi::JS_InitializePropertiesFromCompatibleNativeObject',
+ 'js::jsapi::JS_NewObject',
+ 'js::jsapi::JS_NewObjectWithGivenProto',
+ 'js::jsapi::JS_NewObjectWithoutMetadata',
+ 'js::jsapi::JS_SetImmutablePrototype',
+ 'js::jsapi::JS_SetProperty',
+ 'js::jsapi::JS_SetReservedSlot',
+ 'js::jsapi::JS_SplicePrototype',
+ 'js::jsapi::MutableHandle',
+ 'js::jsapi::MutableHandleObject',
+ 'js::jsapi::MutableHandleValue',
+ 'js::jsapi::ObjectOpResult',
+ 'js::jsapi::PropertyDescriptor',
+ 'js::jsapi::RootedObject',
+ 'js::jsapi::SymbolCode',
+ 'js::jsapi::jsid',
+ 'js::jsval::JSVal',
+ 'js::jsval::NullValue',
+ 'js::jsval::ObjectValue',
+ 'js::jsval::ObjectOrNullValue',
+ 'js::jsval::PrivateValue',
+ 'js::jsval::UndefinedValue',
+ 'js::glue::AppendToAutoIdVector',
+ 'js::glue::CallJitGetterOp',
+ 'js::glue::CallJitMethodOp',
+ 'js::glue::CallJitSetterOp',
+ 'js::glue::CreateProxyHandler',
+ 'js::glue::GetProxyPrivate',
+ 'js::glue::NewProxyObject',
+ 'js::glue::ProxyTraps',
+ 'js::glue::RUST_JSID_IS_STRING',
+ 'js::glue::RUST_SYMBOL_TO_JSID',
+ 'js::glue::int_to_jsid',
+ 'js::rust::GCMethods',
+ 'js::rust::define_methods',
+ 'js::rust::define_properties',
+ 'dom',
+ 'dom::bindings',
+ 'dom::bindings::codegen::InterfaceObjectMap',
+ 'dom::bindings::constant::ConstantSpec',
+ 'dom::bindings::constant::ConstantVal',
+ 'dom::bindings::global::GlobalRef',
+ 'dom::bindings::global::global_root_from_object',
+ 'dom::bindings::global::global_root_from_reflector',
+ 'dom::bindings::interface::ConstructorClassHook',
+ 'dom::bindings::interface::InterfaceConstructorBehavior',
+ 'dom::bindings::interface::NonCallbackInterfaceObjectClass',
+ 'dom::bindings::interface::create_callback_interface_object',
+ 'dom::bindings::interface::create_global_object',
+ 'dom::bindings::interface::create_interface_prototype_object',
+ 'dom::bindings::interface::create_named_constructors',
+ 'dom::bindings::interface::create_noncallback_interface_object',
+ 'dom::bindings::interface::define_guarded_constants',
+ 'dom::bindings::interface::define_guarded_methods',
+ 'dom::bindings::interface::define_guarded_properties',
+ 'dom::bindings::interface::is_exposed_in',
+ 'dom::bindings::iterable::Iterable',
+ 'dom::bindings::iterable::IteratorType',
+ 'dom::bindings::js::JS',
+ 'dom::bindings::js::OptionalRootedReference',
+ 'dom::bindings::js::Root',
+ 'dom::bindings::js::RootedReference',
+ 'dom::bindings::namespace::NamespaceObjectClass',
+ 'dom::bindings::namespace::create_namespace_object',
+ 'dom::bindings::reflector::MutReflectable',
+ 'dom::bindings::reflector::Reflectable',
+ 'dom::bindings::utils::DOMClass',
+ 'dom::bindings::utils::DOMJSClass',
+ 'dom::bindings::utils::DOM_PROTO_UNFORGEABLE_HOLDER_SLOT',
+ 'dom::bindings::utils::JSCLASS_DOM_GLOBAL',
+ 'dom::bindings::utils::ProtoOrIfaceArray',
+ 'dom::bindings::utils::enumerate_global',
+ 'dom::bindings::utils::finalize_global',
+ 'dom::bindings::utils::find_enum_string_index',
+ 'dom::bindings::utils::generic_getter',
+ 'dom::bindings::utils::generic_lenient_getter',
+ 'dom::bindings::utils::generic_lenient_setter',
+ 'dom::bindings::utils::generic_method',
+ 'dom::bindings::utils::generic_setter',
+ 'dom::bindings::utils::get_array_index_from_id',
+ 'dom::bindings::utils::get_dictionary_property',
+ 'dom::bindings::utils::get_property_on_prototype',
+ 'dom::bindings::utils::get_proto_or_iface_array',
+ 'dom::bindings::utils::has_property_on_prototype',
+ 'dom::bindings::utils::is_platform_object',
+ 'dom::bindings::utils::resolve_global',
+ 'dom::bindings::utils::set_dictionary_property',
+ 'dom::bindings::utils::trace_global',
+ 'dom::bindings::trace::JSTraceable',
+ 'dom::bindings::trace::RootedTraceable',
+ 'dom::bindings::callback::CallSetup',
+ 'dom::bindings::callback::CallbackContainer',
+ 'dom::bindings::callback::CallbackInterface',
+ 'dom::bindings::callback::CallbackFunction',
+ 'dom::bindings::callback::ExceptionHandling',
+ 'dom::bindings::callback::wrap_call_this_object',
+ 'dom::bindings::conversions::ConversionBehavior',
+ 'dom::bindings::conversions::ConversionResult',
+ 'dom::bindings::conversions::DOM_OBJECT_SLOT',
+ 'dom::bindings::conversions::FromJSValConvertible',
+ 'dom::bindings::conversions::IDLInterface',
+ 'dom::bindings::conversions::StringificationBehavior',
+ 'dom::bindings::conversions::ToJSValConvertible',
+ 'dom::bindings::conversions::is_array_like',
+ 'dom::bindings::conversions::jsid_to_str',
+ 'dom::bindings::conversions::native_from_handlevalue',
+ 'dom::bindings::conversions::native_from_object',
+ 'dom::bindings::conversions::private_from_object',
+ 'dom::bindings::conversions::root_from_handleobject',
+ 'dom::bindings::conversions::root_from_handlevalue',
+ 'dom::bindings::conversions::root_from_object',
+ 'dom::bindings::codegen::PrototypeList',
+ 'dom::bindings::codegen::RegisterBindings',
+ 'dom::bindings::codegen::UnionTypes',
+ 'dom::bindings::error::Error',
+ 'dom::bindings::error::ErrorResult',
+ 'dom::bindings::error::Fallible',
+ 'dom::bindings::error::Error::JSFailed',
+ 'dom::bindings::error::throw_dom_exception',
+ 'dom::bindings::guard::Condition',
+ 'dom::bindings::guard::Guard',
+ 'dom::bindings::proxyhandler',
+ 'dom::bindings::proxyhandler::ensure_expando_object',
+ 'dom::bindings::proxyhandler::fill_property_descriptor',
+ 'dom::bindings::proxyhandler::get_expando_object',
+ 'dom::bindings::proxyhandler::get_property_descriptor',
+ 'dom::bindings::num::Finite',
+ 'dom::bindings::str::ByteString',
+ 'dom::bindings::str::DOMString',
+ 'dom::bindings::str::USVString',
+ 'dom::bindings::weakref::DOM_WEAK_SLOT',
+ 'dom::bindings::weakref::WeakBox',
+ 'dom::bindings::weakref::WeakReferenceable',
+ 'dom::browsingcontext::BrowsingContext',
+ 'mem::heap_size_of_raw_self_and_children',
+ 'libc',
+ 'util::prefs::PREFS',
+ 'script_runtime::maybe_take_panic_result',
+ 'script_runtime::store_panic_result',
+ 'std::borrow::ToOwned',
+ 'std::cmp',
+ 'std::mem',
+ 'std::num',
+ 'std::os',
+ 'std::panic',
+ 'std::panic::AssertUnwindSafe',
+ 'std::ptr',
+ 'std::str',
+ 'std::rc',
+ 'std::rc::Rc',
+ 'std::default::Default',
+ 'std::ffi::CString',
+ ], config)
+
+
class CGDescriptor(CGThing):
- def __init__(self, descriptor):
+ def __init__(self, descriptor, config, soleDescriptor):
CGThing.__init__(self)
assert not descriptor.concrete or not descriptor.interface.isCallback()
+ reexports = []
+
+ def reexportedName(name):
+ if name.startswith(descriptor.name):
+ return name
+ if not soleDescriptor:
+ return '%s as %s%s' % (name, descriptor.name, name)
+ return name
+
cgThings = []
- if not descriptor.interface.isCallback():
+ if not descriptor.interface.isCallback() and not descriptor.interface.isNamespace():
cgThings.append(CGGetProtoObjectMethod(descriptor))
+ reexports.append('GetProtoObject')
if (descriptor.interface.hasInterfaceObject() and
descriptor.shouldHaveGetConstructorObjectMethod()):
cgThings.append(CGGetConstructorObjectMethod(descriptor))
+ reexports.append('GetConstructorObject')
unscopableNames = []
for m in descriptor.interface.members:
@@ -5099,6 +5638,8 @@ class CGDescriptor(CGThing):
cgThings.append(CGSpecializedSetter(descriptor, m))
elif m.getExtendedAttribute("PutForwards"):
cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
+ elif m.getExtendedAttribute("Replaceable"):
+ cgThings.append(CGSpecializedReplaceableSetter(descriptor, m))
if (not m.isStatic() and not descriptor.interface.isCallback()):
cgThings.append(CGMemberJITInfo(descriptor, m))
@@ -5115,7 +5656,7 @@ class CGDescriptor(CGThing):
if not descriptor.interface.isCallback():
cgThings.append(CGInterfaceObjectJSClass(descriptor))
- if not descriptor.interface.isCallback():
+ if not descriptor.interface.isCallback() and not descriptor.interface.isNamespace():
cgThings.append(CGPrototypeJSClass(descriptor))
# If there are no constant members, don't make a module for constants
@@ -5124,14 +5665,18 @@ class CGDescriptor(CGThing):
cgThings.append(CGNamespace.build([descriptor.name + "Constants"],
CGConstant(constMembers),
public=True))
+ reexports.append(descriptor.name + 'Constants')
- if descriptor.interface.hasInterfaceObject():
+ if descriptor.interface.hasInterfaceObject() and descriptor.register:
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
+ reexports.append('DefineDOMInterface')
cgThings.append(CGConstructorEnabled(descriptor))
if descriptor.proxy:
cgThings.append(CGDefineProxyHandler(descriptor))
+ properties = PropertyArrays(descriptor)
+
if descriptor.concrete:
if descriptor.proxy:
# cgThings.append(CGProxyIsProxy(descriptor))
@@ -5161,10 +5706,14 @@ class CGDescriptor(CGThing):
cgThings.append(CGDOMJSClass(descriptor))
pass
- cgThings.append(CGWrapMethod(descriptor))
+ if descriptor.isGlobal():
+ cgThings.append(CGWrapGlobalMethod(descriptor, properties))
+ else:
+ cgThings.append(CGWrapMethod(descriptor))
+ reexports.append('Wrap')
haveUnscopables = False
- if not descriptor.interface.isCallback():
+ if not descriptor.interface.isCallback() and not descriptor.interface.isNamespace():
if unscopableNames:
haveUnscopables = True
cgThings.append(
@@ -5174,19 +5723,25 @@ class CGDescriptor(CGThing):
CGGeneric("];\n")], "\n"))
if descriptor.concrete or descriptor.hasDescendants():
cgThings.append(CGIDLInterface(descriptor))
- cgThings.append(CGInterfaceTrait(descriptor))
+
+ interfaceTrait = CGInterfaceTrait(descriptor)
+ cgThings.append(interfaceTrait)
+ if not interfaceTrait.empty:
+ reexports.append('%sMethods' % descriptor.name)
+
if descriptor.weakReferenceable:
cgThings.append(CGWeakReferenceableTrait(descriptor))
- properties = PropertyArrays(descriptor)
cgThings.append(CGGeneric(str(properties)))
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties, haveUnscopables))
- cgThings = CGList(cgThings, "\n")
- # self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
- # cgThings),
- # post='\n')
- self.cgRoot = cgThings
+ cgThings = generate_imports(config, CGList(cgThings, '\n'), [descriptor])
+ cgThings = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
+ cgThings, public=True),
+ post='\n')
+ reexports = ', '.join(map(lambda name: reexportedName(name), reexports))
+ self.cgRoot = CGList([CGGeneric('pub use self::%s::{%s};' % (toBindingNamespace(descriptor.name), reexports)),
+ cgThings], '\n')
def define(self):
return self.cgRoot.define()
@@ -5271,9 +5826,14 @@ class CGDictionary(CGThing):
def impl(self):
d = self.dictionary
if d.parent:
- initParent = "parent: try!(%s::%s::new(cx, val)),\n" % (
- self.makeModuleName(d.parent),
- self.makeClassName(d.parent))
+ initParent = ("parent: match try!(%s::%s::new(cx, val)) {\n"
+ " ConversionResult::Success(v) => v,\n"
+ " ConversionResult::Failure(error) => {\n"
+ " throw_type_error(cx, &error);\n"
+ " return Err(());\n"
+ " }\n"
+ " },\n" % (self.makeModuleName(d.parent),
+ self.makeClassName(d.parent)))
else:
initParent = ""
@@ -5307,9 +5867,13 @@ class CGDictionary(CGThing):
return string.Template(
"impl ${selfName} {\n"
" pub unsafe fn empty(cx: *mut JSContext) -> ${selfName} {\n"
- " ${selfName}::new(cx, HandleValue::null()).unwrap()\n"
+ " match ${selfName}::new(cx, HandleValue::null()) {\n"
+ " Ok(ConversionResult::Success(v)) => v,\n"
+ " _ => unreachable!(),\n"
+ " }\n"
" }\n"
- " pub unsafe fn new(cx: *mut JSContext, val: HandleValue) -> Result<${selfName}, ()> {\n"
+ " pub unsafe fn new(cx: *mut JSContext, val: HandleValue) \n"
+ " -> Result<ConversionResult<${selfName}>, ()> {\n"
" let object = if val.get().is_null_or_undefined() {\n"
" ptr::null_mut()\n"
" } else if val.get().is_object() {\n"
@@ -5319,17 +5883,17 @@ class CGDictionary(CGThing):
" return Err(());\n"
" };\n"
" rooted!(in(cx) let object = object);\n"
- " Ok(${selfName} {\n"
+ " Ok(ConversionResult::Success(${selfName} {\n"
"${initParent}"
"${initMembers}"
- " })\n"
+ " }))\n"
" }\n"
"}\n"
"\n"
"impl FromJSValConvertible for ${selfName} {\n"
" type Config = ();\n"
" unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _option: ())\n"
- " -> Result<${selfName}, ()> {\n"
+ " -> Result<ConversionResult<${selfName}>, ()> {\n"
" ${selfName}::new(cx, value)\n"
" }\n"
"}\n"
@@ -5427,8 +5991,8 @@ class CGRegisterProxyHandlersMethod(CGAbstractMethod):
def definition_body(self):
return CGList([
- CGGeneric("proxy_handlers[Proxies::%s as usize] = codegen::Bindings::%sBinding::DefineProxyHandler();"
- % (desc.name, desc.name))
+ CGGeneric("proxy_handlers[Proxies::%s as usize] = Bindings::%s::DefineProxyHandler();"
+ % (desc.name, '::'.join([desc.name + 'Binding'] * 2)))
for desc in self.descriptors
], "\n")
@@ -5501,7 +6065,7 @@ class CGBindingRoot(CGThing):
for c in mainCallbacks)
# Do codegen for all the descriptors
- cgthings.extend([CGDescriptor(x) for x in descriptors])
+ cgthings.extend([CGDescriptor(x, config, len(descriptors) == 1) for x in descriptors])
# Do codegen for all the callback interfaces.
cgthings.extend(CGList([CGCallbackInterface(x),
@@ -5512,102 +6076,8 @@ class CGBindingRoot(CGThing):
curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
# Add imports
- curr = CGImports(curr, descriptors + callbackDescriptors, mainCallbacks, [
- 'js',
- 'js::{JS_CALLEE, JSCLASS_GLOBAL_SLOT_COUNT}',
- 'js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_MASK}',
- 'js::error::throw_type_error',
- 'js::jsapi::{JSJitInfo_AliasSet, JSJitInfo_ArgType, AutoIdVector, CallArgs, FreeOp}',
- 'js::jsapi::{JSITER_SYMBOLS, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_SHARED}',
- 'js::jsapi::{JSCLASS_RESERVED_SLOTS_SHIFT, JSITER_HIDDEN, JSITER_OWNONLY}',
- 'js::jsapi::{GetPropertyKeys, Handle}',
- 'js::jsapi::{HandleId, HandleObject, HandleValue, HandleValueArray}',
- 'js::jsapi::{INTERNED_STRING_TO_JSID, IsCallable, JS_CallFunctionValue}',
- 'js::jsapi::{JS_CopyPropertiesFrom, JS_ForwardGetPropertyTo}',
- 'js::jsapi::{JS_GetClass, JS_GetErrorPrototype, JS_GetFunctionPrototype}',
- 'js::jsapi::{JS_GetGlobalForObject, JS_GetObjectPrototype, JS_GetProperty}',
- 'js::jsapi::{JS_GetPropertyById, JS_GetPropertyDescriptorById, JS_GetReservedSlot}',
- 'js::jsapi::{JS_HasProperty, JS_HasPropertyById, JS_InitializePropertiesFromCompatibleNativeObject}',
- 'js::jsapi::{JS_AtomizeAndPinString, JS_NewObject, JS_NewObjectWithGivenProto}',
- 'js::jsapi::{JS_NewObjectWithoutMetadata, JS_SetProperty}',
- 'js::jsapi::{JS_SetPrototype, JS_SetReservedSlot, JSAutoCompartment}',
- 'js::jsapi::{JSContext, JSClass, JSFreeOp, JSFunctionSpec}',
- 'js::jsapi::{JSJitGetterCallArgs, JSJitInfo, JSJitMethodCallArgs, JSJitSetterCallArgs}',
- 'js::jsapi::{JSNative, JSObject, JSNativeWrapper, JSPropertySpec}',
- 'js::jsapi::{JSString, JSTracer, JSType, JSTypedMethodJitInfo, JSValueType}',
- 'js::jsapi::{ObjectOpResult, JSJitInfo_OpType, MutableHandle, MutableHandleObject}',
- 'js::jsapi::{MutableHandleValue, PropertyDescriptor, RootedObject}',
- 'js::jsapi::{SymbolCode, jsid}',
- 'js::jsval::JSVal',
- 'js::jsval::{ObjectValue, ObjectOrNullValue, PrivateValue}',
- 'js::jsval::{NullValue, UndefinedValue}',
- 'js::glue::{CallJitMethodOp, CallJitGetterOp, CallJitSetterOp, CreateProxyHandler}',
- 'js::glue::{GetProxyPrivate, NewProxyObject, ProxyTraps}',
- 'js::glue::{RUST_JSID_IS_STRING, int_to_jsid}',
- 'js::glue::AppendToAutoIdVector',
- 'js::rust::{GCMethods, define_methods, define_properties}',
- 'dom::bindings',
- 'dom::bindings::codegen::InterfaceObjectMap',
- 'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}',
- 'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
- 'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
- 'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}',
- 'dom::bindings::interface::{define_guarded_methods, define_guarded_properties}',
- 'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
- 'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
- 'dom::bindings::interface::is_exposed_in',
- 'dom::bindings::js::{JS, Root, RootedReference}',
- 'dom::bindings::js::{OptionalRootedReference}',
- 'dom::bindings::reflector::{Reflectable}',
- 'dom::bindings::utils::{DOMClass, DOMJSClass}',
- 'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}',
- 'dom::bindings::utils::{ProtoOrIfaceArray, create_dom_global}',
- 'dom::bindings::utils::{enumerate_global, finalize_global, find_enum_string_index}',
- 'dom::bindings::utils::{generic_getter, generic_lenient_getter, generic_lenient_setter}',
- 'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}',
- 'dom::bindings::utils::{get_dictionary_property, get_property_on_prototype}',
- 'dom::bindings::utils::{get_proto_or_iface_array, has_property_on_prototype}',
- 'dom::bindings::utils::{is_platform_object, resolve_global, set_dictionary_property, trace_global}',
- 'dom::bindings::trace::{JSTraceable, RootedTraceable}',
- 'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}',
- 'dom::bindings::callback::{CallSetup,ExceptionHandling}',
- 'dom::bindings::callback::wrap_call_this_object',
- 'dom::bindings::conversions::{ConversionBehavior, DOM_OBJECT_SLOT}',
- 'dom::bindings::conversions::{IDLInterface, is_array_like}',
- 'dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior}',
- 'dom::bindings::conversions::{ToJSValConvertible, jsid_to_str, native_from_handlevalue}',
- 'dom::bindings::conversions::{native_from_object, private_from_object, root_from_object}',
- 'dom::bindings::conversions::{root_from_handleobject, root_from_handlevalue}',
- 'dom::bindings::codegen::{PrototypeList, RegisterBindings, UnionTypes}',
- 'dom::bindings::codegen::Bindings::*',
- 'dom::bindings::error::{Fallible, Error, ErrorResult}',
- 'dom::bindings::error::Error::JSFailed',
- 'dom::bindings::error::throw_dom_exception',
- 'dom::bindings::guard::{Condition, Guard}',
- 'dom::bindings::proxyhandler',
- 'dom::bindings::proxyhandler::{ensure_expando_object, fill_property_descriptor}',
- 'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}',
- 'dom::bindings::num::Finite',
- 'dom::bindings::str::{ByteString, DOMString, USVString}',
- 'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
- 'dom::browsingcontext::BrowsingContext',
- 'mem::heap_size_of_raw_self_and_children',
- 'libc',
- 'util::prefs::PREFS',
- 'script_runtime::{store_panic_result, maybe_take_panic_result}',
- 'std::borrow::ToOwned',
- 'std::cmp',
- 'std::mem',
- 'std::num',
- 'std::os',
- 'std::panic::{self, AssertUnwindSafe}',
- 'std::ptr',
- 'std::str',
- 'std::rc',
- 'std::rc::Rc',
- 'std::default::Default',
- 'std::ffi::CString',
- ], config)
+ curr = generate_imports(config, curr, callbackDescriptors, mainCallbacks,
+ dictionaries, enums)
# Add the auto-generated comment.
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
@@ -6071,7 +6541,8 @@ class CallbackMethod(CallbackMember):
def getCall(self):
replacements = {
"thisObj": self.getThisObj(),
- "getCallable": self.getCallableDecl()
+ "getCallable": self.getCallableDecl(),
+ "callGuard": self.getCallGuard(),
}
if self.argCount > 0:
replacements["argv"] = "argv.as_ptr()"
@@ -6082,7 +6553,7 @@ class CallbackMethod(CallbackMember):
return string.Template(
"${getCallable}"
"rooted!(in(cx) let rootedThis = ${thisObj});\n"
- "let ok = JS_CallFunctionValue(\n"
+ "let ok = ${callGuard}JS_CallFunctionValue(\n"
" cx, rootedThis.handle(), callable.handle(),\n"
" &HandleValueArray {\n"
" length_: ${argc} as ::libc::size_t,\n"
@@ -6098,6 +6569,7 @@ class CallbackMethod(CallbackMember):
class CallCallback(CallbackMethod):
def __init__(self, callback, descriptorProvider):
+ self.callback = callback
CallbackMethod.__init__(self, callback.signatures()[0], "Call",
descriptorProvider, needThisHandling=True)
@@ -6107,6 +6579,11 @@ class CallCallback(CallbackMethod):
def getCallableDecl(self):
return "rooted!(in(cx) let callable = ObjectValue(&*self.parent.callback()));\n"
+ def getCallGuard(self):
+ if self.callback._treatNonObjectAsNull:
+ return "!IsCallable(self.parent.callback()) || "
+ return ""
+
class CallbackOperationBase(CallbackMethod):
"""
@@ -6142,6 +6619,9 @@ class CallbackOperationBase(CallbackMethod):
CGGeneric('ObjectValue(&*self.parent.callback())'),
CGGeneric(getCallableFromProp))).define() + ');\n')
+ def getCallGuard(self):
+ return ""
+
class CallbackOperation(CallbackOperationBase):
"""
@@ -6209,6 +6689,53 @@ class CallbackSetter(CallbackMember):
return None
+class CGIterableMethodGenerator(CGGeneric):
+ """
+ Creates methods for iterable interfaces. Unwrapping/wrapping
+ will be taken care of by the usual method generation machinery in
+ CGMethodCall/CGPerSignatureCall. Functionality is filled in here instead of
+ using CGCallGenerator.
+ """
+ def __init__(self, descriptor, iterable, methodName):
+ if methodName == "forEach":
+ CGGeneric.__init__(self, fill(
+ """
+ if !IsCallable(arg0) {
+ throw_type_error(cx, "Argument 1 of ${ifaceName}.forEach is not callable.");
+ return false;
+ }
+ rooted!(in(cx) let arg0 = ObjectValue(&*arg0));
+ rooted!(in(cx) let mut call_arg1 = UndefinedValue());
+ rooted!(in(cx) let mut call_arg2 = UndefinedValue());
+ let mut call_args = vec![UndefinedValue(), UndefinedValue(), ObjectValue(&**_obj)];
+ rooted!(in(cx) let mut ignoredReturnVal = UndefinedValue());
+ for i in 0..(*this).get_iterable_length() {
+ (*this).get_value_at_index(i).to_jsval(cx, call_arg1.handle_mut());
+ (*this).get_key_at_index(i).to_jsval(cx, call_arg2.handle_mut());
+ call_args[0] = call_arg1.handle().get();
+ call_args[1] = call_arg2.handle().get();
+ let call_args = HandleValueArray { length_: 3, elements_: call_args.as_ptr() };
+ if !Call(cx, arg1, arg0.handle(), &call_args,
+ ignoredReturnVal.handle_mut()) {
+ return false;
+ }
+ }
+
+ let result = ();
+ """,
+ ifaceName=descriptor.interface.identifier.name))
+ return
+ CGGeneric.__init__(self, fill(
+ """
+ let result = ${iterClass}::new(&*this,
+ IteratorType::${itrMethod},
+ super::${ifaceName}IteratorBinding::Wrap);
+ """,
+ iterClass=iteratorNativeType(descriptor, True),
+ ifaceName=descriptor.interface.identifier.name,
+ itrMethod=methodName.title()))
+
+
def camel_to_upper_snake(s):
return "_".join(m.group(0).upper() for m in re.finditer("[A-Z][a-z]*", s))
@@ -6245,12 +6772,12 @@ class GlobalGenRoots():
pairs = []
for d in config.getDescriptors(hasInterfaceObject=True):
binding = toBindingNamespace(d.name)
- pairs.append((d.name, binding))
+ pairs.append((d.name, binding, binding))
for ctor in d.interface.namedConstructors:
- pairs.append((ctor.identifier.name, binding))
+ pairs.append((ctor.identifier.name, binding, binding))
pairs.sort(key=operator.itemgetter(0))
mappings = [
- CGGeneric('b"%s" => codegen::Bindings::%s::DefineDOMInterface as unsafe fn(_, _),' % pair)
+ CGGeneric('b"%s" => codegen::Bindings::%s::%s::DefineDOMInterface as unsafe fn(_, _),' % pair)
for pair in pairs
]
mapType = "phf::Map<&'static [u8], unsafe fn(*mut JSContext, HandleObject)>"
@@ -6267,10 +6794,12 @@ class GlobalGenRoots():
@staticmethod
def PrototypeList(config):
# Prototype ID enum.
- interfaces = config.getDescriptors(isCallback=False)
+ interfaces = config.getDescriptors(isCallback=False, isNamespace=False)
protos = [d.name for d in interfaces]
- constructors = [d.name for d in config.getDescriptors(hasInterfaceObject=True)
- if d.shouldHaveGetConstructorObjectMethod()]
+ constructors = sorted([MakeNativeName(d.name)
+ for d in config.getDescriptors(hasInterfaceObject=True)
+ if d.shouldHaveGetConstructorObjectMethod()])
+
proxies = [d.name for d in config.getDescriptors(proxy=True)]
return CGList([
@@ -6299,25 +6828,34 @@ class GlobalGenRoots():
CGRegisterProxyHandlers(config),
], "\n")
- return CGImports(code, [], [], [
- 'dom::bindings::codegen',
+ return CGImports(code, descriptors=[], callbacks=[], dictionaries=[], enums=[], imports=[
+ 'dom::bindings::codegen::Bindings',
'dom::bindings::codegen::PrototypeList::Proxies',
'libc',
- ], config, ignored_warnings=[])
+ ], config=config, ignored_warnings=[])
@staticmethod
def InterfaceTypes(config):
- descriptors = [d.name for d in config.getDescriptors(register=True, isCallback=False)]
- curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors])
+ descriptors = sorted([MakeNativeName(d.name)
+ for d in config.getDescriptors(register=True,
+ isCallback=False,
+ isIteratorInterface=False)])
+ curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(),
+ MakeNativeName(name)))
+ for name in descriptors])
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
return curr
@staticmethod
def Bindings(config):
- descriptors = (set(d.name + "Binding" for d in config.getDescriptors(register=True)) |
- set(getModuleFromObject(d) for d in config.callbacks) |
- set(getModuleFromObject(d) for d in config.getDictionaries()))
+ def leafModule(d):
+ return getModuleFromObject(d).split('::')[-1]
+
+ descriptors = config.getDescriptors(register=True, isIteratorInterface=False)
+ descriptors = (set(toBindingNamespace(d.name) for d in descriptors) |
+ set(leafModule(d) for d in config.callbacks) |
+ set(leafModule(d) for d in config.getDictionaries()))
curr = CGList([CGGeneric("pub mod %s;\n" % name) for name in sorted(descriptors)])
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
return curr
@@ -6417,6 +6955,7 @@ impl %(base)s {
curr = UnionTypes(config.getDescriptors(),
config.getDictionaries(),
config.getCallbacks(),
+ config.typedefs,
config)
# Add the auto-generated comment.
diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py
index 4074736a462..6e71bd4bd00 100644
--- a/components/script/dom/bindings/codegen/Configuration.py
+++ b/components/script/dom/bindings/codegen/Configuration.py
@@ -4,7 +4,7 @@
import os
-from WebIDL import IDLExternalInterface, IDLInterface, WebIDLError
+from WebIDL import IDLExternalInterface, IDLWrapperType, WebIDLError
class Configuration:
@@ -30,10 +30,9 @@ class Configuration:
raise WebIDLError("Servo does not support external interfaces.",
[thing.location])
- # Some toplevel things are sadly types, and those have an
- # isInterface that doesn't mean the same thing as IDLObject's
- # isInterface()...
- if not isinstance(thing, IDLInterface):
+ assert not thing.isType()
+
+ if not thing.isInterface() and not thing.isNamespace():
continue
iface = thing
@@ -83,12 +82,16 @@ class Configuration:
getter = lambda x: x.interface.hasInterfaceObject()
elif key == 'isCallback':
getter = lambda x: x.interface.isCallback()
+ elif key == 'isNamespace':
+ getter = lambda x: x.interface.isNamespace()
elif key == 'isJSImplemented':
getter = lambda x: x.interface.isJSImplemented()
elif key == 'isGlobal':
getter = lambda x: x.isGlobal()
elif key == 'isExposedConditionally':
getter = lambda x: x.interface.isExposedConditionally()
+ elif key == 'isIteratorInterface':
+ getter = lambda x: x.interface.isIteratorInterface()
else:
getter = lambda x: getattr(x, key)
curr = filter(lambda x: getter(x) == val, curr)
@@ -177,13 +180,26 @@ class Descriptor(DescriptorProvider):
# Read the desc, and fill in the relevant defaults.
ifaceName = self.interface.identifier.name
- typeName = desc.get('nativeType', ifaceName)
+ nativeTypeDefault = ifaceName
+
+ # For generated iterator interfaces for other iterable interfaces, we
+ # just use IterableIterator as the native type, templated on the
+ # nativeType of the iterable interface. That way we can have a
+ # templated implementation for all the duplicated iterator
+ # functionality.
+ if self.interface.isIteratorInterface():
+ itrName = self.interface.iterableInterface.identifier.name
+ itrDesc = self.getDescriptor(itrName)
+ nativeTypeDefault = iteratorNativeType(itrDesc)
+
+ typeName = desc.get('nativeType', nativeTypeDefault)
# Callback types do not use JS smart pointers, so we should not use the
# built-in rooting mechanisms for them.
if self.interface.isCallback():
self.needsRooting = False
- ty = "%sBinding::%s" % (ifaceName, ifaceName)
+ ty = 'dom::bindings::codegen::Bindings::%sBinding::%s' % (ifaceName, ifaceName)
+ pathDefault = ty
self.returnType = "Rc<%s>" % ty
self.argumentType = "???"
self.nativeType = ty
@@ -192,10 +208,15 @@ class Descriptor(DescriptorProvider):
self.returnType = "Root<%s>" % typeName
self.argumentType = "&%s" % typeName
self.nativeType = "*const %s" % typeName
+ if self.interface.isIteratorInterface():
+ pathDefault = 'dom::bindings::iterable::IterableIterator'
+ else:
+ pathDefault = 'dom::types::%s' % MakeNativeName(typeName)
self.concreteType = typeName
self.register = desc.get('register', True)
- self.path = desc.get('path', 'dom::types::%s' % typeName)
+ self.path = desc.get('path', pathDefault)
+ self.bindingPath = 'dom::bindings::codegen::Bindings::%s' % ('::'.join([ifaceName + 'Binding'] * 2))
self.outerObjectHook = desc.get('outerObjectHook', 'None')
self.proxy = False
self.weakReferenceable = desc.get('weakReferenceable', False)
@@ -203,6 +224,7 @@ class Descriptor(DescriptorProvider):
# If we're concrete, we need to crawl our ancestor interfaces and mark
# them as having a concrete descendant.
self.concrete = (not self.interface.isCallback() and
+ not self.interface.isNamespace() and
not self.interface.getExtendedAttribute("Abstract"))
self.hasUnforgeableMembers = (self.concrete and
any(MemberIsUnforgeable(m, self) for m in
@@ -361,7 +383,7 @@ class Descriptor(DescriptorProvider):
def shouldHaveGetConstructorObjectMethod(self):
assert self.interface.hasInterfaceObject()
- return self.interface.isCallback() or self.hasDescendants()
+ return self.interface.isCallback() or self.interface.isNamespace() or self.hasDescendants()
def isExposedConditionally(self):
return self.interface.isExposedConditionally()
@@ -376,8 +398,15 @@ class Descriptor(DescriptorProvider):
# Some utility methods
+
+
+def MakeNativeName(name):
+ return name[0].upper() + name[1:]
+
+
def getModuleFromObject(object):
- return os.path.basename(object.location.filename()).split('.webidl')[0] + 'Binding'
+ return ('dom::bindings::codegen::Bindings::' +
+ os.path.basename(object.location.filename()).split('.webidl')[0] + 'Binding')
def getTypesFromDescriptor(descriptor):
@@ -404,6 +433,8 @@ def getTypesFromDictionary(dictionary):
"""
Get all member types for this dictionary
"""
+ if isinstance(dictionary, IDLWrapperType):
+ dictionary = dictionary.inner
types = []
curDict = dictionary
while curDict:
@@ -421,3 +452,10 @@ def getTypesFromCallback(callback):
types = [sig[0]] # Return type
types.extend(arg.type for arg in sig[1]) # Arguments
return types
+
+
+def iteratorNativeType(descriptor, infer=False):
+ assert descriptor.interface.isIterable()
+ iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
+ assert iterableDecl.isPairIterator()
+ return "IterableIterator%s" % ("" if infer else '<%s>' % descriptor.interface.identifier.name)
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index 54d510781a1..878c221f01c 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -1261,10 +1261,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
member.getExtendedAttribute("ChromeOnly") or
member.getExtendedAttribute("Pref") or
member.getExtendedAttribute("Func") or
- member.getExtendedAttribute("SecureContext") or
- member.getExtendedAttribute("AvailableIn") or
- member.getExtendedAttribute("CheckAnyPermissions") or
- member.getExtendedAttribute("CheckAllPermissions")):
+ member.getExtendedAttribute("SecureContext")):
raise WebIDLError("[Alias] must not be used on a "
"conditionally exposed operation",
[member.location])
@@ -1290,17 +1287,11 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
alias,
[member.location, m.location])
- for attribute in ["CheckAnyPermissions", "CheckAllPermissions"]:
- if (self.getExtendedAttribute(attribute) and
- self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
- raise WebIDLError("[%s] used on an interface that is "
- "not %s-only" %
- (attribute, self.parentScope.primaryGlobalName),
- [self.location])
-
# Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties.
- if (self.isExposedConditionally() and
+ # And SecureContext makes sense for interfaces with no interface object,
+ # since it is also propagated to interface members.
+ if (self.isExposedConditionally(exclusions=["SecureContext"]) and
not self.hasInterfaceObject() and
not self.isNavigatorProperty()):
raise WebIDLError("Interface with no interface object is "
@@ -1538,8 +1529,8 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
"SecureContext",
"CheckAnyPermissions",
"CheckAllPermissions" ]
- def isExposedConditionally(self):
- return any(self.getExtendedAttribute(a) for a in self.conditionExtendedAttributes)
+ def isExposedConditionally(self, exclusions=[]):
+ return any(((not a in exclusions) and self.getExtendedAttribute(a)) for a in self.conditionExtendedAttributes)
class IDLInterface(IDLInterfaceOrNamespace):
def __init__(self, location, parentScope, name, parent, members,
@@ -1715,10 +1706,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "JSImplementation" or
identifier == "HeaderFile" or
identifier == "NavigatorProperty" or
- identifier == "AvailableIn" or
identifier == "Func" or
- identifier == "CheckAnyPermissions" or
- identifier == "CheckAllPermissions" or
identifier == "Deprecated"):
# Known extended attributes that take a string value
if not attr.hasValue():
@@ -2170,7 +2158,7 @@ class IDLUnresolvedType(IDLType):
return typedefType.complete(scope)
elif obj.isCallback() and not obj.isInterface():
assert self.name.name == obj.identifier.name
- return IDLCallbackType(self.location, obj)
+ return IDLCallbackType(obj.location, obj)
if self._promiseInnerType and not self._promiseInnerType.isComplete():
self._promiseInnerType = self._promiseInnerType.complete(scope)
@@ -2503,10 +2491,18 @@ class IDLUnionType(IDLType):
return type.name
for (i, type) in enumerate(self.memberTypes):
- if not type.isComplete():
+ # Exclude typedefs because if given "typedef (B or C) test",
+ # we want AOrTest, not AOrBOrC
+ if not type.isComplete() and not isinstance(type, IDLTypedefType):
self.memberTypes[i] = type.complete(scope)
self.name = "Or".join(typeName(type) for type in self.memberTypes)
+
+ # We do this again to complete the typedef types
+ for (i, type) in enumerate(self.memberTypes):
+ if not type.isComplete():
+ self.memberTypes[i] = type.complete(scope)
+
self.flatMemberTypes = list(self.memberTypes)
i = 0
while i < len(self.flatMemberTypes):
@@ -3544,14 +3540,6 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
IDLExposureMixins.finish(self, scope)
def validate(self):
- for attribute in ["CheckAnyPermissions", "CheckAllPermissions"]:
- if (self.getExtendedAttribute(attribute) and
- self.exposureSet != set([self._globalScope.primaryGlobalName])):
- raise WebIDLError("[%s] used on an interface member that is "
- "not %s-only" %
- (attribute, self.parentScope.primaryGlobalName),
- [self.location])
-
if self.isAttr() or self.isMethod():
if self.affects == "Everything" and self.dependsOn != "Everything":
raise WebIDLError("Interface member is flagged as affecting "
@@ -3968,10 +3956,7 @@ class IDLConst(IDLInterfaceMember):
elif (identifier == "Pref" or
identifier == "ChromeOnly" or
identifier == "Func" or
- identifier == "SecureContext" or
- identifier == "AvailableIn" or
- identifier == "CheckAnyPermissions" or
- identifier == "CheckAllPermissions"):
+ identifier == "SecureContext"):
# Known attributes that we don't need to do anything with here
pass
else:
@@ -4311,11 +4296,8 @@ class IDLAttribute(IDLInterfaceMember):
identifier == "Func" or
identifier == "SecureContext" or
identifier == "Frozen" or
- identifier == "AvailableIn" or
identifier == "NewObject" or
identifier == "UnsafeInPrerendering" or
- identifier == "CheckAnyPermissions" or
- identifier == "CheckAllPermissions" or
identifier == "BinaryName"):
# Known attributes that we don't need to do anything with here
pass
@@ -5037,9 +5019,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
identifier == "Deprecated" or
identifier == "Func" or
identifier == "SecureContext" or
- identifier == "AvailableIn" or
- identifier == "CheckAnyPermissions" or
- identifier == "CheckAllPermissions" or
identifier == "BinaryName" or
identifier == "StaticClassOverride"):
# Known attributes that we don't need to do anything with here
@@ -6534,7 +6513,7 @@ class Parser(Tokenizer):
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
obj.identifier.name)
elif obj.isCallback() and not obj.isInterface():
- type = IDLCallbackType(self.getLocation(p, 1), obj)
+ type = IDLCallbackType(obj.location, obj)
else:
type = IDLWrapperType(self.getLocation(p, 1), p[1])
p[0] = self.handleModifiers(type, p[2])
diff --git a/components/script/dom/bindings/codegen/parser/abstract.patch b/components/script/dom/bindings/codegen/parser/abstract.patch
new file mode 100644
index 00000000000..a8e2ddcf759
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/abstract.patch
@@ -0,0 +1,12 @@
+--- WebIDL.py
++++ WebIDL.py
+@@ -1416,7 +1416,8 @@
+ identifier == "LegacyEventInit" or
+ identifier == "ProbablyShortLivingObject" or
+ identifier == "LegacyUnenumerableNamedProperties" or
+- identifier == "NonOrdinaryGetPrototypeOf"):
++ identifier == "NonOrdinaryGetPrototypeOf" or
++ identifier == "Abstract"):
+ # Known extended attributes that do not take values
+ if not attr.noArguments():
+ raise WebIDLError("[%s] must take no arguments" % identifier,
diff --git a/components/script/dom/bindings/codegen/parser/bytestring.patch b/components/script/dom/bindings/codegen/parser/bytestring.patch
new file mode 100644
index 00000000000..823f14cf996
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/bytestring.patch
@@ -0,0 +1,29 @@
+--- WebIDL.py
++++ WebIDL.py
+@@ -3391,6 +3391,11 @@ class IDLValue(IDLObject):
+ # extra normalization step.
+ assert self.type.isDOMString()
+ return self
++ elif self.type.isString() and type.isByteString():
++ # Allow ByteStrings to use default value just like
++ # DOMString. No coercion is required here.
++ assert self.type.isDOMString()
++ return self
+ raise WebIDLError("Cannot coerce type %s to type %s." %
+ (self.type, type), [location])
+
+@@ -5759,6 +5764,14 @@ class Parser(Tokenizer):
+ booleanType = BuiltinTypes[IDLBuiltinType.Types.boolean]
+ p[0] = IDLValue(location, booleanType, p[1])
+
++ def p_ConstValueByteString(self, p):
++ """
++ ConstValue : BYTESTRING
++ """
++ location = self.getLocation(p, 1)
++ bytestringType = BuiltinTypes[IDLBuiltinType.Types.bytestring]
++ p[0] = IDLValue(location, bytestringType, p[1])
++
+ def p_ConstValueInteger(self, p):
+ """
+ ConstValue : INTEGER
diff --git a/components/script/dom/bindings/codegen/parser/callback-location.patch b/components/script/dom/bindings/codegen/parser/callback-location.patch
new file mode 100644
index 00000000000..fac5d035801
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/callback-location.patch
@@ -0,0 +1,22 @@
+diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
+index da32340..81c52b7 100644
+--- WebIDL.py
++++ WebIDL.py
+@@ -2170,7 +2170,7 @@ class IDLUnresolvedType(IDLType):
+ return typedefType.complete(scope)
+ elif obj.isCallback() and not obj.isInterface():
+ assert self.name.name == obj.identifier.name
+- return IDLCallbackType(self.location, obj)
++ return IDLCallbackType(obj.location, obj)
+
+ if self._promiseInnerType and not self._promiseInnerType.isComplete():
+ self._promiseInnerType = self._promiseInnerType.complete(scope)
+@@ -6521,7 +6521,7 @@ class Parser(Tokenizer):
+ type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
+ obj.identifier.name)
+ elif obj.isCallback() and not obj.isInterface():
+- type = IDLCallbackType(self.getLocation(p, 1), obj)
++ type = IDLCallbackType(obj.location, obj)
+ else:
+ type = IDLWrapperType(self.getLocation(p, 1), p[1])
+ p[0] = self.handleModifiers(type, p[2])
diff --git a/components/script/dom/bindings/codegen/parser/pref-main-thread.patch b/components/script/dom/bindings/codegen/parser/pref-main-thread.patch
index 4e4f8945f60..7be2dcbfc5e 100644
--- a/components/script/dom/bindings/codegen/parser/pref-main-thread.patch
+++ b/components/script/dom/bindings/codegen/parser/pref-main-thread.patch
@@ -2,7 +2,7 @@
+++ WebIDL.py
@@ -1239,12 +1239,6 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
alias,
- [member.location, m.location])
+ [member.location, m.location])
- if (self.getExtendedAttribute("Pref") and
- self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
@@ -10,9 +10,9 @@
- self.parentScope.primaryGlobalName,
- [self.location])
-
- for attribute in ["CheckAnyPermissions", "CheckAllPermissions"]:
- if (self.getExtendedAttribute(attribute) and
- self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
+ # Conditional exposure makes no sense for interfaces with no
+ # interface object, unless they're navigator properties.
+ # And SecureContext makes sense for interfaces with no interface object,
@@ -3459,12 +3453,6 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
IDLExposureMixins.finish(self, scope)
@@ -23,6 +23,6 @@
- "%s-only" % self._globalScope.primaryGlobalName,
- [self.location])
-
- for attribute in ["CheckAnyPermissions", "CheckAllPermissions"]:
- if (self.getExtendedAttribute(attribute) and
- self.exposureSet != set([self._globalScope.primaryGlobalName])):
+ if self.isAttr() or self.isMethod():
+ if self.affects == "Everything" and self.dependsOn != "Everything":
+ raise WebIDLError("Interface member is flagged as affecting "
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_securecontext_extended_attribute.py b/components/script/dom/bindings/codegen/parser/tests/test_securecontext_extended_attribute.py
index d907d08449f..084f19fa7f5 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_securecontext_extended_attribute.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_securecontext_extended_attribute.py
@@ -316,3 +316,17 @@ def WebIDLTest(parser, harness):
harness.ok(results[0].members[3].getExtendedAttribute("SecureContext") is None,
"Methods copied from non-[SecureContext] interface should not be [SecureContext]")
+ # Test SecureContext and NoInterfaceObject
+ parser = parser.reset()
+ parser.parse("""
+ [NoInterfaceObject, SecureContext]
+ interface TestSecureContextNoInterfaceObject {
+ void testSecureMethod(byte foo);
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results[0].members), 1, "TestSecureContextNoInterfaceObject should have only one member")
+ harness.ok(results[0].getExtendedAttribute("SecureContext"),
+ "Interface should have [SecureContext] extended attribute")
+ harness.ok(results[0].members[0].getExtendedAttribute("SecureContext"),
+ "Interface member should have [SecureContext] extended attribute")
diff --git a/components/script/dom/bindings/codegen/parser/update.sh b/components/script/dom/bindings/codegen/parser/update.sh
index 76a99d9cecb..ef1da728b13 100755
--- a/components/script/dom/bindings/codegen/parser/update.sh
+++ b/components/script/dom/bindings/codegen/parser/update.sh
@@ -2,6 +2,8 @@ wget https://hg.mozilla.org/mozilla-central/raw-file/tip/dom/bindings/parser/Web
patch < abstract.patch
patch < debug.patch
patch < pref-main-thread.patch
+patch < callback-location.patch
+patch < bytestring.patch
wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz
rm -r tests
diff --git a/components/script/dom/bindings/constant.rs b/components/script/dom/bindings/constant.rs
new file mode 100644
index 00000000000..7d453a1fd09
--- /dev/null
+++ b/components/script/dom/bindings/constant.rs
@@ -0,0 +1,65 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! WebIDL constants.
+
+use js::jsapi::{HandleObject, JSContext, JSPROP_ENUMERATE, JSPROP_PERMANENT};
+use js::jsapi::{JSPROP_READONLY, JS_DefineProperty};
+use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value};
+use libc;
+
+/// Representation of an IDL constant.
+#[derive(Clone)]
+pub struct ConstantSpec {
+ /// name of the constant.
+ pub name: &'static [u8],
+ /// value of the constant.
+ pub value: ConstantVal,
+}
+
+/// Representation of an IDL constant value.
+#[derive(Clone)]
+pub enum ConstantVal {
+ /// `long` constant.
+ IntVal(i32),
+ /// `unsigned long` constant.
+ UintVal(u32),
+ /// `double` constant.
+ DoubleVal(f64),
+ /// `boolean` constant.
+ BoolVal(bool),
+ /// `null` constant.
+ NullVal,
+}
+
+impl ConstantSpec {
+ /// Returns a `JSVal` that represents the value of this `ConstantSpec`.
+ pub fn get_value(&self) -> JSVal {
+ match self.value {
+ ConstantVal::NullVal => NullValue(),
+ ConstantVal::IntVal(i) => Int32Value(i),
+ ConstantVal::UintVal(u) => UInt32Value(u),
+ ConstantVal::DoubleVal(d) => DoubleValue(d),
+ ConstantVal::BoolVal(b) => BooleanValue(b),
+ }
+ }
+}
+
+/// Defines constants on `obj`.
+/// Fails on JSAPI failure.
+pub unsafe fn define_constants(
+ cx: *mut JSContext,
+ obj: HandleObject,
+ constants: &[ConstantSpec]) {
+ for spec in constants {
+ rooted!(in(cx) let value = spec.get_value());
+ assert!(JS_DefineProperty(cx,
+ obj,
+ spec.name.as_ptr() as *const libc::c_char,
+ value.handle(),
+ JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT,
+ None,
+ None));
+ }
+}
diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs
index 01282ea3b1f..113a9d279d5 100644
--- a/components/script/dom/bindings/conversions.rs
+++ b/components/script/dom/bindings/conversions.rs
@@ -39,7 +39,8 @@ use dom::bindings::reflector::{Reflectable, Reflector};
use dom::bindings::str::{ByteString, DOMString, USVString};
use dom::bindings::utils::DOMClass;
use js;
-pub use js::conversions::{FromJSValConvertible, ToJSValConvertible, ConversionBehavior};
+pub use js::conversions::{FromJSValConvertible, ToJSValConvertible, ConversionResult};
+pub use js::conversions::ConversionBehavior;
use js::conversions::latin1_to_string;
use js::error::throw_type_error;
use js::glue::{GetProxyPrivate, IsWrapper};
@@ -81,10 +82,17 @@ impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite
unsafe fn from_jsval(cx: *mut JSContext,
value: HandleValue,
option: ())
- -> Result<Finite<T>, ()> {
- let result = try!(FromJSValConvertible::from_jsval(cx, value, option));
+ -> Result<ConversionResult<Finite<T>>, ()> {
+ let result = match FromJSValConvertible::from_jsval(cx, value, option) {
+ Ok(ConversionResult::Success(v)) => v,
+ Ok(ConversionResult::Failure(error)) => {
+ throw_type_error(cx, &error);
+ return Err(());
+ }
+ _ => return Err(()),
+ };
match Finite::new(result) {
- Some(v) => Ok(v),
+ Some(v) => Ok(ConversionResult::Success(v)),
None => {
throw_type_error(cx, "this argument is not a finite floating-point value");
Err(())
@@ -96,15 +104,14 @@ impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite
impl <T: Reflectable + IDLInterface> FromJSValConvertible for Root<T> {
type Config = ();
- unsafe fn from_jsval(cx: *mut JSContext,
+ unsafe fn from_jsval(_cx: *mut JSContext,
value: HandleValue,
_config: Self::Config)
- -> Result<Root<T>, ()> {
- let result = root_from_handlevalue(value);
- if let Err(()) = result {
- throw_type_error(cx, "value is not an object");
- }
- result
+ -> Result<ConversionResult<Root<T>>, ()> {
+ Ok(match root_from_handlevalue(value) {
+ Ok(result) => ConversionResult::Success(result),
+ Err(()) => ConversionResult::Failure("value is not an object".into()),
+ })
}
}
@@ -146,17 +153,17 @@ impl FromJSValConvertible for DOMString {
unsafe fn from_jsval(cx: *mut JSContext,
value: HandleValue,
null_behavior: StringificationBehavior)
- -> Result<DOMString, ()> {
+ -> Result<ConversionResult<DOMString>, ()> {
if null_behavior == StringificationBehavior::Empty &&
value.get().is_null() {
- Ok(DOMString::new())
+ Ok(ConversionResult::Success(DOMString::new()))
} else {
let jsstr = ToString(cx, value);
if jsstr.is_null() {
debug!("ToString failed");
Err(())
} else {
- Ok(jsstring_to_str(cx, jsstr))
+ Ok(ConversionResult::Success(jsstring_to_str(cx, jsstr)))
}
}
}
@@ -203,7 +210,8 @@ pub unsafe fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString
// http://heycam.github.io/webidl/#es-USVString
impl FromJSValConvertible for USVString {
type Config = ();
- unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ()) -> Result<USVString, ()> {
+ unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ())
+ -> Result<ConversionResult<USVString>, ()> {
let jsstr = ToString(cx, value);
if jsstr.is_null() {
debug!("ToString failed");
@@ -212,13 +220,14 @@ impl FromJSValConvertible for USVString {
let latin1 = JS_StringHasLatin1Chars(jsstr);
if latin1 {
// FIXME(ajeffrey): Convert directly from DOMString to USVString
- return Ok(USVString(String::from(jsstring_to_str(cx, jsstr))));
+ return Ok(ConversionResult::Success(
+ USVString(String::from(jsstring_to_str(cx, jsstr)))));
}
let mut length = 0;
let chars = JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), jsstr, &mut length);
assert!(!chars.is_null());
let char_vec = slice::from_raw_parts(chars as *const u16, length as usize);
- Ok(USVString(String::from_utf16_lossy(char_vec)))
+ Ok(ConversionResult::Success(USVString(String::from_utf16_lossy(char_vec))))
}
}
@@ -241,7 +250,7 @@ impl FromJSValConvertible for ByteString {
unsafe fn from_jsval(cx: *mut JSContext,
value: HandleValue,
_option: ())
- -> Result<ByteString, ()> {
+ -> Result<ConversionResult<ByteString>, ()> {
let string = ToString(cx, value);
if string.is_null() {
debug!("ToString failed");
@@ -255,7 +264,7 @@ impl FromJSValConvertible for ByteString {
assert!(!chars.is_null());
let char_slice = slice::from_raw_parts(chars as *mut u8, length as usize);
- return Ok(ByteString::new(char_slice.to_vec()));
+ return Ok(ConversionResult::Success(ByteString::new(char_slice.to_vec())));
}
let mut length = 0;
@@ -266,7 +275,8 @@ impl FromJSValConvertible for ByteString {
throw_type_error(cx, "Invalid ByteString");
Err(())
} else {
- Ok(ByteString::new(char_vec.iter().map(|&c| c as u8).collect()))
+ Ok(ConversionResult::Success(
+ ByteString::new(char_vec.iter().map(|&c| c as u8).collect())))
}
}
}
diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs
index c4bda97e521..c9cbeb09f21 100644
--- a/components/script/dom/bindings/error.rs
+++ b/components/script/dom/bindings/error.rs
@@ -6,16 +6,14 @@
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
use dom::bindings::codegen::PrototypeList::proto_id_to_name;
+use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, ToJSValConvertible};
use dom::bindings::conversions::root_from_object;
-use dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible};
-use dom::bindings::global::GlobalRef;
+use dom::bindings::global::{GlobalRef, global_root_from_context};
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;
-use js::jsapi::JSObject;
use js::jsapi::JS_ClearPendingException;
use js::jsapi::JS_ErrorFromException;
use js::jsapi::JS_GetPendingException;
@@ -134,11 +132,16 @@ 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,
+/// A struct encapsulating information about a runtime script error.
+pub struct ErrorInfo {
+ /// The error message.
+ pub message: String,
+ /// The file name.
+ pub filename: String,
+ /// The line number.
+ pub lineno: c_uint,
+ /// The column number.
+ pub column: c_uint,
}
impl ErrorInfo {
@@ -194,9 +197,11 @@ impl ErrorInfo {
}
/// Report a pending exception, thereby clearing it.
-pub unsafe fn report_pending_exception(cx: *mut JSContext, obj: *mut JSObject) {
+///
+/// The `dispatch_event` argument is temporary and non-standard; passing false
+/// prevents dispatching the `error` event.
+pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool) {
if JS_IsExceptionPending(cx) {
- let _ac = JSAutoCompartment::new(cx, obj);
rooted!(in(cx) let mut value = UndefinedValue());
if !JS_GetPendingException(cx, value.handle_mut()) {
JS_ClearPendingException(cx);
@@ -205,22 +210,30 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, obj: *mut JSObject) {
}
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"),
+ let error_info = if value.is_object() {
+ rooted!(in(cx) let object = value.to_object());
+ let error_info = ErrorInfo::from_native_error(cx, object.handle())
+ .or_else(|| ErrorInfo::from_dom_exception(object.handle()));
+ match error_info {
+ Some(error_info) => error_info,
+ None => {
+ error!("Uncaught exception: failed to extract information");
+ return;
+ }
}
- 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(object.handle()));
- let error_info = match error_info {
- Some(error_info) => error_info,
- None => {
- error!("Uncaught exception: failed to extract information");
- return;
+ } else {
+ match USVString::from_jsval(cx, value.handle(), ()) {
+ Ok(ConversionResult::Success(USVString(string))) => {
+ ErrorInfo {
+ message: format!("uncaught exception: {}", string),
+ filename: String::new(),
+ lineno: 0,
+ column: 0,
+ }
+ },
+ _ => {
+ panic!("Uncaught exception: failed to stringify primitive");
+ },
}
};
@@ -229,6 +242,11 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, obj: *mut JSObject) {
error_info.lineno,
error_info.column,
error_info.message);
+
+ if dispatch_event {
+ let global = global_root_from_context(cx);
+ global.r().report_an_error(error_info, value.handle());
+ }
}
}
diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs
index bfc3212a9c4..a5c9d1a3d79 100644
--- a/components/script/dom/bindings/global.rs
+++ b/components/script/dom/bindings/global.rs
@@ -10,19 +10,22 @@
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::conversions::root_from_object;
+use dom::bindings::error::ErrorInfo;
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflectable, Reflector};
+use dom::console::TimerSet;
use dom::window::{self, ScriptHelpers};
use dom::workerglobalscope::WorkerGlobalScope;
use ipc_channel::ipc::IpcSender;
+use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
use js::jsapi::{CurrentGlobalOrNull, GetGlobalForObjectCrossCompartment};
use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
-use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
+use js::jsapi::HandleValue;
use msg::constellation_msg::PipelineId;
-use net_traits::{ResourceThreads, CoreResourceThread, IpcSend};
+use net_traits::{CoreResourceThread, IpcSend, ResourceThreads};
use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
-use script_thread::{MainThreadScriptChan, ScriptThread, RunnableWrapper};
+use script_thread::{MainThreadScriptChan, RunnableWrapper, ScriptThread};
use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEventRequest};
use task_source::dom_manipulation::DOMManipulationTaskSource;
use task_source::file_reading::FileReadingTaskSource;
@@ -269,11 +272,11 @@ impl<'a> GlobalRef<'a> {
}
}
- /// Returns the receiver's reflector.
- pub fn reflector(&self) -> &Reflector {
+ /// Returns the global's timers for the Console API.
+ pub fn console_timers(&self) -> &TimerSet {
match *self {
- GlobalRef::Window(ref window) => window.reflector(),
- GlobalRef::Worker(ref worker) => worker.reflector(),
+ GlobalRef::Window(ref window) => window.console_timers(),
+ GlobalRef::Worker(ref worker) => worker.console_timers(),
}
}
@@ -285,6 +288,23 @@ impl<'a> GlobalRef<'a> {
GlobalRef::Worker(ref worker) => worker.get_runnable_wrapper(),
}
}
+
+ /// https://html.spec.whatwg.org/multipage/#report-the-error
+ pub fn report_an_error(&self, error_info: ErrorInfo, value: HandleValue) {
+ match *self {
+ GlobalRef::Window(ref window) => window.report_an_error(error_info, value),
+ GlobalRef::Worker(ref worker) => worker.report_an_error(error_info, value),
+ }
+ }
+}
+
+impl<'a> Reflectable for GlobalRef<'a> {
+ fn reflector(&self) -> &Reflector {
+ match *self {
+ GlobalRef::Window(ref window) => window.reflector(),
+ GlobalRef::Worker(ref worker) => worker.reflector(),
+ }
+ }
}
impl GlobalRoot {
diff --git a/components/script/dom/bindings/inheritance.rs b/components/script/dom/bindings/inheritance.rs
index c9ccdbd0325..f4f1274ac6e 100644
--- a/components/script/dom/bindings/inheritance.rs
+++ b/components/script/dom/bindings/inheritance.rs
@@ -6,8 +6,8 @@
pub use dom::bindings::codegen::InheritTypes::*;
-use dom::bindings::conversions::get_dom_class;
use dom::bindings::conversions::{DerivedFrom, IDLInterface};
+use dom::bindings::conversions::get_dom_class;
use dom::bindings::reflector::Reflectable;
use std::mem;
diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs
index 3b2b5dbde36..cae5da97887 100644
--- a/components/script/dom/bindings/interface.rs
+++ b/components/script/dom/bindings/interface.rs
@@ -6,116 +6,30 @@
use dom::bindings::codegen::InterfaceObjectMap::Globals;
use dom::bindings::codegen::PrototypeList;
-use dom::bindings::conversions::get_dom_class;
+use dom::bindings::constant::{ConstantSpec, define_constants};
+use dom::bindings::conversions::{DOM_OBJECT_SLOT, get_dom_class};
use dom::bindings::guard::Guard;
-use dom::bindings::utils::get_proto_or_iface_array;
+use dom::bindings::utils::{DOM_PROTOTYPE_SLOT, ProtoOrIfaceArray, get_proto_or_iface_array};
use js::error::throw_type_error;
use js::glue::{RUST_SYMBOL_TO_JSID, UncheckedUnwrapObject};
-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};
-use js::jsapi::{JSString, JS_AtomizeAndPinString, JS_DefineProperty, JS_DefineProperty1};
-use js::jsapi::{JS_DefineProperty2, JS_DefineProperty4, JS_DefinePropertyById3};
-use js::jsapi::{JS_GetClass, JS_GetFunctionObject, JS_GetPrototype, JS_LinkConstructorAndPrototype};
-use js::jsapi::{JS_NewFunction, JS_NewObject, JS_NewObjectWithUniqueType};
-use js::jsapi::{JS_NewPlainObject, JS_NewStringCopyN, MutableHandleObject};
-use js::jsapi::{MutableHandleValue, ObjectOps};
-use js::jsapi::{SymbolCode, TrueHandleValue, Value};
-use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value};
+use js::jsapi::{Class, ClassOps, CompartmentOptions, GetGlobalForObjectCrossCompartment};
+use js::jsapi::{GetWellKnownSymbol, HandleObject, HandleValue, JSAutoCompartment};
+use js::jsapi::{JSClass, JSContext, JSFUN_CONSTRUCTOR, JSFunctionSpec, JSObject};
+use js::jsapi::{JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_RESOLVING};
+use js::jsapi::{JSPropertySpec, JSString, JSTracer, JSVersion, JS_AtomizeAndPinString};
+use js::jsapi::{JS_DefineProperty, JS_DefineProperty1, JS_DefineProperty2};
+use js::jsapi::{JS_DefineProperty4, JS_DefinePropertyById3, JS_FireOnNewGlobalObject};
+use js::jsapi::{JS_GetClass, JS_GetFunctionObject, JS_GetPrototype};
+use js::jsapi::{JS_LinkConstructorAndPrototype, JS_NewFunction, JS_NewGlobalObject};
+use js::jsapi::{JS_NewObject, JS_NewObjectWithUniqueType, JS_NewPlainObject};
+use js::jsapi::{JS_NewStringCopyN, JS_SetReservedSlot, MutableHandleObject};
+use js::jsapi::{MutableHandleValue, ObjectOps, OnNewGlobalHookOption, SymbolCode};
+use js::jsapi::{TrueHandleValue, Value};
+use js::jsval::{JSVal, PrivateValue};
use js::rust::{define_methods, define_properties};
use libc;
use std::ptr;
-/// Representation of an IDL constant value.
-#[derive(Clone)]
-pub enum ConstantVal {
- /// `long` constant.
- IntVal(i32),
- /// `unsigned long` constant.
- UintVal(u32),
- /// `double` constant.
- DoubleVal(f64),
- /// `boolean` constant.
- BoolVal(bool),
- /// `null` constant.
- NullVal,
-}
-
-/// Representation of an IDL constant.
-#[derive(Clone)]
-pub struct ConstantSpec {
- /// name of the constant.
- pub name: &'static [u8],
- /// value of the constant.
- pub value: ConstantVal,
-}
-
-impl ConstantSpec {
- /// Returns a `JSVal` that represents the value of this `ConstantSpec`.
- pub fn get_value(&self) -> JSVal {
- match self.value {
- ConstantVal::NullVal => NullValue(),
- ConstantVal::IntVal(i) => Int32Value(i),
- ConstantVal::UintVal(u) => UInt32Value(u),
- ConstantVal::DoubleVal(d) => DoubleValue(d),
- ConstantVal::BoolVal(b) => BooleanValue(b),
- }
- }
-}
-
-/// A JSNative that cannot be null.
-pub type NonNullJSNative =
- unsafe extern "C" fn (arg1: *mut JSContext, arg2: libc::c_uint, arg3: *mut JSVal) -> bool;
-
-/// Defines constants on `obj`.
-/// Fails on JSAPI failure.
-fn define_constants(
- cx: *mut JSContext,
- obj: HandleObject,
- constants: &[ConstantSpec]) {
- for spec in constants {
- rooted!(in(cx) let value = spec.get_value());
- unsafe {
- assert!(JS_DefineProperty(cx,
- obj,
- spec.name.as_ptr() as *const libc::c_char,
- value.handle(),
- JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT,
- None,
- None));
- }
- }
-}
-
-unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext,
- obj: HandleObject,
- _indent: u32)
- -> *mut JSString {
- let js_class = JS_GetClass(obj.get());
- assert!(!js_class.is_null());
- let repr = (*(js_class as *const NonCallbackInterfaceObjectClass)).representation;
- assert!(!repr.is_empty());
- let ret = JS_NewStringCopyN(cx, repr.as_ptr() as *const libc::c_char, repr.len());
- assert!(!ret.is_null());
- 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 {
@@ -132,27 +46,8 @@ 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(ops: &'static ClassOps,
+ pub const fn new(constructor_behavior: &'static InterfaceConstructorBehavior,
string_rep: &'static [u8],
proto_id: PrototypeList::ID,
proto_depth: u16)
@@ -161,7 +56,7 @@ impl NonCallbackInterfaceObjectClass {
class: Class {
name: b"Function\0" as *const _ as *const libc::c_char,
flags: 0,
- cOps: ops,
+ cOps: &constructor_behavior.0,
spec: ptr::null(),
ext: ptr::null(),
oOps: &OBJECT_OPS,
@@ -185,29 +80,84 @@ pub type ConstructorClassHook =
unsafe extern "C" fn(cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool;
/// The constructor behavior of a non-callback interface object.
-pub struct InterfaceConstructorBehavior {
- call: JSNative,
- construct: JSNative,
-}
+pub struct InterfaceConstructorBehavior(ClassOps);
impl InterfaceConstructorBehavior {
/// An interface constructor that unconditionally throws a type error.
- pub const fn throw() -> InterfaceConstructorBehavior {
- InterfaceConstructorBehavior {
+ pub const fn throw() -> Self {
+ InterfaceConstructorBehavior(ClassOps {
+ addProperty: None,
+ delProperty: None,
+ getProperty: None,
+ setProperty: None,
+ enumerate: None,
+ resolve: None,
+ mayResolve: None,
+ finalize: None,
call: Some(invalid_constructor),
construct: Some(invalid_constructor),
- }
+ hasInstance: Some(has_instance_hook),
+ trace: None,
+ })
}
/// An interface constructor that calls a native Rust function.
- pub const fn call(hook: ConstructorClassHook) -> InterfaceConstructorBehavior {
- InterfaceConstructorBehavior {
+ pub const fn call(hook: ConstructorClassHook) -> Self {
+ InterfaceConstructorBehavior(ClassOps {
+ addProperty: None,
+ delProperty: None,
+ getProperty: None,
+ setProperty: None,
+ enumerate: None,
+ resolve: None,
+ mayResolve: None,
+ finalize: None,
call: Some(non_new_constructor),
construct: Some(hook),
- }
+ hasInstance: Some(has_instance_hook),
+ trace: None,
+ })
}
}
+/// A trace hook.
+pub type TraceHook =
+ unsafe extern "C" fn(trc: *mut JSTracer, obj: *mut JSObject);
+
+/// Create a global object with the given class.
+pub unsafe fn create_global_object(
+ cx: *mut JSContext,
+ class: &'static JSClass,
+ private: *const libc::c_void,
+ trace: TraceHook,
+ rval: MutableHandleObject) {
+ assert!(rval.is_null());
+
+ let mut options = CompartmentOptions::default();
+ options.behaviors_.version_ = JSVersion::JSVERSION_ECMA_5;
+ options.creationOptions_.traceGlobal_ = Some(trace);
+ options.creationOptions_.sharedMemoryAndAtomics_ = true;
+
+ rval.set(JS_NewGlobalObject(cx,
+ class,
+ ptr::null_mut(),
+ OnNewGlobalHookOption::DontFireOnNewGlobalHook,
+ &options));
+ assert!(!rval.is_null());
+
+ // Initialize the reserved slots before doing anything that can GC, to
+ // avoid getting trace hooks called on a partially initialized object.
+ JS_SetReservedSlot(rval.get(), DOM_OBJECT_SLOT, PrivateValue(private));
+ let proto_array: Box<ProtoOrIfaceArray> =
+ box [0 as *mut JSObject; PrototypeList::PROTO_OR_IFACE_LENGTH];
+ JS_SetReservedSlot(rval.get(),
+ DOM_PROTOTYPE_SLOT,
+ PrivateValue(Box::into_raw(proto_array) as *const libc::c_void));
+
+ let _ac = JSAutoCompartment::new(cx, rval.get());
+ JS_FireOnNewGlobalObject(cx, rval.handle());
+}
+
/// Create and define the interface object of a callback interface.
pub unsafe fn create_callback_interface_object(
cx: *mut JSContext,
@@ -218,11 +168,7 @@ pub unsafe fn create_callback_interface_object(
assert!(!constants.is_empty());
rval.set(JS_NewObject(cx, ptr::null()));
assert!(!rval.ptr.is_null());
- for guard in constants {
- if let Some(specs) = guard.expose(cx, rval.handle()) {
- define_constants(cx, rval.handle(), specs);
- }
- }
+ define_guarded_constants(cx, rval.handle(), constants);
define_name(cx, rval.handle(), name);
define_on_global_object(cx, global, name, rval.handle());
}
@@ -283,7 +229,7 @@ pub unsafe fn create_noncallback_interface_object(
pub unsafe fn create_named_constructors(
cx: *mut JSContext,
global: HandleObject,
- named_constructors: &[(NonNullJSNative, &[u8], u32)],
+ named_constructors: &[(ConstructorClassHook, &[u8], u32)],
interface_prototype_object: HandleObject) {
rooted!(in(cx) let mut constructor = ptr::null_mut());
@@ -311,6 +257,110 @@ pub unsafe fn create_named_constructors(
}
}
+/// Create a new object with a unique type.
+pub unsafe fn create_object(
+ cx: *mut JSContext,
+ proto: HandleObject,
+ class: &'static JSClass,
+ methods: &[Guard<&'static [JSFunctionSpec]>],
+ properties: &[Guard<&'static [JSPropertySpec]>],
+ constants: &[Guard<&[ConstantSpec]>],
+ rval: MutableHandleObject) {
+ rval.set(JS_NewObjectWithUniqueType(cx, class, proto));
+ assert!(!rval.ptr.is_null());
+ define_guarded_methods(cx, rval.handle(), methods);
+ define_guarded_properties(cx, rval.handle(), properties);
+ define_guarded_constants(cx, rval.handle(), constants);
+}
+
+/// Conditionally define constants on an object.
+pub unsafe fn define_guarded_constants(
+ cx: *mut JSContext,
+ obj: HandleObject,
+ constants: &[Guard<&[ConstantSpec]>]) {
+ for guard in constants {
+ if let Some(specs) = guard.expose(cx, obj) {
+ define_constants(cx, obj, specs);
+ }
+ }
+}
+
+/// Conditionally define methods on an object.
+pub unsafe fn define_guarded_methods(
+ cx: *mut JSContext,
+ obj: HandleObject,
+ methods: &[Guard<&'static [JSFunctionSpec]>]) {
+ for guard in methods {
+ if let Some(specs) = guard.expose(cx, obj) {
+ define_methods(cx, obj, specs).unwrap();
+ }
+ }
+}
+
+/// Conditionally define properties on an object.
+pub unsafe fn define_guarded_properties(
+ cx: *mut JSContext,
+ obj: HandleObject,
+ properties: &[Guard<&'static [JSPropertySpec]>]) {
+ for guard in properties {
+ if let Some(specs) = guard.expose(cx, obj) {
+ define_properties(cx, obj, specs).unwrap();
+ }
+ }
+}
+
+/// Returns whether an interface with exposure set given by `globals` should
+/// be exposed in the global object `obj`.
+pub unsafe fn is_exposed_in(object: HandleObject, globals: Globals) -> bool {
+ let unwrapped = UncheckedUnwrapObject(object.get(), /* stopAtWindowProxy = */ 0);
+ let dom_class = get_dom_class(unwrapped).unwrap();
+ globals.contains(dom_class.global)
+}
+
+/// Define a property with a given name on the global object. Should be called
+/// through the resolve hook.
+pub unsafe fn define_on_global_object(
+ cx: *mut JSContext,
+ global: HandleObject,
+ name: &[u8],
+ obj: HandleObject) {
+ assert!(*name.last().unwrap() == b'\0');
+ assert!(JS_DefineProperty1(cx,
+ global,
+ name.as_ptr() as *const libc::c_char,
+ obj,
+ JSPROP_RESOLVING,
+ None, None));
+}
+
+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),
+};
+
+unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext,
+ obj: HandleObject,
+ _indent: u32)
+ -> *mut JSString {
+ let js_class = JS_GetClass(obj.get());
+ assert!(!js_class.is_null());
+ let repr = (*(js_class as *const NonCallbackInterfaceObjectClass)).representation;
+ assert!(!repr.is_empty());
+ let ret = JS_NewStringCopyN(cx, repr.as_ptr() as *const libc::c_char, repr.len());
+ assert!(!ret.is_null());
+ ret
+}
+
/// Hook for instanceof on interface objects.
unsafe extern "C" fn has_instance_hook(cx: *mut JSContext,
obj: HandleObject,
@@ -370,25 +420,6 @@ unsafe fn has_instance(
Err(())
}
-unsafe fn create_object(
- cx: *mut JSContext,
- proto: HandleObject,
- class: &'static JSClass,
- methods: &[Guard<&'static [JSFunctionSpec]>],
- properties: &[Guard<&'static [JSPropertySpec]>],
- constants: &[Guard<&[ConstantSpec]>],
- rval: MutableHandleObject) {
- rval.set(JS_NewObjectWithUniqueType(cx, class, proto));
- assert!(!rval.ptr.is_null());
- define_guarded_methods(cx, rval.handle(), methods);
- define_guarded_properties(cx, rval.handle(), properties);
- for guard in constants {
- if let Some(specs) = guard.expose(cx, rval.handle()) {
- define_constants(cx, rval.handle(), specs);
- }
- }
-}
-
unsafe fn create_unscopable_object(
cx: *mut JSContext,
names: &[&[u8]],
@@ -405,30 +436,6 @@ unsafe fn create_unscopable_object(
}
}
-/// Conditionally define methods on an object.
-pub unsafe fn define_guarded_methods(
- cx: *mut JSContext,
- obj: HandleObject,
- methods: &[Guard<&'static [JSFunctionSpec]>]) {
- for guard in methods {
- if let Some(specs) = guard.expose(cx, obj) {
- define_methods(cx, obj, specs).unwrap();
- }
- }
-}
-
-/// Conditionally define properties on an object.
-pub unsafe fn define_guarded_properties(
- cx: *mut JSContext,
- obj: HandleObject,
- properties: &[Guard<&'static [JSPropertySpec]>]) {
- for guard in properties {
- if let Some(specs) = guard.expose(cx, obj) {
- define_properties(cx, obj, specs).unwrap();
- }
- }
-}
-
unsafe fn define_name(cx: *mut JSContext, obj: HandleObject, name: &[u8]) {
assert!(*name.last().unwrap() == b'\0');
rooted!(in(cx) let name = JS_AtomizeAndPinString(cx, name.as_ptr() as *const libc::c_char));
@@ -450,20 +457,6 @@ unsafe fn define_length(cx: *mut JSContext, obj: HandleObject, length: u32) {
None, None));
}
-unsafe fn define_on_global_object(
- cx: *mut JSContext,
- global: HandleObject,
- name: &[u8],
- obj: HandleObject) {
- assert!(*name.last().unwrap() == b'\0');
- assert!(JS_DefineProperty1(cx,
- global,
- name.as_ptr() as *const libc::c_char,
- obj,
- JSPROP_RESOLVING,
- None, None));
-}
-
unsafe extern "C" fn invalid_constructor(
cx: *mut JSContext,
_argc: libc::c_uint,
@@ -481,11 +474,3 @@ unsafe extern "C" fn non_new_constructor(
throw_type_error(cx, "This constructor needs to be called with `new`.");
false
}
-
-/// Returns whether an interface with exposure set given by `globals` should
-/// be exposed in the global object `obj`.
-pub unsafe fn is_exposed_in(object: HandleObject, globals: Globals) -> bool {
- let unwrapped = UncheckedUnwrapObject(object.get(), /* stopAtWindowProxy = */ 0);
- let dom_class = get_dom_class(unwrapped).unwrap();
- globals.contains(dom_class.global)
-}
diff --git a/components/script/dom/bindings/iterable.rs b/components/script/dom/bindings/iterable.rs
new file mode 100644
index 00000000000..84381b52655
--- /dev/null
+++ b/components/script/dom/bindings/iterable.rs
@@ -0,0 +1,168 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#![allow(unsafe_code)]
+
+//! Implementation of `iterable<...>` and `iterable<..., ...>` WebIDL declarations.
+
+use core::nonzero::NonZero;
+use dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyAndValueResult;
+use dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyOrValueResult;
+use dom::bindings::error::Fallible;
+use dom::bindings::global::GlobalRef;
+use dom::bindings::js::{JS, Root};
+use dom::bindings::reflector::{Reflector, Reflectable, MutReflectable, reflect_dom_object};
+use dom::bindings::trace::JSTraceable;
+use js::conversions::ToJSValConvertible;
+use js::jsapi::{JSContext, JSObject, MutableHandleValue, MutableHandleObject, HandleValue};
+use js::jsval::UndefinedValue;
+use std::cell::Cell;
+use std::ptr;
+
+/// The values that an iterator will iterate over.
+#[derive(JSTraceable, HeapSizeOf)]
+pub enum IteratorType {
+ /// The keys of the iterable object.
+ Keys,
+ /// The values of the iterable object.
+ Values,
+ /// The keys and values of the iterable object combined.
+ Entries,
+}
+
+/// A DOM object that can be iterated over using a pair value iterator.
+pub trait Iterable {
+ /// The type of the key of the iterator pair.
+ type Key: ToJSValConvertible;
+ /// The type of the value of the iterator pair.
+ type Value: ToJSValConvertible;
+ /// Return the number of entries that can be iterated over.
+ fn get_iterable_length(&self) -> u32;
+ /// Return the value at the provided index.
+ fn get_value_at_index(&self, index: u32) -> Self::Value;
+ /// Return the key at the provided index.
+ fn get_key_at_index(&self, index: u32) -> Self::Key;
+}
+
+/// An iterator over the iterable entries of a given DOM interface.
+//FIXME: #12811 prevents dom_struct with type parameters
+//#[dom_struct]
+#[must_root]
+#[privatize]
+#[derive(JSTraceable)]
+#[derive(HeapSizeOf)]
+pub struct IterableIterator<T: Reflectable + JSTraceable + Iterable> {
+ reflector: Reflector,
+ iterable: JS<T>,
+ type_: IteratorType,
+ index: Cell<u32>,
+}
+
+impl<T: Reflectable + JSTraceable + Iterable> Reflectable for IterableIterator<T> {
+ fn reflector<'a>(&'a self) -> &'a Reflector {
+ &self.reflector
+ }
+}
+
+impl<T: Reflectable + JSTraceable + Iterable> MutReflectable for IterableIterator<T> {
+ fn init_reflector(&mut self, obj: *mut JSObject) {
+ self.reflector.set_jsobject(obj);
+ }
+}
+
+impl<T: Reflectable + JSTraceable + Iterable> ToJSValConvertible for IterableIterator<T> {
+ #[allow(unsafe_code)]
+ unsafe fn to_jsval(&self,
+ cx: *mut JSContext,
+ rval: MutableHandleValue) {
+ let object = Reflectable::reflector(self).get_jsobject();
+ object.to_jsval(cx, rval)
+ }
+}
+
+impl<T: Reflectable + JSTraceable + Iterable> IterableIterator<T> {
+ /// Create a new iterator instance for the provided iterable DOM interface.
+ pub fn new(iterable: &T,
+ type_: IteratorType,
+ wrap: fn(*mut JSContext, GlobalRef, Box<IterableIterator<T>>)
+ -> Root<Self>) -> Root<Self> {
+ let iterator = box IterableIterator {
+ reflector: Reflector::new(),
+ type_: type_,
+ iterable: JS::from_ref(iterable),
+ index: Cell::new(0),
+ };
+ let global = iterable.global();
+ reflect_dom_object(iterator, global.r(), wrap)
+ }
+
+ /// Return the next value from the iterable object.
+ #[allow(non_snake_case)]
+ pub fn Next(&self, cx: *mut JSContext) -> Fallible<NonZero<*mut JSObject>> {
+ let index = self.index.get();
+ rooted!(in(cx) let mut value = UndefinedValue());
+ rooted!(in(cx) let mut rval = ptr::null_mut());
+ let result = if index >= self.iterable.get_iterable_length() {
+ dict_return(cx, rval.handle_mut(), true, value.handle())
+ } else {
+ match self.type_ {
+ IteratorType::Keys => {
+ unsafe {
+ self.iterable.get_key_at_index(index).to_jsval(cx, value.handle_mut());
+ }
+ dict_return(cx, rval.handle_mut(), false, value.handle())
+ }
+ IteratorType::Values => {
+ unsafe {
+ self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut());
+ }
+ dict_return(cx, rval.handle_mut(), false, value.handle())
+ }
+ IteratorType::Entries => {
+ rooted!(in(cx) let mut key = UndefinedValue());
+ unsafe {
+ self.iterable.get_key_at_index(index).to_jsval(cx, key.handle_mut());
+ self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut());
+ }
+ key_and_value_return(cx, rval.handle_mut(), key.handle(), value.handle())
+ }
+ }
+ };
+ self.index.set(index + 1);
+ result.map(|_| {
+ assert!(!rval.is_null());
+ unsafe { NonZero::new(rval.get()) }
+ })
+ }
+}
+
+fn dict_return(cx: *mut JSContext,
+ result: MutableHandleObject,
+ done: bool,
+ value: HandleValue) -> Fallible<()> {
+ let mut dict = unsafe { IterableKeyOrValueResult::empty(cx) };
+ dict.done = done;
+ dict.value = value.get();
+ rooted!(in(cx) let mut dict_value = UndefinedValue());
+ unsafe {
+ dict.to_jsval(cx, dict_value.handle_mut());
+ }
+ result.set(dict_value.to_object());
+ Ok(())
+}
+
+fn key_and_value_return(cx: *mut JSContext,
+ result: MutableHandleObject,
+ key: HandleValue,
+ value: HandleValue) -> Fallible<()> {
+ let mut dict = unsafe { IterableKeyAndValueResult::empty(cx) };
+ dict.done = false;
+ dict.value = Some(vec![key.get(), value.get()]);
+ rooted!(in(cx) let mut dict_value = UndefinedValue());
+ unsafe {
+ dict.to_jsval(cx, dict_value.handle_mut());
+ }
+ result.set(dict_value.to_object());
+ Ok(())
+}
diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs
index 6a0dfd83dea..a7ecc975129 100644
--- a/components/script/dom/bindings/js.rs
+++ b/components/script/dom/bindings/js.rs
@@ -126,7 +126,10 @@ impl<T: Castable> LayoutJS<T> {
T: DerivedFrom<U>
{
debug_assert!(thread_state::get().is_layout());
- unsafe { mem::transmute_copy(self) }
+ let ptr: *const T = *self.ptr;
+ LayoutJS {
+ ptr: unsafe { NonZero::new(ptr as *const U) },
+ }
}
/// Cast a DOM object downwards to one of the interfaces it might implement.
@@ -136,7 +139,10 @@ impl<T: Castable> LayoutJS<T> {
debug_assert!(thread_state::get().is_layout());
unsafe {
if (*self.unsafe_get()).is::<U>() {
- Some(mem::transmute_copy(self))
+ let ptr: *const T = *self.ptr;
+ Some(LayoutJS {
+ ptr: NonZero::new(ptr as *const U),
+ })
} else {
None
}
diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs
index 19797a473d0..16607c9045f 100644
--- a/components/script/dom/bindings/mod.rs
+++ b/components/script/dom/bindings/mod.rs
@@ -128,15 +128,19 @@
//! return `Err()` from the method with the appropriate [error value]
//! (error/enum.Error.html).
+pub use style::domrefcell as cell;
+
pub mod callback;
-pub mod cell;
+pub mod constant;
pub mod conversions;
pub mod error;
pub mod global;
pub mod guard;
pub mod inheritance;
pub mod interface;
+pub mod iterable;
pub mod js;
+pub mod namespace;
pub mod num;
pub mod proxyhandler;
pub mod refcounted;
diff --git a/components/script/dom/bindings/namespace.rs b/components/script/dom/bindings/namespace.rs
new file mode 100644
index 00000000000..38055dea180
--- /dev/null
+++ b/components/script/dom/bindings/namespace.rs
@@ -0,0 +1,42 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! Machinery to initialise namespace objects.
+
+use dom::bindings::guard::Guard;
+use dom::bindings::interface::{create_object, define_on_global_object};
+use js::jsapi::{HandleObject, JSClass, JSContext, JSFunctionSpec, MutableHandleObject};
+use libc;
+use std::ptr;
+
+/// The class of a namespace object.
+#[derive(Copy, Clone)]
+pub struct NamespaceObjectClass(JSClass);
+
+unsafe impl Sync for NamespaceObjectClass {}
+
+impl NamespaceObjectClass {
+ /// Create a new `NamespaceObjectClass` structure.
+ pub const unsafe fn new(name: &'static [u8]) -> Self {
+ NamespaceObjectClass(JSClass {
+ name: name as *const _ as *const libc::c_char,
+ flags: 0,
+ cOps: ptr::null_mut(),
+ reserved: [ptr::null_mut(); 3],
+ })
+ }
+}
+
+/// Create a new namespace object.
+pub unsafe fn create_namespace_object(
+ cx: *mut JSContext,
+ global: HandleObject,
+ proto: HandleObject,
+ class: &'static NamespaceObjectClass,
+ methods: &[Guard<&'static [JSFunctionSpec]>],
+ name: &[u8],
+ rval: MutableHandleObject) {
+ create_object(cx, proto, &class.0, methods, &[], &[], rval);
+ define_on_global_object(cx, global, name, rval.handle());
+}
diff --git a/components/script/dom/bindings/proxyhandler.rs b/components/script/dom/bindings/proxyhandler.rs
index c863cc31994..cacac064376 100644
--- a/components/script/dom/bindings/proxyhandler.rs
+++ b/components/script/dom/bindings/proxyhandler.rs
@@ -8,23 +8,54 @@
use dom::bindings::conversions::is_dom_proxy;
use dom::bindings::utils::delete_property_by_id;
+use js::glue::{GetProxyHandler, GetProxyHandlerFamily, SetProxyExtra};
use js::glue::GetProxyExtra;
use js::glue::InvokeGetOwnPropertyDescriptor;
-use js::glue::{GetProxyHandler, SetProxyExtra};
+use js::jsapi::{DOMProxyShadowsResult, JSContext, JSObject, JSPROP_GETTER, PropertyDescriptor};
+use js::jsapi::{Handle, HandleId, HandleObject, MutableHandle, ObjectOpResult};
+use js::jsapi::{JSErrNum, JS_AlreadyHasOwnPropertyById, JS_StrictPropertyStub};
+use js::jsapi::{JS_DefinePropertyById, JS_NewObjectWithGivenProto, SetDOMProxyInformation};
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};
-use js::jsapi::{JS_DefinePropertyById, JS_NewObjectWithGivenProto};
use js::jsval::ObjectValue;
use libc;
use std::{mem, ptr};
+
static JSPROXYSLOT_EXPANDO: u32 = 0;
+/// Determine if this id shadows any existing properties for this proxy.
+pub unsafe extern "C" fn shadow_check_callback(cx: *mut JSContext,
+ object: HandleObject,
+ id: HandleId)
+ -> DOMProxyShadowsResult {
+ // TODO: support OverrideBuiltins when #12978 is fixed.
+
+ rooted!(in(cx) let expando = get_expando_object(object));
+ if !expando.get().is_null() {
+ let mut has_own = false;
+ if !JS_AlreadyHasOwnPropertyById(cx, expando.handle(), id, &mut has_own) {
+ return DOMProxyShadowsResult::ShadowCheckFailed;
+ }
+
+ if has_own {
+ return DOMProxyShadowsResult::ShadowsViaDirectExpando;
+ }
+ }
+
+ // Our expando, if any, didn't shadow, so we're not shadowing at all.
+ DOMProxyShadowsResult::DoesntShadow
+}
+
+/// Initialize the infrastructure for DOM proxy objects.
+pub unsafe fn init() {
+ SetDOMProxyInformation(GetProxyHandlerFamily(),
+ JSPROXYSLOT_EXPANDO,
+ Some(shadow_check_callback));
+}
+
/// Invoke the [[GetOwnProperty]] trap (`getOwnPropertyDescriptor`) on `proxy`,
/// with argument `id` and return the result, if it is not `undefined`.
/// Otherwise, walk along the prototype chain to find a property with that
diff --git a/components/script/dom/bindings/refcounted.rs b/components/script/dom/bindings/refcounted.rs
index 25239a3dc3b..ea4c47b1148 100644
--- a/components/script/dom/bindings/refcounted.rs
+++ b/components/script/dom/bindings/refcounted.rs
@@ -6,21 +6,21 @@
//! between threads (or intra-thread for asynchronous events). Akin to Gecko's
//! nsMainThreadPtrHandle, this uses thread-safe reference counting and ensures
//! that the actual SpiderMonkey GC integration occurs on the script thread via
-//! message passing. Ownership of a `Trusted<T>` object means the DOM object of
+//! weak refcounts. Ownership of a `Trusted<T>` object means the DOM object of
//! type T to which it points remains alive. Any other behaviour is undefined.
//! To guarantee the lifetime of a DOM object when performing asynchronous operations,
//! obtain a `Trusted<T>` from that object and pass it along with each operation.
//! A usable pointer to the original DOM object can be obtained on the script thread
//! from a `Trusted<T>` via the `to_temporary` method.
//!
-//! The implementation of Trusted<T> is as follows:
-//! A hashtable resides in the script thread, keyed on the pointer to the Rust DOM object.
-//! The values in this hashtable are atomic reference counts. When a Trusted<T> object is
-//! created or cloned, this count is increased. When a Trusted<T> is dropped, the count
-//! decreases. If the count hits zero, a message is dispatched to the script thread to remove
-//! the entry from the hashmap if the count is still zero. The JS reflector for the DOM object
-//! is rooted when a hashmap entry is first created, and unrooted when the hashmap entry
-//! is removed.
+//! The implementation of `Trusted<T>` is as follows:
+//! The `Trusted<T>` object contains an atomic reference counted pointer to the Rust DOM object.
+//! A hashtable resides in the script thread, keyed on the pointer.
+//! The values in this hashtable are weak reference counts. When a `Trusted<T>` object is
+//! created or cloned, the reference count is increased. When a `Trusted<T>` is dropped, the count
+//! decreases. If the count hits zero, the weak reference is emptied, and is removed from
+//! its hash table during the next GC. During GC, the entries of the hash table are counted
+//! as JS roots.
use core::nonzero::NonZero;
use dom::bindings::js::Root;
@@ -28,13 +28,13 @@ use dom::bindings::reflector::{Reflectable, Reflector};
use dom::bindings::trace::trace_reflector;
use js::jsapi::JSTracer;
use libc;
-use script_runtime::{CommonScriptMsg, ScriptChan};
use std::cell::RefCell;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::hash_map::HashMap;
+use std::hash::Hash;
use std::marker::PhantomData;
use std::os;
-use std::sync::{Arc, Mutex};
+use std::sync::{Arc, Weak};
#[allow(missing_docs)] // FIXME
@@ -52,6 +52,12 @@ pub use self::dummy::LIVE_REFERENCES;
pub struct TrustedReference(*const libc::c_void);
unsafe impl Send for TrustedReference {}
+impl TrustedReference {
+ fn new<T: Reflectable>(ptr: *const T) -> TrustedReference {
+ TrustedReference(ptr as *const libc::c_void)
+ }
+}
+
/// A safe wrapper around a raw pointer to a DOM object that can be
/// shared among threads for use in asynchronous operations. The underlying
/// DOM object is guaranteed to live at least as long as the last outstanding
@@ -60,9 +66,7 @@ unsafe impl Send for TrustedReference {}
pub struct Trusted<T: Reflectable> {
/// A pointer to the Rust DOM object of type T, but void to allow
/// sending `Trusted<T>` between threads, regardless of T's sendability.
- ptr: *const libc::c_void,
- refcount: Arc<Mutex<usize>>,
- script_chan: Box<ScriptChan + Send>,
+ refcount: Arc<TrustedReference>,
owner_thread: *const libc::c_void,
phantom: PhantomData<T>,
}
@@ -74,15 +78,12 @@ impl<T: Reflectable> Trusted<T> {
/// be prevented from being GCed for the duration of the resulting `Trusted<T>` object's
/// lifetime.
pub fn new(ptr: &T) -> Trusted<T> {
- let script_chan = ptr.global().r().script_chan();
LIVE_REFERENCES.with(|ref r| {
let r = r.borrow();
let live_references = r.as_ref().unwrap();
let refcount = live_references.addref(&*ptr as *const T);
Trusted {
- ptr: &*ptr as *const T as *const libc::c_void,
refcount: refcount,
- script_chan: script_chan.clone(),
owner_thread: (&*live_references) as *const _ as *const libc::c_void,
phantom: PhantomData,
}
@@ -99,48 +100,26 @@ impl<T: Reflectable> Trusted<T> {
self.owner_thread == (&*live_references) as *const _ as *const libc::c_void
}));
unsafe {
- Root::new(NonZero::new(self.ptr as *const T))
+ Root::new(NonZero::new(self.refcount.0 as *const T))
}
}
}
impl<T: Reflectable> Clone for Trusted<T> {
fn clone(&self) -> Trusted<T> {
- {
- let mut refcount = self.refcount.lock().unwrap();
- *refcount += 1;
- }
-
Trusted {
- ptr: self.ptr,
refcount: self.refcount.clone(),
- script_chan: self.script_chan.clone(),
owner_thread: self.owner_thread,
phantom: PhantomData,
}
}
}
-impl<T: Reflectable> Drop for Trusted<T> {
- fn drop(&mut self) {
- let mut refcount = self.refcount.lock().unwrap();
- assert!(*refcount > 0);
- *refcount -= 1;
- if *refcount == 0 {
- // It's possible this send will fail if the script thread
- // has already exited. There's not much we can do at this
- // point though.
- let msg = CommonScriptMsg::RefcountCleanup(TrustedReference(self.ptr));
- let _ = self.script_chan.send(msg);
- }
- }
-}
-
/// The set of live, pinned DOM objects that are currently prevented
/// from being garbage collected due to outstanding references.
pub struct LiveDOMReferences {
// keyed on pointer to Rust DOM object
- table: RefCell<HashMap<*const libc::c_void, Arc<Mutex<usize>>>>,
+ table: RefCell<HashMap<*const libc::c_void, Weak<TrustedReference>>>,
}
impl LiveDOMReferences {
@@ -153,59 +132,55 @@ impl LiveDOMReferences {
});
}
- fn addref<T: Reflectable>(&self, ptr: *const T) -> Arc<Mutex<usize>> {
+ fn addref<T: Reflectable>(&self, ptr: *const T) -> Arc<TrustedReference> {
let mut table = self.table.borrow_mut();
+ let capacity = table.capacity();
+ let len = table.len();
+ if (0 < capacity) && (capacity <= len) {
+ info!("growing refcounted references by {}", len);
+ remove_nulls(&mut table);
+ table.reserve(len);
+ }
match table.entry(ptr as *const libc::c_void) {
- Occupied(mut entry) => {
- let refcount = entry.get_mut();
- *refcount.lock().unwrap() += 1;
- refcount.clone()
- }
+ Occupied(mut entry) => match entry.get().upgrade() {
+ Some(refcount) => refcount,
+ None => {
+ let refcount = Arc::new(TrustedReference::new(ptr));
+ entry.insert(Arc::downgrade(&refcount));
+ refcount
+ },
+ },
Vacant(entry) => {
- let refcount = Arc::new(Mutex::new(1));
- entry.insert(refcount.clone());
+ let refcount = Arc::new(TrustedReference::new(ptr));
+ entry.insert(Arc::downgrade(&refcount));
refcount
}
}
}
+}
- /// Unpin the given DOM object if its refcount is 0.
- pub fn cleanup(raw_reflectable: TrustedReference) {
- let TrustedReference(raw_reflectable) = raw_reflectable;
- LIVE_REFERENCES.with(|ref r| {
- let r = r.borrow();
- let live_references = r.as_ref().unwrap();
- let mut table = live_references.table.borrow_mut();
- match table.entry(raw_reflectable) {
- Occupied(entry) => {
- if *entry.get().lock().unwrap() != 0 {
- // there could have been a new reference taken since
- // this message was dispatched.
- return;
- }
-
- let _ = entry.remove();
- }
- Vacant(_) => {
- // there could be a cleanup message dispatched, then a new
- // pinned reference obtained and released before the message
- // is processed, at which point there would be no matching
- // hashtable entry.
- info!("attempt to cleanup an unrecognized reflector");
- }
- }
- })
+/// Remove null entries from the live references table
+fn remove_nulls<K: Eq + Hash + Clone, V> (table: &mut HashMap<K, Weak<V>>) {
+ let to_remove: Vec<K> =
+ table.iter()
+ .filter(|&(_, value)| Weak::upgrade(value).is_none())
+ .map(|(key, _)| key.clone())
+ .collect();
+ info!("removing {} refcounted references", to_remove.len());
+ for key in to_remove {
+ table.remove(&key);
}
}
/// A JSTraceDataOp for tracing reflectors held in LIVE_REFERENCES
pub unsafe extern "C" fn trace_refcounted_objects(tracer: *mut JSTracer,
_data: *mut os::raw::c_void) {
- debug!("tracing live refcounted references");
+ info!("tracing live refcounted references");
LIVE_REFERENCES.with(|ref r| {
let r = r.borrow();
let live_references = r.as_ref().unwrap();
- let table = live_references.table.borrow();
+ let mut table = live_references.table.borrow_mut();
+ remove_nulls(&mut table);
for obj in table.keys() {
let reflectable = &*(*obj as *const Reflector);
trace_reflector(tracer, "refcounted", reflectable);
diff --git a/components/script/dom/bindings/reflector.rs b/components/script/dom/bindings/reflector.rs
index 04466ea6926..d5280712a03 100644
--- a/components/script/dom/bindings/reflector.rs
+++ b/components/script/dom/bindings/reflector.rs
@@ -73,11 +73,15 @@ impl Reflector {
pub trait Reflectable {
/// Returns the receiver's reflector.
fn reflector(&self) -> &Reflector;
- /// Initializes the Reflector
- fn init_reflector(&mut self, obj: *mut JSObject);
/// Returns the global object of the realm that the Reflectable was created in.
fn global(&self) -> GlobalRoot where Self: Sized {
global_root_from_reflector(self)
}
}
+
+/// A trait to initialize the `Reflector` for a DOM object.
+pub trait MutReflectable: Reflectable {
+ /// Initializes the Reflector
+ fn init_reflector(&mut self, obj: *mut JSObject);
+}
diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs
index c73a08d182b..2e28a1b314e 100644
--- a/components/script/dom/bindings/str.rs
+++ b/components/script/dom/bindings/str.rs
@@ -5,7 +5,7 @@
//! The `ByteString` struct.
use std::ascii::AsciiExt;
-use std::borrow::{ToOwned, Cow};
+use std::borrow::{Borrow, Cow, ToOwned};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops;
@@ -180,6 +180,13 @@ impl DOMString {
}
}
+impl Borrow<str> for DOMString {
+ #[inline]
+ fn borrow(&self) -> &str {
+ &self.0
+ }
+}
+
impl Default for DOMString {
fn default() -> Self {
DOMString(String::new())
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index d6969f38d6c..fae24096bac 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -50,20 +50,22 @@ use html5ever::tree_builder::QuirksMode;
use hyper::header::Headers;
use hyper::method::Method;
use hyper::mime::Mime;
+use hyper::status::StatusCode;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use js::glue::{CallObjectTracer, CallUnbarrieredObjectTracer, CallValueTracer};
-use js::jsapi::{GCTraceKindToAscii, Heap, TraceKind, JSObject, JSTracer};
+use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSTracer, TraceKind};
use js::jsval::JSVal;
use js::rust::Runtime;
use libc;
-use msg::constellation_msg::{FrameType, PipelineId, SubpageId, WindowSizeType, ReferrerPolicy};
+use msg::constellation_msg::{FrameType, PipelineId, ReferrerPolicy, SubpageId, WindowSizeType};
+use net_traits::{Metadata, NetworkError, ResourceThreads};
use net_traits::filemanager_thread::RelativePos;
use net_traits::image::base::{Image, ImageMetadata};
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
use net_traits::request::Request;
+use net_traits::response::{Response, ResponseBody};
use net_traits::response::HttpsState;
use net_traits::storage_thread::StorageType;
-use net_traits::{Metadata, NetworkError, ResourceThreads};
use offscreen_gl_context::GLLimits;
use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan;
@@ -85,12 +87,13 @@ use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::mpsc::{Receiver, Sender};
-use std::time::SystemTime;
+use std::time::{SystemTime, Instant};
use string_cache::{Atom, Namespace, QualName};
use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
+use style::domrefcell::DOMRefCell;
use style::element_state::*;
use style::properties::PropertyDeclarationBlock;
-use style::selector_impl::{PseudoElement, ElementSnapshot};
+use style::selector_impl::{ElementSnapshot, PseudoElement};
use style::values::specified::Length;
use time::Duration;
use url::Origin as UrlOrigin;
@@ -172,6 +175,13 @@ impl<T: JSTraceable> JSTraceable for UnsafeCell<T> {
}
}
+impl<T: JSTraceable> JSTraceable for DOMRefCell<T> {
+ fn trace(&self, trc: *mut JSTracer) {
+ unsafe {
+ (*self).borrow_for_gc_trace().trace(trc)
+ }
+ }
+}
impl JSTraceable for Heap<*mut JSObject> {
fn trace(&self, trc: *mut JSTracer) {
@@ -331,8 +341,12 @@ no_jsmanaged_fields!(SharedRt);
no_jsmanaged_fields!(TouchpadPressurePhase);
no_jsmanaged_fields!(USVString);
no_jsmanaged_fields!(ReferrerPolicy);
+no_jsmanaged_fields!(Response);
+no_jsmanaged_fields!(ResponseBody);
no_jsmanaged_fields!(ResourceThreads);
+no_jsmanaged_fields!(StatusCode);
no_jsmanaged_fields!(SystemTime);
+no_jsmanaged_fields!(Instant);
no_jsmanaged_fields!(RelativePos);
no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
no_jsmanaged_fields!(PathBuf);
diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs
index 6b2856e7a9e..32ffe4109ae 100644
--- a/components/script/dom/bindings/utils.rs
+++ b/components/script/dom/bindings/utils.rs
@@ -7,8 +7,7 @@
use dom::bindings::codegen::InterfaceObjectMap;
use dom::bindings::codegen::PrototypeList;
use dom::bindings::codegen::PrototypeList::{MAX_PROTO_CHAIN_LENGTH, PROTO_OR_IFACE_LENGTH};
-use dom::bindings::conversions::{DOM_OBJECT_SLOT, is_dom_class};
-use dom::bindings::conversions::{jsstring_to_str, private_from_proto_check};
+use dom::bindings::conversions::{is_dom_class, jsstring_to_str, private_from_proto_check};
use dom::bindings::error::throw_invalid_this;
use dom::bindings::inheritance::TopTypeId;
use dom::bindings::str::DOMString;
@@ -21,20 +20,18 @@ use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
use js::glue::{GetCrossCompartmentWrapper, WrapperNew};
use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT, RUST_JSID_IS_STRING};
use js::glue::{RUST_JSID_TO_INT, RUST_JSID_TO_STRING, UnwrapObject};
-use js::jsapi::{CallArgs, CompartmentOptions, DOMCallbacks, GetGlobalForObjectCrossCompartment};
-use js::jsapi::{HandleId, HandleObject, HandleValue, Heap, JSAutoCompartment, JSClass, JSContext};
-use js::jsapi::{JSJitInfo, JSObject, JSTraceOp, JSTracer, JSVersion, JSWrapObjectCallbacks};
-use js::jsapi::{JS_DeletePropertyById, JS_EnumerateStandardClasses, JS_FireOnNewGlobalObject};
+use js::jsapi::{CallArgs, DOMCallbacks, GetGlobalForObjectCrossCompartment};
+use js::jsapi::{HandleId, HandleObject, HandleValue, Heap, JSAutoCompartment, JSContext};
+use js::jsapi::{JSJitInfo, JSObject, JSTracer, JSWrapObjectCallbacks};
+use js::jsapi::{JS_DeletePropertyById, JS_EnumerateStandardClasses};
use js::jsapi::{JS_ForwardGetPropertyTo, JS_GetClass, JS_GetLatin1StringCharsAndLength};
use js::jsapi::{JS_GetProperty, JS_GetPrototype, JS_GetReservedSlot, JS_HasProperty};
-use js::jsapi::{JS_HasPropertyById, JS_IsExceptionPending, JS_IsGlobalObject, JS_NewGlobalObject};
+use js::jsapi::{JS_HasPropertyById, JS_IsExceptionPending, JS_IsGlobalObject};
use js::jsapi::{JS_ResolveStandardClass, JS_SetProperty, ToWindowProxyIfWindow};
-use js::jsapi::{JS_SetReservedSlot, JS_StringHasLatin1Chars, MutableHandleValue};
-use js::jsapi::{ObjectOpResult, OnNewGlobalHookOption};
-use js::jsval::{JSVal, ObjectValue, PrivateValue, UndefinedValue};
+use js::jsapi::{JS_StringHasLatin1Chars, MutableHandleValue, ObjectOpResult};
+use js::jsval::{JSVal, UndefinedValue};
use js::rust::{GCMethods, ToString};
use libc;
-use std::default::Default;
use std::ffi::CString;
use std::os::raw::c_void;
use std::ptr;
@@ -103,7 +100,7 @@ unsafe impl Sync for DOMClass {}
#[derive(Copy)]
pub struct DOMJSClass {
/// The actual JSClass.
- pub base: js::jsapi::Class,
+ pub base: js::jsapi::JSClass,
/// Associated data for DOM object reflectors.
pub dom_class: DOMClass,
}
@@ -130,32 +127,29 @@ pub type ProtoOrIfaceArray = [*mut JSObject; PROTO_OR_IFACE_LENGTH];
/// set to true and `*vp` to the value, otherwise `*found` is set to false.
///
/// Returns false on JSAPI failure.
-pub fn get_property_on_prototype(cx: *mut JSContext,
- proxy: HandleObject,
- id: HandleId,
- found: *mut bool,
- vp: MutableHandleValue)
- -> bool {
- unsafe {
- // let proto = GetObjectProto(proxy);
- rooted!(in(cx) let mut proto = ptr::null_mut());
- if !JS_GetPrototype(cx, proxy, proto.handle_mut()) || proto.is_null() {
- *found = false;
- return true;
- }
- let mut has_property = false;
- if !JS_HasPropertyById(cx, proto.handle(), id, &mut has_property) {
- return false;
- }
- *found = has_property;
- let no_output = vp.ptr.is_null();
- if !has_property || no_output {
- return true;
- }
-
- rooted!(in(cx) let receiver = ObjectValue(&*proxy.get()));
- JS_ForwardGetPropertyTo(cx, proto.handle(), id, receiver.handle(), vp)
+pub unsafe fn get_property_on_prototype(cx: *mut JSContext,
+ proxy: HandleObject,
+ receiver: HandleValue,
+ id: HandleId,
+ found: *mut bool,
+ vp: MutableHandleValue)
+ -> bool {
+ rooted!(in(cx) let mut proto = ptr::null_mut());
+ if !JS_GetPrototype(cx, proxy, proto.handle_mut()) || proto.is_null() {
+ *found = false;
+ return true;
+ }
+ let mut has_property = false;
+ if !JS_HasPropertyById(cx, proto.handle(), id, &mut has_property) {
+ return false;
}
+ *found = has_property;
+ let no_output = vp.ptr.is_null();
+ if !has_property || no_output {
+ return true;
+ }
+
+ JS_ForwardGetPropertyTo(cx, proto.handle(), id, receiver, vp)
}
/// Get an array index from the given `jsid`. Returns `None` if the given
@@ -288,49 +282,17 @@ pub fn set_dictionary_property(cx: *mut JSContext,
}
/// Returns whether `proxy` has a property `id` on its prototype.
-pub fn has_property_on_prototype(cx: *mut JSContext, proxy: HandleObject, id: HandleId) -> bool {
- // MOZ_ASSERT(js::IsProxy(proxy) && js::GetProxyHandler(proxy) == handler);
- let mut found = false;
- !get_property_on_prototype(cx, proxy, id, &mut found, unsafe {
- MutableHandleValue::from_marked_location(ptr::null_mut())
- }) || found
-}
-
-/// Create a DOM global object with the given class.
-pub fn create_dom_global(cx: *mut JSContext,
- class: *const JSClass,
- private: *const libc::c_void,
- trace: JSTraceOp)
- -> *mut JSObject {
- unsafe {
- let mut options = CompartmentOptions::default();
- options.behaviors_.version_ = JSVersion::JSVERSION_ECMA_5;
- options.creationOptions_.traceGlobal_ = trace;
- options.creationOptions_.sharedMemoryAndAtomics_ = true;
-
- rooted!(in(cx) let obj =
- JS_NewGlobalObject(cx,
- class,
- ptr::null_mut(),
- OnNewGlobalHookOption::DontFireOnNewGlobalHook,
- &options));
- if obj.is_null() {
- return ptr::null_mut();
- }
-
- // Initialize the reserved slots before doing amything that can GC, to
- // avoid getting trace hooks called on a partially initialized object.
- JS_SetReservedSlot(obj.get(), DOM_OBJECT_SLOT, PrivateValue(private));
- let proto_array: Box<ProtoOrIfaceArray> =
- box [0 as *mut JSObject; PROTO_OR_IFACE_LENGTH];
- JS_SetReservedSlot(obj.get(),
- DOM_PROTOTYPE_SLOT,
- PrivateValue(Box::into_raw(proto_array) as *const libc::c_void));
-
- let _ac = JSAutoCompartment::new(cx, obj.get());
- JS_FireOnNewGlobalObject(cx, obj.handle());
- obj.get()
+pub unsafe fn has_property_on_prototype(cx: *mut JSContext,
+ proxy: HandleObject,
+ id: HandleId,
+ found: &mut bool)
+ -> bool {
+ rooted!(in(cx) let mut proto = ptr::null_mut());
+ if !JS_GetPrototype(cx, proxy, proto.handle_mut()) {
+ return false;
}
+ assert!(!proto.is_null());
+ JS_HasPropertyById(cx, proto.handle(), id, found)
}
/// Drop the resources held by reserved slots of a global object
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs
index 0e513081e10..78990f40564 100644
--- a/components/script/dom/blob.rs
+++ b/components/script/dom/blob.rs
@@ -14,9 +14,9 @@ use dom::bindings::str::DOMString;
use encoding::all::UTF_8;
use encoding::types::{EncoderTrap, Encoding};
use ipc_channel::ipc;
-use net_traits::blob_url_store::{BlobBuf, get_blob_origin};
-use net_traits::filemanager_thread::{FileManagerThreadMsg, RelativePos, ReadFileProgress};
use net_traits::{CoreResourceMsg, IpcSend};
+use net_traits::blob_url_store::{BlobBuf, get_blob_origin};
+use net_traits::filemanager_thread::{FileManagerThreadMsg, ReadFileProgress, RelativePos};
use std::cell::Cell;
use std::mem;
use std::ops::Index;
diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs
index c86fa0150a3..6540f6c971f 100644
--- a/components/script/dom/bluetooth.rs
+++ b/components/script/dom/bluetooth.rs
@@ -5,8 +5,8 @@
use bluetooth_blacklist::{Blacklist, uuid_is_blacklisted};
use core::clone::Clone;
use dom::bindings::codegen::Bindings::BluetoothBinding;
+use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothMethods, BluetoothScanFilter};
use dom::bindings::codegen::Bindings::BluetoothBinding::RequestDeviceOptions;
-use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothScanFilter, BluetoothMethods};
use dom::bindings::error::Error::{self, Security, Type};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs
index 0c27097625c..c88463920e6 100644
--- a/components/script/dom/bluetoothremotegattcharacteristic.rs
+++ b/components/script/dom/bluetoothremotegattcharacteristic.rs
@@ -12,8 +12,8 @@ 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::{ErrorResult, Fallible};
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};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs
index 0ba52181b48..a726de42974 100644
--- a/components/script/dom/bluetoothremotegattdescriptor.rs
+++ b/components/script/dom/bluetoothremotegattdescriptor.rs
@@ -11,8 +11,8 @@ 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::{ErrorResult, Fallible};
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};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs
index f4b1e532f10..615094623e9 100644
--- a/components/script/dom/bluetoothremotegattserver.rs
+++ b/components/script/dom/bluetoothremotegattserver.rs
@@ -6,8 +6,8 @@ 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::{ErrorResult, Fallible};
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};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
diff --git a/components/script/dom/browsingcontext.rs b/components/script/dom/browsingcontext.rs
index 878d376ca66..919b574c27a 100644
--- a/components/script/dom/browsingcontext.rs
+++ b/components/script/dom/browsingcontext.rs
@@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::conversions::{ToJSValConvertible, root_from_handleobject};
use dom::bindings::js::{JS, Root, RootedReference};
use dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor};
-use dom::bindings::reflector::{Reflectable, Reflector};
+use dom::bindings::reflector::{Reflectable, MutReflectable, Reflector};
use dom::bindings::str::DOMString;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::WindowProxyHandler;
@@ -18,11 +18,13 @@ use dom::window::Window;
use js::JSCLASS_IS_GLOBAL;
use js::glue::{CreateWrapperProxyHandler, ProxyTraps, NewWindowProxy};
use js::glue::{GetProxyPrivate, SetProxyExtra, GetProxyExtra};
-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::{MutableHandleObject, MutableHandleValue, ObjectOpResult};
+use js::jsapi::{Handle, HandleId, HandleObject, HandleValue};
+use js::jsapi::{JSAutoCompartment, JSContext, JSErrNum, JSFreeOp, JSObject};
+use js::jsapi::{JSPROP_READONLY, JSTracer, JS_DefinePropertyById};
+use js::jsapi::{JS_ForwardGetPropertyTo, JS_ForwardSetPropertyTo, JS_GetClass};
+use js::jsapi::{JS_GetOwnPropertyDescriptorById, JS_HasPropertyById};
+use js::jsapi::{MutableHandle, MutableHandleObject, MutableHandleValue};
+use js::jsapi::{ObjectOpResult, PropertyDescriptor};
use js::jsval::{UndefinedValue, PrivateValue};
use msg::constellation_msg::{PipelineId, SubpageId};
use std::cell::Cell;
@@ -409,7 +411,7 @@ static PROXY_HANDLER: ProxyTraps = ProxyTraps {
};
#[allow(unsafe_code)]
-unsafe extern fn finalize(_fop: *mut FreeOp, obj: *mut JSObject) {
+unsafe extern fn finalize(_fop: *mut JSFreeOp, obj: *mut JSObject) {
let this = GetProxyExtra(obj, 0).to_private() as *mut BrowsingContext;
assert!(!this.is_null());
let _ = Box::from_raw(this);
diff --git a/components/script/dom/canvasgradient.rs b/components/script/dom/canvasgradient.rs
index f47589b60af..a805b485796 100644
--- a/components/script/dom/canvasgradient.rs
+++ b/components/script/dom/canvasgradient.rs
@@ -3,8 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use canvas_traits::{CanvasGradientStop, FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle};
-use cssparser::Color as CSSColor;
use cssparser::{Parser, RGBA};
+use cssparser::Color as CSSColor;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CanvasGradientBinding;
use dom::bindings::codegen::Bindings::CanvasGradientBinding::CanvasGradientMethods;
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs
index 09d4a8f04e1..13610c53487 100644
--- a/components/script/dom/canvasrenderingcontext2d.rs
+++ b/components/script/dom/canvasrenderingcontext2d.rs
@@ -5,9 +5,9 @@
use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg};
use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle};
-use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap};
-use cssparser::Color as CSSColor;
+use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap, byte_swap_and_premultiply};
use cssparser::{Parser, RGBA};
+use cssparser::Color as CSSColor;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding;
@@ -19,7 +19,7 @@ use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::UnionTypes::HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D;
use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern;
-use dom::bindings::error::{Error, Fallible, ErrorResult};
+use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, LayoutJS, Root};
@@ -42,11 +42,12 @@ use net_traits::image::base::PixelFormat;
use net_traits::image_cache_thread::ImageResponse;
use num_traits::ToPrimitive;
use script_traits::ScriptMsg as ConstellationMsg;
+use std::{cmp, fmt};
use std::cell::Cell;
use std::str::FromStr;
-use std::{cmp, fmt};
use unpremultiplytable::UNPREMULTIPLY_TABLE;
use url::Url;
+use util::opts;
#[must_root]
#[derive(JSTraceable, Clone, HeapSizeOf)]
@@ -299,7 +300,14 @@ impl CanvasRenderingContext2D {
Some((mut data, size)) => {
// Pixels come from cache in BGRA order and drawImage expects RGBA so we
// have to swap the color values
- byte_swap(&mut data);
+ if opts::get().use_webrender {
+ // Webrender doesn't pre-multiply alpha when decoding
+ // images, but canvas expects the images to be
+ // pre-multiplied alpha.
+ byte_swap_and_premultiply(&mut data);
+ } else {
+ byte_swap(&mut data);
+ }
let size = Size2D::new(size.width as f64, size.height as f64);
(data, size)
},
@@ -1092,7 +1100,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
dirtyY: Finite<f64>,
dirtyWidth: Finite<f64>,
dirtyHeight: Finite<f64>) {
- let data = imagedata.get_data_array(&self.global().r());
+ let data = imagedata.get_data_array();
let offset = Point2D::new(*dx, *dy);
let image_data_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64);
diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs
index 01f11e3ac50..979e9a70434 100644
--- a/components/script/dom/characterdata.rs
+++ b/components/script/dom/characterdata.rs
@@ -19,7 +19,7 @@ use dom::element::Element;
use dom::node::{Node, NodeDamage};
use dom::processinginstruction::ProcessingInstruction;
use dom::text::Text;
-use std::cell::Ref;
+use style::refcell::Ref;
use util::opts;
// https://dom.spec.whatwg.org/#characterdata
diff --git a/components/script/dom/client.rs b/components/script/dom/client.rs
index 1039ff1a04a..d800d6f55e0 100644
--- a/components/script/dom/client.rs
+++ b/components/script/dom/client.rs
@@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use dom::bindings::codegen::Bindings::ClientBinding::FrameType;
use dom::bindings::codegen::Bindings::ClientBinding::{ClientMethods, Wrap};
+use dom::bindings::codegen::Bindings::ClientBinding::FrameType;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::JS;
use dom::bindings::js::Root;
diff --git a/components/script/dom/console.rs b/components/script/dom/console.rs
index 9382bf936a8..37d549befd9 100644
--- a/components/script/dom/console.rs
+++ b/components/script/dom/console.rs
@@ -4,39 +4,17 @@
use devtools_traits::{ConsoleMessage, LogLevel, ScriptToDevtoolsControlMsg};
use dom::bindings::cell::DOMRefCell;
-use dom::bindings::codegen::Bindings::ConsoleBinding;
-use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
use dom::bindings::global::GlobalRef;
-use dom::bindings::js::Root;
-use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
use std::collections::HashMap;
+use std::collections::hash_map::Entry;
use time::{Timespec, get_time};
// https://developer.mozilla.org/en-US/docs/Web/API/Console
-#[dom_struct]
-pub struct Console {
- reflector_: Reflector,
- timers: DOMRefCell<HashMap<DOMString, u64>>,
-}
+pub struct Console(());
impl Console {
- fn new_inherited() -> Console {
- Console {
- reflector_: Reflector::new(),
- timers: DOMRefCell::new(HashMap::new()),
- }
- }
-
- pub fn new(global: GlobalRef) -> Root<Console> {
- reflect_dom_object(box Console::new_inherited(),
- global,
- ConsoleBinding::Wrap)
- }
-
- fn send_to_devtools(&self, level: LogLevel, message: DOMString) {
- let global = self.global();
- let global = global.r();
+ fn send_to_devtools(global: GlobalRef, level: LogLevel, message: DOMString) {
if let Some(chan) = global.devtools_chan() {
let console_message = prepare_message(level, message);
let devtools_message = ScriptToDevtoolsControlMsg::ConsoleAPI(
@@ -48,83 +26,73 @@ impl Console {
}
}
-impl ConsoleMethods for Console {
+impl Console {
// https://developer.mozilla.org/en-US/docs/Web/API/Console/log
- fn Log(&self, messages: Vec<DOMString>) {
+ pub fn Log(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
- self.send_to_devtools(LogLevel::Log, message);
+ Self::send_to_devtools(global, LogLevel::Log, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console
- fn Debug(&self, messages: Vec<DOMString>) {
+ pub fn Debug(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
- self.send_to_devtools(LogLevel::Debug, message);
+ Self::send_to_devtools(global, LogLevel::Debug, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/info
- fn Info(&self, messages: Vec<DOMString>) {
+ pub fn Info(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
- self.send_to_devtools(LogLevel::Info, message);
+ Self::send_to_devtools(global, LogLevel::Info, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/warn
- fn Warn(&self, messages: Vec<DOMString>) {
+ pub fn Warn(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
- self.send_to_devtools(LogLevel::Warn, message);
+ Self::send_to_devtools(global, LogLevel::Warn, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/error
- fn Error(&self, messages: Vec<DOMString>) {
+ pub fn Error(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
- self.send_to_devtools(LogLevel::Error, message);
+ Self::send_to_devtools(global, LogLevel::Error, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/assert
- fn Assert(&self, condition: bool, message: Option<DOMString>) {
+ pub fn Assert(global: GlobalRef, condition: bool, message: Option<DOMString>) {
if !condition {
let message = message.unwrap_or_else(|| DOMString::from("no message"));
println!("Assertion failed: {}", message);
- self.send_to_devtools(LogLevel::Error, message);
+ Self::send_to_devtools(global, LogLevel::Error, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/time
- fn Time(&self, label: DOMString) {
- let mut timers = self.timers.borrow_mut();
- if timers.contains_key(&label) {
- // Timer already started
- return;
- }
- if timers.len() >= 10000 {
- // Too many timers on page
- return;
+ pub fn Time(global: GlobalRef, label: DOMString) {
+ if let Ok(()) = global.console_timers().time(label.clone()) {
+ let message = DOMString::from(format!("{}: timer started", label));
+ println!("{}", message);
+ Self::send_to_devtools(global, LogLevel::Log, message);
}
-
- timers.insert(label.clone(), timestamp_in_ms(get_time()));
- let message = DOMString::from(format!("{}: timer started", label));
- println!("{}", message);
- self.send_to_devtools(LogLevel::Log, message);
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd
- fn TimeEnd(&self, label: DOMString) {
- let mut timers = self.timers.borrow_mut();
- if let Some(start) = timers.remove(&label) {
+ pub fn TimeEnd(global: GlobalRef, label: DOMString) {
+ if let Ok(delta) = global.console_timers().time_end(&label) {
let message = DOMString::from(
- format!("{}: {}ms", label, timestamp_in_ms(get_time()) - start)
+ format!("{}: {}ms", label, delta)
);
println!("{}", message);
- self.send_to_devtools(LogLevel::Log, message);
+ Self::send_to_devtools(global, LogLevel::Log, message);
};
}
}
@@ -143,3 +111,32 @@ fn prepare_message(logLevel: LogLevel, message: DOMString) -> ConsoleMessage {
columnNumber: 1,
}
}
+
+#[derive(HeapSizeOf, JSTraceable)]
+pub struct TimerSet(DOMRefCell<HashMap<DOMString, u64>>);
+
+impl TimerSet {
+ pub fn new() -> Self {
+ TimerSet(DOMRefCell::new(Default::default()))
+ }
+
+ fn time(&self, label: DOMString) -> Result<(), ()> {
+ let mut timers = self.0.borrow_mut();
+ if timers.len() >= 10000 {
+ return Err(());
+ }
+ match timers.entry(label) {
+ Entry::Vacant(entry) => {
+ entry.insert(timestamp_in_ms(get_time()));
+ Ok(())
+ },
+ Entry::Occupied(_) => Err(()),
+ }
+ }
+
+ fn time_end(&self, label: &str) -> Result<u64, ()> {
+ self.0.borrow_mut().remove(label).ok_or(()).map(|start| {
+ timestamp_in_ms(get_time()) - start
+ })
+ }
+}
diff --git a/components/script/dom/crypto.rs b/components/script/dom/crypto.rs
index 6e0351d37ee..165a3834227 100644
--- a/components/script/dom/crypto.rs
+++ b/components/script/dom/crypto.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use core::nonzero::NonZero;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CryptoBinding;
use dom::bindings::codegen::Bindings::CryptoBinding::CryptoMethods;
@@ -43,7 +44,8 @@ impl CryptoMethods for Crypto {
fn GetRandomValues(&self,
_cx: *mut JSContext,
input: *mut JSObject)
- -> Fallible<*mut JSObject> {
+ -> Fallible<NonZero<*mut JSObject>> {
+ assert!(!input.is_null());
let mut data = match unsafe { array_buffer_view_data::<u8>(input) } {
Some(data) => data,
None => {
@@ -62,7 +64,7 @@ impl CryptoMethods for Crypto {
self.rng.borrow_mut().fill_bytes(&mut data);
- Ok(input)
+ Ok(unsafe { NonZero::new(input) })
}
}
diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs
index 076a2283b67..c048446d813 100644
--- a/components/script/dom/cssstyledeclaration.rs
+++ b/components/script/dom/cssstyledeclaration.rs
@@ -14,12 +14,13 @@ use dom::element::Element;
use dom::node::{Node, NodeDamage, window_from_node};
use dom::window::Window;
use std::ascii::AsciiExt;
-use std::cell::Ref;
use std::slice;
+use std::sync::Arc;
use string_cache::Atom;
use style::parser::ParserContextExtraData;
use style::properties::{PropertyDeclaration, Shorthand, Importance};
use style::properties::{is_supported_property, parse_one_declaration, parse_style_attribute};
+use style::refcell::Ref;
use style::selector_impl::PseudoElement;
// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
@@ -100,18 +101,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item
fn Item(&self, index: u32) -> DOMString {
- let index = index as usize;
- let elem = self.owner.upcast::<Element>();
- let style_attribute = elem.style_attribute().borrow();
- style_attribute.as_ref().and_then(|declarations| {
- declarations.declarations.get(index)
- }).map(|&(ref declaration, importance)| {
- let mut css = declaration.to_css_string();
- if importance.important() {
- css += " !important";
- }
- DOMString::from(css)
- }).unwrap_or_else(DOMString::new)
+ self.IndexedGetter(index).unwrap_or_default()
}
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
@@ -333,10 +323,19 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
}
// https://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> DOMString {
- let rval = self.Item(index);
- *found = index < self.Length();
- rval
+ fn IndexedGetter(&self, index: u32) -> Option<DOMString> {
+ let index = index as usize;
+ let elem = self.owner.upcast::<Element>();
+ let style_attribute = elem.style_attribute().borrow();
+ style_attribute.as_ref().and_then(|declarations| {
+ declarations.declarations.get(index)
+ }).map(|&(ref declaration, importance)| {
+ let mut css = declaration.to_css_string();
+ if importance.important() {
+ css += " !important";
+ }
+ DOMString::from(css)
+ })
}
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext
@@ -367,7 +366,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
*element.style_attribute().borrow_mut() = if decl_block.declarations.is_empty() {
None // Step 2
} else {
- Some(decl_block)
+ Some(Arc::new(decl_block))
};
element.sync_property_with_attrs_style();
let node = element.upcast::<Node>();
diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs
index 68899bd36b8..4f0bad72949 100644
--- a/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/components/script/dom/dedicatedworkerglobalscope.rs
@@ -4,22 +4,24 @@
use devtools;
use devtools_traits::DevtoolScriptControlMsg;
-use dom::abstractworker::{WorkerScriptMsg, SharedRt , SimpleWorkerErrorHandler};
+use dom::abstractworker::{SharedRt, SimpleWorkerErrorHandler, WorkerScriptMsg};
use dom::abstractworkerglobalscope::{SendableWorkerScriptChan, WorkerThreadWorkerChan};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding::DedicatedWorkerGlobalScopeMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
-use dom::bindings::error::ErrorResult;
+use dom::bindings::error::{ErrorInfo, ErrorResult};
use dom::bindings::global::{GlobalRef, global_root_from_context};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root, RootCollection};
-use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
use dom::bindings::structuredclone::StructuredCloneData;
+use dom::errorevent::ErrorEvent;
+use dom::event::{Event, EventBubbles, EventCancelable};
+use dom::eventtarget::EventTarget;
use dom::messageevent::MessageEvent;
-use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler};
+use dom::worker::{TrustedWorkerAddress, WorkerErrorHandler, WorkerMessageHandler};
use dom::workerglobalscope::WorkerGlobalScope;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
@@ -28,15 +30,16 @@ use js::jsapi::{JSAutoCompartment, JSContext};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::PipelineId;
-use net_traits::{LoadContext, load_whole_resource, IpcSend};
+use net_traits::{IpcSend, LoadContext, load_whole_resource};
use rand::random;
-use script_runtime::ScriptThreadEventCategory::WorkerEvent;
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
-use script_traits::{TimerEvent, TimerSource, WorkerScriptLoadOrigin, WorkerGlobalScopeInit};
+use script_runtime::ScriptThreadEventCategory::WorkerEvent;
+use script_traits::{TimerEvent, TimerSource, WorkerGlobalScopeInit, WorkerScriptLoadOrigin};
+use std::cell::Cell;
use std::mem::replace;
+use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicBool;
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
-use std::sync::{Arc, Mutex};
use style::thread_state;
use url::Url;
use util::thread::spawn_named;
@@ -89,6 +92,8 @@ pub struct DedicatedWorkerGlobalScope {
#[ignore_heap_size_of = "Can't measure trait objects"]
/// Sender to the parent thread.
parent_sender: Box<ScriptChan + Send>,
+ /// https://html.spec.whatwg.org/multipage/#in-error-reporting-mode
+ in_error_reporting_mode: Cell<bool>
}
impl DedicatedWorkerGlobalScope {
@@ -117,6 +122,7 @@ impl DedicatedWorkerGlobalScope {
timer_event_port: timer_event_port,
parent_sender: parent_sender,
worker: DOMRefCell::new(None),
+ in_error_reporting_mode: Cell::new(false),
}
}
@@ -298,9 +304,6 @@ impl DedicatedWorkerGlobalScope {
WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => {
runnable.handler()
},
- WorkerScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) => {
- LiveDOMReferences::cleanup(addr);
- },
WorkerScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) => {
let scope = self.upcast::<WorkerGlobalScope>();
let cx = scope.get_cx();
@@ -343,6 +346,42 @@ impl DedicatedWorkerGlobalScope {
}
}
}
+
+ /// https://html.spec.whatwg.org/multipage/#report-the-error
+ pub fn report_an_error(&self, error_info: ErrorInfo, value: HandleValue) {
+ // Step 1.
+ if self.in_error_reporting_mode.get() {
+ return;
+ }
+
+ // Step 2.
+ self.in_error_reporting_mode.set(true);
+
+ // Steps 3-12.
+ // FIXME(#13195): muted errors.
+ let event = ErrorEvent::new(GlobalRef::Worker(self.upcast()),
+ atom!("error"),
+ EventBubbles::DoesNotBubble,
+ EventCancelable::Cancelable,
+ error_info.message.as_str().into(),
+ error_info.filename.as_str().into(),
+ error_info.lineno,
+ error_info.column,
+ value);
+
+ // Step 13.
+ let handled = !event.upcast::<Event>().fire(self.upcast::<EventTarget>());
+ if !handled {
+ let worker = self.worker.borrow().as_ref().unwrap().clone();
+ // TODO: Should use the DOM manipulation task source.
+ self.parent_sender
+ .send(CommonScriptMsg::RunnableMsg(WorkerEvent,
+ box WorkerErrorHandler::new(worker, error_info)))
+ .unwrap();
+ }
+
+ self.in_error_reporting_mode.set(false);
+ }
}
#[allow(unsafe_code)]
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index cbd4b2ac253..fe55c035ff7 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use core::nonzero::NonZero;
use document_loader::{DocumentLoader, LoadType};
use dom::activation::{ActivationSource, synthetic_click_activation};
use dom::attr::Attr;
@@ -22,14 +23,14 @@ use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
-use dom::bindings::js::RootedReference;
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root};
+use dom::bindings::js::RootedReference;
use dom::bindings::num::Finite;
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::{DOMString, USVString};
+use dom::bindings::xmlname::{namespace_from_domstring, validate_and_extract, xml_name_type};
use dom::bindings::xmlname::XMLName::InvalidXMLName;
-use dom::bindings::xmlname::{validate_and_extract, namespace_from_domstring, xml_name_type};
use dom::browsingcontext::BrowsingContext;
use dom::closeevent::CloseEvent;
use dom::comment::Comment;
@@ -89,39 +90,40 @@ use encoding::all::UTF_8;
use euclid::point::Point2D;
use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks, QuirksMode};
use ipc_channel::ipc::{self, IpcSender};
-use js::jsapi::JS_GetRuntime;
use js::jsapi::{JSContext, JSObject, JSRuntime};
+use js::jsapi::JS_GetRuntime;
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
use msg::constellation_msg::{PipelineId, ReferrerPolicy, SubpageId};
+use net_traits::{AsyncResponseTarget, IpcSend, PendingAsyncLoad};
use net_traits::CookieSource::NonHTTP;
use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
use net_traits::response::HttpsState;
-use net_traits::{AsyncResponseTarget, PendingAsyncLoad, IpcSend};
use num_traits::ToPrimitive;
use origin::Origin;
-use parse::{ParserRoot, ParserRef, MutNullableParserField};
+use parse::{MutNullableParserField, ParserRef, ParserRoot};
use script_layout_interface::message::{Msg, ReflowQueryType};
use script_thread::{MainThreadScriptMsg, Runnable};
-use script_traits::UntrustedNodeAddress;
use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{ScriptMsg as ConstellationMsg, TouchpadPressurePhase};
use script_traits::{TouchEventType, TouchId};
+use script_traits::UntrustedNodeAddress;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::boxed::FnBox;
-use std::cell::{Cell, Ref, RefMut};
+use std::cell::Cell;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::default::Default;
use std::iter::once;
use std::mem;
-use std::ptr;
use std::rc::Rc;
use std::sync::Arc;
+use std::time::{Duration, Instant};
use string_cache::{Atom, QualName};
use style::attr::AttrValue;
use style::context::ReflowGoal;
+use style::refcell::{Ref, RefMut};
use style::selector_impl::ElementSnapshot;
use style::str::{split_html_space_chars, str_join};
use style::stylesheets::Stylesheet;
@@ -221,6 +223,9 @@ pub struct Document {
/// For each element that has had a state or attribute change since the last restyle,
/// track the original condition of the element.
modified_elements: DOMRefCell<HashMap<JS<Element>, ElementSnapshot>>,
+ /// This flag will be true if layout suppressed a reflow attempt that was
+ /// needed in order for the page to be painted.
+ needs_paint: Cell<bool>,
/// http://w3c.github.io/touch-events/#dfn-active-touch-point
active_touch_points: DOMRefCell<Vec<JS<Touch>>>,
/// Navigation Timing properties:
@@ -243,6 +248,9 @@ pub struct Document {
referrer: Option<String>,
/// https://html.spec.whatwg.org/multipage/#target-element
target_element: MutNullableHeap<JS<Element>>,
+ /// https://w3c.github.io/uievents/#event-type-dblclick
+ #[ignore_heap_size_of = "Defined in std"]
+ last_click_info: DOMRefCell<Option<(Instant, Point2D<f32>)>>,
}
#[derive(JSTraceable, HeapSizeOf)]
@@ -376,6 +384,10 @@ impl Document {
}
}
+ pub fn needs_paint(&self) -> bool {
+ self.needs_paint.get()
+ }
+
pub fn needs_reflow(&self) -> bool {
// FIXME: This should check the dirty bit on the document,
// not the document element. Needs some layout changes to make
@@ -384,7 +396,8 @@ impl Document {
Some(root) => {
root.upcast::<Node>().is_dirty() ||
root.upcast::<Node>().has_dirty_descendants() ||
- !self.modified_elements.borrow().is_empty()
+ !self.modified_elements.borrow().is_empty() ||
+ self.needs_paint()
}
None => false,
}
@@ -765,12 +778,64 @@ impl Document {
if let MouseEventType::Click = mouse_event_type {
self.commit_focus_transaction(FocusType::Element);
+ self.maybe_fire_dblclick(client_point, node);
}
+
self.window.reflow(ReflowGoal::ForDisplay,
ReflowQueryType::NoQuery,
ReflowReason::MouseEvent);
}
+ fn maybe_fire_dblclick(&self, click_pos: Point2D<f32>, target: &Node) {
+ // https://w3c.github.io/uievents/#event-type-dblclick
+ let now = Instant::now();
+
+ let opt = self.last_click_info.borrow_mut().take();
+
+ if let Some((last_time, last_pos)) = opt {
+ let DBL_CLICK_TIMEOUT = Duration::from_millis(PREFS.get("dom.document.dblclick_timeout").as_u64()
+ .unwrap_or(300));
+ let DBL_CLICK_DIST_THRESHOLD = PREFS.get("dom.document.dblclick_dist").as_u64().unwrap_or(1);
+
+ // Calculate distance between this click and the previous click.
+ let line = click_pos - last_pos;
+ let dist = (line.dot(line) as f64).sqrt();
+
+ if now.duration_since(last_time) < DBL_CLICK_TIMEOUT &&
+ dist < DBL_CLICK_DIST_THRESHOLD as f64 {
+ // A double click has occurred if this click is within a certain time and dist. of previous click.
+ let clickCount = 2;
+ let client_x = click_pos.x as i32;
+ let client_y = click_pos.y as i32;
+
+ let event = MouseEvent::new(&self.window,
+ DOMString::from("dblclick"),
+ EventBubbles::Bubbles,
+ EventCancelable::Cancelable,
+ Some(&self.window),
+ clickCount,
+ client_x,
+ client_y,
+ client_x,
+ client_y,
+ false,
+ false,
+ false,
+ false,
+ 0i16,
+ None);
+ event.upcast::<Event>().fire(target.upcast());
+
+ // When a double click occurs, self.last_click_info is left as None so that a
+ // third sequential click will not cause another double click.
+ return;
+ }
+ }
+
+ // Update last_click_info with the time and position of the click.
+ *self.last_click_info.borrow_mut() = Some((now, click_pos));
+ }
+
pub fn handle_touchpad_pressure_event(&self,
js_runtime: *mut JSRuntime,
client_point: Point2D<f32>,
@@ -1602,6 +1667,8 @@ pub enum DocumentSource {
pub trait LayoutDocumentHelpers {
unsafe fn is_html_document_for_layout(&self) -> bool;
unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementSnapshot)>;
+ unsafe fn needs_paint_from_layout(&self);
+ unsafe fn will_paint(&self);
}
#[allow(unsafe_code)]
@@ -1618,6 +1685,16 @@ impl LayoutDocumentHelpers for LayoutJS<Document> {
let result = elements.drain().map(|(k, v)| (k.to_layout(), v)).collect();
result
}
+
+ #[inline]
+ unsafe fn needs_paint_from_layout(&self) {
+ (*self.unsafe_get()).needs_paint.set(true)
+ }
+
+ #[inline]
+ unsafe fn will_paint(&self) {
+ (*self.unsafe_get()).needs_paint.set(false)
+ }
}
/// https://url.spec.whatwg.org/#network-scheme
@@ -1723,6 +1800,7 @@ impl Document {
base_element: Default::default(),
appropriate_template_contents_owner_document: Default::default(),
modified_elements: DOMRefCell::new(HashMap::new()),
+ needs_paint: Cell::new(false),
active_touch_points: DOMRefCell::new(Vec::new()),
dom_loading: Cell::new(Default::default()),
dom_interactive: Cell::new(Default::default()),
@@ -1737,6 +1815,7 @@ impl Document {
referrer: referrer,
referrer_policy: Cell::new(referrer_policy),
target_element: MutNullableHeap::new(None),
+ last_click_info: DOMRefCell::new(None),
}
}
@@ -2689,8 +2768,9 @@ impl DocumentMethods for Document {
self.set_body_attribute(&atom!("text"), value)
}
+ #[allow(unsafe_code)]
// https://html.spec.whatwg.org/multipage/#dom-tree-accessors:dom-document-nameditem-filter
- fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString, found: &mut bool) -> *mut JSObject {
+ fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString) -> Option<NonZero<*mut JSObject>> {
#[derive(JSTraceable, HeapSizeOf)]
struct NamedElementFilter {
name: Atom,
@@ -2756,23 +2836,24 @@ impl DocumentMethods for Document {
.peekable();
if let Some(first) = elements.next() {
if elements.peek().is_none() {
- *found = true;
// TODO: Step 2.
// Step 3.
- return first.reflector().get_jsobject().get();
+ return unsafe {
+ Some(NonZero::new(first.reflector().get_jsobject().get()))
+ };
}
} else {
- *found = false;
- return ptr::null_mut();
+ return None;
}
}
// Step 4.
- *found = true;
let filter = NamedElementFilter {
name: name,
};
let collection = HTMLCollection::create(self.window(), root, box filter);
- collection.reflector().get_jsobject().get()
+ unsafe {
+ Some(NonZero::new(collection.reflector().get_jsobject().get()))
+ }
}
// https://html.spec.whatwg.org/multipage/#dom-tree-accessors:supported-property-names
diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs
index 824cc0b88cf..dd55630204c 100644
--- a/components/script/dom/domimplementation.rs
+++ b/components/script/dom/domimplementation.rs
@@ -13,9 +13,9 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
-use dom::bindings::xmlname::{validate_qualified_name, namespace_from_domstring};
-use dom::document::DocumentSource;
+use dom::bindings::xmlname::{namespace_from_domstring, validate_qualified_name};
use dom::document::{Document, IsHTMLDocument};
+use dom::document::DocumentSource;
use dom::documenttype::DocumentType;
use dom::htmlbodyelement::HTMLBodyElement;
use dom::htmlheadelement::HTMLHeadElement;
diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs
index 3964c84abcb..a52f0b8b82f 100644
--- a/components/script/dom/domparser.rs
+++ b/components/script/dom/domparser.rs
@@ -16,8 +16,8 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
-use dom::document::DocumentSource;
use dom::document::{Document, IsHTMLDocument};
+use dom::document::DocumentSource;
use dom::window::Window;
use parse::html::{ParseContext, parse_html};
use parse::xml::{self, parse_xml};
diff --git a/components/script/dom/domrectlist.rs b/components/script/dom/domrectlist.rs
index adb246158f4..86774a49ff3 100644
--- a/components/script/dom/domrectlist.rs
+++ b/components/script/dom/domrectlist.rs
@@ -52,8 +52,7 @@ impl DOMRectListMethods for DOMRectList {
}
// check-tidy: no specs after this line
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<DOMRect>> {
- *found = index < self.rects.len() as u32;
+ fn IndexedGetter(&self, index: u32) -> Option<Root<DOMRect>> {
self.Item(index)
}
}
diff --git a/components/script/dom/domstringmap.rs b/components/script/dom/domstringmap.rs
index c5e534d242e..11479d6b5df 100644
--- a/components/script/dom/domstringmap.rs
+++ b/components/script/dom/domstringmap.rs
@@ -47,10 +47,8 @@ impl DOMStringMapMethods for DOMStringMap {
}
// https://html.spec.whatwg.org/multipage/#dom-domstringmap-nameditem
- fn NamedGetter(&self, name: DOMString, found: &mut bool) -> DOMString {
- let attr = self.element.get_custom_attr(name);
- *found = attr.is_some();
- attr.unwrap_or_default()
+ fn NamedGetter(&self, name: DOMString) -> Option<DOMString> {
+ self.element.get_custom_attr(name)
}
// https://html.spec.whatwg.org/multipage/#the-domstringmap-interface:supported-property-names
diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs
index 364b6366282..c1c09de94c2 100644
--- a/components/script/dom/domtokenlist.rs
+++ b/components/script/dom/domtokenlist.rs
@@ -171,9 +171,7 @@ impl DOMTokenListMethods for DOMTokenList {
}
// check-tidy: no specs after this line
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<DOMString> {
- let item = self.Item(index);
- *found = item.is_some();
- item
+ fn IndexedGetter(&self, index: u32) -> Option<DOMString> {
+ self.Item(index)
}
}
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 2d57ddab4d6..f85f608545f 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -17,8 +17,8 @@ use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
-use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
+use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
@@ -26,8 +26,8 @@ use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, Nod
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
use dom::bindings::js::{Root, RootedReference};
use dom::bindings::str::DOMString;
-use dom::bindings::xmlname::XMLName::InvalidXMLName;
use dom::bindings::xmlname::{namespace_from_domstring, validate_and_extract, xml_name_type};
+use dom::bindings::xmlname::XMLName::InvalidXMLName;
use dom::characterdata::CharacterData;
use dom::create::create_element;
use dom::document::{Document, LayoutDocumentHelpers};
@@ -70,13 +70,12 @@ use html5ever::serialize::SerializeOpts;
use html5ever::serialize::TraversalScope;
use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks};
-use ref_filter_map::ref_filter_map;
-use selectors::matching::{ElementFlags, matches};
-use selectors::matching::{HAS_SLOW_SELECTOR, HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
+use selectors::matching::{ElementFlags, MatchingReason, matches};
+use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
use selectors::parser::{AttrSelector, NamespaceConstraint, parse_author_origin_selector_list_from_str};
use std::ascii::AsciiExt;
use std::borrow::Cow;
-use std::cell::{Cell, Ref};
+use std::cell::Cell;
use std::convert::TryFrom;
use std::default::Default;
use std::fmt;
@@ -87,11 +86,12 @@ use style::attr::{AttrValue, LengthOrPercentageOrAuto};
use style::element_state::*;
use style::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
use style::parser::ParserContextExtraData;
-use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size};
use style::properties::{DeclaredValue, Importance};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
+use style::properties::longhands::{self, background_image, border_spacing, font_family, font_size, overflow_x};
+use style::refcell::Ref;
use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
-use style::selector_matching::DeclarationBlock;
+use style::selector_matching::ApplicableDeclarationBlock;
use style::sink::Push;
use style::values::CSSFloat;
use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage};
@@ -109,7 +109,7 @@ pub struct Element {
prefix: Option<DOMString>,
attrs: DOMRefCell<Vec<JS<Attr>>>,
id_attribute: DOMRefCell<Option<Atom>>,
- style_attribute: DOMRefCell<Option<PropertyDeclarationBlock>>,
+ style_attribute: DOMRefCell<Option<Arc<PropertyDeclarationBlock>>>,
attr_list: MutNullableHeap<JS<NamedNodeMap>>,
class_list: MutNullableHeap<JS<DOMTokenList>>,
state: Cell<ElementState>,
@@ -291,13 +291,13 @@ pub trait LayoutElementHelpers {
#[allow(unsafe_code)]
unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, &mut V)
- where V: Push<DeclarationBlock>;
+ where V: Push<ApplicableDeclarationBlock>;
#[allow(unsafe_code)]
unsafe fn get_colspan(self) -> u32;
#[allow(unsafe_code)]
unsafe fn html_element_in_html_document_for_layout(&self) -> bool;
fn id_attribute(&self) -> *const Option<Atom>;
- fn style_attribute(&self) -> *const Option<PropertyDeclarationBlock>;
+ fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>>;
fn local_name(&self) -> &Atom;
fn namespace(&self) -> &Namespace;
fn get_checked_state_for_layout(&self) -> bool;
@@ -324,12 +324,15 @@ impl LayoutElementHelpers for LayoutJS<Element> {
#[allow(unsafe_code)]
unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
- where V: Push<DeclarationBlock>
+ where V: Push<ApplicableDeclarationBlock>
{
#[inline]
- fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock {
- DeclarationBlock::from_declarations(
- Arc::new(vec![(rule, Importance::Normal)]),
+ fn from_declaration(rule: PropertyDeclaration) -> ApplicableDeclarationBlock {
+ ApplicableDeclarationBlock::from_declarations(
+ Arc::new(PropertyDeclarationBlock {
+ declarations: vec![(rule, Importance::Normal)],
+ important_count: 0,
+ }),
Importance::Normal)
}
@@ -615,7 +618,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
}
#[allow(unsafe_code)]
- fn style_attribute(&self) -> *const Option<PropertyDeclarationBlock> {
+ fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>> {
unsafe {
(*self.unsafe_get()).style_attribute.borrow_for_layout()
}
@@ -704,7 +707,7 @@ impl Element {
self.attrs.borrow()
}
- pub fn style_attribute(&self) -> &DOMRefCell<Option<PropertyDeclarationBlock>> {
+ pub fn style_attribute(&self) -> &DOMRefCell<Option<Arc<PropertyDeclarationBlock>>> {
&self.style_attribute
}
@@ -774,7 +777,8 @@ impl Element {
matching
});
if let Some(index) = index {
- Arc::make_mut(&mut declarations.declarations).remove(index);
+ let declarations = Arc::make_mut(declarations);
+ declarations.declarations.remove(index);
if importance.unwrap().important() {
declarations.important_count -= 1;
}
@@ -796,7 +800,8 @@ impl Element {
{
// Usually, the reference count will be 1 here. But transitions could make it greater
// than that.
- let existing_declarations = Arc::make_mut(&mut declaration_block.declarations);
+ let declaration_block = Arc::make_mut(declaration_block);
+ let existing_declarations = &mut declaration_block.declarations;
'outer: for incoming_declaration in declarations {
for existing_declaration in &mut *existing_declarations {
@@ -829,10 +834,10 @@ impl Element {
0
};
- *inline_declarations = Some(PropertyDeclarationBlock {
- declarations: Arc::new(declarations.into_iter().map(|d| (d, importance)).collect()),
+ *inline_declarations = Some(Arc::new(PropertyDeclarationBlock {
+ declarations: declarations.into_iter().map(|d| (d, importance)).collect(),
important_count: important_count,
- });
+ }));
}
update(self, declarations, importance);
@@ -847,7 +852,8 @@ impl Element {
if let &mut Some(ref mut block) = &mut *inline_declarations {
// Usually, the reference counts of `from` and `to` will be 1 here. But transitions
// could make them greater than that.
- let declarations = Arc::make_mut(&mut block.declarations);
+ let block = Arc::make_mut(block);
+ let declarations = &mut block.declarations;
for &mut (ref declaration, ref mut importance) in declarations {
if properties.iter().any(|p| declaration.name() == **p) {
match (*importance, new_importance) {
@@ -871,7 +877,7 @@ impl Element {
pub fn get_inline_style_declaration(&self,
property: &Atom)
-> Option<Ref<(PropertyDeclaration, Importance)>> {
- ref_filter_map(self.style_attribute.borrow(), |inline_declarations| {
+ Ref::filter_map(self.style_attribute.borrow(), |inline_declarations| {
inline_declarations.as_ref().and_then(|declarations| {
declarations.declarations
.iter()
@@ -2000,7 +2006,7 @@ impl ElementMethods for Element {
match parse_author_origin_selector_list_from_str(&selectors) {
Err(()) => Err(Error::Syntax),
Ok(ref selectors) => {
- Ok(matches(selectors, &Root::from_ref(self), None))
+ Ok(matches(selectors, &Root::from_ref(self), None, MatchingReason::Other))
}
}
}
@@ -2018,7 +2024,7 @@ impl ElementMethods for Element {
let root = self.upcast::<Node>();
for element in root.inclusive_ancestors() {
if let Some(element) = Root::downcast::<Element>(element) {
- if matches(selectors, &element, None) {
+ if matches(selectors, &element, None, MatchingReason::Other) {
return Ok(Some(element));
}
}
@@ -2102,8 +2108,11 @@ impl VirtualMethods for Element {
*self.style_attribute.borrow_mut() =
mutation.new_value(attr).map(|value| {
let win = window_from_node(self);
- parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter(),
- ParserContextExtraData::default())
+ Arc::new(parse_style_attribute(
+ &value,
+ &doc.base_url(),
+ win.css_error_reporter(),
+ ParserContextExtraData::default()))
});
if node.is_in_doc() {
node.dirty(NodeDamage::NodeStyleDamaged);
diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs
index da7664e0e19..07330a776ae 100644
--- a/components/script/dom/event.rs
+++ b/components/script/dom/event.rs
@@ -154,11 +154,6 @@ impl Event {
}
#[inline]
- pub fn clear_current_target(&self) {
- self.current_target.set(None);
- }
-
- #[inline]
pub fn set_current_target(&self, val: &EventTarget) {
self.current_target.set(Some(val));
}
@@ -199,8 +194,22 @@ impl Event {
}
#[inline]
- pub fn set_dispatching(&self, val: bool) {
- self.dispatching.set(val)
+ // https://dom.spec.whatwg.org/#concept-event-dispatch Step 1.
+ pub fn mark_as_dispatching(&self) {
+ assert!(!self.dispatching.get());
+ self.dispatching.set(true);
+ }
+
+ #[inline]
+ // https://dom.spec.whatwg.org/#concept-event-dispatch Steps 10-12.
+ pub fn clear_dispatching_flags(&self) {
+ assert!(self.dispatching.get());
+
+ self.dispatching.set(false);
+ self.stop_propagation.set(false);
+ self.stop_immediate.set(false);
+ self.set_phase(EventPhase::None);
+ self.current_target.set(None);
}
#[inline]
diff --git a/components/script/dom/eventdispatcher.rs b/components/script/dom/eventdispatcher.rs
index 7509df2ef13..01973e7c916 100644
--- a/components/script/dom/eventdispatcher.rs
+++ b/components/script/dom/eventdispatcher.rs
@@ -123,7 +123,7 @@ pub fn dispatch_event(target: &EventTarget,
}
// Step 1. Postponed here for the reason stated above.
- event.set_dispatching(true);
+ event.mark_as_dispatching();
// Step 3. The "invoke" algorithm is only used on `target` separately,
// so we don't put it in the path.
@@ -158,14 +158,8 @@ pub fn dispatch_event(target: &EventTarget,
None => {}
}
- // Step 10.
- event.set_dispatching(false);
-
- // Step 11.
- event.set_phase(EventPhase::None);
-
- // Step 12.
- event.clear_current_target();
+ // Step 10-12.
+ event.clear_dispatching_flags();
// Step 13.
!event.DefaultPrevented()
diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs
index 0175023deb1..c941eb8e20e 100644
--- a/components/script/dom/eventtarget.rs
+++ b/components/script/dom/eventtarget.rs
@@ -426,7 +426,9 @@ impl EventTarget {
if !rv || handler.get().is_null() {
// Step 1.8.2
unsafe {
- report_pending_exception(cx, self.reflector().get_jsobject().get());
+ let _ac = JSAutoCompartment::new(cx, self.reflector().get_jsobject().get());
+ // FIXME(#13152): dispatch error event.
+ report_pending_exception(cx, false);
}
// Step 1.8.1 / 1.8.3
return None;
diff --git a/components/script/dom/filelist.rs b/components/script/dom/filelist.rs
index 4f8e976f5f7..8adbe1ed467 100644
--- a/components/script/dom/filelist.rs
+++ b/components/script/dom/filelist.rs
@@ -55,9 +55,7 @@ impl FileListMethods for FileList {
}
// check-tidy: no specs after this line
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<File>> {
- let item = self.Item(index);
- *found = item.is_some();
- item
+ fn IndexedGetter(&self, index: u32) -> Option<Root<File>> {
+ self.Item(index)
}
}
diff --git a/components/script/dom/headers.rs b/components/script/dom/headers.rs
index 4ed9a5aebec..b977110955c 100644
--- a/components/script/dom/headers.rs
+++ b/components/script/dom/headers.rs
@@ -5,9 +5,11 @@
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HeadersBinding;
use dom::bindings::codegen::Bindings::HeadersBinding::HeadersMethods;
+use dom::bindings::codegen::Bindings::HeadersBinding::HeadersWrap;
use dom::bindings::codegen::UnionTypes::HeadersOrByteStringSequenceSequence;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
+use dom::bindings::iterable::Iterable;
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::{ByteString, is_token};
@@ -45,7 +47,7 @@ impl Headers {
}
pub fn new(global: GlobalRef) -> Root<Headers> {
- reflect_dom_object(box Headers::new_inherited(), global, HeadersBinding::Wrap)
+ reflect_dom_object(box Headers::new_inherited(), global, HeadersWrap)
}
// https://fetch.spec.whatwg.org/#dom-headers
@@ -205,7 +207,13 @@ impl Headers {
headers_for_request
}
- pub fn set_guard(&self, new_guard: Guard) {
+ pub fn for_response(global: GlobalRef) -> Root<Headers> {
+ let headers_for_response = Headers::new(global);
+ headers_for_response.guard.set(Guard::Response);
+ headers_for_response
+ }
+
+ pub fn set_guard(&self, new_guard: Guard) {
self.guard.set(new_guard)
}
@@ -221,6 +229,41 @@ impl Headers {
pub fn extract_mime_type(&self) -> Vec<u8> {
self.header_list.borrow().get_raw("content-type").map_or(vec![], |v| v[0].clone())
}
+
+ pub fn sort_header_list(&self) -> Vec<(String, String)> {
+ let borrowed_header_list = self.header_list.borrow();
+ let headers_iter = borrowed_header_list.iter();
+ let mut header_vec = vec![];
+ for header in headers_iter {
+ let name = header.name().to_string();
+ let value = header.value_string();
+ let name_value = (name, value);
+ header_vec.push(name_value);
+ }
+ header_vec.sort();
+ header_vec
+ }
+}
+
+impl Iterable for Headers {
+ type Key = ByteString;
+ type Value = ByteString;
+
+ fn get_iterable_length(&self) -> u32 {
+ self.header_list.borrow().iter().count() as u32
+ }
+
+ fn get_value_at_index(&self, n: u32) -> ByteString {
+ let sorted_header_vec = self.sort_header_list();
+ let value = sorted_header_vec[n as usize].1.clone();
+ ByteString::new(value.into_bytes().to_vec())
+ }
+
+ fn get_key_at_index(&self, n: u32) -> ByteString {
+ let sorted_header_vec = self.sort_header_list();
+ let key = sorted_header_vec[n as usize].0.clone();
+ ByteString::new(key.into_bytes().to_vec())
+ }
}
fn is_cors_safelisted_request_content_type(value: &[u8]) -> bool {
@@ -307,7 +350,7 @@ pub fn is_forbidden_header_name(name: &str) -> bool {
// [3] https://tools.ietf.org/html/rfc7230#section-3.2.6
// [4] https://www.rfc-editor.org/errata_search.php?rfc=7230
fn validate_name_and_value(name: ByteString, value: ByteString)
- -> Result<(String, Vec<u8>), Error> {
+ -> Fallible<(String, Vec<u8>)> {
let valid_name = try!(validate_name(name));
if !is_field_content(&value) {
return Err(Error::Type("Value is not valid".to_string()));
@@ -315,7 +358,7 @@ fn validate_name_and_value(name: ByteString, value: ByteString)
Ok((valid_name, value.into()))
}
-fn validate_name(name: ByteString) -> Result<String, Error> {
+fn validate_name(name: ByteString) -> Fallible<String> {
if !is_field_name(&name) {
return Err(Error::Type("Name is not valid".to_string()));
}
@@ -405,7 +448,7 @@ fn is_field_vchar(x: u8) -> bool {
}
// https://tools.ietf.org/html/rfc5234#appendix-B.1
-fn is_vchar(x: u8) -> bool {
+pub fn is_vchar(x: u8) -> bool {
match x {
0x21...0x7E => true,
_ => false,
@@ -413,7 +456,7 @@ fn is_vchar(x: u8) -> bool {
}
// http://tools.ietf.org/html/rfc7230#section-3.2.6
-fn is_obs_text(x: u8) -> bool {
+pub fn is_obs_text(x: u8) -> bool {
match x {
0x80...0xFF => true,
_ => false,
diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs
index 6c15cf92150..af95ec404b9 100644
--- a/components/script/dom/htmlbuttonelement.rs
+++ b/components/script/dom/htmlbuttonelement.rs
@@ -15,9 +15,9 @@ use dom::event::Event;
use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement;
use dom::htmlfieldsetelement::HTMLFieldSetElement;
-use dom::htmlformelement::HTMLFormElement;
use dom::htmlformelement::{FormControl, FormDatum, FormDatumValue};
use dom::htmlformelement::{FormSubmitter, ResetFrom, SubmittedFrom};
+use dom::htmlformelement::HTMLFormElement;
use dom::node::{Node, UnbindContext, document_from_node, window_from_node};
use dom::nodelist::NodeList;
use dom::validation::Validatable;
diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs
index 38969860722..73b51962fe4 100644
--- a/components/script/dom/htmlcanvaselement.rs
+++ b/components/script/dom/htmlcanvaselement.rs
@@ -10,6 +10,7 @@ use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext;
+use dom::bindings::conversions::ConversionResult;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
@@ -27,6 +28,7 @@ use euclid::size::Size2D;
use image::ColorType;
use image::png::PNGEncoder;
use ipc_channel::ipc::{self, IpcSender};
+use js::error::throw_type_error;
use js::jsapi::{HandleValue, JSContext};
use offscreen_gl_context::GLContextAttributes;
use rustc_serialize::base64::{STANDARD, ToBase64};
@@ -159,11 +161,17 @@ impl HTMLCanvasElement {
let size = self.get_size();
let attrs = if let Some(webgl_attributes) = attrs {
- if let Ok(ref attrs) = unsafe { WebGLContextAttributes::new(cx, webgl_attributes) } {
- From::from(attrs)
- } else {
- debug!("Unexpected error on conversion of WebGLContextAttributes");
- return None;
+ match unsafe {
+ WebGLContextAttributes::new(cx, webgl_attributes) } {
+ Ok(ConversionResult::Success(ref attrs)) => From::from(attrs),
+ Ok(ConversionResult::Failure(ref error)) => {
+ unsafe { throw_type_error(cx, &error); }
+ return None;
+ }
+ _ => {
+ debug!("Unexpected error on conversion of WebGLContextAttributes");
+ return None;
+ }
}
} else {
GLContextAttributes::default()
@@ -265,11 +273,10 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
// Step 3.
let raw_data = match *self.context.borrow() {
Some(CanvasContext::Context2d(ref context)) => {
- let window = window_from_node(self);
let image_data = try!(context.GetImageData(Finite::wrap(0f64), Finite::wrap(0f64),
Finite::wrap(self.Width() as f64),
Finite::wrap(self.Height() as f64)));
- image_data.get_data_array(&GlobalRef::Window(window.r()))
+ image_data.get_data_array()
}
None => {
// Each pixel is fully-transparent black.
diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs
index 95134556bc0..2f226590719 100644
--- a/components/script/dom/htmlcollection.rs
+++ b/components/script/dom/htmlcollection.rs
@@ -317,17 +317,13 @@ impl HTMLCollectionMethods for HTMLCollection {
}
// https://dom.spec.whatwg.org/#dom-htmlcollection-item
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Element>> {
- let maybe_elem = self.Item(index);
- *found = maybe_elem.is_some();
- maybe_elem
+ fn IndexedGetter(&self, index: u32) -> Option<Root<Element>> {
+ self.Item(index)
}
// check-tidy: no specs after this line
- fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<Root<Element>> {
- let maybe_elem = self.NamedItem(name);
- *found = maybe_elem.is_some();
- maybe_elem
+ fn NamedGetter(&self, name: DOMString) -> Option<Root<Element>> {
+ self.NamedItem(name)
}
// https://dom.spec.whatwg.org/#interface-htmlcollection
diff --git a/components/script/dom/htmldataelement.rs b/components/script/dom/htmldataelement.rs
index f412fd57570..c4bd0bfd173 100644
--- a/components/script/dom/htmldataelement.rs
+++ b/components/script/dom/htmldataelement.rs
@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::Bindings::HTMLDataElementBinding;
+use dom::bindings::codegen::Bindings::HTMLDataElementBinding::HTMLDataElementMethods;
use dom::bindings::js::Root;
use dom::bindings::str::DOMString;
use dom::document::Document;
@@ -33,3 +34,11 @@ impl HTMLDataElement {
HTMLDataElementBinding::Wrap)
}
}
+
+impl HTMLDataElementMethods for HTMLDataElement {
+ // https://html.spec.whatwg.org/multipage/#dom-data-value
+ make_getter!(Value, "value");
+
+ // https://html.spec.whatwg.org/multipage/#dom-data-value
+ make_setter!(SetValue, "value");
+}
diff --git a/components/script/dom/htmldialogelement.rs b/components/script/dom/htmldialogelement.rs
index 621eefcd8a4..1afd7f0d76f 100644
--- a/components/script/dom/htmldialogelement.rs
+++ b/components/script/dom/htmldialogelement.rs
@@ -5,11 +5,14 @@
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLDialogElementBinding;
use dom::bindings::codegen::Bindings::HTMLDialogElementBinding::HTMLDialogElementMethods;
+use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::str::DOMString;
use dom::document::Document;
+use dom::element::Element;
+use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement;
-use dom::node::Node;
+use dom::node::{Node, window_from_node};
use string_cache::Atom;
#[dom_struct]
@@ -56,4 +59,26 @@ impl HTMLDialogElementMethods for HTMLDialogElement {
fn SetReturnValue(&self, return_value: DOMString) {
*self.return_value.borrow_mut() = return_value;
}
+
+ // https://html.spec.whatwg.org/multipage/#dom-dialog-close
+ fn Close(&self, return_value: Option<DOMString>) {
+ let element = self.upcast::<Element>();
+ let target = self.upcast::<EventTarget>();
+ let win = window_from_node(self);
+
+ // Step 1 & 2
+ if element.remove_attribute(&ns!(), &atom!("open")).is_none() {
+ return;
+ }
+
+ // Step 3
+ if let Some(new_value) = return_value {
+ *self.return_value.borrow_mut() = new_value;
+ }
+
+ // TODO: Step 4 implement pending dialog stack removal
+
+ // Step 5
+ win.dom_manipulation_task_source().queue_simple_event(target, atom!("close"), win.r());
+ }
}
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs
index e9d967514d7..4ec42ced6d6 100644
--- a/components/script/dom/htmlelement.rs
+++ b/components/script/dom/htmlelement.rs
@@ -11,8 +11,8 @@ use dom::bindings::codegen::Bindings::HTMLElementBinding;
use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::error::{Error, ErrorResult};
-use dom::bindings::inheritance::Castable;
use dom::bindings::inheritance::{ElementTypeId, HTMLElementTypeId, NodeTypeId};
+use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference};
use dom::bindings::str::DOMString;
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
diff --git a/components/script/dom/htmlformcontrolscollection.rs b/components/script/dom/htmlformcontrolscollection.rs
index 9229b854b26..e52a541225f 100644
--- a/components/script/dom/htmlformcontrolscollection.rs
+++ b/components/script/dom/htmlformcontrolscollection.rs
@@ -77,10 +77,8 @@ impl HTMLFormControlsCollectionMethods for HTMLFormControlsCollection {
}
// https://html.spec.whatwg.org/multipage/#dom-htmlformcontrolscollection-nameditem
- fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<RadioNodeListOrElement> {
- let maybe_elem = self.NamedItem(name);
- *found = maybe_elem.is_some();
- maybe_elem
+ fn NamedGetter(&self, name: DOMString) -> Option<RadioNodeListOrElement> {
+ self.NamedItem(name)
}
// https://html.spec.whatwg.org/multipage/#the-htmlformcontrolscollection-interface:supported-property-names
@@ -93,7 +91,7 @@ impl HTMLFormControlsCollectionMethods for HTMLFormControlsCollection {
// https://github.com/servo/servo/issues/5875
//
// https://dom.spec.whatwg.org/#dom-htmlcollection-item
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Element>> {
- self.collection.IndexedGetter(index, found)
+ fn IndexedGetter(&self, index: u32) -> Option<Root<Element>> {
+ self.collection.IndexedGetter(index)
}
}
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index db9e3cb8d41..fa16618b564 100644
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -230,9 +230,9 @@ impl HTMLFormElementMethods for HTMLFormElement {
}
// https://html.spec.whatwg.org/multipage/#dom-form-item
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Element>> {
+ fn IndexedGetter(&self, index: u32) -> Option<Root<Element>> {
let elements = self.Elements();
- elements.IndexedGetter(index, found)
+ elements.IndexedGetter(index)
}
}
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index 73d750cc8dd..59578b37b59 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use document_loader::{LoadType, LoadBlocker};
+use document_loader::{LoadBlocker, LoadType};
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserElementErrorEventDetail;
@@ -20,7 +20,7 @@ use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
-use dom::bindings::js::{JS, MutNullableHeap, Root, LayoutJS};
+use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root};
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
use dom::browsingcontext::BrowsingContext;
@@ -31,18 +31,18 @@ use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
use dom::event::Event;
use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement;
-use dom::node::{Node, NodeDamage, UnbindContext, window_from_node, document_from_node};
+use dom::node::{Node, NodeDamage, UnbindContext, document_from_node, window_from_node};
use dom::urlhelper::UrlHelper;
use dom::virtualmethods::VirtualMethods;
use dom::window::{ReflowReason, Window};
use ipc_channel::ipc;
use js::jsapi::{JSAutoCompartment, JSContext, MutableHandleValue};
-use js::jsval::{UndefinedValue, NullValue};
-use msg::constellation_msg::{FrameType, LoadData, TraversalDirection, PipelineId, SubpageId};
+use js::jsval::{NullValue, UndefinedValue};
+use msg::constellation_msg::{FrameType, LoadData, PipelineId, SubpageId, TraversalDirection};
use net_traits::response::HttpsState;
use script_layout_interface::message::ReflowQueryType;
-use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
use script_traits::{IFrameLoadInfo, MozBrowserEvent, ScriptMsg as ConstellationMsg};
+use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
use std::cell::Cell;
use string_cache::Atom;
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
@@ -355,7 +355,7 @@ unsafe fn build_mozbrowser_event_detail(event: MozBrowserEvent,
type_: Some(DOMString::from(error_type.name())),
description: Some(DOMString::from(description)),
report: Some(DOMString::from(report)),
- version: Some(DOMString::from_string(servo_version().into())),
+ version: Some(DOMString::from_string(servo_version())),
}.to_jsval(cx, rval);
},
MozBrowserEvent::SecurityChange(https_state) => {
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index a98fcbcfb4e..978d93f6138 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -13,17 +13,17 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementM
use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods;
use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::inheritance::Castable;
-use dom::bindings::js::{JS, LayoutJS, Root, RootedReference, MutNullableHeap};
+use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root, RootedReference};
use dom::bindings::str::DOMString;
use dom::document::Document;
-use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers, LayoutElementHelpers};
+use dom::element::{AttributeMutation, Element, LayoutElementHelpers, RawLayoutElementHelpers};
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
use dom::file::File;
use dom::filelist::FileList;
use dom::htmlelement::HTMLElement;
use dom::htmlfieldsetelement::HTMLFieldSetElement;
-use dom::htmlformelement::{FormDatumValue, FormControl, FormDatum, FormSubmitter, HTMLFormElement};
+use dom::htmlformelement::{FormControl, FormDatum, FormDatumValue, FormSubmitter, HTMLFormElement};
use dom::htmlformelement::{ResetFrom, SubmittedFrom};
use dom::keyboardevent::KeyboardEvent;
use dom::node::{Node, NodeDamage, UnbindContext};
@@ -34,9 +34,9 @@ use dom::virtualmethods::VirtualMethods;
use ipc_channel::ipc::{self, IpcSender};
use mime_guess;
use msg::constellation_msg::Key;
+use net_traits::{CoreResourceMsg, IpcSend};
use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern};
-use net_traits::{IpcSend, CoreResourceMsg};
use script_traits::ScriptMsg as ConstellationMsg;
use std::borrow::ToOwned;
use std::cell::Cell;
@@ -45,9 +45,9 @@ use string_cache::Atom;
use style::attr::AttrValue;
use style::element_state::*;
use style::str::split_commas;
+use textinput::{SelectionDirection, TextInput};
use textinput::KeyReaction::{DispatchInput, Nothing, RedrawSelection, TriggerDefaultAction};
use textinput::Lines::Single;
-use textinput::{TextInput, SelectionDirection};
const DEFAULT_SUBMIT_VALUE: &'static str = "Submit";
const DEFAULT_RESET_VALUE: &'static str = "Reset";
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index 9264bcb0490..07cd47cbcec 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -22,7 +22,6 @@ use dom::virtualmethods::VirtualMethods;
use encoding::EncodingRef;
use encoding::all::UTF_8;
use hyper::header::ContentType;
-use hyper::http::RawStatus;
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper_serde::Serde;
use ipc_channel::ipc;
@@ -335,7 +334,7 @@ impl AsyncResponseListener for StylesheetContext {
document.invalidate_stylesheets();
// FIXME: Revisit once consensus is reached at: https://github.com/whatwg/html/issues/1142
- successful = metadata.status.map_or(false, |Serde(RawStatus(code, _))| code == 200);
+ successful = metadata.status.map_or(false, |(code, _)| code == 200);
}
if elem.parser_inserted.get() {
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index d26ac6a044e..6be1fbb3d96 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use audio_video_metadata;
use document_loader::LoadType;
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
@@ -24,7 +25,6 @@ use dom::htmlsourceelement::HTMLSourceElement;
use dom::mediaerror::MediaError;
use dom::node::{window_from_node, document_from_node, Node, UnbindContext};
use dom::virtualmethods::VirtualMethods;
-use hyper_serde::Serde;
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError};
@@ -66,7 +66,7 @@ impl AsyncResponseListener for HTMLMediaElementContext {
.as_ref()
.and_then(|m| m.status
.as_ref()
- .map(|&Serde(ref s)| s.0 < 200 || s.0 >= 300))
+ .map(|&(s, _)| s < 200 || s >= 300))
.unwrap_or(false);
if is_failure {
// Ensure that the element doesn't receive any further notifications
@@ -160,12 +160,24 @@ impl HTMLMediaElementContext {
}
fn check_metadata(&mut self, elem: &HTMLMediaElement) {
- // Step 6.
- //
- // TODO: Properly implement once we have figured out the build and
- // licensing ffmpeg issues.
- elem.change_ready_state(HAVE_METADATA);
- self.have_metadata = true;
+ match audio_video_metadata::get_format_from_slice(&self.data) {
+ Ok(audio_video_metadata::Metadata::Video(meta)) => {
+ let dur = meta.audio.duration.unwrap_or(::std::time::Duration::new(0, 0));
+ *elem.video.borrow_mut() = Some(VideoMedia {
+ format: format!("{:?}", meta.format),
+ duration: Duration::seconds(dur.as_secs() as i64) +
+ Duration::nanoseconds(dur.subsec_nanos() as i64),
+ width: meta.dimensions.width,
+ height: meta.dimensions.height,
+ video: meta.video.unwrap_or("".to_owned()),
+ audio: meta.audio.audio,
+ });
+ // Step 6
+ elem.change_ready_state(HAVE_METADATA);
+ self.have_metadata = true;
+ }
+ _ => {}
+ }
}
}
diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs
index b8c2cd423fa..e6f86f41d86 100644
--- a/components/script/dom/htmlmetaelement.rs
+++ b/components/script/dom/htmlmetaelement.rs
@@ -79,7 +79,7 @@ impl HTMLMetaElement {
if !content.is_empty() {
if let Some(translated_rule) = ViewportRule::from_meta(&**content) {
*self.stylesheet.borrow_mut() = Some(Arc::new(Stylesheet {
- rules: vec![CSSRule::Viewport(translated_rule)],
+ rules: vec![CSSRule::Viewport(Arc::new(translated_rule))],
origin: Origin::Author,
media: None,
// Viewport constraints are always recomputed on resize; they don't need to
diff --git a/components/script/dom/htmloptionelement.rs b/components/script/dom/htmloptionelement.rs
index 737bc67bd4c..9183a78de0c 100644
--- a/components/script/dom/htmloptionelement.rs
+++ b/components/script/dom/htmloptionelement.rs
@@ -6,6 +6,7 @@ use dom::attr::Attr;
use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding;
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods;
+use dom::bindings::codegen::Bindings::HTMLSelectElementBinding::HTMLSelectElementBinding::HTMLSelectElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
@@ -14,6 +15,8 @@ use dom::characterdata::CharacterData;
use dom::document::Document;
use dom::element::{AttributeMutation, Element};
use dom::htmlelement::HTMLElement;
+use dom::htmlformelement::HTMLFormElement;
+use dom::htmloptgroupelement::HTMLOptGroupElement;
use dom::htmlscriptelement::HTMLScriptElement;
use dom::htmlselectelement::HTMLSelectElement;
use dom::node::{Node, UnbindContext};
@@ -110,6 +113,19 @@ impl HTMLOptionElementMethods for HTMLOptionElement {
self.upcast::<Node>().SetTextContent(Some(value))
}
+ // https://html.spec.whatwg.org/multipage/#dom-option-form
+ fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
+ let parent = self.upcast::<Node>().GetParentNode().and_then(|p|
+ if p.is::<HTMLOptGroupElement>() {
+ p.upcast::<Node>().GetParentNode()
+ } else {
+ Some(p)
+ }
+ );
+
+ parent.and_then(|p| p.downcast::<HTMLSelectElement>().and_then(|s| s.GetForm()))
+ }
+
// https://html.spec.whatwg.org/multipage/#attr-option-value
fn Value(&self) -> DOMString {
let element = self.upcast::<Element>();
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index 6a6fe7d50b4..6484de1e029 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -11,8 +11,8 @@ use dom::bindings::codegen::Bindings::HTMLScriptElementBinding::HTMLScriptElemen
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
-use dom::bindings::js::RootedReference;
use dom::bindings::js::{JS, Root};
+use dom::bindings::js::RootedReference;
use dom::bindings::refcounted::Trusted;
use dom::bindings::str::DOMString;
use dom::document::Document;
@@ -26,8 +26,6 @@ use dom::window::ScriptHelpers;
use encoding::label::encoding_from_whatwg_label;
use encoding::types::{DecoderTrap, EncodingRef};
use html5ever::tree_builder::NextParserState;
-use hyper::http::RawStatus;
-use hyper_serde::Serde;
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use js::jsval::UndefinedValue;
@@ -159,7 +157,7 @@ impl AsyncResponseListener for ScriptContext {
let status_code = self.metadata.as_ref().and_then(|m| {
match m.status {
- Some(Serde(RawStatus(c, _))) => Some(c),
+ Some((c, _)) => Some(c),
_ => None,
}
}).unwrap_or(0);
diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs
index a89df91f99b..5df0778fa2b 100644
--- a/components/script/dom/htmltextareaelement.rs
+++ b/components/script/dom/htmltextareaelement.rs
@@ -12,8 +12,8 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::str::DOMString;
use dom::document::Document;
-use dom::element::RawLayoutElementHelpers;
use dom::element::{AttributeMutation, Element};
+use dom::element::RawLayoutElementHelpers;
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::htmlelement::HTMLElement;
use dom::htmlfieldsetelement::HTMLFieldSetElement;
@@ -31,7 +31,7 @@ use std::ops::Range;
use string_cache::Atom;
use style::attr::AttrValue;
use style::element_state::*;
-use textinput::{KeyReaction, Lines, TextInput, SelectionDirection};
+use textinput::{KeyReaction, Lines, SelectionDirection, TextInput};
#[dom_struct]
pub struct HTMLTextAreaElement {
diff --git a/components/script/dom/imagedata.rs b/components/script/dom/imagedata.rs
index abcb9b5640b..0959a52eb32 100644
--- a/components/script/dom/imagedata.rs
+++ b/components/script/dom/imagedata.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use core::nonzero::NonZero;
use dom::bindings::codegen::Bindings::ImageDataBinding;
use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods;
use dom::bindings::global::GlobalRef;
@@ -37,6 +38,7 @@ impl ImageData {
unsafe {
let cx = global.get_cx();
let js_object: *mut JSObject = JS_NewUint8ClampedArray(cx, width * height * 4);
+ assert!(!js_object.is_null());
if let Some(vec) = data {
let mut is_shared = false;
@@ -52,12 +54,13 @@ impl ImageData {
}
#[allow(unsafe_code)]
- pub fn get_data_array(&self, global: &GlobalRef) -> Vec<u8> {
+ pub fn get_data_array(&self) -> Vec<u8> {
unsafe {
- let cx = global.get_cx();
let mut is_shared = false;
+ assert!(!self.data.get().is_null());
let data: *const uint8_t =
- JS_GetUint8ClampedArrayData(self.Data(cx), &mut is_shared, ptr::null()) as *const uint8_t;
+ JS_GetUint8ClampedArrayData(self.data.get(), &mut is_shared, ptr::null()) as *const uint8_t;
+ assert!(!data.is_null());
assert!(!is_shared);
let len = self.Width() * self.Height() * 4;
slice::from_raw_parts(data, len as usize).to_vec()
@@ -80,8 +83,10 @@ impl ImageDataMethods for ImageData {
self.height
}
+ #[allow(unsafe_code)]
// https://html.spec.whatwg.org/multipage/#dom-imagedata-data
- fn Data(&self, _: *mut JSContext) -> *mut JSObject {
- self.data.get()
+ fn Data(&self, _: *mut JSContext) -> NonZero<*mut JSObject> {
+ assert!(!self.data.get().is_null());
+ unsafe { NonZero::new(self.data.get()) }
}
}
diff --git a/components/script/dom/mimetypearray.rs b/components/script/dom/mimetypearray.rs
index 96fc48c86d0..de820f6d06a 100644
--- a/components/script/dom/mimetypearray.rs
+++ b/components/script/dom/mimetypearray.rs
@@ -46,12 +46,12 @@ impl MimeTypeArrayMethods for MimeTypeArray {
}
// https://html.spec.whatwg.org/multipage/#dom-mimetypearray-item
- fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Root<MimeType>> {
+ fn IndexedGetter(&self, _index: u32) -> Option<Root<MimeType>> {
None
}
// check-tidy: no specs after this line
- fn NamedGetter(&self, _name: DOMString, _found: &mut bool) -> Option<Root<MimeType>> {
+ fn NamedGetter(&self, _name: DOMString) -> Option<Root<MimeType>> {
None
}
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 432246d814f..f38d1e8949c 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -372,6 +372,7 @@ pub mod progressevent;
pub mod radionodelist;
pub mod range;
pub mod request;
+pub mod response;
pub mod screen;
pub mod serviceworker;
pub mod serviceworkercontainer;
@@ -384,6 +385,8 @@ pub mod storageevent;
pub mod stylesheet;
pub mod stylesheetlist;
pub mod testbinding;
+pub mod testbindingiterable;
+pub mod testbindingpairiterable;
pub mod testbindingproxy;
pub mod text;
pub mod textdecoder;
diff --git a/components/script/dom/namednodemap.rs b/components/script/dom/namednodemap.rs
index 10b6b8982ae..9edc1b1e93b 100644
--- a/components/script/dom/namednodemap.rs
+++ b/components/script/dom/namednodemap.rs
@@ -85,17 +85,13 @@ impl NamedNodeMapMethods for NamedNodeMap {
}
// https://dom.spec.whatwg.org/#dom-namednodemap-item
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Attr>> {
- let item = self.Item(index);
- *found = item.is_some();
- item
+ fn IndexedGetter(&self, index: u32) -> Option<Root<Attr>> {
+ self.Item(index)
}
// check-tidy: no specs after this line
- fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<Root<Attr>> {
- let item = self.GetNamedItem(name);
- *found = item.is_some();
- item
+ fn NamedGetter(&self, name: DOMString) -> Option<Root<Attr>> {
+ self.GetNamedItem(name)
}
// https://heycam.github.io/webidl/#dfn-supported-property-names
diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs
index 75bd2c13c23..61936c59e5f 100644
--- a/components/script/dom/navigator.rs
+++ b/components/script/dom/navigator.rs
@@ -107,4 +107,10 @@ impl NavigatorMethods for Navigator {
fn ServiceWorker(&self) -> Root<ServiceWorkerContainer> {
self.serviceWorker.or_init(|| ServiceWorkerContainer::new(self.global().r()))
}
+
+ // https://html.spec.whatwg.org/multipage/#dom-navigator-cookieenabled
+ fn CookieEnabled(&self) -> bool {
+ true
+ }
+
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 49aa8242b34..5f1bee3a730 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -23,9 +23,9 @@ use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::{Castable, CharacterDataTypeId, ElementTypeId};
use dom::bindings::inheritance::{EventTargetTypeId, HTMLElementTypeId, NodeTypeId};
+use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
use dom::bindings::js::Root;
use dom::bindings::js::RootedReference;
-use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::{DOMString, USVString};
use dom::bindings::xmlname::namespace_from_domstring;
@@ -59,11 +59,11 @@ use libc::{self, c_void, uintptr_t};
use msg::constellation_msg::PipelineId;
use parse::html::parse_html_fragment;
use ref_slice::ref_slice;
-use script_layout_interface::message::Msg;
use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData};
-use script_layout_interface::{LayoutNodeType, LayoutElementType, TrustedNodeAddress};
+use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress};
+use script_layout_interface::message::Msg;
use script_traits::UntrustedNodeAddress;
-use selectors::matching::matches;
+use selectors::matching::{MatchingReason, matches};
use selectors::parser::Selector;
use selectors::parser::parse_author_origin_selector_list_from_str;
use std::borrow::ToOwned;
@@ -319,7 +319,7 @@ impl<'a> Iterator for QuerySelectorIterator {
// (instead of passing `None`)? Probably.
self.iterator.by_ref().filter_map(|node| {
if let Some(element) = Root::downcast(node) {
- if matches(selectors, &element, None) {
+ if matches(selectors, &element, None, MatchingReason::Other) {
return Some(Root::upcast(element));
}
}
@@ -711,7 +711,7 @@ impl Node {
// Step 3.
Ok(ref selectors) => {
Ok(self.traverse_preorder().filter_map(Root::downcast).find(|element| {
- matches(selectors, element, None)
+ matches(selectors, element, None, MatchingReason::Other)
}))
}
}
diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs
index 2503378187e..8f8a5515592 100644
--- a/components/script/dom/nodelist.rs
+++ b/components/script/dom/nodelist.rs
@@ -75,10 +75,8 @@ impl NodeListMethods for NodeList {
}
// https://dom.spec.whatwg.org/#dom-nodelist-item
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Node>> {
- let item = self.Item(index);
- *found = item.is_some();
- item
+ fn IndexedGetter(&self, index: u32) -> Option<Root<Node>> {
+ self.Item(index)
}
}
diff --git a/components/script/dom/plugin.rs b/components/script/dom/plugin.rs
index dc4ca4fe42d..222e9a2840a 100644
--- a/components/script/dom/plugin.rs
+++ b/components/script/dom/plugin.rs
@@ -45,12 +45,12 @@ impl PluginMethods for Plugin {
}
// https://html.spec.whatwg.org/multipage/#dom-plugin-item
- fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Root<MimeType>> {
+ fn IndexedGetter(&self, _index: u32) -> Option<Root<MimeType>> {
unreachable!()
}
// check-tidy: no specs after this line
- fn NamedGetter(&self, _name: DOMString, _found: &mut bool) -> Option<Root<MimeType>> {
+ fn NamedGetter(&self, _name: DOMString) -> Option<Root<MimeType>> {
unreachable!()
}
diff --git a/components/script/dom/pluginarray.rs b/components/script/dom/pluginarray.rs
index aabba4928a4..aa6b779280d 100644
--- a/components/script/dom/pluginarray.rs
+++ b/components/script/dom/pluginarray.rs
@@ -50,12 +50,12 @@ impl PluginArrayMethods for PluginArray {
}
// https://html.spec.whatwg.org/multipage/#dom-pluginarray-item
- fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Root<Plugin>> {
+ fn IndexedGetter(&self, _index: u32) -> Option<Root<Plugin>> {
None
}
// check-tidy: no specs after this line
- fn NamedGetter(&self, _name: DOMString, _found: &mut bool) -> Option<Root<Plugin>> {
+ fn NamedGetter(&self, _name: DOMString) -> Option<Root<Plugin>> {
None
}
diff --git a/components/script/dom/radionodelist.rs b/components/script/dom/radionodelist.rs
index d88fc69eacd..9bbdae00c85 100644
--- a/components/script/dom/radionodelist.rs
+++ b/components/script/dom/radionodelist.rs
@@ -105,7 +105,7 @@ impl RadioNodeListMethods for RadioNodeList {
// https://github.com/servo/servo/issues/5875
//
// https://dom.spec.whatwg.org/#dom-nodelist-item
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Node>> {
- self.node_list.IndexedGetter(index, found)
+ fn IndexedGetter(&self, index: u32) -> Option<Root<Node>> {
+ self.node_list.IndexedGetter(index)
}
}
diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs
index b8cb72c4dc4..bab6bdcc3a2 100644
--- a/components/script/dom/range.rs
+++ b/components/script/dom/range.rs
@@ -6,14 +6,14 @@ use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods
use dom::bindings::codegen::Bindings::NodeBinding::NodeConstants;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
-use dom::bindings::codegen::Bindings::RangeBinding::RangeMethods;
use dom::bindings::codegen::Bindings::RangeBinding::{self, RangeConstants};
+use dom::bindings::codegen::Bindings::RangeBinding::RangeMethods;
use dom::bindings::codegen::Bindings::TextBinding::TextMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
-use dom::bindings::inheritance::Castable;
use dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId};
+use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutHeap, Root, RootedReference};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs
index c396c0d36e1..a32799cd61c 100644
--- a/components/script/dom/request.rs
+++ b/components/script/dom/request.rs
@@ -19,10 +19,11 @@ use dom::bindings::error::{Error, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
-use dom::bindings::str::{ByteString, USVString, DOMString};
-use dom::headers::{Headers, Guard};
+use dom::bindings::str::{ByteString, DOMString, USVString};
+use dom::headers::{Guard, Headers};
use hyper;
-use msg::constellation_msg::{ReferrerPolicy as MsgReferrerPolicy};
+use msg::constellation_msg::ReferrerPolicy as MsgReferrerPolicy;
+use net_traits::request::{Origin, Window};
use net_traits::request::CacheMode as NetTraitsRequestCache;
use net_traits::request::CredentialsMode as NetTraitsRequestCredentials;
use net_traits::request::Destination as NetTraitsRequestDestination;
@@ -31,7 +32,6 @@ use net_traits::request::Referer as NetTraitsRequestReferer;
use net_traits::request::Request as NetTraitsRequest;
use net_traits::request::RequestMode as NetTraitsRequestMode;
use net_traits::request::Type as NetTraitsRequestType;
-use net_traits::request::{Origin, Window};
use std::cell::Cell;
use url::Url;
diff --git a/components/script/dom/response.rs b/components/script/dom/response.rs
new file mode 100644
index 00000000000..acfc181283a
--- /dev/null
+++ b/components/script/dom/response.rs
@@ -0,0 +1,290 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use core::cell::Cell;
+use dom::bindings::cell::DOMRefCell;
+use dom::bindings::codegen::Bindings::HeadersBinding::HeadersMethods;
+use dom::bindings::codegen::Bindings::ResponseBinding;
+use dom::bindings::codegen::Bindings::ResponseBinding::{ResponseMethods, ResponseType as DOMResponseType};
+use dom::bindings::error::{Error, Fallible};
+use dom::bindings::global::GlobalRef;
+use dom::bindings::js::{JS, MutNullableHeap, Root};
+use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
+use dom::bindings::str::{ByteString, USVString};
+use dom::headers::{Headers, Guard};
+use dom::headers::{is_vchar, is_obs_text};
+use hyper::status::StatusCode;
+use net_traits::response::{ResponseBody as NetTraitsResponseBody};
+use std::str::FromStr;
+use url::Position;
+use url::Url;
+
+#[dom_struct]
+pub struct Response {
+ reflector_: Reflector,
+ headers_reflector: MutNullableHeap<JS<Headers>>,
+ mime_type: DOMRefCell<Vec<u8>>,
+ body_used: Cell<bool>,
+ /// `None` can be considered a StatusCode of `0`.
+ #[ignore_heap_size_of = "Defined in hyper"]
+ status: DOMRefCell<Option<StatusCode>>,
+ raw_status: DOMRefCell<Option<(u16, Vec<u8>)>>,
+ response_type: DOMRefCell<DOMResponseType>,
+ url: DOMRefCell<Option<Url>>,
+ url_list: DOMRefCell<Vec<Url>>,
+ // For now use the existing NetTraitsResponseBody enum, until body
+ // is implemented.
+ body: DOMRefCell<NetTraitsResponseBody>,
+}
+
+impl Response {
+ pub fn new_inherited() -> Response {
+ Response {
+ reflector_: Reflector::new(),
+ headers_reflector: Default::default(),
+ mime_type: DOMRefCell::new("".to_string().into_bytes()),
+ body_used: Cell::new(false),
+ status: DOMRefCell::new(Some(StatusCode::Ok)),
+ raw_status: DOMRefCell::new(Some((200, b"OK".to_vec()))),
+ response_type: DOMRefCell::new(DOMResponseType::Default),
+ url: DOMRefCell::new(None),
+ url_list: DOMRefCell::new(vec![]),
+ body: DOMRefCell::new(NetTraitsResponseBody::Empty),
+ }
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response
+ pub fn new(global: GlobalRef) -> Root<Response> {
+ reflect_dom_object(box Response::new_inherited(), global, ResponseBinding::Wrap)
+ }
+
+ pub fn Constructor(global: GlobalRef, _body: Option<USVString>, init: &ResponseBinding::ResponseInit)
+ -> Fallible<Root<Response>> {
+ // Step 1
+ if init.status < 200 || init.status > 599 {
+ return Err(Error::Range(
+ format!("init's status member should be in the range 200 to 599, inclusive, but is {}"
+ , init.status)));
+ }
+
+ // Step 2
+ if !is_valid_status_text(&init.statusText) {
+ return Err(Error::Type("init's statusText member does not match the reason-phrase token production"
+ .to_string()));
+ }
+
+ // Step 3
+ let r = Response::new(global);
+
+ // Step 4
+ *r.status.borrow_mut() = Some(StatusCode::from_u16(init.status));
+
+ // Step 5
+ *r.raw_status.borrow_mut() = Some((init.status, init.statusText.clone().into()));
+
+ // Step 6
+ if let Some(ref headers_member) = init.headers {
+ // Step 6.1
+ // TODO: Figure out how/if we should make r's response's
+ // header list and r's Headers object the same thing. For
+ // now just working with r's Headers object. Also, the
+ // header list should already be empty so this step may be
+ // unnecessary.
+ r.Headers().empty_header_list();
+
+ // Step 6.2
+ try!(r.Headers().fill(Some(headers_member.clone())));
+ }
+
+ // Step 7
+ if let Some(_) = _body {
+ // Step 7.1
+ if is_null_body_status(init.status) {
+ return Err(Error::Type(
+ "Body is non-null but init's status member is a null body status".to_string()));
+ };
+
+ // Step 7.2
+ let content_type: Option<ByteString> = None;
+
+ // Step 7.3
+ // TODO: Extract body and implement step 7.3.
+
+ // Step 7.4
+ if let Some(content_type_contents) = content_type {
+ if !r.Headers().Has(ByteString::new(b"Content-Type".to_vec())).unwrap() {
+ try!(r.Headers().Append(ByteString::new(b"Content-Type".to_vec()), content_type_contents));
+ }
+ };
+ }
+
+ // Step 8
+ *r.mime_type.borrow_mut() = r.Headers().extract_mime_type();
+
+ // Step 9
+ // TODO: `entry settings object` is not implemented in Servo yet.
+
+ // Step 10
+ // TODO: Write this step once Promises are merged in
+
+ // Step 11
+ Ok(r)
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response-error
+ pub fn Error(global: GlobalRef) -> Root<Response> {
+ let r = Response::new(global);
+ *r.response_type.borrow_mut() = DOMResponseType::Error;
+ r.Headers().set_guard(Guard::Immutable);
+ *r.raw_status.borrow_mut() = Some((0, b"".to_vec()));
+ r
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response-redirect
+ pub fn Redirect(global: GlobalRef, url: USVString, status: u16) -> Fallible<Root<Response>> {
+ // Step 1
+ // TODO: `entry settings object` is not implemented in Servo yet.
+ let base_url = global.get_url();
+ let parsed_url = base_url.join(&url.0);
+
+ // Step 2
+ let url = match parsed_url {
+ Ok(url) => url,
+ Err(_) => return Err(Error::Type("Url could not be parsed".to_string())),
+ };
+
+ // Step 3
+ if !is_redirect_status(status) {
+ return Err(Error::Range("status is not a redirect status".to_string()));
+ }
+
+ // Step 4
+ // see Step 4 continued
+ let r = Response::new(global);
+
+ // Step 5
+ *r.status.borrow_mut() = Some(StatusCode::from_u16(status));
+ *r.raw_status.borrow_mut() = Some((status, b"".to_vec()));
+
+ // Step 6
+ let url_bytestring = ByteString::from_str(url.as_str()).unwrap_or(ByteString::new(b"".to_vec()));
+ try!(r.Headers().Set(ByteString::new(b"Location".to_vec()), url_bytestring));
+
+ // Step 4 continued
+ // Headers Guard is set to Immutable here to prevent error in Step 6
+ r.Headers().set_guard(Guard::Immutable);
+
+ // Step 7
+ Ok(r)
+ }
+}
+
+// https://fetch.spec.whatwg.org/#redirect-status
+fn is_redirect_status(status: u16) -> bool {
+ status == 301 || status == 302 || status == 303 || status == 307 || status == 308
+}
+
+// https://tools.ietf.org/html/rfc7230#section-3.1.2
+fn is_valid_status_text(status_text: &ByteString) -> bool {
+ // reason-phrase = *( HTAB / SP / VCHAR / obs-text )
+ for byte in status_text.iter() {
+ if !(*byte == b'\t' || *byte == b' ' || is_vchar(*byte) || is_obs_text(*byte)) {
+ return false;
+ }
+ }
+ true
+}
+
+// https://fetch.spec.whatwg.org/#null-body-status
+fn is_null_body_status(status: u16) -> bool {
+ status == 101 || status == 204 || status == 205 || status == 304
+}
+
+impl ResponseMethods for Response {
+ // https://fetch.spec.whatwg.org/#dom-response-type
+ fn Type(&self) -> DOMResponseType {
+ *self.response_type.borrow()//into()
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response-url
+ fn Url(&self) -> USVString {
+ USVString(String::from((*self.url.borrow()).as_ref().map(|u| serialize_without_fragment(u)).unwrap_or("")))
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response-redirected
+ fn Redirected(&self) -> bool {
+ let url_list_len = self.url_list.borrow().len();
+ url_list_len > 1
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response-status
+ fn Status(&self) -> u16 {
+ match *self.raw_status.borrow() {
+ Some((s, _)) => s,
+ None => 0,
+ }
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response-ok
+ fn Ok(&self) -> bool {
+ match *self.status.borrow() {
+ Some(s) => {
+ let status_num = s.to_u16();
+ return status_num >= 200 && status_num <= 299;
+ }
+ None => false,
+ }
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response-statustext
+ fn StatusText(&self) -> ByteString {
+ match *self.raw_status.borrow() {
+ Some((_, ref st)) => ByteString::new(st.clone()),
+ None => ByteString::new(b"OK".to_vec()),
+ }
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response-headers
+ fn Headers(&self) -> Root<Headers> {
+ self.headers_reflector.or_init(|| Headers::for_response(self.global().r()))
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-response-clone
+ fn Clone(&self) -> Fallible<Root<Response>> {
+ // Step 1
+ // TODO: This step relies on body and stream, which are still unimplemented.
+
+ // Step 2
+ let new_response = Response::new(self.global().r());
+ new_response.Headers().set_guard(self.Headers().get_guard());
+
+ // https://fetch.spec.whatwg.org/#concept-response-clone
+ // Instead of storing a net_traits::Response internally, we
+ // only store the relevant fields, and only clone them here
+ *new_response.response_type.borrow_mut() = self.response_type.borrow().clone();
+ *new_response.status.borrow_mut() = self.status.borrow().clone();
+ *new_response.raw_status.borrow_mut() = self.raw_status.borrow().clone();
+ *new_response.url.borrow_mut() = self.url.borrow().clone();
+ *new_response.url_list.borrow_mut() = self.url_list.borrow().clone();
+
+ if *self.body.borrow() != NetTraitsResponseBody::Empty {
+ *new_response.body.borrow_mut() = self.body.borrow().clone();
+ }
+
+ // Step 3
+ // TODO: This step relies on promises, which are still unimplemented.
+
+ // Step 4
+ Ok(new_response)
+ }
+
+ // https://fetch.spec.whatwg.org/#dom-body-bodyused
+ fn BodyUsed(&self) -> bool {
+ self.body_used.get()
+ }
+}
+
+fn serialize_without_fragment(url: &Url) -> &str {
+ &url[..Position::AfterQuery]
+}
diff --git a/components/script/dom/serviceworker.rs b/components/script/dom/serviceworker.rs
index 19af9b09ba4..2b79be43dc8 100644
--- a/components/script/dom/serviceworker.rs
+++ b/components/script/dom/serviceworker.rs
@@ -2,8 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use dom::abstractworker::WorkerScriptMsg;
-use dom::abstractworker::{SimpleWorkerErrorHandler, WorkerErrorHandler};
+use dom::abstractworker::{SimpleWorkerErrorHandler, WorkerScriptMsg};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::ServiceWorkerBinding::{ServiceWorkerMethods, ServiceWorkerState, Wrap};
@@ -11,12 +10,9 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
-use dom::bindings::reflector::{Reflectable, reflect_dom_object};
-use dom::bindings::str::{DOMString, USVString};
-use dom::errorevent::ErrorEvent;
-use dom::event::{Event, EventBubbles, EventCancelable};
+use dom::bindings::reflector::reflect_dom_object;
+use dom::bindings::str::USVString;
use dom::eventtarget::EventTarget;
-use js::jsval::UndefinedValue;
use script_thread::Runnable;
use std::cell::Cell;
use std::sync::mpsc::Sender;
@@ -66,18 +62,6 @@ impl ServiceWorker {
Url::parse(&self.script_url.borrow().clone()).unwrap()
}
- pub fn handle_error_message(address: TrustedServiceWorkerAddress, message: DOMString,
- filename: DOMString, lineno: u32, colno: u32) {
- let worker = address.root();
-
- let global = worker.r().global();
- rooted!(in(global.r().get_cx()) let error = UndefinedValue());
- let errorevent = ErrorEvent::new(global.r(), atom!("error"),
- EventBubbles::Bubbles, EventCancelable::Cancelable,
- message, filename, lineno, colno, error.handle());
- errorevent.upcast::<Event>().fire(worker.upcast());
- }
-
pub fn install_serviceworker(global: GlobalRef,
script_url: Url,
skip_waiting: bool) -> Root<ServiceWorker> {
@@ -112,11 +96,3 @@ impl Runnable for SimpleWorkerErrorHandler<ServiceWorker> {
ServiceWorker::dispatch_simple_error(this.addr);
}
}
-
-impl Runnable for WorkerErrorHandler<ServiceWorker> {
- #[allow(unrooted_must_root)]
- fn handler(self: Box<WorkerErrorHandler<ServiceWorker>>) {
- let this = *self;
- ServiceWorker::handle_error_message(this.addr, this.msg, this.file_name, this.line_num, this.col_num);
- }
-}
diff --git a/components/script/dom/serviceworkercontainer.rs b/components/script/dom/serviceworkercontainer.rs
index 4487c064fe1..06080b7731c 100644
--- a/components/script/dom/serviceworkercontainer.rs
+++ b/components/script/dom/serviceworkercontainer.rs
@@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use dom::bindings::codegen::Bindings::ServiceWorkerContainerBinding::RegistrationOptions;
use dom::bindings::codegen::Bindings::ServiceWorkerContainerBinding::{ServiceWorkerContainerMethods, Wrap};
+use dom::bindings::codegen::Bindings::ServiceWorkerContainerBinding::RegistrationOptions;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs
index 275fffdb99a..3d26cbdb67f 100644
--- a/components/script/dom/serviceworkerglobalscope.rs
+++ b/components/script/dom/serviceworkerglobalscope.rs
@@ -12,7 +12,6 @@ use dom::bindings::codegen::Bindings::ServiceWorkerGlobalScopeBinding::ServiceWo
use dom::bindings::global::{GlobalRef, global_root_from_context};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root, RootCollection};
-use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
use dom::eventtarget::EventTarget;
@@ -238,9 +237,6 @@ impl ServiceWorkerGlobalScope {
CommonWorker(WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable))) => {
runnable.handler()
},
- CommonWorker(WorkerScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr))) => {
- LiveDOMReferences::cleanup(addr);
- },
CommonWorker(WorkerScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan))) => {
let scope = self.upcast::<WorkerGlobalScope>();
let cx = scope.get_cx();
diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs
index d4d2cbc911a..548dad24dae 100644
--- a/components/script/dom/servohtmlparser.rs
+++ b/components/script/dom/servohtmlparser.rs
@@ -33,9 +33,9 @@ use js::jsapi::JSTracer;
use msg::constellation_msg::{PipelineId, SubpageId};
use net_traits::{AsyncResponseListener, Metadata, NetworkError};
use network_listener::PreInvoke;
-use parse::{TrustedParser, ParserRef, Parser};
+use parse::{Parser, ParserRef, TrustedParser};
+use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType, profile};
use profile_traits::time::ProfilerCategory;
-use profile_traits::time::{profile, TimerMetadata, TimerMetadataReflowType, TimerMetadataFrameType};
use script_thread::ScriptThread;
use std::cell::Cell;
use std::default::Default;
diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs
index d6d1e1968f8..7827cdb6b15 100644
--- a/components/script/dom/storage.rs
+++ b/components/script/dom/storage.rs
@@ -136,10 +136,8 @@ impl StorageMethods for Storage {
}
// check-tidy: no specs after this line
- fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<DOMString> {
- let item = self.GetItem(name);
- *found = item.is_some();
- item
+ fn NamedGetter(&self, name: DOMString) -> Option<DOMString> {
+ self.GetItem(name)
}
fn NamedSetter(&self, name: DOMString, value: DOMString) -> ErrorResult {
diff --git a/components/script/dom/stylesheetlist.rs b/components/script/dom/stylesheetlist.rs
index 1b7eb643e50..721ac06525c 100644
--- a/components/script/dom/stylesheetlist.rs
+++ b/components/script/dom/stylesheetlist.rs
@@ -46,9 +46,7 @@ impl StyleSheetListMethods for StyleSheetList {
}
// check-tidy: no specs after this line
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<StyleSheet>>{
- let item = self.Item(index);
- *found = item.is_some();
- item
+ fn IndexedGetter(&self, index: u32) -> Option<Root<StyleSheet>> {
+ self.Item(index)
}
}
diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs
index 9143c8b0188..b9e34ebe0a7 100644
--- a/components/script/dom/testbinding.rs
+++ b/components/script/dom/testbinding.rs
@@ -4,6 +4,7 @@
// check-tidy: no specs after this line
+use core::nonzero::NonZero;
use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::Bindings::TestBindingBinding;
@@ -11,8 +12,9 @@ use dom::bindings::codegen::Bindings::TestBindingBinding::{TestBindingMethods, T
use dom::bindings::codegen::Bindings::TestBindingBinding::{TestDictionaryDefaults, TestEnum};
use dom::bindings::codegen::UnionTypes::{BlobOrBoolean, BlobOrBlobSequence, LongOrLongSequenceSequence};
use dom::bindings::codegen::UnionTypes::{BlobOrString, BlobOrUnsignedLong, EventOrString};
-use dom::bindings::codegen::UnionTypes::{ByteStringOrLong, ByteStringSequenceOrLongOrString, ByteStringSequenceOrLong};
-use dom::bindings::codegen::UnionTypes::{EventOrUSVString, HTMLElementOrLong};
+use dom::bindings::codegen::UnionTypes::{ByteStringOrLong, ByteStringSequenceOrLongOrString};
+use dom::bindings::codegen::UnionTypes::{ByteStringSequenceOrLong, DocumentOrTestTypedef};
+use dom::bindings::codegen::UnionTypes::{EventOrUSVString, HTMLElementOrLong, LongSequenceOrTestTypedef};
use dom::bindings::codegen::UnionTypes::{HTMLElementOrUnsignedLongOrStringOrBoolean, LongSequenceOrBoolean};
use dom::bindings::codegen::UnionTypes::{StringOrLongSequence, StringOrStringSequence, StringSequenceOrUnsignedLong};
use dom::bindings::codegen::UnionTypes::{StringOrUnsignedLong, StringOrBoolean, UnsignedLongOrBoolean};
@@ -26,6 +28,7 @@ use dom::bindings::weakref::MutableWeakRef;
use dom::blob::{Blob, BlobImpl};
use dom::url::URL;
use js::jsapi::{HandleObject, HandleValue, JSContext, JSObject};
+use js::jsapi::{JS_NewPlainObject, JS_NewUint8ClampedArray};
use js::jsval::{JSVal, NullValue};
use std::borrow::ToOwned;
use std::ptr;
@@ -137,10 +140,24 @@ impl TestBindingMethods for TestBinding {
ByteStringOrLong::ByteString(ByteString::new(vec!()))
}
fn SetUnion9Attribute(&self, _: ByteStringOrLong) {}
- fn ArrayAttribute(&self, _: *mut JSContext) -> *mut JSObject { NullValue().to_object_or_null() }
+ #[allow(unsafe_code)]
+ fn ArrayAttribute(&self, cx: *mut JSContext) -> NonZero<*mut JSObject> {
+ unsafe {
+ rooted!(in(cx) let array = JS_NewUint8ClampedArray(cx, 16));
+ assert!(!array.is_null());
+ NonZero::new(array.get())
+ }
+ }
fn AnyAttribute(&self, _: *mut JSContext) -> JSVal { NullValue() }
fn SetAnyAttribute(&self, _: *mut JSContext, _: HandleValue) {}
- fn ObjectAttribute(&self, _: *mut JSContext) -> *mut JSObject { panic!() }
+ #[allow(unsafe_code)]
+ fn ObjectAttribute(&self, cx: *mut JSContext) -> NonZero<*mut JSObject> {
+ unsafe {
+ rooted!(in(cx) let obj = JS_NewPlainObject(cx));
+ assert!(!obj.is_null());
+ NonZero::new(obj.get())
+ }
+ }
fn SetObjectAttribute(&self, _: *mut JSContext, _: *mut JSObject) {}
fn GetBooleanAttributeNullable(&self) -> Option<bool> { Some(false) }
@@ -193,7 +210,7 @@ impl TestBindingMethods for TestBinding {
fn SetInterfaceAttributeWeak(&self, url: Option<&URL>) {
self.url.set(url);
}
- fn GetObjectAttributeNullable(&self, _: *mut JSContext) -> *mut JSObject { ptr::null_mut() }
+ fn GetObjectAttributeNullable(&self, _: *mut JSContext) -> Option<NonZero<*mut JSObject>> { None }
fn SetObjectAttributeNullable(&self, _: *mut JSContext, _: *mut JSObject) {}
fn GetUnionAttributeNullable(&self) -> Option<HTMLElementOrLong> {
Some(HTMLElementOrLong::Long(0))
@@ -242,7 +259,9 @@ impl TestBindingMethods for TestBinding {
Blob::new(self.global().r(), BlobImpl::new_from_bytes(vec![]), "".to_owned())
}
fn ReceiveAny(&self, _: *mut JSContext) -> JSVal { NullValue() }
- fn ReceiveObject(&self, _: *mut JSContext) -> *mut JSObject { panic!() }
+ fn ReceiveObject(&self, cx: *mut JSContext) -> NonZero<*mut JSObject> {
+ self.ObjectAttribute(cx)
+ }
fn ReceiveUnion(&self) -> HTMLElementOrLong { HTMLElementOrLong::Long(0) }
fn ReceiveUnion2(&self) -> EventOrString { EventOrString::String(DOMString::new()) }
fn ReceiveUnion3(&self) -> StringOrLongSequence { StringOrLongSequence::LongSequence(vec![]) }
@@ -283,7 +302,9 @@ impl TestBindingMethods for TestBinding {
fn ReceiveNullableInterface(&self) -> Option<Root<Blob>> {
Some(Blob::new(self.global().r(), BlobImpl::new_from_bytes(vec![]), "".to_owned()))
}
- fn ReceiveNullableObject(&self, _: *mut JSContext) -> *mut JSObject { ptr::null_mut() }
+ fn ReceiveNullableObject(&self, cx: *mut JSContext) -> Option<NonZero<*mut JSObject>> {
+ self.GetObjectAttributeNullable(cx)
+ }
fn ReceiveNullableUnion(&self) -> Option<HTMLElementOrLong> {
Some(HTMLElementOrLong::Long(0))
}
@@ -401,6 +422,8 @@ impl TestBindingMethods for TestBinding {
fn PassUnion6(&self, _: UnsignedLongOrBoolean) {}
fn PassUnion7(&self, _: StringSequenceOrUnsignedLong) {}
fn PassUnion8(&self, _: ByteStringSequenceOrLong) {}
+ fn PassUnionWithTypedef(&self, _: DocumentOrTestTypedef) {}
+ fn PassUnionWithTypedef2(&self, _: LongSequenceOrTestTypedef) {}
fn PassAny(&self, _: *mut JSContext, _: HandleValue) {}
fn PassObject(&self, _: *mut JSContext, _: *mut JSObject) {}
fn PassCallbackFunction(&self, _: Rc<Function>) {}
diff --git a/components/script/dom/testbindingiterable.rs b/components/script/dom/testbindingiterable.rs
new file mode 100644
index 00000000000..2ad0df6dbb6
--- /dev/null
+++ b/components/script/dom/testbindingiterable.rs
@@ -0,0 +1,41 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// check-tidy: no specs after this line
+
+use dom::bindings::cell::DOMRefCell;
+use dom::bindings::codegen::Bindings::TestBindingIterableBinding::{self, TestBindingIterableMethods};
+use dom::bindings::error::Fallible;
+use dom::bindings::global::GlobalRef;
+use dom::bindings::js::Root;
+use dom::bindings::reflector::{Reflector, reflect_dom_object};
+use dom::bindings::str::DOMString;
+
+#[dom_struct]
+pub struct TestBindingIterable {
+ reflector: Reflector,
+ vals: DOMRefCell<Vec<DOMString>>,
+}
+
+impl TestBindingIterable {
+ fn new(global: GlobalRef) -> Root<TestBindingIterable> {
+ reflect_dom_object(box TestBindingIterable {
+ reflector: Reflector::new(),
+ vals: DOMRefCell::new(vec![]),
+ }, global, TestBindingIterableBinding::Wrap)
+ }
+
+ pub fn Constructor(global: GlobalRef) -> Fallible<Root<TestBindingIterable>> {
+ Ok(TestBindingIterable::new(global))
+ }
+}
+
+impl TestBindingIterableMethods for TestBindingIterable {
+ fn Add(&self, v: DOMString) { self.vals.borrow_mut().push(v); }
+ fn Length(&self) -> u32 { self.vals.borrow().len() as u32 }
+ fn GetItem(&self, n: u32) -> DOMString { self.IndexedGetter(n).unwrap_or_default() }
+ fn IndexedGetter(&self, n: u32) -> Option<DOMString> {
+ self.vals.borrow().get(n as usize).cloned()
+ }
+}
diff --git a/components/script/dom/testbindingpairiterable.rs b/components/script/dom/testbindingpairiterable.rs
new file mode 100644
index 00000000000..9bceedd4980
--- /dev/null
+++ b/components/script/dom/testbindingpairiterable.rs
@@ -0,0 +1,54 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// check-tidy: no specs after this line
+
+use dom::bindings::cell::DOMRefCell;
+use dom::bindings::codegen::Bindings::TestBindingPairIterableBinding;
+use dom::bindings::codegen::Bindings::TestBindingPairIterableBinding::TestBindingPairIterableMethods;
+use dom::bindings::error::Fallible;
+use dom::bindings::global::GlobalRef;
+use dom::bindings::iterable::Iterable;
+use dom::bindings::js::Root;
+use dom::bindings::reflector::{Reflector, reflect_dom_object};
+use dom::bindings::str::DOMString;
+
+#[dom_struct]
+pub struct TestBindingPairIterable {
+ reflector: Reflector,
+ map: DOMRefCell<Vec<(DOMString, u32)>>,
+}
+
+impl Iterable for TestBindingPairIterable {
+ type Key = DOMString;
+ type Value = u32;
+ fn get_iterable_length(&self) -> u32 {
+ self.map.borrow().len() as u32
+ }
+ fn get_value_at_index(&self, index: u32) -> u32 {
+ self.map.borrow().iter().nth(index as usize).map(|a| &a.1).unwrap().clone()
+ }
+ fn get_key_at_index(&self, index: u32) -> DOMString {
+ self.map.borrow().iter().nth(index as usize).map(|a| &a.0).unwrap().clone()
+ }
+}
+
+impl TestBindingPairIterable {
+ fn new(global: GlobalRef) -> Root<TestBindingPairIterable> {
+ reflect_dom_object(box TestBindingPairIterable {
+ reflector: Reflector::new(),
+ map: DOMRefCell::new(vec![]),
+ }, global, TestBindingPairIterableBinding::TestBindingPairIterableWrap)
+ }
+
+ pub fn Constructor(global: GlobalRef) -> Fallible<Root<TestBindingPairIterable>> {
+ Ok(TestBindingPairIterable::new(global))
+ }
+}
+
+impl TestBindingPairIterableMethods for TestBindingPairIterable {
+ fn Add(&self, key: DOMString, value: u32) {
+ self.map.borrow_mut().push((key, value));
+ }
+}
diff --git a/components/script/dom/testbindingproxy.rs b/components/script/dom/testbindingproxy.rs
index 3308639305c..45e66bc5919 100644
--- a/components/script/dom/testbindingproxy.rs
+++ b/components/script/dom/testbindingproxy.rs
@@ -23,10 +23,10 @@ impl TestBindingProxyMethods for TestBindingProxy {
fn SetItem(&self, _: u32, _: DOMString) -> () {}
fn RemoveItem(&self, _: DOMString) -> () {}
fn Stringifier(&self) -> DOMString { DOMString::new() }
- fn IndexedGetter(&self, _: u32, _: &mut bool) -> DOMString { DOMString::new() }
+ fn IndexedGetter(&self, _: u32) -> Option<DOMString> { None }
fn NamedDeleter(&self, _: DOMString) -> () {}
fn IndexedSetter(&self, _: u32, _: DOMString) -> () {}
fn NamedSetter(&self, _: DOMString, _: DOMString) -> () {}
- fn NamedGetter(&self, _: DOMString, _: &mut bool) -> DOMString { DOMString::new() }
+ fn NamedGetter(&self, _: DOMString) -> Option<DOMString> { None }
}
diff --git a/components/script/dom/textencoder.rs b/components/script/dom/textencoder.rs
index 84100e723ba..674243dded8 100644
--- a/components/script/dom/textencoder.rs
+++ b/components/script/dom/textencoder.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use core::nonzero::NonZero;
use dom::bindings::codegen::Bindings::TextEncoderBinding;
use dom::bindings::codegen::Bindings::TextEncoderBinding::TextEncoderMethods;
use dom::bindings::error::{Error, Fallible};
@@ -70,16 +71,17 @@ impl TextEncoderMethods for TextEncoder {
#[allow(unsafe_code)]
// https://encoding.spec.whatwg.org/#dom-textencoder-encode
- fn Encode(&self, cx: *mut JSContext, input: USVString) -> *mut JSObject {
+ fn Encode(&self, cx: *mut JSContext, input: USVString) -> NonZero<*mut JSObject> {
unsafe {
let encoded = self.encoder.encode(&input.0, EncoderTrap::Strict).unwrap();
let length = encoded.len() as u32;
- let js_object: *mut JSObject = JS_NewUint8Array(cx, length);
+ rooted!(in(cx) let js_object = JS_NewUint8Array(cx, length));
+ assert!(!js_object.is_null());
let mut is_shared = false;
- let js_object_data: *mut uint8_t = JS_GetUint8ArrayData(js_object, &mut is_shared, ptr::null());
+ let js_object_data: *mut uint8_t = JS_GetUint8ArrayData(js_object.get(), &mut is_shared, ptr::null());
assert!(!is_shared);
ptr::copy_nonoverlapping(encoded.as_ptr(), js_object_data, length as usize);
- js_object
+ NonZero::new(js_object.get())
}
}
}
diff --git a/components/script/dom/touchlist.rs b/components/script/dom/touchlist.rs
index ae5313e855e..14bb8a68766 100644
--- a/components/script/dom/touchlist.rs
+++ b/components/script/dom/touchlist.rs
@@ -42,9 +42,7 @@ impl TouchListMethods for TouchList {
}
/// https://w3c.github.io/touch-events/#widl-TouchList-item-getter-Touch-unsigned-long-index
- fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Touch>> {
- let item = self.Item(index);
- *found = item.is_some();
- item
+ fn IndexedGetter(&self, index: u32) -> Option<Root<Touch>> {
+ self.Item(index)
}
}
diff --git a/components/script/dom/treewalker.rs b/components/script/dom/treewalker.rs
index 8103421a155..c4097fc761a 100644
--- a/components/script/dom/treewalker.rs
+++ b/components/script/dom/treewalker.rs
@@ -10,8 +10,8 @@ use dom::bindings::codegen::Bindings::TreeWalkerBinding;
use dom::bindings::codegen::Bindings::TreeWalkerBinding::TreeWalkerMethods;
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
-use dom::bindings::js::Root;
use dom::bindings::js::{JS, MutHeap};
+use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::document::Document;
use dom::node::Node;
diff --git a/components/script/dom/uievent.rs b/components/script/dom/uievent.rs
index 16461315ca1..a0f35868662 100644
--- a/components/script/dom/uievent.rs
+++ b/components/script/dom/uievent.rs
@@ -8,8 +8,8 @@ use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
-use dom::bindings::js::Root;
use dom::bindings::js::{JS, MutNullableHeap, RootedReference};
+use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::event::{Event, EventBubbles, EventCancelable};
diff --git a/components/script/dom/url.rs b/components/script/dom/url.rs
index e42b3b7f1cd..bc686d23cc4 100644
--- a/components/script/dom/url.rs
+++ b/components/script/dom/url.rs
@@ -14,13 +14,13 @@ use dom::blob::Blob;
use dom::urlhelper::UrlHelper;
use dom::urlsearchparams::URLSearchParams;
use ipc_channel::ipc;
+use net_traits::{CoreResourceMsg, IpcSend};
use net_traits::blob_url_store::{get_blob_origin, parse_blob_url};
use net_traits::filemanager_thread::FileManagerThreadMsg;
-use net_traits::{IpcSend, CoreResourceMsg};
use std::borrow::ToOwned;
use std::default::Default;
-use url::quirks::domain_to_unicode;
use url::{Host, Url};
+use url::quirks::domain_to_unicode;
use uuid::Uuid;
// https://url.spec.whatwg.org/#url
diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs
index 543a551ee17..9ac3f4e1ad4 100644
--- a/components/script/dom/webglprogram.rs
+++ b/components/script/dom/webglprogram.rs
@@ -87,6 +87,10 @@ impl WebGLProgram {
}
}
+ pub fn is_deleted(&self) -> bool {
+ self.is_deleted.get()
+ }
+
/// glLinkProgram
pub fn link(&self) {
self.linked.set(false);
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index 4db5654d738..3fc63349634 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -3,12 +3,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use canvas_traits::{CanvasCommonMsg, CanvasMsg, byte_swap};
+use core::nonzero::NonZero;
+use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes};
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
-use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes};
use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
use dom::bindings::conversions::{ToJSValConvertible, array_buffer_view_data, array_buffer_view_data_checked};
-use dom::bindings::conversions::{array_buffer_view_to_vec_checked, array_buffer_view_to_vec};
+use dom::bindings::conversions::{array_buffer_view_to_vec, array_buffer_view_to_vec_checked};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root};
@@ -21,7 +22,7 @@ use dom::node::{Node, NodeDamage, window_from_node};
use dom::webgl_validations::WebGLValidator;
use dom::webgl_validations::tex_image_2d::{CommonTexImage2DValidator, CommonTexImage2DValidatorResult};
use dom::webgl_validations::tex_image_2d::{TexImage2DValidator, TexImage2DValidatorResult};
-use dom::webgl_validations::types::{TexFormat, TexImageTarget, TexDataType};
+use dom::webgl_validations::types::{TexDataType, TexFormat, TexImageTarget};
use dom::webglactiveinfo::WebGLActiveInfo;
use dom::webglbuffer::WebGLBuffer;
use dom::webglcontextevent::WebGLContextEvent;
@@ -33,15 +34,15 @@ use dom::webgltexture::{TexParameterValue, WebGLTexture};
use dom::webgluniformlocation::WebGLUniformLocation;
use euclid::size::Size2D;
use ipc_channel::ipc::{self, IpcSender};
-use js::jsapi::{JSContext, JS_GetArrayBufferViewType, JSObject, Type};
+use js::jsapi::{JSContext, JSObject, JS_GetArrayBufferViewType, Type};
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue};
use net_traits::image::base::PixelFormat;
use net_traits::image_cache_thread::ImageResponse;
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use script_traits::ScriptMsg as ConstellationMsg;
use std::cell::Cell;
-use webrender_traits::WebGLError::*;
use webrender_traits::{WebGLCommand, WebGLError, WebGLFramebufferBindingRequest, WebGLParameter};
+use webrender_traits::WebGLError::*;
type ImagePixelResult = Result<(Vec<u8>, Size2D<i32>), ()>;
pub const MAX_UNIFORM_AND_ATTRIBUTE_LEN: usize = 256;
@@ -61,6 +62,38 @@ macro_rules! handle_potential_webgl_error {
};
}
+// From the GLES 2.0.25 spec, page 85:
+//
+// "If a texture that is currently bound to one of the targets
+// TEXTURE_2D, or TEXTURE_CUBE_MAP is deleted, it is as though
+// BindTexture had been executed with the same target and texture
+// zero."
+//
+// and similar text occurs for other object types.
+macro_rules! handle_object_deletion {
+ ($binding:expr, $object:ident) => {
+ if let Some(bound_object) = $binding.get() {
+ if bound_object.id() == $object.id() {
+ $binding.set(None);
+ }
+ }
+ };
+}
+
+macro_rules! object_binding_to_js_or_null {
+ ($cx: expr, $binding:expr) => {
+ {
+ rooted!(in($cx) let mut rval = NullValue());
+ if let Some(bound_object) = $binding.get() {
+ unsafe {
+ bound_object.to_jsval($cx, rval.handle_mut());
+ }
+ }
+ rval.get()
+ }
+ };
+}
+
/// Set of bitflags for texture unpacking (texImage2d, etc...)
bitflags! {
#[derive(HeapSizeOf, JSTraceable)]
@@ -83,6 +116,7 @@ pub struct WebGLRenderingContext {
last_error: Cell<Option<WebGLError>>,
texture_unpacking_settings: Cell<TextureUnpacking>,
bound_framebuffer: MutNullableHeap<JS<WebGLFramebuffer>>,
+ bound_renderbuffer: MutNullableHeap<JS<WebGLRenderbuffer>>,
bound_texture_2d: MutNullableHeap<JS<WebGLTexture>>,
bound_texture_cube_map: MutNullableHeap<JS<WebGLTexture>>,
bound_buffer_array: MutNullableHeap<JS<WebGLBuffer>>,
@@ -117,6 +151,7 @@ impl WebGLRenderingContext {
bound_texture_cube_map: MutNullableHeap::new(None),
bound_buffer_array: MutNullableHeap::new(None),
bound_buffer_element_array: MutNullableHeap::new(None),
+ bound_renderbuffer: MutNullableHeap::new(None),
current_program: MutNullableHeap::new(None),
current_vertex_attrib_0: Cell::new((0f32, 0f32, 0f32, 1f32)),
}
@@ -271,8 +306,7 @@ impl WebGLRenderingContext {
// complexity is worth it.
let (pixels, size) = match source {
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::ImageData(image_data) => {
- let global = self.global();
- (image_data.get_data_array(&global.r()), image_data.get_size())
+ (image_data.get_data_array(), image_data.get_size())
},
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLImageElement(image) => {
let img_url = match image.get_url() {
@@ -513,19 +547,22 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
#[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
fn GetParameter(&self, cx: *mut JSContext, parameter: u32) -> JSVal {
- // Handle the GL_FRAMEBUFFER_BINDING without going all the way
+ // Handle the GL_*_BINDING without going all the way
// to the GL, since we would just need to map back from GL's
- // returned ID to the WebGLFramebuffer we're tracking.
+ // returned ID to the WebGL* object we're tracking.
match parameter {
- constants::FRAMEBUFFER_BINDING => {
- rooted!(in(cx) let mut rval = NullValue());
- if let Some(bound_fb) = self.bound_framebuffer.get() {
- unsafe {
- bound_fb.to_jsval(cx, rval.handle_mut());
- }
- }
- return rval.get()
- }
+ constants::ARRAY_BUFFER_BINDING =>
+ return object_binding_to_js_or_null!(cx, &self.bound_buffer_array),
+ constants::ELEMENT_ARRAY_BUFFER_BINDING =>
+ return object_binding_to_js_or_null!(cx, &self.bound_buffer_element_array),
+ constants::FRAMEBUFFER_BINDING =>
+ return object_binding_to_js_or_null!(cx, &self.bound_framebuffer),
+ constants::RENDERBUFFER_BINDING =>
+ return object_binding_to_js_or_null!(cx, &self.bound_renderbuffer),
+ constants::TEXTURE_BINDING_2D =>
+ return object_binding_to_js_or_null!(cx, &self.bound_texture_2d),
+ constants::TEXTURE_BINDING_CUBE_MAP =>
+ return object_binding_to_js_or_null!(cx, &self.bound_texture_cube_map),
_ => {}
}
@@ -595,8 +632,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.14
- fn GetExtension(&self, _cx: *mut JSContext, _name: DOMString) -> *mut JSObject {
- 0 as *mut JSObject
+ fn GetExtension(&self, _cx: *mut JSContext, _name: DOMString)
+ -> Option<NonZero<*mut JSObject>> {
+ None
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@@ -705,13 +743,19 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidEnum);
}
- if let Some(renderbuffer) = renderbuffer {
- renderbuffer.bind(target)
- } else {
- // Unbind the currently bound renderbuffer
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, None)))
- .unwrap()
+ match renderbuffer {
+ // Implementations differ on what to do in the deleted
+ // case: Chromium currently unbinds, and Gecko silently
+ // returns. The conformance tests don't cover this case.
+ Some(renderbuffer) if !renderbuffer.is_deleted() => {
+ renderbuffer.bind(target)
+ }
+ _ => {
+ // Unbind the currently bound renderbuffer
+ self.ipc_renderer
+ .send(CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, None)))
+ .unwrap()
+ }
}
}
@@ -1095,6 +1139,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
fn DeleteBuffer(&self, buffer: Option<&WebGLBuffer>) {
if let Some(buffer) = buffer {
+ handle_object_deletion!(self.bound_buffer_array, buffer);
+ handle_object_deletion!(self.bound_buffer_element_array, buffer);
buffer.delete()
}
}
@@ -1102,11 +1148,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6
fn DeleteFramebuffer(&self, framebuffer: Option<&WebGLFramebuffer>) {
if let Some(framebuffer) = framebuffer {
- if let Some(bound_fb) = self.bound_framebuffer.get() {
- if bound_fb.id() == framebuffer.id() {
- self.bound_framebuffer.set(None);
- }
- }
+ handle_object_deletion!(self.bound_framebuffer, framebuffer);
framebuffer.delete()
}
}
@@ -1114,6 +1156,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7
fn DeleteRenderbuffer(&self, renderbuffer: Option<&WebGLRenderbuffer>) {
if let Some(renderbuffer) = renderbuffer {
+ handle_object_deletion!(self.bound_renderbuffer, renderbuffer);
renderbuffer.delete()
}
}
@@ -1121,6 +1164,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
fn DeleteTexture(&self, texture: Option<&WebGLTexture>) {
if let Some(texture) = texture {
+ handle_object_deletion!(self.bound_texture_2d, texture);
+ handle_object_deletion!(self.bound_texture_cube_map, texture);
texture.delete()
}
}
@@ -1128,6 +1173,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
fn DeleteProgram(&self, program: Option<&WebGLProgram>) {
if let Some(program) = program {
+ handle_object_deletion!(self.current_program, program);
program.delete()
}
}
@@ -1165,10 +1211,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
fn DrawElements(&self, mode: u32, count: i32, type_: u32, offset: i64) {
+ // From the GLES 2.0.25 spec, page 21:
+ //
+ // "type must be one of UNSIGNED_BYTE or UNSIGNED_SHORT"
let type_size = match type_ {
- constants::BYTE | constants::UNSIGNED_BYTE => 1,
- constants::SHORT | constants::UNSIGNED_SHORT => 2,
- constants::INT | constants::UNSIGNED_INT | constants::FLOAT => 4,
+ constants::UNSIGNED_BYTE => 1,
+ constants::UNSIGNED_SHORT => 2,
_ => return self.webgl_error(InvalidEnum),
};
@@ -1356,6 +1404,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
frame_buffer.map_or(false, |buf| buf.target().is_some() && !buf.is_deleted())
}
+ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
+ fn IsProgram(&self, program: Option<&WebGLProgram>) -> bool {
+ program.map_or(false, |p| !p.is_deleted())
+ }
+
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7
fn IsRenderbuffer(&self, render_buffer: Option<&WebGLRenderbuffer>) -> bool {
render_buffer.map_or(false, |buf| buf.ever_bound() && !buf.is_deleted())
@@ -1479,6 +1532,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4
fn Scissor(&self, x: i32, y: i32, width: i32, height: i32) {
+ if width < 0 || height < 0 {
+ return self.webgl_error(InvalidValue)
+ }
+
self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Scissor(x, y, width, height)))
.unwrap()
@@ -1891,6 +1948,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4
fn Viewport(&self, x: i32, y: i32, width: i32, height: i32) {
+ if width < 0 || height < 0 {
+ return self.webgl_error(InvalidValue)
+ }
+
self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Viewport(x, y, width, height)))
.unwrap()
diff --git a/components/script/dom/webidls/Console.webidl b/components/script/dom/webidls/Console.webidl
index 09273db78b8..90f9bb9f58e 100644
--- a/components/script/dom/webidls/Console.webidl
+++ b/components/script/dom/webidls/Console.webidl
@@ -9,8 +9,10 @@
* © Copyright 2014 Mozilla Foundation.
*/
-[Exposed=(Window,Worker)]
-interface Console {
+[ClassString="Console",
+ Exposed=(Window,Worker),
+ ProtoObjectHack]
+namespace console {
// These should be DOMString message, DOMString message2, ...
void log(DOMString... messages);
void debug(DOMString... messages);
diff --git a/components/script/dom/webidls/HTMLDataElement.webidl b/components/script/dom/webidls/HTMLDataElement.webidl
index be932250678..658f5274491 100644
--- a/components/script/dom/webidls/HTMLDataElement.webidl
+++ b/components/script/dom/webidls/HTMLDataElement.webidl
@@ -4,5 +4,5 @@
// https://html.spec.whatwg.org/multipage/#htmldataelement
interface HTMLDataElement : HTMLElement {
- // attribute DOMString value;
+ attribute DOMString value;
};
diff --git a/components/script/dom/webidls/HTMLDialogElement.webidl b/components/script/dom/webidls/HTMLDialogElement.webidl
index 78a14e1e2a0..0ac76a0465e 100644
--- a/components/script/dom/webidls/HTMLDialogElement.webidl
+++ b/components/script/dom/webidls/HTMLDialogElement.webidl
@@ -8,5 +8,5 @@ interface HTMLDialogElement : HTMLElement {
attribute DOMString returnValue;
//void show(optional (MouseEvent or Element) anchor);
//void showModal(optional (MouseEvent or Element) anchor);
- //void close(optional DOMString returnValue);
+ void close(optional DOMString returnValue);
};
diff --git a/components/script/dom/webidls/HTMLOptionElement.webidl b/components/script/dom/webidls/HTMLOptionElement.webidl
index a5c7c3295da..d4bc5bcdc83 100644
--- a/components/script/dom/webidls/HTMLOptionElement.webidl
+++ b/components/script/dom/webidls/HTMLOptionElement.webidl
@@ -9,7 +9,7 @@
[Exposed=(Window,Worker)]
interface HTMLOptionElement : HTMLElement {
attribute boolean disabled;
- //readonly attribute HTMLFormElement? form;
+ readonly attribute HTMLFormElement? form;
attribute DOMString label;
attribute boolean defaultSelected;
attribute boolean selected;
diff --git a/components/script/dom/webidls/Headers.webidl b/components/script/dom/webidls/Headers.webidl
index 6696bf64731..ee3d4b2fe94 100644
--- a/components/script/dom/webidls/Headers.webidl
+++ b/components/script/dom/webidls/Headers.webidl
@@ -20,5 +20,5 @@ interface Headers {
boolean has(ByteString name);
[Throws]
void set(ByteString name, ByteString value);
- // iterable<ByteString, ByteString>; // TODO see issue #12628
+ iterable<ByteString, ByteString>;
};
diff --git a/components/script/dom/webidls/IterableIterator.webidl b/components/script/dom/webidls/IterableIterator.webidl
new file mode 100644
index 00000000000..d975aa5645d
--- /dev/null
+++ b/components/script/dom/webidls/IterableIterator.webidl
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This interface is entirely internal to Servo, and should not be accessible to
+// web pages.
+
+dictionary IterableKeyOrValueResult {
+ any value;
+ boolean done = false;
+};
+
+dictionary IterableKeyAndValueResult {
+ sequence<any> value;
+ boolean done = false;
+};
diff --git a/components/script/dom/webidls/Navigator.webidl b/components/script/dom/webidls/Navigator.webidl
index 493c4ba34e4..ba24348b7f8 100644
--- a/components/script/dom/webidls/Navigator.webidl
+++ b/components/script/dom/webidls/Navigator.webidl
@@ -14,6 +14,7 @@ Navigator implements NavigatorLanguage;
//Navigator implements NavigatorContentUtils;
//Navigator implements NavigatorStorageUtils;
Navigator implements NavigatorPlugins;
+Navigator implements NavigatorCookies;
// https://html.spec.whatwg.org/multipage/#navigatorid
[NoInterfaceObject, Exposed=(Window,Worker)]
@@ -52,3 +53,9 @@ interface NavigatorPlugins {
[SameObject] readonly attribute MimeTypeArray mimeTypes;
boolean javaEnabled();
};
+
+// https://html.spec.whatwg.org/multipage/#navigatorcookies
+[NoInterfaceObject, Exposed=(Window,Worker)]
+interface NavigatorCookies {
+ readonly attribute boolean cookieEnabled;
+};
diff --git a/components/script/dom/webidls/NodeList.webidl b/components/script/dom/webidls/NodeList.webidl
index e61eae6d6b1..780abc66746 100644
--- a/components/script/dom/webidls/NodeList.webidl
+++ b/components/script/dom/webidls/NodeList.webidl
@@ -12,5 +12,5 @@ interface NodeList {
getter Node? item(unsigned long index);
[Pure]
readonly attribute unsigned long length;
- // iterable<Node>;
+ iterable<Node?>;
};
diff --git a/components/script/dom/webidls/Response.webidl b/components/script/dom/webidls/Response.webidl
new file mode 100644
index 00000000000..2052f5c6371
--- /dev/null
+++ b/components/script/dom/webidls/Response.webidl
@@ -0,0 +1,37 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// https://fetch.spec.whatwg.org/#response-class
+
+// TODO: pass 'optional ResponseBodyInit? body = null' to constructor in place of USVString
+ [Constructor(optional USVString? body = null, optional ResponseInit init),
+ Exposed=(Window,Worker)]
+interface Response {
+ [NewObject] static Response error();
+ [NewObject, Throws] static Response redirect(USVString url, optional unsigned short status = 302);
+
+ readonly attribute ResponseType type;
+
+ readonly attribute USVString url;
+ readonly attribute boolean redirected;
+ readonly attribute unsigned short status;
+ readonly attribute boolean ok;
+ readonly attribute ByteString statusText;
+ [SameObject] readonly attribute Headers headers;
+ // readonly attribute ReadableStream? body;
+ // [SameObject] readonly attribute Promise<Headers> trailer;
+
+ [NewObject, Throws] Response clone();
+};
+Response implements Body;
+
+dictionary ResponseInit {
+ unsigned short status = 200;
+ ByteString statusText = "OK";
+ HeadersInit headers;
+};
+
+enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredirect" };
+
+// typedef (BodyInit or ReadableStream) ResponseBodyInit;
diff --git a/components/script/dom/webidls/TestBinding.webidl b/components/script/dom/webidls/TestBinding.webidl
index 392aee5963b..d98b9428031 100644
--- a/components/script/dom/webidls/TestBinding.webidl
+++ b/components/script/dom/webidls/TestBinding.webidl
@@ -6,6 +6,7 @@
// web pages.
enum TestEnum { "", "foo", "bar" };
+typedef (DOMString or URL or Blob) TestTypedef;
dictionary TestDictionary {
required boolean requiredValue;
@@ -241,6 +242,8 @@ interface TestBinding {
void passUnion6((unsigned long or boolean) bool);
void passUnion7((sequence<DOMString> or unsigned long) arg);
void passUnion8((sequence<ByteString> or long) arg);
+ void passUnionWithTypedef((Document or TestTypedef) arg);
+ void passUnionWithTypedef2((sequence<long> or TestTypedef) arg);
void passAny(any arg);
void passObject(object arg);
void passCallbackFunction(Function fun);
diff --git a/components/script/dom/webidls/TestBindingIterable.webidl b/components/script/dom/webidls/TestBindingIterable.webidl
new file mode 100644
index 00000000000..c9e61074eed
--- /dev/null
+++ b/components/script/dom/webidls/TestBindingIterable.webidl
@@ -0,0 +1,14 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This interface is entirely internal to Servo, and should not be accessible to
+// web pages.
+
+[Pref="dom.testbinding.enabled", Exposed=(Window,Worker), Constructor]
+interface TestBindingIterable {
+ void add(DOMString arg);
+ readonly attribute unsigned long length;
+ getter DOMString getItem(unsigned long index);
+ iterable<DOMString>;
+};
diff --git a/components/script/dom/webidls/TestBindingPairIterable.webidl b/components/script/dom/webidls/TestBindingPairIterable.webidl
new file mode 100644
index 00000000000..a7bc66c1be3
--- /dev/null
+++ b/components/script/dom/webidls/TestBindingPairIterable.webidl
@@ -0,0 +1,12 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This interface is entirely internal to Servo, and should not be accessible to
+// web pages.
+
+[Pref="dom.testbinding.enabled", Exposed=(Window,Worker), Constructor]
+interface TestBindingPairIterable {
+ void add(DOMString key, unsigned long value);
+ iterable<DOMString, unsigned long>;
+};
diff --git a/components/script/dom/webidls/WebGLRenderingContext.webidl b/components/script/dom/webidls/WebGLRenderingContext.webidl
index eea550a5bc0..e95ce00e5e5 100644
--- a/components/script/dom/webidls/WebGLRenderingContext.webidl
+++ b/components/script/dom/webidls/WebGLRenderingContext.webidl
@@ -605,7 +605,7 @@ interface WebGLRenderingContextBase
[WebGLHandlesContextLoss] GLboolean isBuffer(WebGLBuffer? buffer);
//[WebGLHandlesContextLoss] GLboolean isEnabled(GLenum cap);
[WebGLHandlesContextLoss] GLboolean isFramebuffer(WebGLFramebuffer? framebuffer);
- //[WebGLHandlesContextLoss] GLboolean isProgram(WebGLProgram? program);
+ [WebGLHandlesContextLoss] GLboolean isProgram(WebGLProgram? program);
[WebGLHandlesContextLoss] GLboolean isRenderbuffer(WebGLRenderbuffer? renderbuffer);
[WebGLHandlesContextLoss] GLboolean isShader(WebGLShader? shader);
[WebGLHandlesContextLoss] GLboolean isTexture(WebGLTexture? texture);
diff --git a/components/script/dom/webidls/Window.webidl b/components/script/dom/webidls/Window.webidl
index 7057a4541a6..dbe73ca4831 100644
--- a/components/script/dom/webidls/Window.webidl
+++ b/components/script/dom/webidls/Window.webidl
@@ -89,7 +89,7 @@ Window implements WindowBase64;
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#sec-window.performance-attribute
partial interface Window {
- /*[Replaceable]*/ readonly attribute Performance performance;
+ [Replaceable] readonly attribute Performance performance;
};
// https://html.spec.whatwg.org/multipage/#Window-partial
@@ -161,7 +161,6 @@ partial interface Window {
// Proprietary extensions.
partial interface Window {
- readonly attribute Console console;
void debug(DOMString arg);
void gc();
void trap();
diff --git a/components/script/dom/webidls/WorkerGlobalScope.webidl b/components/script/dom/webidls/WorkerGlobalScope.webidl
index ec65bcb09a6..186e5cd7fee 100644
--- a/components/script/dom/webidls/WorkerGlobalScope.webidl
+++ b/components/script/dom/webidls/WorkerGlobalScope.webidl
@@ -9,7 +9,7 @@ interface WorkerGlobalScope : EventTarget {
readonly attribute WorkerLocation location;
//void close();
- // attribute OnErrorEventHandler onerror;
+ attribute OnErrorEventHandler onerror;
// attribute EventHandler onlanguagechange;
// attribute EventHandler onoffline;
// attribute EventHandler ononline;
@@ -24,10 +24,3 @@ partial interface WorkerGlobalScope { // not obsolete
};
WorkerGlobalScope implements WindowTimers;
WorkerGlobalScope implements WindowBase64;
-
-// Proprietary
-[Exposed=Worker]
-partial interface WorkerGlobalScope {
- [Replaceable]
- readonly attribute Console console;
-};
diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs
index 3b3652040e9..df9c2e5ed34 100644
--- a/components/script/dom/websocket.rs
+++ b/components/script/dom/websocket.rs
@@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::{BinaryType, WebSocketMethods};
use dom::bindings::codegen::UnionTypes::StringOrStringSequence;
use dom::bindings::conversions::ToJSValConvertible;
-use dom::bindings::error::{Error, Fallible, ErrorResult};
+use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
@@ -23,18 +23,18 @@ use dom::eventtarget::EventTarget;
use dom::messageevent::MessageEvent;
use dom::urlhelper::UrlHelper;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
-use js::jsapi::JSAutoCompartment;
use js::jsapi::{JS_GetArrayBufferData, JS_NewArrayBuffer};
+use js::jsapi::JSAutoCompartment;
use js::jsval::UndefinedValue;
use libc::{uint32_t, uint8_t};
+use net_traits::{WebSocketCommunicate, WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent};
use net_traits::CookieSource::HTTP;
-use net_traits::CoreResourceMsg::{WebsocketConnect, SetCookiesForUrl};
+use net_traits::CoreResourceMsg::{SetCookiesForUrl, WebsocketConnect};
use net_traits::MessageData;
use net_traits::hosts::replace_hosts;
use net_traits::unwrap_websocket_protocol;
-use net_traits::{WebSocketCommunicate, WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent};
-use script_runtime::ScriptThreadEventCategory::WebSocketEvent;
use script_runtime::{CommonScriptMsg, ScriptChan};
+use script_runtime::ScriptThreadEventCategory::WebSocketEvent;
use script_thread::Runnable;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index e728e38a451..e8006123360 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -12,9 +12,9 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::OnBeforeUnloadEventHa
use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
-use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
use dom::bindings::codegen::Bindings::WindowBinding::{self, FrameRequestCallback, WindowMethods};
-use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception};
+use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
+use dom::bindings::error::{Error, ErrorInfo, ErrorResult, Fallible, report_pending_exception};
use dom::bindings::global::{GlobalRef, global_root_from_object};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root};
@@ -25,12 +25,13 @@ use dom::bindings::str::DOMString;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::utils::{GlobalStaticData, WindowProxyHandler};
use dom::browsingcontext::BrowsingContext;
-use dom::console::Console;
+use dom::console::TimerSet;
use dom::crypto::Crypto;
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
use dom::document::Document;
use dom::element::Element;
-use dom::event::Event;
+use dom::errorevent::ErrorEvent;
+use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
use dom::history::History;
use dom::htmliframeelement::build_mozbrowser_custom_event;
@@ -45,7 +46,7 @@ use euclid::{Point2D, Rect, Size2D};
use gfx_traits::LayerId;
use ipc_channel::ipc::{self, IpcSender};
use js::jsapi::{Evaluate2, HandleObject, HandleValue, JSAutoCompartment, JSContext};
-use js::jsapi::{JS_GetRuntime, JS_GC, MutableHandleValue, SetWindowProxy};
+use js::jsapi::{JS_GC, JS_GetRuntime, MutableHandleValue, SetWindowProxy};
use js::jsval::UndefinedValue;
use js::rust::CompileOptionsWrapper;
use js::rust::Runtime;
@@ -67,13 +68,13 @@ use script_layout_interface::message::{Msg, Reflow, ReflowQueryType, ScriptReflo
use script_layout_interface::reporter::CSSErrorReporter;
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
use script_layout_interface::rpc::{MarginStyleResponse, ResolvedStyleResponse};
-use script_runtime::{ScriptChan, ScriptPort, CommonScriptMsg, ScriptThreadEventCategory, maybe_take_panic_result};
+use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory, maybe_take_panic_result};
+use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, RunnableWrapper};
use script_thread::SendableMainThreadScriptChan;
-use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper, Runnable};
-use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
use script_traits::{ConstellationControlMsg, MozBrowserEvent, UntrustedNodeAddress};
use script_traits::{DocumentState, MsDuration, TimerEvent, TimerEventId};
use script_traits::{ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource, WindowSizeData};
+use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::Cell;
@@ -83,10 +84,10 @@ use std::ffi::CString;
use std::io::{Write, stderr, stdout};
use std::panic;
use std::rc::Rc;
+use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::mpsc::TryRecvError::{Disconnected, Empty};
use std::sync::mpsc::{Sender, channel};
-use std::sync::{Arc, Mutex};
+use std::sync::mpsc::TryRecvError::{Disconnected, Empty};
use string_cache::Atom;
use style::context::ReflowGoal;
use style::error_reporting::ParseErrorReporter;
@@ -156,7 +157,6 @@ pub struct Window {
history_traversal_task_source: HistoryTraversalTaskSource,
#[ignore_heap_size_of = "task sources are hard"]
file_reading_task_source: FileReadingTaskSource,
- console: MutNullableHeap<JS<Console>>,
crypto: MutNullableHeap<JS<Crypto>>,
navigator: MutNullableHeap<JS<Navigator>>,
#[ignore_heap_size_of = "channels are hard"]
@@ -273,6 +273,12 @@ pub struct Window {
/// A list of scroll offsets for each scrollable element.
scroll_offsets: DOMRefCell<HashMap<UntrustedNodeAddress, Point2D<f32>>>,
+
+ /// https://html.spec.whatwg.org/multipage/#in-error-reporting-mode
+ in_error_reporting_mode: Cell<bool>,
+
+ /// Timers used by the Console API.
+ console_timers: TimerSet,
}
impl Window {
@@ -504,11 +510,6 @@ impl WindowMethods for Window {
self.local_storage.or_init(|| Storage::new(&GlobalRef::Window(self), StorageType::Local))
}
- // https://developer.mozilla.org/en-US/docs/Web/API/Console
- fn Console(&self) -> Root<Console> {
- self.console.or_init(|| Console::new(GlobalRef::Window(self)))
- }
-
// https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#dfn-GlobalCrypto
fn Crypto(&self) -> Root<Crypto> {
self.crypto.or_init(|| Crypto::new(GlobalRef::Window(self)))
@@ -946,13 +947,13 @@ impl<'a, T: Reflectable> ScriptHelpers for &'a T {
let filename = CString::new(filename).unwrap();
let _ac = JSAutoCompartment::new(cx, globalhandle.get());
- let options = CompileOptionsWrapper::new(cx, filename.as_ptr(), 0);
+ let options = CompileOptionsWrapper::new(cx, filename.as_ptr(), 1);
unsafe {
if !Evaluate2(cx, options.ptr, code.as_ptr(),
code.len() as libc::size_t,
rval) {
debug!("error evaluating JS string");
- report_pending_exception(cx, globalhandle.get());
+ report_pending_exception(cx, true);
}
}
@@ -1200,9 +1201,11 @@ impl Window {
if !for_display || self.Document().needs_reflow() {
issued_reflow = self.force_reflow(goal, query_type, reason);
- // If window_size is `None`, we don't reflow, so the document stays dirty.
- // Otherwise, we shouldn't need a reflow immediately after a reflow.
+ // If window_size is `None`, we don't reflow, so the document stays
+ // dirty. Otherwise, we shouldn't need a reflow immediately after a
+ // reflow, except if we're waiting for a deferred paint.
assert!(!self.Document().needs_reflow() ||
+ (!for_display && self.Document().needs_paint()) ||
self.window_size.get().is_none() ||
self.suppress_reflow.get());
} else {
@@ -1695,7 +1698,6 @@ impl Window {
history_traversal_task_source: history_task_source,
file_reading_task_source: file_task_source,
image_cache_chan: image_cache_chan,
- console: Default::default(),
crypto: Default::default(),
navigator: Default::default(),
image_cache_thread: image_cache_thread,
@@ -1740,13 +1742,49 @@ impl Window {
ignore_further_async_events: Arc::new(AtomicBool::new(false)),
error_reporter: error_reporter,
scroll_offsets: DOMRefCell::new(HashMap::new()),
+ in_error_reporting_mode: Cell::new(false),
+ console_timers: TimerSet::new(),
};
WindowBinding::Wrap(runtime.cx(), win)
}
+
+ pub fn console_timers(&self) -> &TimerSet {
+ &self.console_timers
+ }
+
pub fn live_devtools_updates(&self) -> bool {
return self.devtools_wants_updates.get();
}
+
+ /// https://html.spec.whatwg.org/multipage/#report-the-error
+ pub fn report_an_error(&self, error_info: ErrorInfo, value: HandleValue) {
+ // Step 1.
+ if self.in_error_reporting_mode.get() {
+ return;
+ }
+
+ // Step 2.
+ self.in_error_reporting_mode.set(true);
+
+ // Steps 3-12.
+ // FIXME(#13195): muted errors.
+ let event = ErrorEvent::new(GlobalRef::Window(self),
+ atom!("error"),
+ EventBubbles::DoesNotBubble,
+ EventCancelable::Cancelable,
+ error_info.message.into(),
+ error_info.filename.into(),
+ error_info.lineno,
+ error_info.column,
+ value);
+
+ // Step 13.
+ event.upcast::<Event>().fire(self.upcast::<EventTarget>());
+
+ // Step 14.
+ self.in_error_reporting_mode.set(false);
+ }
}
fn should_move_clip_rect(clip_rect: Rect<Au>, new_viewport: Rect<f32>) -> bool {
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs
index c1ad7cf5a96..e40ebee24f0 100644
--- a/components/script/dom/worker.rs
+++ b/components/script/dom/worker.rs
@@ -2,13 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolsPageInfo};
+use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg};
+use dom::abstractworker::{SharedRt, SimpleWorkerErrorHandler};
use dom::abstractworker::WorkerScriptMsg;
-use dom::abstractworker::{SimpleWorkerErrorHandler, SharedRt, WorkerErrorHandler};
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::WorkerBinding;
use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
-use dom::bindings::error::{Error, ErrorResult, Fallible};
+use dom::bindings::error::{Error, ErrorResult, Fallible, ErrorInfo};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
@@ -23,14 +23,14 @@ use dom::eventtarget::EventTarget;
use dom::messageevent::MessageEvent;
use dom::workerglobalscope::prepare_workerscope_init;
use ipc_channel::ipc;
-use js::jsapi::{HandleValue, JSContext, JSAutoCompartment};
+use js::jsapi::{HandleValue, JSAutoCompartment, JSContext, NullHandleValue};
use js::jsval::UndefinedValue;
use script_thread::Runnable;
use script_traits::WorkerScriptLoadOrigin;
use std::cell::Cell;
+use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Sender, channel};
-use std::sync::{Arc, Mutex};
pub type TrustedWorkerAddress = Trusted<Worker>;
@@ -140,20 +140,24 @@ impl Worker {
worker.upcast().fire_simple_event("error");
}
- pub fn handle_error_message(address: TrustedWorkerAddress, message: DOMString,
- filename: DOMString, lineno: u32, colno: u32) {
- let worker = address.root();
-
- if worker.is_terminated() {
+ fn dispatch_error(&self, error_info: ErrorInfo) {
+ let global = self.global();
+ let event = ErrorEvent::new(global.r(),
+ atom!("error"),
+ EventBubbles::DoesNotBubble,
+ EventCancelable::Cancelable,
+ error_info.message.as_str().into(),
+ error_info.filename.as_str().into(),
+ error_info.lineno,
+ error_info.column,
+ NullHandleValue);
+
+ let handled = !event.upcast::<Event>().fire(self.upcast::<EventTarget>());
+ if handled {
return;
}
- let global = worker.r().global();
- rooted!(in(global.r().get_cx()) let error = UndefinedValue());
- let errorevent = ErrorEvent::new(global.r(), atom!("error"),
- EventBubbles::Bubbles, EventCancelable::Cancelable,
- message, filename, lineno, colno, error.handle());
- errorevent.upcast::<Event>().fire(worker.upcast());
+ global.r().report_an_error(error_info, NullHandleValue);
}
}
@@ -221,10 +225,23 @@ impl Runnable for SimpleWorkerErrorHandler<Worker> {
}
}
-impl Runnable for WorkerErrorHandler<Worker> {
- #[allow(unrooted_must_root)]
- fn handler(self: Box<WorkerErrorHandler<Worker>>) {
+pub struct WorkerErrorHandler {
+ address: Trusted<Worker>,
+ error_info: ErrorInfo,
+}
+
+impl WorkerErrorHandler {
+ pub fn new(address: Trusted<Worker>, error_info: ErrorInfo) -> WorkerErrorHandler {
+ WorkerErrorHandler {
+ address: address,
+ error_info: error_info,
+ }
+ }
+}
+
+impl Runnable for WorkerErrorHandler {
+ fn handler(self: Box<Self>) {
let this = *self;
- Worker::handle_error_message(this.addr, this.msg, this.file_name, this.line_num, this.col_num);
+ this.address.root().dispatch_error(this.error_info);
}
}
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index 16388d54d73..1c2c46fb52d 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -3,15 +3,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
+use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
-use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception};
+use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception, ErrorInfo};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
-use dom::console::Console;
+use dom::console::TimerSet;
use dom::crypto::Crypto;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::eventtarget::EventTarget;
@@ -20,18 +21,18 @@ use dom::window::{base64_atob, base64_btoa};
use dom::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator;
use ipc_channel::ipc::IpcSender;
-use js::jsapi::{HandleValue, JSContext, JSRuntime};
+use js::jsapi::{HandleValue, JSAutoCompartment, JSContext, JSRuntime};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
+use net_traits::{IpcSend, LoadOrigin};
use net_traits::{LoadContext, ResourceThreads, load_whole_resource};
-use net_traits::{LoadOrigin, IpcSend};
use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, maybe_take_panic_result};
use script_thread::RunnableWrapper;
+use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
use script_traits::ScriptMsg as ConstellationMsg;
use script_traits::WorkerGlobalScopeInit;
-use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
use std::cell::Cell;
use std::default::Default;
use std::panic;
@@ -79,7 +80,6 @@ pub struct WorkerGlobalScope {
resource_threads: ResourceThreads,
location: MutNullableHeap<JS<WorkerLocation>>,
navigator: MutNullableHeap<JS<WorkerNavigator>>,
- console: MutNullableHeap<JS<Console>>,
crypto: MutNullableHeap<JS<Crypto>>,
timers: OneshotTimers,
@@ -109,6 +109,9 @@ pub struct WorkerGlobalScope {
#[ignore_heap_size_of = "Defined in std"]
scheduler_chan: IpcSender<TimerEventRequest>,
+
+ /// Timers used by the Console API.
+ console_timers: TimerSet,
}
impl WorkerGlobalScope {
@@ -129,7 +132,6 @@ impl WorkerGlobalScope {
resource_threads: init.resource_threads,
location: Default::default(),
navigator: Default::default(),
- console: Default::default(),
crypto: Default::default(),
timers: OneshotTimers::new(timer_event_chan, init.scheduler_chan.clone()),
mem_profiler_chan: init.mem_profiler_chan,
@@ -140,9 +142,14 @@ impl WorkerGlobalScope {
devtools_wants_updates: Cell::new(false),
constellation_chan: init.constellation_chan,
scheduler_chan: init.scheduler_chan,
+ console_timers: TimerSet::new(),
}
}
+ pub fn console_timers(&self) -> &TimerSet {
+ &self.console_timers
+ }
+
pub fn mem_profiler_chan(&self) -> &mem::ProfilerChan {
&self.mem_profiler_chan
}
@@ -248,6 +255,9 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
})
}
+ // https://html.spec.whatwg.org/multipage/#handler-workerglobalscope-onerror
+ error_event_handler!(error, GetOnerror, SetOnerror);
+
// https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-importscripts
fn ImportScripts(&self, url_strings: Vec<DOMString>) -> ErrorResult {
let mut urls = Vec::with_capacity(url_strings.len());
@@ -295,11 +305,6 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
self.navigator.or_init(|| WorkerNavigator::new(self))
}
- // https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/console
- fn Console(&self) -> Root<Console> {
- self.console.or_init(|| Console::new(GlobalRef::Worker(self)))
- }
-
// https://html.spec.whatwg.org/multipage/#dfn-Crypto
fn Crypto(&self) -> Root<Crypto> {
self.crypto.or_init(|| Crypto::new(GlobalRef::Worker(self)))
@@ -382,8 +387,9 @@ impl WorkerGlobalScope {
// https://github.com/servo/servo/issues/6422
println!("evaluate_script failed");
unsafe {
- report_pending_exception(
- self.runtime.cx(), self.reflector().get_jsobject().get());
+ let _ac = JSAutoCompartment::new(self.runtime.cx(),
+ self.reflector().get_jsobject().get());
+ report_pending_exception(self.runtime.cx(), true);
}
}
}
@@ -450,4 +456,11 @@ impl WorkerGlobalScope {
closing.store(true, Ordering::SeqCst);
}
}
+
+ /// https://html.spec.whatwg.org/multipage/#report-the-error
+ pub fn report_an_error(&self, error_info: ErrorInfo, value: HandleValue) {
+ self.downcast::<DedicatedWorkerGlobalScope>()
+ .expect("Should implement report_an_error for this worker")
+ .report_an_error(error_info, value);
+ }
}
diff --git a/components/script/dom/xmldocument.rs b/components/script/dom/xmldocument.rs
index 5f6b6e1919c..1a00f67b80c 100644
--- a/components/script/dom/xmldocument.rs
+++ b/components/script/dom/xmldocument.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use core::nonzero::NonZero;
use document_loader::DocumentLoader;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::XMLDocumentBinding::{self, XMLDocumentMethods};
@@ -87,7 +88,7 @@ impl XMLDocumentMethods for XMLDocument {
}
// https://html.spec.whatwg.org/multipage/#dom-tree-accessors:dom-document-nameditem-filter
- fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString, found: &mut bool) -> *mut JSObject {
- self.upcast::<Document>().NamedGetter(_cx, name, found)
+ fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString) -> Option<NonZero<*mut JSObject>> {
+ self.upcast::<Document>().NamedGetter(_cx, name)
}
}
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 382e4c69faa..a97dc7f802b 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -21,8 +21,8 @@ use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::{ByteString, DOMString, USVString, is_token};
use dom::blob::{Blob, BlobImpl};
-use dom::document::DocumentSource;
use dom::document::{Document, IsHTMLDocument};
+use dom::document::DocumentSource;
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
use dom::headers::is_forbidden_header_name;
@@ -34,23 +34,22 @@ use encoding::all::UTF_8;
use encoding::label::encoding_from_whatwg_label;
use encoding::types::{DecoderTrap, EncoderTrap, Encoding, EncodingRef};
use euclid::length::Length;
-use hyper::header::Headers;
use hyper::header::{ContentLength, ContentType};
-use hyper::http::RawStatus;
+use hyper::header::Headers;
use hyper::method::Method;
-use hyper::mime::{self, Mime, Attr as MimeAttr, Value as MimeValue};
+use hyper::mime::{self, Attr as MimeAttr, Mime, Value as MimeValue};
use hyper_serde::Serde;
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
-use js::jsapi::JS_ClearPendingException;
use js::jsapi::{JSContext, JS_ParseJSON};
+use js::jsapi::JS_ClearPendingException;
use js::jsval::{JSVal, NullValue, UndefinedValue};
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
+use net_traits::{CoreResourceThread, LoadOrigin};
+use net_traits::{FetchResponseListener, Metadata, NetworkError};
use net_traits::CoreResourceMsg::Fetch;
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
use net_traits::trim_http_whitespace;
-use net_traits::{CoreResourceThread, LoadOrigin};
-use net_traits::{FetchResponseListener, Metadata, NetworkError};
use network_listener::{NetworkListener, PreInvoke};
use parse::html::{ParseContext, parse_html};
use parse::xml::{self, parse_xml};
@@ -64,7 +63,7 @@ use std::sync::{Arc, Mutex};
use string_cache::Atom;
use time;
use timers::{OneshotTimerCallback, OneshotTimerHandle};
-use url::{Url, Position};
+use url::{Position, Url};
use util::prefs::PREFS;
#[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf)]
@@ -91,7 +90,7 @@ struct XHRContext {
#[derive(Clone)]
pub enum XHRProgress {
/// Notify that headers have been received
- HeadersReceived(GenerationId, Option<Headers>, Option<RawStatus>),
+ HeadersReceived(GenerationId, Option<Headers>, Option<(u16, Vec<u8>)>),
/// Partial progress (after receiving headers), containing portion of the response
Loading(GenerationId, ByteString),
/// Loading is done
@@ -879,7 +878,7 @@ impl XMLHttpRequest {
self.process_partial_response(XHRProgress::HeadersReceived(
gen_id,
metadata.headers.map(Serde::into_inner),
- metadata.status.map(Serde::into_inner)));
+ metadata.status));
Ok(())
}
@@ -943,9 +942,9 @@ impl XMLHttpRequest {
// Part of step 13, send() (processing response)
// XXXManishearth handle errors, if any (substep 1)
// Substep 2
- status.map(|RawStatus(code, reason)| {
+ status.map(|(code, reason)| {
self.status.set(code);
- *self.status_text.borrow_mut() = ByteString::new(reason.into_owned().into_bytes());
+ *self.status_text.borrow_mut() = ByteString::new(reason);
});
headers.as_ref().map(|h| *self.response_headers.borrow_mut() = h.clone());
@@ -1236,8 +1235,8 @@ impl XMLHttpRequest {
fn filter_response_headers(&self) -> Headers {
// https://fetch.spec.whatwg.org/#concept-response-header-list
use hyper::error::Result;
- use hyper::header::SetCookie;
use hyper::header::{Header, HeaderFormat};
+ use hyper::header::SetCookie;
use std::fmt;
// a dummy header so we can use headers.remove::<SetCookie2>()
diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs
index b4e54fe5bd9..5411deb91a8 100644
--- a/components/script/layout_wrapper.rs
+++ b/components/script/layout_wrapper.rs
@@ -36,34 +36,34 @@ use dom::bindings::js::LayoutJS;
use dom::characterdata::LayoutCharacterDataHelpers;
use dom::document::{Document, LayoutDocumentHelpers};
use dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
-use dom::node::{CAN_BE_FRAGMENTED, HAS_CHANGED, HAS_DIRTY_DESCENDANTS, IS_DIRTY, DIRTY_ON_VIEWPORT_SIZE_CHANGE};
-use dom::node::{Node, LayoutNodeHelpers};
+use dom::node::{CAN_BE_FRAGMENTED, DIRTY_ON_VIEWPORT_SIZE_CHANGE, HAS_CHANGED, HAS_DIRTY_DESCENDANTS, IS_DIRTY};
+use dom::node::{LayoutNodeHelpers, Node};
use dom::text::Text;
use gfx_traits::ByteIndex;
use msg::constellation_msg::PipelineId;
use range::Range;
-use script_layout_interface::restyle_damage::RestyleDamage;
-use script_layout_interface::wrapper_traits::{DangerousThreadSafeLayoutNode, LayoutNode, PseudoElementType};
-use script_layout_interface::wrapper_traits::{ThreadSafeLayoutNode, ThreadSafeLayoutElement};
use script_layout_interface::{HTMLCanvasData, LayoutNodeType, TrustedNodeAddress};
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialStyleAndLayoutData};
+use script_layout_interface::restyle_damage::RestyleDamage;
+use script_layout_interface::wrapper_traits::{DangerousThreadSafeLayoutNode, LayoutNode, PseudoElementType};
+use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use selectors::matching::ElementFlags;
use selectors::parser::{AttrSelector, NamespaceConstraint};
use std::fmt;
use std::marker::PhantomData;
-use std::mem::{transmute, transmute_copy};
+use std::mem::transmute;
use std::sync::Arc;
use string_cache::{Atom, Namespace};
use style::attr::AttrValue;
use style::computed_values::display;
use style::context::SharedStyleContext;
use style::data::PrivateStyleData;
-use style::dom::{PresentationalHintsSynthetizer, OpaqueNode, TDocument, TElement, TNode, UnsafeNode};
+use style::dom::{OpaqueNode, PresentationalHintsSynthetizer, TDocument, TElement, TNode, UnsafeNode};
use style::element_state::*;
use style::properties::{ComputedValues, PropertyDeclarationBlock};
use style::refcell::{Ref, RefCell, RefMut};
use style::selector_impl::{ElementSnapshot, NonTSPseudoClass, PseudoElement, ServoSelectorImpl};
-use style::selector_matching::DeclarationBlock;
+use style::selector_matching::ApplicableDeclarationBlock;
use style::sink::Push;
use style::str::is_whitespace;
use url::Url;
@@ -115,11 +115,11 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
type ConcreteElement = ServoLayoutElement<'ln>;
type ConcreteDocument = ServoLayoutDocument<'ln>;
type ConcreteRestyleDamage = RestyleDamage;
+ type ConcreteChildrenIterator = ServoChildrenIterator<'ln>;
fn to_unsafe(&self) -> UnsafeNode {
unsafe {
- let ptr: usize = transmute_copy(self);
- (ptr, 0)
+ (self.node.unsafe_get() as usize, 0)
}
}
@@ -147,6 +147,12 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
self.dump_style_indent(0);
}
+ fn children(self) -> ServoChildrenIterator<'ln> {
+ ServoChildrenIterator {
+ current: self.first_child(),
+ }
+ }
+
fn opaque(&self) -> OpaqueNode {
unsafe { self.get_jsmanaged().opaque() }
}
@@ -163,10 +169,6 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
self.opaque().0
}
- fn children_count(&self) -> u32 {
- unsafe { self.node.children_count() }
- }
-
fn as_element(&self) -> Option<ServoLayoutElement<'ln>> {
as_element(self.node)
}
@@ -280,6 +282,19 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
}
}
+pub struct ServoChildrenIterator<'a> {
+ current: Option<ServoLayoutNode<'a>>,
+}
+
+impl<'a> Iterator for ServoChildrenIterator<'a> {
+ type Item = ServoLayoutNode<'a>;
+ fn next(&mut self) -> Option<ServoLayoutNode<'a>> {
+ let node = self.current;
+ self.current = node.and_then(|node| node.next_sibling());
+ node
+ }
+}
+
impl<'ln> LayoutNode for ServoLayoutNode<'ln> {
type ConcreteThreadSafeLayoutNode = ServoThreadSafeLayoutNode<'ln>;
@@ -389,6 +404,14 @@ impl<'ld> TDocument for ServoLayoutDocument<'ld> {
let elements = unsafe { self.document.drain_modified_elements() };
elements.into_iter().map(|(el, snapshot)| (ServoLayoutElement::from_layout_js(el), snapshot)).collect()
}
+
+ fn needs_paint_from_layout(&self) {
+ unsafe { self.document.needs_paint_from_layout(); }
+ }
+
+ fn will_paint(&self) {
+ unsafe { self.document.will_paint(); }
+ }
}
impl<'ld> ServoLayoutDocument<'ld> {
@@ -419,7 +442,7 @@ impl<'le> fmt::Debug for ServoLayoutElement<'le> {
impl<'le> PresentationalHintsSynthetizer for ServoLayoutElement<'le> {
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
- where V: Push<DeclarationBlock>
+ where V: Push<ApplicableDeclarationBlock>
{
unsafe {
self.element.synthesize_presentational_hints_for_legacy_attributes(hints);
@@ -435,9 +458,9 @@ impl<'le> TElement for ServoLayoutElement<'le> {
ServoLayoutNode::from_layout_js(self.element.upcast())
}
- fn style_attribute(&self) -> &Option<PropertyDeclarationBlock> {
+ fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
unsafe {
- &*self.element.style_attribute()
+ (*self.element.style_attribute()).as_ref()
}
}
@@ -1071,5 +1094,5 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
impl<'le> PresentationalHintsSynthetizer for ServoThreadSafeLayoutElement<'le> {
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
- where V: Push<DeclarationBlock> {}
+ where V: Push<ApplicableDeclarationBlock> {}
}
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 0f28a2b065c..840e078d93f 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -17,7 +17,6 @@
#![feature(slice_patterns)]
#![feature(stmt_expr_attributes)]
#![feature(question_mark)]
-#![feature(try_borrow)]
#![feature(try_from)]
#![deny(unsafe_code)]
@@ -31,6 +30,7 @@
extern crate angle;
extern crate app_units;
+extern crate audio_video_metadata;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate bitflags;
@@ -69,7 +69,6 @@ extern crate phf;
extern crate profile_traits;
extern crate rand;
extern crate range;
-extern crate ref_filter_map;
extern crate ref_slice;
extern crate regex;
extern crate rustc_serialize;
@@ -114,10 +113,10 @@ mod unpremultiplytable;
mod webdriver_handlers;
use dom::bindings::codegen::RegisterBindings;
-use js::jsapi::{Handle, JSContext, JSObject, SetDOMProxyInformation};
+use dom::bindings::proxyhandler;
+use js::jsapi::{Handle, JSContext, JSObject};
use script_traits::SWManagerSenders;
use serviceworker_manager::ServiceWorkerManager;
-use std::ptr;
use util::opts;
#[cfg(target_os = "linux")]
@@ -164,7 +163,7 @@ fn perform_platform_specific_initialization() {}
#[allow(unsafe_code)]
pub fn init(sw_senders: SWManagerSenders) {
unsafe {
- SetDOMProxyInformation(ptr::null(), 0, Some(script_thread::shadow_check_callback));
+ proxyhandler::init();
}
// Spawn the service worker manager passing the constellation sender
diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs
index 1dd0d8f0a34..4ff65bf8073 100644
--- a/components/script/network_listener.rs
+++ b/components/script/network_listener.rs
@@ -4,8 +4,8 @@
use net_traits::{Action, AsyncResponseListener, FetchResponseListener};
use net_traits::{FetchResponseMsg, ResponseAction};
-use script_runtime::ScriptThreadEventCategory::NetworkEvent;
use script_runtime::{CommonScriptMsg, ScriptChan};
+use script_runtime::ScriptThreadEventCategory::NetworkEvent;
use script_thread::{Runnable, RunnableWrapper};
use std::sync::{Arc, Mutex};
diff --git a/components/script/origin.rs b/components/script/origin.rs
index 9b0ba7738e2..21204980e26 100644
--- a/components/script/origin.rs
+++ b/components/script/origin.rs
@@ -3,8 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::sync::Arc;
+use url::{Host, Url};
use url::Origin as UrlOrigin;
-use url::{Url, Host};
/// A representation of an [origin](https://html.spec.whatwg.org/multipage/#origin-2).
#[derive(HeapSizeOf, JSTraceable)]
diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs
index 659772b851b..39684bd1b3e 100644
--- a/components/script/parse/html.rs
+++ b/components/script/parse/html.rs
@@ -13,23 +13,23 @@ use dom::bindings::js::{JS, RootedReference};
use dom::bindings::str::DOMString;
use dom::characterdata::CharacterData;
use dom::comment::Comment;
-use dom::document::Document;
use dom::document::{DocumentSource, IsHTMLDocument};
+use dom::document::Document;
use dom::documenttype::DocumentType;
use dom::element::{Element, ElementCreator};
use dom::htmlformelement::HTMLFormElement;
use dom::htmlscriptelement::HTMLScriptElement;
use dom::htmltemplateelement::HTMLTemplateElement;
-use dom::node::Node;
use dom::node::{document_from_node, window_from_node};
+use dom::node::Node;
use dom::processinginstruction::ProcessingInstruction;
use dom::servohtmlparser;
use dom::servohtmlparser::{FragmentContext, ServoHTMLParser};
use dom::text::Text;
use html5ever::Attribute;
+use html5ever::serialize::{AttrRef, Serializable, Serializer};
use html5ever::serialize::TraversalScope;
use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
-use html5ever::serialize::{AttrRef, Serializable, Serializer};
use html5ever::tendril::StrTendril;
use html5ever::tree_builder::{NextParserState, NodeOrText, QuirksMode, TreeSink};
use msg::constellation_msg::PipelineId;
diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs
index b16ca804f5c..124bf8f2b84 100644
--- a/components/script/script_runtime.rs
+++ b/components/script/script_runtime.rs
@@ -6,7 +6,7 @@
//! script thread, the dom, and the worker threads.
use dom::bindings::js::{RootCollection, RootCollectionPtr, trace_roots};
-use dom::bindings::refcounted::{LiveDOMReferences, TrustedReference, trace_refcounted_objects};
+use dom::bindings::refcounted::{LiveDOMReferences, trace_refcounted_objects};
use dom::bindings::trace::trace_traceables;
use dom::bindings::utils::DOM_CALLBACKS;
use js::glue::CollectServoSizes;
@@ -35,8 +35,6 @@ pub enum CommonScriptMsg {
/// Requests that the script thread measure its memory usage. The results are sent back via the
/// supplied channel.
CollectReports(ReportsChan),
- /// A DOM object's last pinned reference was removed (dispatched to all threads).
- RefcountCleanup(TrustedReference),
/// Generic message that encapsulates event handling.
RunnableMsg(ScriptThreadEventCategory, Box<Runnable + Send>),
}
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 4834218a89b..d69124b5d07 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -18,20 +18,20 @@
//! loop.
use devtools;
-use devtools_traits::CSSError;
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
+use devtools_traits::CSSError;
use document_loader::DocumentLoader;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
-use dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior};
+use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root, RootCollection};
use dom::bindings::js::{RootCollectionPtr, RootedReference};
-use dom::bindings::refcounted::{LiveDOMReferences, Trusted};
+use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
use dom::bindings::trace::JSTraceable;
@@ -52,25 +52,24 @@ use euclid::Rect;
use euclid::point::Point2D;
use gfx_traits::LayerId;
use hyper::header::{ContentType, Headers, HttpDate, LastModified};
-use hyper::header::{ReferrerPolicy as ReferrerPolicyHeader};
+use hyper::header::ReferrerPolicy as ReferrerPolicyHeader;
use hyper::method::Method;
use hyper::mime::{Mime, SubLevel, TopLevel};
use hyper_serde::Serde;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use js::glue::GetWindowProxyClass;
-use js::jsapi::{DOMProxyShadowsResult, HandleId, HandleObject};
use js::jsapi::{JSAutoCompartment, JSContext, JS_SetWrapObjectCallbacks};
use js::jsapi::{JSTracer, SetWindowProxyClass};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use mem::heap_size_of_self_and_children;
use msg::constellation_msg::{FrameType, LoadData, PipelineId, PipelineNamespace};
-use msg::constellation_msg::{SubpageId, WindowSizeType, ReferrerPolicy};
-use net_traits::bluetooth_thread::BluetoothMethodMsg;
-use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
+use msg::constellation_msg::{ReferrerPolicy, SubpageId, WindowSizeType};
use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata, ResourceThreads};
use net_traits::{IpcSend, LoadData as NetLoadData};
+use net_traits::bluetooth_thread::BluetoothMethodMsg;
+use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
use network_listener::NetworkListener;
use parse::ParserRoot;
use parse::html::{ParseContext, parse_html};
@@ -79,15 +78,15 @@ use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
use profile_traits::time::{self, ProfilerCategory, profile};
use script_layout_interface::message::{self, NewLayoutThreadInfo, ReflowQueryType};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
-use script_runtime::{ScriptPort, StackRootTLS, new_rt_and_cx, get_reports};
-use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
-use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent};
-use script_traits::webdriver_msg::WebDriverScriptCommand;
+use script_runtime::{ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
use script_traits::{CompositorEvent, ConstellationControlMsg, EventResult};
use script_traits::{InitialScriptState, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg};
use script_traits::{ScriptThreadFactory, TimerEvent, TimerEventRequest, TimerSource};
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData};
+use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
+use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent};
+use script_traits::webdriver_msg::WebDriverScriptCommand;
use std::borrow::ToOwned;
use std::cell::Cell;
use std::collections::{HashMap, HashSet};
@@ -95,19 +94,19 @@ use std::option::Option;
use std::ptr;
use std::rc::Rc;
use std::result::Result;
-use std::sync::atomic::{Ordering, AtomicBool};
-use std::sync::mpsc::{Receiver, Select, Sender, channel};
use std::sync::{Arc, Mutex};
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::mpsc::{Receiver, Select, Sender, channel};
use style::context::ReflowGoal;
use style::thread_state;
use task_source::TaskSource;
-use task_source::dom_manipulation::{DOMManipulationTaskSource, DOMManipulationTask};
+use task_source::dom_manipulation::{DOMManipulationTask, DOMManipulationTaskSource};
use task_source::file_reading::FileReadingTaskSource;
use task_source::history_traversal::HistoryTraversalTaskSource;
use task_source::networking::NetworkingTaskSource;
-use task_source::user_interaction::{UserInteractionTaskSource, UserInteractionTask};
+use task_source::user_interaction::{UserInteractionTask, UserInteractionTaskSource};
use time::Tm;
-use url::{Url, Position};
+use url::{Position, Url};
use util::opts;
use util::thread;
use webdriver_handlers;
@@ -484,12 +483,6 @@ impl ScriptThreadFactory for ScriptThread {
}
}
-pub unsafe extern "C" fn shadow_check_callback(_cx: *mut JSContext,
- _object: HandleObject, _id: HandleId) -> DOMProxyShadowsResult {
- // XXX implement me
- DOMProxyShadowsResult::ShadowCheckFailed
-}
-
impl ScriptThread {
pub fn page_headers_available(id: &PipelineId, subpage: Option<&SubpageId>, metadata: Option<Metadata>)
-> Option<ParserRoot> {
@@ -955,8 +948,6 @@ impl ScriptThread {
runnable.handler()
}
}
- MainThreadScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) =>
- LiveDOMReferences::cleanup(addr),
MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) =>
self.collect_reports(reports_chan),
MainThreadScriptMsg::DOMManipulation(task) =>
@@ -1789,7 +1780,10 @@ impl ScriptThread {
let strval = DOMString::from_jsval(self.get_cx(),
jsval.handle(),
StringificationBehavior::Empty);
- strval.unwrap_or(DOMString::new())
+ match strval {
+ Ok(ConversionResult::Success(s)) => s,
+ _ => DOMString::new(),
+ }
}
} else {
DOMString::new()
@@ -2205,7 +2199,7 @@ fn shut_down_layout(context_tree: &BrowsingContext) {
let chan = window.layout_chan().clone();
if chan.send(message::Msg::PrepareToExit(response_chan)).is_ok() {
channels.push(chan);
- response_port.recv().unwrap();
+ let _ = response_port.recv();
}
}
diff --git a/components/script/serviceworker_manager.rs b/components/script/serviceworker_manager.rs
index 1c24c6fef3f..09f5288929a 100644
--- a/components/script/serviceworker_manager.rs
+++ b/components/script/serviceworker_manager.rs
@@ -72,7 +72,7 @@ impl ServiceWorkerManager {
}
}
- if let Some(ref scope_url) = scope_url {
+ if let Some(scope_url) = scope_url {
if self.active_workers.contains_key(&scope_url) {
// do not run the same worker if already active.
warn!("Service worker for {:?} already active", scope_url);
@@ -100,7 +100,7 @@ impl ServiceWorkerManager {
self.own_sender.clone(),
scope_url.clone());
// We store the activated worker
- self.active_workers.insert(scope_url.clone(), scope_things.clone());
+ self.active_workers.insert(scope_url, scope_things.clone());
return Some(sender);
} else {
warn!("Unable to activate service worker");
diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs
index 2d55345d324..b43262080b0 100644
--- a/components/script/webdriver_handlers.rs
+++ b/components/script/webdriver_handlers.rs
@@ -12,7 +12,7 @@ use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElemen
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
-use dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior};
+use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::str::DOMString;
@@ -29,14 +29,14 @@ use euclid::rect::Rect;
use euclid::size::Size2D;
use hyper_serde::Serde;
use ipc_channel::ipc::{self, IpcSender};
-use js::jsapi::{JSContext, HandleValue};
+use js::jsapi::{HandleValue, JSContext};
use js::jsval::UndefinedValue;
use msg::constellation_msg::PipelineId;
use net_traits::CookieSource::{HTTP, NonHTTP};
use net_traits::CoreResourceMsg::{GetCookiesDataForUrl, SetCookiesForUrlWithData};
use net_traits::IpcSend;
-use script_traits::webdriver_msg::WebDriverCookieError;
use script_traits::webdriver_msg::{WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverJSValue};
+use script_traits::webdriver_msg::WebDriverCookieError;
use url::Url;
fn find_node_by_unique_id(context: &BrowsingContext,
@@ -59,10 +59,17 @@ pub unsafe fn jsval_to_webdriver(cx: *mut JSContext, val: HandleValue) -> WebDri
} else if val.get().is_boolean() {
Ok(WebDriverJSValue::Boolean(val.get().to_boolean()))
} else if val.get().is_double() || val.get().is_int32() {
- Ok(WebDriverJSValue::Number(FromJSValConvertible::from_jsval(cx, val, ()).unwrap()))
+ Ok(WebDriverJSValue::Number(match FromJSValConvertible::from_jsval(cx, val, ()).unwrap() {
+ ConversionResult::Success(c) => c,
+ _ => unreachable!(),
+ }))
} else if val.get().is_string() {
//FIXME: use jsstring_to_str when jsval grows to_jsstring
- let string: DOMString = FromJSValConvertible::from_jsval(cx, val, StringificationBehavior::Default).unwrap();
+ let string: DOMString = match FromJSValConvertible::from_jsval(cx, val, StringificationBehavior::Default)
+ .unwrap() {
+ ConversionResult::Success(c) => c,
+ _ => unreachable!(),
+ };
Ok(WebDriverJSValue::String(String::from(string)))
} else if val.get().is_null() {
Ok(WebDriverJSValue::Null)