aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorMs2ger <Ms2ger@gmail.com>2016-07-04 16:24:09 +0200
committerMs2ger <Ms2ger@gmail.com>2016-07-28 13:05:56 +0200
commit89efccc4267706eec8d1cd32043bb25d7f37f9b2 (patch)
treed64ac6286bf487cb16e22639e658bc4eaaa35816 /components/script/dom
parenta0c502261dc2bd710e31dcbbbd2d81d2a2c53724 (diff)
downloadservo-89efccc4267706eec8d1cd32043bb25d7f37f9b2.tar.gz
servo-89efccc4267706eec8d1cd32043bb25d7f37f9b2.zip
Update SpiderMonkey to m-c bcf4ff0c3eef.
This currently breaks Servo on Android, because there are a number of interdependent changes that cannot easily land serially in a way that keeps it working throughout. We expect to fix this in the near future.
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py84
-rw-r--r--components/script/dom/bindings/error.rs109
-rw-r--r--components/script/dom/bindings/interface.rs92
-rw-r--r--components/script/dom/bindings/proxyhandler.rs21
-rw-r--r--components/script/dom/browsingcontext.rs25
5 files changed, 220 insertions, 111 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 8360dfc322a..2e0dc2415dd 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -1872,56 +1872,31 @@ class CGDOMJSClass(CGThing):
elif self.descriptor.weakReferenceable:
args["slots"] = "2"
return """\
+static CLASS_OPS: js::jsapi::ClassOps = js::jsapi::ClassOps {
+ addProperty: None,
+ delProperty: None,
+ getProperty: None,
+ setProperty: None,
+ enumerate: %(enumerateHook)s,
+ resolve: %(resolveHook)s,
+ mayResolve: None,
+ finalize: Some(%(finalizeHook)s),
+ call: None,
+ hasInstance: None,
+ construct: None,
+ trace: Some(%(traceHook)s),
+};
+
static Class: DOMJSClass = DOMJSClass {
base: js::jsapi::Class {
name: %(name)s as *const u8 as *const libc::c_char,
flags: JSCLASS_IS_DOMJSCLASS | %(flags)s |
(((%(slots)s) & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT)
/* JSCLASS_HAS_RESERVED_SLOTS(%(slots)s) */,
- addProperty: None,
- delProperty: None,
- getProperty: None,
- setProperty: None,
- enumerate: %(enumerateHook)s,
- resolve: %(resolveHook)s,
- mayResolve: None,
- finalize: Some(%(finalizeHook)s),
- call: None,
- hasInstance: None,
- construct: None,
- trace: Some(%(traceHook)s),
-
- spec: js::jsapi::ClassSpec {
- createConstructor_: None,
- createPrototype_: None,
- constructorFunctions_: 0 as *const js::jsapi::JSFunctionSpec,
- constructorProperties_: 0 as *const js::jsapi::JSPropertySpec,
- prototypeFunctions_: 0 as *const js::jsapi::JSFunctionSpec,
- prototypeProperties_: 0 as *const js::jsapi::JSPropertySpec,
- finishInit_: None,
- flags: 0,
- },
-
- ext: js::jsapi::ClassExtension {
- isWrappedNative: false,
- weakmapKeyDelegateOp: None,
- objectMovedOp: None,
- },
-
- ops: js::jsapi::ObjectOps {
- lookupProperty: None,
- defineProperty: None,
- hasProperty: None,
- getProperty: None,
- setProperty: None,
- getOwnPropertyDescriptor: None,
- deleteProperty: None,
- watch: None,
- unwatch: None,
- getElements: None,
- enumerate: None,
- funToString: None,
- },
+ cOps: &CLASS_OPS,
+ spec: ptr::null(),
+ ext: ptr::null(),
+ oOps: ptr::null(),
},
dom_class: %(domClass)s
};""" % args
@@ -1947,19 +1922,8 @@ static PrototypeClass: JSClass = JSClass {
flags:
// JSCLASS_HAS_RESERVED_SLOTS(%(slotCount)s)
(%(slotCount)s & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT,
- addProperty: None,
- delProperty: None,
- getProperty: None,
- setProperty: None,
- enumerate: None,
- resolve: None,
- mayResolve: None,
- finalize: None,
- call: None,
- hasInstance: None,
- construct: None,
- trace: None,
- reserved: [0 as *mut os::raw::c_void; 23]
+ cOps: 0 as *const _,
+ reserved: [0 as *mut os::raw::c_void; 3]
};
""" % {'name': name, 'slotCount': slotCount}
@@ -1983,9 +1947,12 @@ class CGInterfaceObjectJSClass(CGThing):
"depth": self.descriptor.prototypeDepth
}
return """\
+static INTERFACE_OBJECT_OPS: js::jsapi::ClassOps =
+ NonCallbackInterfaceObjectClass::ops(%(constructorBehavior)s);
+
static InterfaceObjectClass: NonCallbackInterfaceObjectClass =
NonCallbackInterfaceObjectClass::new(
- %(constructorBehavior)s,
+ &INTERFACE_OBJECT_OPS,
%(representation)s,
PrototypeList::ID::%(id)s,
%(depth)s);
@@ -2772,6 +2739,7 @@ let traps = ProxyTraps {
ownPropertyKeys: Some(own_property_keys),
delete_: Some(%(delete)s),
enumerate: None,
+ getPrototypeIfOrdinary: Some(proxyhandler::get_prototype_if_ordinary),
preventExtensions: Some(proxyhandler::prevent_extensions),
isExtensible: Some(proxyhandler::is_extensible),
has: None,
diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs
index d0074335c23..bd63ba84fb1 100644
--- a/components/script/dom/bindings/error.rs
+++ b/components/script/dom/bindings/error.rs
@@ -4,15 +4,26 @@
//! Utilities to throw exceptions from Rust bindings.
+use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
use dom::bindings::codegen::PrototypeList::proto_id_to_name;
-use dom::bindings::conversions::ToJSValConvertible;
+use dom::bindings::conversions::root_from_object;
+use dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible};
use dom::bindings::global::GlobalRef;
+use dom::bindings::str::USVString;
use dom::domexception::{DOMErrorName, DOMException};
use js::error::{throw_range_error, throw_type_error};
+use js::jsapi::HandleObject;
use js::jsapi::JSAutoCompartment;
-use js::jsapi::{JSContext, JSObject};
-use js::jsapi::{JS_IsExceptionPending, JS_ReportPendingException, JS_SetPendingException};
+use js::jsapi::JSContext;
+use js::jsapi::JSObject;
+use js::jsapi::JS_ClearPendingException;
+use js::jsapi::JS_ErrorFromException;
+use js::jsapi::JS_GetPendingException;
+use js::jsapi::JS_IsExceptionPending;
+use js::jsapi::JS_SetPendingException;
use js::jsval::UndefinedValue;
+use libc::c_uint;
+use std::slice::from_raw_parts;
/// DOM exceptions that can be thrown by a native DOM method.
#[derive(Debug, Clone, HeapSizeOf)]
@@ -123,11 +134,101 @@ pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: GlobalRef, result:
JS_SetPendingException(cx, thrown.handle());
}
+struct ErrorInfo {
+ filename: String,
+ message: String,
+ lineno: c_uint,
+ column: c_uint,
+}
+
+impl ErrorInfo {
+ unsafe fn from_native_error(cx: *mut JSContext, object: HandleObject)
+ -> Option<ErrorInfo> {
+ let report = JS_ErrorFromException(cx, object);
+ if report.is_null() {
+ return None;
+ }
+
+ let filename = {
+ let filename = (*report).filename as *const u8;
+ if !filename.is_null() {
+ let length = (0..).find(|idx| *filename.offset(*idx) == 0).unwrap();
+ let filename = from_raw_parts(filename, length as usize);
+ String::from_utf8_lossy(filename).into_owned()
+ } else {
+ "none".to_string()
+ }
+ };
+
+ let lineno = (*report).lineno;
+ let column = (*report).column;
+
+ let message = {
+ let message = (*report).ucmessage;
+ let length = (0..).find(|idx| *message.offset(*idx) == 0).unwrap();
+ let message = from_raw_parts(message, length as usize);
+ String::from_utf16_lossy(message)
+ };
+
+ Some(ErrorInfo {
+ filename: filename,
+ message: message,
+ lineno: lineno,
+ column: column,
+ })
+ }
+
+ fn from_dom_exception(cx: *mut JSContext, object: HandleObject) -> Option<ErrorInfo> {
+ let exception = match root_from_object::<DOMException>(object.get()) {
+ Ok(exception) => exception,
+ Err(_) => return None,
+ };
+
+ Some(ErrorInfo {
+ filename: "".to_string(),
+ message: exception.Stringifier().into(),
+ lineno: 0,
+ column: 0,
+ })
+ }
+}
+
/// Report a pending exception, thereby clearing it.
pub unsafe fn report_pending_exception(cx: *mut JSContext, obj: *mut JSObject) {
if JS_IsExceptionPending(cx) {
let _ac = JSAutoCompartment::new(cx, obj);
- JS_ReportPendingException(cx);
+ rooted!(in(cx) let mut value = UndefinedValue());
+ if !JS_GetPendingException(cx, value.handle_mut()) {
+ JS_ClearPendingException(cx);
+ error!("Uncaught exception: JS_GetPendingException failed");
+ return;
+ }
+
+ JS_ClearPendingException(cx);
+ if !value.is_object() {
+ match USVString::from_jsval(cx, value.handle(), ()) {
+ Ok(USVString(string)) => error!("Uncaught exception: {}", string),
+ Err(_) => error!("Uncaught exception: failed to stringify primitive"),
+ }
+ return;
+ }
+
+ rooted!(in(cx) let object = value.to_object());
+ let error_info = ErrorInfo::from_native_error(cx, object.handle())
+ .or_else(|| ErrorInfo::from_dom_exception(cx, object.handle()));
+ let error_info = match error_info {
+ Some(error_info) => error_info,
+ None => {
+ error!("Uncaught exception: failed to extract information");
+ return;
+ }
+ };
+
+ error!("Error at {}:{}:{} {}",
+ error_info.filename,
+ error_info.lineno,
+ error_info.column,
+ error_info.message);
}
}
diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs
index 4e2c630a453..3b2b5dbde36 100644
--- a/components/script/dom/bindings/interface.rs
+++ b/components/script/dom/bindings/interface.rs
@@ -11,7 +11,7 @@ use dom::bindings::guard::Guard;
use dom::bindings::utils::get_proto_or_iface_array;
use js::error::throw_type_error;
use js::glue::{RUST_SYMBOL_TO_JSID, UncheckedUnwrapObject};
-use js::jsapi::{Class, ClassExtension, ClassSpec, GetGlobalForObjectCrossCompartment};
+use js::jsapi::{Class, ClassOps, GetGlobalForObjectCrossCompartment};
use js::jsapi::{GetWellKnownSymbol, HandleObject, HandleValue, JSClass, JSContext};
use js::jsapi::{JSFunctionSpec, JSNative, JSFUN_CONSTRUCTOR, JSPROP_ENUMERATE};
use js::jsapi::{JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_RESOLVING, JSPropertySpec};
@@ -101,6 +101,21 @@ unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext,
ret
}
+const OBJECT_OPS: ObjectOps = ObjectOps {
+ lookupProperty: None,
+ defineProperty: None,
+ hasProperty: None,
+ getProperty: None,
+ setProperty: None,
+ getOwnPropertyDescriptor: None,
+ deleteProperty: None,
+ watch: None,
+ unwatch: None,
+ getElements: None,
+ enumerate: None,
+ funToString: Some(fun_to_string_hook),
+};
+
/// The class of a non-callback interface object.
#[derive(Copy, Clone)]
pub struct NonCallbackInterfaceObjectClass {
@@ -117,58 +132,39 @@ pub struct NonCallbackInterfaceObjectClass {
unsafe impl Sync for NonCallbackInterfaceObjectClass {}
impl NonCallbackInterfaceObjectClass {
+ /// Create `ClassOps` for a `NonCallbackInterfaceObjectClass`.
+ pub const fn ops(constructor_behavior: InterfaceConstructorBehavior)
+ -> ClassOps {
+ ClassOps {
+ addProperty: None,
+ delProperty: None,
+ getProperty: None,
+ setProperty: None,
+ enumerate: None,
+ resolve: None,
+ mayResolve: None,
+ finalize: None,
+ call: constructor_behavior.call,
+ construct: constructor_behavior.construct,
+ hasInstance: Some(has_instance_hook),
+ trace: None,
+ }
+ }
+
/// Create a new `NonCallbackInterfaceObjectClass` structure.
- pub const fn new(
- constructor_behavior: InterfaceConstructorBehavior,
- string_rep: &'static [u8],
- proto_id: PrototypeList::ID,
- proto_depth: u16)
- -> NonCallbackInterfaceObjectClass {
+ pub const fn new(ops: &'static ClassOps,
+ string_rep: &'static [u8],
+ proto_id: PrototypeList::ID,
+ proto_depth: u16)
+ -> NonCallbackInterfaceObjectClass {
NonCallbackInterfaceObjectClass {
class: Class {
name: b"Function\0" as *const _ as *const libc::c_char,
flags: 0,
- addProperty: None,
- delProperty: None,
- getProperty: None,
- setProperty: None,
- enumerate: None,
- resolve: None,
- mayResolve: None,
- finalize: None,
- call: constructor_behavior.call,
- construct: constructor_behavior.construct,
- hasInstance: Some(has_instance_hook),
- trace: None,
- spec: ClassSpec {
- createConstructor_: None,
- createPrototype_: None,
- constructorFunctions_: ptr::null(),
- constructorProperties_: ptr::null(),
- prototypeFunctions_: ptr::null(),
- prototypeProperties_: ptr::null(),
- finishInit_: None,
- flags: 0,
- },
- ext: ClassExtension {
- isWrappedNative: false,
- weakmapKeyDelegateOp: None,
- objectMovedOp: None,
- },
- ops: ObjectOps {
- lookupProperty: None,
- defineProperty: None,
- hasProperty: None,
- getProperty: None,
- setProperty: None,
- getOwnPropertyDescriptor: None,
- deleteProperty: None,
- watch: None,
- unwatch: None,
- getElements: None,
- enumerate: None,
- funToString: Some(fun_to_string_hook),
- }
+ cOps: ops,
+ spec: ptr::null(),
+ ext: ptr::null(),
+ oOps: &OBJECT_OPS,
},
proto_id: proto_id,
proto_depth: proto_depth,
diff --git a/components/script/dom/bindings/proxyhandler.rs b/components/script/dom/bindings/proxyhandler.rs
index 9db30d8835c..c863cc31994 100644
--- a/components/script/dom/bindings/proxyhandler.rs
+++ b/components/script/dom/bindings/proxyhandler.rs
@@ -12,7 +12,9 @@ use js::glue::GetProxyExtra;
use js::glue::InvokeGetOwnPropertyDescriptor;
use js::glue::{GetProxyHandler, SetProxyExtra};
use js::jsapi::GetObjectProto;
+use js::jsapi::GetStaticPrototype;
use js::jsapi::JS_GetPropertyDescriptorById;
+use js::jsapi::MutableHandleObject;
use js::jsapi::{Handle, HandleId, HandleObject, MutableHandle, ObjectOpResult};
use js::jsapi::{JSContext, JSObject, JSPROP_GETTER, PropertyDescriptor};
use js::jsapi::{JSErrNum, JS_StrictPropertyStub};
@@ -103,6 +105,25 @@ pub unsafe extern "C" fn is_extensible(_cx: *mut JSContext,
true
}
+/// If `proxy` (underneath any functionally-transparent wrapper proxies) has as
+/// its `[[GetPrototypeOf]]` trap the ordinary `[[GetPrototypeOf]]` behavior
+/// defined for ordinary objects, set `*is_ordinary` to true and store `obj`'s
+/// prototype in `proto`. Otherwise set `*isOrdinary` to false. In case of
+/// error, both outparams have unspecified value.
+///
+/// This implementation always handles the case of the ordinary
+/// `[[GetPrototypeOf]]` behavior. An alternative implementation will be
+/// necessary for the Location object.
+pub unsafe extern "C" fn get_prototype_if_ordinary(_: *mut JSContext,
+ proxy: HandleObject,
+ is_ordinary: *mut bool,
+ proto: MutableHandleObject)
+ -> bool {
+ *is_ordinary = true;
+ proto.set(GetStaticPrototype(proxy.get()));
+ true
+}
+
/// Get the expando object, or null if there is none.
pub fn get_expando_object(obj: HandleObject) -> *mut JSObject {
unsafe {
diff --git a/components/script/dom/browsingcontext.rs b/components/script/dom/browsingcontext.rs
index 4c0914ddf3c..878d376ca66 100644
--- a/components/script/dom/browsingcontext.rs
+++ b/components/script/dom/browsingcontext.rs
@@ -22,7 +22,7 @@ use js::jsapi::{Handle, HandleId, HandleObject, HandleValue, JSAutoCompartment};
use js::jsapi::{JSContext, JSPROP_READONLY, JSErrNum, JSObject, PropertyDescriptor, JS_DefinePropertyById};
use js::jsapi::{JS_ForwardGetPropertyTo, JS_ForwardSetPropertyTo, JS_GetClass, JSTracer, FreeOp};
use js::jsapi::{JS_GetOwnPropertyDescriptorById, JS_HasPropertyById, MutableHandle};
-use js::jsapi::{MutableHandleValue, ObjectOpResult};
+use js::jsapi::{MutableHandleObject, MutableHandleValue, ObjectOpResult};
use js::jsval::{UndefinedValue, PrivateValue};
use msg::constellation_msg::{PipelineId, SubpageId};
use std::cell::Cell;
@@ -354,6 +354,28 @@ unsafe extern "C" fn set(cx: *mut JSContext,
res)
}
+#[allow(unsafe_code)]
+unsafe extern "C" fn get_prototype_if_ordinary(_: *mut JSContext,
+ _: HandleObject,
+ is_ordinary: *mut bool,
+ _: MutableHandleObject)
+ -> bool {
+ // Window's [[GetPrototypeOf]] trap isn't the ordinary definition:
+ //
+ // https://html.spec.whatwg.org/multipage/#windowproxy-getprototypeof
+ //
+ // We nonetheless can implement it with a static [[Prototype]], because
+ // wrapper-class handlers (particularly, XOW in FilteringWrapper.cpp) supply
+ // all non-ordinary behavior.
+ //
+ // But from a spec point of view, it's the exact same object in both cases --
+ // only the observer's changed. So this getPrototypeIfOrdinary trap on the
+ // non-wrapper object *must* report non-ordinary, even if static [[Prototype]]
+ // usually means ordinary.
+ *is_ordinary = false;
+ return true;
+}
+
static PROXY_HANDLER: ProxyTraps = ProxyTraps {
enter: None,
getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor),
@@ -361,6 +383,7 @@ static PROXY_HANDLER: ProxyTraps = ProxyTraps {
ownPropertyKeys: None,
delete_: None,
enumerate: None,
+ getPrototypeIfOrdinary: Some(get_prototype_if_ordinary),
preventExtensions: None,
isExtensible: None,
has: Some(has),