aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorCorey Farwell <coreyf@rwell.org>2015-07-09 07:09:52 +0900
committerCorey Farwell <coreyf@rwell.org>2015-07-09 07:25:14 +0900
commit1ce089abf47e9aa62e862c9e1d875727c4297c07 (patch)
treee37d94ca816b35e5015515b7efb86968a9270bba /components/script/dom
parent805232a85e401f1a07635da894c8e7d05fed4ce9 (diff)
downloadservo-1ce089abf47e9aa62e862c9e1d875727c4297c07.tar.gz
servo-1ce089abf47e9aa62e862c9e1d875727c4297c07.zip
Remove unused files in 'script/dom/bindings/'
As per this conversation: https://github.com/servo/servo/pull/6580
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/bindings/codegen/BindingUtils.cpp633
-rw-r--r--components/script/dom/bindings/codegen/BindingUtils.h1151
-rw-r--r--components/script/dom/bindings/codegen/Codegen.py5788
-rw-r--r--components/script/dom/bindings/codegen/DOMJSClass.h114
-rw-r--r--components/script/dom/bindings/codegen/DOMJSProxyHandler.cpp247
-rw-r--r--components/script/dom/bindings/codegen/DOMJSProxyHandler.h109
-rw-r--r--components/script/dom/bindings/codegen/ErrorResult.h59
-rw-r--r--components/script/dom/bindings/codegen/GlobalGen.py2
-rw-r--r--components/script/dom/bindings/codegen/Nullable.h68
-rw-r--r--components/script/dom/bindings/codegen/PrimitiveConversions.h350
-rw-r--r--components/script/dom/bindings/codegen/RegisterBindings.h14
-rw-r--r--components/script/dom/bindings/codegen/TypedArray.h121
12 files changed, 0 insertions, 8656 deletions
diff --git a/components/script/dom/bindings/codegen/BindingUtils.cpp b/components/script/dom/bindings/codegen/BindingUtils.cpp
deleted file mode 100644
index 27ac92e3596..00000000000
--- a/components/script/dom/bindings/codegen/BindingUtils.cpp
+++ /dev/null
@@ -1,633 +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/. */
-
-#include <stdarg.h>
-
-#include "BindingUtils.h"
-
-#include "WrapperFactory.h"
-#include "xpcprivate.h"
-#include "XPCQuickStubs.h"
-
-namespace mozilla {
-namespace dom {
-
-JSErrorFormatString ErrorFormatString[] = {
-#define MSG_DEF(_name, _argc, _str) \
- { _str, _argc, JSEXN_TYPEERR },
-#include "mozilla/dom/Errors.msg"
-#undef MSG_DEF
-};
-
-const JSErrorFormatString*
-GetErrorMessage(void* aUserRef, const char* aLocale,
- const unsigned aErrorNumber)
-{
- MOZ_ASSERT(aErrorNumber < ArrayLength(ErrorFormatString));
- return &ErrorFormatString[aErrorNumber];
-}
-
-bool
-ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...)
-{
- va_list ap;
- va_start(ap, aErrorNumber);
- JS_ReportErrorNumberVA(aCx, GetErrorMessage, NULL,
- static_cast<const unsigned>(aErrorNumber), ap);
- va_end(ap);
- return false;
-}
-
-bool
-DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs)
-{
- for (; cs->name; ++cs) {
- JSBool ok =
- JS_DefineProperty(cx, obj, cs->name, cs->value, NULL, NULL,
- JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
- if (!ok) {
- return false;
- }
- }
- return true;
-}
-
-static inline bool
-Define(JSContext* cx, JSObject* obj, JSFunctionSpec* spec) {
- return JS_DefineFunctions(cx, obj, spec);
-}
-static inline bool
-Define(JSContext* cx, JSObject* obj, JSPropertySpec* spec) {
- return JS_DefineProperties(cx, obj, spec);
-}
-static inline bool
-Define(JSContext* cx, JSObject* obj, ConstantSpec* spec) {
- return DefineConstants(cx, obj, spec);
-}
-
-template<typename T>
-bool
-DefinePrefable(JSContext* cx, JSObject* obj, Prefable<T>* props)
-{
- MOZ_ASSERT(props);
- MOZ_ASSERT(props->specs);
- do {
- // Define if enabled
- if (props->enabled) {
- if (!Define(cx, obj, props->specs)) {
- return false;
- }
- }
- } while ((++props)->specs);
- return true;
-}
-
-// We should use JSFunction objects for interface objects, but we need a custom
-// hasInstance hook because we have new interface objects on prototype chains of
-// old (XPConnect-based) bindings. Because Function.prototype.toString throws if
-// passed a non-Function object we also need to provide our own toString method
-// for interface objects.
-
-enum {
- TOSTRING_CLASS_RESERVED_SLOT = 0,
- TOSTRING_NAME_RESERVED_SLOT = 1
-};
-
-JSBool
-InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp)
-{
- JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
-
- JSObject* obj = JS_THIS_OBJECT(cx, vp);
- if (!obj) {
- JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,
- "null", "object");
- return false;
- }
-
- jsval v = js::GetFunctionNativeReserved(callee, TOSTRING_CLASS_RESERVED_SLOT);
- JSClass* clasp = static_cast<JSClass*>(JSVAL_TO_PRIVATE(v));
-
- v = js::GetFunctionNativeReserved(callee, TOSTRING_NAME_RESERVED_SLOT);
- JSString* jsname = static_cast<JSString*>(JSVAL_TO_STRING(v));
- size_t length;
- const jschar* name = JS_GetInternedStringCharsAndLength(jsname, &length);
-
- if (js::GetObjectJSClass(obj) != clasp) {
- JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
- NS_ConvertUTF16toUTF8(name).get(), "toString",
- "object");
- return false;
- }
-
- nsString str;
- str.AppendLiteral("function ");
- str.Append(name, length);
- str.AppendLiteral("() {");
- str.Append('\n');
- str.AppendLiteral(" [native code]");
- str.Append('\n');
- str.AppendLiteral("}");
-
- return xpc::NonVoidStringToJsval(cx, str, vp);
-}
-
-static JSObject*
-CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
- JSClass* constructorClass, JSNative constructorNative,
- unsigned ctorNargs, JSObject* proto,
- Prefable<JSFunctionSpec>* staticMethods,
- Prefable<ConstantSpec>* constants,
- const char* name)
-{
- JSObject* constructor;
- if (constructorClass) {
- JSObject* functionProto = JS_GetFunctionPrototype(cx, global);
- if (!functionProto) {
- return NULL;
- }
- constructor = JS_NewObject(cx, constructorClass, functionProto, global);
- } else {
- MOZ_ASSERT(constructorNative);
- JSFunction* fun = JS_NewFunction(cx, constructorNative, ctorNargs,
- JSFUN_CONSTRUCTOR, global, name);
- if (!fun) {
- return NULL;
- }
- constructor = JS_GetFunctionObject(fun);
- }
- if (!constructor) {
- return NULL;
- }
-
- if (staticMethods && !DefinePrefable(cx, constructor, staticMethods)) {
- return NULL;
- }
-
- if (constructorClass) {
- JSFunction* toString = js::DefineFunctionWithReserved(cx, constructor,
- "toString",
- InterfaceObjectToString,
- 0, 0);
- if (!toString) {
- return NULL;
- }
-
- JSObject* toStringObj = JS_GetFunctionObject(toString);
- js::SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT,
- PRIVATE_TO_JSVAL(constructorClass));
-
- JSString *str = ::JS_InternString(cx, name);
- if (!str) {
- return NULL;
- }
- js::SetFunctionNativeReserved(toStringObj, TOSTRING_NAME_RESERVED_SLOT,
- STRING_TO_JSVAL(str));
- }
-
- if (constants && !DefinePrefable(cx, constructor, constants)) {
- return NULL;
- }
-
- if (proto && !JS_LinkConstructorAndPrototype(cx, constructor, proto)) {
- return NULL;
- }
-
- JSBool alreadyDefined;
- if (!JS_AlreadyHasOwnProperty(cx, receiver, name, &alreadyDefined)) {
- return NULL;
- }
-
- // This is Enumerable: False per spec.
- if (!alreadyDefined &&
- !JS_DefineProperty(cx, receiver, name, OBJECT_TO_JSVAL(constructor), NULL,
- NULL, 0)) {
- return NULL;
- }
-
- return constructor;
-}
-
-static JSObject*
-CreateInterfacePrototypeObject(JSContext* cx, JSObject* global,
- JSObject* parentProto, JSClass* protoClass,
- Prefable<JSFunctionSpec>* methods,
- Prefable<JSPropertySpec>* properties,
- Prefable<ConstantSpec>* constants)
-{
- JSObject* ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto,
- global);
- if (!ourProto) {
- return NULL;
- }
-
- if (methods && !DefinePrefable(cx, ourProto, methods)) {
- return NULL;
- }
-
- if (properties && !DefinePrefable(cx, ourProto, properties)) {
- return NULL;
- }
-
- if (constants && !DefinePrefable(cx, ourProto, constants)) {
- return NULL;
- }
-
- return ourProto;
-}
-
-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)
-{
- MOZ_ASSERT(protoClass || constructorClass || constructor,
- "Need at least one class or a constructor!");
- MOZ_ASSERT(!(methods || properties) || protoClass,
- "Methods or properties but no protoClass!");
- MOZ_ASSERT(!staticMethods || constructorClass || constructor,
- "Static methods but no constructorClass or constructor!");
- MOZ_ASSERT(bool(name) == bool(constructorClass || constructor),
- "Must have name precisely when we have an interface object");
- MOZ_ASSERT(!constructorClass || !constructor);
-
- JSObject* proto;
- if (protoClass) {
- proto = CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
- methods, properties, constants);
- if (!proto) {
- return NULL;
- }
-
- js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
- JS::PrivateValue(const_cast<DOMClass*>(domClass)));
- }
- else {
- proto = NULL;
- }
-
- JSObject* interface;
- if (constructorClass || constructor) {
- interface = CreateInterfaceObject(cx, global, receiver, constructorClass,
- constructor, ctorNargs, proto,
- staticMethods, constants, name);
- if (!interface) {
- return NULL;
- }
- }
-
- return protoClass ? proto : interface;
-}
-
-static bool
-NativeInterface2JSObjectAndThrowIfFailed(XPCLazyCallContext& aLccx,
- JSContext* aCx,
- JS::Value* aRetval,
- xpcObjectHelper& aHelper,
- const nsIID* aIID,
- bool aAllowNativeWrapper)
-{
- nsresult rv;
- if (!XPCConvert::NativeInterface2JSObject(aLccx, aRetval, NULL, aHelper, aIID,
- NULL, aAllowNativeWrapper, &rv)) {
- // I can't tell if NativeInterface2JSObject throws JS exceptions
- // or not. This is a sloppy stab at the right semantics; the
- // method really ought to be fixed to behave consistently.
- if (!JS_IsExceptionPending(aCx)) {
- Throw<true>(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
- }
- return false;
- }
- return true;
-}
-
-bool
-DoHandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope,
- nsISupports* value, JS::Value* vp)
-{
- if (JS_IsExceptionPending(cx)) {
- return false;
- }
-
- XPCLazyCallContext lccx(JS_CALLER, cx, scope);
-
- if (value) {
- xpcObjectHelper helper(value);
- return NativeInterface2JSObjectAndThrowIfFailed(lccx, cx, vp, helper, NULL,
- true);
- }
-
- return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
-}
-
-// 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)
-{
- const DOMClass* domClass = static_cast<DOMClass*>(
- js::GetReservedSlot(protoObject, DOM_PROTO_INSTANCE_CLASS_SLOT).toPrivate());
- return (uint32_t)domClass->mInterfaceChain[depth] == protoID;
-}
-
-// 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)
-{
- XPCLazyCallContext lccx(JS_CALLER, cx, scope);
-
- if (!NativeInterface2JSObjectAndThrowIfFailed(lccx, cx, rval, helper, iid,
- allowNativeWrapper)) {
- return false;
- }
-
-#ifdef DEBUG
- JSObject* jsobj = JSVAL_TO_OBJECT(*rval);
- if (jsobj && !js::GetObjectParent(jsobj))
- NS_ASSERTION(js::GetObjectClass(jsobj)->flags & JSCLASS_IS_GLOBAL,
- "Why did we recreate this wrapper?");
-#endif
-
- return true;
-}
-
-JSBool
-QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
-{
- JS::Value thisv = JS_THIS(cx, vp);
- if (thisv == JSVAL_NULL)
- return false;
-
- // Get the object. It might be a security wrapper, in which case we do a checked
- // unwrap.
- JSObject* origObj = JSVAL_TO_OBJECT(thisv);
- JSObject* obj = js::UnwrapObjectChecked(cx, origObj);
- if (!obj)
- return false;
-
- nsISupports* native;
- if (!UnwrapDOMObjectToISupports(obj, native)) {
- return Throw<true>(cx, NS_ERROR_FAILURE);
- }
-
- if (argc < 1) {
- return Throw<true>(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
- }
-
- JS::Value* argv = JS_ARGV(cx, vp);
- if (!argv[0].isObject()) {
- return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
- }
-
- nsIJSIID* iid;
- xpc_qsSelfRef iidRef;
- if (NS_FAILED(xpc_qsUnwrapArg<nsIJSIID>(cx, argv[0], &iid, &iidRef.ptr,
- &argv[0]))) {
- return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
- }
- MOZ_ASSERT(iid);
-
- if (iid->GetID()->Equals(NS_GET_IID(nsIClassInfo))) {
- nsresult rv;
- nsCOMPtr<nsIClassInfo> ci = do_QueryInterface(native, &rv);
- if (NS_FAILED(rv)) {
- return Throw<true>(cx, rv);
- }
-
- return WrapObject(cx, origObj, ci, &NS_GET_IID(nsIClassInfo), vp);
- }
-
- // Lie, otherwise we need to check classinfo or QI
- *vp = thisv;
- return true;
-}
-
-JSBool
-ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
-{
- return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
-}
-
-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)
-{
- for (size_t prefIdx = 0; prefIdx < methodCount; ++prefIdx) {
- MOZ_ASSERT(methods[prefIdx].specs);
- if (methods[prefIdx].enabled) {
- // Set i to be the index into our full list of ids/specs that we're
- // looking at now.
- size_t i = methods[prefIdx].specs - methodSpecs;
- for ( ; methodIds[i] != JSID_VOID; ++i) {
- if (id == methodIds[i]) {
- JSFunction *fun = JS_NewFunctionById(cx, methodSpecs[i].call.op,
- methodSpecs[i].nargs, 0,
- wrapper, id);
- if (!fun) {
- return false;
- }
- SET_JITINFO(fun, methodSpecs[i].call.info);
- JSObject *funobj = JS_GetFunctionObject(fun);
- desc->value.setObject(*funobj);
- desc->attrs = methodSpecs[i].flags;
- desc->obj = wrapper;
- desc->setter = nullptr;
- desc->getter = nullptr;
- return true;
- }
- }
- }
- }
-
- for (size_t prefIdx = 0; prefIdx < attributeCount; ++prefIdx) {
- MOZ_ASSERT(attributes[prefIdx].specs);
- if (attributes[prefIdx].enabled) {
- // Set i to be the index into our full list of ids/specs that we're
- // looking at now.
- size_t i = attributes[prefIdx].specs - attributeSpecs;
- for ( ; attributeIds[i] != JSID_VOID; ++i) {
- if (id == attributeIds[i]) {
- // Because of centralization, we need to make sure we fault in the
- // JitInfos as well. At present, until the JSAPI changes, the easiest
- // way to do this is wrap them up as functions ourselves.
- desc->attrs = attributeSpecs[i].flags & ~JSPROP_NATIVE_ACCESSORS;
- // They all have getters, so we can just make it.
- JSObject *global = JS_GetGlobalForObject(cx, wrapper);
- JSFunction *fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].getter.op,
- 0, 0, global, NULL);
- if (!fun)
- return false;
- SET_JITINFO(fun, attributeSpecs[i].getter.info);
- JSObject *funobj = JS_GetFunctionObject(fun);
- desc->getter = js::CastAsJSPropertyOp(funobj);
- desc->attrs |= JSPROP_GETTER;
- if (attributeSpecs[i].setter.op) {
- // We have a setter! Make it.
- fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].setter.op,
- 1, 0, global, NULL);
- if (!fun)
- return false;
- SET_JITINFO(fun, attributeSpecs[i].setter.info);
- funobj = JS_GetFunctionObject(fun);
- desc->setter = js::CastAsJSStrictPropertyOp(funobj);
- desc->attrs |= JSPROP_SETTER;
- } else {
- desc->setter = NULL;
- }
- desc->obj = wrapper;
- return true;
- }
- }
- }
- }
-
- for (size_t prefIdx = 0; prefIdx < constantCount; ++prefIdx) {
- MOZ_ASSERT(constants[prefIdx].specs);
- if (constants[prefIdx].enabled) {
- // Set i to be the index into our full list of ids/specs that we're
- // looking at now.
- size_t i = constants[prefIdx].specs - constantSpecs;
- for ( ; constantIds[i] != JSID_VOID; ++i) {
- if (id == constantIds[i]) {
- desc->attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
- desc->obj = wrapper;
- desc->value = constantSpecs[i].value;
- return true;
- }
- }
- }
- }
-
- return true;
-}
-
-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)
-{
- for (size_t prefIdx = 0; prefIdx < methodCount; ++prefIdx) {
- MOZ_ASSERT(methods[prefIdx].specs);
- if (methods[prefIdx].enabled) {
- // Set i to be the index into our full list of ids/specs that we're
- // looking at now.
- size_t i = methods[prefIdx].specs - methodSpecs;
- for ( ; methodIds[i] != JSID_VOID; ++i) {
- if ((methodSpecs[i].flags & JSPROP_ENUMERATE) &&
- !props.append(methodIds[i])) {
- return false;
- }
- }
- }
- }
-
- for (size_t prefIdx = 0; prefIdx < attributeCount; ++prefIdx) {
- MOZ_ASSERT(attributes[prefIdx].specs);
- if (attributes[prefIdx].enabled) {
- // Set i to be the index into our full list of ids/specs that we're
- // looking at now.
- size_t i = attributes[prefIdx].specs - attributeSpecs;
- for ( ; attributeIds[i] != JSID_VOID; ++i) {
- if ((attributeSpecs[i].flags & JSPROP_ENUMERATE) &&
- !props.append(attributeIds[i])) {
- return false;
- }
- }
- }
- }
-
- for (size_t prefIdx = 0; prefIdx < constantCount; ++prefIdx) {
- MOZ_ASSERT(constants[prefIdx].specs);
- if (constants[prefIdx].enabled) {
- // Set i to be the index into our full list of ids/specs that we're
- // looking at now.
- size_t i = constants[prefIdx].specs - constantSpecs;
- for ( ; constantIds[i] != JSID_VOID; ++i) {
- if (!props.append(constantIds[i])) {
- return false;
- }
- }
- }
- }
-
- return true;
-}
-
-bool
-GetPropertyOnPrototype(JSContext* cx, JSObject* proxy, jsid id, bool* found,
- JS::Value* vp)
-{
- JSObject* proto;
- if (!js::GetObjectProto(cx, proxy, &proto)) {
- return false;
- }
- if (!proto) {
- *found = false;
- return true;
- }
-
- JSBool hasProp;
- if (!JS_HasPropertyById(cx, proto, id, &hasProp)) {
- return false;
- }
-
- *found = hasProp;
- if (!hasProp || !vp) {
- return true;
- }
-
- return JS_ForwardGetPropertyTo(cx, proto, id, proxy, vp);
-}
-
-bool
-HasPropertyOnPrototype(JSContext* cx, JSObject* proxy, DOMProxyHandler* handler,
- jsid id)
-{
- Maybe<JSAutoCompartment> ac;
- if (xpc::WrapperFactory::IsXrayWrapper(proxy)) {
- proxy = js::UnwrapObject(proxy);
- ac.construct(cx, proxy);
- }
- MOZ_ASSERT(js::IsProxy(proxy) && js::GetProxyHandler(proxy) == handler);
-
- bool found;
- // We ignore an error from GetPropertyOnPrototype.
- return !GetPropertyOnPrototype(cx, proxy, id, &found, NULL) || found;
-}
-
-} // namespace dom
-} // namespace mozilla
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__ */
diff --git a/components/script/dom/bindings/codegen/Codegen.py b/components/script/dom/bindings/codegen/Codegen.py
deleted file mode 100644
index 6d2cc0bde36..00000000000
--- a/components/script/dom/bindings/codegen/Codegen.py
+++ /dev/null
@@ -1,5788 +0,0 @@
-# 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/.
-
-# Common codegen classes.
-
-import os
-import string
-import operator
-
-from WebIDL import *
-from Configuration import NoSuchDescriptorError
-
-AUTOGENERATED_WARNING_COMMENT = \
- "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
-ADDPROPERTY_HOOK_NAME = '_addProperty'
-FINALIZE_HOOK_NAME = '_finalize'
-TRACE_HOOK_NAME = '_trace'
-CONSTRUCT_HOOK_NAME = '_constructor'
-HASINSTANCE_HOOK_NAME = '_hasInstance'
-
-def replaceFileIfChanged(filename, newContents):
- """
- Read a copy of the old file, so that we don't touch it if it hasn't changed.
- Returns True if the file was updated, false otherwise.
- """
- oldFileContents = ""
- try:
- oldFile = open(filename, 'rb')
- oldFileContents = ''.join(oldFile.readlines())
- oldFile.close()
- except:
- pass
-
- if newContents == oldFileContents:
- return False
-
- f = open(filename, 'wb')
- f.write(newContents)
- f.close()
-
-def toStringBool(arg):
- return str(not not arg).lower()
-
-def toBindingNamespace(arg):
- return re.sub("((_workers)?$)", "Binding\\1", arg);
-
-class CGThing():
- """
- Abstract base class for things that spit out code.
- """
- def __init__(self):
- pass # Nothing for now
- def declare(self):
- """Produce code for a header file."""
- assert(False) # Override me!
- def define(self):
- """Produce code for a cpp file."""
- assert(False) # Override me!
-
-class CGNativePropertyHooks(CGThing):
- """
- Generate a NativePropertyHooks for a given descriptor
- """
- def __init__(self, descriptor):
- CGThing.__init__(self)
- self.descriptor = descriptor
- def declare(self):
- if self.descriptor.workers:
- return ""
- return "extern const NativePropertyHooks NativeHooks;\n"
- def define(self):
- if self.descriptor.workers:
- return ""
- if self.descriptor.concrete and self.descriptor.proxy:
- resolveOwnProperty = "ResolveOwnProperty"
- enumerateOwnProperties = "EnumerateOwnProperties"
- else:
- enumerateOwnProperties = resolveOwnProperty = "NULL"
- parent = self.descriptor.interface.parent
- parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::NativeHooks"
- if parent else 'NULL')
- return """
-const NativePropertyHooks NativeHooks = { %s, ResolveProperty, %s, EnumerateProperties, %s };
-""" % (resolveOwnProperty, enumerateOwnProperties, parentHooks)
-
-def DOMClass(descriptor):
- protoList = ['prototypes::id::' + proto for proto in descriptor.prototypeChain]
- # Pad out the list to the right length with _ID_Count so we
- # guarantee that all the lists are the same length. _ID_Count
- # is never the ID of any prototype, so it's safe to use as
- # padding.
- protoList.extend(['prototypes::id::_ID_Count'] * (descriptor.config.maxProtoChainLength - len(protoList)))
- prototypeChainString = ', '.join(protoList)
- nativeHooks = "NULL" if descriptor.workers else "&NativeHooks"
- return """{
- { %s },
- %s, %s
-}""" % (prototypeChainString, toStringBool(descriptor.nativeIsISupports),
- nativeHooks)
-
-class CGDOMJSClass(CGThing):
- """
- Generate a DOMJSClass for a given descriptor
- """
- def __init__(self, descriptor):
- CGThing.__init__(self)
- self.descriptor = descriptor
- def declare(self):
- return "extern DOMJSClass Class;\n"
- def define(self):
- traceHook = TRACE_HOOK_NAME if self.descriptor.customTrace else 'NULL'
- return """
-DOMJSClass Class = {
- { "%s",
- JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1),
- %s, /* addProperty */
- JS_PropertyStub, /* delProperty */
- JS_PropertyStub, /* getProperty */
- JS_StrictPropertyStub, /* setProperty */
- JS_EnumerateStub,
- JS_ResolveStub,
- JS_ConvertStub,
- %s, /* finalize */
- NULL, /* checkAccess */
- NULL, /* call */
- NULL, /* hasInstance */
- NULL, /* construct */
- %s, /* trace */
- JSCLASS_NO_INTERNAL_MEMBERS
- },
- %s
-};
-""" % (self.descriptor.interface.identifier.name,
- ADDPROPERTY_HOOK_NAME if self.descriptor.concrete and not self.descriptor.workers and self.descriptor.wrapperCache else 'JS_PropertyStub',
- FINALIZE_HOOK_NAME, traceHook,
- CGIndenter(CGGeneric(DOMClass(self.descriptor))).define())
-
-class CGPrototypeJSClass(CGThing):
- def __init__(self, descriptor):
- CGThing.__init__(self)
- self.descriptor = descriptor
- def declare(self):
- # We're purely for internal consumption
- return ""
- def define(self):
- return """static JSClass PrototypeClass = {
- "%sPrototype",
- JSCLASS_HAS_RESERVED_SLOTS(1),
- JS_PropertyStub, /* addProperty */
- JS_PropertyStub, /* delProperty */
- JS_PropertyStub, /* getProperty */
- JS_StrictPropertyStub, /* setProperty */
- JS_EnumerateStub,
- JS_ResolveStub,
- JS_ConvertStub,
- NULL, /* finalize */
- NULL, /* checkAccess */
- NULL, /* call */
- NULL, /* hasInstance */
- NULL, /* construct */
- NULL, /* trace */
- JSCLASS_NO_INTERNAL_MEMBERS
-};
-""" % (self.descriptor.interface.identifier.name)
-
-class CGInterfaceObjectJSClass(CGThing):
- def __init__(self, descriptor):
- CGThing.__init__(self)
- self.descriptor = descriptor
- def declare(self):
- # We're purely for internal consumption
- return ""
- def define(self):
- if not self.descriptor.hasInstanceInterface:
- return ""
- ctorname = "NULL" if not self.descriptor.interface.ctor() else CONSTRUCT_HOOK_NAME
- hasinstance = HASINSTANCE_HOOK_NAME
- return """
-static JSClass InterfaceObjectClass = {
- "Function", 0,
- JS_PropertyStub, /* addProperty */
- JS_PropertyStub, /* delProperty */
- JS_PropertyStub, /* getProperty */
- JS_StrictPropertyStub, /* setProperty */
- JS_EnumerateStub,
- JS_ResolveStub,
- JS_ConvertStub,
- NULL, /* finalize */
- NULL, /* checkAccess */
- %s, /* call */
- %s, /* hasInstance */
- %s, /* construct */
- NULL, /* trace */
- JSCLASS_NO_INTERNAL_MEMBERS
-};
-""" % (ctorname, hasinstance, ctorname)
-
-class CGList(CGThing):
- """
- Generate code for a list of GCThings. Just concatenates them together, with
- an optional joiner string. "\n" is a common joiner.
- """
- def __init__(self, children, joiner=""):
- CGThing.__init__(self)
- self.children = children
- self.joiner = joiner
- def append(self, child):
- self.children.append(child)
- def prepend(self, child):
- self.children.insert(0, child)
- def join(self, generator):
- return self.joiner.join(filter(lambda s: len(s) > 0, (child for child in generator)))
- def declare(self):
- return self.join(child.declare() for child in self.children if child is not None)
- def define(self):
- return self.join(child.define() for child in self.children if child is not None)
-
-class CGGeneric(CGThing):
- """
- A class that spits out a fixed string into the codegen. Can spit out a
- separate string for the declaration too.
- """
- def __init__(self, define="", declare=""):
- self.declareText = declare
- self.defineText = define
- def declare(self):
- return self.declareText
- def define(self):
- return self.defineText
-
-# We'll want to insert the indent at the beginnings of lines, but we
-# don't want to indent empty lines. So only indent lines that have a
-# non-newline character on them.
-lineStartDetector = re.compile("^(?=[^\n#])", re.MULTILINE)
-class CGIndenter(CGThing):
- """
- A class that takes another CGThing and generates code that indents that
- CGThing by some number of spaces. The default indent is two spaces.
- """
- def __init__(self, child, indentLevel=2, declareOnly=False):
- CGThing.__init__(self)
- self.child = child
- self.indent = " " * indentLevel
- self.declareOnly = declareOnly
- def declare(self):
- decl = self.child.declare()
- if decl is not "":
- return re.sub(lineStartDetector, self.indent, decl)
- else:
- return ""
- def define(self):
- defn = self.child.define()
- if defn is not "" and not self.declareOnly:
- return re.sub(lineStartDetector, self.indent, defn)
- else:
- return defn
-
-class CGWrapper(CGThing):
- """
- Generic CGThing that wraps other CGThings with pre and post text.
- """
- def __init__(self, child, pre="", post="", declarePre=None,
- declarePost=None, definePre=None, definePost=None,
- declareOnly=False, defineOnly=False, reindent=False):
- CGThing.__init__(self)
- self.child = child
- self.declarePre = declarePre or pre
- self.declarePost = declarePost or post
- self.definePre = definePre or pre
- self.definePost = definePost or post
- self.declareOnly = declareOnly
- self.defineOnly = defineOnly
- self.reindent = reindent
- def declare(self):
- if self.defineOnly:
- return ''
- decl = self.child.declare()
- if self.reindent:
- # We don't use lineStartDetector because we don't want to
- # insert whitespace at the beginning of our _first_ line.
- decl = stripTrailingWhitespace(
- decl.replace("\n", "\n" + (" " * len(self.declarePre))))
- return self.declarePre + decl + self.declarePost
- def define(self):
- if self.declareOnly:
- return ''
- defn = self.child.define()
- if self.reindent:
- # We don't use lineStartDetector because we don't want to
- # insert whitespace at the beginning of our _first_ line.
- defn = stripTrailingWhitespace(
- defn.replace("\n", "\n" + (" " * len(self.definePre))))
- return self.definePre + defn + self.definePost
-
-class CGIfWrapper(CGWrapper):
- def __init__(self, child, condition):
- pre = CGWrapper(CGGeneric(condition), pre="if (", post=") {\n",
- reindent=True)
- CGWrapper.__init__(self, CGIndenter(child), pre=pre.define(),
- post="\n}")
-
-class CGNamespace(CGWrapper):
- def __init__(self, namespace, child, declareOnly=False):
- pre = "namespace %s {\n" % namespace
- post = "} // namespace %s\n" % namespace
- CGWrapper.__init__(self, child, pre=pre, post=post,
- declareOnly=declareOnly)
- @staticmethod
- def build(namespaces, child, declareOnly=False):
- """
- Static helper method to build multiple wrapped namespaces.
- """
- if not namespaces:
- return CGWrapper(child, declareOnly=declareOnly)
- inner = CGNamespace.build(namespaces[1:], child, declareOnly=declareOnly)
- return CGNamespace(namespaces[0], inner, declareOnly=declareOnly)
-
-class CGIncludeGuard(CGWrapper):
- """
- Generates include guards for a header.
- """
- def __init__(self, prefix, child):
- """|prefix| is the filename without the extension."""
- define = 'mozilla_dom_%s_h__' % prefix
- CGWrapper.__init__(self, child,
- declarePre='#ifndef %s\n#define %s\n\n' % (define, define),
- declarePost='\n#endif // %s\n' % define)
-
-def getTypes(descriptor):
- """
- Get all argument and return types for all members of the descriptor
- """
- members = [m for m in descriptor.interface.members]
- if descriptor.interface.ctor():
- members.append(descriptor.interface.ctor())
- signatures = [s for m in members if m.isMethod() for s in m.signatures()]
- types = []
- for s in signatures:
- assert len(s) == 2
- (returnType, arguments) = s
- types.append(returnType)
- types.extend([a.type for a in arguments])
-
- types.extend(a.type for a in members if a.isAttr())
- return types
-
-class CGHeaders(CGWrapper):
- """
- Generates the appropriate include statements.
- """
- def __init__(self, descriptors, dictionaries, declareIncludes,
- defineIncludes, child):
- """
- Builds a set of includes to cover |descriptors|.
-
- Also includes the files in |declareIncludes| in the header
- file and the files in |defineIncludes| in the .cpp.
- """
-
- # Determine the filenames for which we need headers.
- interfaceDeps = [d.interface for d in descriptors]
- ancestors = []
- for iface in interfaceDeps:
- while iface.parent:
- ancestors.append(iface.parent)
- iface = iface.parent
- interfaceDeps.extend(ancestors)
- bindingIncludes = set(self.getDeclarationFilename(d) for d in interfaceDeps)
-
- # Grab all the implementation declaration files we need.
- implementationIncludes = set(d.headerFile for d in descriptors)
-
- # Now find all the things we'll need as arguments because we
- # need to wrap or unwrap them.
- bindingHeaders = set()
- for d in descriptors:
- types = getTypes(d)
- for dictionary in dictionaries:
- curDict = dictionary
- while curDict:
- types.extend([m.type for m in curDict.members])
- curDict = curDict.parent
-
- for t in types:
- if t.unroll().isUnion():
- # UnionConversions.h includes UnionTypes.h
- bindingHeaders.add("mozilla/dom/UnionConversions.h")
- elif t.unroll().isInterface():
- if t.unroll().isSpiderMonkeyInterface():
- bindingHeaders.add("jsfriendapi.h")
- bindingHeaders.add("mozilla/dom/TypedArray.h")
- else:
- typeDesc = d.getDescriptor(t.unroll().inner.identifier.name)
- if typeDesc is not None:
- implementationIncludes.add(typeDesc.headerFile)
- bindingHeaders.add(self.getDeclarationFilename(typeDesc.interface))
- elif t.unroll().isDictionary():
- bindingHeaders.add(self.getDeclarationFilename(t.unroll().inner))
-
- declareIncludes = set(declareIncludes)
- for d in dictionaries:
- if d.parent:
- declareIncludes.add(self.getDeclarationFilename(d.parent))
- bindingHeaders.add(self.getDeclarationFilename(d))
-
- # Let the machinery do its thing.
- def _includeString(includes):
- return ''.join(['#include "%s"\n' % i for i in includes]) + '\n'
- CGWrapper.__init__(self, child,
- declarePre=_includeString(sorted(declareIncludes)),
- definePre=_includeString(sorted(set(defineIncludes) |
- bindingIncludes |
- bindingHeaders |
- implementationIncludes)))
- @staticmethod
- def getDeclarationFilename(decl):
- # Use our local version of the header, not the exported one, so that
- # test bindings, which don't export, will work correctly.
- basename = os.path.basename(decl.filename())
- return basename.replace('.webidl', 'Binding.h')
-
-def SortedTuples(l):
- """
- Sort a list of tuples based on the first item in the tuple
- """
- return sorted(l, key=operator.itemgetter(0))
-
-def SortedDictValues(d):
- """
- Returns a list of values from the dict sorted by key.
- """
- # Create a list of tuples containing key and value, sorted on key.
- d = SortedTuples(d.items())
- # We're only interested in the values.
- return (i[1] for i in d)
-
-def UnionTypes(descriptors):
- """
- Returns a tuple containing a set of header filenames to include, a set of
- tuples containing a type declaration and a boolean if the type is a struct
- for member types of the unions and a CGList containing CGUnionStructs for
- every union.
- """
-
- # Now find all the things we'll need as arguments and return values because
- # we need to wrap or unwrap them.
- headers = set()
- declarations = set()
- unionStructs = dict()
- for d in descriptors:
- if d.interface.isExternal():
- continue
-
- for t in getTypes(d):
- t = t.unroll()
- if t.isUnion():
- name = str(t)
- if not name in unionStructs:
- unionStructs[name] = CGUnionStruct(t, d)
- for f in t.flatMemberTypes:
- f = f.unroll()
- if f.isInterface():
- if f.isSpiderMonkeyInterface():
- headers.add("jsfriendapi.h")
- headers.add("mozilla/dom/TypedArray.h")
- else:
- typeDesc = d.getDescriptor(f.inner.identifier.name)
- if typeDesc is not None:
- declarations.add((typeDesc.nativeType, False))
- elif f.isDictionary():
- declarations.add((f.inner.identifier.name, True))
-
- return (headers, declarations, CGList(SortedDictValues(unionStructs), "\n"))
-
-def UnionConversions(descriptors):
- """
- Returns a CGThing to declare all union argument conversion helper structs.
- """
- # Now find all the things we'll need as arguments because we
- # need to unwrap them.
- unionConversions = dict()
- for d in descriptors:
- if d.interface.isExternal():
- continue
-
- def addUnionTypes(type):
- if type.isUnion():
- type = type.unroll()
- name = str(type)
- if not name in unionConversions:
- unionConversions[name] = CGUnionConversionStruct(type, d)
-
- members = [m for m in d.interface.members]
- if d.interface.ctor():
- members.append(d.interface.ctor())
- signatures = [s for m in members if m.isMethod() for s in m.signatures()]
- for s in signatures:
- assert len(s) == 2
- (_, arguments) = s
- for a in arguments:
- addUnionTypes(a.type)
-
- for m in members:
- if m.isAttr() and not m.readonly:
- addUnionTypes(m.type)
-
- return CGWrapper(CGList(SortedDictValues(unionConversions), "\n"),
- post="\n\n")
-
-class Argument():
- """
- A class for outputting the type and name of an argument
- """
- def __init__(self, argType, name):
- self.argType = argType
- self.name = name
- def __str__(self):
- return self.argType + ' ' + self.name
-
-class CGAbstractMethod(CGThing):
- """
- An abstract class for generating code for a method. Subclasses
- should override definition_body to create the actual code.
-
- descriptor is the descriptor for the interface the method is associated with
-
- name is the name of the method as a string
-
- returnType is the IDLType of the return value
-
- args is a list of Argument objects
-
- inline should be True to generate an inline method, whose body is
- part of the declaration.
-
- alwaysInline should be True to generate an inline method annotated with
- MOZ_ALWAYS_INLINE.
-
- static should be True to generate a static method, which only has
- a definition.
-
- If templateArgs is not None it should be a list of strings containing
- template arguments, and the function will be templatized using those
- arguments.
- """
- def __init__(self, descriptor, name, returnType, args, inline=False, alwaysInline=False, static=False, templateArgs=None):
- CGThing.__init__(self)
- self.descriptor = descriptor
- self.name = name
- self.returnType = returnType
- self.args = args
- self.inline = inline
- self.alwaysInline = alwaysInline
- self.static = static
- self.templateArgs = templateArgs
- def _argstring(self):
- return ', '.join([str(a) for a in self.args])
- def _template(self):
- if self.templateArgs is None:
- return ''
- return 'template <%s>\n' % ', '.join(self.templateArgs)
- def _decorators(self):
- decorators = []
- if self.alwaysInline:
- decorators.append('MOZ_ALWAYS_INLINE')
- elif self.inline:
- decorators.append('inline')
- if self.static:
- decorators.append('static')
- decorators.append(self.returnType)
- maybeNewline = " " if self.inline else "\n"
- return ' '.join(decorators) + maybeNewline
- def declare(self):
- if self.inline:
- return self._define()
- return "%s%s%s(%s);\n" % (self._template(), self._decorators(), self.name, self._argstring())
- def _define(self):
- return self.definition_prologue() + "\n" + self.definition_body() + self.definition_epilogue()
- def define(self):
- return "" if self.inline else self._define()
- def definition_prologue(self):
- return "%s%s%s(%s)\n{" % (self._template(), self._decorators(),
- self.name, self._argstring())
- def definition_epilogue(self):
- return "\n}\n"
- def definition_body(self):
- assert(False) # Override me!
-
-class CGAbstractStaticMethod(CGAbstractMethod):
- """
- Abstract base class for codegen of implementation-only (no
- declaration) static methods.
- """
- def __init__(self, descriptor, name, returnType, args):
- CGAbstractMethod.__init__(self, descriptor, name, returnType, args,
- inline=False, static=True)
- def declare(self):
- # We only have implementation
- return ""
-
-class CGAbstractClassHook(CGAbstractStaticMethod):
- """
- Meant for implementing JSClass hooks, like Finalize or Trace. Does very raw
- 'this' unwrapping as it assumes that the unwrapped type is always known.
- """
- def __init__(self, descriptor, name, returnType, args):
- CGAbstractStaticMethod.__init__(self, descriptor, name, returnType,
- args)
-
- def definition_body_prologue(self):
- return """
- %s* self = UnwrapDOMObject<%s>(obj, eRegularDOMObject);
-""" % (self.descriptor.nativeType, self.descriptor.nativeType)
-
- def definition_body(self):
- return self.definition_body_prologue() + self.generate_code()
-
- def generate_code(self):
- # Override me
- assert(False)
-
-class CGAddPropertyHook(CGAbstractClassHook):
- """
- A hook for addProperty, used to preserve our wrapper from GC.
- """
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
- Argument('JSHandleId', 'id'), Argument('JSMutableHandleValue', 'vp')]
- CGAbstractClassHook.__init__(self, descriptor, ADDPROPERTY_HOOK_NAME,
- 'JSBool', args)
-
- def generate_code(self):
- # FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=774279
- # Using a real trace hook might enable us to deal with non-nsISupports
- # wrappercached things here.
- assert self.descriptor.nativeIsISupports
- return """ nsContentUtils::PreserveWrapper(reinterpret_cast<nsISupports*>(self), self);
- return true;"""
-
-def finalizeHook(descriptor, hookName, context):
- if descriptor.customFinalize:
- return """if (self) {
- self->%s(%s);
-}""" % (hookName, context)
- clearWrapper = "ClearWrapper(self, self);\n" if descriptor.wrapperCache else ""
- if descriptor.workers:
- release = "self->Release();"
- else:
- assert descriptor.nativeIsISupports
- release = """XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
-if (rt) {
- rt->DeferredRelease(reinterpret_cast<nsISupports*>(self));
-} else {
- NS_RELEASE(self);
-}"""
- return clearWrapper + release
-
-class CGClassFinalizeHook(CGAbstractClassHook):
- """
- A hook for finalize, used to release our native object.
- """
- def __init__(self, descriptor):
- args = [Argument('JSFreeOp*', 'fop'), Argument('JSObject*', 'obj')]
- CGAbstractClassHook.__init__(self, descriptor, FINALIZE_HOOK_NAME,
- 'void', args)
-
- def generate_code(self):
- return CGIndenter(CGGeneric(finalizeHook(self.descriptor, self.name, self.args[0].name))).define()
-
-class CGClassTraceHook(CGAbstractClassHook):
- """
- A hook to trace through our native object; used for GC and CC
- """
- def __init__(self, descriptor):
- args = [Argument('JSTracer*', 'trc'), Argument('JSObject*', 'obj')]
- CGAbstractClassHook.__init__(self, descriptor, TRACE_HOOK_NAME, 'void',
- args)
-
- def generate_code(self):
- return """ if (self) {
- self->%s(%s);
- }""" % (self.name, self.args[0].name)
-
-class CGClassConstructHook(CGAbstractStaticMethod):
- """
- JS-visible constructor for our objects
- """
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')]
- CGAbstractStaticMethod.__init__(self, descriptor, CONSTRUCT_HOOK_NAME,
- 'JSBool', args)
- self._ctor = self.descriptor.interface.ctor()
-
- def define(self):
- if not self._ctor:
- return ""
- return CGAbstractStaticMethod.define(self)
-
- def definition_body(self):
- return self.generate_code()
-
- def generate_code(self):
- preamble = """
- JSObject* obj = JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
-"""
- if self.descriptor.workers:
- preArgs = ["cx", "obj"]
- else:
- preamble += """
- nsISupports* global;
- xpc_qsSelfRef globalRef;
- {
- nsresult rv;
- JS::Value val = OBJECT_TO_JSVAL(obj);
- rv = xpc_qsUnwrapArg<nsISupports>(cx, val, &global, &globalRef.ptr, &val);
- if (NS_FAILED(rv)) {
- return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
- }
- }
-"""
- preArgs = ["global"]
-
- name = self._ctor.identifier.name
- nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
- callGenerator = CGMethodCall(preArgs, nativeName, True,
- self.descriptor, self._ctor)
- return preamble + callGenerator.define();
-
-class CGClassHasInstanceHook(CGAbstractStaticMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
- Argument('JSMutableHandleValue', 'vp'), Argument('JSBool*', 'bp')]
- CGAbstractStaticMethod.__init__(self, descriptor, HASINSTANCE_HOOK_NAME,
- 'JSBool', args)
-
- def define(self):
- if not self.descriptor.hasInstanceInterface:
- return ""
- return CGAbstractStaticMethod.define(self)
-
- def definition_body(self):
- return self.generate_code()
-
- def generate_code(self):
- return """ if (!vp.isObject()) {
- *bp = false;
- return true;
- }
-
- jsval protov;
- if (!JS_GetProperty(cx, obj, "prototype", &protov))
- return false;
- if (!protov.isObject()) {
- JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE,
- "%s");
- return false;
- }
- JSObject *objProto = &protov.toObject();
-
- JSObject* instance = &vp.toObject();
- JSObject* proto;
- if (!JS_GetPrototype(cx, instance, &proto))
- return false;
- while (proto) {
- if (proto == objProto) {
- *bp = true;
- return true;
- }
- if (!JS_GetPrototype(cx, proto, &proto))
- return false;
- }
-
- nsISupports* native =
- nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, instance);
- nsCOMPtr<%s> qiResult = do_QueryInterface(native);
- *bp = !!qiResult;
- return true;
-""" % (self.descriptor.name, self.descriptor.hasInstanceInterface)
-
-def isChromeOnly(m):
- return m.getExtendedAttribute("ChromeOnly")
-
-class PropertyDefiner:
- """
- A common superclass for defining things on prototype objects.
-
- Subclasses should implement generateArray to generate the actual arrays of
- things we're defining. They should also set self.chrome to the list of
- things exposed to chrome and self.regular to the list of things exposed to
- web pages. self.chrome must be a superset of self.regular but also include
- all the ChromeOnly stuff.
- """
- def __init__(self, descriptor, name):
- self.descriptor = descriptor
- self.name = name
- # self.prefCacheData will store an array of (prefname, bool*)
- # pairs for our bool var caches. generateArray will fill it
- # in as needed.
- self.prefCacheData = []
- def hasChromeOnly(self):
- return len(self.chrome) > len(self.regular)
- def hasNonChromeOnly(self):
- return len(self.regular) > 0
- def variableName(self, chrome):
- if chrome and self.hasChromeOnly():
- return "sChrome" + self.name
- if self.hasNonChromeOnly():
- return "s" + self.name
- return "NULL"
- def usedForXrays(self, chrome):
- # We only need Xrays for methods, attributes and constants. And we only
- # need them for the non-chrome ones if we have no chromeonly things.
- # Otherwise (we have chromeonly attributes) we need Xrays for the chrome
- # methods/attributes/constants. Finally, in workers there are no Xrays.
- return ((self.name is "Methods" or self.name is "Attributes" or
- self.name is "Constants") and
- chrome == self.hasChromeOnly() and
- not self.descriptor.workers)
-
- def __str__(self):
- # We only need to generate id arrays for things that will end
- # up used via ResolveProperty or EnumerateProperties.
- str = self.generateArray(self.regular, self.variableName(False),
- self.usedForXrays(False))
- if self.hasChromeOnly():
- str += self.generateArray(self.chrome, self.variableName(True),
- self.usedForXrays(True))
- return str
-
- @staticmethod
- def getControllingPref(interfaceMember):
- prefName = interfaceMember.getExtendedAttribute("Pref")
- if prefName is None:
- return None
- # It's a list of strings
- assert(len(prefName) is 1)
- assert(prefName[0] is not None)
- return prefName[0]
-
- def generatePrefableArray(self, array, name, specTemplate, specTerminator,
- specType, getPref, getDataTuple, doIdArrays):
- """
- This method generates our various arrays.
-
- array is an array of interface members as passed to generateArray
-
- name is the name as passed to generateArray
-
- specTemplate is a template for each entry of the spec array
-
- specTerminator is a terminator for the spec array (inserted every time
- our controlling pref changes and at the end of the array)
-
- specType is the actual typename of our spec
-
- getPref is a callback function that takes an array entry and returns
- the corresponding pref value.
-
- getDataTuple is a callback function that takes an array entry and
- returns a tuple suitable for substitution into specTemplate.
- """
-
- # We want to generate a single list of specs, but with specTerminator
- # inserted at every point where the pref name controlling the member
- # changes. That will make sure the order of the properties as exposed
- # on the interface and interface prototype objects does not change when
- # pref control is added to members while still allowing us to define all
- # the members in the smallest number of JSAPI calls.
- assert(len(array) is not 0)
- lastPref = getPref(array[0]) # So we won't put a specTerminator
- # at the very front of the list.
- specs = []
- prefableSpecs = []
- if doIdArrays:
- prefableIds = []
-
- prefableTemplate = ' { true, &%s[%d] }'
- prefCacheTemplate = '&%s[%d].enabled'
- def switchToPref(props, pref):
- # Remember the info about where our pref-controlled
- # booleans live.
- if pref is not None:
- props.prefCacheData.append(
- (pref, prefCacheTemplate % (name, len(prefableSpecs)))
- )
- # Set up pointers to the new sets of specs and ids
- # inside prefableSpecs and prefableIds
- prefableSpecs.append(prefableTemplate %
- (name + "_specs", len(specs)))
-
- switchToPref(self, lastPref)
-
- for member in array:
- curPref = getPref(member)
- if lastPref != curPref:
- # Terminate previous list
- specs.append(specTerminator)
- # And switch to our new pref
- switchToPref(self, curPref)
- lastPref = curPref
- # And the actual spec
- specs.append(specTemplate % getDataTuple(member))
- specs.append(specTerminator)
- prefableSpecs.append(" { false, NULL }");
-
- arrays = (("static %s %s_specs[] = {\n" +
- ',\n'.join(specs) + "\n" +
- "};\n\n" +
- "static Prefable<%s> %s[] = {\n" +
- ',\n'.join(prefableSpecs) + "\n" +
- "};\n\n") % (specType, name, specType, name))
- if doIdArrays:
- arrays += ("static jsid %s_ids[%i] = { JSID_VOID };\n\n" %
- (name, len(specs)))
- return arrays
-
-
-# The length of a method is the maximum of the lengths of the
-# argument lists of all its overloads.
-def methodLength(method):
- signatures = method.signatures()
- return max([len(arguments) for (retType, arguments) in signatures])
-
-class MethodDefiner(PropertyDefiner):
- """
- A class for defining methods on a prototype object.
- """
- def __init__(self, descriptor, name, static):
- PropertyDefiner.__init__(self, descriptor, name)
-
- # FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=772822
- # We should be able to check for special operations without an
- # identifier. For now we check if the name starts with __
- methods = [m for m in descriptor.interface.members if
- m.isMethod() and m.isStatic() == static and
- not m.isIdentifierLess()]
- self.chrome = [{"name": m.identifier.name,
- "length": methodLength(m),
- "flags": "JSPROP_ENUMERATE",
- "pref": PropertyDefiner.getControllingPref(m) }
- for m in methods]
- self.regular = [{"name": m.identifier.name,
- "length": methodLength(m),
- "flags": "JSPROP_ENUMERATE",
- "pref": PropertyDefiner.getControllingPref(m) }
- for m in methods if not isChromeOnly(m)]
-
- # FIXME Check for an existing iterator on the interface first.
- if any(m.isGetter() and m.isIndexed() for m in methods):
- self.chrome.append({"name": 'iterator',
- "methodInfo": False,
- "nativeName": "JS_ArrayIterator",
- "length": 0,
- "flags": "JSPROP_ENUMERATE",
- "pref": None })
- self.regular.append({"name": 'iterator',
- "methodInfo": False,
- "nativeName": "JS_ArrayIterator",
- "length": 0,
- "flags": "JSPROP_ENUMERATE",
- "pref": None })
-
- if not descriptor.interface.parent and not static and not descriptor.workers:
- self.chrome.append({"name": 'QueryInterface',
- "methodInfo": False,
- "length": 1,
- "flags": "0",
- "pref": None })
-
- if static:
- if not descriptor.interface.hasInterfaceObject():
- # static methods go on the interface object
- assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
- else:
- if not descriptor.interface.hasInterfacePrototypeObject():
- # non-static methods go on the interface prototype object
- assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
-
- def generateArray(self, array, name, doIdArrays):
- if len(array) == 0:
- return ""
-
- def pref(m):
- return m["pref"]
-
- def specData(m):
- if m.get("methodInfo", True):
- jitinfo = ("&%s_methodinfo" % m["name"])
- accessor = "genericMethod"
- else:
- jitinfo = "nullptr"
- accessor = m.get("nativeName", m["name"])
- return (m["name"], accessor, jitinfo, m["length"], m["flags"])
-
- return self.generatePrefableArray(
- array, name,
- ' JS_FNINFO("%s", %s, %s, %s, %s)',
- ' JS_FS_END',
- 'JSFunctionSpec',
- pref, specData, doIdArrays)
-
-class AttrDefiner(PropertyDefiner):
- def __init__(self, descriptor, name):
- PropertyDefiner.__init__(self, descriptor, name)
- self.name = name
- self.chrome = [m for m in descriptor.interface.members if m.isAttr()]
- self.regular = [m for m in self.chrome if not isChromeOnly(m)]
-
- def generateArray(self, array, name, doIdArrays):
- if len(array) == 0:
- return ""
-
- def flags(attr):
- return "JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS"
-
- def getter(attr):
- native = ("genericLenientGetter" if attr.hasLenientThis()
- else "genericGetter")
- return ("{(JSPropertyOp)%(native)s, &%(name)s_getterinfo}"
- % {"name" : attr.identifier.name,
- "native" : native})
-
- def setter(attr):
- if attr.readonly:
- return "JSOP_NULLWRAPPER"
- native = ("genericLenientSetter" if attr.hasLenientThis()
- else "genericSetter")
- return ("{(JSStrictPropertyOp)%(native)s, &%(name)s_setterinfo}"
- % {"name" : attr.identifier.name,
- "native" : native})
-
- def specData(attr):
- return (attr.identifier.name, flags(attr), getter(attr),
- setter(attr))
-
- return self.generatePrefableArray(
- array, name,
- ' { "%s", 0, %s, %s, %s}',
- ' { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }',
- 'JSPropertySpec',
- PropertyDefiner.getControllingPref, specData, doIdArrays)
-
-class ConstDefiner(PropertyDefiner):
- """
- A class for definining constants on the interface object
- """
- def __init__(self, descriptor, name):
- PropertyDefiner.__init__(self, descriptor, name)
- self.name = name
- self.chrome = [m for m in descriptor.interface.members if m.isConst()]
- self.regular = [m for m in self.chrome if not isChromeOnly(m)]
-
- def generateArray(self, array, name, doIdArrays):
- if len(array) == 0:
- return ""
-
- def specData(const):
- return (const.identifier.name,
- convertConstIDLValueToJSVal(const.value))
-
- return self.generatePrefableArray(
- array, name,
- ' { "%s", %s }',
- ' { 0, JSVAL_VOID }',
- 'ConstantSpec',
- PropertyDefiner.getControllingPref, specData, doIdArrays)
-
-class PropertyArrays():
- def __init__(self, descriptor):
- self.staticMethods = MethodDefiner(descriptor, "StaticMethods", True)
- self.methods = MethodDefiner(descriptor, "Methods", False)
- self.attrs = AttrDefiner(descriptor, "Attributes")
- self.consts = ConstDefiner(descriptor, "Constants")
-
- @staticmethod
- def arrayNames():
- return [ "staticMethods", "methods", "attrs", "consts" ]
-
- @staticmethod
- def xrayRelevantArrayNames():
- return [ "methods", "attrs", "consts" ]
-
- def hasChromeOnly(self):
- return reduce(lambda b, a: b or getattr(self, a).hasChromeOnly(),
- self.arrayNames(), False)
- def variableNames(self, chrome):
- names = {}
- for array in self.arrayNames():
- names[array] = getattr(self, array).variableName(chrome)
- return names
- def __str__(self):
- define = ""
- for array in self.arrayNames():
- define += str(getattr(self, array))
- return define
-
-class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
- """
- Generate the CreateInterfaceObjects method for an interface descriptor.
-
- properties should be a PropertyArrays instance.
- """
- def __init__(self, descriptor, properties):
- args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal'),
- Argument('JSObject*', 'aReceiver')]
- CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'JSObject*', args)
- self.properties = properties
- def definition_body(self):
- protoChain = self.descriptor.prototypeChain
- if len(protoChain) == 1:
- getParentProto = "JS_GetObjectPrototype(aCx, aGlobal)"
- else:
- parentProtoName = self.descriptor.prototypeChain[-2]
- getParentProto = ("%s::GetProtoObject(aCx, aGlobal, aReceiver)" %
- toBindingNamespace(parentProtoName))
-
- needInterfaceObject = self.descriptor.interface.hasInterfaceObject()
- needInterfacePrototypeObject = self.descriptor.interface.hasInterfacePrototypeObject()
-
- # if we don't need to create anything, why are we generating this?
- assert needInterfaceObject or needInterfacePrototypeObject
-
- idsToInit = []
- # There is no need to init any IDs in workers, because worker bindings
- # don't have Xrays.
- if not self.descriptor.workers:
- for var in self.properties.xrayRelevantArrayNames():
- props = getattr(self.properties, var)
- # We only have non-chrome ids to init if we have no chrome ids.
- if props.hasChromeOnly():
- idsToInit.append(props.variableName(True))
- elif props.hasNonChromeOnly():
- idsToInit.append(props.variableName(False))
- if len(idsToInit) > 0:
- initIds = CGList(
- [CGGeneric("!InitIds(aCx, %s, %s_ids)" % (varname, varname)) for
- varname in idsToInit], ' ||\n')
- if len(idsToInit) > 1:
- initIds = CGWrapper(initIds, pre="(", post=")", reindent=True)
- initIds = CGList(
- [CGGeneric("%s_ids[0] == JSID_VOID &&" % idsToInit[0]), initIds],
- "\n")
- initIds = CGWrapper(initIds, pre="if (", post=") {", reindent=True)
- initIds = CGList(
- [initIds,
- CGGeneric((" %s_ids[0] = JSID_VOID;\n"
- " return NULL;") % idsToInit[0]),
- CGGeneric("}")],
- "\n")
- else:
- initIds = None
-
- prefCacheData = []
- for var in self.properties.arrayNames():
- props = getattr(self.properties, var)
- prefCacheData.extend(props.prefCacheData)
- if len(prefCacheData) is not 0:
- prefCacheData = [
- CGGeneric('Preferences::AddBoolVarCache(%s, "%s");' % (ptr, pref)) for
- (pref, ptr) in prefCacheData]
- prefCache = CGWrapper(CGIndenter(CGList(prefCacheData, "\n")),
- pre=("static bool sPrefCachesInited = false;\n"
- "if (!sPrefCachesInited) {\n"
- " sPrefCachesInited = true;\n"),
- post="\n}")
- else:
- prefCache = None
-
- getParentProto = ("JSObject* parentProto = %s;\n" +
- "if (!parentProto) {\n" +
- " return NULL;\n" +
- "}\n") % getParentProto
-
- needInterfaceObjectClass = (needInterfaceObject and
- self.descriptor.hasInstanceInterface)
- needConstructor = (needInterfaceObject and
- not self.descriptor.hasInstanceInterface)
- if self.descriptor.interface.ctor():
- constructHook = CONSTRUCT_HOOK_NAME
- constructArgs = methodLength(self.descriptor.interface.ctor())
- else:
- constructHook = "ThrowingConstructor"
- constructArgs = 0
-
- if self.descriptor.concrete:
- if self.descriptor.proxy:
- domClass = "&Class"
- else:
- domClass = "&Class.mClass"
- else:
- domClass = "nullptr"
-
- call = """return dom::CreateInterfaceObjects(aCx, aGlobal, aReceiver, parentProto,
- %s, %s, %s, %d,
- %s,
- %%(methods)s, %%(attrs)s,
- %%(consts)s, %%(staticMethods)s,
- %s);""" % (
- "&PrototypeClass" if needInterfacePrototypeObject else "NULL",
- "&InterfaceObjectClass" if needInterfaceObjectClass else "NULL",
- constructHook if needConstructor else "NULL",
- constructArgs,
- domClass,
- '"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL")
- if self.properties.hasChromeOnly():
- if self.descriptor.workers:
- accessCheck = "mozilla::dom::workers::GetWorkerPrivateFromContext(aCx)->IsChromeWorker()"
- else:
- accessCheck = "xpc::AccessCheck::isChrome(js::GetObjectCompartment(aGlobal))"
- chrome = CGIfWrapper(CGGeneric(call % self.properties.variableNames(True)),
- accessCheck)
- chrome = CGWrapper(chrome, pre="\n\n")
- else:
- chrome = None
-
- functionBody = CGList(
- [CGGeneric(getParentProto), initIds, prefCache, chrome,
- CGGeneric(call % self.properties.variableNames(False))],
- "\n\n")
- return CGIndenter(functionBody).define()
-
-class CGGetPerInterfaceObject(CGAbstractMethod):
- """
- A method for getting a per-interface object (a prototype object or interface
- constructor object).
- """
- def __init__(self, descriptor, name, idPrefix=""):
- args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal'),
- Argument('JSObject*', 'aReceiver')]
- CGAbstractMethod.__init__(self, descriptor, name,
- 'JSObject*', args, inline=True)
- self.id = idPrefix + "id::" + self.descriptor.name
- def definition_body(self):
- return """
-
- /* aGlobal and aReceiver are usually the same, but they can be different
- too. For example a sandbox often has an xray wrapper for a window as the
- prototype of the sandbox's global. In that case aReceiver is the xray
- wrapper and aGlobal is the sandbox's global.
- */
-
- /* Make sure our global is sane. Hopefully we can remove this sometime */
- if (!(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL)) {
- return NULL;
- }
- /* Check to see whether the interface objects are already installed */
- JSObject** protoOrIfaceArray = GetProtoOrIfaceArray(aGlobal);
- JSObject* cachedObject = protoOrIfaceArray[%s];
- if (!cachedObject) {
- protoOrIfaceArray[%s] = cachedObject = CreateInterfaceObjects(aCx, aGlobal, aReceiver);
- }
-
- /* cachedObject might _still_ be null, but that's OK */
- return cachedObject;""" % (self.id, self.id)
-
-class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
- """
- A method for getting the interface prototype object.
- """
- def __init__(self, descriptor):
- CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject",
- "prototypes::")
- def definition_body(self):
- return """
- /* Get the interface prototype object for this class. This will create the
- object as needed. */""" + CGGetPerInterfaceObject.definition_body(self)
-
-class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
- """
- A method for getting the interface constructor object.
- """
- def __init__(self, descriptor):
- CGGetPerInterfaceObject.__init__(self, descriptor, "GetConstructorObject",
- "constructors::")
- def definition_body(self):
- return """
- /* Get the interface object for this class. This will create the object as
- needed. */""" + CGGetPerInterfaceObject.definition_body(self)
-
-def CheckPref(descriptor, globalName, varName, retval, wrapperCache = None):
- """
- Check whether bindings should be enabled for this descriptor. If not, set
- varName to false and return retval.
- """
- if not descriptor.prefable:
- return ""
-
- if wrapperCache:
- wrapperCache = " %s->ClearIsDOMBinding();\n" % (wrapperCache)
- else:
- wrapperCache = ""
-
- failureCode = (" %s = false;\n" +
- " return %s;") % (varName, retval)
- return """
- {
- XPCWrappedNativeScope* scope =
- XPCWrappedNativeScope::FindInJSObjectScope(aCx, %s);
- if (!scope) {
-%s
- }
-
- if (!scope->ExperimentalBindingsEnabled()) {
-%s%s
- }
- }
-""" % (globalName, failureCode, wrapperCache, failureCode)
-
-class CGDefineDOMInterfaceMethod(CGAbstractMethod):
- """
- A method for resolve hooks to try to lazily define the interface object for
- a given interface.
- """
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aReceiver'),
- Argument('bool*', 'aEnabled')]
- CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'bool', args)
-
- def declare(self):
- if self.descriptor.workers:
- return ''
- return CGAbstractMethod.declare(self)
-
- def define(self):
- if self.descriptor.workers:
- return ''
- return CGAbstractMethod.define(self)
-
- def definition_body(self):
- if self.descriptor.interface.hasInterfacePrototypeObject():
- # We depend on GetProtoObject defining an interface constructor
- # object as needed.
- getter = "GetProtoObject"
- else:
- getter = "GetConstructorObject"
-
- return (" JSObject* global = JS_GetGlobalForObject(aCx, aReceiver);\n" +
- CheckPref(self.descriptor, "global", "*aEnabled", "false") +
- """
- *aEnabled = true;
- return !!%s(aCx, global, aReceiver);""" % (getter))
-
-class CGPrefEnabled(CGAbstractMethod):
- """
- A method for testing whether the preference controlling this
- interface is enabled. When it's not, the interface should not be
- visible on the global.
- """
- def __init__(self, descriptor):
- CGAbstractMethod.__init__(self, descriptor, 'PrefEnabled', 'bool', [])
-
- def declare(self):
- return CGAbstractMethod.declare(self)
-
- def define(self):
- return CGAbstractMethod.define(self)
-
- def definition_body(self):
- return " return %s::PrefEnabled();" % self.descriptor.nativeType
-
-class CGIsMethod(CGAbstractMethod):
- def __init__(self, descriptor):
- args = [Argument('JSObject*', 'obj')]
- CGAbstractMethod.__init__(self, descriptor, 'Is', 'bool', args)
-
- def definition_body(self):
- # Non-proxy implementation would check
- # js::GetObjectJSClass(obj) == &Class.mBase
- return """ return IsProxy(obj);"""
-
-def CreateBindingJSObject(descriptor, parent):
- if descriptor.proxy:
- create = """ JSObject *obj = NewProxyObject(aCx, DOMProxyHandler::getInstance(),
- JS::PrivateValue(aObject), proto, %s);
- if (!obj) {
- return NULL;
- }
-
-"""
- else:
- create = """ JSObject* obj = JS_NewObject(aCx, &Class.mBase, proto, %s);
- if (!obj) {
- return NULL;
- }
-
- js::SetReservedSlot(obj, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
-"""
- return create % parent
-
-class CGWrapWithCacheMethod(CGAbstractMethod):
- def __init__(self, descriptor):
- assert descriptor.interface.hasInterfacePrototypeObject()
- args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aScope'),
- Argument(descriptor.nativeType + '*', 'aObject'),
- Argument('nsWrapperCache*', 'aCache'),
- Argument('bool*', 'aTriedToWrap')]
- CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
-
- def definition_body(self):
- if self.descriptor.workers:
- return """ *aTriedToWrap = true;
- return aObject->GetJSObject();"""
-
- return """ *aTriedToWrap = true;
-
- JSObject* parent = WrapNativeParent(aCx, aScope, aObject->GetParentObject());
- if (!parent) {
- return NULL;
- }
-
- JSAutoCompartment ac(aCx, parent);
- JSObject* global = JS_GetGlobalForObject(aCx, parent);
-%s
- JSObject* proto = GetProtoObject(aCx, global, global);
- if (!proto) {
- return NULL;
- }
-
-%s
- NS_ADDREF(aObject);
-
- aCache->SetWrapper(obj);
-
- return obj;""" % (CheckPref(self.descriptor, "global", "*aTriedToWrap", "NULL", "aCache"),
- CreateBindingJSObject(self.descriptor, "parent"))
-
-class CGWrapMethod(CGAbstractMethod):
- def __init__(self, descriptor):
- # XXX can we wrap if we don't have an interface prototype object?
- assert descriptor.interface.hasInterfacePrototypeObject()
- args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aScope'),
- Argument('T*', 'aObject'), Argument('bool*', 'aTriedToWrap')]
- CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args, inline=True, templateArgs=["class T"])
-
- def definition_body(self):
- return " return Wrap(aCx, aScope, aObject, aObject, aTriedToWrap);"
-
-class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
- def __init__(self, descriptor):
- # XXX can we wrap if we don't have an interface prototype object?
- assert descriptor.interface.hasInterfacePrototypeObject()
- args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aScope'),
- Argument(descriptor.nativeType + '*', 'aObject')]
- CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
-
- def definition_body(self):
- return """
- JSObject* global = JS_GetGlobalForObject(aCx, aScope);
- JSObject* proto = GetProtoObject(aCx, global, global);
- if (!proto) {
- return NULL;
- }
-
-%s
- NS_ADDREF(aObject);
-
- return obj;""" % CreateBindingJSObject(self.descriptor, "global")
-
-builtinNames = {
- IDLType.Tags.bool: 'bool',
- IDLType.Tags.int8: 'int8_t',
- IDLType.Tags.int16: 'int16_t',
- IDLType.Tags.int32: 'int32_t',
- IDLType.Tags.int64: 'int64_t',
- IDLType.Tags.uint8: 'uint8_t',
- IDLType.Tags.uint16: 'uint16_t',
- IDLType.Tags.uint32: 'uint32_t',
- IDLType.Tags.uint64: 'uint64_t',
- IDLType.Tags.float: 'float',
- IDLType.Tags.double: 'double'
-}
-
-numericTags = [
- IDLType.Tags.int8, IDLType.Tags.uint8,
- IDLType.Tags.int16, IDLType.Tags.uint16,
- IDLType.Tags.int32, IDLType.Tags.uint32,
- IDLType.Tags.int64, IDLType.Tags.uint64,
- IDLType.Tags.float, IDLType.Tags.double
- ]
-
-class CastableObjectUnwrapper():
- """
- A class for unwrapping an object named by the "source" argument
- based on the passed-in descriptor and storing it in a variable
- called by the name in the "target" argument.
-
- codeOnFailure is the code to run if unwrapping fails.
- """
- def __init__(self, descriptor, source, target, codeOnFailure):
- assert descriptor.castable
-
- self.substitution = { "type" : descriptor.nativeType,
- "protoID" : "prototypes::id::" + descriptor.name,
- "source" : source,
- "target" : target,
- "codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure), 4).define() }
- if descriptor.hasXPConnectImpls:
- # We don't use xpc_qsUnwrapThis because it will always throw on
- # unwrap failure, whereas we want to control whether we throw or
- # not.
- self.substitution["codeOnFailure"] = CGIndenter(CGGeneric(string.Template(
- "${type} *objPtr;\n"
- "xpc_qsSelfRef objRef;\n"
- "JS::Value val = JS::ObjectValue(*${source});\n"
- "nsresult rv = xpc_qsUnwrapArg<${type}>(cx, val, &objPtr, &objRef.ptr, &val);\n"
- "if (NS_FAILED(rv)) {\n"
- "${codeOnFailure}\n"
- "}\n"
- "// We should be castable!\n"
- "MOZ_ASSERT(!objRef.ptr);\n"
- "// We should have an object, too!\n"
- "MOZ_ASSERT(objPtr);\n"
- "${target} = objPtr;").substitute(self.substitution)), 4).define()
-
- def __str__(self):
- return string.Template(
-"""{
- nsresult rv = UnwrapObject<${protoID}, ${type}>(cx, ${source}, ${target});
- if (NS_FAILED(rv)) {
-${codeOnFailure}
- }
-}""").substitute(self.substitution)
-
-class FailureFatalCastableObjectUnwrapper(CastableObjectUnwrapper):
- """
- As CastableObjectUnwrapper, but defaulting to throwing if unwrapping fails
- """
- def __init__(self, descriptor, source, target):
- CastableObjectUnwrapper.__init__(self, descriptor, source, target,
- "return Throw<%s>(cx, rv);" %
- toStringBool(not descriptor.workers))
-
-class CallbackObjectUnwrapper:
- """
- A class for unwrapping objects implemented in JS.
-
- |source| is the JSObject we want to use in native code.
- |target| is an nsCOMPtr of the appropriate type in which we store the result.
- """
- def __init__(self, descriptor, source, target, codeOnFailure=None):
- if codeOnFailure is None:
- codeOnFailure = ("return Throw<%s>(cx, rv);" %
- toStringBool(not descriptor.workers))
- self.descriptor = descriptor
- self.substitution = { "nativeType" : descriptor.nativeType,
- "source" : source,
- "target" : target,
- "codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure)).define() }
-
- def __str__(self):
- if self.descriptor.workers:
- return string.Template(
- "${target} = ${source};"
- ).substitute(self.substitution)
-
- return string.Template(
- """nsresult rv;
-XPCCallContext ccx(JS_CALLER, cx);
-if (!ccx.IsValid()) {
- rv = NS_ERROR_XPC_BAD_CONVERT_JS;
-${codeOnFailure}
-}
-
-const nsIID& iid = NS_GET_IID(${nativeType});
-nsRefPtr<nsXPCWrappedJS> wrappedJS;
-rv = nsXPCWrappedJS::GetNewOrUsed(ccx, ${source}, iid,
- NULL, getter_AddRefs(wrappedJS));
-if (NS_FAILED(rv) || !wrappedJS) {
-${codeOnFailure}
-}
-
-// Use a temp nsCOMPtr for the null-check, because ${target} might be
-// OwningNonNull, not an nsCOMPtr.
-nsCOMPtr<${nativeType}> tmp = do_QueryObject(wrappedJS.get());
-if (!tmp) {
-${codeOnFailure}
-}
-${target} = tmp.forget();""").substitute(self.substitution)
-
-def dictionaryHasSequenceMember(dictionary):
- return (any(typeIsSequenceOrHasSequenceMember(m.type) for m in
- dictionary.members) or
- (dictionary.parent and
- dictionaryHasSequenceMember(dictionary.parent)))
-
-def typeIsSequenceOrHasSequenceMember(type):
- if type.nullable():
- type = type.inner
- if type.isSequence():
- return True
- if type.isArray():
- elementType = type.inner
- return typeIsSequenceOrHasSequenceMember(elementType)
- if type.isDictionary():
- return dictionaryHasSequenceMember(type.inner)
- if type.isUnion():
- return any(typeIsSequenceOrHasSequenceMember(m.type) for m in
- type.flatMemberTypes)
- return False
-
-def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
- isDefinitelyObject=False,
- isMember=False,
- isOptional=False,
- invalidEnumValueFatal=True,
- defaultValue=None,
- treatNullAs="Default",
- treatUndefinedAs="Default",
- isEnforceRange=False,
- isClamp=False):
- """
- Get a template for converting a JS value to a native object based on the
- given type and descriptor. If failureCode is given, then we're actually
- testing whether we can convert the argument to the desired type. That
- means that failures to convert due to the JS value being the wrong type of
- value need to use failureCode instead of throwing exceptions. Failures to
- convert that are due to JS exceptions (from toString or valueOf methods) or
- out of memory conditions need to throw exceptions no matter what
- failureCode is.
-
- If isDefinitelyObject is True, that means we know the value
- isObject() and we have no need to recheck that.
-
- if isMember is True, we're being converted from a property of some
- JS object, not from an actual method argument, so we can't rely on
- our jsval being rooted or outliving us in any way. Any caller
- passing true needs to ensure that it is handled correctly in
- typeIsSequenceOrHasSequenceMember.
-
- If isOptional is true, then we are doing conversion of an optional
- argument with no default value.
-
- invalidEnumValueFatal controls whether an invalid enum value conversion
- attempt will throw (if true) or simply return without doing anything (if
- false).
-
- If defaultValue is not None, it's the IDL default value for this conversion
-
- If isEnforceRange is true, we're converting an integer and throwing if the
- value is out of range.
-
- If isClamp is true, we're converting an integer and clamping if the
- value is out of range.
-
- The return value from this function is a tuple consisting of four things:
-
- 1) A string representing the conversion code. This will have template
- substitution performed on it as follows:
-
- ${val} replaced by an expression for the JS::Value in question
- ${valPtr} is a pointer to the JS::Value in question
- ${holderName} replaced by the holder's name, if any
- ${declName} replaced by the declaration's name
- ${haveValue} replaced by an expression that evaluates to a boolean
- for whether we have a JS::Value. Only used when
- defaultValue is not None.
-
- 2) A CGThing representing the native C++ type we're converting to
- (declType). This is allowed to be None if the conversion code is
- supposed to be used as-is.
- 3) A CGThing representing the type of a "holder" (holderType) which will
- hold a possible reference to the C++ thing whose type we returned in #1,
- or None if no such holder is needed.
- 4) A boolean indicating whether the caller has to do optional-argument handling.
- This will only be true if isOptional is true and if the returned template
- expects both declType and holderType to be wrapped in Optional<>, with
- ${declName} and ${holderName} adjusted to point to the Value() of the
- Optional, and Construct() calls to be made on the Optional<>s as needed.
-
- ${declName} must be in scope before the generated code is entered.
-
- If holderType is not None then ${holderName} must be in scope
- before the generated code is entered.
- """
- # If we have a defaultValue then we're not actually optional for
- # purposes of what we need to be declared as.
- assert(defaultValue is None or not isOptional)
-
- # Also, we should not have a defaultValue if we know we're an object
- assert(not isDefinitelyObject or defaultValue is None)
-
- # Helper functions for dealing with failures due to the JS value being the
- # wrong type of value
- def onFailureNotAnObject(failureCode):
- return CGWrapper(CGGeneric(
- failureCode or
- 'return ThrowErrorMessage(cx, MSG_NOT_OBJECT);'), post="\n")
- def onFailureBadType(failureCode, typeName):
- return CGWrapper(CGGeneric(
- failureCode or
- 'return ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "%s");' % typeName), post="\n")
-
- # A helper function for handling default values. Takes a template
- # body and the C++ code to set the default value and wraps the
- # given template body in handling for the default value.
- def handleDefault(template, setDefault):
- if defaultValue is None:
- return template
- return CGWrapper(
- CGIndenter(CGGeneric(template)),
- pre="if (${haveValue}) {\n",
- post=("\n"
- "} else {\n"
- "%s;\n"
- "}" %
- CGIndenter(CGGeneric(setDefault)).define())).define()
-
- # A helper function for handling null default values. Much like
- # handleDefault, but checks that the default value, if it exists, is null.
- def handleDefaultNull(template, codeToSetNull):
- if (defaultValue is not None and
- not isinstance(defaultValue, IDLNullValue)):
- raise TypeError("Can't handle non-null default value here")
- return handleDefault(template, codeToSetNull)
-
- # A helper function for wrapping up the template body for
- # possibly-nullable objecty stuff
- def wrapObjectTemplate(templateBody, isDefinitelyObject, type,
- codeToSetNull, failureCode=None):
- if not isDefinitelyObject:
- # Handle the non-object cases by wrapping up the whole
- # thing in an if cascade.
- templateBody = (
- "if (${val}.isObject()) {\n" +
- CGIndenter(CGGeneric(templateBody)).define() + "\n")
- if type.nullable():
- templateBody += (
- "} else if (${val}.isNullOrUndefined()) {\n"
- " %s;\n" % codeToSetNull)
- templateBody += (
- "} else {\n" +
- CGIndenter(onFailureNotAnObject(failureCode)).define() +
- "}")
- if type.nullable():
- templateBody = handleDefaultNull(templateBody, codeToSetNull)
- else:
- assert(defaultValue is None)
-
- return templateBody
-
- assert not (isEnforceRange and isClamp) # These are mutually exclusive
-
- if type.isArray():
- raise TypeError("Can't handle array arguments yet")
-
- if type.isSequence():
- assert not isEnforceRange and not isClamp
-
- if failureCode is not None:
- raise TypeError("Can't handle sequences when failureCode is not None")
- nullable = type.nullable();
- # Be very careful not to change "type": we need it later
- if nullable:
- elementType = type.inner.inner
- else:
- elementType = type.inner
-
- # We have to be careful with reallocation behavior for arrays. In
- # particular, if we have a sequence of elements which are themselves
- # sequences (so nsAutoTArrays) or have sequences as members, we have a
- # problem. In that case, resizing the outermost nsAutoTarray to the
- # right size will memmove its elements, but nsAutoTArrays are not
- # memmovable and hence will end up with pointers to bogus memory, which
- # is bad. To deal with this, we disallow sequences, arrays,
- # dictionaries, and unions which contain sequences as sequence item
- # types. If WebIDL ever adds another container type, we'd have to
- # disallow it as well.
- if typeIsSequenceOrHasSequenceMember(elementType):
- raise TypeError("Can't handle a sequence containing another "
- "sequence as an element or member of an element. "
- "See the big comment explaining why.\n%s" %
- str(type.location))
-
- (elementTemplate, elementDeclType,
- elementHolderType, dealWithOptional) = getJSToNativeConversionTemplate(
- elementType, descriptorProvider, isMember=True)
- if dealWithOptional:
- raise TypeError("Shouldn't have optional things in sequences")
- if elementHolderType is not None:
- raise TypeError("Shouldn't need holders for sequences")
-
- typeName = CGWrapper(elementDeclType, pre="Sequence< ", post=" >")
- if nullable:
- typeName = CGWrapper(typeName, pre="Nullable< ", post=" >")
- arrayRef = "${declName}.Value()"
- else:
- arrayRef = "${declName}"
- # If we're optional, the const will come from the Optional
- mutableTypeName = typeName
- if not isOptional:
- typeName = CGWrapper(typeName, pre="const ")
-
- templateBody = ("""JSObject* seq = &${val}.toObject();\n
-if (!IsArrayLike(cx, seq)) {
- return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
-}
-uint32_t length;
-// JS_GetArrayLength actually works on all objects
-if (!JS_GetArrayLength(cx, seq, &length)) {
- return false;
-}
-Sequence< %s > &arr = const_cast< Sequence< %s >& >(%s);
-if (!arr.SetCapacity(length)) {
- return Throw<%s>(cx, NS_ERROR_OUT_OF_MEMORY);
-}
-for (uint32_t i = 0; i < length; ++i) {
- jsval temp;
- if (!JS_GetElement(cx, seq, i, &temp)) {
- return false;
- }
-""" % (toStringBool(descriptorProvider.workers),
- elementDeclType.define(),
- elementDeclType.define(),
- arrayRef,
- toStringBool(descriptorProvider.workers)))
-
- templateBody += CGIndenter(CGGeneric(
- string.Template(elementTemplate).substitute(
- {
- "val" : "temp",
- "valPtr": "&temp",
- "declName" : "(*arr.AppendElement())"
- }
- ))).define()
-
- templateBody += "\n}"
- templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
- type,
- "const_cast< %s & >(${declName}).SetNull()" % mutableTypeName.define())
- return (templateBody, typeName, None, isOptional)
-
- if type.isUnion():
- if isMember:
- raise TypeError("Can't handle unions as members, we have a "
- "holderType")
- nullable = type.nullable();
- if nullable:
- type = type.inner
-
- assert(defaultValue is None or
- (isinstance(defaultValue, IDLNullValue) and nullable))
-
- unionArgumentObj = "${holderName}"
- if isOptional or nullable:
- unionArgumentObj += ".ref()"
-
- memberTypes = type.flatMemberTypes
- names = []
-
- interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes)
- if len(interfaceMemberTypes) > 0:
- interfaceObject = []
- for memberType in interfaceMemberTypes:
- if type.isGeckoInterface():
- name = memberType.inner.identifier.name
- else:
- name = memberType.name
- interfaceObject.append(CGGeneric("(failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext" % (unionArgumentObj, name)))
- names.append(name)
- interfaceObject = CGWrapper(CGList(interfaceObject, " ||\n"), pre="done = ", post=";\n", reindent=True)
- else:
- interfaceObject = None
-
- arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes)
- if len(arrayObjectMemberTypes) > 0:
- assert len(arrayObjectMemberTypes) == 1
- memberType = arrayObjectMemberTypes[0]
- name = memberType.name
- arrayObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
- # XXX Now we're supposed to check for an array or a platform object
- # that supports indexed properties... skip that last for now. It's a
- # bit of a pain.
- arrayObject = CGWrapper(CGIndenter(arrayObject),
- pre="if (IsArrayLike(cx, &argObj)) {\n",
- post="}")
- names.append(name)
- else:
- arrayObject = None
-
- dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes)
- if len(dateObjectMemberTypes) > 0:
- assert len(dateObjectMemberTypes) == 1
- memberType = dateObjectMemberTypes[0]
- name = memberType.name
- dateObject = CGGeneric("%s.SetTo%s(cx, ${val}, ${valPtr});\n"
- "done = true;" % (unionArgumentObj, name))
- dateObject = CGWrapper(CGIndenter(dateObject),
- pre="if (JS_ObjectIsDate(cx, &argObj)) {\n",
- post="\n}")
- names.append(name)
- else:
- dateObject = None
-
- callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes)
- if len(callbackMemberTypes) > 0:
- assert len(callbackMemberTypes) == 1
- memberType = callbackMemberTypes[0]
- name = memberType.name
- callbackObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
- names.append(name)
- else:
- callbackObject = None
-
- dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
- if len(dictionaryMemberTypes) > 0:
- raise TypeError("No support for unwrapping dictionaries as member "
- "of a union")
- else:
- dictionaryObject = None
-
- if callbackObject or dictionaryObject:
- nonPlatformObject = CGList([callbackObject, dictionaryObject], "\n")
- nonPlatformObject = CGWrapper(CGIndenter(nonPlatformObject),
- pre="if (!IsPlatformObject(cx, &argObj)) {\n",
- post="\n}")
- else:
- nonPlatformObject = None
-
- objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
- if len(objectMemberTypes) > 0:
- object = CGGeneric("%s.SetToObject(&argObj);\n"
- "done = true;" % unionArgumentObj)
- else:
- object = None
-
- hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object
- if hasObjectTypes:
- # If we try more specific object types first then we need to check
- # whether that succeeded before converting to object.
- if object and (interfaceObject or arrayObject or dateObject or nonPlatformObject):
- object = CGWrapper(CGIndenter(object), pre="if (!done) {\n",
- post=("\n}"))
-
- if arrayObject or dateObject or nonPlatformObject:
- # An object can be both an array object and not a platform
- # object, but we shouldn't have both in the union's members
- # because they are not distinguishable.
- assert not (arrayObject and nonPlatformObject)
- templateBody = CGList([arrayObject, dateObject, nonPlatformObject], " else ")
- else:
- templateBody = None
- if interfaceObject:
- if templateBody:
- templateBody = CGList([templateBody, object], "\n")
- templateBody = CGWrapper(CGIndenter(templateBody),
- pre="if (!done) {\n", post=("\n}"))
- templateBody = CGList([interfaceObject, templateBody], "\n")
- else:
- templateBody = CGList([templateBody, object], "\n")
-
- if any([arrayObject, dateObject, nonPlatformObject, object]):
- templateBody.prepend(CGGeneric("JSObject& argObj = ${val}.toObject();"))
- templateBody = CGWrapper(CGIndenter(templateBody),
- pre="if (${val}.isObject()) {\n",
- post="\n}")
- else:
- templateBody = CGGeneric()
-
- otherMemberTypes = filter(lambda t: t.isString() or t.isEnum(),
- memberTypes)
- otherMemberTypes.extend(t for t in memberTypes if t.isPrimitive())
- if len(otherMemberTypes) > 0:
- assert len(otherMemberTypes) == 1
- memberType = otherMemberTypes[0]
- if memberType.isEnum():
- name = memberType.inner.identifier.name
- else:
- name = memberType.name
- other = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
- names.append(name)
- if hasObjectTypes:
- other = CGWrapper(CGIndenter(other), "{\n", post="\n}")
- if object:
- join = " else "
- else:
- other = CGWrapper(other, pre="if (!done) ")
- join = "\n"
- templateBody = CGList([templateBody, other], join)
- else:
- other = None
-
- templateBody = CGWrapper(templateBody, pre="bool done = false, failed = false, tryNext;\n")
- throw = CGGeneric("if (failed) {\n"
- " return false;\n"
- "}\n"
- "if (!done) {\n"
- " return ThrowErrorMessage(cx, MSG_NOT_IN_UNION, \"%s\");\n"
- "}" % ", ".join(names))
- templateBody = CGWrapper(CGIndenter(CGList([templateBody, throw], "\n")), pre="{\n", post="\n}")
-
- typeName = type.name
- argumentTypeName = typeName + "Argument"
- if nullable:
- typeName = "Nullable<" + typeName + " >"
- if isOptional:
- nonConstDecl = "const_cast<Optional<" + typeName + " >& >(${declName})"
- else:
- nonConstDecl = "const_cast<" + typeName + "& >(${declName})"
- typeName = "const " + typeName
-
- def handleNull(templateBody, setToNullVar, extraConditionForNull=""):
- null = CGGeneric("if (%s${val}.isNullOrUndefined()) {\n"
- " %s.SetNull();\n"
- "}" % (extraConditionForNull, setToNullVar))
- templateBody = CGWrapper(CGIndenter(templateBody), pre="{\n", post="\n}")
- return CGList([null, templateBody], " else ")
-
- if type.hasNullableType:
- templateBody = handleNull(templateBody, unionArgumentObj)
-
- declType = CGGeneric(typeName)
- holderType = CGGeneric(argumentTypeName)
- if isOptional:
- mutableDecl = nonConstDecl + ".Value()"
- declType = CGWrapper(declType, pre="const Optional<", post=" >")
- holderType = CGWrapper(holderType, pre="Maybe<", post=" >")
- constructDecl = CGGeneric(nonConstDecl + ".Construct();")
- if nullable:
- constructHolder = CGGeneric("${holderName}.construct(%s.SetValue());" % mutableDecl)
- else:
- constructHolder = CGGeneric("${holderName}.construct(${declName}.Value());")
- else:
- mutableDecl = nonConstDecl
- constructDecl = None
- if nullable:
- holderType = CGWrapper(holderType, pre="Maybe<", post=" >")
- constructHolder = CGGeneric("${holderName}.construct(%s.SetValue());" % mutableDecl)
- else:
- constructHolder = CGWrapper(holderType, post=" ${holderName}(${declName});")
- holderType = None
-
- templateBody = CGList([constructHolder, templateBody], "\n")
- if nullable:
- if defaultValue:
- assert(isinstance(defaultValue, IDLNullValue))
- valueMissing = "!(${haveValue}) || "
- else:
- valueMissing = ""
- templateBody = handleNull(templateBody, mutableDecl,
- extraConditionForNull=valueMissing)
- templateBody = CGList([constructDecl, templateBody], "\n")
-
- return templateBody.define(), declType, holderType, False
-
- if type.isGeckoInterface():
- assert not isEnforceRange and not isClamp
-
- descriptor = descriptorProvider.getDescriptor(
- type.unroll().inner.identifier.name)
- # This is an interface that we implement as a concrete class
- # or an XPCOM interface.
-
- # Allow null pointers for nullable types and old-binding classes
- argIsPointer = type.nullable() or type.unroll().inner.isExternal()
-
- # Sequences and non-worker callbacks have to hold a strong ref to the
- # thing being passed down.
- forceOwningType = (descriptor.interface.isCallback() and
- not descriptor.workers) or isMember
-
- typeName = descriptor.nativeType
- typePtr = typeName + "*"
-
- # Compute a few things:
- # - declType is the type we want to return as the first element of our
- # tuple.
- # - holderType is the type we want to return as the third element
- # of our tuple.
-
- # Set up some sensible defaults for these things insofar as we can.
- holderType = None
- if argIsPointer:
- if forceOwningType:
- declType = "nsRefPtr<" + typeName + ">"
- else:
- declType = typePtr
- else:
- if forceOwningType:
- declType = "OwningNonNull<" + typeName + ">"
- else:
- declType = "NonNull<" + typeName + ">"
-
- templateBody = ""
- if descriptor.castable:
- if descriptor.prefable:
- raise TypeError("We don't support prefable castable object "
- "arguments (like %s), because we don't know "
- "how to handle them being preffed off" %
- descriptor.interface.identifier.name)
- if descriptor.interface.isConsequential():
- raise TypeError("Consequential interface %s being used as an "
- "argument but flagged as castable" %
- descriptor.interface.identifier.name)
- if failureCode is not None:
- templateBody += str(CastableObjectUnwrapper(
- descriptor,
- "&${val}.toObject()",
- "${declName}",
- failureCode))
- else:
- templateBody += str(FailureFatalCastableObjectUnwrapper(
- descriptor,
- "&${val}.toObject()",
- "${declName}"))
- elif descriptor.interface.isCallback():
- templateBody += str(CallbackObjectUnwrapper(
- descriptor,
- "&${val}.toObject()",
- "${declName}",
- codeOnFailure=failureCode))
- elif descriptor.workers:
- templateBody += "${declName} = &${val}.toObject();"
- else:
- # Either external, or new-binding non-castable. We always have a
- # holder for these, because we don't actually know whether we have
- # to addref when unwrapping or not. So we just pass an
- # getter_AddRefs(nsRefPtr) to XPConnect and if we'll need a release
- # it'll put a non-null pointer in there.
- if forceOwningType:
- # Don't return a holderType in this case; our declName
- # will just own stuff.
- templateBody += "nsRefPtr<" + typeName + "> ${holderName};\n"
- else:
- holderType = "nsRefPtr<" + typeName + ">"
- templateBody += (
- "jsval tmpVal = ${val};\n" +
- typePtr + " tmp;\n"
- "if (NS_FAILED(xpc_qsUnwrapArg<" + typeName + ">(cx, ${val}, &tmp, static_cast<" + typeName + "**>(getter_AddRefs(${holderName})), &tmpVal))) {\n")
- templateBody += CGIndenter(onFailureBadType(failureCode,
- descriptor.interface.identifier.name)).define()
- templateBody += ("}\n"
- "MOZ_ASSERT(tmp);\n")
-
- if not isDefinitelyObject:
- # Our tmpVal will go out of scope, so we can't rely on it
- # for rooting
- templateBody += (
- "if (tmpVal != ${val} && !${holderName}) {\n"
- " // We have to have a strong ref, because we got this off\n"
- " // some random object that might get GCed\n"
- " ${holderName} = tmp;\n"
- "}\n")
-
- # And store our tmp, before it goes out of scope.
- templateBody += "${declName} = tmp;"
-
- templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
- type, "${declName} = NULL",
- failureCode)
-
- declType = CGGeneric(declType)
- if holderType is not None:
- holderType = CGGeneric(holderType)
- return (templateBody, declType, holderType, isOptional)
-
- if type.isSpiderMonkeyInterface():
- assert not isEnforceRange and not isClamp
- if isMember:
- raise TypeError("Can't handle member arraybuffers or "
- "arraybuffer views because making sure all the "
- "objects are properly rooted is hard")
- name = type.name
- # By default, we use a Maybe<> to hold our typed array. And in the optional
- # non-nullable case we want to pass Optional<TypedArray> to consumers, not
- # Optional<NonNull<TypedArray> >, so jump though some hoops to do that.
- holderType = "Maybe<%s>" % name
- constructLoc = "${holderName}"
- constructMethod = "construct"
- constructInternal = "ref"
- if type.nullable():
- if isOptional:
- declType = "const Optional<" + name + "*>"
- else:
- declType = name + "*"
- else:
- if isOptional:
- declType = "const Optional<" + name + ">"
- # We don't need a holder in this case
- holderType = None
- constructLoc = "(const_cast<Optional<" + name + ">& >(${declName}))"
- constructMethod = "Construct"
- constructInternal = "Value"
- else:
- declType = "NonNull<" + name + ">"
- template = (
- "%s.%s(cx, &${val}.toObject());\n"
- "if (!%s.%s().inited()) {\n"
- "%s" # No newline here because onFailureBadType() handles that
- "}\n" %
- (constructLoc, constructMethod, constructLoc, constructInternal,
- CGIndenter(onFailureBadType(failureCode, type.name)).define()))
- nullableTarget = ""
- if type.nullable():
- if isOptional:
- mutableDecl = "(const_cast<Optional<" + name + "*>& >(${declName}))"
- template += "%s.Construct();\n" % mutableDecl
- nullableTarget = "%s.Value()" % mutableDecl
- else:
- nullableTarget = "${declName}"
- template += "%s = ${holderName}.addr();" % nullableTarget
- elif not isOptional:
- template += "${declName} = ${holderName}.addr();"
- template = wrapObjectTemplate(template, isDefinitelyObject, type,
- "%s = NULL" % nullableTarget,
- failureCode)
-
- if holderType is not None:
- holderType = CGGeneric(holderType)
- # We handle all the optional stuff ourselves; no need for caller to do it.
- return (template, CGGeneric(declType), holderType, False)
-
- if type.isString():
- assert not isEnforceRange and not isClamp
-
- treatAs = {
- "Default": "eStringify",
- "EmptyString": "eEmpty",
- "Null": "eNull"
- }
- if type.nullable():
- # For nullable strings null becomes a null string.
- treatNullAs = "Null"
- # For nullable strings undefined becomes a null string unless
- # specified otherwise.
- if treatUndefinedAs == "Default":
- treatUndefinedAs = "Null"
- nullBehavior = treatAs[treatNullAs]
- if treatUndefinedAs == "Missing":
- raise TypeError("We don't support [TreatUndefinedAs=Missing]")
- undefinedBehavior = treatAs[treatUndefinedAs]
-
- def getConversionCode(varName):
- conversionCode = (
- "if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, %s)) {\n"
- " return false;\n"
- "}" % (nullBehavior, undefinedBehavior, varName))
- if defaultValue is None:
- return conversionCode
-
- if isinstance(defaultValue, IDLNullValue):
- assert(type.nullable())
- return handleDefault(conversionCode,
- "%s.SetNull()" % varName)
- return handleDefault(
- conversionCode,
- ("static const PRUnichar data[] = { %s };\n"
- "%s.SetData(data, ArrayLength(data) - 1)" %
- (", ".join(["'" + char + "'" for char in defaultValue.value] + ["0"]),
- varName)))
-
- if isMember:
- # We have to make a copy, because our jsval may well not
- # live as long as our string needs to.
- declType = CGGeneric("nsString")
- return (
- "{\n"
- " FakeDependentString str;\n"
- "%s\n"
- " ${declName} = str;\n"
- "}\n" % CGIndenter(CGGeneric(getConversionCode("str"))).define(),
- declType, None, isOptional)
-
- if isOptional:
- declType = "Optional<nsAString>"
- else:
- declType = "NonNull<nsAString>"
-
- return (
- "%s\n"
- "const_cast<%s&>(${declName}) = &${holderName};" %
- (getConversionCode("${holderName}"), declType),
- CGGeneric("const " + declType), CGGeneric("FakeDependentString"),
- # No need to deal with Optional here; we have handled it already
- False)
-
- if type.isEnum():
- assert not isEnforceRange and not isClamp
-
- if type.nullable():
- raise TypeError("We don't support nullable enumerated arguments "
- "yet")
- enum = type.inner.identifier.name
- if invalidEnumValueFatal:
- handleInvalidEnumValueCode = " MOZ_ASSERT(index >= 0);\n"
- else:
- handleInvalidEnumValueCode = (
- " if (index < 0) {\n"
- " return true;\n"
- " }\n")
-
- template = (
- "{\n"
- " bool ok;\n"
- " int index = FindEnumStringIndex<%(invalidEnumValueFatal)s>(cx, ${val}, %(values)s, \"%(enumtype)s\", &ok);\n"
- " if (!ok) {\n"
- " return false;\n"
- " }\n"
- "%(handleInvalidEnumValueCode)s"
- " ${declName} = static_cast<%(enumtype)s>(index);\n"
- "}" % { "enumtype" : enum,
- "values" : enum + "Values::strings",
- "invalidEnumValueFatal" : toStringBool(invalidEnumValueFatal),
- "handleInvalidEnumValueCode" : handleInvalidEnumValueCode })
-
- if defaultValue is not None:
- assert(defaultValue.type.tag() == IDLType.Tags.domstring)
- template = handleDefault(template,
- ("${declName} = %sValues::%s" %
- (enum,
- getEnumValueName(defaultValue.value))))
- return (template, CGGeneric(enum), None, isOptional)
-
- if type.isCallback():
- assert not isEnforceRange and not isClamp
-
- if isMember:
- raise TypeError("Can't handle member callbacks; need to sort out "
- "rooting issues")
- # XXXbz we're going to assume that callback types are always
- # nullable and always have [TreatNonCallableAsNull] for now.
- haveCallable = "${val}.isObject() && JS_ObjectIsCallable(cx, &${val}.toObject())"
- if defaultValue is not None:
- assert(isinstance(defaultValue, IDLNullValue))
- haveCallable = "${haveValue} && " + haveCallable
- return (
- "if (%s) {\n"
- " ${declName} = &${val}.toObject();\n"
- "} else {\n"
- " ${declName} = NULL;\n"
- "}" % haveCallable,
- CGGeneric("JSObject*"), None, isOptional)
-
- if type.isAny():
- assert not isEnforceRange and not isClamp
-
- if isMember:
- raise TypeError("Can't handle member 'any'; need to sort out "
- "rooting issues")
- templateBody = "${declName} = ${val};"
- templateBody = handleDefaultNull(templateBody,
- "${declName} = JS::NullValue()")
- return (templateBody, CGGeneric("JS::Value"), None, isOptional)
-
- if type.isObject():
- assert not isEnforceRange and not isClamp
-
- if isMember:
- raise TypeError("Can't handle member 'object'; need to sort out "
- "rooting issues")
- template = wrapObjectTemplate("${declName} = &${val}.toObject();",
- isDefinitelyObject, type,
- "${declName} = NULL",
- failureCode)
- if type.nullable():
- declType = CGGeneric("JSObject*")
- else:
- declType = CGGeneric("NonNull<JSObject>")
- return (template, declType, None, isOptional)
-
- if type.isDictionary():
- if failureCode is not None:
- raise TypeError("Can't handle dictionaries when failureCode is not None")
- # There are no nullable dictionaries
- assert not type.nullable()
- # All optional dictionaries always have default values, so we
- # should be able to assume not isOptional here.
- assert not isOptional
-
- typeName = CGDictionary.makeDictionaryName(type.inner,
- descriptorProvider.workers)
- actualTypeName = typeName
- selfRef = "${declName}"
-
- declType = CGGeneric(actualTypeName)
-
- # If we're a member of something else, the const
- # will come from the Optional or our container.
- if not isMember:
- declType = CGWrapper(declType, pre="const ")
- selfRef = "const_cast<%s&>(%s)" % (typeName, selfRef)
-
- # We do manual default value handling here, because we
- # actually do want a jsval, and we only handle null anyway
- if defaultValue is not None:
- assert(isinstance(defaultValue, IDLNullValue))
- val = "(${haveValue}) ? ${val} : JSVAL_NULL"
- else:
- val = "${val}"
-
- template = ("if (!%s.Init(cx, %s)) {\n"
- " return false;\n"
- "}" % (selfRef, val))
-
- return (template, declType, None, False)
-
- if not type.isPrimitive():
- raise TypeError("Need conversion for argument type '%s'" % str(type))
-
- typeName = builtinNames[type.tag()]
-
- conversionBehavior = "eDefault"
- if isEnforceRange:
- conversionBehavior = "eEnforceRange"
- elif isClamp:
- conversionBehavior = "eClamp"
-
- if type.nullable():
- dataLoc = "${declName}.SetValue()"
- nullCondition = "${val}.isNullOrUndefined()"
- if defaultValue is not None and isinstance(defaultValue, IDLNullValue):
- nullCondition = "!(${haveValue}) || " + nullCondition
- template = (
- "if (%s) {\n"
- " ${declName}.SetNull();\n"
- "} else if (!ValueToPrimitive<%s, %s>(cx, ${val}, &%s)) {\n"
- " return false;\n"
- "}" % (nullCondition, typeName, conversionBehavior, dataLoc))
- declType = CGGeneric("Nullable<" + typeName + ">")
- else:
- assert(defaultValue is None or
- not isinstance(defaultValue, IDLNullValue))
- dataLoc = "${declName}"
- template = (
- "if (!ValueToPrimitive<%s, %s>(cx, ${val}, &%s)) {\n"
- " return false;\n"
- "}" % (typeName, conversionBehavior, dataLoc))
- declType = CGGeneric(typeName)
- if (defaultValue is not None and
- # We already handled IDLNullValue, so just deal with the other ones
- not isinstance(defaultValue, IDLNullValue)):
- tag = defaultValue.type.tag()
- if tag in numericTags:
- defaultStr = defaultValue.value
- else:
- assert(tag == IDLType.Tags.bool)
- defaultStr = toStringBool(defaultValue.value)
- template = CGWrapper(CGIndenter(CGGeneric(template)),
- pre="if (${haveValue}) {\n",
- post=("\n"
- "} else {\n"
- " %s = %s;\n"
- "}" % (dataLoc, defaultStr))).define()
-
- return (template, declType, None, isOptional)
-
-def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
- argcAndIndex=None):
- """
- Take a tuple as returned by getJSToNativeConversionTemplate and a set of
- replacements as required by the strings in such a tuple, and generate code
- to convert into stack C++ types.
-
- If argcAndIndex is not None it must be a dict that can be used to
- replace ${argc} and ${index}, where ${index} is the index of this
- argument (0-based) and ${argc} is the total number of arguments.
- """
- (templateBody, declType, holderType, dealWithOptional) = templateTuple
-
- if dealWithOptional and argcAndIndex is None:
- raise TypeError("Have to deal with optional things, but don't know how")
- if argcAndIndex is not None and declType is None:
- raise TypeError("Need to predeclare optional things, so they will be "
- "outside the check for big enough arg count!");
-
- result = CGList([], "\n")
- # Make a copy of "replacements" since we may be about to start modifying it
- replacements = dict(replacements)
- originalHolderName = replacements["holderName"]
- if holderType is not None:
- if dealWithOptional:
- replacements["holderName"] = (
- "const_cast< %s & >(%s.Value())" %
- (holderType.define(), originalHolderName))
- mutableHolderType = CGWrapper(holderType, pre="Optional< ", post=" >")
- holderType = CGWrapper(mutableHolderType, pre="const ")
- result.append(
- CGList([holderType, CGGeneric(" "),
- CGGeneric(originalHolderName),
- CGGeneric(";")]))
-
- originalDeclName = replacements["declName"]
- if declType is not None:
- if dealWithOptional:
- replacements["declName"] = (
- "const_cast< %s & >(%s.Value())" %
- (declType.define(), originalDeclName))
- mutableDeclType = CGWrapper(declType, pre="Optional< ", post=" >")
- declType = CGWrapper(mutableDeclType, pre="const ")
- result.append(
- CGList([declType, CGGeneric(" "),
- CGGeneric(originalDeclName),
- CGGeneric(";")]))
-
- conversion = CGGeneric(
- string.Template(templateBody).substitute(replacements)
- )
-
- if argcAndIndex is not None:
- if dealWithOptional:
- declConstruct = CGIndenter(
- CGGeneric("const_cast< %s &>(%s).Construct();" %
- (mutableDeclType.define(), originalDeclName)))
- if holderType is not None:
- holderConstruct = CGIndenter(
- CGGeneric("const_cast< %s &>(%s).Construct();" %
- (mutableHolderType.define(), originalHolderName)))
- else:
- holderConstruct = None
- else:
- declConstruct = None
- holderConstruct = None
-
- conversion = CGList(
- [CGGeneric(
- string.Template("if (${index} < ${argc}) {").substitute(
- argcAndIndex
- )),
- declConstruct,
- holderConstruct,
- CGIndenter(conversion),
- CGGeneric("}")],
- "\n")
-
- result.append(conversion)
- # Add an empty CGGeneric to get an extra newline after the argument
- # conversion.
- result.append(CGGeneric(""))
- return result;
-
-def convertConstIDLValueToJSVal(value):
- if isinstance(value, IDLNullValue):
- return "JSVAL_NULL"
- tag = value.type.tag()
- if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
- IDLType.Tags.uint16, IDLType.Tags.int32]:
- return "INT_TO_JSVAL(%s)" % (value.value)
- if tag == IDLType.Tags.uint32:
- return "UINT_TO_JSVAL(%s)" % (value.value)
- if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]:
- return "DOUBLE_TO_JSVAL(%s)" % (value.value)
- if tag == IDLType.Tags.bool:
- return "JSVAL_TRUE" if value.value else "JSVAL_FALSE"
- if tag in [IDLType.Tags.float, IDLType.Tags.double]:
- return "DOUBLE_TO_JSVAL(%s)" % (value.value)
- raise TypeError("Const value of unhandled type: " + value.type)
-
-class CGArgumentConverter(CGThing):
- """
- A class that takes an IDL argument object, its index in the
- argument list, and the argv and argc strings and generates code to
- unwrap the argument to the right native type.
- """
- def __init__(self, argument, index, argv, argc, descriptorProvider,
- invalidEnumValueFatal=True):
- CGThing.__init__(self)
- self.argument = argument
- if argument.variadic:
- raise TypeError("We don't support variadic arguments yet " +
- str(argument.location))
- assert(not argument.defaultValue or argument.optional)
-
- replacer = {
- "index" : index,
- "argc" : argc,
- "argv" : argv
- }
- self.replacementVariables = {
- "declName" : "arg%d" % index,
- "holderName" : ("arg%d" % index) + "_holder"
- }
- self.replacementVariables["val"] = string.Template(
- "${argv}[${index}]"
- ).substitute(replacer)
- self.replacementVariables["valPtr"] = (
- "&" + self.replacementVariables["val"])
- if argument.defaultValue:
- self.replacementVariables["haveValue"] = string.Template(
- "${index} < ${argc}").substitute(replacer)
- self.descriptorProvider = descriptorProvider
- if self.argument.optional and not self.argument.defaultValue:
- self.argcAndIndex = replacer
- else:
- self.argcAndIndex = None
- self.invalidEnumValueFatal = invalidEnumValueFatal
-
- def define(self):
- return instantiateJSToNativeConversionTemplate(
- getJSToNativeConversionTemplate(self.argument.type,
- self.descriptorProvider,
- isOptional=(self.argcAndIndex is not None),
- invalidEnumValueFatal=self.invalidEnumValueFatal,
- defaultValue=self.argument.defaultValue,
- treatNullAs=self.argument.treatNullAs,
- treatUndefinedAs=self.argument.treatUndefinedAs,
- isEnforceRange=self.argument.enforceRange,
- isClamp=self.argument.clamp),
- self.replacementVariables,
- self.argcAndIndex).define()
-
-def getWrapTemplateForType(type, descriptorProvider, result, successCode,
- isCreator):
- """
- Reflect a C++ value stored in "result", of IDL type "type" into JS. The
- "successCode" is the code to run once we have successfully done the
- conversion. The resulting string should be used with string.Template, it
- needs the following keys when substituting: jsvalPtr/jsvalRef/obj.
-
- Returns (templateString, infallibility of conversion template)
- """
- haveSuccessCode = successCode is not None
- if not haveSuccessCode:
- successCode = "return true;"
-
- def setValue(value, callWrapValue=False):
- """
- Returns the code to set the jsval to value. If "callWrapValue" is true
- JS_WrapValue will be called on the jsval.
- """
- if not callWrapValue:
- tail = successCode
- elif haveSuccessCode:
- tail = ("if (!JS_WrapValue(cx, ${jsvalPtr})) {\n" +
- " return false;\n" +
- "}\n" +
- successCode)
- else:
- tail = "return JS_WrapValue(cx, ${jsvalPtr});"
- return ("${jsvalRef} = %s;\n" +
- tail) % (value)
-
- def wrapAndSetPtr(wrapCall, failureCode=None):
- """
- Returns the code to set the jsval by calling "wrapCall". "failureCode"
- is the code to run if calling "wrapCall" fails
- """
- if failureCode is None:
- if not haveSuccessCode:
- return "return " + wrapCall + ";"
- failureCode = "return false;"
- str = ("if (!%s) {\n" +
- CGIndenter(CGGeneric(failureCode)).define() + "\n" +
- "}\n" +
- successCode) % (wrapCall)
- return str
-
- if type is None or type.isVoid():
- return (setValue("JSVAL_VOID"), True)
-
- if type.isArray():
- raise TypeError("Can't handle array return values yet")
-
- if type.isSequence():
- if type.nullable():
- # Nullable sequences are Nullable< nsTArray<T> >
- (recTemplate, recInfall) = getWrapTemplateForType(type.inner, descriptorProvider,
- "%s.Value()" % result, successCode,
- isCreator)
- return ("""
-if (%s.IsNull()) {
-%s
-}
-%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(), recTemplate), recInfall)
-
- # Now do non-nullable sequences. We use setting the element
- # in the array as our succcess code because when we succeed in
- # wrapping that's what we should do.
- innerTemplate = wrapForType(
- type.inner, descriptorProvider,
- {
- 'result' : "%s[i]" % result,
- 'successCode': ("if (!JS_DefineElement(cx, returnArray, i, tmp,\n"
- " NULL, NULL, JSPROP_ENUMERATE)) {\n"
- " return false;\n"
- "}"),
- 'jsvalRef': "tmp",
- 'jsvalPtr': "&tmp",
- 'isCreator': isCreator
- }
- )
- innerTemplate = CGIndenter(CGGeneric(innerTemplate)).define()
- return (("""
-uint32_t length = %s.Length();
-JSObject *returnArray = JS_NewArrayObject(cx, length, NULL);
-if (!returnArray) {
- return false;
-}
-jsval tmp;
-for (uint32_t i = 0; i < length; ++i) {
-%s
-}\n""" % (result, innerTemplate)) + setValue("JS::ObjectValue(*returnArray)"), False)
-
- if type.isGeckoInterface():
- descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
- if type.nullable():
- wrappingCode = ("if (!%s) {\n" % (result) +
- CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
- "}\n")
- else:
- wrappingCode = ""
- if (not descriptor.interface.isExternal() and
- not descriptor.interface.isCallback()):
- if descriptor.wrapperCache:
- wrapMethod = "WrapNewBindingObject"
- else:
- if not isCreator:
- raise MethodNotCreatorError(descriptor.interface.identifier.name)
- wrapMethod = "WrapNewBindingNonWrapperCachedObject"
- wrap = "%s(cx, ${obj}, %s, ${jsvalPtr})" % (wrapMethod, result)
- # We don't support prefable stuff in workers.
- assert(not descriptor.prefable or not descriptor.workers)
- if not descriptor.prefable:
- # Non-prefable bindings can only fail to wrap as a new-binding object
- # if they already threw an exception. Same thing for
- # non-prefable bindings.
- failed = ("MOZ_ASSERT(JS_IsExceptionPending(cx));\n" +
- "return false;")
- else:
- if descriptor.notflattened:
- raise TypeError("%s is prefable but not flattened; "
- "fallback won't work correctly" %
- descriptor.interface.identifier.name)
- # Try old-style wrapping for bindings which might be preffed off.
- failed = wrapAndSetPtr("HandleNewBindingWrappingFailure(cx, ${obj}, %s, ${jsvalPtr})" % result)
- wrappingCode += wrapAndSetPtr(wrap, failed)
- else:
- if descriptor.notflattened:
- getIID = "&NS_GET_IID(%s), " % descriptor.nativeType
- else:
- getIID = ""
- wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID)
- wrappingCode += wrapAndSetPtr(wrap)
- return (wrappingCode, False)
-
- if type.isString():
- if type.nullable():
- return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalPtr})" % result), False)
- else:
- return (wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr})" % result), False)
-
- if type.isEnum():
- if type.nullable():
- raise TypeError("We don't support nullable enumerated return types "
- "yet")
- return ("""MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s));
-JSString* %(resultStr)s = JS_NewStringCopyN(cx, %(strings)s[uint32_t(%(result)s)].value, %(strings)s[uint32_t(%(result)s)].length);
-if (!%(resultStr)s) {
- return false;
-}
-""" % { "result" : result,
- "resultStr" : result + "_str",
- "strings" : type.inner.identifier.name + "Values::strings" } +
- setValue("JS::StringValue(%s_str)" % result), False)
-
- if type.isCallback():
- assert not type.isInterface()
- # XXXbz we're going to assume that callback types are always
- # nullable and always have [TreatNonCallableAsNull] for now.
- # See comments in WrapNewBindingObject explaining why we need
- # to wrap here.
- # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
- return (setValue("JS::ObjectOrNullValue(%s)" % result, True), False)
-
- if type.tag() == IDLType.Tags.any:
- # See comments in WrapNewBindingObject explaining why we need
- # to wrap here.
- # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
- return (setValue(result, True), False)
-
- if type.isObject() or type.isSpiderMonkeyInterface():
- # See comments in WrapNewBindingObject explaining why we need
- # to wrap here.
- if type.nullable():
- toValue = "JS::ObjectOrNullValue(%s)"
- else:
- toValue = "JS::ObjectValue(*%s)"
- # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
- return (setValue(toValue % result, True), False)
-
- if not type.isPrimitive():
- raise TypeError("Need to learn to wrap %s" % type)
-
- if type.nullable():
- (recTemplate, recInfal) = getWrapTemplateForType(type.inner, descriptorProvider,
- "%s.Value()" % result, successCode,
- isCreator)
- return ("if (%s.IsNull()) {\n" % result +
- CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
- "}\n" + recTemplate, recInfal)
-
- tag = type.tag()
-
- if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
- IDLType.Tags.uint16, IDLType.Tags.int32]:
- return (setValue("INT_TO_JSVAL(int32_t(%s))" % result), True)
-
- elif tag in [IDLType.Tags.int64, IDLType.Tags.uint64, IDLType.Tags.float,
- IDLType.Tags.double]:
- # XXXbz will cast to double do the "even significand" thing that webidl
- # calls for for 64-bit ints? Do we care?
- return (setValue("JS_NumberValue(double(%s))" % result), True)
-
- elif tag == IDLType.Tags.uint32:
- return (setValue("UINT_TO_JSVAL(%s)" % result), True)
-
- elif tag == IDLType.Tags.bool:
- return (setValue("BOOLEAN_TO_JSVAL(%s)" % result), True)
-
- else:
- raise TypeError("Need to learn to wrap primitive: %s" % type)
-
-def wrapForType(type, descriptorProvider, templateValues):
- """
- Reflect a C++ value of IDL type "type" into JS. TemplateValues is a dict
- that should contain:
-
- * 'jsvalRef': a C++ reference to the jsval in which to store the result of
- the conversion
- * 'jsvalPtr': a C++ pointer to the jsval in which to store the result of
- the conversion
- * 'obj' (optional): the name of the variable that contains the JSObject to
- use as a scope when wrapping, if not supplied 'obj'
- will be used as the name
- * 'result' (optional): the name of the variable in which the C++ value is
- stored, if not supplied 'result' will be used as
- the name
- * 'successCode' (optional): the code to run once we have successfully done
- the conversion, if not supplied 'return true;'
- will be used as the code
- * 'isCreator' (optional): If true, we're wrapping for the return value of
- a [Creator] method. Assumed false if not set.
- """
- wrap = getWrapTemplateForType(type, descriptorProvider,
- templateValues.get('result', 'result'),
- templateValues.get('successCode', None),
- templateValues.get('isCreator', False))[0]
-
- defaultValues = {'obj': 'obj'}
- return string.Template(wrap).substitute(defaultValues, **templateValues)
-
-def infallibleForMember(member, type, descriptorProvider):
- """
- Determine the fallibility of changing a C++ value of IDL type "type" into
- JS for the given attribute. Apart from isCreator, all the defaults are used,
- since the fallbility does not change based on the boolean values,
- and the template will be discarded.
-
- CURRENT ASSUMPTIONS:
- We assume that successCode for wrapping up return values cannot contain
- failure conditions.
- """
- return getWrapTemplateForType(type, descriptorProvider, 'result', None,\
- memberIsCreator(member))[1]
-
-def typeNeedsCx(type, retVal=False):
- if type is None:
- return False
- if type.nullable():
- type = type.inner
- if type.isSequence() or type.isArray():
- type = type.inner
- if type.isUnion():
- return any(typeNeedsCx(t) for t in type.unroll().flatMemberTypes)
- if retVal and type.isSpiderMonkeyInterface():
- return True
- return type.isCallback() or type.isAny() or type.isObject()
-
-# Returns a tuple consisting of a CGThing containing the type of the return
-# value, or None if there is no need for a return value, and a boolean signaling
-# whether the return value is passed in an out parameter.
-def getRetvalDeclarationForType(returnType, descriptorProvider,
- resultAlreadyAddRefed):
- if returnType is None or returnType.isVoid():
- # Nothing to declare
- return None, False
- if returnType.isPrimitive() and returnType.tag() in builtinNames:
- result = CGGeneric(builtinNames[returnType.tag()])
- if returnType.nullable():
- result = CGWrapper(result, pre="Nullable<", post=">")
- return result, False
- if returnType.isString():
- return CGGeneric("nsString"), True
- if returnType.isEnum():
- if returnType.nullable():
- raise TypeError("We don't support nullable enum return values")
- return CGGeneric(returnType.inner.identifier.name), False
- if returnType.isGeckoInterface():
- result = CGGeneric(descriptorProvider.getDescriptor(
- returnType.unroll().inner.identifier.name).nativeType)
- if resultAlreadyAddRefed:
- result = CGWrapper(result, pre="nsRefPtr<", post=">")
- else:
- result = CGWrapper(result, post="*")
- return result, False
- if returnType.isCallback():
- # XXXbz we're going to assume that callback types are always
- # nullable for now.
- return CGGeneric("JSObject*"), False
- if returnType.isAny():
- return CGGeneric("JS::Value"), False
- if returnType.isObject() or returnType.isSpiderMonkeyInterface():
- return CGGeneric("JSObject*"), False
- if returnType.isSequence():
- nullable = returnType.nullable()
- if nullable:
- returnType = returnType.inner
- # If our result is already addrefed, use the right type in the
- # sequence argument here.
- (result, _) = getRetvalDeclarationForType(returnType.inner,
- descriptorProvider,
- resultAlreadyAddRefed)
- result = CGWrapper(result, pre="nsTArray< ", post=" >")
- if nullable:
- result = CGWrapper(result, pre="Nullable< ", post=" >")
- return result, True
- raise TypeError("Don't know how to declare return value for %s" %
- returnType)
-
-def isResultAlreadyAddRefed(descriptor, extendedAttributes):
- # Default to already_AddRefed on the main thread, raw pointer in workers
- return not descriptor.workers and not 'resultNotAddRefed' in extendedAttributes
-
-class CGCallGenerator(CGThing):
- """
- A class to generate an actual call to a C++ object. Assumes that the C++
- object is stored in a variable whose name is given by the |object| argument.
-
- errorReport should be a CGThing for an error report or None if no
- error reporting is needed.
- """
- def __init__(self, errorReport, arguments, argsPre, returnType,
- extendedAttributes, descriptorProvider, nativeMethodName,
- static, object="self", declareResult=True):
- CGThing.__init__(self)
-
- assert errorReport is None or isinstance(errorReport, CGThing)
-
- isFallible = errorReport is not None
-
- resultAlreadyAddRefed = isResultAlreadyAddRefed(descriptorProvider,
- extendedAttributes)
- (result, resultOutParam) = getRetvalDeclarationForType(returnType,
- descriptorProvider,
- resultAlreadyAddRefed)
-
- args = CGList([CGGeneric(arg) for arg in argsPre], ", ")
- for (a, name) in arguments:
- # This is a workaround for a bug in Apple's clang.
- if a.type.isObject() and not a.type.nullable() and not a.optional:
- name = "(JSObject&)" + name
- args.append(CGGeneric(name))
-
- # Return values that go in outparams go here
- if resultOutParam:
- args.append(CGGeneric("result"))
- if isFallible:
- args.append(CGGeneric("rv"))
-
- needsCx = (typeNeedsCx(returnType, True) or
- any(typeNeedsCx(a.type) for (a, _) in arguments) or
- 'implicitJSContext' in extendedAttributes)
-
- if not "cx" in argsPre and needsCx:
- args.prepend(CGGeneric("cx"))
-
- # Build up our actual call
- self.cgRoot = CGList([], "\n")
-
- call = CGGeneric(nativeMethodName)
- if static:
- call = CGWrapper(call, pre="%s::" % descriptorProvider.nativeType)
- else:
- call = CGWrapper(call, pre="%s->" % object)
- call = CGList([call, CGWrapper(args, pre="(", post=");")])
- if result is not None:
- if declareResult:
- result = CGWrapper(result, post=" result;")
- self.cgRoot.prepend(result)
- if not resultOutParam:
- call = CGWrapper(call, pre="result = ")
-
- call = CGWrapper(call)
- self.cgRoot.append(call)
-
- if isFallible:
- self.cgRoot.prepend(CGGeneric("ErrorResult rv;"))
- self.cgRoot.append(CGGeneric("if (rv.Failed()) {"))
- self.cgRoot.append(CGIndenter(errorReport))
- self.cgRoot.append(CGGeneric("}"))
-
- def define(self):
- return self.cgRoot.define()
-
-class MethodNotCreatorError(Exception):
- def __init__(self, typename):
- self.typename = typename
-
-class CGPerSignatureCall(CGThing):
- """
- This class handles the guts of generating code for a particular
- call signature. A call signature consists of four things:
-
- 1) A return type, which can be None to indicate that there is no
- actual return value (e.g. this is an attribute setter) or an
- IDLType if there's an IDL type involved (including |void|).
- 2) An argument list, which is allowed to be empty.
- 3) A name of a native method to call.
- 4) Whether or not this method is static.
-
- We also need to know whether this is a method or a getter/setter
- to do error reporting correctly.
-
- The idlNode parameter can be either a method or an attr. We can query
- |idlNode.identifier| in both cases, so we can be agnostic between the two.
- """
- # XXXbz For now each entry in the argument list is either an
- # IDLArgument or a FakeArgument, but longer-term we may want to
- # have ways of flagging things like JSContext* or optional_argc in
- # there.
-
- def __init__(self, returnType, argsPre, arguments, nativeMethodName, static,
- descriptor, idlNode, argConversionStartsAt=0,
- getter=False, setter=False):
- CGThing.__init__(self)
- self.returnType = returnType
- self.descriptor = descriptor
- self.idlNode = idlNode
- self.extendedAttributes = descriptor.getExtendedAttributes(idlNode,
- getter=getter,
- setter=setter)
- self.argsPre = argsPre
- self.arguments = arguments
- self.argCount = len(arguments)
- if self.argCount > argConversionStartsAt:
- # Insert our argv in there
- cgThings = [CGGeneric(self.getArgvDecl())]
- else:
- cgThings = []
- cgThings.extend([CGArgumentConverter(arguments[i], i, self.getArgv(),
- self.getArgc(), self.descriptor,
- invalidEnumValueFatal=not setter) for
- i in range(argConversionStartsAt, self.argCount)])
-
- cgThings.append(CGCallGenerator(
- self.getErrorReport() if self.isFallible() else None,
- self.getArguments(), self.argsPre, returnType,
- self.extendedAttributes, descriptor, nativeMethodName,
- static))
- self.cgRoot = CGList(cgThings, "\n")
-
- def getArgv(self):
- return "argv" if self.argCount > 0 else ""
- def getArgvDecl(self):
- return "\nJS::Value* argv = JS_ARGV(cx, vp);\n"
- def getArgc(self):
- return "argc"
- def getArguments(self):
- return [(a, "arg" + str(i)) for (i, a) in enumerate(self.arguments)]
-
- def isFallible(self):
- return not 'infallible' in self.extendedAttributes
-
- def wrap_return_value(self):
- isCreator = memberIsCreator(self.idlNode)
- if isCreator:
- # We better be returning addrefed things!
- assert(isResultAlreadyAddRefed(self.descriptor,
- self.extendedAttributes) or
- # Workers use raw pointers for new-object return
- # values or something
- self.descriptor.workers)
-
- resultTemplateValues = { 'jsvalRef': '*vp', 'jsvalPtr': 'vp',
- 'isCreator': isCreator}
- try:
- return wrapForType(self.returnType, self.descriptor,
- resultTemplateValues)
- except MethodNotCreatorError, err:
- assert not isCreator
- raise TypeError("%s being returned from non-creator method or property %s.%s" %
- (err.typename,
- self.descriptor.interface.identifier.name,
- self.idlNode.identifier.name))
-
- def getErrorReport(self):
- return CGGeneric('return ThrowMethodFailedWithDetails<%s>(cx, rv, "%s", "%s");'
- % (toStringBool(not self.descriptor.workers),
- self.descriptor.interface.identifier.name,
- self.idlNode.identifier.name))
-
- def define(self):
- return (self.cgRoot.define() + "\n" + self.wrap_return_value())
-
-class CGSwitch(CGList):
- """
- A class to generate code for a switch statement.
-
- Takes three constructor arguments: an expression, a list of cases,
- and an optional default.
-
- Each case is a CGCase. The default is a CGThing for the body of
- the default case, if any.
- """
- def __init__(self, expression, cases, default=None):
- CGList.__init__(self, [CGIndenter(c) for c in cases], "\n")
- self.prepend(CGWrapper(CGGeneric(expression),
- pre="switch (", post=") {"));
- if default is not None:
- self.append(
- CGIndenter(
- CGWrapper(
- CGIndenter(default),
- pre="default: {\n",
- post="\n break;\n}"
- )
- )
- )
-
- self.append(CGGeneric("}"))
-
-class CGCase(CGList):
- """
- A class to generate code for a case statement.
-
- Takes three constructor arguments: an expression, a CGThing for
- the body (allowed to be None if there is no body), and an optional
- argument (defaulting to False) for whether to fall through.
- """
- def __init__(self, expression, body, fallThrough=False):
- CGList.__init__(self, [], "\n")
- self.append(CGWrapper(CGGeneric(expression), pre="case ", post=": {"))
- bodyList = CGList([body], "\n")
- if fallThrough:
- bodyList.append(CGGeneric("/* Fall through */"))
- else:
- bodyList.append(CGGeneric("break;"))
- self.append(CGIndenter(bodyList));
- self.append(CGGeneric("}"))
-
-class CGMethodCall(CGThing):
- """
- A class to generate selection of a method signature from a set of
- signatures and generation of a call to that signature.
- """
- def __init__(self, argsPre, nativeMethodName, static, descriptor, method):
- CGThing.__init__(self)
-
- methodName = '"%s.%s"' % (descriptor.interface.identifier.name, method.identifier.name)
-
- def requiredArgCount(signature):
- arguments = signature[1]
- if len(arguments) == 0:
- return 0
- requiredArgs = len(arguments)
- while requiredArgs and arguments[requiredArgs-1].optional:
- requiredArgs -= 1
- return requiredArgs
-
- def getPerSignatureCall(signature, argConversionStartsAt=0):
- return CGPerSignatureCall(signature[0], argsPre, signature[1],
- nativeMethodName, static, descriptor,
- method, argConversionStartsAt)
-
-
- signatures = method.signatures()
- if len(signatures) == 1:
- # Special case: we can just do a per-signature method call
- # here for our one signature and not worry about switching
- # on anything.
- signature = signatures[0]
- self.cgRoot = CGList([ CGIndenter(getPerSignatureCall(signature)) ])
- requiredArgs = requiredArgCount(signature)
-
-
- if requiredArgs > 0:
- code = (
- "if (argc < %d) {\n"
- " return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n"
- "}" % (requiredArgs, methodName))
- self.cgRoot.prepend(
- CGWrapper(CGIndenter(CGGeneric(code)), pre="\n", post="\n"))
- return
-
- # Need to find the right overload
- maxArgCount = method.maxArgCount
- allowedArgCounts = method.allowedArgCounts
-
- argCountCases = []
- for argCount in allowedArgCounts:
- possibleSignatures = method.signaturesForArgCount(argCount)
- if len(possibleSignatures) == 1:
- # easy case!
- signature = possibleSignatures[0]
-
- # (possibly) important optimization: if signature[1] has >
- # argCount arguments and signature[1][argCount] is optional and
- # there is only one signature for argCount+1, then the
- # signature for argCount+1 is just ourselves and we can fall
- # through.
- if (len(signature[1]) > argCount and
- signature[1][argCount].optional and
- (argCount+1) in allowedArgCounts and
- len(method.signaturesForArgCount(argCount+1)) == 1):
- argCountCases.append(
- CGCase(str(argCount), None, True))
- else:
- argCountCases.append(
- CGCase(str(argCount), getPerSignatureCall(signature)))
- continue
-
- distinguishingIndex = method.distinguishingIndexForArgCount(argCount)
-
- # We can't handle unions at the distinguishing index.
- for (returnType, args) in possibleSignatures:
- if args[distinguishingIndex].type.isUnion():
- raise TypeError("No support for unions as distinguishing "
- "arguments yet: %s",
- args[distinguishingIndex].location)
-
- # Convert all our arguments up to the distinguishing index.
- # Doesn't matter which of the possible signatures we use, since
- # they all have the same types up to that point; just use
- # possibleSignatures[0]
- caseBody = [CGGeneric("JS::Value* argv_start = JS_ARGV(cx, vp);")]
- caseBody.extend([ CGArgumentConverter(possibleSignatures[0][1][i],
- i, "argv_start", "argc",
- descriptor) for i in
- range(0, distinguishingIndex) ])
-
- # Select the right overload from our set.
- distinguishingArg = "argv_start[%d]" % distinguishingIndex
-
- def pickFirstSignature(condition, filterLambda):
- sigs = filter(filterLambda, possibleSignatures)
- assert len(sigs) < 2
- if len(sigs) > 0:
- if condition is None:
- caseBody.append(
- getPerSignatureCall(sigs[0], distinguishingIndex))
- else:
- caseBody.append(CGGeneric("if (" + condition + ") {"))
- caseBody.append(CGIndenter(
- getPerSignatureCall(sigs[0], distinguishingIndex)))
- caseBody.append(CGGeneric("}"))
- return True
- return False
-
- # First check for null or undefined
- pickFirstSignature("%s.isNullOrUndefined()" % distinguishingArg,
- lambda s: (s[1][distinguishingIndex].type.nullable() or
- s[1][distinguishingIndex].type.isDictionary()))
-
- # Now check for distinguishingArg being an object that implements a
- # non-callback interface. That includes typed arrays and
- # arraybuffers.
- interfacesSigs = [
- s for s in possibleSignatures
- if (s[1][distinguishingIndex].type.isObject() or
- s[1][distinguishingIndex].type.isNonCallbackInterface()) ]
- # There might be more than one of these; we need to check
- # which ones we unwrap to.
-
- if len(interfacesSigs) > 0:
- # The spec says that we should check for "platform objects
- # implementing an interface", but it's enough to guard on these
- # being an object. The code for unwrapping non-callback
- # interfaces and typed arrays will just bail out and move on to
- # the next overload if the object fails to unwrap correctly. We
- # could even not do the isObject() check up front here, but in
- # cases where we have multiple object overloads it makes sense
- # to do it only once instead of for each overload. That will
- # also allow the unwrapping test to skip having to do codegen
- # for the null-or-undefined case, which we already handled
- # above.
- caseBody.append(CGGeneric("if (%s.isObject()) {" %
- (distinguishingArg)))
- for sig in interfacesSigs:
- caseBody.append(CGIndenter(CGGeneric("do {")));
- type = sig[1][distinguishingIndex].type
-
- # The argument at index distinguishingIndex can't possibly
- # be unset here, because we've already checked that argc is
- # large enough that we can examine this argument.
- testCode = instantiateJSToNativeConversionTemplate(
- getJSToNativeConversionTemplate(type, descriptor,
- failureCode="break;",
- isDefinitelyObject=True),
- {
- "declName" : "arg%d" % distinguishingIndex,
- "holderName" : ("arg%d" % distinguishingIndex) + "_holder",
- "val" : distinguishingArg
- })
-
- # Indent by 4, since we need to indent further than our "do" statement
- caseBody.append(CGIndenter(testCode, 4));
- # If we got this far, we know we unwrapped to the right
- # interface, so just do the call. Start conversion with
- # distinguishingIndex + 1, since we already converted
- # distinguishingIndex.
- caseBody.append(CGIndenter(
- getPerSignatureCall(sig, distinguishingIndex + 1), 4))
- caseBody.append(CGIndenter(CGGeneric("} while (0);")))
-
- caseBody.append(CGGeneric("}"))
-
- # XXXbz Now we're supposed to check for distinguishingArg being
- # an array or a platform object that supports indexed
- # properties... skip that last for now. It's a bit of a pain.
- pickFirstSignature("%s.isObject() && IsArrayLike(cx, &%s.toObject())" %
- (distinguishingArg, distinguishingArg),
- lambda s:
- (s[1][distinguishingIndex].type.isArray() or
- s[1][distinguishingIndex].type.isSequence() or
- s[1][distinguishingIndex].type.isObject()))
-
- # Check for Date objects
- # XXXbz Do we need to worry about security wrappers around the Date?
- pickFirstSignature("%s.isObject() && JS_ObjectIsDate(cx, &%s.toObject())" %
- (distinguishingArg, distinguishingArg),
- lambda s: (s[1][distinguishingIndex].type.isDate() or
- s[1][distinguishingIndex].type.isObject()))
-
- # Check for vanilla JS objects
- # XXXbz Do we need to worry about security wrappers?
- pickFirstSignature("%s.isObject() && !IsPlatformObject(cx, &%s.toObject())" %
- (distinguishingArg, distinguishingArg),
- lambda s: (s[1][distinguishingIndex].type.isCallback() or
- s[1][distinguishingIndex].type.isCallbackInterface() or
- s[1][distinguishingIndex].type.isDictionary() or
- s[1][distinguishingIndex].type.isObject()))
-
- # The remaining cases are mutually exclusive. The
- # pickFirstSignature calls are what change caseBody
- # Check for strings or enums
- if pickFirstSignature(None,
- lambda s: (s[1][distinguishingIndex].type.isString() or
- s[1][distinguishingIndex].type.isEnum())):
- pass
- # Check for primitives
- elif pickFirstSignature(None,
- lambda s: s[1][distinguishingIndex].type.isPrimitive()):
- pass
- # Check for "any"
- elif pickFirstSignature(None,
- lambda s: s[1][distinguishingIndex].type.isAny()):
- pass
- else:
- # Just throw; we have no idea what we're supposed to
- # do with this.
- caseBody.append(CGGeneric("return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);" %
- toStringBool(not descriptor.workers)))
-
- argCountCases.append(CGCase(str(argCount),
- CGList(caseBody, "\n")))
-
- overloadCGThings = []
- overloadCGThings.append(
- CGGeneric("unsigned argcount = NS_MIN(argc, %du);" %
- maxArgCount))
- overloadCGThings.append(
- CGSwitch("argcount",
- argCountCases,
- CGGeneric("return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n" % methodName)))
- overloadCGThings.append(
- CGGeneric('MOZ_NOT_REACHED("We have an always-returning default case");\n'
- 'return false;'))
- self.cgRoot = CGWrapper(CGIndenter(CGList(overloadCGThings, "\n")),
- pre="\n")
-
- def define(self):
- return self.cgRoot.define()
-
-class CGGetterCall(CGPerSignatureCall):
- """
- A class to generate a native object getter call for a particular IDL
- getter.
- """
- def __init__(self, returnType, nativeMethodName, descriptor, attr):
- CGPerSignatureCall.__init__(self, returnType, [], [],
- nativeMethodName, False, descriptor,
- attr, getter=True)
-
-class FakeArgument():
- """
- A class that quacks like an IDLArgument. This is used to make
- setters look like method calls or for special operations.
- """
- def __init__(self, type, interfaceMember):
- self.type = type
- self.optional = False
- self.variadic = False
- self.defaultValue = None
- self.treatNullAs = interfaceMember.treatNullAs
- self.treatUndefinedAs = interfaceMember.treatUndefinedAs
- self.enforceRange = False
- self.clamp = False
-
-class CGSetterCall(CGPerSignatureCall):
- """
- A class to generate a native object setter call for a particular IDL
- setter.
- """
- def __init__(self, argType, nativeMethodName, descriptor, attr):
- CGPerSignatureCall.__init__(self, None, [],
- [FakeArgument(argType, attr)],
- nativeMethodName, False, descriptor, attr,
- setter=True)
- def wrap_return_value(self):
- # We have no return value
- return "\nreturn true;"
- def getArgc(self):
- return "1"
- def getArgvDecl(self):
- # We just get our stuff from our last arg no matter what
- return ""
-
-class FakeCastableDescriptor():
- def __init__(self, descriptor):
- self.castable = True
- self.workers = descriptor.workers
- self.nativeType = descriptor.nativeType
- self.name = descriptor.name
- self.hasXPConnectImpls = descriptor.hasXPConnectImpls
-
-class CGAbstractBindingMethod(CGAbstractStaticMethod):
- """
- Common class to generate the JSNatives for all our methods, getters, and
- setters. This will generate the function declaration and unwrap the
- |this| object. Subclasses are expected to override the generate_code
- function to do the rest of the work. This function should return a
- CGThing which is already properly indented.
- """
- def __init__(self, descriptor, name, args, unwrapFailureCode=None):
- CGAbstractStaticMethod.__init__(self, descriptor, name, "JSBool", args)
-
- if unwrapFailureCode is None:
- self.unwrapFailureCode = ("return Throw<%s>(cx, rv);" %
- toStringBool(not descriptor.workers))
- else:
- self.unwrapFailureCode = unwrapFailureCode
-
- def definition_body(self):
- # Our descriptor might claim that we're not castable, simply because
- # we're someone's consequential interface. But for this-unwrapping, we
- # know that we're the real deal. So fake a descriptor here for
- # consumption by FailureFatalCastableObjectUnwrapper.
- unwrapThis = CGIndenter(CGGeneric(
- str(CastableObjectUnwrapper(
- FakeCastableDescriptor(self.descriptor),
- "obj", "self", self.unwrapFailureCode))))
- return CGList([ self.getThis(), unwrapThis,
- self.generate_code() ], "\n").define()
-
- def getThis(self):
- return CGIndenter(
- CGGeneric("js::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));\n"
- "if (!obj) {\n"
- " return false;\n"
- "}\n"
- "\n"
- "%s* self;" % self.descriptor.nativeType))
-
- def generate_code(self):
- assert(False) # Override me
-
-def MakeNativeName(name):
- return name[0].upper() + name[1:]
-
-class CGGenericMethod(CGAbstractBindingMethod):
- """
- A class for generating the C++ code for an IDL method..
- """
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
- Argument('JS::Value*', 'vp')]
- CGAbstractBindingMethod.__init__(self, descriptor, 'genericMethod', args)
-
- def generate_code(self):
- return CGIndenter(CGGeneric(
- "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
- "JSJitMethodOp method = (JSJitMethodOp)info->op;\n"
- "return method(cx, obj, self, argc, vp);"))
-
-class CGSpecializedMethod(CGAbstractStaticMethod):
- """
- A class for generating the C++ code for a specialized method that the JIT
- can call with lower overhead.
- """
- def __init__(self, descriptor, method):
- self.method = method
- name = method.identifier.name
- args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
- Argument('%s*' % descriptor.nativeType, 'self'),
- Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')]
- CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args)
-
- def definition_body(self):
- name = self.method.identifier.name
- nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
- return CGMethodCall([], nativeName, self.method.isStatic(),
- self.descriptor, self.method).define()
-
-class CGGenericGetter(CGAbstractBindingMethod):
- """
- A class for generating the C++ code for an IDL attribute getter.
- """
- def __init__(self, descriptor, lenientThis=False):
- args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
- Argument('JS::Value*', 'vp')]
- if lenientThis:
- name = "genericLenientGetter"
- unwrapFailureCode = (
- "MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"
- "JS_SET_RVAL(cx, vp, JS::UndefinedValue());\n"
- "return true;")
- else:
- name = "genericGetter"
- unwrapFailureCode = None
- CGAbstractBindingMethod.__init__(self, descriptor, name, args,
- unwrapFailureCode)
-
- def generate_code(self):
- return CGIndenter(CGGeneric(
- "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
- "JSJitPropertyOp getter = info->op;\n"
- "return getter(cx, obj, self, vp);"))
-
-class CGSpecializedGetter(CGAbstractStaticMethod):
- """
- A class for generating the code for a specialized attribute getter
- that the JIT can call with lower overhead.
- """
- def __init__(self, descriptor, attr):
- self.attr = attr
- name = 'get_' + attr.identifier.name
- args = [ Argument('JSContext*', 'cx'),
- Argument('JSHandleObject', 'obj'),
- Argument('%s*' % descriptor.nativeType, 'self'),
- Argument('JS::Value*', 'vp') ]
- CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
-
- def definition_body(self):
- name = self.attr.identifier.name
- nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
- # resultOutParam does not depend on whether resultAlreadyAddRefed is set
- (_, resultOutParam) = getRetvalDeclarationForType(self.attr.type,
- self.descriptor,
- False)
- infallible = ('infallible' in
- self.descriptor.getExtendedAttributes(self.attr,
- getter=True))
- if resultOutParam or self.attr.type.nullable() or not infallible:
- nativeName = "Get" + nativeName
- return CGIndenter(CGGetterCall(self.attr.type, nativeName,
- self.descriptor, self.attr)).define()
-
-class CGGenericSetter(CGAbstractBindingMethod):
- """
- A class for generating the C++ code for an IDL attribute setter.
- """
- def __init__(self, descriptor, lenientThis=False):
- args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
- Argument('JS::Value*', 'vp')]
- if lenientThis:
- name = "genericLenientSetter"
- unwrapFailureCode = (
- "MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"
- "return true;")
- else:
- name = "genericSetter"
- unwrapFailureCode = None
- CGAbstractBindingMethod.__init__(self, descriptor, name, args,
- unwrapFailureCode)
-
- def generate_code(self):
- return CGIndenter(CGGeneric(
- "JS::Value* argv = JS_ARGV(cx, vp);\n"
- "JS::Value undef = JS::UndefinedValue();\n"
- "if (argc == 0) {\n"
- " argv = &undef;\n"
- "}\n"
- "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
- "JSJitPropertyOp setter = info->op;\n"
- "if (!setter(cx, obj, self, argv)) {\n"
- " return false;\n"
- "}\n"
- "*vp = JSVAL_VOID;\n"
- "return true;"))
-
-class CGSpecializedSetter(CGAbstractStaticMethod):
- """
- A class for generating the code for a specialized attribute setter
- that the JIT can call with lower overhead.
- """
- def __init__(self, descriptor, attr):
- self.attr = attr
- name = 'set_' + attr.identifier.name
- args = [ Argument('JSContext*', 'cx'),
- Argument('JSHandleObject', 'obj'),
- Argument('%s*' % descriptor.nativeType, 'self'),
- Argument('JS::Value*', 'argv')]
- CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
-
- def definition_body(self):
- name = self.attr.identifier.name
- nativeName = "Set" + MakeNativeName(self.descriptor.binaryNames.get(name, name))
- return CGIndenter(CGSetterCall(self.attr.type, nativeName,
- self.descriptor, self.attr)).define()
-
-def memberIsCreator(member):
- return member.getExtendedAttribute("Creator") is not None
-
-class CGMemberJITInfo(CGThing):
- """
- A class for generating the JITInfo for a property that points to
- our specialized getter and setter.
- """
- def __init__(self, descriptor, member):
- self.member = member
- self.descriptor = descriptor
-
- def declare(self):
- return ""
-
- def defineJitInfo(self, infoName, opName, infallible):
- protoID = "prototypes::id::%s" % self.descriptor.name
- depth = "PrototypeTraits<%s>::Depth" % protoID
- failstr = "true" if infallible else "false"
- return ("\n"
- "const JSJitInfo %s = {\n"
- " %s,\n"
- " %s,\n"
- " %s,\n"
- " %s, /* isInfallible. False in setters. */\n"
- " false /* isConstant. Only relevant for getters. */\n"
- "};\n" % (infoName, opName, protoID, depth, failstr))
-
- def define(self):
- if self.member.isAttr():
- getterinfo = ("%s_getterinfo" % self.member.identifier.name)
- getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name)
- getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
- getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
- result = self.defineJitInfo(getterinfo, getter, getterinfal)
- if not self.member.readonly:
- setterinfo = ("%s_setterinfo" % self.member.identifier.name)
- setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name)
- # Setters are always fallible, since they have to do a typed unwrap.
- result += self.defineJitInfo(setterinfo, setter, False)
- return result
- if self.member.isMethod():
- methodinfo = ("%s_methodinfo" % self.member.identifier.name)
- # Actually a JSJitMethodOp, but JSJitPropertyOp by struct definition.
- method = ("(JSJitPropertyOp)%s" % self.member.identifier.name)
-
- # Methods are infallible if they are infallible, have no arguments
- # to unwrap, and have a return type that's infallible to wrap up for
- # return.
- methodInfal = False
- sigs = self.member.signatures()
- if len(sigs) == 1:
- # Don't handle overloading. If there's more than one signature,
- # one of them must take arguments.
- sig = sigs[0]
- if len(sig[1]) == 0 and infallibleForMember(self.member, sig[0], self.descriptor):
- # No arguments and infallible return boxing
- methodInfal = True
-
- result = self.defineJitInfo(methodinfo, method, methodInfal)
- return result
- raise TypeError("Illegal member type to CGPropertyJITInfo")
-
-def getEnumValueName(value):
- # Some enum values can be empty strings. Others might have weird
- # characters in them. Deal with the former by returning "_empty",
- # deal with possible name collisions from that by throwing if the
- # enum value is actually "_empty", and throw on any value
- # containing chars other than [a-z] or '-' for now. Replace '-' with '_'.
- value = value.replace('-', '_')
- if value == "_empty":
- raise SyntaxError('"_empty" is not an IDL enum value we support yet')
- if value == "":
- return "_empty"
- if not re.match("^[a-z_]+$", value):
- raise SyntaxError('Enum value "' + value + '" contains characters '
- 'outside [a-z_]')
- return MakeNativeName(value)
-
-class CGEnum(CGThing):
- def __init__(self, enum):
- CGThing.__init__(self)
- self.enum = enum
-
- def declare(self):
- return """
- enum valuelist {
- %s
- };
-
- extern const EnumEntry strings[%d];
-""" % (",\n ".join(map(getEnumValueName, self.enum.values())),
- len(self.enum.values()) + 1)
-
- def define(self):
- return """
- const EnumEntry strings[%d] = {
- %s,
- { NULL, 0 }
- };
-""" % (len(self.enum.values()) + 1,
- ",\n ".join(['{"' + val + '", ' + str(len(val)) + '}' for val in self.enum.values()]))
-
-def getUnionAccessorSignatureType(type, descriptorProvider):
- """
- Returns the types that are used in the getter and setter signatures for
- union types
- """
- if type.isArray():
- raise TypeError("Can't handle array arguments yet")
-
- if type.isSequence():
- nullable = type.nullable();
- if nullable:
- type = type.inner.inner
- else:
- type = type.inner
- (elementTemplate, elementDeclType,
- elementHolderType, dealWithOptional) = getJSToNativeConversionTemplate(
- type, descriptorProvider, isSequenceMember=True)
- typeName = CGWrapper(elementDeclType, pre="Sequence< ", post=" >&")
- if nullable:
- typeName = CGWrapper(typeName, pre="Nullable< ", post=" >&")
-
- return typeName
-
- if type.isUnion():
- typeName = CGGeneric(type.name)
- if type.nullable():
- typeName = CGWrapper(typeName, pre="Nullable< ", post=" >&")
-
- return typeName
-
- if type.isGeckoInterface():
- descriptor = descriptorProvider.getDescriptor(
- type.unroll().inner.identifier.name)
- typeName = CGGeneric(descriptor.nativeType)
- # Allow null pointers for nullable types and old-binding classes
- if type.nullable() or type.unroll().inner.isExternal():
- typeName = CGWrapper(typeName, post="*")
- else:
- typeName = CGWrapper(typeName, post="&")
- return typeName
-
- if type.isSpiderMonkeyInterface():
- typeName = CGGeneric(type.name)
- if type.nullable():
- typeName = CGWrapper(typeName, post="*")
- else:
- typeName = CGWrapper(typeName, post="&")
- return typeName
-
- if type.isString():
- return CGGeneric("const nsAString&")
-
- if type.isEnum():
- if type.nullable():
- raise TypeError("We don't support nullable enumerated arguments or "
- "union members yet")
- return CGGeneric(type.inner.identifier.name)
-
- if type.isCallback():
- return CGGeneric("JSObject*")
-
- if type.isAny():
- return CGGeneric("JS::Value")
-
- if type.isObject():
- typeName = CGGeneric("JSObject")
- if type.nullable():
- typeName = CGWrapper(typeName, post="*")
- else:
- typeName = CGWrapper(typeName, post="&")
- return typeName
-
- if not type.isPrimitive():
- raise TypeError("Need native type for argument type '%s'" % str(type))
-
- typeName = CGGeneric(builtinNames[type.tag()])
- if type.nullable():
- typeName = CGWrapper(typeName, pre="Nullable< ", post=" >&")
- return typeName
-
-def getUnionTypeTemplateVars(type, descriptorProvider):
- # For dictionaries and sequences we need to pass None as the failureCode
- # for getJSToNativeConversionTemplate.
- # Also, for dictionaries we would need to handle conversion of
- # null/undefined to the dictionary correctly.
- if type.isDictionary() or type.isSequence():
- raise TypeError("Can't handle dictionaries or sequences in unions")
-
- if type.isGeckoInterface():
- name = type.inner.identifier.name
- elif type.isEnum():
- name = type.inner.identifier.name
- elif type.isArray() or type.isSequence():
- name = str(type)
- else:
- name = type.name
-
- tryNextCode = """tryNext = true;
-return true;"""
- if type.isGeckoInterface():
- tryNextCode = ("""if (mUnion.mType != mUnion.eUninitialized) {
- mUnion.Destroy%s();
-}""" % name) + tryNextCode
- (template, declType, holderType,
- dealWithOptional) = getJSToNativeConversionTemplate(
- type, descriptorProvider, failureCode=tryNextCode,
- isDefinitelyObject=True)
-
- # This is ugly, but UnionMember needs to call a constructor with no
- # arguments so the type can't be const.
- structType = declType.define()
- if structType.startswith("const "):
- structType = structType[6:]
- externalType = getUnionAccessorSignatureType(type, descriptorProvider).define()
-
- if type.isObject():
- setter = CGGeneric("void SetToObject(JSObject* obj)\n"
- "{\n"
- " mUnion.mValue.mObject.SetValue() = obj;\n"
- " mUnion.mType = mUnion.eObject;\n"
- "}")
- else:
- jsConversion = string.Template(template).substitute(
- {
- "val": "value",
- "valPtr": "pvalue",
- "declName": "SetAs" + name + "()",
- "holderName": "m" + name + "Holder"
- }
- )
- jsConversion = CGWrapper(CGGeneric(jsConversion),
- post="\n"
- "return true;")
- setter = CGWrapper(CGIndenter(jsConversion),
- pre="bool TrySetTo" + name + "(JSContext* cx, const JS::Value& value, JS::Value* pvalue, bool& tryNext)\n"
- "{\n"
- " tryNext = false;\n",
- post="\n"
- "}")
-
- return {
- "name": name,
- "structType": structType,
- "externalType": externalType,
- "setter": CGIndenter(setter).define(),
- "holderType": holderType.define() if holderType else None
- }
-
-def mapTemplate(template, templateVarArray):
- return map(lambda v: string.Template(template).substitute(v),
- templateVarArray)
-
-class CGUnionStruct(CGThing):
- def __init__(self, type, descriptorProvider):
- CGThing.__init__(self)
- self.type = type.unroll()
- self.descriptorProvider = descriptorProvider
-
- def declare(self):
- templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider),
- self.type.flatMemberTypes)
-
- callDestructors = []
- enumValues = []
- methods = []
- if self.type.hasNullableType:
- callDestructors.append(" case eNull:\n"
- " break;")
- enumValues.append("eNull")
- methods.append(""" bool IsNull() const
- {
- return mType == eNull;
- }""")
-
- destructorTemplate = """ void Destroy${name}()
- {
- MOZ_ASSERT(Is${name}(), "Wrong type!");
- mValue.m${name}.Destroy();
- mType = eUninitialized;
- }"""
- destructors = mapTemplate(destructorTemplate, templateVars)
- callDestructors.extend(mapTemplate(" case e${name}:\n"
- " Destroy${name}();\n"
- " break;", templateVars))
- enumValues.extend(mapTemplate("e${name}", templateVars))
- methodTemplate = """ bool Is${name}() const
- {
- return mType == e${name};
- }
- ${externalType} GetAs${name}() const
- {
- MOZ_ASSERT(Is${name}(), "Wrong type!");
- // The cast to ${externalType} is needed to work around a bug in Apple's
- // clang compiler, for some reason it doesn't call |S::operator T&| when
- // casting S<T> to T& and T is forward declared.
- return (${externalType})mValue.m${name}.Value();
- }
- ${structType}& SetAs${name}()
- {
- mType = e${name};
- return mValue.m${name}.SetValue();
- }"""
- methods.extend(mapTemplate(methodTemplate, templateVars))
- values = mapTemplate("UnionMember<${structType} > m${name};", templateVars)
- return string.Template("""
-class ${structName} {
-public:
- ${structName}() : mType(eUninitialized)
- {
- }
- ~${structName}()
- {
- switch (mType) {
-${callDestructors}
- case eUninitialized:
- break;
- }
- }
-
-${methods}
-
-private:
- friend class ${structName}Argument;
-
-${destructors}
-
- enum Type {
- eUninitialized,
- ${enumValues}
- };
- union Value {
- ${values}
- };
-
- Type mType;
- Value mValue;
-};
-
-""").substitute(
- {
- "structName": self.type.__str__(),
- "callDestructors": "\n".join(callDestructors),
- "destructors": "\n".join(destructors),
- "methods": "\n\n".join(methods),
- "enumValues": ",\n ".join(enumValues),
- "values": "\n ".join(values),
- })
-
- def define(self):
- return """
-"""
-
-class CGUnionConversionStruct(CGThing):
- def __init__(self, type, descriptorProvider):
- CGThing.__init__(self)
- self.type = type.unroll()
- self.descriptorProvider = descriptorProvider
-
- def declare(self):
- setters = []
-
- if self.type.hasNullableType:
- setters.append(""" bool SetNull()
- {
- mUnion.mType = mUnion.eNull;
- return true;
- }""")
-
- templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider),
- self.type.flatMemberTypes)
- structName = self.type.__str__()
-
- setters.extend(mapTemplate("${setter}", templateVars))
- private = "\n".join(mapTemplate(""" ${structType}& SetAs${name}()
- {
- mUnion.mType = mUnion.e${name};
- return mUnion.mValue.m${name}.SetValue();
- }""", templateVars))
- private += "\n\n"
- holders = filter(lambda v: v["holderType"] is not None, templateVars)
- if len(holders) > 0:
- private += "\n".join(mapTemplate(" ${holderType} m${name}Holder;", holders))
- private += "\n\n"
- private += " " + structName + "& mUnion;"
- return string.Template("""
-class ${structName}Argument {
-public:
- ${structName}Argument(const ${structName}& aUnion) : mUnion(const_cast<${structName}&>(aUnion))
- {
- }
-
-${setters}
-
-private:
-${private}
-};
-""").substitute({"structName": structName,
- "setters": "\n\n".join(setters),
- "private": private
- })
-
- def define(self):
- return """
-"""
-
-class ClassItem:
- """ Use with CGClass """
- def __init__(self, name, visibility):
- self.name = name
- self.visibility = visibility
- def declare(self, cgClass):
- assert False
- def define(self, cgClass):
- assert False
-
-class ClassBase(ClassItem):
- def __init__(self, name, visibility='public'):
- ClassItem.__init__(self, name, visibility)
- def declare(self, cgClass):
- return '%s %s' % (self.visibility, self.name)
- def define(self, cgClass):
- # Only in the header
- return ''
-
-class ClassMethod(ClassItem):
- def __init__(self, name, returnType, args, inline=False, static=False,
- virtual=False, const=False, bodyInHeader=False,
- templateArgs=None, visibility='public', body=None):
- self.returnType = returnType
- self.args = args
- self.inline = inline or bodyInHeader
- self.static = static
- self.virtual = virtual
- self.const = const
- self.bodyInHeader = bodyInHeader
- self.templateArgs = templateArgs
- self.body = body
- ClassItem.__init__(self, name, visibility)
-
- def getDecorators(self, declaring):
- decorators = []
- if self.inline:
- decorators.append('inline')
- if declaring:
- if self.static:
- decorators.append('static')
- if self.virtual:
- decorators.append('virtual')
- if decorators:
- return ' '.join(decorators) + ' '
- return ''
-
- def getBody(self):
- # Override me or pass a string to constructor
- assert self.body is not None
- return self.body
-
- def declare(self, cgClass):
- templateClause = 'template <%s>\n' % ', '.join(self.templateArgs) \
- if self.bodyInHeader and self.templateArgs else ''
- args = ', '.join([str(a) for a in self.args])
- if self.bodyInHeader:
- body = CGIndenter(CGGeneric(self.getBody())).define()
- body = '\n{\n' + body + '\n}'
- else:
- body = ';'
-
- return string.Template("""${templateClause}${decorators}${returnType}
-${name}(${args})${const}${body}
-""").substitute({ 'templateClause': templateClause,
- 'decorators': self.getDecorators(True),
- 'returnType': self.returnType,
- 'name': self.name,
- 'const': ' const' if self.const else '',
- 'args': args,
- 'body': body })
-
- def define(self, cgClass):
- if self.bodyInHeader:
- return ''
-
- templateArgs = cgClass.templateArgs
- if templateArgs:
- if cgClass.templateSpecialization:
- templateArgs = \
- templateArgs[len(cgClass.templateSpecialization):]
-
- if templateArgs:
- templateClause = \
- 'template <%s>\n' % ', '.join([str(a) for a in templateArgs])
- else:
- templateClause = ''
-
- args = ', '.join([str(a) for a in self.args])
-
- body = CGIndenter(CGGeneric(self.getBody())).define()
-
- return string.Template("""${templateClause}${decorators}${returnType}
-${className}::${name}(${args})${const}
-{
-${body}
-}\n
-""").substitute({ 'templateClause': templateClause,
- 'decorators': self.getDecorators(False),
- 'returnType': self.returnType,
- 'className': cgClass.getNameString(),
- 'name': self.name,
- 'args': args,
- 'const': ' const' if self.const else '',
- 'body': body })
-
-class ClassConstructor(ClassItem):
- """
- Used for adding a constructor to a CGClass.
-
- args is a list of Argument objects that are the arguments taken by the
- constructor.
-
- inline should be True if the constructor should be marked inline.
-
- bodyInHeader should be True if the body should be placed in the class
- declaration in the header.
-
- visibility determines the visibility of the constructor (public,
- protected, private), defaults to private.
-
- baseConstructors is a list of strings containing calls to base constructors,
- defaults to None.
-
- body contains a string with the code for the constructor, defaults to None.
- """
- def __init__(self, args, inline=False, bodyInHeader=False,
- visibility="private", baseConstructors=None, body=None):
- self.args = args
- self.inline = inline or bodyInHeader
- self.bodyInHeader = bodyInHeader
- self.baseConstructors = baseConstructors
- self.body = body
- ClassItem.__init__(self, None, visibility)
-
- def getDecorators(self, declaring):
- decorators = []
- if self.inline and declaring:
- decorators.append('inline')
- if decorators:
- return ' '.join(decorators) + ' '
- return ''
-
- def getInitializationList(self, cgClass):
- items = [str(c) for c in self.baseConstructors]
- for m in cgClass.members:
- if not m.static:
- initialize = m.getBody()
- if initialize:
- items.append(m.name + "(" + initialize + ")")
-
- if len(items) > 0:
- return '\n : ' + ',\n '.join(items)
- return ''
-
- def getBody(self):
- assert self.body is not None
- return self.body
-
- def declare(self, cgClass):
- args = ', '.join([str(a) for a in self.args])
- if self.bodyInHeader:
- body = ' ' + self.getBody();
- body = stripTrailingWhitespace(body.replace('\n', '\n '))
- if len(body) > 0:
- body += '\n'
- body = self.getInitializationList(cgClass) + '\n{\n' + body + '}'
- else:
- body = ';'
-
- return string.Template("""${decorators}${className}(${args})${body}
-""").substitute({ 'decorators': self.getDecorators(True),
- 'className': cgClass.getNameString(),
- 'args': args,
- 'body': body })
-
- def define(self, cgClass):
- if self.bodyInHeader:
- return ''
-
- args = ', '.join([str(a) for a in self.args])
-
- body = ' ' + self.getBody()
- body = '\n' + stripTrailingWhitespace(body.replace('\n', '\n '))
- if len(body) > 0:
- body += '\n'
-
- return string.Template("""${decorators}
-${className}::${className}(${args})${initializationList}
-{${body}}\n
-""").substitute({ 'decorators': self.getDecorators(False),
- 'className': cgClass.getNameString(),
- 'args': args,
- 'initializationList': self.getInitializationList(cgClass),
- 'body': body })
-
-class ClassMember(ClassItem):
- def __init__(self, name, type, visibility="private", static=False,
- body=None):
- self.type = type;
- self.static = static
- self.body = body
- ClassItem.__init__(self, name, visibility)
-
- def declare(self, cgClass):
- return '%s%s %s;\n' % ('static ' if self.static else '', self.type,
- self.name)
-
- def define(self, cgClass):
- if not self.static:
- return ''
- if self.body:
- body = " = " + self.body
- else:
- body = ""
- return '%s %s::%s%s;\n' % (self.type, cgClass.getNameString(),
- self.name, body)
-
-class ClassTypedef(ClassItem):
- def __init__(self, name, type, visibility="public"):
- self.type = type
- ClassItem.__init__(self, name, visibility)
-
- def declare(self, cgClass):
- return 'typedef %s %s;\n' % (self.type, self.name)
-
- def define(self, cgClass):
- # Only goes in the header
- return ''
-
-class ClassEnum(ClassItem):
- def __init__(self, name, entries, values=None, visibility="public"):
- self.entries = entries
- self.values = values
- ClassItem.__init__(self, name, visibility)
-
- def declare(self, cgClass):
- entries = []
- for i in range(0, len(self.entries)):
- if i >= len(self.values):
- entry = '%s' % self.entries[i]
- else:
- entry = '%s = %s' % (self.entries[i], self.values[i])
- entries.append(entry)
- name = '' if not self.name else ' ' + self.name
- return 'enum%s\n{\n %s\n};\n' % (name, ',\n '.join(entries))
-
- def define(self, cgClass):
- # Only goes in the header
- return ''
-
-class CGClass(CGThing):
- def __init__(self, name, bases=[], members=[], constructors=[], methods=[],
- typedefs = [], enums=[], templateArgs=[],
- templateSpecialization=[], isStruct=False, indent=''):
- CGThing.__init__(self)
- self.name = name
- self.bases = bases
- self.members = members
- self.constructors = constructors
- self.methods = methods
- self.typedefs = typedefs
- self.enums = enums
- self.templateArgs = templateArgs
- self.templateSpecialization = templateSpecialization
- self.isStruct = isStruct
- self.indent = indent
- self.defaultVisibility ='public' if isStruct else 'private'
-
- def getNameString(self):
- className = self.name
- if self.templateSpecialization:
- className = className + \
- '<%s>' % ', '.join([str(a) for a
- in self.templateSpecialization])
- return className
-
- def declare(self):
- result = ''
- if self.templateArgs:
- templateArgs = [str(a) for a in self.templateArgs]
- templateArgs = templateArgs[len(self.templateSpecialization):]
- result = result + self.indent + 'template <%s>\n' \
- % ','.join([str(a) for a in templateArgs])
-
- type = 'struct' if self.isStruct else 'class'
-
- if self.templateSpecialization:
- specialization = \
- '<%s>' % ', '.join([str(a) for a in self.templateSpecialization])
- else:
- specialization = ''
-
- result = result + '%s%s %s%s' \
- % (self.indent, type, self.name, specialization)
-
- if self.bases:
- result = result + ' : %s' % ', '.join([d.declare(self) for d in self.bases])
-
- result = result + '\n%s{\n' % self.indent
-
- def declareMembers(cgClass, memberList, defaultVisibility, itemCount,
- separator=''):
- members = { 'private': [], 'protected': [], 'public': [] }
-
- for member in memberList:
- members[member.visibility].append(member)
-
-
- if defaultVisibility == 'public':
- order = [ 'public', 'protected', 'private' ]
- else:
- order = [ 'private', 'protected', 'public' ]
-
- result = ''
-
- lastVisibility = defaultVisibility
- for visibility in order:
- list = members[visibility]
- if list:
- if visibility != lastVisibility:
- if itemCount:
- result = result + '\n'
- result = result + visibility + ':\n'
- itemCount = 0
- for member in list:
- if itemCount != 0:
- result = result + separator
- declaration = member.declare(cgClass)
- declaration = CGIndenter(CGGeneric(declaration)).define()
- result = result + declaration
- itemCount = itemCount + 1
- lastVisibility = visibility
- return (result, lastVisibility, itemCount)
-
- order = [(self.enums, ''), (self.typedefs, ''), (self.members, ''),
- (self.constructors, '\n'), (self.methods, '\n')]
-
- lastVisibility = self.defaultVisibility
- itemCount = 0
- for (memberList, separator) in order:
- (memberString, lastVisibility, itemCount) = \
- declareMembers(self, memberList, lastVisibility, itemCount,
- separator)
- if self.indent:
- memberString = CGIndenter(CGGeneric(memberString),
- len(self.indent)).define()
- result = result + memberString
-
- result = result + self.indent + '};\n'
- return result
-
- def define(self):
- def defineMembers(cgClass, memberList, itemCount, separator=''):
- result = ''
- for member in memberList:
- if itemCount != 0:
- result = result + separator
- result = result + member.define(cgClass)
- itemCount = itemCount + 1
- return (result, itemCount)
-
- order = [(self.members, '\n'), (self.constructors, '\n'),
- (self.methods, '\n')]
-
- result = ''
- itemCount = 0
- for (memberList, separator) in order:
- (memberString, itemCount) = defineMembers(self, memberList,
- itemCount, separator)
- result = result + memberString
- return result
-
-class CGResolveOwnProperty(CGAbstractMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
- Argument('jsid', 'id'), Argument('bool', 'set'),
- Argument('JSPropertyDescriptor*', 'desc')]
- CGAbstractMethod.__init__(self, descriptor, "ResolveOwnProperty", "bool", args)
- def definition_body(self):
- return """ JSObject* obj = wrapper;
- if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
- obj = js::UnwrapObject(obj);
- }
- // We rely on getOwnPropertyDescriptor not shadowing prototype properties by named
- // properties. If that changes we'll need to filter here.
- return js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, wrapper, id, set, desc);
-"""
-
-class CGEnumerateOwnProperties(CGAbstractMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
- Argument('JS::AutoIdVector&', 'props')]
- CGAbstractMethod.__init__(self, descriptor, "EnumerateOwnProperties", "bool", args)
- def definition_body(self):
- return """ JSObject* obj = wrapper;
- if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
- obj = js::UnwrapObject(obj);
- }
- // We rely on getOwnPropertyNames not shadowing prototype properties by named
- // properties. If that changes we'll need to filter here.
- return js::GetProxyHandler(obj)->getOwnPropertyNames(cx, wrapper, props);
-"""
-
-class CGXrayHelper(CGAbstractMethod):
- def __init__(self, descriptor, name, args, properties):
- CGAbstractMethod.__init__(self, descriptor, name, "bool", args)
- self.properties = properties
-
- def definition_body(self):
- varNames = self.properties.variableNames(True)
-
- methods = self.properties.methods
- if methods.hasNonChromeOnly() or methods.hasChromeOnly():
- methodArgs = """// %(methods)s has an end-of-list marker at the end that we ignore
-%(methods)s, %(methods)s_ids, %(methods)s_specs, ArrayLength(%(methods)s) - 1""" % varNames
- else:
- methodArgs = "NULL, NULL, NULL, 0"
- methodArgs = CGGeneric(methodArgs)
-
- attrs = self.properties.attrs
- if attrs.hasNonChromeOnly() or attrs.hasChromeOnly():
- attrArgs = """// %(attrs)s has an end-of-list marker at the end that we ignore
-%(attrs)s, %(attrs)s_ids, %(attrs)s_specs, ArrayLength(%(attrs)s) - 1""" % varNames
- else:
- attrArgs = "NULL, NULL, NULL, 0"
- attrArgs = CGGeneric(attrArgs)
-
- consts = self.properties.consts
- if consts.hasNonChromeOnly() or consts.hasChromeOnly():
- constArgs = """// %(consts)s has an end-of-list marker at the end that we ignore
-%(consts)s, %(consts)s_ids, %(consts)s_specs, ArrayLength(%(consts)s) - 1""" % varNames
- else:
- constArgs = "NULL, NULL, NULL, 0"
- constArgs = CGGeneric(constArgs)
-
- prefixArgs = CGGeneric(self.getPrefixArgs())
-
- return CGIndenter(
- CGWrapper(CGList([prefixArgs, methodArgs, attrArgs, constArgs], ",\n"),
- pre=("return Xray%s(" % self.name),
- post=");",
- reindent=True)).define()
-
-class CGResolveProperty(CGXrayHelper):
- def __init__(self, descriptor, properties):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
- Argument('jsid', 'id'), Argument('bool', 'set'),
- Argument('JSPropertyDescriptor*', 'desc')]
- CGXrayHelper.__init__(self, descriptor, "ResolveProperty", args,
- properties)
-
- def getPrefixArgs(self):
- return "cx, wrapper, id, desc"
-
-
-class CGEnumerateProperties(CGXrayHelper):
- def __init__(self, descriptor, properties):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
- Argument('JS::AutoIdVector&', 'props')]
- CGXrayHelper.__init__(self, descriptor, "EnumerateProperties", args,
- properties)
-
- def getPrefixArgs(self):
- return "props"
-
-class CGPrototypeTraitsClass(CGClass):
- def __init__(self, descriptor, indent=''):
- templateArgs = [Argument('prototypes::ID', 'PrototypeID')]
- templateSpecialization = ['prototypes::id::' + descriptor.name]
- enums = [ClassEnum('', ['Depth'],
- [descriptor.interface.inheritanceDepth()])]
- typedefs = [ClassTypedef('NativeType', descriptor.nativeType)]
- CGClass.__init__(self, 'PrototypeTraits', indent=indent,
- templateArgs=templateArgs,
- templateSpecialization=templateSpecialization,
- enums=enums, typedefs=typedefs, isStruct=True)
-
-class CGPrototypeIDMapClass(CGClass):
- def __init__(self, descriptor, indent=''):
- templateArgs = [Argument('class', 'ConcreteClass')]
- templateSpecialization = [descriptor.nativeType]
- enums = [ClassEnum('', ['PrototypeID'],
- ['prototypes::id::' + descriptor.name])]
- CGClass.__init__(self, 'PrototypeIDMap', indent=indent,
- templateArgs=templateArgs,
- templateSpecialization=templateSpecialization,
- enums=enums, isStruct=True)
-
-class CGClassForwardDeclare(CGThing):
- def __init__(self, name, isStruct=False):
- CGThing.__init__(self)
- self.name = name
- self.isStruct = isStruct
- def declare(self):
- type = 'struct' if self.isStruct else 'class'
- return '%s %s;\n' % (type, self.name)
- def define(self):
- # Header only
- return ''
-
-class CGProxySpecialOperation(CGPerSignatureCall):
- """
- Base class for classes for calling an indexed or named special operation
- (don't use this directly, use the derived classes below).
- """
- def __init__(self, descriptor, operation):
- nativeName = MakeNativeName(descriptor.binaryNames.get(operation, operation))
- operation = descriptor.operations[operation]
- assert len(operation.signatures()) == 1
- signature = operation.signatures()[0]
- extendedAttributes = descriptor.getExtendedAttributes(operation)
-
- (returnType, arguments) = signature
-
- # We pass len(arguments) as the final argument so that the
- # CGPerSignatureCall won't do any argument conversion of its own.
- CGPerSignatureCall.__init__(self, returnType, "", arguments, nativeName,
- False, descriptor, operation,
- len(arguments))
-
- if operation.isSetter() or operation.isCreator():
- # arguments[0] is the index or name of the item that we're setting.
- argument = arguments[1]
- template = getJSToNativeConversionTemplate(argument.type, descriptor,
- treatNullAs=argument.treatNullAs,
- treatUndefinedAs=argument.treatUndefinedAs)
- templateValues = {
- "declName": argument.identifier.name,
- "holderName": argument.identifier.name + "_holder",
- "val": "desc->value",
- "valPtr": "&desc->value"
- }
- self.cgRoot.prepend(instantiateJSToNativeConversionTemplate(template, templateValues))
- elif operation.isGetter():
- self.cgRoot.prepend(CGGeneric("bool found;"))
-
- def getArguments(self):
- args = [(a, a.identifier.name) for a in self.arguments]
- if self.idlNode.isGetter():
- args.append((FakeArgument(BuiltinTypes[IDLBuiltinType.Types.boolean],
- self.idlNode),
- "found"))
- return args
-
- def wrap_return_value(self):
- if not self.idlNode.isGetter() or self.templateValues is None:
- return ""
-
- wrap = CGGeneric(wrapForType(self.returnType, self.descriptor, self.templateValues))
- wrap = CGIfWrapper(wrap, "found")
- return "\n" + wrap.define()
-
-class CGProxyIndexedGetter(CGProxySpecialOperation):
- """
- Class to generate a call to an indexed getter. If templateValues is not None
- the returned value will be wrapped with wrapForType using templateValues.
- """
- def __init__(self, descriptor, templateValues=None):
- self.templateValues = templateValues
- CGProxySpecialOperation.__init__(self, descriptor, 'IndexedGetter')
-
-class CGProxyIndexedSetter(CGProxySpecialOperation):
- """
- Class to generate a call to an indexed setter.
- """
- def __init__(self, descriptor):
- CGProxySpecialOperation.__init__(self, descriptor, 'IndexedSetter')
-
-class CGProxyNamedGetter(CGProxySpecialOperation):
- """
- Class to generate a call to an named getter. If templateValues is not None
- the returned value will be wrapped with wrapForType using templateValues.
- """
- def __init__(self, descriptor, templateValues=None):
- self.templateValues = templateValues
- CGProxySpecialOperation.__init__(self, descriptor, 'NamedGetter')
-
-class CGProxyNamedSetter(CGProxySpecialOperation):
- """
- Class to generate a call to a named setter.
- """
- def __init__(self, descriptor):
- CGProxySpecialOperation.__init__(self, descriptor, 'NamedSetter')
-
-class CGProxyIsProxy(CGAbstractMethod):
- def __init__(self, descriptor):
- args = [Argument('JSObject*', 'obj')]
- CGAbstractMethod.__init__(self, descriptor, "IsProxy", "bool", args, alwaysInline=True)
- def declare(self):
- return ""
- def definition_body(self):
- return " return js::IsProxy(obj) && js::GetProxyHandler(obj) == DOMProxyHandler::getInstance();"
-
-class CGProxyUnwrap(CGAbstractMethod):
- def __init__(self, descriptor):
- args = [Argument('JSObject*', 'obj')]
- CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", descriptor.nativeType + '*', args, alwaysInline=True)
- def declare(self):
- return ""
- def definition_body(self):
- return """ if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
- obj = js::UnwrapObject(obj);
- }
- MOZ_ASSERT(IsProxy(obj));
- return static_cast<%s*>(js::GetProxyPrivate(obj).toPrivate());""" % (self.descriptor.nativeType)
-
-class CGDOMJSProxyHandlerDOMClass(CGThing):
- def __init__(self, descriptor):
- CGThing.__init__(self)
- self.descriptor = descriptor
- def declare(self):
- return "extern const DOMClass Class;\n"
- def define(self):
- return """
-const DOMClass Class = """ + DOMClass(self.descriptor) + """;
-
-"""
-
-class CGDOMJSProxyHandler_CGDOMJSProxyHandler(ClassConstructor):
- def __init__(self):
- ClassConstructor.__init__(self, [], inline=True, visibility="private",
- baseConstructors=["mozilla::dom::DOMProxyHandler(Class)"],
- body="")
-
-class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'proxy'),
- Argument('jsid', 'id'), Argument('bool', 'set'),
- Argument('JSPropertyDescriptor*', 'desc')]
- ClassMethod.__init__(self, "getOwnPropertyDescriptor", "bool", args)
- self.descriptor = descriptor
- def getBody(self):
- indexedGetter = self.descriptor.operations['IndexedGetter']
- indexedSetter = self.descriptor.operations['IndexedSetter']
-
- setOrIndexedGet = ""
- if indexedGetter or indexedSetter:
- setOrIndexedGet += "int32_t index = GetArrayIndexFromId(cx, id);\n"
-
- if indexedGetter:
- readonly = toStringBool(self.descriptor.operations['IndexedSetter'] is None)
- fillDescriptor = "FillPropertyDescriptor(desc, proxy, %s);\nreturn true;" % readonly
- templateValues = {'jsvalRef': 'desc->value', 'jsvalPtr': '&desc->value',
- 'obj': 'proxy', 'successCode': fillDescriptor}
- get = ("if (index >= 0) {\n" +
- " %s* self = UnwrapProxy(proxy);\n" +
- CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define() + "\n" +
- "}\n") % (self.descriptor.nativeType)
-
- if indexedSetter or self.descriptor.operations['NamedSetter']:
- setOrIndexedGet += "if (set) {\n"
- if indexedSetter:
- setOrIndexedGet += (" if (index >= 0) {\n")
- if not 'IndexedCreator' in self.descriptor.operations:
- # FIXME need to check that this is a 'supported property index'
- assert False
- setOrIndexedGet += (" FillPropertyDescriptor(desc, proxy, JSVAL_VOID, false);\n" +
- " return true;\n" +
- " }\n")
- if self.descriptor.operations['NamedSetter']:
- setOrIndexedGet += " if (JSID_IS_STRING(id)) {\n"
- if not 'NamedCreator' in self.descriptor.operations:
- # FIXME need to check that this is a 'supported property name'
- assert False
- setOrIndexedGet += (" FillPropertyDescriptor(desc, proxy, JSVAL_VOID, false);\n" +
- " return true;\n" +
- " }\n")
- setOrIndexedGet += "}"
- if indexedGetter:
- setOrIndexedGet += (" else {\n" +
- CGIndenter(CGGeneric(get)).define() +
- "}")
- setOrIndexedGet += "\n\n"
- elif indexedGetter:
- setOrIndexedGet += ("if (!set) {\n" +
- CGIndenter(CGGeneric(get)).define() +
- "}\n\n")
-
- namedGetter = self.descriptor.operations['NamedGetter']
- if namedGetter:
- readonly = toStringBool(self.descriptor.operations['NamedSetter'] is None)
- fillDescriptor = "FillPropertyDescriptor(desc, proxy, %s);\nreturn true;" % readonly
- templateValues = {'jsvalRef': 'desc->value', 'jsvalPtr': '&desc->value',
- 'obj': 'proxy', 'successCode': fillDescriptor}
- # Once we start supporting OverrideBuiltins we need to make
- # ResolveOwnProperty or EnumerateOwnProperties filter out named
- # properties that shadow prototype properties.
- namedGet = ("\n" +
- "if (!set && JSID_IS_STRING(id) && !HasPropertyOnPrototype(cx, proxy, this, id)) {\n" +
- " JS::Value nameVal = STRING_TO_JSVAL(JSID_TO_STRING(id));\n" +
- " FakeDependentString name;\n"
- " if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
- " eStringify, eStringify, name)) {\n" +
- " return false;\n" +
- " }\n" +
- "\n" +
- " %s* self = UnwrapProxy(proxy);\n" +
- CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" +
- "}\n") % (self.descriptor.nativeType)
- else:
- namedGet = ""
-
- return setOrIndexedGet + """JSObject* expando;
-if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = GetExpandoObject(proxy))) {
- unsigned flags = (set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED;
- if (!JS_GetPropertyDescriptorById(cx, expando, id, flags, desc)) {
- return false;
- }
- if (desc->obj) {
- // Pretend the property lives on the wrapper.
- desc->obj = proxy;
- return true;
- }
-}
-""" + namedGet + """
-desc->obj = NULL;
-return true;"""
-
-class CGDOMJSProxyHandler_defineProperty(ClassMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'proxy'),
- Argument('jsid', 'id'),
- Argument('JSPropertyDescriptor*', 'desc')]
- ClassMethod.__init__(self, "defineProperty", "bool", args)
- self.descriptor = descriptor
- def getBody(self):
- set = ""
-
- indexedSetter = self.descriptor.operations['IndexedSetter']
- if indexedSetter:
- if not (self.descriptor.operations['IndexedCreator'] is indexedSetter):
- raise TypeError("Can't handle creator that's different from the setter")
- set += ("int32_t index = GetArrayIndexFromId(cx, id);\n" +
- "if (index >= 0) {\n" +
- " %s* self = UnwrapProxy(proxy);\n" +
- CGIndenter(CGProxyIndexedSetter(self.descriptor)).define() +
- " return true;\n" +
- "}\n") % (self.descriptor.nativeType)
- elif self.descriptor.operations['IndexedGetter']:
- set += ("if (GetArrayIndexFromId(cx, id) >= 0) {\n" +
- " return ThrowErrorMessage(cx, MSG_NO_PROPERTY_SETTER, \"%s\");\n" +
- "}\n") % self.descriptor.name
-
- namedSetter = self.descriptor.operations['NamedSetter']
- if namedSetter:
- if not self.descriptor.operations['NamedCreator'] is namedSetter:
- raise TypeError("Can't handle creator that's different from the setter")
- set += ("if (JSID_IS_STRING(id)) {\n" +
- " JS::Value nameVal = STRING_TO_JSVAL(JSID_TO_STRING(id));\n" +
- " FakeDependentString name;\n"
- " if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
- " eStringify, eStringify, name)) {\n" +
- " return false;\n" +
- " }\n" +
- "\n" +
- " %s* self = UnwrapProxy(proxy);\n" +
- CGIndenter(CGProxyNamedSetter(self.descriptor)).define() + "\n" +
- "}\n") % (self.descriptor.nativeType)
- elif self.descriptor.operations['NamedGetter']:
- set += ("if (JSID_IS_STRING(id)) {\n" +
- " JS::Value nameVal = STRING_TO_JSVAL(JSID_TO_STRING(id));\n" +
- " FakeDependentString name;\n"
- " if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
- " eStringify, eStringify, name)) {\n" +
- " return false;\n" +
- " }\n" +
- " %s* self = UnwrapProxy(proxy);\n" +
- CGIndenter(CGProxyNamedGetter(self.descriptor)).define() +
- " if (found) {\n"
- " return ThrowErrorMessage(cx, MSG_NO_PROPERTY_SETTER, \"%s\");\n" +
- " }\n" +
- " return true;\n"
- "}\n") % (self.descriptor.nativeType, self.descriptor.name)
- return set + """return mozilla::dom::DOMProxyHandler::defineProperty(%s);""" % ", ".join(a.name for a in self.args)
-
-class CGDOMJSProxyHandler_getOwnPropertyNames(ClassMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'proxy'),
- Argument('JS::AutoIdVector&', 'props')]
- ClassMethod.__init__(self, "getOwnPropertyNames", "bool", args)
- self.descriptor = descriptor
- def getBody(self):
- indexedGetter = self.descriptor.operations['IndexedGetter']
- if indexedGetter:
- addIndices = """uint32_t length = UnwrapProxy(proxy)->Length();
-MOZ_ASSERT(int32_t(length) >= 0);
-for (int32_t i = 0; i < int32_t(length); ++i) {
- if (!props.append(INT_TO_JSID(i))) {
- return false;
- }
-}
-
-"""
- else:
- addIndices = ""
-
- return addIndices + """JSObject* expando;
-if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
- !js::GetPropertyNames(cx, expando, JSITER_OWNONLY | JSITER_HIDDEN, &props)) {
- return false;
-}
-
-// FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=772869 Add named items
-return true;"""
-
-class CGDOMJSProxyHandler_hasOwn(ClassMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'proxy'),
- Argument('jsid', 'id'), Argument('bool*', 'bp')]
- ClassMethod.__init__(self, "hasOwn", "bool", args)
- self.descriptor = descriptor
- def getBody(self):
- indexedGetter = self.descriptor.operations['IndexedGetter']
- if indexedGetter:
- indexed = ("int32_t index = GetArrayIndexFromId(cx, id);\n" +
- "if (index >= 0) {\n" +
- " %s* self = UnwrapProxy(proxy);\n" +
- CGIndenter(CGProxyIndexedGetter(self.descriptor)).define() + "\n" +
- " *bp = found;\n" +
- " return true;\n" +
- "}\n\n") % (self.descriptor.nativeType)
- else:
- indexed = ""
-
- namedGetter = self.descriptor.operations['NamedGetter']
- if namedGetter:
- named = ("if (JSID_IS_STRING(id) && !HasPropertyOnPrototype(cx, proxy, this, id)) {\n" +
- " jsval nameVal = STRING_TO_JSVAL(JSID_TO_STRING(id));\n" +
- " FakeDependentString name;\n"
- " if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
- " eStringify, eStringify, name)) {\n" +
- " return false;\n" +
- " }\n" +
- "\n" +
- " %s* self = UnwrapProxy(proxy);\n" +
- CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" +
- " *bp = found;\n"
- " return true;\n"
- "}\n" +
- "\n") % (self.descriptor.nativeType)
- else:
- named = ""
-
- return indexed + """JSObject* expando = GetExpandoObject(proxy);
-if (expando) {
- JSBool b = true;
- JSBool ok = JS_HasPropertyById(cx, expando, id, &b);
- *bp = !!b;
- if (!ok || *bp) {
- return ok;
- }
-}
-
-""" + named + """*bp = false;
-return true;"""
-
-class CGDOMJSProxyHandler_get(ClassMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'proxy'),
- Argument('JSObject*', 'receiver'), Argument('jsid', 'id'),
- Argument('JS::Value*', 'vp')]
- ClassMethod.__init__(self, "get", "bool", args)
- self.descriptor = descriptor
- def getBody(self):
- getFromExpando = """JSObject* expando = DOMProxyHandler::GetExpandoObject(proxy);
-if (expando) {
- JSBool hasProp;
- if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
- return false;
- }
-
- if (hasProp) {
- return JS_GetPropertyById(cx, expando, id, vp);
- }
-}"""
-
- templateValues = {'jsvalRef': '*vp', 'jsvalPtr': 'vp', 'obj': 'proxy'}
-
- indexedGetter = self.descriptor.operations['IndexedGetter']
- if indexedGetter:
- getIndexedOrExpando = ("int32_t index = GetArrayIndexFromId(cx, id);\n" +
- "if (index >= 0) {\n" +
- " %s* self = UnwrapProxy(proxy);\n" +
- CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define()) % (self.descriptor.nativeType)
- getIndexedOrExpando += """
- // Even if we don't have this index, we don't forward the
- // get on to our expando object.
-} else {
- %s
-}
-""" % (stripTrailingWhitespace(getFromExpando.replace('\n', '\n ')))
- else:
- getIndexedOrExpando = getFromExpando + "\n"
-
- namedGetter = self.descriptor.operations['NamedGetter']
- if namedGetter:
- getNamed = ("if (JSID_IS_STRING(id)) {\n" +
- " JS::Value nameVal = STRING_TO_JSVAL(JSID_TO_STRING(id));\n" +
- " FakeDependentString name;\n"
- " if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
- " eStringify, eStringify, name)) {\n" +
- " return false;\n" +
- " }\n" +
- "\n" +
- " %s* self = UnwrapProxy(proxy);\n" +
- CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
- "}\n") % (self.descriptor.nativeType)
- else:
- getNamed = ""
-
- return """MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
- "Should not have a XrayWrapper here");
-
-%s
-bool found;
-if (!GetPropertyOnPrototype(cx, proxy, id, &found, vp)) {
- return false;
-}
-
-if (found) {
- return true;
-}
-%s
-vp->setUndefined();
-return true;""" % (getIndexedOrExpando, getNamed)
-
-class CGDOMJSProxyHandler_obj_toString(ClassMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'proxy')]
- ClassMethod.__init__(self, "obj_toString", "JSString*", args)
- self.descriptor = descriptor
- def getBody(self):
- stringifier = self.descriptor.operations['Stringifier']
- if stringifier:
- name = stringifier.identifier.name
- nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
- signature = stringifier.signatures()[0]
- returnType = signature[0]
- extendedAttributes = self.descriptor.getExtendedAttributes(stringifier)
- infallible = 'infallible' in extendedAttributes
- if not infallible:
- error = CGGeneric(
- ('ThrowMethodFailedWithDetails(cx, rv, "%s", "toString");\n' +
- "return NULL;") % self.descriptor.interface.identifier.name)
- else:
- error = None
- call = CGCallGenerator(error, [], "", returnType, extendedAttributes, self.descriptor, nativeName, False, object="UnwrapProxy(proxy)")
- return call.define() + """
-
-JSString* jsresult;
-return xpc_qsStringToJsstring(cx, result, &jsresult) ? jsresult : NULL;"""
-
- return "return mozilla::dom::DOMProxyHandler::obj_toString(cx, \"%s\");" % self.descriptor.name
-
-class CGDOMJSProxyHandler_finalize(ClassMethod):
- def __init__(self, descriptor):
- args = [Argument('JSFreeOp*', 'fop'), Argument('JSObject*', 'proxy')]
- ClassMethod.__init__(self, "finalize", "void", args)
- self.descriptor = descriptor
- def getBody(self):
- return ("%s self = UnwrapProxy(proxy);\n\n" % (self.descriptor.nativeType + "*") +
- finalizeHook(self.descriptor, FINALIZE_HOOK_NAME, self.args[0].name))
-
-class CGDOMJSProxyHandler_getElementIfPresent(ClassMethod):
- def __init__(self, descriptor):
- args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'proxy'),
- Argument('JSObject*', 'receiver'),
- Argument('uint32_t', 'index'),
- Argument('JS::Value*', 'vp'), Argument('bool*', 'present')]
- ClassMethod.__init__(self, "getElementIfPresent", "bool", args)
- self.descriptor = descriptor
- def getBody(self):
- indexedGetter = self.descriptor.operations['IndexedGetter']
- if indexedGetter:
- successCode = """*present = found;
-return true;"""
- templateValues = {'jsvalRef': '*vp', 'jsvalPtr': 'vp',
- 'obj': 'proxy', 'successCode': successCode}
- get = ("%s* self = UnwrapProxy(proxy);\n" +
- CGProxyIndexedGetter(self.descriptor, templateValues).define() + "\n"
- "// We skip the expando object if there is an indexed getter.\n" +
- "\n") % (self.descriptor.nativeType)
- else:
- get = """
-
-JSObject* expando = GetExpandoObject(proxy);
-if (expando) {
- JSBool isPresent;
- if (!JS_GetElementIfPresent(cx, expando, index, expando, vp, &isPresent)) {
- return false;
- }
- if (isPresent) {
- *present = true;
- return true;
- }
-}
-"""
-
- return """MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
- "Should not have a XrayWrapper here");
-
-""" + get + """
-// No need to worry about name getters here, so just check the proto.
-
-JSObject *proto;
-if (!js::GetObjectProto(cx, proxy, &proto)) {
- return false;
-}
-if (proto) {
- JSBool isPresent;
- if (!JS_GetElementIfPresent(cx, proto, index, proxy, vp, &isPresent)) {
- return false;
- }
- *present = isPresent;
- return true;
-}
-
-*present = false;
-// Can't Debug_SetValueRangeToCrashOnTouch because it's not public
-return true;"""
-
-class CGDOMJSProxyHandler_getInstance(ClassMethod):
- def __init__(self):
- ClassMethod.__init__(self, "getInstance", "DOMProxyHandler*", [], static=True)
- def getBody(self):
- return """static DOMProxyHandler instance;
-return &instance;"""
-
-class CGDOMJSProxyHandler(CGClass):
- def __init__(self, descriptor):
- constructors = [CGDOMJSProxyHandler_CGDOMJSProxyHandler()]
- methods = [CGDOMJSProxyHandler_getOwnPropertyDescriptor(descriptor)]
- if descriptor.operations['IndexedSetter'] or descriptor.operations['NamedSetter']:
- methods.append(CGDOMJSProxyHandler_defineProperty(descriptor))
- methods.extend([CGDOMJSProxyHandler_getOwnPropertyNames(descriptor),
- CGDOMJSProxyHandler_hasOwn(descriptor),
- CGDOMJSProxyHandler_get(descriptor),
- CGDOMJSProxyHandler_obj_toString(descriptor),
- CGDOMJSProxyHandler_finalize(descriptor),
- CGDOMJSProxyHandler_getElementIfPresent(descriptor),
- CGDOMJSProxyHandler_getInstance()])
- CGClass.__init__(self, 'DOMProxyHandler',
- bases=[ClassBase('mozilla::dom::DOMProxyHandler')],
- constructors=constructors,
- methods=methods)
-
-def stripTrailingWhitespace(text):
- tail = '\n' if text.endswith('\n') else ''
- lines = text.splitlines()
- for i in range(len(lines)):
- lines[i] = lines[i].rstrip()
- return '\n'.join(lines) + tail
-
-class CGDescriptor(CGThing):
- def __init__(self, descriptor):
- CGThing.__init__(self)
-
- assert not descriptor.concrete or descriptor.interface.hasInterfacePrototypeObject()
-
- cgThings = []
- if descriptor.interface.hasInterfacePrototypeObject():
- (hasMethod, hasGetter, hasLenientGetter,
- hasSetter, hasLenientSetter) = False, False, False, False, False
- for m in descriptor.interface.members:
- if m.isMethod() and not m.isStatic() and not m.isIdentifierLess():
- cgThings.append(CGSpecializedMethod(descriptor, m))
- cgThings.append(CGMemberJITInfo(descriptor, m))
- hasMethod = True
- elif m.isAttr():
- cgThings.append(CGSpecializedGetter(descriptor, m))
- if m.hasLenientThis():
- hasLenientGetter = True
- else:
- hasGetter = True
- if not m.readonly:
- cgThings.append(CGSpecializedSetter(descriptor, m))
- if m.hasLenientThis():
- hasLenientSetter = True
- else:
- hasSetter = True
- cgThings.append(CGMemberJITInfo(descriptor, m))
- if hasMethod: cgThings.append(CGGenericMethod(descriptor))
- if hasGetter: cgThings.append(CGGenericGetter(descriptor))
- if hasLenientGetter: cgThings.append(CGGenericGetter(descriptor,
- lenientThis=True))
- if hasSetter: cgThings.append(CGGenericSetter(descriptor))
- if hasLenientSetter: cgThings.append(CGGenericSetter(descriptor,
- lenientThis=True))
-
- if descriptor.concrete and not descriptor.proxy:
- if not descriptor.workers and descriptor.wrapperCache:
- cgThings.append(CGAddPropertyHook(descriptor))
-
- # Always have a finalize hook, regardless of whether the class wants a
- # custom hook.
- cgThings.append(CGClassFinalizeHook(descriptor))
-
- # Only generate a trace hook if the class wants a custom hook.
- if (descriptor.customTrace):
- cgThings.append(CGClassTraceHook(descriptor))
-
- if descriptor.interface.hasInterfaceObject():
- cgThings.append(CGClassConstructHook(descriptor))
- cgThings.append(CGClassHasInstanceHook(descriptor))
- cgThings.append(CGInterfaceObjectJSClass(descriptor))
-
- if descriptor.interface.hasInterfacePrototypeObject():
- cgThings.append(CGPrototypeJSClass(descriptor))
-
- properties = PropertyArrays(descriptor)
- cgThings.append(CGGeneric(define=str(properties)))
- cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
- if descriptor.interface.hasInterfacePrototypeObject():
- cgThings.append(CGGetProtoObjectMethod(descriptor))
- else:
- cgThings.append(CGGetConstructorObjectMethod(descriptor))
-
- # Set up our Xray callbacks as needed. Note that we don't need to do
- # it in workers.
- if (descriptor.interface.hasInterfacePrototypeObject() and
- not descriptor.workers):
- if descriptor.concrete and descriptor.proxy:
- cgThings.append(CGResolveOwnProperty(descriptor))
- cgThings.append(CGEnumerateOwnProperties(descriptor))
- cgThings.append(CGResolveProperty(descriptor, properties))
- cgThings.append(CGEnumerateProperties(descriptor, properties))
-
- if descriptor.interface.hasInterfaceObject():
- cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
- if (not descriptor.interface.isExternal() and
- # Workers stuff is never pref-controlled
- not descriptor.workers and
- descriptor.interface.getExtendedAttribute("PrefControlled") is not None):
- cgThings.append(CGPrefEnabled(descriptor))
-
- if descriptor.interface.hasInterfacePrototypeObject():
- cgThings.append(CGNativePropertyHooks(descriptor))
-
- if descriptor.concrete:
- if descriptor.proxy:
- cgThings.append(CGProxyIsProxy(descriptor))
- cgThings.append(CGProxyUnwrap(descriptor))
- cgThings.append(CGDOMJSProxyHandlerDOMClass(descriptor))
- cgThings.append(CGDOMJSProxyHandler(descriptor))
- cgThings.append(CGIsMethod(descriptor))
- else:
- cgThings.append(CGDOMJSClass(descriptor))
-
- if descriptor.wrapperCache:
- cgThings.append(CGWrapWithCacheMethod(descriptor))
- cgThings.append(CGWrapMethod(descriptor))
- else:
- cgThings.append(CGWrapNonWrapperCacheMethod(descriptor))
-
- cgThings = CGList((CGIndenter(t, declareOnly=True) for t in cgThings), "\n")
- cgThings = CGWrapper(cgThings, pre='\n', post='\n')
- self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
- cgThings),
- post='\n')
-
- def declare(self):
- return self.cgRoot.declare()
- def define(self):
- return self.cgRoot.define()
-
-class CGNamespacedEnum(CGThing):
- def __init__(self, namespace, enumName, names, values, comment=""):
-
- if not values:
- values = []
-
- # Account for explicit enum values.
- entries = []
- for i in range(0, len(names)):
- if len(values) > i and values[i] is not None:
- entry = "%s = %s" % (names[i], values[i])
- else:
- entry = names[i]
- entries.append(entry)
-
- # Append a Count.
- entries.append('_' + enumName + '_Count')
-
- # Indent.
- entries = [' ' + e for e in entries]
-
- # Build the enum body.
- enumstr = comment + 'enum %s\n{\n%s\n};\n' % (enumName, ',\n'.join(entries))
- curr = CGGeneric(declare=enumstr)
-
- # Add some whitespace padding.
- curr = CGWrapper(curr, pre='\n',post='\n')
-
- # Add the namespace.
- curr = CGNamespace(namespace, curr)
-
- # Add the typedef
- typedef = '\ntypedef %s::%s %s;\n\n' % (namespace, enumName, enumName)
- curr = CGList([curr, CGGeneric(declare=typedef)])
-
- # Save the result.
- self.node = curr
-
- def declare(self):
- return self.node.declare()
- def define(self):
- assert False # Only for headers.
-
-class CGDictionary(CGThing):
- def __init__(self, dictionary, descriptorProvider):
- self.dictionary = dictionary;
- self.workers = descriptorProvider.workers
- if all(CGDictionary(d, descriptorProvider).generatable for
- d in CGDictionary.getDictionaryDependencies(dictionary)):
- self.generatable = True
- else:
- self.generatable = False
- # Nothing else to do here
- return
- # Getting a conversion template for interface types can fail
- # if we don't have a relevant descriptor when self.workers is True.
- # If that happens, just mark ourselves as not being
- # generatable and move on.
- try:
- self.memberInfo = [
- (member,
- getJSToNativeConversionTemplate(member.type,
- descriptorProvider,
- isMember=True,
- isOptional=(not member.defaultValue),
- defaultValue=member.defaultValue))
- for member in dictionary.members ]
- except NoSuchDescriptorError, err:
- if not self.workers:
- raise err
- self.generatable = False
-
- def declare(self):
- if not self.generatable:
- return ""
- d = self.dictionary
- if d.parent:
- inheritance = ": public %s " % self.makeClassName(d.parent)
- else:
- inheritance = ""
- memberDecls = [" %s %s;" %
- (self.getMemberType(m), m[0].identifier.name)
- for m in self.memberInfo]
-
- return (string.Template(
- "struct ${selfName} ${inheritance}{\n"
- " ${selfName}() {}\n"
- " bool Init(JSContext* cx, const JS::Value& val);\n"
- "\n" +
- "\n".join(memberDecls) + "\n"
- "private:\n"
- " // Disallow copy-construction\n"
- " ${selfName}(const ${selfName}&) MOZ_DELETE;\n" +
- # NOTE: jsids are per-runtime, so don't use them in workers
- (" static bool InitIds(JSContext* cx);\n"
- " static bool initedIds;\n" if not self.workers else "") +
- "\n".join(" static jsid " +
- self.makeIdName(m.identifier.name) + ";" for
- m in d.members) + "\n"
- "};").substitute( { "selfName": self.makeClassName(d),
- "inheritance": inheritance }))
-
- def define(self):
- if not self.generatable:
- return ""
- d = self.dictionary
- if d.parent:
- initParent = ("// Per spec, we init the parent's members first\n"
- "if (!%s::Init(cx, val)) {\n"
- " return false;\n"
- "}\n" % self.makeClassName(d.parent))
- else:
- initParent = ""
-
- memberInits = [CGIndenter(self.getMemberConversion(m)).define()
- for m in self.memberInfo]
- idinit = [CGGeneric('!InternJSString(cx, %s, "%s")' %
- (m.identifier.name + "_id", m.identifier.name))
- for m in d.members]
- idinit = CGList(idinit, " ||\n")
- idinit = CGWrapper(idinit, pre="if (",
- post=(") {\n"
- " return false;\n"
- "}"),
- reindent=True)
-
- return string.Template(
- # NOTE: jsids are per-runtime, so don't use them in workers
- ("bool ${selfName}::initedIds = false;\n" +
- "\n".join("jsid ${selfName}::%s = JSID_VOID;" %
- self.makeIdName(m.identifier.name)
- for m in d.members) + "\n"
- "\n"
- "bool\n"
- "${selfName}::InitIds(JSContext* cx)\n"
- "{\n"
- " MOZ_ASSERT(!initedIds);\n"
- "${idInit}\n"
- " initedIds = true;\n"
- " return true;\n"
- "}\n"
- "\n" if not self.workers else "") +
- "bool\n"
- "${selfName}::Init(JSContext* cx, const JS::Value& val)\n"
- "{\n" +
- # NOTE: jsids are per-runtime, so don't use them in workers
- (" if (!initedIds && !InitIds(cx)) {\n"
- " return false;\n"
- " }\n" if not self.workers else "") +
- "${initParent}"
- " JSBool found;\n"
- " JS::Value temp;\n"
- " bool isNull = val.isNullOrUndefined();\n"
- " if (!isNull && !val.isObject()) {\n"
- " return Throw<${isMainThread}>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n"
- " }\n"
- "\n"
- "${initMembers}\n"
- " return true;\n"
- "}").substitute({
- "selfName": self.makeClassName(d),
- "initParent": CGIndenter(CGGeneric(initParent)).define(),
- "initMembers": "\n\n".join(memberInits),
- "idInit": CGIndenter(idinit).define(),
- "isMainThread": toStringBool(not self.workers)
- })
-
- @staticmethod
- def makeDictionaryName(dictionary, workers):
- suffix = "Workers" if workers else ""
- return dictionary.identifier.name + suffix
-
- def makeClassName(self, dictionary):
- return self.makeDictionaryName(dictionary, self.workers)
-
- def getMemberType(self, memberInfo):
- (member, (templateBody, declType,
- holderType, dealWithOptional)) = memberInfo
- # We can't handle having a holderType here
- assert holderType is None
- if dealWithOptional:
- declType = CGWrapper(declType, pre="Optional< ", post=" >")
- return declType.define()
-
- def getMemberConversion(self, memberInfo):
- (member, (templateBody, declType,
- holderType, dealWithOptional)) = memberInfo
- replacements = { "val": "temp",
- "valPtr": "&temp",
- # Use this->%s to refer to members, because we don't
- # control the member names and want to make sure we're
- # talking about the member, not some local that
- # shadows the member. Another option would be to move
- # the guts of init to a static method which is passed
- # an explicit reference to our dictionary object, so
- # we couldn't screw this up even if we wanted to....
- "declName": ("(this->%s)" % member.identifier.name),
- # We need a holder name for external interfaces, but
- # it's scoped down to the conversion so we can just use
- # anything we want.
- "holderName": "holder"}
- # We can't handle having a holderType here
- assert holderType is None
- if dealWithOptional:
- replacements["declName"] = "(" + replacements["declName"] + ".Value())"
- if member.defaultValue:
- replacements["haveValue"] = "found"
-
- # NOTE: jsids are per-runtime, so don't use them in workers
- if self.workers:
- propName = member.identifier.name
- propCheck = ('JS_HasProperty(cx, &val.toObject(), "%s", &found)' %
- propName)
- propGet = ('JS_GetProperty(cx, &val.toObject(), "%s", &temp)' %
- propName)
- else:
- propId = self.makeIdName(member.identifier.name);
- propCheck = ("JS_HasPropertyById(cx, &val.toObject(), %s, &found)" %
- propId)
- propGet = ("JS_GetPropertyById(cx, &val.toObject(), %s, &temp)" %
- propId)
-
- conversionReplacements = {
- "prop": "(this->%s)" % member.identifier.name,
- "convert": string.Template(templateBody).substitute(replacements),
- "propCheck": propCheck,
- "propGet": propGet
- }
- conversion = ("if (isNull) {\n"
- " found = false;\n"
- "} else if (!${propCheck}) {\n"
- " return false;\n"
- "}\n")
- if member.defaultValue:
- conversion += (
- "if (found) {\n"
- " if (!${propGet}) {\n"
- " return false;\n"
- " }\n"
- "}\n"
- "${convert}")
- else:
- conversion += (
- "if (found) {\n"
- " ${prop}.Construct();\n"
- " if (!${propGet}) {\n"
- " return false;\n"
- " }\n"
- "${convert}\n"
- "}")
- conversionReplacements["convert"] = CGIndenter(
- CGGeneric(conversionReplacements["convert"])).define()
-
- return CGGeneric(
- string.Template(conversion).substitute(conversionReplacements)
- )
-
- @staticmethod
- def makeIdName(name):
- return name + "_id"
-
- @staticmethod
- def getDictionaryDependencies(dictionary):
- deps = set();
- if dictionary.parent:
- deps.add(dictionary.parent)
- for member in dictionary.members:
- if member.type.isDictionary():
- deps.add(member.type.unroll().inner)
- return deps
-
-
-class CGRegisterProtos(CGAbstractMethod):
- def __init__(self, config):
- CGAbstractMethod.__init__(self, None, 'Register', 'void',
- [Argument('nsScriptNameSpaceManager*', 'aNameSpaceManager')])
- self.config = config
-
- def _defineMacro(self):
- return """
-#define REGISTER_PROTO(_dom_class, _pref_check) \\
- aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Binding::DefineDOMInterface, _pref_check);\n\n"""
- def _undefineMacro(self):
- return "\n#undef REGISTER_PROTO"
- def _registerProtos(self):
- def getPrefCheck(desc):
- if desc.interface.getExtendedAttribute("PrefControlled") is None:
- return "nullptr"
- return "%sBinding::PrefEnabled" % desc.name
- lines = ["REGISTER_PROTO(%s, %s);" % (desc.name, getPrefCheck(desc))
- for desc in self.config.getDescriptors(hasInterfaceObject=True,
- isExternal=False,
- workers=False,
- register=True)]
- return '\n'.join(lines) + '\n'
- def definition_body(self):
- return self._defineMacro() + self._registerProtos() + self._undefineMacro()
-
-class CGBindingRoot(CGThing):
- """
- Root codegen class for binding generation. Instantiate the class, and call
- declare or define to generate header or cpp code (respectively).
- """
- def __init__(self, config, prefix, webIDLFile):
- descriptors = config.getDescriptors(webIDLFile=webIDLFile,
- hasInterfaceOrInterfacePrototypeObject=True)
- dictionaries = config.getDictionaries(webIDLFile)
-
- forwardDeclares = [CGClassForwardDeclare('XPCWrappedNativeScope')]
-
- descriptorsForForwardDeclaration = list(descriptors)
- for dictionary in dictionaries:
- curDict = dictionary
- ifacemembers = []
- while curDict:
- ifacemembers.extend([m.type.unroll().inner for m
- in curDict.members
- if m.type.unroll().isInterface()])
- curDict = curDict.parent
- # Put in all the non-worker descriptors
- descriptorsForForwardDeclaration.extend(
- [config.getDescriptor(iface.identifier.name, False) for
- iface in ifacemembers])
- # And now the worker ones. But these may not exist, so we
- # have to be more careful.
- for iface in ifacemembers:
- try:
- descriptorsForForwardDeclaration.append(
- config.getDescriptor(iface.identifier.name, True))
- except NoSuchDescriptorError:
- # just move along
- pass
-
- for x in descriptorsForForwardDeclaration:
- nativeType = x.nativeType
- components = x.nativeType.split('::')
- className = components[-1]
- # JSObject is a struct, not a class
- declare = CGClassForwardDeclare(className, className is "JSObject")
- if len(components) > 1:
- declare = CGNamespace.build(components[:-1],
- CGWrapper(declare, declarePre='\n',
- declarePost='\n'),
- declareOnly=True)
- forwardDeclares.append(CGWrapper(declare, declarePost='\n'))
-
- forwardDeclares = CGList(forwardDeclares)
-
- descriptorsWithPrototype = filter(lambda d: d.interface.hasInterfacePrototypeObject(),
- descriptors)
- traitsClasses = [CGPrototypeTraitsClass(d) for d in descriptorsWithPrototype]
-
- # We must have a 1:1 mapping here, skip for prototypes that have more
- # than one concrete class implementation.
- traitsClasses.extend([CGPrototypeIDMapClass(d) for d in descriptorsWithPrototype
- if d.uniqueImplementation])
-
- # Wrap all of that in our namespaces.
- if len(traitsClasses) > 0:
- traitsClasses = CGNamespace.build(['mozilla', 'dom'],
- CGWrapper(CGList(traitsClasses),
- declarePre='\n'),
- declareOnly=True)
- traitsClasses = CGWrapper(traitsClasses, declarePost='\n')
- else:
- traitsClasses = None
-
- # Do codegen for all the enums
- def makeEnum(e):
- return CGNamespace.build([e.identifier.name + "Values"],
- CGEnum(e))
- def makeEnumTypedef(e):
- return CGGeneric(declare=("typedef %sValues::valuelist %s;\n" %
- (e.identifier.name, e.identifier.name)))
- cgthings = [ fun(e) for e in config.getEnums(webIDLFile)
- for fun in [makeEnum, makeEnumTypedef] ]
-
- # Do codegen for all the dictionaries. We have to be a bit careful
- # here, because we have to generate these in order from least derived
- # to most derived so that class inheritance works out. We also have to
- # generate members before the dictionary that contains them.
- #
- # XXXbz this will fail if we have two webidl files A and B such that A
- # declares a dictionary which inherits from a dictionary in B and B
- # declares a dictionary (possibly a different one!) that inherits from a
- # dictionary in A. The good news is that I expect this to never happen.
- reSortedDictionaries = []
- dictionaries = set(dictionaries)
- while len(dictionaries) != 0:
- # Find the dictionaries that don't depend on anything else anymore
- # and move them over.
- toMove = [d for d in dictionaries if
- len(CGDictionary.getDictionaryDependencies(d) &
- dictionaries) == 0]
- if len(toMove) == 0:
- raise TypeError("Loop in dictionary dependency graph")
- dictionaries = dictionaries - set(toMove)
- reSortedDictionaries.extend(toMove)
-
- dictionaries = reSortedDictionaries
- cgthings.extend([CGDictionary(d, config.getDescriptorProvider(True))
- for d in dictionaries])
- cgthings.extend([CGDictionary(d, config.getDescriptorProvider(False))
- for d in dictionaries])
-
- # Do codegen for all the descriptors
- cgthings.extend([CGDescriptor(x) for x in descriptors])
-
- # And make sure we have the right number of newlines at the end
- curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
-
- # Wrap all of that in our namespaces.
- curr = CGNamespace.build(['mozilla', 'dom'],
- CGWrapper(curr, pre="\n"))
-
- curr = CGList([forwardDeclares,
- CGWrapper(CGGeneric("using namespace mozilla::dom;"),
- defineOnly=True),
- traitsClasses, curr],
- "\n")
-
- # Add header includes.
- curr = CGHeaders(descriptors,
- dictionaries,
- ['mozilla/dom/BindingUtils.h',
- 'mozilla/dom/DOMJSClass.h',
- 'mozilla/dom/DOMJSProxyHandler.h'],
- ['mozilla/dom/Nullable.h',
- 'PrimitiveConversions.h',
- 'XPCQuickStubs.h',
- 'nsDOMQS.h',
- 'AccessCheck.h',
- 'WorkerPrivate.h',
- 'nsContentUtils.h',
- 'mozilla/Preferences.h',
- # Have to include nsDOMQS.h to get fast arg unwrapping
- # for old-binding things with castability.
- 'nsDOMQS.h'
- ],
- curr)
-
- # Add include guards.
- curr = CGIncludeGuard(prefix, curr)
-
- # Add the auto-generated comment.
- curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
-
- # Store the final result.
- self.root = curr
-
- def declare(self):
- return stripTrailingWhitespace(self.root.declare())
- def define(self):
- return stripTrailingWhitespace(self.root.define())
-
-
-class GlobalGenRoots():
- """
- Roots for global codegen.
-
- To generate code, call the method associated with the target, and then
- call the appropriate define/declare method.
- """
-
- @staticmethod
- def PrototypeList(config):
-
- # Prototype ID enum.
- protos = [d.name for d in config.getDescriptors(hasInterfacePrototypeObject=True)]
- idEnum = CGNamespacedEnum('id', 'ID', protos, [0])
- idEnum = CGList([idEnum])
- idEnum.append(CGGeneric(declare="const unsigned MaxProtoChainLength = " +
- str(config.maxProtoChainLength) + ";\n\n"))
-
- # Wrap all of that in our namespaces.
- idEnum = CGNamespace.build(['mozilla', 'dom', 'prototypes'],
- CGWrapper(idEnum, pre='\n'))
- idEnum = CGWrapper(idEnum, post='\n')
-
- curr = CGList([idEnum])
-
- # Constructor ID enum.
- constructors = [d.name for d in config.getDescriptors(hasInterfaceObject=True,
- hasInterfacePrototypeObject=False)]
- idEnum = CGNamespacedEnum('id', 'ID', constructors, [0])
-
- # Wrap all of that in our namespaces.
- idEnum = CGNamespace.build(['mozilla', 'dom', 'constructors'],
- CGWrapper(idEnum, pre='\n'))
- idEnum = CGWrapper(idEnum, post='\n')
-
- curr.append(idEnum)
-
- traitsDecl = CGGeneric(declare="""
-template <prototypes::ID PrototypeID>
-struct PrototypeTraits;
-
-template <class ConcreteClass>
-struct PrototypeIDMap;
-""")
-
- traitsDecl = CGNamespace.build(['mozilla', 'dom'],
- CGWrapper(traitsDecl, post='\n'))
-
- curr.append(traitsDecl)
-
- # Add include guards.
- curr = CGIncludeGuard('PrototypeList', curr)
-
- # Add the auto-generated comment.
- curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
-
- # Done.
- return curr
-
- @staticmethod
- def RegisterBindings(config):
-
- # TODO - Generate the methods we want
- curr = CGRegisterProtos(config)
-
- # Wrap all of that in our namespaces.
- curr = CGNamespace.build(['mozilla', 'dom'],
- CGWrapper(curr, post='\n'))
- curr = CGWrapper(curr, post='\n')
-
- # Add the includes
- defineIncludes = [CGHeaders.getDeclarationFilename(desc.interface)
- for desc in config.getDescriptors(hasInterfaceObject=True,
- workers=False,
- register=True)]
- defineIncludes.append('nsScriptNameSpaceManager.h')
- curr = CGHeaders([], [], [], defineIncludes, curr)
-
- # Add include guards.
- curr = CGIncludeGuard('RegisterBindings', curr)
-
- # Done.
- return curr
-
- @staticmethod
- def UnionTypes(config):
-
- (includes, declarations, unions) = UnionTypes(config.getDescriptors())
- includes.add("mozilla/dom/BindingUtils.h")
-
- # Wrap all of that in our namespaces.
- curr = CGNamespace.build(['mozilla', 'dom'], unions)
-
- curr = CGWrapper(curr, post='\n')
-
- namespaces = []
- stack = [CGList([])]
- for (clazz, isStruct) in SortedTuples(declarations):
- elements = clazz.split("::")
- clazz = CGClassForwardDeclare(elements.pop(), isStruct=isStruct)
- i = 0
- if len(elements) > 0:
- common = min(len(namespaces), len(elements))
- while i < common and namespaces[i] == elements[i]:
- i += 1
-
- # pop all the namespaces that should be closed
- namespaces = namespaces[:i]
-
- # add all the namespaces that should be opened
- for j, namespace in enumerate(elements[i:]):
- namespaces.append(namespace)
- # every CGNamespace that we add holds a CGList
- list = CGList([])
- # add the new namespace to the list on top of the stack
- stack[i + j].append(CGNamespace(namespace, list))
- # set the top of the namespace stack to the list of the new
- # namespace
- stack[i + j + 1:] = [list]
-
- stack[len(elements)].append(clazz)
-
- curr = CGList([stack[0], curr], "\n")
-
- curr = CGHeaders([], [], includes, [], curr)
-
- # Add include guards.
- curr = CGIncludeGuard('UnionTypes', curr)
-
- # Done.
- return curr
-
- @staticmethod
- def UnionConversions(config):
-
- unions = UnionConversions(config.getDescriptors())
-
- # Wrap all of that in our namespaces.
- curr = CGNamespace.build(['mozilla', 'dom'], unions)
-
- curr = CGWrapper(curr, post='\n')
-
- curr = CGHeaders([], [], ["nsDebug.h", "mozilla/dom/UnionTypes.h", "nsDOMQS.h"], [], curr)
-
- # Add include guards.
- curr = CGIncludeGuard('UnionConversions', curr)
-
- # Done.
- return curr
diff --git a/components/script/dom/bindings/codegen/DOMJSClass.h b/components/script/dom/bindings/codegen/DOMJSClass.h
deleted file mode 100644
index 151960b5901..00000000000
--- a/components/script/dom/bindings/codegen/DOMJSClass.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* 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_DOMJSClass_h
-#define mozilla_dom_DOMJSClass_h
-
-#include "jsapi.h"
-#include "jsfriendapi.h"
-
-#include "mozilla/dom/PrototypeList.h" // auto-generated
-
-// We use slot 0 for holding the raw object. This is safe for both
-// globals and non-globals.
-#define DOM_OBJECT_SLOT 0
-
-// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. We have to
-// start at 1 past JSCLASS_GLOBAL_SLOT_COUNT because XPConnect uses
-// that one.
-#define DOM_PROTOTYPE_SLOT (JSCLASS_GLOBAL_SLOT_COUNT + 1)
-
-// We use these flag bits for the new bindings.
-#define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1
-
-// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
-// LSetDOMProperty. Those constants need to be changed accordingly if this value
-// changes.
-#define DOM_PROTO_INSTANCE_CLASS_SLOT 0
-
-namespace mozilla {
-namespace dom {
-
-typedef bool
-(* ResolveProperty)(JSContext* cx, JSObject* wrapper, jsid id, bool set,
- JSPropertyDescriptor* desc);
-typedef bool
-(* EnumerateProperties)(JSContext* cx, JSObject* wrapper,
- JS::AutoIdVector& props);
-
-struct NativePropertyHooks
-{
- ResolveProperty mResolveOwnProperty;
- ResolveProperty mResolveProperty;
- EnumerateProperties mEnumerateOwnProperties;
- EnumerateProperties mEnumerateProperties;
-
- const NativePropertyHooks *mProtoHooks;
-};
-
-struct DOMClass
-{
- // A list of interfaces that this object implements, in order of decreasing
- // derivedness.
- const prototypes::ID mInterfaceChain[prototypes::id::_ID_Count];
-
- // We store the DOM object in reserved slot with index DOM_OBJECT_SLOT or in
- // the proxy private if we use a proxy object.
- // Sometimes it's an nsISupports and sometimes it's not; this class tells
- // us which it is.
- const bool mDOMObjectIsISupports;
-
- const NativePropertyHooks* mNativeHooks;
-};
-
-// Special JSClass for reflected DOM objects.
-struct DOMJSClass
-{
- // It would be nice to just inherit from JSClass, but that precludes pure
- // compile-time initialization of the form |DOMJSClass = {...};|, since C++
- // only allows brace initialization for aggregate/POD types.
- JSClass mBase;
-
- DOMClass mClass;
-
- static DOMJSClass* FromJSClass(JSClass* base) {
- MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS);
- return reinterpret_cast<DOMJSClass*>(base);
- }
- static const DOMJSClass* FromJSClass(const JSClass* base) {
- MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS);
- return reinterpret_cast<const DOMJSClass*>(base);
- }
-
- static DOMJSClass* FromJSClass(js::Class* base) {
- return FromJSClass(Jsvalify(base));
- }
- static const DOMJSClass* FromJSClass(const js::Class* base) {
- return FromJSClass(Jsvalify(base));
- }
-
- JSClass* ToJSClass() { return &mBase; }
-};
-
-inline bool
-HasProtoOrIfaceArray(JSObject* global)
-{
- MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
- // This can be undefined if we GC while creating the global
- return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined();
-}
-
-inline JSObject**
-GetProtoOrIfaceArray(JSObject* global)
-{
- MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
- return static_cast<JSObject**>(
- js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate());
-}
-
-} // namespace dom
-} // namespace mozilla
-
-#endif /* mozilla_dom_DOMJSClass_h */
diff --git a/components/script/dom/bindings/codegen/DOMJSProxyHandler.cpp b/components/script/dom/bindings/codegen/DOMJSProxyHandler.cpp
deleted file mode 100644
index af45cc6ed1a..00000000000
--- a/components/script/dom/bindings/codegen/DOMJSProxyHandler.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: set ts=2 sw=2 et tw=99 ft=cpp: */
-/* 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/. */
-
-#include "mozilla/Util.h"
-
-#include "DOMJSProxyHandler.h"
-#include "xpcpublic.h"
-#include "xpcprivate.h"
-#include "XPCQuickStubs.h"
-#include "XPCWrapper.h"
-#include "WrapperFactory.h"
-#include "nsDOMClassInfo.h"
-#include "nsGlobalWindow.h"
-#include "nsWrapperCacheInlines.h"
-#include "mozilla/dom/BindingUtils.h"
-
-#include "jsapi.h"
-
-using namespace JS;
-
-namespace mozilla {
-namespace dom {
-
-jsid s_length_id = JSID_VOID;
-
-bool
-DefineStaticJSVals(JSContext* cx)
-{
- JSAutoRequest ar(cx);
-
- return InternJSString(cx, s_length_id, "length");
-}
-
-
-int HandlerFamily;
-
-// Store the information for the specialized ICs.
-struct SetListBaseInformation
-{
- SetListBaseInformation() {
- js::SetListBaseInformation((void*) &HandlerFamily, js::JSSLOT_PROXY_EXTRA + JSPROXYSLOT_EXPANDO);
- }
-};
-
-SetListBaseInformation gSetListBaseInformation;
-
-
-bool
-DefineConstructor(JSContext* cx, JSObject* obj, DefineInterface aDefine, nsresult* aResult)
-{
- bool enabled;
- bool defined = aDefine(cx, obj, &enabled);
- MOZ_ASSERT(!defined || enabled,
- "We defined a constructor but the new bindings are disabled?");
- *aResult = defined ? NS_OK : NS_ERROR_FAILURE;
- return enabled;
-}
-
-// static
-JSObject*
-DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JSObject* obj)
-{
- NS_ASSERTION(IsDOMProxy(obj), "expected a DOM proxy object");
- JSObject* expando = GetExpandoObject(obj);
- if (!expando) {
- expando = JS_NewObjectWithGivenProto(cx, nullptr, nullptr,
- js::GetObjectParent(obj));
- if (!expando) {
- return NULL;
- }
-
- xpc::CompartmentPrivate* priv = xpc::GetCompartmentPrivate(obj);
- if (!priv->RegisterDOMExpandoObject(obj)) {
- return NULL;
- }
-
- nsWrapperCache* cache;
- CallQueryInterface(UnwrapDOMObject<nsISupports>(obj, eProxyDOMObject), &cache);
- cache->SetPreservingWrapper(true);
-
- js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando));
- }
- return expando;
-}
-
-bool
-DOMProxyHandler::getPropertyDescriptor(JSContext* cx, JSObject* proxy, jsid id, bool set,
- JSPropertyDescriptor* desc)
-{
- if (!getOwnPropertyDescriptor(cx, proxy, id, set, desc)) {
- return false;
- }
- if (desc->obj) {
- return true;
- }
-
- JSObject* proto;
- if (!js::GetObjectProto(cx, proxy, &proto)) {
- return false;
- }
- if (!proto) {
- desc->obj = NULL;
- return true;
- }
-
- return JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, desc);
-}
-
-bool
-DOMProxyHandler::defineProperty(JSContext* cx, JSObject* proxy, jsid id,
- JSPropertyDescriptor* desc)
-{
- if ((desc->attrs & JSPROP_GETTER) && desc->setter == JS_StrictPropertyStub) {
- return JS_ReportErrorFlagsAndNumber(cx,
- JSREPORT_WARNING | JSREPORT_STRICT |
- JSREPORT_STRICT_MODE_ERROR,
- js_GetErrorMessage, NULL,
- JSMSG_GETTER_ONLY);
- }
-
- if (xpc::WrapperFactory::IsXrayWrapper(proxy)) {
- return true;
- }
-
- JSObject* expando = EnsureExpandoObject(cx, proxy);
- if (!expando) {
- return false;
- }
-
- return JS_DefinePropertyById(cx, expando, id, desc->value, desc->getter, desc->setter,
- desc->attrs);
-}
-
-bool
-DOMProxyHandler::delete_(JSContext* cx, JSObject* proxy, jsid id, bool* bp)
-{
- JSBool b = true;
-
- JSObject* expando;
- if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = GetExpandoObject(proxy))) {
- Value v;
- if (!JS_DeletePropertyById2(cx, expando, id, &v) || !JS_ValueToBoolean(cx, v, &b)) {
- return false;
- }
- }
-
- *bp = !!b;
- return true;
-}
-
-bool
-DOMProxyHandler::enumerate(JSContext* cx, JSObject* proxy, AutoIdVector& props)
-{
- JSObject* proto;
- if (!JS_GetPrototype(cx, proxy, &proto)) {
- return false;
- }
- return getOwnPropertyNames(cx, proxy, props) &&
- (!proto || js::GetPropertyNames(cx, proto, 0, &props));
-}
-
-bool
-DOMProxyHandler::fix(JSContext* cx, JSObject* proxy, Value* vp)
-{
- vp->setUndefined();
- return true;
-}
-
-bool
-DOMProxyHandler::has(JSContext* cx, JSObject* proxy, jsid id, bool* bp)
-{
- if (!hasOwn(cx, proxy, id, bp)) {
- return false;
- }
-
- if (*bp) {
- // We have the property ourselves; no need to worry about our prototype
- // chain.
- return true;
- }
-
- // OK, now we have to look at the proto
- JSObject *proto;
- if (!js::GetObjectProto(cx, proxy, &proto)) {
- return false;
- }
- if (!proto) {
- return true;
- }
- JSBool protoHasProp;
- bool ok = JS_HasPropertyById(cx, proto, id, &protoHasProp);
- if (ok) {
- *bp = protoHasProp;
- }
- return ok;
-}
-
-// static
-JSString*
-DOMProxyHandler::obj_toString(JSContext* cx, const char* className)
-{
- size_t nchars = sizeof("[object ]") - 1 + strlen(className);
- jschar* chars = static_cast<jschar*>(JS_malloc(cx, (nchars + 1) * sizeof(jschar)));
- if (!chars) {
- return NULL;
- }
-
- const char* prefix = "[object ";
- nchars = 0;
- while ((chars[nchars] = (jschar)*prefix) != 0) {
- nchars++, prefix++;
- }
- while ((chars[nchars] = (jschar)*className) != 0) {
- nchars++, className++;
- }
- chars[nchars++] = ']';
- chars[nchars] = 0;
-
- JSString* str = JS_NewUCString(cx, chars, nchars);
- if (!str) {
- JS_free(cx, chars);
- }
- return str;
-}
-
-int32_t
-IdToInt32(JSContext* cx, jsid id)
-{
- JSAutoRequest ar(cx);
-
- jsval idval;
- double array_index;
- int32_t i;
- if (!::JS_IdToValue(cx, id, &idval) ||
- !::JS_ValueToNumber(cx, idval, &array_index) ||
- !::JS_DoubleIsInt32(array_index, &i)) {
- return -1;
- }
-
- return i;
-}
-
-} // namespace dom
-} // namespace mozilla
diff --git a/components/script/dom/bindings/codegen/DOMJSProxyHandler.h b/components/script/dom/bindings/codegen/DOMJSProxyHandler.h
deleted file mode 100644
index 394e2dc4d2f..00000000000
--- a/components/script/dom/bindings/codegen/DOMJSProxyHandler.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
-/* 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_DOMJSProxyHandler_h
-#define mozilla_dom_DOMJSProxyHandler_h
-
-#include "jsapi.h"
-#include "jsfriendapi.h"
-#include "jsproxy.h"
-#include "xpcpublic.h"
-#include "nsString.h"
-#include "mozilla/Likely.h"
-
-#define DOM_PROXY_OBJECT_SLOT js::JSSLOT_PROXY_PRIVATE
-
-namespace mozilla {
-namespace dom {
-
-enum {
- JSPROXYSLOT_EXPANDO = 0
-};
-
-template<typename T> struct Prefable;
-
-class DOMProxyHandler : public DOMBaseProxyHandler
-{
-public:
- DOMProxyHandler(const DOMClass& aClass)
- : DOMBaseProxyHandler(true),
- mClass(aClass)
- {
- }
-
- bool getPropertyDescriptor(JSContext* cx, JSObject* proxy, jsid id, bool set,
- JSPropertyDescriptor* desc);
- bool defineProperty(JSContext* cx, JSObject* proxy, jsid id,
- JSPropertyDescriptor* desc);
- bool delete_(JSContext* cx, JSObject* proxy, jsid id, bool* bp);
- bool enumerate(JSContext* cx, JSObject* proxy, JS::AutoIdVector& props);
- bool fix(JSContext* cx, JSObject* proxy, JS::Value* vp);
- bool has(JSContext* cx, JSObject* proxy, jsid id, bool* bp);
- using js::BaseProxyHandler::obj_toString;
-
- static JSObject* GetExpandoObject(JSObject* obj)
- {
- MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
- JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
- return v.isUndefined() ? NULL : v.toObjectOrNull();
- }
- static JSObject* EnsureExpandoObject(JSContext* cx, JSObject* obj);
-
- const DOMClass& mClass;
-
-protected:
- static JSString* obj_toString(JSContext* cx, const char* className);
-};
-
-extern jsid s_length_id;
-
-int32_t IdToInt32(JSContext* cx, jsid id);
-
-inline int32_t
-GetArrayIndexFromId(JSContext* cx, jsid id)
-{
- if (MOZ_LIKELY(JSID_IS_INT(id))) {
- return JSID_TO_INT(id);
- }
- if (MOZ_LIKELY(id == s_length_id)) {
- return -1;
- }
- if (MOZ_LIKELY(JSID_IS_ATOM(id))) {
- JSAtom* atom = JSID_TO_ATOM(id);
- jschar s = *js::GetAtomChars(atom);
- if (MOZ_LIKELY((unsigned)s >= 'a' && (unsigned)s <= 'z'))
- return -1;
-
- uint32_t i;
- JSLinearString* str = js::AtomToLinearString(JSID_TO_ATOM(id));
- return js::StringIsArrayIndex(str, &i) ? i : -1;
- }
- return IdToInt32(cx, id);
-}
-
-inline void
-FillPropertyDescriptor(JSPropertyDescriptor* desc, JSObject* obj, bool readonly)
-{
- desc->obj = obj;
- desc->attrs = (readonly ? JSPROP_READONLY : 0) | JSPROP_ENUMERATE;
- desc->getter = NULL;
- desc->setter = NULL;
- desc->shortid = 0;
-}
-
-inline void
-FillPropertyDescriptor(JSPropertyDescriptor* desc, JSObject* obj, jsval v, bool readonly)
-{
- desc->value = v;
- FillPropertyDescriptor(desc, obj, readonly);
-}
-
-JSObject*
-EnsureExpandoObject(JSContext* cx, JSObject* obj);
-
-} // namespace dom
-} // namespace mozilla
-
-#endif /* mozilla_dom_DOMProxyHandler_h */
diff --git a/components/script/dom/bindings/codegen/ErrorResult.h b/components/script/dom/bindings/codegen/ErrorResult.h
deleted file mode 100644
index bbd9404a865..00000000000
--- a/components/script/dom/bindings/codegen/ErrorResult.h
+++ /dev/null
@@ -1,59 +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/. */
-
-/**
- * A struct for tracking exceptions that need to be thrown to JS.
- */
-
-#ifndef mozilla_ErrorResult_h
-#define mozilla_ErrorResult_h
-
-#include "nscore.h"
-#include "mozilla/Assertions.h"
-
-namespace mozilla {
-
-class ErrorResult {
-public:
- ErrorResult() {
- mResult = NS_OK;
- }
-
- void Throw(nsresult rv) {
- MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
- mResult = rv;
- }
-
- // In the future, we can add overloads of Throw that take more
- // interesting things, like strings or DOM exception types or
- // something if desired.
-
- // Backwards-compat to make conversion simpler. We don't call
- // Throw() here because people can easily pass success codes to
- // this.
- void operator=(nsresult rv) {
- mResult = rv;
- }
-
- bool Failed() const {
- return NS_FAILED(mResult);
- }
-
- nsresult ErrorCode() const {
- return mResult;
- }
-
-private:
- nsresult mResult;
-
- // Not to be implemented, to make sure people always pass this by
- // reference, not by value.
- ErrorResult(const ErrorResult&) MOZ_DELETE;
-};
-
-} // namespace mozilla
-
-#endif /* mozilla_ErrorResult_h */
diff --git a/components/script/dom/bindings/codegen/GlobalGen.py b/components/script/dom/bindings/codegen/GlobalGen.py
index cdca464e029..e596ea44f51 100644
--- a/components/script/dom/bindings/codegen/GlobalGen.py
+++ b/components/script/dom/bindings/codegen/GlobalGen.py
@@ -14,8 +14,6 @@ import WebIDL
import cPickle
from Configuration import *
from CodegenRust import GlobalGenRoots, replaceFileIfChanged
-# import Codegen in general, so we can set a variable on it
-import Codegen
def generate_file(config, name, filename):
root = getattr(GlobalGenRoots, name)(config)
diff --git a/components/script/dom/bindings/codegen/Nullable.h b/components/script/dom/bindings/codegen/Nullable.h
deleted file mode 100644
index 8b2cc08642b..00000000000
--- a/components/script/dom/bindings/codegen/Nullable.h
+++ /dev/null
@@ -1,68 +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_Nullable_h
-#define mozilla_dom_Nullable_h
-
-#include "mozilla/Assertions.h"
-
-namespace mozilla {
-namespace dom {
-
-// Support for nullable types
-template <typename T>
-struct Nullable
-{
-private:
- T mValue;
- bool mIsNull;
-
-public:
- Nullable()
- : mIsNull(true)
- {}
-
- Nullable(T aValue)
- : mValue(aValue)
- , mIsNull(false)
- {}
-
- void SetValue(T aValue) {
- mValue = aValue;
- mIsNull = false;
- }
-
- // For cases when |T| is some type with nontrivial copy behavior, we may want
- // to get a reference to our internal copy of T and work with it directly
- // instead of relying on the copying version of SetValue().
- T& SetValue() {
- mIsNull = false;
- return mValue;
- }
-
- void SetNull() {
- mIsNull = true;
- }
-
- const T& Value() const {
- MOZ_ASSERT(!mIsNull);
- return mValue;
- }
-
- T& Value() {
- MOZ_ASSERT(!mIsNull);
- return mValue;
- }
-
- bool IsNull() const {
- return mIsNull;
- }
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif /* mozilla_dom_Nullable_h */
diff --git a/components/script/dom/bindings/codegen/PrimitiveConversions.h b/components/script/dom/bindings/codegen/PrimitiveConversions.h
deleted file mode 100644
index 40c27425772..00000000000
--- a/components/script/dom/bindings/codegen/PrimitiveConversions.h
+++ /dev/null
@@ -1,350 +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/. */
-
-/**
- * Conversions from jsval to primitive values
- */
-
-#ifndef mozilla_dom_PrimitiveConversions_h
-#define mozilla_dom_PrimitiveConversions_h
-
-#include <limits>
-#include <math.h>
-#include "mozilla/Assertions.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/FloatingPoint.h"
-#include "xpcpublic.h"
-
-namespace mozilla {
-namespace dom {
-
-template<typename T>
-struct TypeName {
-};
-
-template<>
-struct TypeName<int8_t> {
- static const char* value() {
- return "byte";
- }
-};
-template<>
-struct TypeName<uint8_t> {
- static const char* value() {
- return "octet";
- }
-};
-template<>
-struct TypeName<int16_t> {
- static const char* value() {
- return "short";
- }
-};
-template<>
-struct TypeName<uint16_t> {
- static const char* value() {
- return "unsigned short";
- }
-};
-template<>
-struct TypeName<int32_t> {
- static const char* value() {
- return "long";
- }
-};
-template<>
-struct TypeName<uint32_t> {
- static const char* value() {
- return "unsigned long";
- }
-};
-template<>
-struct TypeName<int64_t> {
- static const char* value() {
- return "long long";
- }
-};
-template<>
-struct TypeName<uint64_t> {
- static const char* value() {
- return "unsigned long long";
- }
-};
-
-
-enum ConversionBehavior {
- eDefault,
- eEnforceRange,
- eClamp
-};
-
-template<typename T, ConversionBehavior B>
-struct PrimitiveConversionTraits {
-};
-
-template<typename T>
-struct DisallowedConversion {
- typedef int jstype;
- typedef int intermediateType;
-
-private:
- static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
- MOZ_NOT_REACHED("This should never be instantiated!");
- return false;
- }
-};
-
-struct PrimitiveConversionTraits_smallInt {
- // The output of JS::ToInt32 is determined as follows:
- // 1) The value is converted to a double
- // 2) Anything that's not a finite double returns 0
- // 3) The double is rounded towards zero to the nearest integer
- // 4) The resulting integer is reduced mod 2^32. The output of this
- // operation is an integer in the range [0, 2^32).
- // 5) If the resulting number is >= 2^31, 2^32 is subtracted from it.
- //
- // The result of all this is a number in the range [-2^31, 2^31)
- //
- // WebIDL conversions for the 8-bit, 16-bit, and 32-bit integer types
- // are defined in the same way, except that step 4 uses reduction mod
- // 2^8 and 2^16 for the 8-bit and 16-bit types respectively, and step 5
- // is only done for the signed types.
- //
- // C/C++ define integer conversion semantics to unsigned types as taking
- // your input integer mod (1 + largest value representable in the
- // unsigned type). Since 2^32 is zero mod 2^8, 2^16, and 2^32,
- // converting to the unsigned int of the relevant width will correctly
- // perform step 4; in particular, the 2^32 possibly subtracted in step 5
- // will become 0.
- //
- // Once we have step 4 done, we're just going to assume 2s-complement
- // representation and cast directly to the type we really want.
- //
- // So we can cast directly for all unsigned types and for int32_t; for
- // the smaller-width signed types we need to cast through the
- // corresponding unsigned type.
- typedef int32_t jstype;
- typedef int32_t intermediateType;
- static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
- return JS::ToInt32(cx, v, retval);
- }
-};
-template<>
-struct PrimitiveConversionTraits<int8_t, eDefault> : PrimitiveConversionTraits_smallInt {
- typedef uint8_t intermediateType;
-};
-template<>
-struct PrimitiveConversionTraits<uint8_t, eDefault> : PrimitiveConversionTraits_smallInt {
-};
-template<>
-struct PrimitiveConversionTraits<int16_t, eDefault> : PrimitiveConversionTraits_smallInt {
- typedef uint16_t intermediateType;
-};
-template<>
-struct PrimitiveConversionTraits<uint16_t, eDefault> : PrimitiveConversionTraits_smallInt {
-};
-template<>
-struct PrimitiveConversionTraits<int32_t, eDefault> : PrimitiveConversionTraits_smallInt {
-};
-template<>
-struct PrimitiveConversionTraits<uint32_t, eDefault> : PrimitiveConversionTraits_smallInt {
-};
-
-template<>
-struct PrimitiveConversionTraits<int64_t, eDefault> {
- typedef int64_t jstype;
- typedef int64_t intermediateType;
- static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
- return JS::ToInt64(cx, v, retval);
- }
-};
-
-template<>
-struct PrimitiveConversionTraits<uint64_t, eDefault> {
- typedef uint64_t jstype;
- typedef uint64_t intermediateType;
- static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
- return JS::ToUint64(cx, v, retval);
- }
-};
-
-template<typename T>
-struct PrimitiveConversionTraits_Limits {
- static inline T min() {
- return std::numeric_limits<T>::min();
- }
- static inline T max() {
- return std::numeric_limits<T>::max();
- }
-};
-
-template<>
-struct PrimitiveConversionTraits_Limits<int64_t> {
- static inline int64_t min() {
- return -(1LL << 53) + 1;
- }
- static inline int64_t max() {
- return (1LL << 53) - 1;
- }
-};
-
-template<>
-struct PrimitiveConversionTraits_Limits<uint64_t> {
- static inline uint64_t min() {
- return 0;
- }
- static inline uint64_t max() {
- return (1LL << 53) - 1;
- }
-};
-
-template<typename T, bool (*Enforce)(JSContext* cx, const double& d, T* retval)>
-struct PrimitiveConversionTraits_ToCheckedIntHelper {
- typedef T jstype;
- typedef T intermediateType;
-
- static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
- double intermediate;
- if (!JS::ToNumber(cx, v, &intermediate)) {
- return false;
- }
-
- return Enforce(cx, intermediate, retval);
- }
-};
-
-template<typename T>
-inline bool
-PrimitiveConversionTraits_EnforceRange(JSContext* cx, const double& d, T* retval)
-{
- MOZ_STATIC_ASSERT(std::numeric_limits<T>::is_integer,
- "This can only be applied to integers!");
-
- if (!MOZ_DOUBLE_IS_FINITE(d)) {
- return ThrowErrorMessage(cx, MSG_ENFORCE_RANGE_NON_FINITE, TypeName<T>::value());
- }
-
- bool neg = (d < 0);
- double rounded = floor(neg ? -d : d);
- rounded = neg ? -rounded : rounded;
- if (rounded < PrimitiveConversionTraits_Limits<T>::min() ||
- rounded > PrimitiveConversionTraits_Limits<T>::max()) {
- return ThrowErrorMessage(cx, MSG_ENFORCE_RANGE_OUT_OF_RANGE, TypeName<T>::value());
- }
-
- *retval = static_cast<T>(rounded);
- return true;
-}
-
-template<typename T>
-struct PrimitiveConversionTraits<T, eEnforceRange> :
- public PrimitiveConversionTraits_ToCheckedIntHelper<T, PrimitiveConversionTraits_EnforceRange<T> > {
-};
-
-template<typename T>
-inline bool
-PrimitiveConversionTraits_Clamp(JSContext* cx, const double& d, T* retval)
-{
- MOZ_STATIC_ASSERT(std::numeric_limits<T>::is_integer,
- "This can only be applied to integers!");
-
- if (MOZ_DOUBLE_IS_NaN(d)) {
- *retval = 0;
- return true;
- }
- if (d >= PrimitiveConversionTraits_Limits<T>::max()) {
- *retval = PrimitiveConversionTraits_Limits<T>::max();
- return true;
- }
- if (d <= PrimitiveConversionTraits_Limits<T>::min()) {
- *retval = PrimitiveConversionTraits_Limits<T>::min();
- return true;
- }
-
- MOZ_ASSERT(MOZ_DOUBLE_IS_FINITE(d));
-
- // Banker's rounding (round ties towards even).
- // We move away from 0 by 0.5f and then truncate. That gets us the right
- // answer for any starting value except plus or minus N.5. With a starting
- // value of that form, we now have plus or minus N+1. If N is odd, this is
- // the correct result. If N is even, plus or minus N is the correct result.
- double toTruncate = (d < 0) ? d - 0.5 : d + 0.5;
-
- T truncated(toTruncate);
-
- if (truncated == toTruncate) {
- /*
- * It was a tie (since moving away from 0 by 0.5 gave us the exact integer
- * we want). Since we rounded away from 0, we either already have an even
- * number or we have an odd number but the number we want is one closer to
- * 0. So just unconditionally masking out the ones bit should do the trick
- * to get us the value we want.
- */
- truncated &= ~1;
- }
-
- *retval = truncated;
- return true;
-}
-
-template<typename T>
-struct PrimitiveConversionTraits<T, eClamp> :
- public PrimitiveConversionTraits_ToCheckedIntHelper<T, PrimitiveConversionTraits_Clamp<T> > {
-};
-
-
-template<ConversionBehavior B>
-struct PrimitiveConversionTraits<bool, B> : public DisallowedConversion<bool> {};
-
-template<>
-struct PrimitiveConversionTraits<bool, eDefault> {
- typedef JSBool jstype;
- typedef bool intermediateType;
- static inline bool converter(JSContext* /* unused */, JS::Value v, jstype* retval) {
- *retval = JS::ToBoolean(v);
- return true;
- }
-};
-
-
-template<ConversionBehavior B>
-struct PrimitiveConversionTraits<float, B> : public DisallowedConversion<float> {};
-
-template<ConversionBehavior B>
-struct PrimitiveConversionTraits<double, B> : public DisallowedConversion<double> {};
-
-struct PrimitiveConversionTraits_float {
- typedef double jstype;
- typedef double intermediateType;
- static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
- return JS::ToNumber(cx, v, retval);
- }
-};
-
-template<>
-struct PrimitiveConversionTraits<float, eDefault> : PrimitiveConversionTraits_float {
-};
-template<>
-struct PrimitiveConversionTraits<double, eDefault> : PrimitiveConversionTraits_float {
-};
-
-
-template<typename T, ConversionBehavior B>
-bool ValueToPrimitive(JSContext* cx, JS::Value v, T* retval)
-{
- typename PrimitiveConversionTraits<T, B>::jstype t;
- if (!PrimitiveConversionTraits<T, B>::converter(cx, v, &t))
- return false;
-
- *retval =
- static_cast<typename PrimitiveConversionTraits<T, B>::intermediateType>(t);
- return true;
-}
-
-} // namespace dom
-} // namespace mozilla
-
-#endif /* mozilla_dom_PrimitiveConversions_h */
diff --git a/components/script/dom/bindings/codegen/RegisterBindings.h b/components/script/dom/bindings/codegen/RegisterBindings.h
deleted file mode 100644
index 7d83a747cc3..00000000000
--- a/components/script/dom/bindings/codegen/RegisterBindings.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef mozilla_dom_RegisterBindings_h__
-#define mozilla_dom_RegisterBindings_h__
-
-
-namespace mozilla {
-namespace dom {
-void
-Register(nsScriptNameSpaceManager* aNameSpaceManager);
-
-} // namespace dom
-} // namespace mozilla
-
-
-#endif // mozilla_dom_RegisterBindings_h__
diff --git a/components/script/dom/bindings/codegen/TypedArray.h b/components/script/dom/bindings/codegen/TypedArray.h
deleted file mode 100644
index 2a6f17bcb96..00000000000
--- a/components/script/dom/bindings/codegen/TypedArray.h
+++ /dev/null
@@ -1,121 +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_TypedArray_h
-#define mozilla_dom_TypedArray_h
-
-#include "jsfriendapi.h"
-
-namespace mozilla {
-namespace dom {
-
-/*
- * Various typed array classes for argument conversion. We have a base class
- * that has a way of initializing a TypedArray from an existing typed array, and
- * a subclass of the base class that supports creation of a relevant typed array
- * or array buffer object.
- */
-template<typename T,
- JSObject* UnboxArray(JSContext*, JSObject*, uint32_t*, T**)>
-struct TypedArray_base {
- TypedArray_base(JSContext* cx, JSObject* obj)
- {
- mObj = UnboxArray(cx, obj, &mLength, &mData);
- }
-
-private:
- T* mData;
- uint32_t mLength;
- JSObject* mObj;
-
-public:
- inline bool inited() const {
- return !!mObj;
- }
-
- inline T *Data() const {
- MOZ_ASSERT(inited());
- return mData;
- }
-
- inline uint32_t Length() const {
- MOZ_ASSERT(inited());
- return mLength;
- }
-
- inline JSObject *Obj() const {
- MOZ_ASSERT(inited());
- return mObj;
- }
-};
-
-
-template<typename T,
- T* GetData(JSObject*, JSContext*),
- JSObject* UnboxArray(JSContext*, JSObject*, uint32_t*, T**),
- JSObject* CreateNew(JSContext*, uint32_t)>
-struct TypedArray : public TypedArray_base<T,UnboxArray> {
- TypedArray(JSContext* cx, JSObject* obj) :
- TypedArray_base<T,UnboxArray>(cx, obj)
- {}
-
- static inline JSObject*
- Create(JSContext* cx, nsWrapperCache* creator, uint32_t length,
- const T* data = NULL) {
- JSObject* creatorWrapper;
- Maybe<JSAutoCompartment> ac;
- if (creator && (creatorWrapper = creator->GetWrapperPreserveColor())) {
- ac.construct(cx, creatorWrapper);
- }
- JSObject* obj = CreateNew(cx, length);
- if (!obj) {
- return NULL;
- }
- if (data) {
- T* buf = static_cast<T*>(GetData(obj, cx));
- memcpy(buf, data, length*sizeof(T));
- }
- return obj;
- }
-};
-
-typedef TypedArray<int8_t, JS_GetInt8ArrayData, JS_GetObjectAsInt8Array,
- JS_NewInt8Array>
- Int8Array;
-typedef TypedArray<uint8_t, JS_GetUint8ArrayData,
- JS_GetObjectAsUint8Array, JS_NewUint8Array>
- Uint8Array;
-typedef TypedArray<uint8_t, JS_GetUint8ClampedArrayData,
- JS_GetObjectAsUint8ClampedArray, JS_NewUint8ClampedArray>
- Uint8ClampedArray;
-typedef TypedArray<int16_t, JS_GetInt16ArrayData,
- JS_GetObjectAsInt16Array, JS_NewInt16Array>
- Int16Array;
-typedef TypedArray<uint16_t, JS_GetUint16ArrayData,
- JS_GetObjectAsUint16Array, JS_NewUint16Array>
- Uint16Array;
-typedef TypedArray<int32_t, JS_GetInt32ArrayData,
- JS_GetObjectAsInt32Array, JS_NewInt32Array>
- Int32Array;
-typedef TypedArray<uint32_t, JS_GetUint32ArrayData,
- JS_GetObjectAsUint32Array, JS_NewUint32Array>
- Uint32Array;
-typedef TypedArray<float, JS_GetFloat32ArrayData,
- JS_GetObjectAsFloat32Array, JS_NewFloat32Array>
- Float32Array;
-typedef TypedArray<double, JS_GetFloat64ArrayData,
- JS_GetObjectAsFloat64Array, JS_NewFloat64Array>
- Float64Array;
-typedef TypedArray_base<uint8_t, JS_GetObjectAsArrayBufferView>
- ArrayBufferView;
-typedef TypedArray<uint8_t, JS_GetArrayBufferData,
- JS_GetObjectAsArrayBuffer, JS_NewArrayBuffer>
- ArrayBuffer;
-
-} // namespace dom
-} // namespace mozilla
-
-#endif /* mozilla_dom_TypedArray_h */