diff options
author | Anthony Ramine <n.oxyde@gmail.com> | 2015-06-03 12:21:53 +0200 |
---|---|---|
committer | Anthony Ramine <n.oxyde@gmail.com> | 2015-06-24 11:34:30 +0200 |
commit | a90983553b78e3450cc91d810eb3d053398169d0 (patch) | |
tree | b6a3bb31fff9839873bc24d00a775a0b3540c041 /components/script/dom/bindings/utils.rs | |
parent | e7808c526c348fea5e3b48af70b7f1a066652097 (diff) | |
download | servo-a90983553b78e3450cc91d810eb3d053398169d0.tar.gz servo-a90983553b78e3450cc91d810eb3d053398169d0.zip |
Merge generic funs to share them across all bindings (fixes #2684)
Diffstat (limited to 'components/script/dom/bindings/utils.rs')
-rw-r--r-- | components/script/dom/bindings/utils.rs | 108 |
1 files changed, 99 insertions, 9 deletions
diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index fa7204f7dc8..5d055fa7766 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -6,8 +6,11 @@ use dom::bindings::codegen::PrototypeList; use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH; -use dom::bindings::conversions::{native_from_handleobject, is_dom_class, jsstring_to_str}; -use dom::bindings::error::{Error, ErrorResult, Fallible, throw_type_error}; +use dom::bindings::conversions::{is_dom_class, jsstring_to_str}; +use dom::bindings::conversions::native_from_handleobject; +use dom::bindings::conversions::private_from_proto_chain; +use dom::bindings::error::{Error, ErrorResult, Fallible, throw_invalid_this}; +use dom::bindings::error::throw_type_error; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::trace::trace_object; @@ -24,8 +27,11 @@ use std::ptr; use std::cmp::PartialEq; use std::default::Default; use std::cell::UnsafeCell; -use js::glue::UnwrapObject; -use js::glue::{IsWrapper, RUST_JSID_IS_INT, RUST_JSID_TO_INT}; +use js::glue::{CallJitMethodOp, CallJitGetterOp, CallJitSetterOp, IsWrapper}; +use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT}; +use js::glue::{RUST_JSID_TO_INT, UnwrapObject}; +use js::jsapi::{CallArgs, GetGlobalForObjectCrossCompartment, JSJitInfo}; +use js::jsapi::JS_IsExceptionPending; use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewFunction, JSTraceOp}; use js::jsapi::{JS_DefineProperties, JS_ForwardGetPropertyTo}; use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype}; @@ -47,13 +53,12 @@ use js::jsapi::{ObjectOpResult, RootedObject, RootedValue, Heap, MutableHandleOb use js::jsapi::PropertyDefinitionBehavior; use js::jsapi::JSAutoCompartment; use js::jsapi::{DOMCallbacks, JSWrapObjectCallbacks}; -use js::jsval::JSVal; -use js::jsval::{PrivateValue, NullValue}; -use js::jsval::{Int32Value, UInt32Value, DoubleValue, BooleanValue}; +use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue}; +use js::jsval::{PrivateValue, UInt32Value, UndefinedValue}; use js::rust::{GCMethods, ToString}; use js::glue::{WrapperNew, GetCrossCompartmentWrapper}; -use js::{JSPROP_ENUMERATE, JSPROP_READONLY, JSPROP_PERMANENT}; -use js::JSFUN_CONSTRUCTOR; +use js::{JS_ARGV, JS_CALLEE, JSFUN_CONSTRUCTOR, JSPROP_ENUMERATE}; +use js::{JSPROP_PERMANENT, JSPROP_READONLY}; use js; use string_cache::{Atom, Namespace}; @@ -670,6 +675,91 @@ pub unsafe fn delete_property_by_id(cx: *mut JSContext, object: HandleObject, JS_DeletePropertyById1(cx, object, id, bp) } +unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern fn(*const JSJitInfo, *mut JSContext, + HandleObject, *mut libc::c_void, u32, + *mut JSVal) + -> u8) + -> u8 { + let args = CallArgs::from_vp(vp, argc); + let thisobj = args.thisv(); + if !thisobj.get().is_null_or_undefined() && !thisobj.get().is_object() { + return 0; + } + let obj = if thisobj.get().is_object() { + thisobj.get().to_object() + } else { + GetGlobalForObjectCrossCompartment(JS_CALLEE(cx, vp).to_object_or_null()) + }; + let obj = RootedObject::new(cx, obj); + let info = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp)); + let proto_id = (*info).protoID; + let depth = (*info).depth; + let this = match private_from_proto_chain(obj.ptr, proto_id, depth) { + Ok(val) => val, + Err(()) => { + if is_lenient { + debug_assert!(JS_IsExceptionPending(cx) == 0); + *vp = UndefinedValue(); + return 1; + } else { + throw_invalid_this(cx, proto_id); + return 0; + } + } + }; + call(info, cx, obj.handle(), this as *mut libc::c_void, argc, vp) +} + +/// Generic method of IDL interface. +pub unsafe extern fn generic_method(cx: *mut JSContext, + argc: libc::c_uint, vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, false, CallJitMethodOp) +} + +/// Generic getter of IDL interface. +pub unsafe extern fn generic_getter(cx: *mut JSContext, + argc: libc::c_uint, vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, false, CallJitGetterOp) +} + +/// Generic lenient getter of IDL interface. +pub unsafe extern fn generic_lenient_getter(cx: *mut JSContext, + argc: libc::c_uint, + vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, true, CallJitGetterOp) +} + +unsafe extern fn call_setter(info: *const JSJitInfo, cx: *mut JSContext, + handle: HandleObject, this: *mut libc::c_void, + argc: u32, vp: *mut JSVal) + -> u8 { + if CallJitSetterOp(info, cx, handle, this, argc, vp) == 0 { + return 0; + } + *vp = UndefinedValue(); + 1 +} + +/// Generic setter of IDL interface. +pub unsafe extern fn generic_setter(cx: *mut JSContext, + argc: libc::c_uint, vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, false, call_setter) +} + +/// Generic lenient setter of IDL interface. +pub unsafe extern fn generic_lenient_setter(cx: *mut JSContext, + argc: libc::c_uint, + vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, true, call_setter) +} + /// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details. pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult { match xml_name_type(qualified_name) { |