aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/BindingUtils.h
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/codegen/BindingUtils.h')
-rw-r--r--components/script/dom/bindings/codegen/BindingUtils.h1151
1 files changed, 0 insertions, 1151 deletions
diff --git a/components/script/dom/bindings/codegen/BindingUtils.h b/components/script/dom/bindings/codegen/BindingUtils.h
deleted file mode 100644
index ee9d6c3691c..00000000000
--- a/components/script/dom/bindings/codegen/BindingUtils.h
+++ /dev/null
@@ -1,1151 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* vim: set ts=2 sw=2 et tw=79: */
-/* 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/. */
-
-#ifndef mozilla_dom_BindingUtils_h__
-#define mozilla_dom_BindingUtils_h__
-
-#include "mozilla/dom/DOMJSClass.h"
-#include "mozilla/dom/DOMJSProxyHandler.h"
-#include "mozilla/dom/workers/Workers.h"
-#include "mozilla/ErrorResult.h"
-
-#include "jsapi.h"
-#include "jsfriendapi.h"
-#include "jswrapper.h"
-
-#include "nsIXPConnect.h"
-#include "qsObjectHelper.h"
-#include "xpcpublic.h"
-#include "nsTraceRefcnt.h"
-#include "nsWrapperCacheInlines.h"
-#include "mozilla/Likely.h"
-
-// nsGlobalWindow implements nsWrapperCache, but doesn't always use it. Don't
-// try to use it without fixing that first.
-class nsGlobalWindow;
-
-namespace mozilla {
-namespace dom {
-
-enum ErrNum {
-#define MSG_DEF(_name, _argc, _str) \
- _name,
-#include "mozilla/dom/Errors.msg"
-#undef MSG_DEF
- Err_Limit
-};
-
-bool
-ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...);
-
-template<bool mainThread>
-inline bool
-Throw(JSContext* cx, nsresult rv)
-{
- using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
-
- // XXX Introduce exception machinery.
- if (mainThread) {
- xpc::Throw(cx, rv);
- } else {
- if (!JS_IsExceptionPending(cx)) {
- ThrowDOMExceptionForNSResult(cx, rv);
- }
- }
- return false;
-}
-
-template<bool mainThread>
-inline bool
-ThrowMethodFailedWithDetails(JSContext* cx, const ErrorResult& rv,
- const char* /* ifaceName */,
- const char* /* memberName */)
-{
- return Throw<mainThread>(cx, rv.ErrorCode());
-}
-
-inline bool
-IsDOMClass(const JSClass* clasp)
-{
- return clasp->flags & JSCLASS_IS_DOMJSCLASS;
-}
-
-inline bool
-IsDOMClass(const js::Class* clasp)
-{
- return IsDOMClass(Jsvalify(clasp));
-}
-
-// It's ok for eRegularDOMObject and eProxyDOMObject to be the same, but
-// eNonDOMObject should always be different from the other two. This enum
-// shouldn't be used to differentiate between non-proxy and proxy bindings.
-enum DOMObjectSlot {
- eNonDOMObject = -1,
- eRegularDOMObject = DOM_OBJECT_SLOT,
- eProxyDOMObject = DOM_PROXY_OBJECT_SLOT
-};
-
-template <class T>
-inline T*
-UnwrapDOMObject(JSObject* obj, DOMObjectSlot slot)
-{
- MOZ_ASSERT(slot != eNonDOMObject,
- "Don't pass non-DOM objects to this function");
-
-#ifdef DEBUG
- if (IsDOMClass(js::GetObjectClass(obj))) {
- MOZ_ASSERT(slot == eRegularDOMObject);
- } else {
- MOZ_ASSERT(js::IsObjectProxyClass(js::GetObjectClass(obj)) ||
- js::IsFunctionProxyClass(js::GetObjectClass(obj)));
- MOZ_ASSERT(js::GetProxyHandler(obj)->family() == ProxyFamily());
- MOZ_ASSERT(IsNewProxyBinding(js::GetProxyHandler(obj)));
- MOZ_ASSERT(slot == eProxyDOMObject);
- }
-#endif
-
- JS::Value val = js::GetReservedSlot(obj, slot);
- // XXXbz/khuey worker code tries to unwrap interface objects (which have
- // nothing here). That needs to stop.
- // XXX We don't null-check UnwrapObject's result; aren't we going to crash
- // anyway?
- if (val.isUndefined()) {
- return NULL;
- }
-
- return static_cast<T*>(val.toPrivate());
-}
-
-// Only use this with a new DOM binding object (either proxy or regular).
-inline const DOMClass*
-GetDOMClass(JSObject* obj)
-{
- js::Class* clasp = js::GetObjectClass(obj);
- if (IsDOMClass(clasp)) {
- return &DOMJSClass::FromJSClass(clasp)->mClass;
- }
-
- js::BaseProxyHandler* handler = js::GetProxyHandler(obj);
- MOZ_ASSERT(handler->family() == ProxyFamily());
- MOZ_ASSERT(IsNewProxyBinding(handler));
- return &static_cast<DOMProxyHandler*>(handler)->mClass;
-}
-
-inline DOMObjectSlot
-GetDOMClass(JSObject* obj, const DOMClass*& result)
-{
- js::Class* clasp = js::GetObjectClass(obj);
- if (IsDOMClass(clasp)) {
- result = &DOMJSClass::FromJSClass(clasp)->mClass;
- return eRegularDOMObject;
- }
-
- if (js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) {
- js::BaseProxyHandler* handler = js::GetProxyHandler(obj);
- if (handler->family() == ProxyFamily() && IsNewProxyBinding(handler)) {
- result = &static_cast<DOMProxyHandler*>(handler)->mClass;
- return eProxyDOMObject;
- }
- }
-
- return eNonDOMObject;
-}
-
-inline bool
-UnwrapDOMObjectToISupports(JSObject* obj, nsISupports*& result)
-{
- const DOMClass* clasp;
- DOMObjectSlot slot = GetDOMClass(obj, clasp);
- if (slot == eNonDOMObject || !clasp->mDOMObjectIsISupports) {
- return false;
- }
-
- result = UnwrapDOMObject<nsISupports>(obj, slot);
- return true;
-}
-
-inline bool
-IsDOMObject(JSObject* obj)
-{
- js::Class* clasp = js::GetObjectClass(obj);
- return IsDOMClass(clasp) ||
- ((js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) &&
- (js::GetProxyHandler(obj)->family() == ProxyFamily() &&
- IsNewProxyBinding(js::GetProxyHandler(obj))));
-}
-
-// Some callers don't want to set an exception when unwrapping fails
-// (for example, overload resolution uses unwrapping to tell what sort
-// of thing it's looking at).
-// U must be something that a T* can be assigned to (e.g. T* or an nsRefPtr<T>).
-template <prototypes::ID PrototypeID, class T, typename U>
-inline nsresult
-UnwrapObject(JSContext* cx, JSObject* obj, U& value)
-{
- /* First check to see whether we have a DOM object */
- const DOMClass* domClass;
- DOMObjectSlot slot = GetDOMClass(obj, domClass);
- if (slot == eNonDOMObject) {
- /* Maybe we have a security wrapper or outer window? */
- if (!js::IsWrapper(obj)) {
- /* Not a DOM object, not a wrapper, just bail */
- return NS_ERROR_XPC_BAD_CONVERT_JS;
- }
-
- obj = xpc::Unwrap(cx, obj, false);
- if (!obj) {
- return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
- }
- MOZ_ASSERT(!js::IsWrapper(obj));
- slot = GetDOMClass(obj, domClass);
- if (slot == eNonDOMObject) {
- /* We don't have a DOM object */
- return NS_ERROR_XPC_BAD_CONVERT_JS;
- }
- }
-
- /* This object is a DOM object. Double-check that it is safely
- castable to T by checking whether it claims to inherit from the
- class identified by protoID. */
- if (domClass->mInterfaceChain[PrototypeTraits<PrototypeID>::Depth] ==
- PrototypeID) {
- value = UnwrapDOMObject<T>(obj, slot);
- return NS_OK;
- }
-
- /* It's the wrong sort of DOM object */
- return NS_ERROR_XPC_BAD_CONVERT_JS;
-}
-
-inline bool
-IsArrayLike(JSContext* cx, JSObject* obj)
-{
- MOZ_ASSERT(obj);
- // For simplicity, check for security wrappers up front. In case we
- // have a security wrapper, don't forget to enter the compartment of
- // the underlying object after unwrapping.
- Maybe<JSAutoCompartment> ac;
- if (js::IsWrapper(obj)) {
- obj = xpc::Unwrap(cx, obj, false);
- if (!obj) {
- // Let's say it's not
- return false;
- }
-
- ac.construct(cx, obj);
- }
-
- // XXXbz need to detect platform objects (including listbinding
- // ones) with indexGetters here!
- return JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj, cx);
-}
-
-inline bool
-IsPlatformObject(JSContext* cx, JSObject* obj)
-{
- // XXXbz Should be treating list-binding objects as platform objects
- // too? The one consumer so far wants non-array-like platform
- // objects, so listbindings that have an indexGetter should test
- // false from here. Maybe this function should have a different
- // name?
- MOZ_ASSERT(obj);
- // Fast-path the common case
- JSClass* clasp = js::GetObjectJSClass(obj);
- if (IsDOMClass(clasp)) {
- return true;
- }
- // Now for simplicity check for security wrappers before anything else
- if (js::IsWrapper(obj)) {
- obj = xpc::Unwrap(cx, obj, false);
- if (!obj) {
- // Let's say it's not
- return false;
- }
- clasp = js::GetObjectJSClass(obj);
- }
- return IS_WRAPPER_CLASS(js::Valueify(clasp)) || IsDOMClass(clasp) ||
- JS_IsArrayBufferObject(obj, cx);
-}
-
-// U must be something that a T* can be assigned to (e.g. T* or an nsRefPtr<T>).
-template <class T, typename U>
-inline nsresult
-UnwrapObject(JSContext* cx, JSObject* obj, U& value)
-{
- return UnwrapObject<static_cast<prototypes::ID>(
- PrototypeIDMap<T>::PrototypeID), T>(cx, obj, value);
-}
-
-const size_t kProtoOrIfaceCacheCount =
- prototypes::id::_ID_Count + constructors::id::_ID_Count;
-
-inline void
-AllocateProtoOrIfaceCache(JSObject* obj)
-{
- MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
- MOZ_ASSERT(js::GetReservedSlot(obj, DOM_PROTOTYPE_SLOT).isUndefined());
-
- // Important: The () at the end ensure zero-initialization
- JSObject** protoOrIfaceArray = new JSObject*[kProtoOrIfaceCacheCount]();
-
- js::SetReservedSlot(obj, DOM_PROTOTYPE_SLOT,
- JS::PrivateValue(protoOrIfaceArray));
-}
-
-inline void
-TraceProtoOrIfaceCache(JSTracer* trc, JSObject* obj)
-{
- MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
-
- if (!HasProtoOrIfaceArray(obj))
- return;
- JSObject** protoOrIfaceArray = GetProtoOrIfaceArray(obj);
- for (size_t i = 0; i < kProtoOrIfaceCacheCount; ++i) {
- JSObject* proto = protoOrIfaceArray[i];
- if (proto) {
- JS_CALL_OBJECT_TRACER(trc, proto, "protoOrIfaceArray[i]");
- }
- }
-}
-
-inline void
-DestroyProtoOrIfaceCache(JSObject* obj)
-{
- MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
-
- JSObject** protoOrIfaceArray = GetProtoOrIfaceArray(obj);
-
- delete [] protoOrIfaceArray;
-}
-
-struct ConstantSpec
-{
- const char* name;
- JS::Value value;
-};
-
-/**
- * Add constants to an object.
- */
-bool
-DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs);
-
-template<typename T>
-struct Prefable {
- // A boolean indicating whether this set of specs is enabled
- bool enabled;
- // Array of specs, terminated in whatever way is customary for T.
- // Null to indicate a end-of-array for Prefable, when such an
- // indicator is needed.
- T* specs;
-};
-
-/*
- * Create a DOM interface object (if constructorClass is non-null) and/or a
- * DOM interface prototype object (if protoClass is non-null).
- *
- * global is used as the parent of the interface object and the interface
- * prototype object
- * receiver is the object on which we need to define the interface object as a
- * property
- * protoProto is the prototype to use for the interface prototype object.
- * protoClass is the JSClass to use for the interface prototype object.
- * This is null if we should not create an interface prototype
- * object.
- * constructorClass is the JSClass to use for the interface object.
- * This is null if we should not create an interface object or
- * if it should be a function object.
- * constructor is the JSNative to use as a constructor. If this is non-null, it
- * should be used as a JSNative to back the interface object, which
- * should be a Function. If this is null, then we should create an
- * object of constructorClass, unless that's also null, in which
- * case we should not create an interface object at all.
- * ctorNargs is the length of the constructor function; 0 if no constructor
- * instanceClass is the JSClass of instance objects for this class. This can
- * be null if this is not a concrete proto.
- * methods and properties are to be defined on the interface prototype object;
- * these arguments are allowed to be null if there are no
- * methods or properties respectively.
- * constants are to be defined on the interface object and on the interface
- * prototype object; allowed to be null if there are no constants.
- * staticMethods are to be defined on the interface object; allowed to be null
- * if there are no static methods.
- *
- * At least one of protoClass and constructorClass should be non-null.
- * If constructorClass is non-null, the resulting interface object will be
- * defined on the given global with property name |name|, which must also be
- * non-null.
- *
- * returns the interface prototype object if protoClass is non-null, else it
- * returns the interface object.
- */
-JSObject*
-CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* receiver,
- JSObject* protoProto, JSClass* protoClass,
- JSClass* constructorClass, JSNative constructor,
- unsigned ctorNargs, const DOMClass* domClass,
- Prefable<JSFunctionSpec>* methods,
- Prefable<JSPropertySpec>* properties,
- Prefable<ConstantSpec>* constants,
- Prefable<JSFunctionSpec>* staticMethods, const char* name);
-
-template <class T>
-inline bool
-WrapNewBindingObject(JSContext* cx, JSObject* scope, T* value, JS::Value* vp)
-{
- JSObject* obj = value->GetWrapper();
- if (obj && js::GetObjectCompartment(obj) == js::GetObjectCompartment(scope)) {
- *vp = JS::ObjectValue(*obj);
- return true;
- }
-
- if (!obj) {
- bool triedToWrap;
- obj = value->WrapObject(cx, scope, &triedToWrap);
- if (!obj) {
- // At this point, obj is null, so just return false. We could
- // try to communicate triedToWrap to the caller, but in practice
- // callers seem to be testing JS_IsExceptionPending(cx) to
- // figure out whether WrapObject() threw instead.
- return false;
- }
- }
-
- // When called via XrayWrapper, we end up here while running in the
- // chrome compartment. But the obj we have would be created in
- // whatever the content compartment is. So at this point we need to
- // make sure it's correctly wrapped for the compartment of |scope|.
- // cx should already be in the compartment of |scope| here.
- MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
- *vp = JS::ObjectValue(*obj);
- return JS_WrapValue(cx, vp);
-}
-
-// Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
-template <template <typename> class SmartPtr, class T>
-inline bool
-WrapNewBindingObject(JSContext* cx, JSObject* scope, const SmartPtr<T>& value,
- JS::Value* vp)
-{
- return WrapNewBindingObject(cx, scope, value.get(), vp);
-}
-
-template <class T>
-inline bool
-WrapNewBindingNonWrapperCachedObject(JSContext* cx, JSObject* scope, T* value,
- JS::Value* vp)
-{
- // We try to wrap in the compartment of the underlying object of "scope"
- JSObject* obj;
- {
- // scope for the JSAutoCompartment so that we restore the compartment
- // before we call JS_WrapValue.
- Maybe<JSAutoCompartment> ac;
- if (js::IsWrapper(scope)) {
- scope = xpc::Unwrap(cx, scope, false);
- if (!scope)
- return false;
- ac.construct(cx, scope);
- }
-
- obj = value->WrapObject(cx, scope);
- }
-
- // We can end up here in all sorts of compartments, per above. Make
- // sure to JS_WrapValue!
- *vp = JS::ObjectValue(*obj);
- return JS_WrapValue(cx, vp);
-}
-
-// Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
-template <template <typename> class SmartPtr, typename T>
-inline bool
-WrapNewBindingNonWrapperCachedObject(JSContext* cx, JSObject* scope,
- const SmartPtr<T>& value, JS::Value* vp)
-{
- return WrapNewBindingNonWrapperCachedObject(cx, scope, value.get(), vp);
-}
-
-/**
- * A method to handle new-binding wrap failure, by possibly falling back to
- * wrapping as a non-new-binding object.
- */
-bool
-DoHandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope,
- nsISupports* value, JS::Value* vp);
-
-/**
- * An easy way to call the above when you have a value which
- * multiply-inherits from nsISupports.
- */
-template <class T>
-bool
-HandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope, T* value,
- JS::Value* vp)
-{
- nsCOMPtr<nsISupports> val;
- CallQueryInterface(value, getter_AddRefs(val));
- return DoHandleNewBindingWrappingFailure(cx, scope, val, vp);
-}
-
-// Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
-template <template <typename> class SmartPtr, class T>
-MOZ_ALWAYS_INLINE bool
-HandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope,
- const SmartPtr<T>& value, JS::Value* vp)
-{
- return HandleNewBindingWrappingFailure(cx, scope, value.get(), vp);
-}
-
-struct EnumEntry {
- const char* value;
- size_t length;
-};
-
-template<bool Fatal>
-inline bool
-EnumValueNotFound(JSContext* cx, const jschar* chars, size_t length,
- const char* type)
-{
- return false;
-}
-
-template<>
-inline bool
-EnumValueNotFound<false>(JSContext* cx, const jschar* chars, size_t length,
- const char* type)
-{
- // TODO: Log a warning to the console.
- return true;
-}
-
-template<>
-inline bool
-EnumValueNotFound<true>(JSContext* cx, const jschar* chars, size_t length,
- const char* type)
-{
- NS_LossyConvertUTF16toASCII deflated(static_cast<const PRUnichar*>(chars),
- length);
- return ThrowErrorMessage(cx, MSG_INVALID_ENUM_VALUE, deflated.get(), type);
-}
-
-
-template<bool InvalidValueFatal>
-inline int
-FindEnumStringIndex(JSContext* cx, JS::Value v, const EnumEntry* values,
- const char* type, bool* ok)
-{
- // JS_StringEqualsAscii is slow as molasses, so don't use it here.
- JSString* str = JS_ValueToString(cx, v);
- if (!str) {
- *ok = false;
- return 0;
- }
- JS::Anchor<JSString*> anchor(str);
- size_t length;
- const jschar* chars = JS_GetStringCharsAndLength(cx, str, &length);
- if (!chars) {
- *ok = false;
- return 0;
- }
- int i = 0;
- for (const EnumEntry* value = values; value->value; ++value, ++i) {
- if (length != value->length) {
- continue;
- }
-
- bool equal = true;
- const char* val = value->value;
- for (size_t j = 0; j != length; ++j) {
- if (unsigned(val[j]) != unsigned(chars[j])) {
- equal = false;
- break;
- }
- }
-
- if (equal) {
- *ok = true;
- return i;
- }
- }
-
- *ok = EnumValueNotFound<InvalidValueFatal>(cx, chars, length, type);
- return -1;
-}
-
-inline nsWrapperCache*
-GetWrapperCache(nsWrapperCache* cache)
-{
- return cache;
-}
-
-inline nsWrapperCache*
-GetWrapperCache(nsGlobalWindow* not_allowed);
-
-inline nsWrapperCache*
-GetWrapperCache(void* p)
-{
- return NULL;
-}
-
-struct ParentObject {
- template<class T>
- ParentObject(T* aObject) :
- mObject(aObject),
- mWrapperCache(GetWrapperCache(aObject))
- {}
-
- template<class T, template<typename> class SmartPtr>
- ParentObject(const SmartPtr<T>& aObject) :
- mObject(aObject.get()),
- mWrapperCache(GetWrapperCache(aObject.get()))
- {}
-
- ParentObject(nsISupports* aObject, nsWrapperCache* aCache) :
- mObject(aObject),
- mWrapperCache(aCache)
- {}
-
- nsISupports* const mObject;
- nsWrapperCache* const mWrapperCache;
-};
-
-inline nsWrapperCache*
-GetWrapperCache(const ParentObject& aParentObject)
-{
- return aParentObject.mWrapperCache;
-}
-
-template<class T>
-inline nsISupports*
-GetParentPointer(T* aObject)
-{
- return ToSupports(aObject);
-}
-
-inline nsISupports*
-GetParentPointer(const ParentObject& aObject)
-{
- return ToSupports(aObject.mObject);
-}
-
-template<class T>
-inline void
-ClearWrapper(T* p, nsWrapperCache* cache)
-{
- cache->ClearWrapper();
-}
-
-template<class T>
-inline void
-ClearWrapper(T* p, void*)
-{
- nsWrapperCache* cache;
- CallQueryInterface(p, &cache);
- ClearWrapper(p, cache);
-}
-
-// Can only be called with the immediate prototype of the instance object. Can
-// only be called on the prototype of an object known to be a DOM instance.
-JSBool
-InstanceClassHasProtoAtDepth(JSHandleObject protoObject, uint32_t protoID,
- uint32_t depth);
-
-// Only set allowNativeWrapper to false if you really know you need it, if in
-// doubt use true. Setting it to false disables security wrappers.
-bool
-XPCOMObjectToJsval(JSContext* cx, JSObject* scope, xpcObjectHelper &helper,
- const nsIID* iid, bool allowNativeWrapper, JS::Value* rval);
-
-template<class T>
-inline bool
-WrapObject(JSContext* cx, JSObject* scope, T* p, nsWrapperCache* cache,
- const nsIID* iid, JS::Value* vp)
-{
- if (xpc_FastGetCachedWrapper(cache, scope, vp))
- return true;
- qsObjectHelper helper(p, cache);
- return XPCOMObjectToJsval(cx, scope, helper, iid, true, vp);
-}
-
-template<class T>
-inline bool
-WrapObject(JSContext* cx, JSObject* scope, T* p, const nsIID* iid,
- JS::Value* vp)
-{
- return WrapObject(cx, scope, p, GetWrapperCache(p), iid, vp);
-}
-
-template<class T>
-inline bool
-WrapObject(JSContext* cx, JSObject* scope, T* p, JS::Value* vp)
-{
- return WrapObject(cx, scope, p, NULL, vp);
-}
-
-template<class T>
-inline bool
-WrapObject(JSContext* cx, JSObject* scope, nsCOMPtr<T> &p, const nsIID* iid,
- JS::Value* vp)
-{
- return WrapObject(cx, scope, p.get(), iid, vp);
-}
-
-template<class T>
-inline bool
-WrapObject(JSContext* cx, JSObject* scope, nsCOMPtr<T> &p, JS::Value* vp)
-{
- return WrapObject(cx, scope, p, NULL, vp);
-}
-
-template<class T>
-inline bool
-WrapObject(JSContext* cx, JSObject* scope, nsRefPtr<T> &p, const nsIID* iid,
- JS::Value* vp)
-{
- return WrapObject(cx, scope, p.get(), iid, vp);
-}
-
-template<class T>
-inline bool
-WrapObject(JSContext* cx, JSObject* scope, nsRefPtr<T> &p, JS::Value* vp)
-{
- return WrapObject(cx, scope, p, NULL, vp);
-}
-
-template<>
-inline bool
-WrapObject<JSObject>(JSContext* cx, JSObject* scope, JSObject* p, JS::Value* vp)
-{
- vp->setObjectOrNull(p);
- return true;
-}
-
-template<typename T>
-static inline JSObject*
-WrapNativeParent(JSContext* cx, JSObject* scope, const T& p)
-{
- if (!GetParentPointer(p))
- return scope;
-
- nsWrapperCache* cache = GetWrapperCache(p);
- JSObject* obj;
- if (cache && (obj = cache->GetWrapper())) {
-#ifdef DEBUG
- qsObjectHelper helper(GetParentPointer(p), cache);
- JS::Value debugVal;
-
- bool ok = XPCOMObjectToJsval(cx, scope, helper, NULL, false, &debugVal);
- NS_ASSERTION(ok && JSVAL_TO_OBJECT(debugVal) == obj,
- "Unexpected object in nsWrapperCache");
-#endif
- return obj;
- }
-
- qsObjectHelper helper(GetParentPointer(p), cache);
- JS::Value v;
- return XPCOMObjectToJsval(cx, scope, helper, NULL, false, &v) ?
- JSVAL_TO_OBJECT(v) :
- NULL;
-}
-
-static inline bool
-InternJSString(JSContext* cx, jsid& id, const char* chars)
-{
- if (JSString *str = ::JS_InternString(cx, chars)) {
- id = INTERNED_STRING_TO_JSID(cx, str);
- return true;
- }
- return false;
-}
-
-// Spec needs a name property
-template <typename Spec>
-static bool
-InitIds(JSContext* cx, Prefable<Spec>* prefableSpecs, jsid* ids)
-{
- MOZ_ASSERT(prefableSpecs);
- MOZ_ASSERT(prefableSpecs->specs);
- do {
- // We ignore whether the set of ids is enabled and just intern all the IDs,
- // because this is only done once per application runtime.
- Spec* spec = prefableSpecs->specs;
- do {
- if (!InternJSString(cx, *ids, spec->name)) {
- return false;
- }
- } while (++ids, (++spec)->name);
-
- // We ran out of ids for that pref. Put a JSID_VOID in on the id
- // corresponding to the list terminator for the pref.
- *ids = JSID_VOID;
- ++ids;
- } while ((++prefableSpecs)->specs);
-
- return true;
-}
-
-JSBool
-QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp);
-JSBool
-ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
-
-bool
-GetPropertyOnPrototype(JSContext* cx, JSObject* proxy, jsid id, bool* found,
- JS::Value* vp);
-
-bool
-HasPropertyOnPrototype(JSContext* cx, JSObject* proxy, DOMProxyHandler* handler,
- jsid id);
-
-template<class T>
-class NonNull
-{
-public:
- NonNull()
-#ifdef DEBUG
- : inited(false)
-#endif
- {}
-
- operator T&() {
- MOZ_ASSERT(inited);
- MOZ_ASSERT(ptr, "NonNull<T> was set to null");
- return *ptr;
- }
-
- operator const T&() const {
- MOZ_ASSERT(inited);
- MOZ_ASSERT(ptr, "NonNull<T> was set to null");
- return *ptr;
- }
-
- void operator=(T* t) {
- ptr = t;
- MOZ_ASSERT(ptr);
-#ifdef DEBUG
- inited = true;
-#endif
- }
-
- template<typename U>
- void operator=(U* t) {
- ptr = t->ToAStringPtr();
- MOZ_ASSERT(ptr);
-#ifdef DEBUG
- inited = true;
-#endif
- }
-
- T** Slot() {
-#ifdef DEBUG
- inited = true;
-#endif
- return &ptr;
- }
-
-protected:
- T* ptr;
-#ifdef DEBUG
- bool inited;
-#endif
-};
-
-template<class T>
-class OwningNonNull
-{
-public:
- OwningNonNull()
-#ifdef DEBUG
- : inited(false)
-#endif
- {}
-
- operator T&() {
- MOZ_ASSERT(inited);
- MOZ_ASSERT(ptr, "OwningNonNull<T> was set to null");
- return *ptr;
- }
-
- void operator=(T* t) {
- init(t);
- }
-
- void operator=(const already_AddRefed<T>& t) {
- init(t);
- }
-
-protected:
- template<typename U>
- void init(U t) {
- ptr = t;
- MOZ_ASSERT(ptr);
-#ifdef DEBUG
- inited = true;
-#endif
- }
-
- nsRefPtr<T> ptr;
-#ifdef DEBUG
- bool inited;
-#endif
-};
-
-// A struct that has the same layout as an nsDependentString but much
-// faster constructor and destructor behavior
-struct FakeDependentString {
- FakeDependentString() :
- mFlags(nsDependentString::F_TERMINATED)
- {
- }
-
- void SetData(const nsDependentString::char_type* aData,
- nsDependentString::size_type aLength) {
- MOZ_ASSERT(mFlags == nsDependentString::F_TERMINATED);
- mData = aData;
- mLength = aLength;
- }
-
- void Truncate() {
- mData = nsDependentString::char_traits::sEmptyBuffer;
- mLength = 0;
- }
-
- void SetNull() {
- Truncate();
- mFlags |= nsDependentString::F_VOIDED;
- }
-
- const nsAString* ToAStringPtr() const {
- return reinterpret_cast<const nsDependentString*>(this);
- }
-
- nsAString* ToAStringPtr() {
- return reinterpret_cast<nsDependentString*>(this);
- }
-
- operator const nsAString& () const {
- return *reinterpret_cast<const nsDependentString*>(this);
- }
-
-private:
- const nsDependentString::char_type* mData;
- nsDependentString::size_type mLength;
- uint32_t mFlags;
-
- // A class to use for our static asserts to ensure our object layout
- // matches that of nsDependentString.
- class DependentStringAsserter;
- friend class DependentStringAsserter;
-
- class DepedentStringAsserter : public nsDependentString {
- public:
- static void StaticAsserts() {
- MOZ_STATIC_ASSERT(sizeof(FakeDependentString) == sizeof(nsDependentString),
- "Must have right object size");
- MOZ_STATIC_ASSERT(offsetof(FakeDependentString, mData) ==
- offsetof(DepedentStringAsserter, mData),
- "Offset of mData should match");
- MOZ_STATIC_ASSERT(offsetof(FakeDependentString, mLength) ==
- offsetof(DepedentStringAsserter, mLength),
- "Offset of mLength should match");
- MOZ_STATIC_ASSERT(offsetof(FakeDependentString, mFlags) ==
- offsetof(DepedentStringAsserter, mFlags),
- "Offset of mFlags should match");
- }
- };
-};
-
-enum StringificationBehavior {
- eStringify,
- eEmpty,
- eNull
-};
-
-// pval must not be null and must point to a rooted JS::Value
-static inline bool
-ConvertJSValueToString(JSContext* cx, const JS::Value& v, JS::Value* pval,
- StringificationBehavior nullBehavior,
- StringificationBehavior undefinedBehavior,
- FakeDependentString& result)
-{
- JSString *s;
- if (v.isString()) {
- s = v.toString();
- } else {
- StringificationBehavior behavior;
- if (v.isNull()) {
- behavior = nullBehavior;
- } else if (v.isUndefined()) {
- behavior = undefinedBehavior;
- } else {
- behavior = eStringify;
- }
-
- if (behavior != eStringify) {
- if (behavior == eEmpty) {
- result.Truncate();
- } else {
- result.SetNull();
- }
- return true;
- }
-
- s = JS_ValueToString(cx, v);
- if (!s) {
- return false;
- }
- pval->setString(s); // Root the new string.
- }
-
- size_t len;
- const jschar *chars = JS_GetStringCharsZAndLength(cx, s, &len);
- if (!chars) {
- return false;
- }
-
- result.SetData(chars, len);
- return true;
-}
-
-// Class for representing optional arguments.
-template<typename T>
-class Optional {
-public:
- Optional() {}
-
- bool WasPassed() const {
- return !mImpl.empty();
- }
-
- void Construct() {
- mImpl.construct();
- }
-
- template <class T1, class T2>
- void Construct(const T1 &t1, const T2 &t2) {
- mImpl.construct(t1, t2);
- }
-
- const T& Value() const {
- return mImpl.ref();
- }
-
- T& Value() {
- return mImpl.ref();
- }
-
-private:
- // Forbid copy-construction and assignment
- Optional(const Optional& other) MOZ_DELETE;
- const Optional &operator=(const Optional &other) MOZ_DELETE;
-
- Maybe<T> mImpl;
-};
-
-// Specialization for strings.
-template<>
-class Optional<nsAString> {
-public:
- Optional() : mPassed(false) {}
-
- bool WasPassed() const {
- return mPassed;
- }
-
- void operator=(const nsAString* str) {
- MOZ_ASSERT(str);
- mStr = str;
- mPassed = true;
- }
-
- void operator=(const FakeDependentString* str) {
- MOZ_ASSERT(str);
- mStr = str->ToAStringPtr();
- mPassed = true;
- }
-
- const nsAString& Value() const {
- MOZ_ASSERT(WasPassed());
- return *mStr;
- }
-
-private:
- // Forbid copy-construction and assignment
- Optional(const Optional& other) MOZ_DELETE;
- const Optional &operator=(const Optional &other) MOZ_DELETE;
-
- bool mPassed;
- const nsAString* mStr;
-};
-
-// Class for representing sequences in arguments. We use an auto array that can
-// hold 16 elements, to avoid having to allocate in common cases. This needs to
-// be fallible because web content controls the length of the array, and can
-// easily try to create very large lengths.
-template<typename T>
-class Sequence : public AutoFallibleTArray<T, 16>
-{
-public:
- Sequence() : AutoFallibleTArray<T, 16>() {}
-};
-
-// Class for holding the type of members of a union. The union type has an enum
-// to keep track of which of its UnionMembers has been constructed.
-template<class T>
-class UnionMember {
- AlignedStorage2<T> storage;
-
-public:
- T& SetValue() {
- new (storage.addr()) T();
- return *storage.addr();
- }
- const T& Value() const {
- return *storage.addr();
- }
- void Destroy() {
- storage.addr()->~T();
- }
-};
-
-// Implementation of the bits that XrayWrapper needs
-bool
-XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
- JSPropertyDescriptor* desc,
- // And the things we need to determine the descriptor
- Prefable<JSFunctionSpec>* methods,
- jsid* methodIds,
- JSFunctionSpec* methodSpecs,
- size_t methodCount,
- Prefable<JSPropertySpec>* attributes,
- jsid* attributeIds,
- JSPropertySpec* attributeSpecs,
- size_t attributeCount,
- Prefable<ConstantSpec>* constants,
- jsid* constantIds,
- ConstantSpec* constantSpecs,
- size_t constantCount);
-
-bool
-XrayEnumerateProperties(JS::AutoIdVector& props,
- Prefable<JSFunctionSpec>* methods,
- jsid* methodIds,
- JSFunctionSpec* methodSpecs,
- size_t methodCount,
- Prefable<JSPropertySpec>* attributes,
- jsid* attributeIds,
- JSPropertySpec* attributeSpecs,
- size_t attributeCount,
- Prefable<ConstantSpec>* constants,
- jsid* constantIds,
- ConstantSpec* constantSpecs,
- size_t constantCount);
-
-} // namespace dom
-} // namespace mozilla
-
-#endif /* mozilla_dom_BindingUtils_h__ */