aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/utils.rs
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2016-01-29 01:10:26 +0100
committerAnthony Ramine <n.oxyde@gmail.com>2016-02-25 15:56:47 +0100
commit1559f5a39fab451d83ad40ef960d9a3e5cd9f453 (patch)
tree0228ec739ce6cc78dc72f4cd00d2ad4389b44191 /components/script/dom/bindings/utils.rs
parentca979e115b087cf627baf2be8d54ea47b1f773a1 (diff)
downloadservo-1559f5a39fab451d83ad40ef960d9a3e5cd9f453.tar.gz
servo-1559f5a39fab451d83ad40ef960d9a3e5cd9f453.zip
Lazily define interface objects on globals (fixes #6419)
Diffstat (limited to 'components/script/dom/bindings/utils.rs')
-rw-r--r--components/script/dom/bindings/utils.rs68
1 files changed, 61 insertions, 7 deletions
diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs
index d06dc10c8da..2b4e5ee5ae0 100644
--- a/components/script/dom/bindings/utils.rs
+++ b/components/script/dom/bindings/utils.rs
@@ -4,6 +4,7 @@
//! Various utilities to glue JavaScript and the DOM implementation together.
+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};
@@ -18,16 +19,18 @@ use js;
use js::error::throw_type_error;
use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
use js::glue::{GetCrossCompartmentWrapper, WrapperNew};
-use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT};
-use js::glue::{RUST_JSID_TO_INT, UnwrapObject};
+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_DeletePropertyById1, JS_FireOnNewGlobalObject, JS_ForwardGetPropertyTo};
-use js::jsapi::{JS_GetClass, JS_GetProperty, JS_GetPrototype, JS_GetReservedSlot, JS_HasProperty};
-use js::jsapi::{JS_HasPropertyById, JS_IsExceptionPending, JS_NewGlobalObject};
-use js::jsapi::{JS_ObjectToOuterObject, JS_SetProperty, JS_SetReservedSlot};
-use js::jsapi::{MutableHandleValue, ObjectOpResult, OnNewGlobalHookOption, RootedObject};
+use js::jsapi::{JS_DeletePropertyById1, JS_EnumerateStandardClasses, JS_FireOnNewGlobalObject};
+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_ObjectToOuterObject, JS_ResolveStandardClass, JS_SetProperty};
+use js::jsapi::{JS_SetReservedSlot, JS_StringHasLatin1Chars, MutableHandleValue, ObjectOpResult};
+use js::jsapi::{OnNewGlobalHookOption, RootedObject};
use js::jsval::{JSVal};
use js::jsval::{PrivateValue, UndefinedValue};
use js::rust::{GCMethods, ToString};
@@ -37,6 +40,7 @@ use std::default::Default;
use std::ffi::CString;
use std::os::raw::c_void;
use std::ptr;
+use std::slice;
use util::non_geckolib::jsstring_to_str;
/// Proxy handler for a WindowProxy.
@@ -364,6 +368,56 @@ pub unsafe fn trace_global(tracer: *mut JSTracer, obj: *mut JSObject) {
}
}
+/// Enumerate lazy properties of a global object.
+pub unsafe extern "C" fn enumerate_global(cx: *mut JSContext, obj: HandleObject) -> bool {
+ assert!(JS_IsGlobalObject(obj.get()));
+ if !JS_EnumerateStandardClasses(cx, obj) {
+ return false;
+ }
+ for init_fun in InterfaceObjectMap::MAP.values() {
+ init_fun(cx, obj);
+ }
+ true
+}
+
+/// Resolve a lazy global property, for interface objects and named constructors.
+pub unsafe extern "C" fn resolve_global(
+ cx: *mut JSContext,
+ obj: HandleObject,
+ id: HandleId,
+ rval: *mut bool)
+ -> bool {
+ assert!(JS_IsGlobalObject(obj.get()));
+ if !JS_ResolveStandardClass(cx, obj, id, rval) {
+ return false;
+ }
+ if *rval {
+ return true;
+ }
+ if !RUST_JSID_IS_STRING(id) {
+ *rval = false;
+ return true;
+ }
+
+ let string = RUST_JSID_TO_STRING(id);
+ if !JS_StringHasLatin1Chars(string) {
+ *rval = false;
+ return true;
+ }
+ let mut length = 0;
+ let ptr = JS_GetLatin1StringCharsAndLength(cx, ptr::null(), string, &mut length);
+ assert!(!ptr.is_null());
+ let bytes = slice::from_raw_parts(ptr, length as usize);
+
+ if let Some(init_fun) = InterfaceObjectMap::MAP.get(bytes) {
+ init_fun(cx, obj);
+ *rval = true;
+ } else {
+ *rval = false;
+ }
+ true
+}
+
unsafe extern "C" fn wrap(cx: *mut JSContext,
_existing: HandleObject,
obj: HandleObject)