diff options
author | Anthony Ramine <n.oxyde@gmail.com> | 2016-01-29 01:10:26 +0100 |
---|---|---|
committer | Anthony Ramine <n.oxyde@gmail.com> | 2016-02-25 15:56:47 +0100 |
commit | 1559f5a39fab451d83ad40ef960d9a3e5cd9f453 (patch) | |
tree | 0228ec739ce6cc78dc72f4cd00d2ad4389b44191 /components/script/dom/bindings/utils.rs | |
parent | ca979e115b087cf627baf2be8d54ea47b1f773a1 (diff) | |
download | servo-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.rs | 68 |
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) |