diff options
author | Jack Moffitt <jack@metajack.im> | 2014-08-28 09:34:23 -0600 |
---|---|---|
committer | Jack Moffitt <jack@metajack.im> | 2014-09-08 20:21:42 -0600 |
commit | c6ab60dbfc6da7b4f800c9e40893c8b58413960c (patch) | |
tree | d1d74076cf7fa20e4f77ec7cb82cae98b67362cb /src/components/script/dom/bindings/codegen | |
parent | db2f642c32fc5bed445bb6f2e45b0f6f0b4342cf (diff) | |
download | servo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.tar.gz servo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.zip |
Cargoify servo
Diffstat (limited to 'src/components/script/dom/bindings/codegen')
103 files changed, 0 insertions, 30131 deletions
diff --git a/src/components/script/dom/bindings/codegen/BindingGen.py b/src/components/script/dom/bindings/codegen/BindingGen.py deleted file mode 100644 index 408280dacfb..00000000000 --- a/src/components/script/dom/bindings/codegen/BindingGen.py +++ /dev/null @@ -1,52 +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/. - -import sys -sys.path.append("./parser/") -sys.path.append("./ply/") -import os -import cPickle -import WebIDL -from Configuration import * -from CodegenRust import CGBindingRoot, replaceFileIfChanged - -def generate_binding_rs(config, outputprefix, webidlfile): - """ - |config| Is the configuration object. - |outputprefix| is a prefix to use for the header guards and filename. - """ - - filename = outputprefix + ".rs" - root = CGBindingRoot(config, outputprefix, webidlfile) - if replaceFileIfChanged(filename, root.define()): - print "Generating binding implementation: %s" % (filename) - -def main(): - # Parse arguments. - from optparse import OptionParser - usagestring = "usage: %prog configFile outputPrefix webIDLFile" - o = OptionParser(usage=usagestring) - o.add_option("--verbose-errors", action='store_true', default=False, - help="When an error happens, display the Python traceback.") - (options, args) = o.parse_args() - - if len(args) != 3: - o.error(usagestring) - configFile = os.path.normpath(args[0]) - outputPrefix = args[1] - webIDLFile = os.path.normpath(args[2]) - - # Load the parsing results - f = open('ParserResults.pkl', 'rb') - parserData = cPickle.load(f) - f.close() - - # Create the configuration data. - config = Configuration(configFile, parserData) - - # Generate the prototype classes. - generate_binding_rs(config, outputPrefix, webIDLFile); - -if __name__ == '__main__': - main() diff --git a/src/components/script/dom/bindings/codegen/BindingUtils.cpp b/src/components/script/dom/bindings/codegen/BindingUtils.cpp deleted file mode 100644 index 27ac92e3596..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/BindingUtils.h b/src/components/script/dom/bindings/codegen/BindingUtils.h deleted file mode 100644 index ee9d6c3691c..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf deleted file mode 100644 index f8119bc71f5..00000000000 --- a/src/components/script/dom/bindings/codegen/Bindings.conf +++ /dev/null @@ -1,28 +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/. - -# DOM Bindings Configuration. -# -# The WebIDL interfaces are defined in dom/webidls. For each such interface, -# there is a corresponding entry in the configuration table below. -# The configuration table maps each interface name to a |descriptor|. -# -# Valid fields for all descriptors: -# * createGlobal: True for global objects. -# * outerObjectHook: string to use in place of default value for outerObject and thisObject -# JS class hooks - -DOMInterfaces = { - -'EventListener': { - 'nativeType': 'EventListenerBinding::EventListener', -}, -'Window': { - 'outerObjectHook': 'Some(bindings::utils::outerize_global)', -}, - -#FIXME(jdm): This should be 'register': False, but then we don't generate enum types -'TestBinding': {}, - -} diff --git a/src/components/script/dom/bindings/codegen/Codegen.py b/src/components/script/dom/bindings/codegen/Codegen.py deleted file mode 100644 index 6d2cc0bde36..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py deleted file mode 100644 index 1666589940e..00000000000 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ /dev/null @@ -1,5534 +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 operator -import os -import re -import string - -from WebIDL import ( - BuiltinTypes, - IDLBuiltinType, - IDLNullValue, - IDLType, - IDLUndefinedValue, -) - -from Configuration import getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback - -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. - """ - #XXXjdm This doesn't play well with make right now. - # Force the file to always be updated, or else changing CodegenRust.py - # will cause many autogenerated bindings to be regenerated perpetually - # until the result is actually different. - - #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() - - return True - -def toStringBool(arg): - return str(not not arg).lower() - -def toBindingNamespace(arg): - return re.sub("((_workers)?$)", "Binding\\1", arg); - -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 - -def MakeNativeName(name): - return name[0].upper() + name[1:] - -builtinNames = { - IDLType.Tags.bool: 'bool', - IDLType.Tags.int8: 'i8', - IDLType.Tags.int16: 'i16', - IDLType.Tags.int32: 'i32', - IDLType.Tags.int64: 'i64', - IDLType.Tags.uint8: 'u8', - IDLType.Tags.uint16: 'u16', - IDLType.Tags.uint32: 'u32', - IDLType.Tags.uint64: 'u64', - IDLType.Tags.float: 'f32', - IDLType.Tags.double: 'f64' -} - -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. Stringifies to a Rust expression of - the appropriate type. - - codeOnFailure is the code to run if unwrapping fails. - """ - def __init__(self, descriptor, source, codeOnFailure): - self.substitution = { - "type": descriptor.nativeType, - "depth": descriptor.interface.inheritanceDepth(), - "prototype": "PrototypeList::id::" + descriptor.name, - "protoID": "PrototypeList::id::" + descriptor.name + " as uint", - "source": source, - "codeOnFailure": CGIndenter(CGGeneric(codeOnFailure), 4).define(), - } - - def __str__(self): - return string.Template( -"""match unwrap_jsmanaged(${source}, ${prototype}, ${depth}) { - Ok(val) => val, - Err(()) => { -${codeOnFailure} - } -}""").substitute(self.substitution) - - -class CGThing(): - """ - Abstract base class for things that spit out code. - """ - def __init__(self): - pass # Nothing for now - - def define(self): - """Produce code for a Rust file.""" - assert(False) # Override me! - - -class CGNativePropertyHooks(CGThing): - """ - Generate a NativePropertyHooks for a given descriptor - """ - def __init__(self, descriptor, properties): - CGThing.__init__(self) - self.descriptor = descriptor - self.properties = properties - - def define(self): - parent = self.descriptor.interface.parent - if parent: - parentHooks = "Some(&::dom::bindings::codegen::Bindings::%sBinding::sNativePropertyHooks)" % parent.identifier.name - else: - parentHooks = "None" - - substitutions = { - "parentHooks": parentHooks - } - - return string.Template( - "pub static sNativePropertyHooks: NativePropertyHooks = NativePropertyHooks {\n" - " native_properties: &sNativeProperties,\n" - " proto_hooks: ${parentHooks},\n" - "};\n").substitute(substitutions) - - -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, signatureIndex=0): - return CGPerSignatureCall(signature[0], argsPre, signature[1], - nativeMethodName + '_'*signatureIndex, - 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([getPerSignatureCall(signature)]) - requiredArgs = requiredArgCount(signature) - - - if requiredArgs > 0: - code = ( - "if argc < %d {\n" - " throw_type_error(cx, \"Not enough arguments to %s.\");\n" - " return 0;\n" - "}" % (requiredArgs, methodName)) - self.cgRoot.prepend( - CGWrapper(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] - - - sigIndex = signatures.index(signature) - argCountCases.append( - CGCase(str(argCount), getPerSignatureCall(signature, - signatureIndex=sigIndex))) - 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("let 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.offset(%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, - possibleSignatures.index(sigs[0]))) - else: - caseBody.append(CGGeneric("if " + condition + " {")) - caseBody.append(CGIndenter( - getPerSignatureCall(sigs[0], distinguishingIndex, - possibleSignatures.index(sigs[0])))) - 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).is_object() {" % - (distinguishingArg))) - for idx, sig in enumerate(interfacesSigs): - caseBody.append(CGIndenter(CGGeneric("loop {"))); - 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. - template, _, declType, needsRooting = getJSToNativeConversionTemplate( - type, descriptor, failureCode="break;", isDefinitelyObject=True) - - testCode = instantiateJSToNativeConversionTemplate( - template, - {"val": distinguishingArg}, - declType, - "arg%d" % distinguishingIndex, - needsRooting) - - # 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, idx), 4)) - caseBody.append(CGIndenter(CGGeneric("}"))) - - 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(cx, NS_ERROR_XPC_BAD_CONVERT_JS);")) - - argCountCases.append(CGCase(str(argCount), - CGList(caseBody, "\n"))) - - overloadCGThings = [] - overloadCGThings.append( - CGGeneric("let argcount = cmp::min(argc, %d);" % - maxArgCount)) - overloadCGThings.append( - CGSwitch("argcount", - argCountCases, - CGGeneric("throw_type_error(cx, \"Not enough arguments to %s.\");\n" - "return 0;\n" % methodName))) - #XXXjdm Avoid unreachable statement warnings - #overloadCGThings.append( - # CGGeneric('fail!("We have an always-returning default case");\n' - # 'return 0;')) - self.cgRoot = CGWrapper(CGList(overloadCGThings, "\n"), - pre="\n") - - def define(self): - return self.cgRoot.define() - -class FakeCastableDescriptor(): - def __init__(self, descriptor): - self.nativeType = "*const %s" % descriptor.concreteType - self.name = descriptor.name - class FakeInterface: - def inheritanceDepth(self): - return descriptor.interface.inheritanceDepth() - self.interface = FakeInterface() - -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 typeNeedsRooting(type, descriptorProvider): - return type.isGeckoInterface() and descriptorProvider.getDescriptor(type.name).needsRooting - -def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None, - isDefinitelyObject=False, - isMember=False, - isArgument=False, - invalidEnumValueFatal=True, - defaultValue=None, - treatNullAs="Default", - isEnforceRange=False, - isClamp=False, - exceptionCode=None, - allowTreatNonObjectAsNull=False, - isCallbackReturnValue=False, - sourceDescription="value"): - """ - 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. - - 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. - - If allowTreatNonObjectAsNull is true, then [TreatNonObjectAsNull] - extended attributes on nullable callback functions will be honored. - - 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 - - 2) A string or None representing Rust code for the default value (if any). - - 3) 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. - - 4) A boolean indicating whether the caller has to root the result. - - """ - # We should not have a defaultValue if we know we're an object - assert(not isDefinitelyObject or defaultValue is None) - - # If exceptionCode is not set, we'll just rethrow the exception we got. - # Note that we can't just set failureCode to exceptionCode, because setting - # failureCode will prevent pending exceptions from being set in cases when - # they really should be! - if exceptionCode is None: - exceptionCode = "return 0;" - - needsRooting = typeNeedsRooting(type, descriptorProvider) - - def handleOptional(template, declType, default): - assert (defaultValue is None) == (default is None) - return (template, default, declType, needsRooting) - - # Unfortunately, .capitalize() on a string will lowercase things inside the - # string, which we do not want. - def firstCap(string): - return string[0].upper() + string[1:] - - # Helper functions for dealing with failures due to the JS value being the - # wrong type of value - # 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 - ('throw_type_error(cx, "%s is not an object.");\n' - '%s' % (firstCap(sourceDescription), exceptionCode))), - post="\n") - def onFailureBadType(failureCode, typeName): - return CGWrapper( - CGGeneric( - failureCode or - ('throw_type_error(cx, \"%s does not implement interface %s.\");\n' - '%s' % (firstCap(sourceDescription), typeName, - exceptionCode))), - post="\n") - def onFailureNotCallable(failureCode): - return CGWrapper( - CGGeneric( - failureCode or - ('throw_type_error(cx, \"%s is not callable.\");\n' - '%s' % (firstCap(sourceDescription), exceptionCode))), - post="\n") - - - # A helper function for handling null default values. Checks that the - # default value, if it exists, is null. - def handleDefaultNull(nullValue): - if defaultValue is None: - return None - - if not isinstance(defaultValue, IDLNullValue): - raise TypeError("Can't handle non-null default value here") - - assert type.nullable() or type.isDictionary() - return nullValue - - # A helper function for wrapping up the template body for - # possibly-nullable objecty stuff - def wrapObjectTemplate(templateBody, isDefinitelyObject, type, - failureCode=None): - if not isDefinitelyObject: - # Handle the non-object cases by wrapping up the whole - # thing in an if cascade. - templateBody = ( - "if (${val}).is_object() {\n" + - CGIndenter(CGGeneric(templateBody)).define() + "\n") - if type.nullable(): - templateBody += ( - "} else if (${val}).is_null_or_undefined() {\n" - " None\n") - templateBody += ( - "} else {\n" + - CGIndenter(onFailureNotAnObject(failureCode)).define() + - "}\n") - - 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(): - raise TypeError("Can't handle sequence arguments yet") - - if type.isUnion(): - declType = CGGeneric(type.name + "::" + type.name) - if type.nullable(): - declType = CGWrapper(declType, pre="Option<", post=" >") - - templateBody = ("match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n" - " Ok(value) => value,\n" - " Err(()) => { %s },\n" - "}" % exceptionCode) - - return handleOptional(templateBody, declType, handleDefaultNull("None")) - - if type.isGeckoInterface(): - assert not isEnforceRange and not isClamp - - descriptor = descriptorProvider.getDescriptor( - type.unroll().inner.identifier.name) - - if descriptor.interface.isCallback(): - name = descriptor.nativeType - declType = CGGeneric("Option<%s>" % name); - conversion = ("Some(%s::new((${val}).to_object()))" % name) - - template = wrapObjectTemplate(conversion, isDefinitelyObject, type, - failureCode) - return handleOptional(template, declType, handleDefaultNull("None")) - - if isMember: - descriptorType = descriptor.memberType - elif isArgument: - descriptorType = descriptor.argumentType - else: - descriptorType = descriptor.nativeType - - templateBody = "" - if descriptor.interface.isConsequential(): - raise TypeError("Consequential interface %s being used as an " - "argument" % descriptor.interface.identifier.name) - - if failureCode is None: - substitutions = { - "sourceDescription": sourceDescription, - "interface": descriptor.interface.identifier.name, - "exceptionCode": exceptionCode, - } - unwrapFailureCode = string.Template( - 'throw_type_error(cx, "${sourceDescription} does not ' - 'implement interface ${interface}.");\n' - '${exceptionCode}').substitute(substitutions) - else: - unwrapFailureCode = failureCode - - templateBody = str(CastableObjectUnwrapper( - descriptor, - "(${val}).to_object()", - unwrapFailureCode)) - - declType = CGGeneric(descriptorType) - if type.nullable(): - templateBody = "Some(%s)" % templateBody - declType = CGWrapper(declType, pre="Option<", post=">") - - if isMember: - templateBody += ".root()" - - templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject, - type, failureCode) - - return handleOptional(templateBody, declType, handleDefaultNull("None")) - - if type.isSpiderMonkeyInterface(): - raise TypeError("Can't handle SpiderMonkey interface arguments yet") - - if type.isDOMString(): - assert not isEnforceRange and not isClamp - - treatAs = { - "Default": "Default", - "EmptyString": "Empty", - } - if treatNullAs not in treatAs: - raise TypeError("We don't support [TreatNullAs=%s]" % treatNullAs) - if type.nullable(): - nullBehavior = "()" - else: - nullBehavior = treatAs[treatNullAs] - - conversionCode = ( - "match FromJSValConvertible::from_jsval(cx, ${val}, %s) {\n" - " Ok(strval) => strval,\n" - " Err(_) => { %s },\n" - "}" % (nullBehavior, exceptionCode)) - - if defaultValue is None: - default = None - elif isinstance(defaultValue, IDLNullValue): - assert type.nullable() - default = "None" - else: - assert defaultValue.type.tag() == IDLType.Tags.domstring - value = "str::from_utf8(data).unwrap().to_string()" - if type.nullable(): - value = "Some(%s)" % value - - default = ( - "static data: [u8, ..%s] = [ %s ];\n" - "%s" % - (len(defaultValue.value) + 1, - ", ".join(["'" + char + "' as u8" for char in defaultValue.value] + ["0"]), - value)) - - declType = "DOMString" - if type.nullable(): - declType = "Option<%s>" % declType - - return handleOptional(conversionCode, CGGeneric(declType), default) - - if type.isByteString(): - assert not isEnforceRange and not isClamp - - conversionCode = ( - "match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n" - " Ok(strval) => strval,\n" - " Err(_) => { %s },\n" - "}" % exceptionCode) - - declType = CGGeneric("ByteString") - if type.nullable(): - declType = CGWrapper(declType, pre="Option<", post=">") - - return handleOptional(conversionCode, declType, handleDefaultNull("None")) - - 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 = exceptionCode - else: - handleInvalidEnumValueCode = "return 1;" - - template = ( - "match FindEnumStringIndex(cx, ${val}, %(values)s) {\n" - " Err(_) => { %(exceptionCode)s },\n" - " Ok(None) => { %(handleInvalidEnumValueCode)s },\n" - " Ok(Some(index)) => {\n" - " //XXXjdm need some range checks up in here.\n" - " unsafe { mem::transmute(index) }\n" - " },\n" - "}" % { "values" : enum + "Values::strings", - "exceptionCode" : exceptionCode, -"handleInvalidEnumValueCode" : handleInvalidEnumValueCode }) - - if defaultValue is not None: - assert(defaultValue.type.tag() == IDLType.Tags.domstring) - default = "%sValues::%s" % (enum, getEnumValueName(defaultValue.value)) - else: - default = None - - return handleOptional(template, CGGeneric(enum), default) - - if type.isCallback(): - assert not isEnforceRange and not isClamp - assert not type.treatNonCallableAsNull() - assert not type.treatNonObjectAsNull() or type.nullable() - assert not type.treatNonObjectAsNull() or not type.treatNonCallableAsNull() - - declType = CGGeneric('%s::%s' % (type.unroll().module(), type.unroll().identifier.name)) - - conversion = CGCallbackTempRoot(declType.define()) - - if type.nullable(): - declType = CGTemplatedType("Option", declType) - conversion = CGWrapper(conversion, pre="Some(", post=")") - - if allowTreatNonObjectAsNull and type.treatNonObjectAsNull(): - if not isDefinitelyObject: - haveObject = "${val}.is_object()" - template = CGIfElseWrapper(haveObject, - conversion, - CGGeneric("None")).define() - else: - template = conversion - else: - template = CGIfElseWrapper("JS_ObjectIsCallable(cx, ${val}.to_object()) != 0", - conversion, - onFailureNotCallable(failureCode)).define() - template = wrapObjectTemplate( - template, - isDefinitelyObject, - type, - failureCode) - - if defaultValue is not None: - assert allowTreatNonObjectAsNull - assert type.treatNonObjectAsNull() - assert type.nullable() - assert isinstance(defaultValue, IDLNullValue) - default = "None" - else: - default = None - - return (template, default, declType, needsRooting) - - if type.isAny(): - assert not isEnforceRange and not isClamp - - declType = CGGeneric("JSVal") - - if defaultValue is None: - default = None - elif isinstance(defaultValue, IDLNullValue): - default = "NullValue()" - elif isinstance(defaultValue, IDLUndefinedValue): - default = "UndefinedValue()" - else: - raise TypeError("Can't handle non-null, non-undefined default value here") - - return handleOptional("${val}", declType, default) - - if type.isObject(): - raise TypeError("Can't handle object arguments yet") - - 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() - - typeName = CGDictionary.makeDictionaryName(type.inner) - declType = CGGeneric(typeName) - template = ("match %s::new(cx, ${val}) {\n" - " Ok(dictionary) => dictionary,\n" - " Err(_) => return 0,\n" - "}" % typeName) - - return handleOptional(template, declType, handleDefaultNull("%s::empty()" % typeName)) - - if type.isVoid(): - # This one only happens for return values, and its easy: Just - # ignore the jsval. - return ("", None, None, False) - - if not type.isPrimitive(): - raise TypeError("Need conversion for argument type '%s'" % str(type)) - - assert not isEnforceRange and not isClamp - - if failureCode is None: - failureCode = 'return 0' - - declType = CGGeneric(builtinNames[type.tag()]) - if type.nullable(): - declType = CGWrapper(declType, pre="Option<", post=">") - - #XXXjdm support conversionBehavior here - template = ( - "match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n" - " Ok(v) => v,\n" - " Err(_) => { %s }\n" - "}" % exceptionCode) - - if defaultValue is not None: - if isinstance(defaultValue, IDLNullValue): - assert type.nullable() - defaultStr = "None" - else: - tag = defaultValue.type.tag() - if tag in numericTags: - defaultStr = str(defaultValue.value) - else: - assert(tag == IDLType.Tags.bool) - defaultStr = toStringBool(defaultValue.value) - - if type.nullable(): - defaultStr = "Some(%s)" % defaultStr - else: - defaultStr = None - - return handleOptional(template, declType, defaultStr) - -def instantiateJSToNativeConversionTemplate(templateBody, replacements, - declType, declName, needsRooting): - """ - Take the templateBody and declType as returned by - getJSToNativeConversionTemplate, a set of replacements as required by the - strings in such a templateBody, and a declName, and generate code to - convert into a stack Rust binding with that name. - """ - result = CGList([], "\n") - - conversion = CGGeneric( - string.Template(templateBody).substitute(replacements) - ) - - if declType is not None: - newDecl = [ - CGGeneric("let "), - CGGeneric(declName), - CGGeneric(": "), - declType, - CGGeneric(" = "), - conversion, - CGGeneric(";"), - ] - result.append(CGList(newDecl)) - else: - result.append(conversion) - - # Add an empty CGGeneric to get an extra newline after the argument - # conversion. - result.append(CGGeneric("")) - - if needsRooting: - rootBody = "let %s = %s.root();" % (declName, declName) - result.append(CGGeneric(rootBody)) - result.append(CGGeneric("")) - - return result; - -def convertConstIDLValueToJSVal(value): - if isinstance(value, IDLNullValue): - return "NullVal" - tag = value.type.tag() - if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16, - IDLType.Tags.uint16, IDLType.Tags.int32]: - return "IntVal(%s)" % (value.value) - if tag == IDLType.Tags.uint32: - return "UintVal(%s)" % (value.value) - if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]: - return "DoubleVal(%s)" % (value.value) - if tag == IDLType.Tags.bool: - return "BoolVal(true)" if value.value else "BoolVal(false)" - if tag in [IDLType.Tags.float, IDLType.Tags.double]: - return "DoubleVal(%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) - assert(not argument.defaultValue or argument.optional) - - replacer = { - "index": index, - "argc": argc, - "argv": argv - } - condition = string.Template("${index} < ${argc}").substitute(replacer) - - replacementVariables = { - "val": string.Template("(*${argv}.offset(${index}))").substitute(replacer), - } - - template, default, declType, needsRooting = getJSToNativeConversionTemplate( - argument.type, - descriptorProvider, - invalidEnumValueFatal=invalidEnumValueFatal, - defaultValue=argument.defaultValue, - treatNullAs=argument.treatNullAs, - isEnforceRange=argument.enforceRange, - isClamp=argument.clamp, - isMember="Variadic" if argument.variadic else False, - allowTreatNonObjectAsNull=argument.allowTreatNonCallableAsNull()) - - if not argument.variadic: - if argument.optional: - if argument.defaultValue: - assert default - template = CGIfElseWrapper(condition, - CGGeneric(template), - CGGeneric(default)).define() - else: - assert not default - declType = CGWrapper(declType, pre="Option<", post=">") - template = CGIfElseWrapper(condition, - CGGeneric("Some(%s)" % template), - CGGeneric("None")).define() - else: - assert not default - - self.converter = instantiateJSToNativeConversionTemplate( - template, replacementVariables, declType, "arg%d" % index, - needsRooting) - else: - assert argument.optional - variadicConversion = { - "val": string.Template("(*${argv}.offset(variadicArg as int))").substitute(replacer), - } - innerConverter = instantiateJSToNativeConversionTemplate( - template, variadicConversion, declType, "slot", - needsRooting) - - seqType = CGTemplatedType("Vec", declType) - variadicConversion = string.Template( - "{\n" - " let mut vector: ${seqType} = Vec::with_capacity((${argc} - ${index}) as uint);\n" - " for variadicArg in range(${index}, ${argc}) {\n" - "${inner}\n" - " vector.push(slot);\n" - " }\n" - " vector\n" - "}" - ).substitute({ - "index": index, - "argc": argc, - "seqType": seqType.define(), - "inner": CGIndenter(innerConverter, 4).define(), - }) - - self.converter = instantiateJSToNativeConversionTemplate( - variadicConversion, replacementVariables, seqType, "arg%d" % index, - False) - - def define(self): - return self.converter.define() - - -def wrapForType(jsvalRef, result='result', successCode='return 1;'): - """ - Reflect a Rust value into JS. - - * 'jsvalRef': a Rust reference to the JSVal in which to store the result - of the conversion; - * 'result': the name of the variable in which the Rust value is stored; - * 'successCode': the code to run once we have done the conversion. - """ - return "%s = (%s).to_jsval(cx);\n%s" % (jsvalRef, result, successCode) - - -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.isAny() or type.isObject() - -def typeRetValNeedsRooting(type): - if type is None: - return False - if type.nullable(): - type = type.inner - return type.isGeckoInterface() and not type.isCallback() and not type.isCallbackInterface() - -def memberIsCreator(member): - return member.getExtendedAttribute("Creator") is not None - -# Returns a CGThing containing the type of the return value. -def getRetvalDeclarationForType(returnType, descriptorProvider): - if returnType is None or returnType.isVoid(): - # Nothing to declare - return CGGeneric("()") - if returnType.isPrimitive() and returnType.tag() in builtinNames: - result = CGGeneric(builtinNames[returnType.tag()]) - if returnType.nullable(): - result = CGWrapper(result, pre="Option<", post=">") - return result - if returnType.isDOMString(): - result = CGGeneric("DOMString") - if returnType.nullable(): - result = CGWrapper(result, pre="Option<", post=">") - return result - if returnType.isByteString(): - result = CGGeneric("ByteString") - if returnType.nullable(): - result = CGWrapper(result, pre="Option<", post=">") - return result - if returnType.isEnum(): - result = CGGeneric(returnType.unroll().inner.identifier.name) - if returnType.nullable(): - result = CGWrapper(result, pre="Option<", post=">") - return result - if returnType.isGeckoInterface(): - descriptor = descriptorProvider.getDescriptor( - returnType.unroll().inner.identifier.name) - result = CGGeneric(descriptor.returnType) - if returnType.nullable(): - result = CGWrapper(result, pre="Option<", post=">") - return result - if returnType.isCallback(): - result = CGGeneric('%s::%s' % (returnType.unroll().module(), - returnType.unroll().identifier.name)) - if returnType.nullable(): - result = CGWrapper(result, pre="Option<", post=">") - return result - if returnType.isUnion(): - result = CGGeneric('%s::%s' % (returnType.unroll().name, returnType.unroll().name)) - if returnType.nullable(): - result = CGWrapper(result, pre="Option<", post=">") - return result - if returnType.isAny(): - return CGGeneric("JSVal") - if returnType.isObject() or returnType.isSpiderMonkeyInterface(): - return CGGeneric("*mut JSObject") - if returnType.isSequence(): - raise TypeError("We don't support sequence return values") - - raise TypeError("Don't know how to declare return value for %s" % - returnType) - -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.regular to the list of - things exposed to web pages. - """ - def __init__(self, descriptor, name): - self.descriptor = descriptor - self.name = name - - def variableName(self): - return "s" + self.name - - def length(self): - return len(self.regular) - - def __str__(self): - # We only need to generate id arrays for things that will end - # up used via ResolveProperty or EnumerateProperties. - return self.generateArray(self.regular, self.variableName()) - - def generatePrefableArray(self, array, name, specTemplate, specTerminator, - specType, getDataTuple): - """ - 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 at the end - of the array), or None - - specType is the actual typename of our spec - - getDataTuple is a callback function that takes an array entry and - returns a tuple suitable for substitution into specTemplate. - """ - - assert(len(array) is not 0) - specs = [] - - for member in array: - specs.append(specTemplate % getDataTuple(member)) - if specTerminator: - specs.append(specTerminator) - - return (("static %s: &'static [%s] = &[\n" + - ",\n".join(specs) + "\n" + - "];\n\n") % (name, specType)) - -# 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.regular = [{"name": m.identifier.name, - "methodInfo": not m.isStatic(), - "length": methodLength(m), - "flags": "JSPROP_ENUMERATE" } - for m in methods] - - # FIXME Check for an existing iterator on the interface first. - if any(m.isGetter() and m.isIndexed() for m in methods): - self.regular.append({"name": 'iterator', - "methodInfo": False, - "nativeName": "JS_ArrayIterator", - "length": 0, - "flags": "JSPROP_ENUMERATE" }) - - def generateArray(self, array, name): - if len(array) == 0: - return "" - - def specData(m): - if m.get("methodInfo", True): - jitinfo = ("&%s_methodinfo" % m["name"]) - accessor = "genericMethod" - else: - jitinfo = "0 as *const JSJitInfo" - accessor = m.get("nativeName", m["name"]) - return (m["name"], accessor, jitinfo, m["length"], m["flags"]) - - def stringDecl(m): - return "static %s_name: [u8, ..%i] = %s;\n" % (m["name"], len(m["name"]) + 1, - str_to_const_array(m["name"])) - - decls = ''.join([stringDecl(m) for m in array]) - return decls + self.generatePrefableArray( - array, name, - ' JSFunctionSpec {name: &%s_name as *const u8 as *const libc::c_char, call: JSNativeWrapper {op: Some(%s), info: %s}, nargs: %s, flags: %s as u16, selfHostedName: 0 as *const libc::c_char }', - ' JSFunctionSpec {name: 0 as *const libc::c_char, call: JSNativeWrapper {op: None, info: 0 as *const JSJitInfo}, nargs: 0, flags: 0, selfHostedName: 0 as *const libc::c_char }', - 'JSFunctionSpec', - specData) - -class AttrDefiner(PropertyDefiner): - def __init__(self, descriptor, name, static): - PropertyDefiner.__init__(self, descriptor, name) - self.name = name - self.regular = [ - m - for m in descriptor.interface.members - if m.isAttr() and m.isStatic() == static - ] - self.static = static - - def generateArray(self, array, name): - if len(array) == 0: - return "" - - def flags(attr): - return "JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS" - - def getter(attr): - if self.static: - accessor = 'get_' + attr.identifier.name - jitinfo = "0" - else: - if attr.hasLenientThis(): - accessor = "genericLenientGetter" - else: - accessor = "genericGetter" - jitinfo = "&%s_getterinfo" % attr.identifier.name - - return ("JSPropertyOpWrapper {op: Some(%(native)s), info: %(info)s as *const JSJitInfo}" - % {"info" : jitinfo, - "native" : accessor}) - - def setter(attr): - if attr.readonly: - return "JSStrictPropertyOpWrapper {op: None, info: 0 as *const JSJitInfo}" - - if self.static: - accessor = 'set_' + attr.identifier.name - jitinfo = "0" - else: - if attr.hasLenientThis(): - accessor = "genericLenientSetter" - else: - accessor = "genericSetter" - jitinfo = "&%s_setterinfo" % attr.identifier.name - - return ("JSStrictPropertyOpWrapper {op: Some(%(native)s), info: %(info)s as *const JSJitInfo}" - % {"info" : jitinfo, - "native" : accessor}) - - def specData(attr): - return (attr.identifier.name, flags(attr), getter(attr), - setter(attr)) - - def stringDecl(attr): - name = attr.identifier.name - return "static %s_name: [u8, ..%i] = %s;\n" % (name, len(name) + 1, - str_to_const_array(name)) - - decls = ''.join([stringDecl(m) for m in array]) - - return decls + self.generatePrefableArray( - array, name, - ' JSPropertySpec { name: &%s_name as *const u8 as *const libc::c_char, tinyid: 0, flags: ((%s) & 0xFF) as u8, getter: %s, setter: %s }', - ' JSPropertySpec { name: 0 as *const libc::c_char, tinyid: 0, flags: 0, getter: JSPropertyOpWrapper {op: None, info: 0 as *const JSJitInfo}, setter: JSStrictPropertyOpWrapper {op: None, info: 0 as *const JSJitInfo} }', - 'JSPropertySpec', - specData) - -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.regular = [m for m in descriptor.interface.members if m.isConst()] - - def generateArray(self, array, name): - if len(array) == 0: - return "" - - def specData(const): - return (const.identifier.name, - convertConstIDLValueToJSVal(const.value)) - - def stringDecl(const): - name = const.identifier.name - return "static %s_name: &'static [u8] = &%s;\n" % (name, str_to_const_array(name)) - - decls = ''.join([stringDecl(m) for m in array]) - - return decls + self.generatePrefableArray( - array, name, - ' ConstantSpec { name: %s_name, value: %s }', - None, - 'ConstantSpec', - specData) - -# 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): - CGThing.__init__(self) - self.child = child - self.indent = " " * indentLevel - - def define(self): - defn = self.child.define() - if defn is not "": - 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="", reindent=False): - CGThing.__init__(self) - self.child = child - self.pre = pre - self.post = post - self.reindent = reindent - - def define(self): - 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.pre)))) - return self.pre + defn + self.post - -class CGImports(CGWrapper): - """ - Generates the appropriate import/use statements. - """ - def __init__(self, child, descriptors, imports): - """ - Adds a set of imports. - """ - ignored_warnings = [ - # Allow unreachable_code because we use 'break' in a way that - # sometimes produces two 'break's in a row. See for example - # CallbackMember.getArgConversions. - 'unreachable_code', - 'non_camel_case_types', - 'non_uppercase_statics', - 'unnecessary_parens', - 'unused_imports', - 'unused_variable', - 'unused_unsafe', - 'unused_mut', - 'dead_assignment', - 'dead_code', - ] - - statements = ['#![allow(%s)]' % ','.join(ignored_warnings)] - statements.extend('use %s;' % i for i in sorted(imports)) - - CGWrapper.__init__(self, child, - pre='\n'.join(statements) + '\n\n') - - @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.rs') - -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 CGTemplatedType(CGWrapper): - def __init__(self, templateName, child): - CGWrapper.__init__(self, child, pre=templateName + "<", post=">") - -class CGNamespace(CGWrapper): - def __init__(self, namespace, child, public=False): - pre = "%smod %s {\n" % ("pub " if public else "", namespace) - post = "} // mod %s\n" % namespace - CGWrapper.__init__(self, child, pre=pre, post=post) - - @staticmethod - def build(namespaces, child, public=False): - """ - Static helper method to build multiple wrapped namespaces. - """ - if not namespaces: - return child - inner = CGNamespace.build(namespaces[1:], child, public=public) - return CGNamespace(namespaces[0], inner, public=public) - -def DOMClass(descriptor): - protoList = ['PrototypeList::id::' + proto for proto in descriptor.prototypeChain] - # Pad out the list to the right length with IDCount so we - # guarantee that all the lists are the same length. IDCount - # is never the ID of any prototype, so it's safe to use as - # padding. - protoList.extend(['PrototypeList::id::IDCount'] * (descriptor.config.maxProtoChainLength - len(protoList))) - prototypeChainString = ', '.join(protoList) - return """DOMClass { - interface_chain: [ %s ], - native_hooks: &sNativePropertyHooks, -}""" % prototypeChainString - -class CGDOMJSClass(CGThing): - """ - Generate a DOMJSClass for a given descriptor - """ - def __init__(self, descriptor): - CGThing.__init__(self) - self.descriptor = descriptor - - def define(self): - traceHook = "Some(%s)" % TRACE_HOOK_NAME - if self.descriptor.isGlobal(): - flags = "JSCLASS_IS_GLOBAL | JSCLASS_DOM_GLOBAL" - slots = "JSCLASS_GLOBAL_SLOT_COUNT + 1" - else: - flags = "0" - slots = "1" - return """ -static Class_name: [u8, ..%i] = %s; -static Class: DOMJSClass = DOMJSClass { - base: js::Class { - name: &Class_name as *const u8 as *const libc::c_char, - flags: JSCLASS_IS_DOMJSCLASS | %s | (((%s) & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT as uint), //JSCLASS_HAS_RESERVED_SLOTS(%s), - addProperty: Some(JS_PropertyStub), - delProperty: Some(JS_PropertyStub), - getProperty: Some(JS_PropertyStub), - setProperty: Some(JS_StrictPropertyStub), - enumerate: Some(JS_EnumerateStub), - resolve: Some(JS_ResolveStub), - convert: Some(JS_ConvertStub), - finalize: Some(%s), - checkAccess: None, - call: None, - hasInstance: None, - construct: None, - trace: %s, - - ext: js::ClassExtension { - equality: 0 as *const u8, - outerObject: %s, - innerObject: None, - iteratorObject: 0 as *const u8, - unused: 0 as *const u8, - isWrappedNative: 0 as *const u8, - }, - - ops: js::ObjectOps { - lookupGeneric: 0 as *const u8, - lookupProperty: 0 as *const u8, - lookupElement: 0 as *const u8, - lookupSpecial: 0 as *const u8, - defineGeneric: 0 as *const u8, - defineProperty: 0 as *const u8, - defineElement: 0 as *const u8, - defineSpecial: 0 as *const u8, - getGeneric: 0 as *const u8, - getProperty: 0 as *const u8, - getElement: 0 as *const u8, - getElementIfPresent: 0 as *const u8, - getSpecial: 0 as *const u8, - setGeneric: 0 as *const u8, - setProperty: 0 as *const u8, - setElement: 0 as *const u8, - setSpecial: 0 as *const u8, - getGenericAttributes: 0 as *const u8, - getPropertyAttributes: 0 as *const u8, - getElementAttributes: 0 as *const u8, - getSpecialAttributes: 0 as *const u8, - setGenericAttributes: 0 as *const u8, - setPropertyAttributes: 0 as *const u8, - setElementAttributes: 0 as *const u8, - setSpecialAttributes: 0 as *const u8, - deleteProperty: 0 as *const u8, - deleteElement: 0 as *const u8, - deleteSpecial: 0 as *const u8, - - enumerate: 0 as *const u8, - typeOf: 0 as *const u8, - thisObject: %s, - clear: 0 as *const u8, - }, - }, - dom_class: %s -}; -""" % (len(self.descriptor.interface.identifier.name) + 1, - str_to_const_array(self.descriptor.interface.identifier.name), - flags, slots, slots, - FINALIZE_HOOK_NAME, traceHook, - self.descriptor.outerObjectHook, - self.descriptor.outerObjectHook, - CGIndenter(CGGeneric(DOMClass(self.descriptor))).define()) - -def str_to_const_array(s): - return "[" + (", ".join(map(lambda x: "'" + x + "' as u8", list(s)) + ['0 as u8'])) + "]" - -class CGPrototypeJSClass(CGThing): - def __init__(self, descriptor): - CGThing.__init__(self) - self.descriptor = descriptor - - def define(self): - return """ -static PrototypeClassName__: [u8, ..%s] = %s; -static PrototypeClass: JSClass = JSClass { - name: &PrototypeClassName__ as *const u8 as *const libc::c_char, - flags: (1 & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT as uint, //JSCLASS_HAS_RESERVED_SLOTS(1) - addProperty: Some(JS_PropertyStub), - delProperty: Some(JS_PropertyStub), - getProperty: Some(JS_PropertyStub), - setProperty: Some(JS_StrictPropertyStub), - enumerate: Some(JS_EnumerateStub), - resolve: Some(JS_ResolveStub), - convert: Some(JS_ConvertStub), - finalize: None, - checkAccess: None, - call: None, - hasInstance: None, - construct: None, - trace: None, - reserved: [0 as *mut libc::c_void, ..40] -}; -""" % (len(self.descriptor.interface.identifier.name + "Prototype") + 1, - str_to_const_array(self.descriptor.interface.identifier.name + "Prototype")) - -class CGInterfaceObjectJSClass(CGThing): - def __init__(self, descriptor): - CGThing.__init__(self) - self.descriptor = descriptor - - def define(self): - if True: - return "" - ctorname = "0 as *const u8" if not self.descriptor.interface.ctor() else CONSTRUCT_HOOK_NAME - hasinstance = HASINSTANCE_HOOK_NAME - return """ -static InterfaceObjectClass: JSClass = { - %s, 0, - JS_PropertyStub, - JS_PropertyStub, - JS_PropertyStub, - JS_StrictPropertyStub, - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub, - 0 as *const u8, - 0 as *const u8, - %s, - %s, - %s, - 0 as *const u8, - JSCLASS_NO_INTERNAL_MEMBERS -}; -""" % (str_to_const_array("Function"), 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 define(self): - return self.join(child.define() for child in self.children if child is not None) - - -class CGIfElseWrapper(CGList): - def __init__(self, condition, ifTrue, ifFalse): - kids = [ CGIfWrapper(ifTrue, condition), - CGWrapper(CGIndenter(ifFalse), pre=" else {\n", post="\n}") ] - CGList.__init__(self, kids) - - -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, text): - self.text = text - - def define(self): - return self.text - -class CGCallbackTempRoot(CGGeneric): - def __init__(self, name): - val = "%s::new(tempRoot)" % name - define = """{ - let tempRoot = ${val}.to_object(); - %s -}""" % val - CGGeneric.__init__(self, define) - - -def getAllTypes(descriptors, dictionaries, callbacks): - """ - Generate all the types we're dealing with. For each type, a tuple - containing type, descriptor, dictionary is yielded. The - descriptor and dictionary can be None if the type does not come - from a descriptor or dictionary; they will never both be non-None. - """ - for d in descriptors: - for t in getTypesFromDescriptor(d): - yield (t, d, None) - for dictionary in dictionaries: - for t in getTypesFromDictionary(dictionary): - yield (t, None, dictionary) - for callback in callbacks: - for t in getTypesFromCallback(callback): - yield (t, None, None) - -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, dictionaries, callbacks, config): - """ - Returns a CGList containing CGUnionStructs for every union. - """ - - imports = [ - 'dom::bindings::utils::unwrap_jsmanaged', - 'dom::bindings::codegen::PrototypeList', - 'dom::bindings::conversions::FromJSValConvertible', - 'dom::bindings::conversions::ToJSValConvertible', - 'dom::bindings::conversions::Default', - 'dom::bindings::error::throw_not_in_union', - 'dom::bindings::js::JS', - 'dom::types::*', - 'js::jsapi::JSContext', - 'js::jsval::JSVal', - 'servo_util::str::DOMString', - ] - - # Now find all the things we'll need as arguments and return values because - # we need to wrap or unwrap them. - unionStructs = dict() - for (t, descriptor, dictionary) in getAllTypes(descriptors, dictionaries, callbacks): - assert not descriptor or not dictionary - t = t.unroll() - if not t.isUnion(): - continue - name = str(t) - if not name in unionStructs: - provider = descriptor or config.getDescriptorProvider() - unionStructs[name] = CGNamespace(name, - CGImports(CGList([ - CGUnionStruct(t, provider), - CGUnionConversionStruct(t, provider) - ]), [], imports), - public=True) - - return CGList(SortedDictValues(unionStructs), "\n\n") - - -class Argument(): - """ - A class for outputting the type and name of an argument - """ - def __init__(self, argType, name, default=None, mutable=False): - self.argType = argType - self.name = name - self.default = default - self.mutable = mutable - def declare(self): - string = ('mut ' if self.mutable else '') + self.name + ((': ' + self.argType) if self.argType else '') - #XXXjdm Support default arguments somehow :/ - #if self.default is not None: - # string += " = " + self.default - return string - def define(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. - - 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, extern=False, pub=False, templateArgs=None, unsafe=True): - CGThing.__init__(self) - self.descriptor = descriptor - self.name = name - self.returnType = returnType - self.args = args - self.alwaysInline = alwaysInline - self.extern = extern - self.templateArgs = templateArgs - self.pub = pub; - self.unsafe = unsafe - def _argstring(self): - return ', '.join([a.declare() for a in self.args]) - def _template(self): - if self.templateArgs is None: - return '' - return '<%s>\n' % ', '.join(self.templateArgs) - - def _decorators(self): - decorators = [] - if self.alwaysInline: - decorators.append('#[inline(always)]') - - if self.extern: - decorators.append('extern') - - if self.pub: - decorators.append('pub') - - if not decorators: - return '' - return ' '.join(decorators) + ' ' - - def _returnType(self): - return (" -> %s" % self.returnType) if self.returnType != "void" else "" - - def define(self): - body = self.definition_body() - if self.unsafe: - body = CGWrapper(body, pre="unsafe {\n", post="\n}") - - return CGWrapper(CGIndenter(body), - pre=self.definition_prologue(), - post=self.definition_epilogue()).define() - - def definition_prologue(self): - return "%sfn %s%s(%s)%s {\n" % (self._decorators(), self.name, self._template(), - self._argstring(), self._returnType()) - def definition_epilogue(self): - return "\n}\n" - def definition_body(self): - assert(False) # Override me! - -def CreateBindingJSObject(descriptor, parent=None): - create = "let mut raw: JS<%s> = JS::from_raw(&*aObject);\n" % descriptor.concreteType - if descriptor.proxy: - assert not descriptor.isGlobal() - create += """ -let handler = RegisterBindings::proxy_handlers[PrototypeList::proxies::%s as uint]; -let mut private = PrivateValue(squirrel_away_unique(aObject) as *const libc::c_void); -let obj = with_compartment(aCx, proto, || { - NewProxyObject(aCx, handler, - &private, - proto, %s, - ptr::mut_null(), ptr::mut_null()) -}); -assert!(obj.is_not_null()); - -""" % (descriptor.name, parent) - else: - if descriptor.isGlobal(): - create += "let obj = CreateDOMGlobal(aCx, &Class.base as *const js::Class as *const JSClass);\n" - else: - create += ("let obj = with_compartment(aCx, proto, || {\n" - " JS_NewObject(aCx, &Class.base as *const js::Class as *const JSClass, &*proto, &*%s)\n" - "});\n" % parent) - create += """assert!(obj.is_not_null()); - -JS_SetReservedSlot(obj, DOM_OBJECT_SLOT as u32, - PrivateValue(squirrel_away_unique(aObject) as *const libc::c_void)); -""" - return create - -class CGWrapMethod(CGAbstractMethod): - """ - Class that generates the FooBinding::Wrap function for non-callback - interfaces. - """ - def __init__(self, descriptor): - assert not descriptor.interface.isCallback() - if not descriptor.isGlobal(): - args = [Argument('*mut JSContext', 'aCx'), Argument('&GlobalRef', 'aScope'), - Argument("Box<%s>" % descriptor.concreteType, 'aObject', mutable=True)] - else: - args = [Argument('*mut JSContext', 'aCx'), - Argument("Box<%s>" % descriptor.concreteType, 'aObject', mutable=True)] - retval = 'Temporary<%s>' % descriptor.concreteType - CGAbstractMethod.__init__(self, descriptor, 'Wrap', retval, args, pub=True) - - def definition_body(self): - if not self.descriptor.isGlobal(): - return CGGeneric("""\ -let scope = aScope.reflector().get_jsobject(); -assert!(scope.is_not_null()); -assert!(((*JS_GetClass(scope)).flags & JSCLASS_IS_GLOBAL) != 0); - -let proto = with_compartment(aCx, scope, || GetProtoObject(aCx, scope, scope)); -assert!(proto.is_not_null()); - -%s - -raw.reflector().set_jsobject(obj); - -Temporary::new(raw)""" % CreateBindingJSObject(self.descriptor, "scope")) - else: - return CGGeneric("""\ -%s -with_compartment(aCx, obj, || { - let proto = GetProtoObject(aCx, obj, obj); - JS_SetPrototype(aCx, obj, proto); - - raw.reflector().set_jsobject(obj); - - RegisterBindings::Register(aCx, obj); -}); - -Temporary::new(raw)""" % CreateBindingJSObject(self.descriptor)) - - -class CGIDLInterface(CGThing): - """ - Class for codegen of an implementation of the IDLInterface trait. - """ - def __init__(self, descriptor): - CGThing.__init__(self) - self.descriptor = descriptor - - def define(self): - replacer = { - 'type': self.descriptor.name, - 'depth': self.descriptor.interface.inheritanceDepth(), - } - return string.Template(""" -impl IDLInterface for ${type} { - fn get_prototype_id(_: Option<${type}>) -> PrototypeList::id::ID { - PrototypeList::id::${type} - } - fn get_prototype_depth(_: Option<${type}>) -> uint { - ${depth} - } -} -""").substitute(replacer) - - -class CGAbstractExternMethod(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, extern=True) - -class PropertyArrays(): - def __init__(self, descriptor): - self.staticMethods = MethodDefiner(descriptor, "StaticMethods", - static=True) - self.staticAttrs = AttrDefiner(descriptor, "StaticAttributes", - static=True) - self.methods = MethodDefiner(descriptor, "Methods", static=False) - self.attrs = AttrDefiner(descriptor, "Attributes", static=False) - self.consts = ConstDefiner(descriptor, "Constants") - pass - - @staticmethod - def arrayNames(): - return [ "staticMethods", "staticAttrs", "methods", "attrs", "consts" ] - - def variableNames(self): - names = {} - for array in self.arrayNames(): - names[array] = getattr(self, array).variableName() - return names - def __str__(self): - define = "" - for array in self.arrayNames(): - define += str(getattr(self, array)) - return define - - -class CGNativeProperties(CGThing): - def __init__(self, descriptor, properties): - CGThing.__init__(self) - self.properties = properties - - def define(self): - def getField(array): - propertyArray = getattr(self.properties, array) - if propertyArray.length() > 0: - value = "Some(%s)" % propertyArray.variableName() - else: - value = "None" - - return CGGeneric(string.Template('${name}: ${value},').substitute({ - 'name': array, - 'value': value, - })) - - nativeProps = CGList([getField(array) for array in self.properties.arrayNames()], '\n') - return CGWrapper(CGIndenter(nativeProps), - pre="static sNativeProperties: NativeProperties = NativeProperties {\n", - post="\n};\n").define() - - -class CGCreateInterfaceObjectsMethod(CGAbstractMethod): - """ - Generate the CreateInterfaceObjects method for an interface descriptor. - - properties should be a PropertyArrays instance. - """ - def __init__(self, descriptor, properties): - assert not descriptor.interface.isCallback() - args = [Argument('*mut JSContext', 'aCx'), Argument('*mut JSObject', 'aGlobal'), - Argument('*mut JSObject', 'aReceiver')] - CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', '*mut 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)) - - getParentProto = ("let parentProto: *mut JSObject = %s;\n" - "assert!(parentProto.is_not_null());\n") % getParentProto - - if self.descriptor.concrete: - if self.descriptor.proxy: - domClass = "&Class" - else: - domClass = "&Class.dom_class" - else: - domClass = "ptr::null()" - - if self.descriptor.interface.hasInterfaceObject(): - if self.descriptor.interface.ctor(): - constructHook = CONSTRUCT_HOOK_NAME - constructArgs = methodLength(self.descriptor.interface.ctor()) - else: - constructHook = "ThrowingConstructor" - constructArgs = 0 - - constructor = 'Some((%s, "%s", %d))' % ( - constructHook, self.descriptor.interface.identifier.name, - constructArgs) - else: - constructor = 'None' - - call = """return CreateInterfaceObjects2(aCx, aGlobal, aReceiver, parentProto, - &PrototypeClass, %s, - %s, - &sNativeProperties);""" % (constructor, domClass) - - return CGList([ - CGGeneric(getParentProto), - CGGeneric(call % self.properties.variableNames()) - ], "\n") - -class CGGetPerInterfaceObject(CGAbstractMethod): - """ - A method for getting a per-interface object (a prototype object or interface - constructor object). - """ - def __init__(self, descriptor, name, idPrefix="", pub=False): - args = [Argument('*mut JSContext', 'aCx'), Argument('*mut JSObject', 'aGlobal'), - Argument('*mut JSObject', 'aReceiver')] - CGAbstractMethod.__init__(self, descriptor, name, - '*mut JSObject', args, pub=pub) - self.id = idPrefix + "id::" + self.descriptor.name - def definition_body(self): - return CGGeneric(""" - -/* 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. - */ - -assert!(((*JS_GetClass(aGlobal)).flags & JSCLASS_DOM_GLOBAL) != 0); - -/* Check to see whether the interface objects are already installed */ -let protoOrIfaceArray = GetProtoOrIfaceArray(aGlobal); -let cachedObject: *mut JSObject = *protoOrIfaceArray.offset(%s as int); -if cachedObject.is_null() { - let tmp: *mut JSObject = CreateInterfaceObjects(aCx, aGlobal, aReceiver); - assert!(tmp.is_not_null()); - *protoOrIfaceArray.offset(%s as int) = tmp; - tmp -} else { - 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", - "PrototypeList::", pub=True) - def definition_body(self): - return CGList([ - CGGeneric("""\ -/* 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 CGList([ - CGGeneric("""\ -/* Get the interface object for this class. This will create the object as - needed. */"""), - CGGetPerInterfaceObject.definition_body(self), - ]) - - -class CGDefineProxyHandler(CGAbstractMethod): - """ - A method to create and cache the proxy trap for a given interface. - """ - def __init__(self, descriptor): - assert descriptor.proxy - CGAbstractMethod.__init__(self, descriptor, 'DefineProxyHandler', '*const libc::c_void', [], pub=True) - - def define(self): - return CGAbstractMethod.define(self) - - def definition_body(self): - body = """\ -let traps = ProxyTraps { - getPropertyDescriptor: Some(getPropertyDescriptor), - getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor), - defineProperty: Some(defineProperty), - getOwnPropertyNames: ptr::null(), - delete_: Some(delete_), - enumerate: ptr::null(), - - has: None, - hasOwn: Some(hasOwn), - get: Some(get), - set: None, - keys: ptr::null(), - iterate: None, - - call: None, - construct: None, - nativeCall: ptr::null(), - hasInstance: None, - typeOf: None, - objectClassIs: None, - obj_toString: Some(obj_toString), - fun_toString: None, - //regexp_toShared: ptr::null(), - defaultValue: None, - iteratorNext: None, - finalize: Some(%s), - getElementIfPresent: None, - getPrototypeOf: None, - trace: Some(%s) -}; - -CreateProxyHandler(&traps, &Class as *const _ as *const _) -""" % (FINALIZE_HOOK_NAME, - TRACE_HOOK_NAME) - return CGGeneric(body) - - - -class CGDefineDOMInterfaceMethod(CGAbstractMethod): - """ - A method for resolve hooks to try to lazily define the interface object for - a given interface. - """ - def __init__(self, descriptor): - assert descriptor.interface.hasInterfaceObject() - args = [ - Argument('*mut JSContext', 'cx'), - Argument('*mut JSObject', 'global'), - ] - CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'void', args, pub=True) - - def define(self): - return CGAbstractMethod.define(self) - - def definition_body(self): - return CGGeneric("""\ -assert!(global.is_not_null()); -assert!(GetProtoObject(cx, global, global).is_not_null());""") - -def needCx(returnType, arguments, considerTypes): - return (considerTypes and - (typeNeedsCx(returnType, True) or - any(typeNeedsCx(a.type) for a in arguments))) - -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. - - errorResult should be a string for the value to return in case of an - exception from the native code, or None if no error reporting is needed. - """ - def __init__(self, errorResult, arguments, argsPre, returnType, - extendedAttributes, descriptorProvider, nativeMethodName, - static, object="this"): - CGThing.__init__(self) - - assert errorResult is None or isinstance(errorResult, str) - - isFallible = errorResult is not None - - result = getRetvalDeclarationForType(returnType, descriptorProvider) - if isFallible: - result = CGWrapper(result, pre="Result<", post=", Error>") - - args = CGList([CGGeneric(arg) for arg in argsPre], ", ") - for (a, name) in arguments: - #XXXjdm Perhaps we should pass all nontrivial types by borrowed pointer - if a.type.isGeckoInterface(): - if not (a.type.nullable() or a.optional): - name = "&" + name - elif a.type.isDictionary(): - name = "&" + name - args.append(CGGeneric(name)) - - needsCx = needCx(returnType, (a for (a, _) in arguments), True) - - 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.interface.identifier.name) - else: - call = CGWrapper(call, pre="(*%s)." % object) - call = CGList([call, CGWrapper(args, pre="(", post=")")]) - - self.cgRoot.append(CGList([ - CGGeneric("let result: "), - result, - CGGeneric(" = "), - call, - CGGeneric(";"), - ])) - - if isFallible: - if static: - glob = "" - else: - glob = " let global = global_object_for_js_object(this.reflector().get_jsobject());\n"\ - " let global = global.root();\n" - - self.cgRoot.append(CGGeneric( - "let result = match result {\n" - " Ok(result) => result,\n" - " Err(e) => {\n" - "%s" - " throw_dom_exception(cx, &global.root_ref(), e);\n" - " return%s;\n" - " },\n" - "};\n" % (glob, errorResult))) - - if typeRetValNeedsRooting(returnType): - self.cgRoot.append(CGGeneric("let result = result.root();")) - - 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( - ' false as JSBool' 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 "\nlet argv = JS_ARGV(cx, vp);\n" - def getArgc(self): - return "argc" - def getArguments(self): - def process(arg, i): - argVal = "arg" + str(i) - if arg.type.isGeckoInterface() and not arg.type.unroll().inner.isCallback(): - argVal += ".root_ref()" - return argVal - return [(a, process(a, i)) for (i, a) in enumerate(self.arguments)] - - def isFallible(self): - return not 'infallible' in self.extendedAttributes - - def wrap_return_value(self): - return wrapForType('*vp') - - 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="match ", post=" {")); - if default is not None: - self.append( - CGIndenter( - CGWrapper( - CGIndenter(default), - pre="_ => {\n", - post="\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), post=" => {")) - bodyList = CGList([body], "\n") - if fallThrough: - raise TypeError("fall through required but unsupported") - #bodyList.append(CGGeneric('fail!("fall through unsupported"); /* Fall through */')) - self.append(CGIndenter(bodyList)); - self.append(CGGeneric("}")) - -class CGGetterCall(CGPerSignatureCall): - """ - A class to generate a native object getter call for a particular IDL - getter. - """ - def __init__(self, argsPre, returnType, nativeMethodName, descriptor, attr): - CGPerSignatureCall.__init__(self, returnType, argsPre, [], - nativeMethodName, attr.isStatic(), 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, allowTreatNonObjectAsNull=False): - self.type = type - self.optional = False - self.variadic = False - self.defaultValue = None - self._allowTreatNonObjectAsNull = allowTreatNonObjectAsNull - self.treatNullAs = interfaceMember.treatNullAs - self.enforceRange = False - self.clamp = False - - def allowTreatNonCallableAsNull(self): - return self._allowTreatNonObjectAsNull - -class CGSetterCall(CGPerSignatureCall): - """ - A class to generate a native object setter call for a particular IDL - setter. - """ - def __init__(self, argsPre, argType, nativeMethodName, descriptor, attr): - CGPerSignatureCall.__init__(self, None, argsPre, - [FakeArgument(argType, attr, allowTreatNonObjectAsNull=True)], - nativeMethodName, attr.isStatic(), descriptor, attr, - setter=True) - def wrap_return_value(self): - # We have no return value - return "\nreturn 1;" - def getArgc(self): - return "1" - def getArgvDecl(self): - # We just get our stuff from our last arg no matter what - return "" - -class CGAbstractBindingMethod(CGAbstractExternMethod): - """ - 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): - CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args) - - if unwrapFailureCode is None: - self.unwrapFailureCode = ( - 'throw_type_error(cx, "\\"this\\" object does not ' - 'implement interface %s.");\n' - 'return 0;' % descriptor.interface.identifier.name) - 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 = str(CastableObjectUnwrapper( - FakeCastableDescriptor(self.descriptor), - "obj", self.unwrapFailureCode)) - unwrapThis = CGGeneric( - "let obj: *mut JSObject = JS_THIS_OBJECT(cx, vp as *mut JSVal);\n" - "if obj.is_null() {\n" - " return false as JSBool;\n" - "}\n" - "\n" - "let this: JS<%s> = %s;\n" % (self.descriptor.concreteType, unwrapThis)) - return CGList([ unwrapThis, self.generate_code() ], "\n") - - def generate_code(self): - assert(False) # Override me - - -class CGAbstractStaticBindingMethod(CGAbstractMethod): - """ - Common class to generate the JSNatives for all our static methods, getters - and setters. This will generate the function declaration and unwrap the - global 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 = [ - Argument('*mut JSContext', 'cx'), - Argument('libc::c_uint', 'argc'), - Argument('*mut JSVal', 'vp'), - ] - CGAbstractMethod.__init__(self, descriptor, name, "JSBool", args, extern=True) - - def definition_body(self): - return self.generate_code() - - def generate_code(self): - assert False # Override me - - -class CGGenericMethod(CGAbstractBindingMethod): - """ - A class for generating the C++ code for an IDL method.. - """ - def __init__(self, descriptor): - args = [Argument('*mut JSContext', 'cx'), Argument('libc::c_uint', 'argc'), - Argument('*mut JSVal', 'vp')] - CGAbstractBindingMethod.__init__(self, descriptor, 'genericMethod', args) - - def generate_code(self): - return CGGeneric( - "let _info: *const JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n" - "return CallJitMethodOp(_info, cx, obj, this.unsafe_get() as *mut libc::c_void, argc, vp);") - -class CGSpecializedMethod(CGAbstractExternMethod): - """ - 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('*mut JSContext', 'cx'), Argument('JSHandleObject', '_obj'), - Argument('*const %s' % descriptor.concreteType, 'this'), - Argument('libc::c_uint', 'argc'), Argument('*mut JSVal', 'vp')] - CGAbstractExternMethod.__init__(self, descriptor, name, 'JSBool', args) - - def definition_body(self): - nativeName = CGSpecializedMethod.makeNativeName(self.descriptor, - self.method) - return CGWrapper(CGMethodCall([], nativeName, self.method.isStatic(), - self.descriptor, self.method), - pre="let this = JS::from_raw(this);\n" - "let this = this.root();\n") - - @staticmethod - def makeNativeName(descriptor, method): - return MakeNativeName(method.identifier.name) - -class CGStaticMethod(CGAbstractStaticBindingMethod): - """ - A class for generating the Rust code for an IDL static method. - """ - def __init__(self, descriptor, method): - self.method = method - name = method.identifier.name - CGAbstractStaticBindingMethod.__init__(self, descriptor, name) - - def generate_code(self): - nativeName = CGSpecializedMethod.makeNativeName(self.descriptor, - self.method) - return CGMethodCall([], nativeName, True, self.descriptor, self.method) - - -class CGGenericGetter(CGAbstractBindingMethod): - """ - A class for generating the C++ code for an IDL attribute getter. - """ - def __init__(self, descriptor, lenientThis=False): - args = [Argument('*mut JSContext', 'cx'), Argument('libc::c_uint', 'argc'), - Argument('*mut JSVal', '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 CGGeneric( - "let info: *const JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n" - "return CallJitPropertyOp(info, cx, obj, this.unsafe_get() as *mut libc::c_void, vp);\n") - -class CGSpecializedGetter(CGAbstractExternMethod): - """ - 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('*mut JSContext', 'cx'), - Argument('JSHandleObject', '_obj'), - Argument('*const %s' % descriptor.concreteType, 'this'), - Argument('*mut JSVal', 'vp') ] - CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args) - - def definition_body(self): - nativeName = CGSpecializedGetter.makeNativeName(self.descriptor, - self.attr) - - return CGWrapper(CGGetterCall([], self.attr.type, nativeName, - self.descriptor, self.attr), - pre="let this = JS::from_raw(this);\n" - "let this = this.root();\n") - - @staticmethod - def makeNativeName(descriptor, attr): - nativeName = MakeNativeName(attr.identifier.name) - infallible = ('infallible' in - descriptor.getExtendedAttributes(attr, getter=True)) - if attr.type.nullable() or not infallible: - return "Get" + nativeName - - return nativeName - - -class CGStaticGetter(CGAbstractStaticBindingMethod): - """ - A class for generating the C++ code for an IDL static attribute getter. - """ - def __init__(self, descriptor, attr): - self.attr = attr - name = 'get_' + attr.identifier.name - CGAbstractStaticBindingMethod.__init__(self, descriptor, name) - - def generate_code(self): - nativeName = CGSpecializedGetter.makeNativeName(self.descriptor, - self.attr) - return CGGetterCall([], self.attr.type, nativeName, self.descriptor, - self.attr) - - -class CGGenericSetter(CGAbstractBindingMethod): - """ - A class for generating the Rust code for an IDL attribute setter. - """ - def __init__(self, descriptor, lenientThis=False): - args = [Argument('*mut JSContext', 'cx'), Argument('libc::c_uint', 'argc'), - Argument('*mut JSVal', '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 CGGeneric( - "let mut undef = UndefinedValue();\n" - "let argv: *mut JSVal = if argc != 0 { JS_ARGV(cx, vp) } else { &mut undef as *mut JSVal };\n" - "let info: *const JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n" - "if CallJitPropertyOp(info, cx, obj, this.unsafe_get() as *mut libc::c_void, argv) == 0 {\n" - " return 0;\n" - "}\n" - "*vp = UndefinedValue();\n" - "return 1;") - -class CGSpecializedSetter(CGAbstractExternMethod): - """ - 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('*mut JSContext', 'cx'), - Argument('JSHandleObject', '_obj'), - Argument('*const %s' % descriptor.concreteType, 'this'), - Argument('*mut JSVal', 'argv')] - CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args) - - def definition_body(self): - nativeName = CGSpecializedSetter.makeNativeName(self.descriptor, - self.attr) - return CGWrapper(CGSetterCall([], self.attr.type, nativeName, - self.descriptor, self.attr), - pre="let this = JS::from_raw(this);\n" - "let this = this.root();\n") - - @staticmethod - def makeNativeName(descriptor, attr): - return "Set" + MakeNativeName(attr.identifier.name) - - -class CGStaticSetter(CGAbstractStaticBindingMethod): - """ - A class for generating the C++ code for an IDL static attribute setter. - """ - def __init__(self, descriptor, attr): - self.attr = attr - name = 'set_' + attr.identifier.name - CGAbstractStaticBindingMethod.__init__(self, descriptor, name) - - def generate_code(self): - nativeName = CGSpecializedSetter.makeNativeName(self.descriptor, - self.attr) - checkForArg = CGGeneric( - "let argv = JS_ARGV(cx, vp);\n" - "if (argc == 0) {\n" - " throw_type_error(cx, \"Not enough arguments to %s setter.\");\n" - " return 0;\n" - "}\n" % self.attr.identifier.name) - call = CGSetterCall([], self.attr.type, nativeName, self.descriptor, - self.attr) - return CGList([checkForArg, call]) - - -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 defineJitInfo(self, infoName, opName, infallible): - protoID = "PrototypeList::id::%s as u32" % self.descriptor.name - depth = self.descriptor.interface.inheritanceDepth() - failstr = "true" if infallible else "false" - return ("\n" - "static %s: JSJitInfo = JSJitInfo {\n" - " op: %s as *const u8,\n" - " protoID: %s,\n" - " depth: %s,\n" - " isInfallible: %s, /* False in setters. */\n" - " isConstant: false /* 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 = ("get_%s" % self.member.identifier.name) - getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True) - result = self.defineJitInfo(getterinfo, getter, getterinfal) - if not self.member.readonly: - setterinfo = ("%s_setterinfo" % self.member.identifier.name) - setter = ("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 = ("%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: - # 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 non-ASCII chars for now. Replace all chars other than - # [0-9A-Za-z_] with '_'. - if re.match("[^\x20-\x7E]", value): - raise SyntaxError('Enum value "' + value + '" contains non-ASCII characters') - if re.match("^[0-9]", value): - raise SyntaxError('Enum value "' + value + '" starts with a digit') - value = re.sub(r'[^0-9A-Za-z_]', '_', value) - if re.match("^_[A-Z]|__", value): - raise SyntaxError('Enum value "' + value + '" is reserved by the C++ spec') - if value == "_empty": - raise SyntaxError('"_empty" is not an IDL enum value we support yet') - if value == "": - return "_empty" - return MakeNativeName(value) - -class CGEnum(CGThing): - def __init__(self, enum): - CGThing.__init__(self) - inner = """ -use dom::bindings::conversions::ToJSValConvertible; -use js::jsapi::JSContext; -use js::jsval::JSVal; - -#[repr(uint)] -#[deriving(Encodable, PartialEq)] -pub enum valuelist { - %s -} - -pub static strings: &'static [&'static str] = &[ - %s, -]; - -impl ToJSValConvertible for valuelist { - fn to_jsval(&self, cx: *mut JSContext) -> JSVal { - strings[*self as uint].to_string().to_jsval(cx) - } -} -""" % (",\n ".join(map(getEnumValueName, enum.values())), - ",\n ".join(['"%s"' % val for val in enum.values()])) - - self.cgRoot = CGList([ - CGNamespace.build([enum.identifier.name + "Values"], - CGIndenter(CGGeneric(inner)), public=True), - CGGeneric("pub type %s = self::%sValues::valuelist;\n" % - (enum.identifier.name, enum.identifier.name)), - ]) - - def define(self): - return self.cgRoot.define() - - -def convertConstIDLValueToRust(value): - tag = value.type.tag() - if tag in [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]: - return str(value.value) - - if tag == IDLType.Tags.bool: - return toStringBool(value.value) - - raise TypeError("Const value of unhandled type: " + value.type) - -class CGConstant(CGThing): - def __init__(self, constants): - CGThing.__init__(self) - self.constants = constants - - def define(self): - def stringDecl(const): - name = const.identifier.name - value = convertConstIDLValueToRust(const.value) - return CGGeneric("pub static %s: %s = %s;\n" % (name, builtinNames[const.value.type.tag()], value)) - - return CGIndenter(CGList(stringDecl(m) for m in self.constants)).define() - -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 - typeName = descriptorProvider.getDescriptor(name).nativeType - elif type.isEnum(): - name = type.inner.identifier.name - typeName = name - elif type.isArray() or type.isSequence(): - name = str(type) - #XXXjdm dunno about typeName here - typeName = "/*" + type.name + "*/" - elif type.isDOMString(): - name = type.name - typeName = "DOMString" - elif type.isPrimitive(): - name = type.name - typeName = builtinNames[type.tag()] - else: - name = type.name - typeName = "/*" + type.name + "*/" - - template, _, _, _ = getJSToNativeConversionTemplate( - type, descriptorProvider, failureCode="return Ok(None);", - exceptionCode='return Err(());', - isDefinitelyObject=True) - - assert not type.isObject() - jsConversion = string.Template(template).substitute({ - "val": "value", - }) - jsConversion = CGWrapper(CGGeneric(jsConversion), pre="Ok(Some(", post="))") - - return { - "name": name, - "typeName": typeName, - "jsConversion": jsConversion, - } - -class CGUnionStruct(CGThing): - def __init__(self, type, descriptorProvider): - assert not type.nullable() - assert not type.hasNullableType - - CGThing.__init__(self) - self.type = type - self.descriptorProvider = descriptorProvider - - def define(self): - templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider), - self.type.flatMemberTypes) - enumValues = [ - " e%s(%s)," % (v["name"], v["typeName"]) for v in templateVars - ] - enumConversions = [ - " e%s(ref inner) => inner.to_jsval(cx)," % v["name"] for v in templateVars - ] - return ("""pub enum %s { -%s -} - -impl ToJSValConvertible for %s { - fn to_jsval(&self, cx: *mut JSContext) -> JSVal { - match *self { -%s - } - } -} -""") % (self.type, "\n".join(enumValues), - self.type, "\n".join(enumConversions)) - - -class CGUnionConversionStruct(CGThing): - def __init__(self, type, descriptorProvider): - assert not type.nullable() - assert not type.hasNullableType - - CGThing.__init__(self) - self.type = type - self.descriptorProvider = descriptorProvider - - def from_jsval(self): - memberTypes = self.type.flatMemberTypes - names = [] - conversions = [] - - interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes) - if len(interfaceMemberTypes) > 0: - def get_name(memberType): - if self.type.isGeckoInterface(): - return memberType.inner.identifier.name - - return memberType.name - - def get_match(name): - return ( - "match %s::TryConvertTo%s(cx, value) {\n" - " Err(_) => return Err(()),\n" - " Ok(Some(value)) => return Ok(e%s(value)),\n" - " Ok(None) => (),\n" - "}\n") % (self.type, name, name) - - typeNames = [get_name(memberType) for memberType in interfaceMemberTypes] - interfaceObject = CGList(CGGeneric(get_match(typeName)) for typeName in typeNames) - names.extend(typeNames) - else: - interfaceObject = None - - arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes) - if len(arrayObjectMemberTypes) > 0: - assert len(arrayObjectMemberTypes) == 1 - raise TypeError("Can't handle arrays or sequences in unions.") - else: - arrayObject = None - - dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes) - if len(dateObjectMemberTypes) > 0: - assert len(dateObjectMemberTypes) == 1 - raise TypeError("Can't handle dates in unions.") - else: - dateObject = None - - callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes) - if len(callbackMemberTypes) > 0: - assert len(callbackMemberTypes) == 1 - raise TypeError("Can't handle callbacks in unions.") - 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: - assert False, "Not currently supported" - else: - nonPlatformObject = None - - objectMemberTypes = filter(lambda t: t.isObject(), memberTypes) - if len(objectMemberTypes) > 0: - raise TypeError("Can't handle objects in unions.") - else: - object = None - - hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object - if hasObjectTypes: - assert interfaceObject - templateBody = CGList([interfaceObject], "\n") - conversions.append(CGIfWrapper(templateBody, "value.is_object()")) - - otherMemberTypes = [ - t for t in memberTypes if t.isPrimitive() or t.isString() or t.isEnum() - ] - if len(otherMemberTypes) > 0: - assert len(otherMemberTypes) == 1 - memberType = otherMemberTypes[0] - if memberType.isEnum(): - name = memberType.inner.identifier.name - else: - name = memberType.name - match = ( - "match %s::TryConvertTo%s(cx, value) {\n" - " Err(_) => return Err(()),\n" - " Ok(Some(value)) => return Ok(e%s(value)),\n" - " Ok(None) => (),\n" - "}\n") % (self.type, name, name) - conversions.append(CGGeneric(match)) - names.append(name) - - conversions.append(CGGeneric( - "throw_not_in_union(cx, \"%s\");\n" - "Err(())" % ", ".join(names))) - method = CGWrapper( - CGIndenter(CGList(conversions, "\n\n")), - pre="fn from_jsval(cx: *mut JSContext, value: JSVal, _option: ()) -> Result<%s, ()> {\n" % self.type, - post="\n}") - return CGWrapper( - CGIndenter(method), - pre="impl FromJSValConvertible<()> for %s {\n" % self.type, - post="\n}") - - def try_method(self, t): - templateVars = getUnionTypeTemplateVars(t, self.descriptorProvider) - returnType = "Result<Option<%s>, ()>" % templateVars["typeName"] - jsConversion = templateVars["jsConversion"] - - return CGWrapper( - CGIndenter(jsConversion, 4), - pre="fn TryConvertTo%s(cx: *mut JSContext, value: JSVal) -> %s {\n" % (t.name, returnType), - post="\n}") - - def define(self): - from_jsval = self.from_jsval() - methods = CGIndenter(CGList([ - self.try_method(t) for t in self.type.flatMemberTypes - ], "\n\n")) - return """ -%s - -impl %s { -%s -} -""" % (from_jsval.define(), self.type, methods.define()) - - -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='pub'): - 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, - breakAfterReturnDecl="\n", - breakAfterSelf="\n", override=False): - """ - override indicates whether to flag the method as MOZ_OVERRIDE - """ - assert not override or virtual - self.returnType = returnType - self.args = args - self.inline = False - self.static = static - self.virtual = virtual - self.const = const - self.bodyInHeader = True - self.templateArgs = templateArgs - self.body = body - self.breakAfterReturnDecl = breakAfterReturnDecl - self.breakAfterSelf = breakAfterSelf - self.override = override - 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 = '<%s>' % ', '.join(self.templateArgs) \ - if self.bodyInHeader and self.templateArgs else '' - args = ', '.join([a.declare() for a in self.args]) - if self.bodyInHeader: - body = CGIndenter(CGGeneric(self.getBody())).define() - body = ' {\n' + body + '\n}' - else: - body = ';' - - return string.Template("${decorators}%s" - "${visibility}fn ${name}${templateClause}(${args})${returnType}${const}${override}${body}%s" % - (self.breakAfterReturnDecl, self.breakAfterSelf) - ).substitute({ - 'templateClause': templateClause, - 'decorators': self.getDecorators(True), - 'returnType': (" -> %s" % self.returnType) if self.returnType else "", - 'name': self.name, - 'const': ' const' if self.const else '', - 'override': ' MOZ_OVERRIDE' if self.override else '', - 'args': args, - 'body': body, - 'visibility': self.visibility + ' ' if self.visibility is not 'priv' else '' - }) - - def define(self, cgClass): - pass - -class ClassUsingDeclaration(ClassItem): - """" - Used for importing a name from a base class into a CGClass - - baseClass is the name of the base class to import the name from - - name is the name to import - - visibility determines the visibility of the name (public, - protected, private), defaults to public. - """ - def __init__(self, baseClass, name, visibility='public'): - self.baseClass = baseClass - ClassItem.__init__(self, name, visibility) - - def declare(self, cgClass): - return string.Template("""using ${baseClass}::${name}; -""").substitute({ 'baseClass': self.baseClass, - 'name': self.name }) - - def define(self, cgClass): - return '' - -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. - - explicit should be True if the constructor should be marked explicit. - - 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 empty. - """ - def __init__(self, args, inline=False, bodyInHeader=False, - visibility="priv", explicit=False, baseConstructors=None, - body=""): - self.args = args - self.inline = False - self.bodyInHeader = bodyInHeader - self.explicit = explicit - self.baseConstructors = baseConstructors or [] - self.body = body - ClassItem.__init__(self, None, visibility) - - def getDecorators(self, declaring): - decorators = [] - if self.explicit: - decorators.append('explicit') - 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.body - if initialize: - items.append(m.name + "(" + initialize + ")") - - if len(items) > 0: - return '\n : ' + ',\n '.join(items) - return '' - - def getBody(self, cgClass): - initializers = [" parent: %s" % str(self.baseConstructors[0])] - return (self.body + ( - "%s {\n" - "%s\n" - "}") % (cgClass.name, '\n'.join(initializers))) - - def declare(self, cgClass): - args = ', '.join([a.declare() for a in self.args]) - body = ' ' + self.getBody(cgClass); - body = stripTrailingWhitespace(body.replace('\n', '\n ')) - if len(body) > 0: - body += '\n' - body = ' {\n' + body + '}' - - return string.Template("""pub fn ${decorators}new(${args}) -> ${className}${body} -""").substitute({ 'decorators': self.getDecorators(True), - 'className': cgClass.getNameString(), - 'args': args, - 'body': body }) - - def define(self, cgClass): - if self.bodyInHeader: - return '' - - args = ', '.join([a.define() 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}} -""").substitute({ 'decorators': self.getDecorators(False), - 'className': cgClass.getNameString(), - 'args': args, - 'initializationList': self.getInitializationList(cgClass), - 'body': body }) - -class ClassDestructor(ClassItem): - """ - Used for adding a destructor to a CGClass. - - inline should be True if the destructor 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 destructor (public, - protected, private), defaults to private. - - body contains a string with the code for the destructor, defaults to empty. - - virtual determines whether the destructor is virtual, defaults to False. - """ - def __init__(self, inline=False, bodyInHeader=False, - visibility="private", body='', virtual=False): - self.inline = inline or bodyInHeader - self.bodyInHeader = bodyInHeader - self.body = body - self.virtual = virtual - ClassItem.__init__(self, None, visibility) - - def getDecorators(self, declaring): - decorators = [] - if self.virtual and declaring: - decorators.append('virtual') - if self.inline and declaring: - decorators.append('inline') - if decorators: - return ' '.join(decorators) + ' ' - return '' - - def getBody(self): - return self.body - - def declare(self, cgClass): - if self.bodyInHeader: - body = ' ' + self.getBody(); - body = stripTrailingWhitespace(body.replace('\n', '\n ')) - if len(body) > 0: - body += '\n' - body = '\n{\n' + body + '}' - else: - body = ';' - - return string.Template("""${decorators}~${className}()${body} -""").substitute({ 'decorators': self.getDecorators(True), - 'className': cgClass.getNameString(), - 'body': body }) - - def define(self, cgClass): - if self.bodyInHeader: - return '' - - body = ' ' + self.getBody() - body = '\n' + stripTrailingWhitespace(body.replace('\n', '\n ')) - if len(body) > 0: - body += '\n' - - return string.Template("""${decorators} -${className}::~${className}() -{${body}} -""").substitute({ 'decorators': self.getDecorators(False), - 'className': cgClass.getNameString(), - 'body': body }) - -class ClassMember(ClassItem): - def __init__(self, name, type, visibility="priv", 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' % (self.visibility, self.name, self.type) - - 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 not self.values or 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 ClassUnion(ClassItem): - def __init__(self, name, entries, visibility="public"): - self.entries = [entry + ";" for entry in entries] - ClassItem.__init__(self, name, visibility) - - def declare(self, cgClass): - return 'union %s\n{\n %s\n};\n' % (self.name, '\n '.join(self.entries)) - - def define(self, cgClass): - # Only goes in the header - return '' - -class CGClass(CGThing): - def __init__(self, name, bases=[], members=[], constructors=[], - destructor=None, methods=[], - typedefs = [], enums=[], unions=[], templateArgs=[], - templateSpecialization=[], isStruct=False, - disallowCopyConstruction=False, indent='', - decorators='', - extradeclarations='', - extradefinitions=''): - CGThing.__init__(self) - self.name = name - self.bases = bases - self.members = members - self.constructors = constructors - # We store our single destructor in a list, since all of our - # code wants lists of members. - self.destructors = [destructor] if destructor else [] - self.methods = methods - self.typedefs = typedefs - self.enums = enums - self.unions = unions - self.templateArgs = templateArgs - self.templateSpecialization = templateSpecialization - self.isStruct = isStruct - self.disallowCopyConstruction = disallowCopyConstruction - self.indent = indent - self.decorators = decorators - self.extradeclarations = extradeclarations - self.extradefinitions = extradefinitions - - def getNameString(self): - className = self.name - if self.templateSpecialization: - className = className + \ - '<%s>' % ', '.join([str(a) for a - in self.templateSpecialization]) - return className - - def define(self): - result = '' - if self.templateArgs: - templateArgs = [a.declare() for a in self.templateArgs] - templateArgs = templateArgs[len(self.templateSpecialization):] - result = result + self.indent + 'template <%s>\n' \ - % ','.join([str(a) for a in templateArgs]) - - if self.templateSpecialization: - specialization = \ - '<%s>' % ', '.join([str(a) for a in self.templateSpecialization]) - else: - specialization = '' - - myself = '' - if self.decorators != '': - myself += self.decorators + '\n' - myself += '%spub struct %s%s' % (self.indent, self.name, specialization) - result += myself - - assert len(self.bases) == 1 #XXjdm Can we support multiple inheritance? - - result += '{\n%s\n' % self.indent - - if self.bases: - self.members = [ClassMember("parent", self.bases[0].name, "pub")] + self.members - - result += CGIndenter(CGGeneric(self.extradeclarations), - len(self.indent)).define() - - def declareMembers(cgClass, memberList): - result = '' - - for member in memberList: - declaration = member.declare(cgClass) - declaration = CGIndenter(CGGeneric(declaration)).define() - result = result + declaration - return result - - if self.disallowCopyConstruction: - class DisallowedCopyConstructor(object): - def __init__(self): - self.visibility = "private" - def declare(self, cgClass): - name = cgClass.getNameString() - return ("%s(const %s&) MOZ_DELETE;\n" - "void operator=(const %s) MOZ_DELETE;\n" % (name, name, name)) - disallowedCopyConstructors = [DisallowedCopyConstructor()] - else: - disallowedCopyConstructors = [] - - order = [(self.enums, ''), (self.unions, ''), - (self.typedefs, ''), (self.members, '')] - - for (memberList, separator) in order: - memberString = declareMembers(self, memberList) - if self.indent: - memberString = CGIndenter(CGGeneric(memberString), - len(self.indent)).define() - result = result + memberString - - result += self.indent + '}\n\n' - result += 'impl %s {\n' % self.name - - order = [(self.constructors + disallowedCopyConstructors, '\n'), - (self.destructors, '\n'), (self.methods, '\n)')] - for (memberList, separator) in order: - memberString = declareMembers(self, memberList) - if self.indent: - memberString = CGIndenter(CGGeneric(memberString), - len(self.indent)).define() - result = result + memberString - - result += "}" - return result - -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(operation) - operation = descriptor.operations[operation] - assert len(operation.signatures()) == 1 - signature = operation.signatures()[0] - - (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, _, declType, needsRooting = getJSToNativeConversionTemplate( - argument.type, descriptor, treatNullAs=argument.treatNullAs) - templateValues = { - "val": "(*desc).value", - } - self.cgRoot.prepend(instantiateJSToNativeConversionTemplate( - template, templateValues, declType, argument.identifier.name, - needsRooting)) - elif operation.isGetter(): - self.cgRoot.prepend(CGGeneric("let mut found = false;")) - - def getArguments(self): - def process(arg): - argVal = arg.identifier.name - if arg.type.isGeckoInterface() and not arg.type.unroll().inner.isCallback(): - argVal += ".root_ref()" - return argVal - args = [(a, process(a)) for a in self.arguments] - if self.idlNode.isGetter(): - args.append((FakeArgument(BuiltinTypes[IDLBuiltinType.Types.boolean], - self.idlNode), - "&mut found")) - return args - - def wrap_return_value(self): - if not self.idlNode.isGetter() or self.templateValues is None: - return "" - - wrap = CGGeneric(wrapForType(**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 CGProxyUnwrap(CGAbstractMethod): - def __init__(self, descriptor): - args = [Argument('*mut JSObject', 'obj')] - CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", '*const ' + descriptor.concreteType, args, alwaysInline=True) - - def definition_body(self): - return CGGeneric("""/*if (xpc::WrapperFactory::IsXrayWrapper(obj)) { - obj = js::UnwrapObject(obj); -}*/ -//MOZ_ASSERT(IsProxy(obj)); -let box_ = GetProxyPrivate(obj).to_private() as *const %s; -return box_;""" % self.descriptor.concreteType) - -class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod): - def __init__(self, descriptor): - args = [Argument('*mut JSContext', 'cx'), Argument('*mut JSObject', 'proxy'), - Argument('jsid', 'id'), Argument('bool', 'set'), - Argument('*mut JSPropertyDescriptor', 'desc')] - CGAbstractExternMethod.__init__(self, descriptor, "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 += "let index = GetArrayIndexFromId(cx, id);\n" - - if indexedGetter: - readonly = toStringBool(self.descriptor.operations['IndexedSetter'] is None) - fillDescriptor = "FillPropertyDescriptor(&mut *desc, proxy, %s);\nreturn true;" % readonly - templateValues = {'jsvalRef': '(*desc).value', 'successCode': fillDescriptor} - get = ("if index.is_some() {\n" + - " let index = index.unwrap();\n" + - " let this = UnwrapProxy(proxy);\n" + - " let this = JS::from_raw(this);\n" + - " let this = this.root();\n" + - CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define() + "\n" + - "}\n") - - if indexedSetter or self.descriptor.operations['NamedSetter']: - setOrIndexedGet += "if set != 0 {\n" - if indexedSetter: - setOrIndexedGet += (" if index.is_some() {\n" + - " let index = index.unwrap();\n") - if not 'IndexedCreator' in self.descriptor.operations: - # FIXME need to check that this is a 'supported property index' - assert False - setOrIndexedGet += (" FillPropertyDescriptor(&mut *desc, proxy, false);\n" + - " return true;\n" + - " }\n") - if self.descriptor.operations['NamedSetter']: - setOrIndexedGet += " if RUST_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(&mut *desc, proxy, 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(&mut *desc, proxy, %s);\nreturn true;" % readonly - templateValues = {'jsvalRef': '(*desc).value', '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 && RUST_JSID_IS_STRING(id) != 0 && !HasPropertyOnPrototype(cx, proxy, id) {\n" + - " let name = jsid_to_str(cx, id);\n" + - " let this = UnwrapProxy(proxy);\n" + - " let this = JS::from_raw(this);\n" + - " let this = this.root();\n" + - CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" + - "}\n") - else: - namedGet = "" - - return setOrIndexedGet + """let expando: *mut JSObject = GetExpandoObject(proxy); -//if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = GetExpandoObject(proxy))) { -if expando.is_not_null() { - let flags = if set { JSRESOLVE_ASSIGNING } else { 0 } | JSRESOLVE_QUALIFIED; - if JS_GetPropertyDescriptorById(cx, expando, id, flags, desc) == 0 { - return false; - } - if (*desc).obj.is_not_null() { - // Pretend the property lives on the wrapper. - (*desc).obj = proxy; - return true; - } -} -""" + namedGet + """ -(*desc).obj = ptr::mut_null(); -return true;""" - - def definition_body(self): - return CGGeneric(self.getBody()) - -class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod): - def __init__(self, descriptor): - args = [Argument('*mut JSContext', 'cx'), Argument('*mut JSObject', 'proxy'), - Argument('jsid', 'id'), - Argument('*const JSPropertyDescriptor', 'desc')] - CGAbstractExternMethod.__init__(self, descriptor, "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 += ("let index = GetArrayIndexFromId(cx, id);\n" + - "if index.is_some() {\n" + - " let index = index.unwrap();\n" + - " let this = UnwrapProxy(proxy);\n" + - " let this = JS::from_raw(this);\n" + - " let this = this.root();\n" + - CGIndenter(CGProxyIndexedSetter(self.descriptor)).define() + - " return true;\n" + - "}\n") - elif self.descriptor.operations['IndexedGetter']: - set += ("if GetArrayIndexFromId(cx, id).is_some() {\n" + - " return false;\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 RUST_JSID_IS_STRING(id) != 0 {\n" + - " let name = jsid_to_str(cx, id);\n" + - " let this = UnwrapProxy(proxy);\n" + - " let this = JS::from_raw(this);\n" + - " let this = this.root();\n" + - CGIndenter(CGProxyNamedSetter(self.descriptor)).define() + "\n" + - "}\n") - elif self.descriptor.operations['NamedGetter']: - set += ("if RUST_JSID_IS_STRING(id) {\n" + - " let name = jsid_to_str(cx, id);\n" + - " let this = UnwrapProxy(proxy);\n" + - " let this = JS::from_raw(this);\n" + - " let this = this.root();\n" + - CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + - " if (found) {\n" - " return false;\n" + - " //return ThrowErrorMessage(cx, MSG_NO_PROPERTY_SETTER, \"%s\");\n" + - " }\n" + - " return true;\n" - "}\n") % (self.descriptor.name) - return set + """return proxyhandler::defineProperty_(%s);""" % ", ".join(a.name for a in self.args) - - def definition_body(self): - return CGGeneric(self.getBody()) - -class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod): - def __init__(self, descriptor): - args = [Argument('*mut JSContext', 'cx'), Argument('*mut JSObject', 'proxy'), - Argument('jsid', 'id'), Argument('*mut bool', 'bp')] - CGAbstractExternMethod.__init__(self, descriptor, "hasOwn", "bool", args) - self.descriptor = descriptor - def getBody(self): - indexedGetter = self.descriptor.operations['IndexedGetter'] - if indexedGetter: - indexed = ("let index = GetArrayIndexFromId(cx, id);\n" + - "if index.is_some() {\n" + - " let index = index.unwrap();\n" + - " let this = UnwrapProxy(proxy);\n" + - " let this = JS::from_raw(this);\n" + - " let this = this.root();\n" + - CGIndenter(CGProxyIndexedGetter(self.descriptor)).define() + "\n" + - " *bp = found;\n" + - " return true;\n" + - "}\n\n") - else: - indexed = "" - - namedGetter = self.descriptor.operations['NamedGetter'] - if namedGetter: - named = ("if RUST_JSID_IS_STRING(id) != 0 && !HasPropertyOnPrototype(cx, proxy, id) {\n" + - " let name = jsid_to_str(cx, id);\n" + - " let this = UnwrapProxy(proxy);\n" + - " let this = JS::from_raw(this);\n" + - " let this = this.root();\n" + - CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" + - " *bp = found;\n" - " return true;\n" - "}\n" + - "\n") - else: - named = "" - - return indexed + """let expando: *mut JSObject = GetExpandoObject(proxy); -if expando.is_not_null() { - let mut b: JSBool = 1; - let ok = JS_HasPropertyById(cx, expando, id, &mut b) != 0; - *bp = b != 0; - if !ok || *bp { - return ok; - } -} - -""" + named + """*bp = false; -return true;""" - - def definition_body(self): - return CGGeneric(self.getBody()) - -class CGDOMJSProxyHandler_get(CGAbstractExternMethod): - def __init__(self, descriptor): - args = [Argument('*mut JSContext', 'cx'), Argument('*mut JSObject', 'proxy'), - Argument('*mut JSObject', 'receiver'), Argument('jsid', 'id'), - Argument('*mut JSVal', 'vp')] - CGAbstractExternMethod.__init__(self, descriptor, "get", "bool", args) - self.descriptor = descriptor - def getBody(self): - getFromExpando = """let expando = GetExpandoObject(proxy); -if expando.is_not_null() { - let mut hasProp = 0; - if JS_HasPropertyById(cx, expando, id, &mut hasProp) == 0 { - return false; - } - - if hasProp != 0 { - return JS_GetPropertyById(cx, expando, id, vp) != 0; - } -}""" - - templateValues = { - 'jsvalRef': '*vp', - 'successCode': 'return true;', - } - - indexedGetter = self.descriptor.operations['IndexedGetter'] - if indexedGetter: - getIndexedOrExpando = ("let index = GetArrayIndexFromId(cx, id);\n" + - "if index.is_some() {\n" + - " let index = index.unwrap();\n" + - " let this = UnwrapProxy(proxy);\n" + - " let this = JS::from_raw(this);\n" + - " let this = this.root();\n" + - CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define()) - 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 and False: #XXXjdm unfinished - getNamed = ("if (JSID_IS_STRING(id)) {\n" + - " let name = jsid_to_str(cx, id);\n" + - " let this = UnwrapProxy(proxy);\n" + - " let this = JS::from_raw(this);\n" + - " let this = this.root();\n" + - CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + - "}\n") % (self.descriptor.concreteType) - else: - getNamed = "" - - return """//MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy), - //"Should not have a XrayWrapper here"); - -%s -let mut found = false; -if !GetPropertyOnPrototype(cx, proxy, id, &mut found, vp) { - return false; -} - -if found { - return true; -} -%s -*vp = UndefinedValue(); -return true;""" % (getIndexedOrExpando, getNamed) - - def definition_body(self): - return CGGeneric(self.getBody()) - -class CGDOMJSProxyHandler_obj_toString(CGAbstractExternMethod): - def __init__(self, descriptor): - args = [Argument('*mut JSContext', 'cx'), Argument('*mut JSObject', 'proxy')] - CGAbstractExternMethod.__init__(self, descriptor, "obj_toString", "*mut JSString", args) - self.descriptor = descriptor - def getBody(self): - stringifier = self.descriptor.operations['Stringifier'] - if stringifier: - nativeName = MakeNativeName(stringifier.identifier.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 """let s = "%s".to_c_str(); - _obj_toString(cx, s.as_ptr())""" % self.descriptor.name - - def definition_body(self): - return CGGeneric(self.getBody()) - -class CGAbstractClassHook(CGAbstractExternMethod): - """ - 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): - CGAbstractExternMethod.__init__(self, descriptor, name, returnType, - args) - - def definition_body_prologue(self): - return CGGeneric("""\ -let this: *const %s = unwrap::<%s>(obj); -""" % (self.descriptor.concreteType, self.descriptor.concreteType)) - - def definition_body(self): - return CGList([ - self.definition_body_prologue(), - self.generate_code(), - ]) - - def generate_code(self): - # Override me - assert(False) - -def finalizeHook(descriptor, hookName, context): - release = """let val = JS_GetReservedSlot(obj, dom_object_slot(obj)); -let _: Box<%s> = mem::transmute(val.to_private()); -debug!("%s finalize: {:p}", this); -""" % (descriptor.concreteType, descriptor.concreteType) - return release - -class CGClassTraceHook(CGAbstractClassHook): - """ - A hook to trace through our native object; used for GC and CC - """ - def __init__(self, descriptor): - args = [Argument('*mut JSTracer', 'trc'), Argument('*mut JSObject', 'obj')] - CGAbstractClassHook.__init__(self, descriptor, TRACE_HOOK_NAME, 'void', - args) - - def generate_code(self): - return CGGeneric("(*this).trace(%s);" % self.args[0].name) - -class CGClassConstructHook(CGAbstractExternMethod): - """ - JS-visible constructor for our objects - """ - def __init__(self, descriptor): - args = [Argument('*mut JSContext', 'cx'), Argument('u32', 'argc'), Argument('*mut JSVal', 'vp')] - CGAbstractExternMethod.__init__(self, descriptor, CONSTRUCT_HOOK_NAME, - 'JSBool', args) - self._ctor = self.descriptor.interface.ctor() - - def define(self): - if not self._ctor: - return "" - return CGAbstractExternMethod.define(self) - - def definition_body(self): - preamble = CGGeneric("""\ -let global = global_object_for_js_object(JS_CALLEE(cx, vp).to_object()); -let global = global.root(); -""") - nativeName = MakeNativeName(self._ctor.identifier.name) - callGenerator = CGMethodCall(["&global.root_ref()"], nativeName, True, - self.descriptor, self._ctor) - return CGList([preamble, callGenerator]) - -class CGClassFinalizeHook(CGAbstractClassHook): - """ - A hook for finalize, used to release our native object. - """ - def __init__(self, descriptor): - args = [Argument('*mut JSFreeOp', 'fop'), Argument('*mut JSObject', 'obj')] - CGAbstractClassHook.__init__(self, descriptor, FINALIZE_HOOK_NAME, - 'void', args) - - def generate_code(self): - return CGGeneric(finalizeHook(self.descriptor, self.name, self.args[0].name)) - -class CGDOMJSProxyHandlerDOMClass(CGThing): - def __init__(self, descriptor): - CGThing.__init__(self) - self.descriptor = descriptor - - def define(self): - return """ -static Class: DOMClass = """ + DOMClass(self.descriptor) + """; - -""" - - -class CGInterfaceTrait(CGThing): - def __init__(self, descriptor): - CGThing.__init__(self) - - def argument_type(ty, optional=False, defaultValue=None, variadic=False): - _, _, declType, _ = getJSToNativeConversionTemplate( - ty, descriptor, isArgument=True) - - if variadic: - declType = CGWrapper(declType, pre="Vec<", post=">") - elif optional and not defaultValue: - declType = CGWrapper(declType, pre="Option<", post=">") - - if ty.isGeckoInterface() and not (ty.nullable() or optional): - declType = CGWrapper(declType, pre="&") - elif ty.isDictionary(): - declType = CGWrapper(declType, pre="&") - - return declType.define() - - def attribute_arguments(needCx, argument=None): - if needCx: - yield "cx", "*mut JSContext" - - if argument: - yield "value", argument_type(argument) - - def method_arguments(returnType, arguments, trailing=None): - if needCx(returnType, arguments, True): - yield "cx", "*mut JSContext" - - for argument in arguments: - ty = argument_type(argument.type, argument.optional, - argument.defaultValue, argument.variadic) - yield CGDictionary.makeMemberName(argument.identifier.name), ty - - if trailing: - yield trailing - - def return_type(rettype, infallible): - result = getRetvalDeclarationForType(rettype, descriptor) - if not infallible: - result = CGWrapper(result, pre="Fallible<", post=">") - return result.define() - - def members(): - for m in descriptor.interface.members: - if m.isMethod() and not m.isStatic(): - name = CGSpecializedMethod.makeNativeName(descriptor, m) - infallible = 'infallible' in descriptor.getExtendedAttributes(m) - for idx, (rettype, arguments) in enumerate(m.signatures()): - arguments = method_arguments(rettype, arguments) - rettype = return_type(rettype, infallible) - yield name + ('_' * idx), arguments, rettype - elif m.isAttr() and not m.isStatic(): - name = CGSpecializedGetter.makeNativeName(descriptor, m) - infallible = 'infallible' in descriptor.getExtendedAttributes(m, getter=True) - needCx = typeNeedsCx(m.type) - yield name, attribute_arguments(needCx), return_type(m.type, infallible) - - if not m.readonly: - name = CGSpecializedSetter.makeNativeName(descriptor, m) - infallible = 'infallible' in descriptor.getExtendedAttributes(m, setter=True) - if infallible: - rettype = "()" - else: - rettype = "ErrorResult" - yield name, attribute_arguments(needCx, m.type), rettype - - if descriptor.proxy: - for name, operation in descriptor.operations.iteritems(): - if not operation: - continue - - assert len(operation.signatures()) == 1 - rettype, arguments = operation.signatures()[0] - - infallible = 'infallible' in descriptor.getExtendedAttributes(operation) - arguments = method_arguments(rettype, arguments, ("found", "&mut bool")) - rettype = return_type(rettype, infallible) - yield name, arguments, rettype - - def fmt(arguments): - return "".join(", %s: %s" % argument for argument in arguments) - - methods = CGList([ - CGGeneric("fn %s(&self%s) -> %s;\n" % (name, fmt(arguments), rettype)) - for name, arguments, rettype in members() - ], "") - self.cgRoot = CGWrapper(CGIndenter(methods), - pre="pub trait %sMethods {\n" % descriptor.interface.identifier.name, - post="}") - - def define(self): - return self.cgRoot.define() - - -class CGDescriptor(CGThing): - def __init__(self, descriptor): - CGThing.__init__(self) - - assert not descriptor.interface.isCallback() - - cgThings = [] - cgThings.append(CGGetProtoObjectMethod(descriptor)) - if descriptor.interface.hasInterfaceObject(): - # https://github.com/mozilla/servo/issues/2665 - # cgThings.append(CGGetConstructorObjectMethod(descriptor)) - pass - - (hasMethod, hasGetter, hasLenientGetter, - hasSetter, hasLenientSetter) = False, False, False, False, False - for m in descriptor.interface.members: - if m.isMethod() and not m.isIdentifierLess(): - if m.isStatic(): - assert descriptor.interface.hasInterfaceObject() - cgThings.append(CGStaticMethod(descriptor, m)) - else: - cgThings.append(CGSpecializedMethod(descriptor, m)) - cgThings.append(CGMemberJITInfo(descriptor, m)) - hasMethod = True - elif m.isAttr(): - if m.isStatic(): - assert descriptor.interface.hasInterfaceObject() - cgThings.append(CGStaticGetter(descriptor, m)) - else: - cgThings.append(CGSpecializedGetter(descriptor, m)) - if m.hasLenientThis(): - hasLenientGetter = True - else: - hasGetter = True - - if not m.readonly: - if m.isStatic(): - assert descriptor.interface.hasInterfaceObject() - cgThings.append(CGStaticSetter(descriptor, m)) - else: - cgThings.append(CGSpecializedSetter(descriptor, m)) - if m.hasLenientThis(): - hasLenientSetter = True - else: - hasSetter = True - - if not m.isStatic(): - cgThings.append(CGMemberJITInfo(descriptor, m)) - if hasMethod: - cgThings.append(CGGenericMethod(descriptor)) - if hasGetter: - cgThings.append(CGGenericGetter(descriptor)) - if hasLenientGetter: - pass - if hasSetter: - cgThings.append(CGGenericSetter(descriptor)) - if hasLenientSetter: - pass - - if descriptor.concrete: - cgThings.append(CGClassFinalizeHook(descriptor)) - cgThings.append(CGClassTraceHook(descriptor)) - - if descriptor.interface.hasInterfaceObject(): - cgThings.append(CGClassConstructHook(descriptor)) - cgThings.append(CGInterfaceObjectJSClass(descriptor)) - - cgThings.append(CGPrototypeJSClass(descriptor)) - - properties = PropertyArrays(descriptor) - cgThings.append(CGGeneric(str(properties))) - cgThings.append(CGNativeProperties(descriptor, properties)) - cgThings.append(CGNativePropertyHooks(descriptor, properties)) - cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties)) - - cgThings.append(CGNamespace.build([descriptor.name + "Constants"], - CGConstant(m for m in descriptor.interface.members if m.isConst()), - public=True)) - - if descriptor.interface.hasInterfaceObject(): - cgThings.append(CGDefineDOMInterfaceMethod(descriptor)) - - if descriptor.proxy: - cgThings.append(CGDefineProxyHandler(descriptor)) - - if descriptor.concrete: - if descriptor.proxy: - #cgThings.append(CGProxyIsProxy(descriptor)) - cgThings.append(CGProxyUnwrap(descriptor)) - cgThings.append(CGDOMJSProxyHandlerDOMClass(descriptor)) - cgThings.append(CGDOMJSProxyHandler_getOwnPropertyDescriptor(descriptor)) - cgThings.append(CGDOMJSProxyHandler_obj_toString(descriptor)) - cgThings.append(CGDOMJSProxyHandler_get(descriptor)) - cgThings.append(CGDOMJSProxyHandler_hasOwn(descriptor)) - if descriptor.operations['IndexedSetter'] or descriptor.operations['NamedSetter']: - cgThings.append(CGDOMJSProxyHandler_defineProperty(descriptor)) - - #cgThings.append(CGDOMJSProxyHandler(descriptor)) - #cgThings.append(CGIsMethod(descriptor)) - pass - else: - cgThings.append(CGDOMJSClass(descriptor)) - pass - - cgThings.append(CGWrapMethod(descriptor)) - - cgThings.append(CGIDLInterface(descriptor)) - cgThings.append(CGInterfaceTrait(descriptor)) - - cgThings = CGList(cgThings, "\n") - cgThings = CGWrapper(cgThings, pre='\n', post='\n') - #self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name), - # cgThings), - # post='\n') - self.cgRoot = cgThings - - def define(self): - return self.cgRoot.define() - -class CGNamespacedEnum(CGThing): - def __init__(self, namespace, enumName, names, values, comment="", deriving=""): - - 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 = ' + str(len(entries))) - - # Indent. - entries = [' ' + e for e in entries] - - # Build the enum body. - enumstr = comment + 'pub enum %s {\n%s\n}\n' % (enumName, ',\n'.join(entries)) - if deriving: - enumstr = ('#[deriving(%s)]\n' % deriving) + enumstr - curr = CGGeneric(enumstr) - - # Add some whitespace padding. - curr = CGWrapper(curr, pre='\n',post='\n') - - # Add the namespace. - curr = CGNamespace(namespace, curr, public=True) - - # Add the typedef - #typedef = '\ntypedef %s::%s %s;\n\n' % (namespace, enumName, enumName) - #curr = CGList([curr, CGGeneric(typedef)]) - - # Save the result. - self.node = curr - - def define(self): - return self.node.define() - -class CGDictionary(CGThing): - def __init__(self, dictionary, descriptorProvider): - self.dictionary = dictionary; - 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 - self.memberInfo = [ - (member, - getJSToNativeConversionTemplate(member.type, - descriptorProvider, - isMember="Dictionary", - defaultValue=member.defaultValue, - failureCode="return Err(());", - exceptionCode="return Err(());")) - for member in dictionary.members ] - - def define(self): - if not self.generatable: - return "" - return self.struct() + "\n" + self.impl() - - def struct(self): - d = self.dictionary - if d.parent: - inheritance = " pub parent: %s::%s<'a, 'b>,\n" % (self.makeModuleName(d.parent), - self.makeClassName(d.parent)) - else: - inheritance = "" - memberDecls = [" pub %s: %s," % - (self.makeMemberName(m[0].identifier.name), self.getMemberType(m)) - for m in self.memberInfo] - - return (string.Template( - "pub struct ${selfName}<'a, 'b> {\n" + - "${inheritance}" + - "\n".join(memberDecls) + "\n" + - "}").substitute( { "selfName": self.makeClassName(d), - "inheritance": inheritance })) - - def impl(self): - d = self.dictionary - if d.parent: - initParent = ("parent: match %s::%s::new(cx, val) {\n" - " Ok(parent) => parent,\n" - " Err(_) => return Err(()),\n" - "},\n") % (self.makeModuleName(d.parent), - self.makeClassName(d.parent)) - else: - initParent = "" - - def memberInit(memberInfo): - member, _ = memberInfo - name = self.makeMemberName(member.identifier.name) - conversion = self.getMemberConversion(memberInfo) - return CGGeneric("%s: %s,\n" % (name, conversion.define())) - - memberInits = CGList([memberInit(m) for m in self.memberInfo]) - - return string.Template( - "impl<'a, 'b> ${selfName}<'a, 'b> {\n" - " pub fn empty() -> ${selfName}<'a, 'b> {\n" - " ${selfName}::new(ptr::mut_null(), NullValue()).unwrap()\n" - " }\n" - " pub fn new(cx: *mut JSContext, val: JSVal) -> Result<${selfName}<'a, 'b>, ()> {\n" - " let object = if val.is_null_or_undefined() {\n" - " ptr::mut_null()\n" - " } else if val.is_object() {\n" - " val.to_object()\n" - " } else {\n" - " throw_type_error(cx, \"Value not an object.\");\n" - " return Err(());\n" - " };\n" - " Ok(${selfName} {\n" - "${initParent}" - "${initMembers}" - " })\n" - " }\n" - "}").substitute({ - "selfName": self.makeClassName(d), - "initParent": CGIndenter(CGGeneric(initParent), indentLevel=6).define(), - "initMembers": CGIndenter(memberInits, indentLevel=6).define(), - }) - - @staticmethod - def makeDictionaryName(dictionary): - return dictionary.identifier.name - - def makeClassName(self, dictionary): - return self.makeDictionaryName(dictionary) - - @staticmethod - def makeModuleName(dictionary): - name = dictionary.identifier.name - if name.endswith('Init'): - return toBindingNamespace(name.replace('Init', '')) - #XXXjdm This breaks on the test webidl files, sigh. - #raise TypeError("No idea how to find this dictionary's definition: " + name) - return "/* uh oh */ %s" % name - - def getMemberType(self, memberInfo): - member, (_, _, declType, _) = memberInfo - if not member.defaultValue: - declType = CGWrapper(declType, pre="Option<", post=">") - return declType.define() - - def getMemberConversion(self, memberInfo): - def indent(s): - return CGIndenter(CGGeneric(s), 8).define() - - member, (templateBody, default, declType, _) = memberInfo - replacements = { "val": "value" } - conversion = string.Template(templateBody).substitute(replacements) - - assert (member.defaultValue is None) == (default is None) - if not default: - default = "None" - conversion = "Some(%s)" % conversion - - conversion = ( - "match get_dictionary_property(cx, object, \"%s\") {\n" - " Err(()) => return Err(()),\n" - " Ok(Some(value)) => {\n" - "%s\n" - " },\n" - " Ok(None) => {\n" - "%s\n" - " },\n" - "}") % (member.identifier.name, indent(conversion), indent(default)) - - return CGGeneric(conversion) - - @staticmethod - def makeIdName(name): - return name + "_id" - - @staticmethod - def makeMemberName(name): - # Can't use Rust keywords as member names. - if name == "type": - return name + "_" - return name - - @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): - arguments = [ - Argument('*mut JSContext', 'cx'), - Argument('*mut JSObject', 'global'), - ] - CGAbstractMethod.__init__(self, None, 'Register', 'void', arguments, - unsafe=False, pub=True) - self.config = config - - def definition_body(self): - return CGList([ - CGGeneric("codegen::Bindings::%sBinding::DefineDOMInterface(cx, global);" % desc.name) - for desc in self.config.getDescriptors(hasInterfaceObject=True, register=True) - ], "\n") - - -class CGRegisterProxyHandlersMethod(CGAbstractMethod): - def __init__(self, descriptors): - CGAbstractMethod.__init__(self, None, 'RegisterProxyHandlers', 'void', [], - unsafe=True, pub=True) - self.descriptors = descriptors - - def definition_body(self): - return CGList([ - CGGeneric("proxy_handlers[proxies::%s as uint] = codegen::Bindings::%sBinding::DefineProxyHandler();" % (desc.name, desc.name)) - for desc in self.descriptors - ], "\n") - - -class CGRegisterProxyHandlers(CGThing): - def __init__(self, config): - descriptors = config.getDescriptors(proxy=True) - length = len(descriptors) - self.root = CGList([ - CGGeneric("pub static mut proxy_handlers: [*const libc::c_void, ..%d] = [0 as *const libc::c_void, ..%d];" % (length, length)), - CGRegisterProxyHandlersMethod(descriptors), - ], "\n") - - def define(self): - return self.root.define() - - -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, - isCallback=False) - dictionaries = config.getDictionaries(webIDLFile=webIDLFile) - - cgthings = [] - - mainCallbacks = config.getCallbacks(webIDLFile=webIDLFile) - callbackDescriptors = config.getDescriptors(webIDLFile=webIDLFile, - isCallback=True) - - # Do codegen for all the enums - cgthings = [CGEnum(e) for e in config.getEnums(webIDLFile)] - - cgthings.extend([CGDictionary(d, config.getDescriptorProvider()) - for d in dictionaries]) - - # Do codegen for all the callbacks. - cgthings.extend(CGList([CGCallbackFunction(c, config.getDescriptorProvider()), - CGCallbackFunctionImpl(c)], "\n") - for c in mainCallbacks) - - # Do codegen for all the descriptors - cgthings.extend([CGDescriptor(x) for x in descriptors]) - - # Do codegen for all the callback interfaces. - cgthings.extend(CGList([CGCallbackInterface(x), - CGCallbackFunctionImpl(x)], "\n") - for x in callbackDescriptors) - - # 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(['dom'], - # CGWrapper(curr, pre="\n")) - - # Add imports - #XXXjdm This should only import the namespace for the current binding, - # not every binding ever. - curr = CGImports(curr, descriptors, [ - 'js', - 'js::{JS_ARGV, JS_CALLEE, JS_THIS_OBJECT}', - 'js::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IS_DOMJSCLASS}', - 'js::{JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_SHIFT}', - 'js::{JSCLASS_RESERVED_SLOTS_MASK, JSID_VOID, JSJitInfo}', - 'js::{JSPROP_ENUMERATE, JSPROP_NATIVE_ACCESSORS, JSPROP_SHARED}', - 'js::{JSRESOLVE_ASSIGNING, JSRESOLVE_QUALIFIED}', - 'js::jsapi::{JS_CallFunctionValue, JS_GetClass, JS_GetGlobalForObject}', - 'js::jsapi::{JS_GetObjectPrototype, JS_GetProperty, JS_GetPropertyById}', - 'js::jsapi::{JS_GetPropertyDescriptorById, JS_GetReservedSlot}', - 'js::jsapi::{JS_HasProperty, JS_HasPropertyById, JS_IsExceptionPending}', - 'js::jsapi::{JS_NewObject, JS_ObjectIsCallable, JS_SetPrototype}', - 'js::jsapi::{JS_SetReservedSlot, JS_WrapValue, JSBool, JSContext}', - 'js::jsapi::{JSClass, JSFreeOp, JSFunctionSpec, JSHandleObject, jsid}', - 'js::jsapi::{JSNativeWrapper, JSObject, JSPropertyDescriptor, JS_ArrayIterator}', - 'js::jsapi::{JSPropertyOpWrapper, JSPropertySpec, JS_PropertyStub}', - 'js::jsapi::{JSStrictPropertyOpWrapper, JSString, JSTracer, JS_ConvertStub}', - 'js::jsapi::{JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub}', - 'js::jsval::JSVal', - 'js::jsval::{ObjectValue, ObjectOrNullValue, PrivateValue}', - 'js::jsval::{NullValue, UndefinedValue}', - 'js::glue::{CallJitMethodOp, CallJitPropertyOp, CreateProxyHandler}', - 'js::glue::{GetProxyPrivate, NewProxyObject, ProxyTraps}', - 'js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO}', - 'js::glue::{RUST_JS_NumberValue, RUST_JSID_IS_STRING}', - 'js::rust::with_compartment', - 'dom::types::*', - 'dom::bindings', - 'dom::bindings::global::GlobalRef', - 'dom::bindings::js::{JS, JSRef, Root, RootedReference, Temporary}', - 'dom::bindings::js::{OptionalRootable, OptionalRootedRootable, ResultRootable}', - 'dom::bindings::js::{OptionalRootedReference, OptionalOptionalRootedRootable}', - 'dom::bindings::utils::{CreateDOMGlobal, CreateInterfaceObjects2}', - 'dom::bindings::utils::{ConstantSpec, cx_for_dom_object}', - 'dom::bindings::utils::{dom_object_slot, DOM_OBJECT_SLOT, DOMClass}', - 'dom::bindings::utils::{DOMJSClass, JSCLASS_DOM_GLOBAL}', - 'dom::bindings::utils::{FindEnumStringIndex, GetArrayIndexFromId}', - 'dom::bindings::utils::{GetPropertyOnPrototype, GetProtoOrIfaceArray}', - 'dom::bindings::utils::{HasPropertyOnPrototype, IntVal}', - 'dom::bindings::utils::{jsid_to_str}', - 'dom::bindings::utils::global_object_for_js_object', - 'dom::bindings::utils::{Reflectable}', - 'dom::bindings::utils::{squirrel_away_unique}', - 'dom::bindings::utils::{ThrowingConstructor, unwrap, unwrap_jsmanaged}', - 'dom::bindings::utils::VoidVal', - 'dom::bindings::utils::get_dictionary_property', - 'dom::bindings::utils::{NativeProperties, NativePropertyHooks}', - 'dom::bindings::trace::JSTraceable', - 'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}', - 'dom::bindings::callback::{CallSetup,ExceptionHandling}', - 'dom::bindings::callback::{WrapCallThisObject}', - 'dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible}', - 'dom::bindings::conversions::IDLInterface', - 'dom::bindings::conversions::{Default, Empty}', - 'dom::bindings::codegen::*', - 'dom::bindings::codegen::Bindings::*', - 'dom::bindings::codegen::RegisterBindings', - 'dom::bindings::codegen::UnionTypes::*', - 'dom::bindings::error::{FailureUnknown, Fallible, Error, ErrorResult}', - 'dom::bindings::error::throw_dom_exception', - 'dom::bindings::error::throw_type_error', - 'dom::bindings::proxyhandler', - 'dom::bindings::proxyhandler::{_obj_toString, defineProperty}', - 'dom::bindings::proxyhandler::{FillPropertyDescriptor, GetExpandoObject}', - 'dom::bindings::proxyhandler::{delete_, getPropertyDescriptor}', - 'dom::bindings::str::ByteString', - 'page::JSPageInfo', - 'libc', - 'servo_util::str::DOMString', - 'std::mem', - 'std::cmp', - 'std::ptr', - 'std::str', - 'std::num', - ]) - - # Add the auto-generated comment. - curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) - - # Store the final result. - self.root = curr - - def define(self): - return stripTrailingWhitespace(self.root.define()) - -class CGNativeMember(ClassMethod): - def __init__(self, descriptorProvider, member, name, signature, extendedAttrs, - breakAfter=True, passJSBitsAsNeeded=True, visibility="public", - jsObjectsArePtr=False, variadicIsSequence=False): - """ - If jsObjectsArePtr is true, typed arrays and "object" will be - passed as JSObject*. - - If passJSBitsAsNeeded is false, we don't automatically pass in a - JSContext* or a JSObject* based on the return and argument types. - """ - self.descriptorProvider = descriptorProvider - self.member = member - self.extendedAttrs = extendedAttrs - self.passJSBitsAsNeeded = passJSBitsAsNeeded - self.jsObjectsArePtr = jsObjectsArePtr - self.variadicIsSequence = variadicIsSequence - breakAfterSelf = "\n" if breakAfter else "" - ClassMethod.__init__(self, name, - self.getReturnType(signature[0], False), - self.getArgs(signature[0], signature[1]), - static=member.isStatic(), - # Mark our getters, which are attrs that - # have a non-void return type, as const. - const=(not member.isStatic() and member.isAttr() and - not signature[0].isVoid()), - breakAfterReturnDecl=" ", - breakAfterSelf=breakAfterSelf, - visibility=visibility) - - def getReturnType(self, type, isMember): - return self.getRetvalInfo(type, isMember)[0] - - def getRetvalInfo(self, type, isMember): - """ - Returns a tuple: - - The first element is the type declaration for the retval - - The second element is a template for actually returning a value stored in - "${declName}". This means actually returning it if - we're not outparam, else assigning to the "retval" outparam. If - isMember is true, this can be None, since in that case the caller will - never examine this value. - """ - if type.isVoid(): - typeDecl, template = "", "" - elif type.isPrimitive() and type.tag() in builtinNames: - result = CGGeneric(builtinNames[type.tag()]) - if type.nullable(): - raise TypeError("Nullable primitives are not supported here.") - - typeDecl, template = result.define(), "return Ok(${declName});" - elif type.isDOMString(): - if isMember: - # No need for a third element in the isMember case - typeDecl, template = "nsString", None - # Outparam - else: - typeDecl, template = "void", "retval = ${declName};" - elif type.isByteString(): - if isMember: - # No need for a third element in the isMember case - typeDecl, template = "nsCString", None - # Outparam - typeDecl, template = "void", "retval = ${declName};" - elif type.isEnum(): - enumName = type.unroll().inner.identifier.name - if type.nullable(): - enumName = CGTemplatedType("Nullable", - CGGeneric(enumName)).define() - typeDecl, template = enumName, "return ${declName};" - elif type.isGeckoInterface(): - iface = type.unroll().inner; - nativeType = self.descriptorProvider.getDescriptor( - iface.identifier.name).nativeType - # Now trim off unnecessary namespaces - nativeType = nativeType.split("::") - if nativeType[0] == "mozilla": - nativeType.pop(0) - if nativeType[0] == "dom": - nativeType.pop(0) - result = CGWrapper(CGGeneric("::".join(nativeType)), post="*") - # Since we always force an owning type for callback return values, - # our ${declName} is an OwningNonNull or nsRefPtr. So we can just - # .forget() to get our already_AddRefed. - typeDecl, template = result.define(), "return ${declName}.forget();" - elif type.isCallback(): - typeDecl, template = \ - ("already_AddRefed<%s>" % type.unroll().identifier.name, - "return ${declName}.forget();") - elif type.isAny(): - typeDecl, template = "JSVal", "return Ok(${declName});" - elif type.isObject(): - typeDecl, template = "JSObject*", "return ${declName};" - elif type.isSpiderMonkeyInterface(): - if type.nullable(): - returnCode = "return ${declName}.IsNull() ? nullptr : ${declName}.Value().Obj();" - else: - returnCode = "return ${declName}.Obj();" - typeDecl, template = "JSObject*", returnCode - elif type.isSequence(): - # If we want to handle sequence-of-sequences return values, we're - # going to need to fix example codegen to not produce nsTArray<void> - # for the relevant argument... - assert not isMember - # Outparam. - if type.nullable(): - returnCode = ("if (${declName}.IsNull()) {\n" - " retval.SetNull();\n" - "} else {\n" - " retval.SetValue().SwapElements(${declName}.Value());\n" - "}") - else: - returnCode = "retval.SwapElements(${declName});" - typeDecl, template = "void", returnCode - elif type.isDate(): - result = CGGeneric("Date") - if type.nullable(): - result = CGTemplatedType("Nullable", result) - typeDecl, template = result.define(), "return ${declName};" - else: - raise TypeError("Don't know how to declare return value for %s" % type) - - if not 'infallible' in self.extendedAttrs: - if typeDecl: - typeDecl = "Fallible<%s>" % typeDecl - else: - typeDecl = "ErrorResult" - if not template: - template = "return Ok(());" - return typeDecl, template - - def getArgs(self, returnType, argList): - args = [self.getArg(arg) for arg in argList] - # Now the outparams - if returnType.isDOMString(): - args.append(Argument("nsString&", "retval")) - if returnType.isByteString(): - args.append(Argument("nsCString&", "retval")) - elif returnType.isSequence(): - nullable = returnType.nullable() - if nullable: - returnType = returnType.inner - # And now the actual underlying type - elementDecl = self.getReturnType(returnType.inner, True) - type = CGTemplatedType("nsTArray", CGGeneric(elementDecl)) - if nullable: - type = CGTemplatedType("Nullable", type) - args.append(Argument("%s&" % type.define(), "retval")) - # The legacycaller thisval - if self.member.isMethod() and self.member.isLegacycaller(): - # If it has an identifier, we can't deal with it yet - assert self.member.isIdentifierLess() - args.insert(0, Argument("JS::Value", "aThisVal")) - # And jscontext bits. - if needCx(returnType, argList, self.passJSBitsAsNeeded): - args.insert(0, Argument("JSContext*", "cx")) - # And if we're static, a global - if self.member.isStatic(): - args.insert(0, Argument("const GlobalObject&", "global")) - return args - - def doGetArgType(self, type, optional, isMember): - """ - The main work of getArgType. Returns a string type decl, whether this - is a const ref, as well as whether the type should be wrapped in - Nullable as needed. - - isMember can be false or one of the strings "Sequence" or "Variadic" - """ - if type.isArray(): - raise TypeError("Can't handle array arguments yet") - - if type.isSequence(): - nullable = type.nullable() - if nullable: - type = type.inner - elementType = type.inner - argType = self.getArgType(elementType, False, "Sequence")[0] - decl = CGTemplatedType("Sequence", argType) - return decl.define(), True, True - - if type.isUnion(): - if type.nullable(): - type = type.inner - return str(type) + "::" + str(type), False, True - - if type.isGeckoInterface() and not type.isCallbackInterface(): - iface = type.unroll().inner - argIsPointer = type.nullable() - forceOwningType = iface.isCallback() or isMember - if argIsPointer: - if (optional or isMember) and forceOwningType: - typeDecl = "nsRefPtr<%s>" - else: - typeDecl = "*%s" - else: - if optional or isMember: - if forceOwningType: - typeDecl = "OwningNonNull<%s>" - else: - typeDecl = "NonNull<%s>" - else: - typeDecl = "%s" - descriptor = self.descriptorProvider.getDescriptor(iface.identifier.name) - return (typeDecl % descriptor.argumentType, - False, False) - - if type.isSpiderMonkeyInterface(): - if self.jsObjectsArePtr: - return "JSObject*", False, False - - return type.name, True, True - - if type.isDOMString(): - declType = "DOMString" - return declType, True, False - - if type.isByteString(): - declType = "nsCString" - return declType, True, False - - if type.isEnum(): - return type.unroll().inner.identifier.name, False, True - - if type.isCallback() or type.isCallbackInterface(): - forceOwningType = optional or isMember - if type.nullable(): - if forceOwningType: - declType = "nsRefPtr<%s>" - else: - declType = "%s*" - else: - if forceOwningType: - declType = "OwningNonNull<%s>" - else: - declType = "%s&" - if type.isCallback(): - name = type.unroll().identifier.name - else: - name = type.unroll().inner.identifier.name - return declType % name, False, False - - if type.isAny(): - # Don't do the rooting stuff for variadics for now - if isMember: - declType = "JS::Value" - else: - declType = "JSVal" - return declType, False, False - - if type.isObject(): - if isMember: - declType = "JSObject*" - else: - declType = "JS::Handle<JSObject*>" - return declType, False, False - - if type.isDictionary(): - typeName = CGDictionary.makeDictionaryName(type.inner) - return typeName, True, True - - if type.isDate(): - return "Date", False, True - - assert type.isPrimitive() - - return builtinNames[type.tag()], False, True - - def getArgType(self, type, optional, isMember): - """ - Get the type of an argument declaration. Returns the type CGThing, and - whether this should be a const ref. - - isMember can be False, "Sequence", or "Variadic" - """ - (decl, ref, handleNullable) = self.doGetArgType(type, optional, - isMember) - decl = CGGeneric(decl) - if handleNullable and type.nullable(): - decl = CGTemplatedType("Nullable", decl) - ref = True - if isMember == "Variadic": - arrayType = "Sequence" if self.variadicIsSequence else "nsTArray" - decl = CGTemplatedType(arrayType, decl) - ref = True - elif optional: - # Note: All variadic args claim to be optional, but we can just use - # empty arrays to represent them not being present. - decl = CGTemplatedType("Option", decl) - ref = False - return (decl, ref) - - def getArg(self, arg): - """ - Get the full argument declaration for an argument - """ - (decl, ref) = self.getArgType(arg.type, - arg.optional and not arg.defaultValue, - "Variadic" if arg.variadic else False) - if ref: - decl = CGWrapper(decl, pre="&") - - return Argument(decl.define(), arg.identifier.name) - -class CGCallback(CGClass): - def __init__(self, idlObject, descriptorProvider, baseName, methods, - getters=[], setters=[]): - self.baseName = baseName - self._deps = idlObject.getDeps() - name = idlObject.identifier.name - # For our public methods that needThisHandling we want most of the - # same args and the same return type as what CallbackMember - # generates. So we want to take advantage of all its - # CGNativeMember infrastructure, but that infrastructure can't deal - # with templates and most especially template arguments. So just - # cheat and have CallbackMember compute all those things for us. - realMethods = [] - for method in methods: - if not method.needThisHandling: - realMethods.append(method) - else: - realMethods.extend(self.getMethodImpls(method)) - CGClass.__init__(self, name, - bases=[ClassBase(baseName)], - constructors=self.getConstructors(), - methods=realMethods+getters+setters, - decorators="#[deriving(PartialEq,Clone,Encodable)]") - - def getConstructors(self): - return [ClassConstructor( - [Argument("*mut JSObject", "aCallback")], - bodyInHeader=True, - visibility="pub", - explicit=False, - baseConstructors=[ - "%s::new(aCallback)" % self.baseName - ])] - - def getMethodImpls(self, method): - assert method.needThisHandling - args = list(method.args) - # Strip out the JSContext*/JSObject* args - # that got added. - assert args[0].name == "cx" and args[0].argType == "*mut JSContext" - assert args[1].name == "aThisObj" and args[1].argType == "*mut JSObject" - args = args[2:] - # Record the names of all the arguments, so we can use them when we call - # the private method. - argnames = [arg.name for arg in args] - argnamesWithThis = ["s.GetContext()", "thisObjJS"] + argnames - argnamesWithoutThis = ["s.GetContext()", "ptr::mut_null()"] + argnames - # Now that we've recorded the argnames for our call to our private - # method, insert our optional argument for deciding whether the - # CallSetup should re-throw exceptions on aRv. - args.append(Argument("ExceptionHandling", "aExceptionHandling", - "ReportExceptions")) - - args[0] = Argument('&' + args[0].argType, args[0].name, args[0].default) - method.args[2] = args[0] - - # And now insert our template argument. - argsWithoutThis = list(args) - args.insert(0, Argument("&JSRef<T>", "thisObj")) - - # And the self argument - method.args.insert(0, Argument(None, "&self")) - args.insert(0, Argument(None, "&self")) - argsWithoutThis.insert(0, Argument(None, "&self")) - - setupCall = ("let s = CallSetup::new(self, aExceptionHandling);\n" - "if s.GetContext().is_null() {\n" - " return Err(FailureUnknown);\n" - "}\n") - - bodyWithThis = string.Template( - setupCall+ - "let thisObjJS = WrapCallThisObject(s.GetContext(), thisObj);\n" - "if thisObjJS.is_null() {\n" - " return Err(FailureUnknown);\n" - "}\n" - "return ${methodName}(${callArgs});").substitute({ - "callArgs" : ", ".join(argnamesWithThis), - "methodName": 'self.' + method.name, - }) - bodyWithoutThis = string.Template( - setupCall + - "return ${methodName}(${callArgs});").substitute({ - "callArgs" : ", ".join(argnamesWithoutThis), - "methodName": 'self.' + method.name, - }) - return [ClassMethod(method.name+'_', method.returnType, args, - bodyInHeader=True, - templateArgs=["T: Reflectable"], - body=bodyWithThis, - visibility='pub'), - ClassMethod(method.name+'__', method.returnType, argsWithoutThis, - bodyInHeader=True, - body=bodyWithoutThis, - visibility='pub'), - method] - - def deps(self): - return self._deps - -# We're always fallible -def callbackGetterName(attr): - return "Get" + MakeNativeName(attr.identifier.name) - -def callbackSetterName(attr): - return "Set" + MakeNativeName(attr.identifier.name) - -class CGCallbackFunction(CGCallback): - def __init__(self, callback, descriptorProvider): - CGCallback.__init__(self, callback, descriptorProvider, - "CallbackFunction", - methods=[CallCallback(callback, descriptorProvider)]) - - def getConstructors(self): - return CGCallback.getConstructors(self) - -class CGCallbackFunctionImpl(CGGeneric): - def __init__(self, callback): - impl = string.Template("""impl CallbackContainer for ${type} { - fn new(callback: *mut JSObject) -> ${type} { - ${type}::new(callback) - } - - fn callback(&self) -> *mut JSObject { - self.parent.callback() - } -} - -impl ToJSValConvertible for ${type} { - fn to_jsval(&self, cx: *mut JSContext) -> JSVal { - self.callback().to_jsval(cx) - } -} -""").substitute({"type": callback.name}) - CGGeneric.__init__(self, impl) - -class CGCallbackInterface(CGCallback): - def __init__(self, descriptor): - iface = descriptor.interface - attrs = [m for m in iface.members if m.isAttr() and not m.isStatic()] - getters = [CallbackGetter(a, descriptor) for a in attrs] - setters = [CallbackSetter(a, descriptor) for a in attrs - if not a.readonly] - methods = [m for m in iface.members - if m.isMethod() and not m.isStatic() and not m.isIdentifierLess()] - methods = [CallbackOperation(m, sig, descriptor) for m in methods - for sig in m.signatures()] - assert not iface.isJSImplemented() or not iface.ctor() - CGCallback.__init__(self, iface, descriptor, "CallbackInterface", - methods, getters=getters, setters=setters) - -class FakeMember(): - def __init__(self): - self.treatNullAs = "Default" - def isStatic(self): - return False - def isAttr(self): - return False - def isMethod(self): - return False - def getExtendedAttribute(self, name): - return None - -class CallbackMember(CGNativeMember): - def __init__(self, sig, name, descriptorProvider, needThisHandling, rethrowContentException=False): - """ - needThisHandling is True if we need to be able to accept a specified - thisObj, False otherwise. - """ - assert not rethrowContentException or not needThisHandling - - self.retvalType = sig[0] - self.originalSig = sig - args = sig[1] - self.argCount = len(args) - if self.argCount > 0: - # Check for variadic arguments - lastArg = args[self.argCount-1] - if lastArg.variadic: - self.argCountStr = ( - "(%d - 1) + %s.Length()" % (self.argCount, - lastArg.identifier.name)) - else: - self.argCountStr = "%d" % self.argCount - self.needThisHandling = needThisHandling - # If needThisHandling, we generate ourselves as private and the caller - # will handle generating public versions that handle the "this" stuff. - visibility = "priv" if needThisHandling else "pub" - self.rethrowContentException = rethrowContentException - # We don't care, for callback codegen, whether our original member was - # a method or attribute or whatnot. Just always pass FakeMember() - # here. - CGNativeMember.__init__(self, descriptorProvider, FakeMember(), - name, (self.retvalType, args), - extendedAttrs={}, - passJSBitsAsNeeded=False, - visibility=visibility, - jsObjectsArePtr=True) - # We have to do all the generation of our body now, because - # the caller relies on us throwing if we can't manage it. - self.exceptionCode= "return Err(FailureUnknown);\n" - self.body = self.getImpl() - - def getImpl(self): - replacements = { - "declRval": self.getRvalDecl(), - "returnResult": self.getResultConversion(), - "convertArgs": self.getArgConversions(), - "doCall": self.getCall(), - "setupCall": self.getCallSetup(), - } - if self.argCount > 0: - replacements["argCount"] = self.argCountStr - replacements["argvDecl"] = string.Template( - "let mut argv = Vec::from_elem(${argCount}, UndefinedValue());\n" - ).substitute(replacements) - else: - # Avoid weird 0-sized arrays - replacements["argvDecl"] = "" - - # Newlines and semicolons are in the values - pre = string.Template( - "${setupCall}" - "${declRval}" - "${argvDecl}").substitute(replacements) - body = string.Template( - "${convertArgs}" - "${doCall}" - "${returnResult}").substitute(replacements) - return CGList([ - CGGeneric(pre), - CGWrapper(CGIndenter(CGGeneric(body)), - pre="with_compartment(cx, self.parent.callback(), || {\n", - post="})") - ], "\n").define() - - def getResultConversion(self): - replacements = { - "val": "rval", - "declName": "rvalDecl", - } - - template, _, declType, needsRooting = getJSToNativeConversionTemplate( - self.retvalType, - self.descriptorProvider, - exceptionCode=self.exceptionCode, - isCallbackReturnValue="Callback", - # XXXbz we should try to do better here - sourceDescription="return value") - - convertType = instantiateJSToNativeConversionTemplate( - template, replacements, declType, "rvalDecl", needsRooting) - - assignRetval = string.Template( - self.getRetvalInfo(self.retvalType, - False)[1]).substitute(replacements) - return convertType.define() + "\n" + assignRetval + "\n" - - def getArgConversions(self): - # Just reget the arglist from self.originalSig, because our superclasses - # just have way to many members they like to clobber, so I can't find a - # safe member name to store it in. - argConversions = [self.getArgConversion(i, arg) for (i, arg) - in enumerate(self.originalSig[1])] - # Do them back to front, so our argc modifications will work - # correctly, because we examine trailing arguments first. - argConversions.reverse(); - # Wrap each one in a scope so that any locals it has don't leak out, and - # also so that we can just "break;" for our successCode. - argConversions = [CGWrapper(CGIndenter(CGGeneric(c)), - pre="loop {\n", - post="\nbreak;}\n") - for c in argConversions] - if self.argCount > 0: - argConversions.insert(0, self.getArgcDecl()) - # And slap them together. - return CGList(argConversions, "\n\n").define() + "\n\n" - - def getArgConversion(self, i, arg): - argval = arg.identifier.name - - if arg.variadic: - argval = argval + "[idx]" - jsvalIndex = "%d + idx" % i - else: - jsvalIndex = "%d" % i - if arg.optional and not arg.defaultValue: - argval += ".clone().unwrap()" - - conversion = wrapForType("*argv.get_mut(%s)" % jsvalIndex, - result=argval, - successCode="continue;" if arg.variadic else "break;") - if arg.variadic: - conversion = string.Template( - "for (uint32_t idx = 0; idx < ${arg}.Length(); ++idx) {\n" + - CGIndenter(CGGeneric(conversion)).define() + "\n" - "}\n" - "break;").substitute({ "arg": arg.identifier.name }) - elif arg.optional and not arg.defaultValue: - conversion = ( - CGIfWrapper(CGGeneric(conversion), - "%s.is_some()" % arg.identifier.name).define() + - " else if (argc == %d) {\n" - " // This is our current trailing argument; reduce argc\n" - " argc -= 1;\n" - "} else {\n" - " *argv.get_mut(%d) = UndefinedValue();\n" - "}" % (i+1, i)) - return conversion - - def getArgs(self, returnType, argList): - args = CGNativeMember.getArgs(self, returnType, argList) - if not self.needThisHandling: - # Since we don't need this handling, we're the actual method that - # will be called, so we need an aRethrowExceptions argument. - if self.rethrowContentException: - args.append(Argument("JSCompartment*", "aCompartment", "nullptr")) - else: - args.append(Argument("ExceptionHandling", "aExceptionHandling", - "ReportExceptions")) - return args - # We want to allow the caller to pass in a "this" object, as - # well as a JSContext. - return [Argument("*mut JSContext", "cx"), - Argument("*mut JSObject", "aThisObj")] + args - - def getCallSetup(self): - if self.needThisHandling: - # It's been done for us already - return "" - callSetup = "CallSetup s(CallbackPreserveColor(), aRv" - if self.rethrowContentException: - # getArgs doesn't add the aExceptionHandling argument but does add - # aCompartment for us. - callSetup += ", RethrowContentExceptions, aCompartment" - else: - callSetup += ", aExceptionHandling" - callSetup += ");" - return string.Template( - "${callSetup}\n" - "JSContext* cx = s.GetContext();\n" - "if (!cx) {\n" - " return Err(FailureUnknown);\n" - "}\n").substitute({ - "callSetup": callSetup, - }) - - def getArgcDecl(self): - return CGGeneric("let mut argc = %su32;" % self.argCountStr); - - @staticmethod - def ensureASCIIName(idlObject): - type = "attribute" if idlObject.isAttr() else "operation" - if re.match("[^\x20-\x7E]", idlObject.identifier.name): - raise SyntaxError('Callback %s name "%s" contains non-ASCII ' - "characters. We can't handle that. %s" % - (type, idlObject.identifier.name, - idlObject.location)) - if re.match('"', idlObject.identifier.name): - raise SyntaxError("Callback %s name '%s' contains " - "double-quote character. We can't handle " - "that. %s" % - (type, idlObject.identifier.name, - idlObject.location)) - -class CallbackMethod(CallbackMember): - def __init__(self, sig, name, descriptorProvider, needThisHandling, rethrowContentException=False): - CallbackMember.__init__(self, sig, name, descriptorProvider, - needThisHandling, rethrowContentException) - def getRvalDecl(self): - return "let mut rval = UndefinedValue();\n" - - def getCall(self): - replacements = { - "thisObj": self.getThisObj(), - "getCallable": self.getCallableDecl() - } - if self.argCount > 0: - replacements["argv"] = "argv.as_mut_ptr()" - replacements["argc"] = "argc" - else: - replacements["argv"] = "nullptr" - replacements["argc"] = "0" - return string.Template("${getCallable}" - "let ok = unsafe {\n" - " JS_CallFunctionValue(cx, ${thisObj}, callable,\n" - " ${argc}, ${argv}, &mut rval)\n" - "};\n" - "if ok == 0 {\n" - " return Err(FailureUnknown);\n" - "}\n").substitute(replacements) - -class CallCallback(CallbackMethod): - def __init__(self, callback, descriptorProvider): - CallbackMethod.__init__(self, callback.signatures()[0], "Call", - descriptorProvider, needThisHandling=True) - - def getThisObj(self): - return "aThisObj" - - def getCallableDecl(self): - return "let callable = ObjectValue(unsafe {&*self.parent.callback()});\n"; - -class CallbackOperationBase(CallbackMethod): - """ - Common class for implementing various callback operations. - """ - def __init__(self, signature, jsName, nativeName, descriptor, singleOperation, rethrowContentException=False): - self.singleOperation = singleOperation - self.methodName = jsName - CallbackMethod.__init__(self, signature, nativeName, descriptor, singleOperation, rethrowContentException) - - def getThisObj(self): - if not self.singleOperation: - return "self.parent.callback()" - # This relies on getCallableDecl declaring a boolean - # isCallable in the case when we're a single-operation - # interface. - return "if isCallable { aThisObj } else { self.parent.callback() }" - - def getCallableDecl(self): - replacements = { - "methodName": self.methodName - } - getCallableFromProp = string.Template( - 'match self.parent.GetCallableProperty(cx, "${methodName}") {\n' - ' Err(_) => return Err(FailureUnknown),\n' - ' Ok(callable) => callable,\n' - '}').substitute(replacements) - if not self.singleOperation: - return 'JS::Rooted<JS::Value> callable(cx);\n' + getCallableFromProp - return ( - 'let isCallable = unsafe { JS_ObjectIsCallable(cx, self.parent.callback()) != 0 };\n' - 'let callable =\n' + - CGIndenter( - CGIfElseWrapper('isCallable', - CGGeneric('unsafe { ObjectValue(&*self.parent.callback()) }'), - CGGeneric(getCallableFromProp))).define() + ';\n') - -class CallbackOperation(CallbackOperationBase): - """ - Codegen actual WebIDL operations on callback interfaces. - """ - def __init__(self, method, signature, descriptor): - self.ensureASCIIName(method) - jsName = method.identifier.name - CallbackOperationBase.__init__(self, signature, - jsName, MakeNativeName(jsName), - descriptor, descriptor.interface.isSingleOperationInterface(), - rethrowContentException=descriptor.interface.isJSImplemented()) - -class CallbackGetter(CallbackMember): - def __init__(self, attr, descriptor): - self.ensureASCIIName(attr) - self.attrName = attr.identifier.name - CallbackMember.__init__(self, - (attr.type, []), - callbackGetterName(attr), - descriptor, - needThisHandling=False, - rethrowContentException=descriptor.interface.isJSImplemented()) - - def getRvalDecl(self): - return "JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());\n" - - def getCall(self): - replacements = { - "attrName": self.attrName - } - return string.Template( - 'if (!JS_GetProperty(cx, mCallback, "${attrName}", &rval)) {\n' - ' return Err(FailureUnknown);\n' - '}\n').substitute(replacements); - -class CallbackSetter(CallbackMember): - def __init__(self, attr, descriptor): - self.ensureASCIIName(attr) - self.attrName = attr.identifier.name - CallbackMember.__init__(self, - (BuiltinTypes[IDLBuiltinType.Types.void], - [FakeArgument(attr.type, attr)]), - callbackSetterName(attr), - descriptor, - needThisHandling=False, - rethrowContentException=descriptor.interface.isJSImplemented()) - - def getRvalDecl(self): - # We don't need an rval - return "" - - def getCall(self): - replacements = { - "attrName": self.attrName, - "argv": "argv.handleAt(0)", - } - return string.Template( - 'MOZ_ASSERT(argv.length() == 1);\n' - 'if (!JS_SetProperty(cx, mCallback, "${attrName}", ${argv})) {\n' - ' return Err(FailureUnknown);\n' - '}\n').substitute(replacements) - - def getArgcDecl(self): - return None - -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(isCallback=False)] - proxies = [d.name for d in config.getDescriptors(proxy=True)] - - return CGList([ - CGGeneric(AUTOGENERATED_WARNING_COMMENT), - CGGeneric("pub static MAX_PROTO_CHAIN_LENGTH: uint = %d;\n\n" % config.maxProtoChainLength), - CGNamespacedEnum('id', 'ID', protos, [0], deriving="PartialEq"), - CGNamespacedEnum('proxies', 'Proxy', proxies, [0], deriving="PartialEq"), - ]) - - - @staticmethod - def RegisterBindings(config): - # TODO - Generate the methods we want - code = CGList([ - CGRegisterProtos(config), - CGRegisterProxyHandlers(config), - ], "\n") - - return CGImports(code, [], [ - 'dom::bindings::codegen', - 'dom::bindings::codegen::PrototypeList::proxies', - 'js::jsapi::JSContext', - 'js::jsapi::JSObject', - 'libc', - ]) - - @staticmethod - def InterfaceTypes(config): - descriptors = [d.name for d in config.getDescriptors(register=True, isCallback=False)] - curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors]) - curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) - return curr - - @staticmethod - def Bindings(config): - - descriptors = (set(d.name + "Binding" for d in config.getDescriptors(register=True)) | - set(d.unroll().module() for d in config.callbacks)) - curr = CGList([CGGeneric("pub mod %s;\n" % name) for name in sorted(descriptors)]) - curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) - return curr - - @staticmethod - def InheritTypes(config): - - descriptors = config.getDescriptors(register=True, isCallback=False) - allprotos = [CGGeneric("#![allow(unused_imports)]\n"), - CGGeneric("use dom::types::*;\n"), - CGGeneric("use dom::bindings::js::{JS, JSRef, Temporary};\n"), - CGGeneric("use dom::bindings::trace::JSTraceable;\n"), - CGGeneric("use dom::bindings::utils::Reflectable;\n"), - CGGeneric("use serialize::{Encodable, Encoder};\n"), - CGGeneric("use js::jsapi::JSTracer;\n\n")] - for descriptor in descriptors: - name = descriptor.name - protos = [CGGeneric('pub trait %s {}\n' % (name + 'Base'))] - for proto in descriptor.prototypeChain: - protos += [CGGeneric('impl %s for %s {}\n' % (proto + 'Base', - descriptor.concreteType))] - derived = [CGGeneric('pub trait %s { fn %s(&self) -> bool; }\n' % - (name + 'Derived', 'is_' + name.lower()))] - for protoName in descriptor.prototypeChain[1:-1]: - protoDescriptor = config.getDescriptor(protoName) - delegate = string.Template('''impl ${selfName} for ${baseName} { - fn ${fname}(&self) -> bool { - self.${parentName}.${fname}() - } -} -''').substitute({'fname': 'is_' + name.lower(), - 'selfName': name + 'Derived', - 'baseName': protoDescriptor.concreteType, - 'parentName': protoDescriptor.prototypeChain[-2].lower()}) - derived += [CGGeneric(delegate)] - derived += [CGGeneric('\n')] - - cast = [CGGeneric(string.Template('''pub trait ${castTraitName} { - #[inline(always)] - fn to_ref<'a, 'b, T: ${toBound}+Reflectable>(base: &'a JSRef<'b, T>) -> Option<&'a JSRef<'b, Self>> { - match base.deref().${checkFn}() { - true => unsafe { Some(base.transmute()) }, - false => None - } - } - - #[inline(always)] - fn to_mut_ref<'a, 'b, T: ${toBound}+Reflectable>(base: &'a mut JSRef<'b, T>) -> Option<&'a mut JSRef<'b, Self>> { - match base.deref().${checkFn}() { - true => unsafe { Some(base.transmute_mut()) }, - false => None - } - } - - #[inline(always)] - fn from_ref<'a, 'b, T: ${fromBound}>(derived: &'a JSRef<'b, T>) -> &'a JSRef<'b, Self> { - unsafe { derived.transmute() } - } - - #[inline(always)] - fn from_mut_ref<'a, 'b, T: ${fromBound}>(derived: &'a mut JSRef<'b, T>) -> &'a mut JSRef<'b, Self> { - unsafe { derived.transmute_mut() } - } - - #[inline(always)] - fn from_temporary<T: ${fromBound}+Reflectable>(derived: Temporary<T>) -> Temporary<Self> { - unsafe { derived.transmute() } - } -} -''').substitute({'checkFn': 'is_' + name.lower(), - 'castTraitName': name + 'Cast', - 'fromBound': name + 'Base', - 'toBound': name + 'Derived'})), - CGGeneric("impl %s for %s {}\n\n" % (name + 'Cast', name))] - - trace = [CGGeneric(string.Template('''impl JSTraceable for ${name} { - fn trace(&self, tracer: *mut JSTracer) { - unsafe { - self.encode(&mut *tracer).ok().expect("failed to encode"); - } - } -} -''').substitute({'name': name}))] - - allprotos += protos + derived + cast + trace - - curr = CGList(allprotos) - curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) - return curr - - @staticmethod - def UnionTypes(config): - - curr = UnionTypes(config.getDescriptors(), - config.getDictionaries(), - config.getCallbacks(), - config) - - # Add the auto-generated comment. - curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) - - # Done. - return curr diff --git a/src/components/script/dom/bindings/codegen/Configuration.py b/src/components/script/dom/bindings/codegen/Configuration.py deleted file mode 100644 index d9be43fd2e6..00000000000 --- a/src/components/script/dom/bindings/codegen/Configuration.py +++ /dev/null @@ -1,341 +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/. - -from WebIDL import IDLInterface - -autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n" - -class Configuration: - """ - Represents global configuration state based on IDL parse data and - the configuration file. - """ - def __init__(self, filename, parseData): - # Read the configuration file. - glbl = {} - execfile(filename, glbl) - config = glbl['DOMInterfaces'] - - # Build descriptors for all the interfaces we have in the parse data. - # This allows callers to specify a subset of interfaces by filtering - # |parseData|. - self.descriptors = [] - self.interfaces = {} - self.maxProtoChainLength = 0; - for thing in parseData: - # Some toplevel things are sadly types, and those have an - # isInterface that doesn't mean the same thing as IDLObject's - # isInterface()... - if not isinstance(thing, IDLInterface): - continue - - iface = thing - self.interfaces[iface.identifier.name] = iface - if iface.identifier.name not in config: - # Completely skip consequential interfaces with no descriptor - # if they have no interface object because chances are we - # don't need to do anything interesting with them. - if iface.isConsequential() and not iface.hasInterfaceObject(): - continue - entry = {} - else: - entry = config[iface.identifier.name] - if not isinstance(entry, list): - assert isinstance(entry, dict) - entry = [entry] - self.descriptors.extend([Descriptor(self, iface, x) for x in entry]) - - # Mark the descriptors for which only a single nativeType implements - # an interface. - for descriptor in self.descriptors: - intefaceName = descriptor.interface.identifier.name - otherDescriptors = [d for d in self.descriptors - if d.interface.identifier.name == intefaceName] - descriptor.uniqueImplementation = len(otherDescriptors) == 1 - - self.enums = [e for e in parseData if e.isEnum()] - self.dictionaries = [d for d in parseData if d.isDictionary()] - self.callbacks = [c for c in parseData if - c.isCallback() and not c.isInterface()] - - # Keep the descriptor list sorted for determinism. - self.descriptors.sort(lambda x,y: cmp(x.name, y.name)) - - def getInterface(self, ifname): - return self.interfaces[ifname] - def getDescriptors(self, **filters): - """Gets the descriptors that match the given filters.""" - curr = self.descriptors - for key, val in filters.iteritems(): - if key == 'webIDLFile': - getter = lambda x: x.interface.filename() - elif key == 'hasInterfaceObject': - getter = lambda x: x.interface.hasInterfaceObject() - elif key == 'isCallback': - getter = lambda x: x.interface.isCallback() - elif key == 'isJSImplemented': - getter = lambda x: x.interface.isJSImplemented() - else: - getter = lambda x: getattr(x, key) - curr = filter(lambda x: getter(x) == val, curr) - return curr - def getEnums(self, webIDLFile): - return filter(lambda e: e.filename() == webIDLFile, self.enums) - - @staticmethod - def _filterForFile(items, webIDLFile=""): - """Gets the items that match the given filters.""" - if not webIDLFile: - return items - - return filter(lambda x: x.filename() == webIDLFile, items) - - def getDictionaries(self, webIDLFile=""): - return self._filterForFile(self.dictionaries, webIDLFile=webIDLFile) - def getCallbacks(self, webIDLFile=""): - return self._filterForFile(self.callbacks, webIDLFile=webIDLFile) - - def getDescriptor(self, interfaceName): - """ - Gets the appropriate descriptor for the given interface name. - """ - iface = self.getInterface(interfaceName) - descriptors = self.getDescriptors(interface=iface) - - # We should have exactly one result. - if len(descriptors) is not 1: - raise NoSuchDescriptorError("For " + interfaceName + " found " + - str(len(matches)) + " matches"); - return descriptors[0] - def getDescriptorProvider(self): - """ - Gets a descriptor provider that can provide descriptors as needed. - """ - return DescriptorProvider(self) - -class NoSuchDescriptorError(TypeError): - def __init__(self, str): - TypeError.__init__(self, str) - -class DescriptorProvider: - """ - A way of getting descriptors for interface names - """ - def __init__(self, config): - self.config = config - - def getDescriptor(self, interfaceName): - """ - Gets the appropriate descriptor for the given interface name given the - context of the current descriptor. - """ - return self.config.getDescriptor(interfaceName) - -class Descriptor(DescriptorProvider): - """ - Represents a single descriptor for an interface. See Bindings.conf. - """ - def __init__(self, config, interface, desc): - DescriptorProvider.__init__(self, config) - self.interface = interface - - # Read the desc, and fill in the relevant defaults. - ifaceName = self.interface.identifier.name - - # Callback types do not use JS smart pointers, so we should not use the - # built-in rooting mechanisms for them. - if self.interface.isCallback(): - self.needsRooting = False - else: - self.needsRooting = True - - self.returnType = desc.get('returnType', "Temporary<%s>" % ifaceName) - self.argumentType = "JSRef<%s>" % ifaceName - self.memberType = "Root<'a, 'b, %s>" % ifaceName - self.nativeType = desc.get('nativeType', 'JS<%s>' % ifaceName) - self.concreteType = desc.get('concreteType', ifaceName) - self.register = desc.get('register', True) - self.outerObjectHook = desc.get('outerObjectHook', 'None') - - # If we're concrete, we need to crawl our ancestor interfaces and mark - # them as having a concrete descendant. - self.concrete = desc.get('concrete', True) - if self.concrete: - self.proxy = False - operations = { - 'IndexedGetter': None, - 'IndexedSetter': None, - 'IndexedCreator': None, - 'IndexedDeleter': None, - 'NamedGetter': None, - 'NamedSetter': None, - 'NamedCreator': None, - 'NamedDeleter': None, - 'Stringifier': None - } - iface = self.interface - while iface: - for m in iface.members: - if not m.isMethod(): - continue - - def addOperation(operation, m): - if not operations[operation]: - operations[operation] = m - def addIndexedOrNamedOperation(operation, m): - self.proxy = True - if m.isIndexed(): - operation = 'Indexed' + operation - else: - assert m.isNamed() - operation = 'Named' + operation - addOperation(operation, m) - - if m.isStringifier(): - addOperation('Stringifier', m) - else: - if m.isGetter(): - addIndexedOrNamedOperation('Getter', m) - if m.isSetter(): - addIndexedOrNamedOperation('Setter', m) - if m.isCreator(): - addIndexedOrNamedOperation('Creator', m) - if m.isDeleter(): - addIndexedOrNamedOperation('Deleter', m) - raise TypeError("deleter specified on %s but we " - "don't support deleters yet" % - self.interface.identifier.name) - - iface.setUserData('hasConcreteDescendant', True) - iface = iface.parent - - if self.proxy: - self.operations = operations - iface = self.interface - while iface: - iface.setUserData('hasProxyDescendant', True) - iface = iface.parent - - self.name = interface.identifier.name - - # self.extendedAttributes is a dict of dicts, keyed on - # all/getterOnly/setterOnly and then on member name. Values are an - # array of extended attributes. - self.extendedAttributes = { 'all': {}, 'getterOnly': {}, 'setterOnly': {} } - - def addExtendedAttribute(attribute, config): - def add(key, members, attribute): - for member in members: - self.extendedAttributes[key].setdefault(member, []).append(attribute) - - if isinstance(config, dict): - for key in ['all', 'getterOnly', 'setterOnly']: - add(key, config.get(key, []), attribute) - elif isinstance(config, list): - add('all', config, attribute) - else: - assert isinstance(config, str) - if config == '*': - iface = self.interface - while iface: - add('all', map(lambda m: m.name, iface.members), attribute) - iface = iface.parent - else: - add('all', [config], attribute) - - # Build the prototype chain. - self.prototypeChain = [] - parent = interface - while parent: - self.prototypeChain.insert(0, parent.identifier.name) - parent = parent.parent - config.maxProtoChainLength = max(config.maxProtoChainLength, - len(self.prototypeChain)) - - def getExtendedAttributes(self, member, getter=False, setter=False): - def maybeAppendInfallibleToAttrs(attrs, throws): - if throws is None: - attrs.append("infallible") - elif throws is True: - pass - else: - raise TypeError("Unknown value for 'Throws'") - - name = member.identifier.name - if member.isMethod(): - attrs = self.extendedAttributes['all'].get(name, []) - throws = member.getExtendedAttribute("Throws") - maybeAppendInfallibleToAttrs(attrs, throws) - return attrs - - assert member.isAttr() - assert bool(getter) != bool(setter) - key = 'getterOnly' if getter else 'setterOnly' - attrs = self.extendedAttributes['all'].get(name, []) + self.extendedAttributes[key].get(name, []) - throws = member.getExtendedAttribute("Throws") - if throws is None: - throwsAttr = "GetterThrows" if getter else "SetterThrows" - throws = member.getExtendedAttribute(throwsAttr) - maybeAppendInfallibleToAttrs(attrs, throws) - return attrs - - def isGlobal(self): - """ - Returns true if this is the primary interface for a global object - of some sort. - """ - return (self.interface.getExtendedAttribute("Global") or - self.interface.getExtendedAttribute("PrimaryGlobal")) - - -# Some utility methods -def getTypesFromDescriptor(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()) - members.extend(descriptor.interface.namedConstructors) - 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 - -def getFlatTypes(types): - retval = set() - for type in types: - type = type.unroll() - if type.isUnion(): - retval |= set(type.flatMemberTypes) - else: - retval.add(type) - return retval - -def getTypesFromDictionary(dictionary): - """ - Get all member types for this dictionary - """ - types = [] - curDict = dictionary - while curDict: - types.extend([m.type for m in curDict.members]) - curDict = curDict.parent - return types - -def getTypesFromCallback(callback): - """ - Get the types this callback depends on: its return type and the - types of its arguments. - """ - sig = callback.signatures()[0] - types = [sig[0]] # Return type - types.extend(arg.type for arg in sig[1]) # Arguments - return types diff --git a/src/components/script/dom/bindings/codegen/DOMJSClass.h b/src/components/script/dom/bindings/codegen/DOMJSClass.h deleted file mode 100644 index 151960b5901..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/DOMJSProxyHandler.cpp b/src/components/script/dom/bindings/codegen/DOMJSProxyHandler.cpp deleted file mode 100644 index af45cc6ed1a..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/DOMJSProxyHandler.h b/src/components/script/dom/bindings/codegen/DOMJSProxyHandler.h deleted file mode 100644 index 394e2dc4d2f..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/ErrorResult.h b/src/components/script/dom/bindings/codegen/ErrorResult.h deleted file mode 100644 index bbd9404a865..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/Errors.msg b/src/components/script/dom/bindings/codegen/Errors.msg deleted file mode 100644 index 81d6624cec8..00000000000 --- a/src/components/script/dom/bindings/codegen/Errors.msg +++ /dev/null @@ -1,30 +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/. */ - -/* - * The format for each error message is: - * - * MSG_DEF(<SYMBOLIC_NAME>, <ARGUMENT_COUNT>, <FORMAT_STRING>) - * - * where - * - * <SYMBOLIC_NAME> is a legal C++ identifer that will be used in the source. - * - * <ARGUMENT_COUNT> is an integer literal specifying the total number of - * replaceable arguments in the following format string. - * - * <FORMAT_STRING> is a string literal, containing <ARGUMENT_COUNT> sequences - * {X} where X is an integer representing the argument number that will - * be replaced with a string value when the error is reported. - */ - -MSG_DEF(MSG_INVALID_ENUM_VALUE, 2, "Value '{0}' is not a valid value for enumeration {1}.") -MSG_DEF(MSG_MISSING_ARGUMENTS, 1, "Not enough arguments to {0}.") -MSG_DEF(MSG_NOT_OBJECT, 0, "Value not an object.") -MSG_DEF(MSG_DOES_NOT_IMPLEMENT_INTERFACE, 1, "Value does not implement interface {0}.") -MSG_DEF(MSG_NOT_IN_UNION, 1, "Value could not be converted to any of: {0}.") -MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, "Illegal constructor.") -MSG_DEF(MSG_NO_PROPERTY_SETTER, 1, "{0} doesn't have an indexed property setter.") -MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, "Non-finite value is out of range for {0}.") -MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, "Value is out of range for {0}.") diff --git a/src/components/script/dom/bindings/codegen/GenerateCSS2PropertiesWebIDL.py b/src/components/script/dom/bindings/codegen/GenerateCSS2PropertiesWebIDL.py deleted file mode 100644 index 1bb50afaee7..00000000000 --- a/src/components/script/dom/bindings/codegen/GenerateCSS2PropertiesWebIDL.py +++ /dev/null @@ -1,26 +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/. - -import sys -import string - -propList = eval(sys.stdin.read()) -props = "" -for [prop, pref] in propList: - extendedAttrs = ["Throws", "TreatNullAs=EmptyString"] - if pref is not "": - extendedAttrs.append("Pref=%s" % pref) - if not prop.startswith("Moz"): - prop = prop[0].lower() + prop[1:] - # Unfortunately, even some of the getters here are fallible - # (e.g. on nsComputedDOMStyle). - props += " [%s] attribute DOMString %s;\n" % (", ".join(extendedAttrs), - prop) - -idlFile = open(sys.argv[1], "r"); -idlTemplate = idlFile.read(); -idlFile.close(); - -print ("/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT */\n\n" + - string.Template(idlTemplate).substitute({ "props": props })) diff --git a/src/components/script/dom/bindings/codegen/GlobalGen.py b/src/components/script/dom/bindings/codegen/GlobalGen.py deleted file mode 100644 index cdca464e029..00000000000 --- a/src/components/script/dom/bindings/codegen/GlobalGen.py +++ /dev/null @@ -1,83 +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/. - -# We do one global pass over all the WebIDL to generate our prototype enum -# and generate information for subsequent phases. - -import sys -sys.path.append("./parser/") -sys.path.append("./ply/") -import os -import cStringIO -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) - code = root.define() - - if replaceFileIfChanged(filename, code): - print "Generating %s" % (filename) - else: - print "%s hasn't changed - not touching it" % (filename) - -def main(): - # Parse arguments. - from optparse import OptionParser - usageString = "usage: %prog [options] webidldir [files]" - o = OptionParser(usage=usageString) - o.add_option("--cachedir", dest='cachedir', default=None, - help="Directory in which to cache lex/parse tables.") - o.add_option("--verbose-errors", action='store_true', default=False, - help="When an error happens, display the Python traceback.") - (options, args) = o.parse_args() - - if len(args) < 2: - o.error(usageString) - - configFile = args[0] - baseDir = args[1] - fileList = args[2:] - - # Parse the WebIDL. - parser = WebIDL.Parser(options.cachedir) - for filename in fileList: - fullPath = os.path.normpath(os.path.join(baseDir, filename)) - f = open(fullPath, 'rb') - lines = f.readlines() - f.close() - parser.parse(''.join(lines), fullPath) - parserResults = parser.finish() - - # Write the parser results out to a pickle. - resultsFile = open('ParserResults.pkl', 'wb') - cPickle.dump(parserResults, resultsFile, -1) - resultsFile.close() - - # Load the configuration. - config = Configuration(configFile, parserResults) - - # Generate the prototype list. - generate_file(config, 'PrototypeList', 'PrototypeList.rs') - - # Generate the common code. - generate_file(config, 'RegisterBindings', 'RegisterBindings.rs') - - # Generate the type list. - generate_file(config, 'InterfaceTypes', 'InterfaceTypes.rs') - - # Generate the type list. - generate_file(config, 'InheritTypes', 'InheritTypes.rs') - - # Generate the module declarations. - generate_file(config, 'Bindings', 'Bindings/mod.rs') - - generate_file(config, 'UnionTypes', 'UnionTypes.rs') - -if __name__ == '__main__': - main() diff --git a/src/components/script/dom/bindings/codegen/Makefile.in b/src/components/script/dom/bindings/codegen/Makefile.in deleted file mode 100644 index 5fef1e77218..00000000000 --- a/src/components/script/dom/bindings/codegen/Makefile.in +++ /dev/null @@ -1,165 +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/. - -DEPTH = @DEPTH@ -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ -FAIL_ON_WARNINGS := 1 - -MODULE = dom -LIBRARY_NAME = dombindings_s -LIBXUL_LIBRARY = 1 -FORCE_STATIC_LIB = 1 -EXPORT_LIBRARY = 1 - -include $(topsrcdir)/config/config.mk - -# Need this to find all our DOM source files. -include $(topsrcdir)/dom/dom-config.mk - -include $(topsrcdir)/dom/webidl/WebIDL.mk - -binding_include_path := mozilla/dom -all_webidl_files = $(webidl_files) $(generated_webidl_files) -# Set exported_binding_headers before adding the test IDL to the mix -exported_binding_headers := $(subst .webidl,Binding.h,$(all_webidl_files)) -# Set linked_binding_cpp_files before adding the test IDL to the mix -linked_binding_cpp_files := $(subst .webidl,Binding.cpp,$(all_webidl_files)) - -all_webidl_files += $(test_webidl_files) - -binding_header_files := $(subst .webidl,Binding.h,$(all_webidl_files)) -binding_cpp_files := $(subst .webidl,Binding.cpp,$(all_webidl_files)) - -globalgen_targets := \ - PrototypeList.h \ - RegisterBindings.h \ - RegisterBindings.cpp \ - UnionTypes.h \ - UnionConversions.h \ - $(NULL) - -CPPSRCS = \ - $(linked_binding_cpp_files) \ - $(filter %.cpp, $(globalgen_targets)) \ - BindingUtils.cpp \ - DOMJSProxyHandler.cpp \ - $(NULL) - -EXPORTS_NAMESPACES = $(binding_include_path) mozilla - -EXPORTS_mozilla = \ - ErrorResult.h \ - $(NULL) - -EXPORTS_$(binding_include_path) = \ - BindingUtils.h \ - DOMJSClass.h \ - DOMJSProxyHandler.h \ - Errors.msg \ - Nullable.h \ - PrimitiveConversions.h \ - PrototypeList.h \ - RegisterBindings.h \ - TypedArray.h \ - UnionConversions.h \ - UnionTypes.h \ - $(exported_binding_headers) \ - $(NULL) - -LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \ - -I$(topsrcdir)/js/xpconnect/wrappers \ - -I$(topsrcdir)/content/canvas/src \ - -I$(topsrcdir)/content/html/content/src - -include $(topsrcdir)/config/rules.mk - -# If you change bindinggen_dependencies here, change it in -# dom/bindings/test/Makefile.in too. -bindinggen_dependencies := \ - BindingGen.py \ - Bindings.conf \ - Configuration.py \ - Codegen.py \ - parser/WebIDL.py \ - ParserResults.pkl \ - $(GLOBAL_DEPS) \ - $(NULL) - -CSS2Properties.webidl: $(topsrcdir)/layout/style/nsCSSPropList.h \ - $(topsrcdir)/layout/style/nsCSSPropAliasList.h \ - $(webidl_base)/CSS2Properties.webidl.in \ - $(webidl_base)/CSS2PropertiesProps.h \ - $(srcdir)/GenerateCSS2PropertiesWebIDL.py \ - $(GLOBAL_DEPS) - $(CPP) $(DEFINES) $(ACDEFINES) -I$(topsrcdir)/layout/style $(webidl_base)/CSS2PropertiesProps.h | \ - $(PYTHON) \ - $(srcdir)/GenerateCSS2PropertiesWebIDL.py $(webidl_base)/CSS2Properties.webidl.in > CSS2Properties.webidl - -$(webidl_files): %: $(webidl_base)/% - $(INSTALL) $(IFLAGS1) $(webidl_base)/$* . - -$(test_webidl_files): %: $(srcdir)/test/% - $(INSTALL) $(IFLAGS1) $(srcdir)/test/$* . - -$(binding_header_files): %Binding.h: $(bindinggen_dependencies) \ - %.webidl \ - $(NULL) - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - $(PLY_INCLUDE) -I$(srcdir)/parser \ - $(srcdir)/BindingGen.py header \ - $(srcdir)/Bindings.conf $*Binding \ - $*.webidl - -$(binding_cpp_files): %Binding.cpp: $(bindinggen_dependencies) \ - %.webidl \ - $(NULL) - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - $(PLY_INCLUDE) -I$(srcdir)/parser \ - $(srcdir)/BindingGen.py cpp \ - $(srcdir)/Bindings.conf $*Binding \ - $*.webidl - -$(globalgen_targets): ParserResults.pkl - -CACHE_DIR = _cache - -globalgen_dependencies := \ - GlobalGen.py \ - Bindings.conf \ - Configuration.py \ - Codegen.py \ - parser/WebIDL.py \ - $(CACHE_DIR)/.done \ - $(GLOBAL_DEPS) \ - $(NULL) - -$(CACHE_DIR)/.done: - $(MKDIR) -p $(CACHE_DIR) - @$(TOUCH) $@ - -ParserResults.pkl: $(globalgen_dependencies) \ - $(all_webidl_files) - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - $(PLY_INCLUDE) -I$(srcdir)/parser \ - $(srcdir)/GlobalGen.py $(srcdir)/Bindings.conf . \ - --cachedir=$(CACHE_DIR) \ - $(all_webidl_files) - -GARBAGE += \ - $(binding_header_files) \ - $(binding_cpp_files) \ - $(all_webidl_files) \ - $(globalgen_targets) \ - ParserResults.pkl \ - webidlyacc.py \ - parser.out \ - $(NULL) - -# Make sure all binding header files are created during the export stage, so we -# don't have issues with .cpp files being compiled before we've generated the -# headers they depend on. This is really only needed for the test files, since -# the non-test headers are all exported above anyway. -export:: $(binding_header_files) diff --git a/src/components/script/dom/bindings/codegen/Nullable.h b/src/components/script/dom/bindings/codegen/Nullable.h deleted file mode 100644 index 8b2cc08642b..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/PrimitiveConversions.h b/src/components/script/dom/bindings/codegen/PrimitiveConversions.h deleted file mode 100644 index 40c27425772..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/RegisterBindings.h b/src/components/script/dom/bindings/codegen/RegisterBindings.h deleted file mode 100644 index 7d83a747cc3..00000000000 --- a/src/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/src/components/script/dom/bindings/codegen/TypedArray.h b/src/components/script/dom/bindings/codegen/TypedArray.h deleted file mode 100644 index 2a6f17bcb96..00000000000 --- a/src/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 */ diff --git a/src/components/script/dom/bindings/codegen/crashtests/769464.html b/src/components/script/dom/bindings/codegen/crashtests/769464.html deleted file mode 100644 index 84d6dbc08b4..00000000000 --- a/src/components/script/dom/bindings/codegen/crashtests/769464.html +++ /dev/null @@ -1,11 +0,0 @@ -<!DOCTYPE html> -<script> - -function boom() -{ - window.getComputedStyle(new Worker("404.js")); -} - -window.addEventListener("load", boom, false); - -</script> diff --git a/src/components/script/dom/bindings/codegen/crashtests/crashtests.list b/src/components/script/dom/bindings/codegen/crashtests/crashtests.list deleted file mode 100644 index cb954bd91fc..00000000000 --- a/src/components/script/dom/bindings/codegen/crashtests/crashtests.list +++ /dev/null @@ -1 +0,0 @@ -asserts-if(cocoaWidget,0-1) load 769464.html diff --git a/src/components/script/dom/bindings/codegen/parser/README b/src/components/script/dom/bindings/codegen/parser/README deleted file mode 100644 index 94b64b88459..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/README +++ /dev/null @@ -1 +0,0 @@ -A WebIDL parser written in Python to be used in Mozilla.
\ No newline at end of file diff --git a/src/components/script/dom/bindings/codegen/parser/UPSTREAM b/src/components/script/dom/bindings/codegen/parser/UPSTREAM deleted file mode 100644 index 7ac5899379e..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/UPSTREAM +++ /dev/null @@ -1 +0,0 @@ -http://dev.w3.org/cvsweb/~checkout~/2006/webapi/WebIDL/Overview.html?rev=1.409;content-type=text%2Fhtml%3b+charset=utf-8
\ No newline at end of file diff --git a/src/components/script/dom/bindings/codegen/parser/WebIDL.py b/src/components/script/dom/bindings/codegen/parser/WebIDL.py deleted file mode 100644 index 32f80e82c56..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/WebIDL.py +++ /dev/null @@ -1,5583 +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/. - -""" A WebIDL parser. """ - -from ply import lex, yacc -import re -import os -import traceback -import math -from collections import defaultdict - -# Machinery - -def parseInt(literal): - string = literal - sign = 0 - base = 0 - - if string[0] == '-': - sign = -1 - string = string[1:] - else: - sign = 1 - - if string[0] == '0' and len(string) > 1: - if string[1] == 'x' or string[1] == 'X': - base = 16 - string = string[2:] - else: - base = 8 - string = string[1:] - else: - base = 10 - - value = int(string, base) - return value * sign - -# Magic for creating enums -def M_add_class_attribs(attribs, start): - def foo(name, bases, dict_): - for v, k in enumerate(attribs): - dict_[k] = start + v - assert 'length' not in dict_ - dict_['length'] = start + len(attribs) - return type(name, bases, dict_) - return foo - -def enum(*names, **kw): - if len(kw) == 1: - base = kw['base'].__class__ - start = base.length - else: - assert len(kw) == 0 - base = object - start = 0 - class Foo(base): - __metaclass__ = M_add_class_attribs(names, start) - def __setattr__(self, name, value): # this makes it read-only - raise NotImplementedError - return Foo() - -class WebIDLError(Exception): - def __init__(self, message, locations, warning=False): - self.message = message - self.locations = [str(loc) for loc in locations] - self.warning = warning - - def __str__(self): - return "%s: %s%s%s" % (self.warning and 'warning' or 'error', - self.message, - ", " if len(self.locations) != 0 else "", - "\n".join(self.locations)) - -class Location(object): - def __init__(self, lexer, lineno, lexpos, filename): - self._line = None - self._lineno = lineno - self._lexpos = lexpos - self._lexdata = lexer.lexdata - self._file = filename if filename else "<unknown>" - - def __eq__(self, other): - return self._lexpos == other._lexpos and \ - self._file == other._file - - def filename(self): - return self._file - - def resolve(self): - if self._line: - return - - startofline = self._lexdata.rfind('\n', 0, self._lexpos) + 1 - endofline = self._lexdata.find('\n', self._lexpos, self._lexpos + 80) - if endofline != -1: - self._line = self._lexdata[startofline:endofline] - else: - self._line = self._lexdata[startofline:] - self._colno = self._lexpos - startofline - - # Our line number seems to point to the start of self._lexdata - self._lineno += self._lexdata.count('\n', 0, startofline) - - def get(self): - self.resolve() - return "%s line %s:%s" % (self._file, self._lineno, self._colno) - - def _pointerline(self): - return " " * self._colno + "^" - - def __str__(self): - self.resolve() - return "%s line %s:%s\n%s\n%s" % (self._file, self._lineno, self._colno, - self._line, self._pointerline()) - -class BuiltinLocation(object): - def __init__(self, text): - self.msg = text + "\n" - - def __eq__(self, other): - return isinstance(other, BuiltinLocation) and \ - self.msg == other.msg - - def filename(self): - return '<builtin>' - - def resolve(self): - pass - - def get(self): - return self.msg - - def __str__(self): - return self.get() - - -# Data Model - -class IDLObject(object): - def __init__(self, location): - self.location = location - self.userData = dict() - - def filename(self): - return self.location.filename() - - def isInterface(self): - return False - - def isEnum(self): - return False - - def isCallback(self): - return False - - def isType(self): - return False - - def isDictionary(self): - return False; - - def isUnion(self): - return False - - def getUserData(self, key, default): - return self.userData.get(key, default) - - def setUserData(self, key, value): - self.userData[key] = value - - def addExtendedAttributes(self, attrs): - assert False # Override me! - - def handleExtendedAttribute(self, attr): - assert False # Override me! - - def _getDependentObjects(self): - assert False # Override me! - - def getDeps(self, visited=None): - """ Return a set of files that this object depends on. If any of - these files are changed the parser needs to be rerun to regenerate - a new IDLObject. - - The visited argument is a set of all the objects already visited. - We must test to see if we are in it, and if so, do nothing. This - prevents infinite recursion.""" - - # NB: We can't use visited=set() above because the default value is - # evaluated when the def statement is evaluated, not when the function - # is executed, so there would be one set for all invocations. - if visited == None: - visited = set() - - if self in visited: - return set() - - visited.add(self) - - deps = set() - if self.filename() != "<builtin>": - deps.add(self.filename()) - - for d in self._getDependentObjects(): - deps = deps.union(d.getDeps(visited)) - - return deps - -class IDLScope(IDLObject): - def __init__(self, location, parentScope, identifier): - IDLObject.__init__(self, location) - - self.parentScope = parentScope - if identifier: - assert isinstance(identifier, IDLIdentifier) - self._name = identifier - else: - self._name = None - - self._dict = {} - self.globalNames = set() - # A mapping from global name to the set of global interfaces - # that have that global name. - self.globalNameMapping = defaultdict(set) - self.primaryGlobalAttr = None - self.primaryGlobalName = None - - def __str__(self): - return self.QName() - - def QName(self): - if self._name: - return self._name.QName() + "::" - return "::" - - def ensureUnique(self, identifier, object): - """ - Ensure that there is at most one 'identifier' in scope ('self'). - Note that object can be None. This occurs if we end up here for an - interface type we haven't seen yet. - """ - assert isinstance(identifier, IDLUnresolvedIdentifier) - assert not object or isinstance(object, IDLObjectWithIdentifier) - assert not object or object.identifier == identifier - - if identifier.name in self._dict: - if not object: - return - - # ensureUnique twice with the same object is not allowed - assert id(object) != id(self._dict[identifier.name]) - - replacement = self.resolveIdentifierConflict(self, identifier, - self._dict[identifier.name], - object) - self._dict[identifier.name] = replacement - return - - assert object - - self._dict[identifier.name] = object - - def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject): - if isinstance(originalObject, IDLExternalInterface) and \ - isinstance(newObject, IDLExternalInterface) and \ - originalObject.identifier.name == newObject.identifier.name: - return originalObject - - if (isinstance(originalObject, IDLExternalInterface) or - isinstance(newObject, IDLExternalInterface)): - raise WebIDLError( - "Name collision between " - "interface declarations for identifier '%s' at '%s' and '%s'" - % (identifier.name, - originalObject.location, newObject.location), []) - - if (isinstance(originalObject, IDLDictionary) or - isinstance(newObject, IDLDictionary)): - raise WebIDLError( - "Name collision between dictionary declarations for " - "identifier '%s'.\n%s\n%s" - % (identifier.name, - originalObject.location, newObject.location), []) - - # We do the merging of overloads here as opposed to in IDLInterface - # because we need to merge overloads of NamedConstructors and we need to - # detect conflicts in those across interfaces. See also the comment in - # IDLInterface.addExtendedAttributes for "NamedConstructor". - if originalObject.tag == IDLInterfaceMember.Tags.Method and \ - newObject.tag == IDLInterfaceMember.Tags.Method: - return originalObject.addOverload(newObject) - - # Default to throwing, derived classes can override. - conflictdesc = "\n\t%s at %s\n\t%s at %s" % \ - (originalObject, originalObject.location, newObject, newObject.location) - - raise WebIDLError( - "Multiple unresolvable definitions of identifier '%s' in scope '%s%s" - % (identifier.name, str(self), conflictdesc), []) - - def _lookupIdentifier(self, identifier): - return self._dict[identifier.name] - - def lookupIdentifier(self, identifier): - assert isinstance(identifier, IDLIdentifier) - assert identifier.scope == self - return self._lookupIdentifier(identifier) - -class IDLIdentifier(IDLObject): - def __init__(self, location, scope, name): - IDLObject.__init__(self, location) - - self.name = name - assert isinstance(scope, IDLScope) - self.scope = scope - - def __str__(self): - return self.QName() - - def QName(self): - return self.scope.QName() + self.name - - def __hash__(self): - return self.QName().__hash__() - - def __eq__(self, other): - return self.QName() == other.QName() - - def object(self): - return self.scope.lookupIdentifier(self) - -class IDLUnresolvedIdentifier(IDLObject): - def __init__(self, location, name, allowDoubleUnderscore = False, - allowForbidden = False): - IDLObject.__init__(self, location) - - assert len(name) > 0 - - if name[:2] == "__" and name != "__content" and name != "___noSuchMethod__" and not allowDoubleUnderscore: - raise WebIDLError("Identifiers beginning with __ are reserved", - [location]) - if name[0] == '_' and not allowDoubleUnderscore: - name = name[1:] - # TODO: Bug 872377, Restore "toJSON" to below list. - # We sometimes need custom serialization, so allow toJSON for now. - if (name in ["constructor", "toString"] and - not allowForbidden): - raise WebIDLError("Cannot use reserved identifier '%s'" % (name), - [location]) - - self.name = name - - def __str__(self): - return self.QName() - - def QName(self): - return "<unresolved scope>::" + self.name - - def resolve(self, scope, object): - assert isinstance(scope, IDLScope) - assert not object or isinstance(object, IDLObjectWithIdentifier) - assert not object or object.identifier == self - - scope.ensureUnique(self, object) - - identifier = IDLIdentifier(self.location, scope, self.name) - if object: - object.identifier = identifier - return identifier - - def finish(self): - assert False # Should replace with a resolved identifier first. - -class IDLObjectWithIdentifier(IDLObject): - def __init__(self, location, parentScope, identifier): - IDLObject.__init__(self, location) - - assert isinstance(identifier, IDLUnresolvedIdentifier) - - self.identifier = identifier - - if parentScope: - self.resolve(parentScope) - - self.treatNullAs = "Default" - - def resolve(self, parentScope): - assert isinstance(parentScope, IDLScope) - assert isinstance(self.identifier, IDLUnresolvedIdentifier) - self.identifier.resolve(parentScope, self) - - def checkForStringHandlingExtendedAttributes(self, attrs, - isDictionaryMember=False, - isOptional=False): - """ - A helper function to deal with TreatNullAs. Returns the list - of attrs it didn't handle itself. - """ - assert isinstance(self, IDLArgument) or isinstance(self, IDLAttribute) - unhandledAttrs = list() - for attr in attrs: - if not attr.hasValue(): - unhandledAttrs.append(attr) - continue - - identifier = attr.identifier() - value = attr.value() - if identifier == "TreatNullAs": - if not self.type.isDOMString() or self.type.nullable(): - raise WebIDLError("[TreatNullAs] is only allowed on " - "arguments or attributes whose type is " - "DOMString", - [self.location]) - if isDictionaryMember: - raise WebIDLError("[TreatNullAs] is not allowed for " - "dictionary members", [self.location]) - if value != 'EmptyString': - raise WebIDLError("[TreatNullAs] must take the identifier " - "'EmptyString', not '%s'" % value, - [self.location]) - self.treatNullAs = value - else: - unhandledAttrs.append(attr) - - return unhandledAttrs - -class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope): - def __init__(self, location, parentScope, identifier): - assert isinstance(identifier, IDLUnresolvedIdentifier) - - IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier) - IDLScope.__init__(self, location, parentScope, self.identifier) - -class IDLIdentifierPlaceholder(IDLObjectWithIdentifier): - def __init__(self, location, identifier): - assert isinstance(identifier, IDLUnresolvedIdentifier) - IDLObjectWithIdentifier.__init__(self, location, None, identifier) - - def finish(self, scope): - try: - scope._lookupIdentifier(self.identifier) - except: - raise WebIDLError("Unresolved type '%s'." % self.identifier, - [self.location]) - - obj = self.identifier.resolve(scope, None) - return scope.lookupIdentifier(obj) - -class IDLExternalInterface(IDLObjectWithIdentifier): - def __init__(self, location, parentScope, identifier): - raise WebIDLError("Servo does not support external interfaces.", - [self.location]) - -class IDLPartialInterface(IDLObject): - def __init__(self, location, name, members, nonPartialInterface): - assert isinstance(name, IDLUnresolvedIdentifier) - - IDLObject.__init__(self, location) - self.identifier = name - self.members = members - # propagatedExtendedAttrs are the ones that should get - # propagated to our non-partial interface. - self.propagatedExtendedAttrs = [] - self._nonPartialInterface = nonPartialInterface - self._finished = False - nonPartialInterface.addPartialInterface(self) - - def addExtendedAttributes(self, attrs): - for attr in attrs: - identifier = attr.identifier() - - if identifier in ["Constructor", "NamedConstructor"]: - self.propagatedExtendedAttrs.append(attr) - elif identifier == "Exposed": - # This just gets propagated to all our members. - for member in self.members: - if len(member._exposureGlobalNames) != 0: - raise WebIDLError("[Exposed] specified on both a " - "partial interface member and on the " - "partial interface itself", - [member.location, attr.location]) - member.addExtendedAttributes([attr]) - else: - raise WebIDLError("Unknown extended attribute %s on partial " - "interface" % identifier, - [attr.location]) - - def finish(self, scope): - if self._finished: - return - self._finished = True - # Need to make sure our non-partial interface gets finished so it can - # report cases when we only have partial interfaces. - self._nonPartialInterface.finish(scope) - - def validate(self): - pass - - -def convertExposedAttrToGlobalNameSet(exposedAttr, targetSet): - assert len(targetSet) == 0 - if exposedAttr.hasValue(): - targetSet.add(exposedAttr.value()) - else: - assert exposedAttr.hasArgs() - targetSet.update(exposedAttr.args()) - -def globalNameSetToExposureSet(globalScope, nameSet, exposureSet): - for name in nameSet: - exposureSet.update(globalScope.globalNameMapping[name]) - -class IDLInterface(IDLObjectWithScope): - def __init__(self, location, parentScope, name, parent, members, - isKnownNonPartial): - assert isinstance(parentScope, IDLScope) - assert isinstance(name, IDLUnresolvedIdentifier) - assert isKnownNonPartial or not parent - assert isKnownNonPartial or len(members) == 0 - - self.parent = None - self._callback = False - self._finished = False - self.members = [] - self._partialInterfaces = [] - self._extendedAttrDict = {} - # namedConstructors needs deterministic ordering because bindings code - # outputs the constructs in the order that namedConstructors enumerates - # them. - self.namedConstructors = list() - self.implementedInterfaces = set() - self._consequential = False - self._isKnownNonPartial = False - # self.interfacesBasedOnSelf is the set of interfaces that inherit from - # self or have self as a consequential interface, including self itself. - # Used for distinguishability checking. - self.interfacesBasedOnSelf = set([self]) - # self.interfacesImplementingSelf is the set of interfaces that directly - # have self as a consequential interface - self.interfacesImplementingSelf = set() - self._hasChildInterfaces = False - self._isOnGlobalProtoChain = False - # Tracking of the number of reserved slots we need for our - # members and those of ancestor interfaces. - self.totalMembersInSlots = 0 - # Tracking of the number of own own members we have in slots - self._ownMembersInSlots = 0 - # _exposureGlobalNames are the global names listed in our [Exposed] - # extended attribute. exposureSet is the exposure set as defined in the - # Web IDL spec: it contains interface names. - self._exposureGlobalNames = set() - self.exposureSet = set() - - IDLObjectWithScope.__init__(self, location, parentScope, name) - - if isKnownNonPartial: - self.setNonPartial(location, parent, members) - - def __str__(self): - return "Interface '%s'" % self.identifier.name - - def ctor(self): - identifier = IDLUnresolvedIdentifier(self.location, "constructor", - allowForbidden=True) - try: - return self._lookupIdentifier(identifier) - except: - return None - - def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject): - assert isinstance(scope, IDLScope) - assert isinstance(originalObject, IDLInterfaceMember) - assert isinstance(newObject, IDLInterfaceMember) - - retval = IDLScope.resolveIdentifierConflict(self, scope, identifier, - originalObject, newObject) - - # Might be a ctor, which isn't in self.members - if newObject in self.members: - self.members.remove(newObject) - return retval - - def finish(self, scope): - if self._finished: - return - - self._finished = True - - if not self._isKnownNonPartial: - raise WebIDLError("Interface %s does not have a non-partial " - "declaration" % self.identifier.name, - [self.location]) - - # Verify that our [Exposed] value, if any, makes sense. - for globalName in self._exposureGlobalNames: - if globalName not in scope.globalNames: - raise WebIDLError("Unknown [Exposed] value %s" % globalName, - [self.location]) - - if len(self._exposureGlobalNames) == 0: - self._exposureGlobalNames.add(scope.primaryGlobalName) - - globalNameSetToExposureSet(scope, self._exposureGlobalNames, - self.exposureSet) - - # Now go ahead and merge in our partial interfaces. - for partial in self._partialInterfaces: - partial.finish(scope) - self.addExtendedAttributes(partial.propagatedExtendedAttrs) - self.members.extend(partial.members) - - # Now that we've merged in our partial interfaces, set the - # _exposureGlobalNames on any members that don't have it set yet. Note - # that any partial interfaces that had [Exposed] set have already set up - # _exposureGlobalNames on all the members coming from them, so this is - # just implementing the "members default to interface that defined them" - # and "partial interfaces default to interface they're a partial for" - # rules from the spec. - for m in self.members: - # If m, or the partial interface m came from, had [Exposed] - # specified, it already has a nonempty exposure global names set. - if len(m._exposureGlobalNames) == 0: - m._exposureGlobalNames.update(self._exposureGlobalNames) - - assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder) - parent = self.parent.finish(scope) if self.parent else None - if parent and isinstance(parent, IDLExternalInterface): - raise WebIDLError("%s inherits from %s which does not have " - "a definition" % - (self.identifier.name, - self.parent.identifier.name), - [self.location]) - assert not parent or isinstance(parent, IDLInterface) - - self.parent = parent - - assert iter(self.members) - - if self.parent: - self.parent.finish(scope) - - self.parent._hasChildInterfaces = True - - self.totalMembersInSlots = self.parent.totalMembersInSlots - - # Interfaces with [Global] or [PrimaryGlobal] must not - # have anything inherit from them - if (self.parent.getExtendedAttribute("Global") or - self.parent.getExtendedAttribute("PrimaryGlobal")): - # Note: This is not a self.parent.isOnGlobalProtoChain() check - # because ancestors of a [Global] interface can have other - # descendants. - raise WebIDLError("[Global] interface has another interface " - "inheriting from it", - [self.location, self.parent.location]) - - # Make sure that we're not exposed in places where our parent is not - if not self.exposureSet.issubset(self.parent.exposureSet): - raise WebIDLError("Interface %s is exposed in globals where its " - "parent interface %s is not exposed." % - (self.identifier.name, - self.parent.identifier.name), - [self.location, self.parent.location]) - - # Callbacks must not inherit from non-callbacks or inherit from - # anything that has consequential interfaces. - # XXXbz Can non-callbacks inherit from callbacks? Spec issue pending. - # XXXbz Can callbacks have consequential interfaces? Spec issue pending - if self.isCallback(): - if not self.parent.isCallback(): - raise WebIDLError("Callback interface %s inheriting from " - "non-callback interface %s" % - (self.identifier.name, - self.parent.identifier.name), - [self.location, self.parent.location]) - elif self.parent.isCallback(): - raise WebIDLError("Non-callback interface %s inheriting from " - "callback interface %s" % - (self.identifier.name, - self.parent.identifier.name), - [self.location, self.parent.location]) - - for iface in self.implementedInterfaces: - iface.finish(scope) - - cycleInGraph = self.findInterfaceLoopPoint(self) - if cycleInGraph: - raise WebIDLError("Interface %s has itself as ancestor or " - "implemented interface" % self.identifier.name, - [self.location, cycleInGraph.location]) - - if self.isCallback(): - # "implements" should have made sure we have no - # consequential interfaces. - assert len(self.getConsequentialInterfaces()) == 0 - # And that we're not consequential. - assert not self.isConsequential() - - # Now resolve() and finish() our members before importing the - # ones from our implemented interfaces. - - # resolve() will modify self.members, so we need to iterate - # over a copy of the member list here. - for member in list(self.members): - member.resolve(self) - - for member in self.members: - member.finish(scope) - - # Now that we've finished our members, which has updated their exposure - # sets, make sure they aren't exposed in places where we are not. - for member in self.members: - if not member.exposureSet.issubset(self.exposureSet): - raise WebIDLError("Interface member has larger exposure set " - "than the interface itself", - [member.location, self.location]) - - ctor = self.ctor() - if ctor is not None: - ctor.finish(scope) - - for ctor in self.namedConstructors: - ctor.finish(scope) - - # Make a copy of our member list, so things that implement us - # can get those without all the stuff we implement ourselves - # admixed. - self.originalMembers = list(self.members) - - # Import everything from our consequential interfaces into - # self.members. Sort our consequential interfaces by name - # just so we have a consistent order. - for iface in sorted(self.getConsequentialInterfaces(), - cmp=cmp, - key=lambda x: x.identifier.name): - # Flag the interface as being someone's consequential interface - iface.setIsConsequentialInterfaceOf(self) - # Verify that we're not exposed somewhere where iface is not exposed - if not self.exposureSet.issubset(iface.exposureSet): - raise WebIDLError("Interface %s is exposed in globals where its " - "consequential interface %s is not exposed." % - (self.identifier.name, iface.identifier.name), - [self.location, iface.location]) - additionalMembers = iface.originalMembers; - for additionalMember in additionalMembers: - for member in self.members: - if additionalMember.identifier.name == member.identifier.name: - raise WebIDLError( - "Multiple definitions of %s on %s coming from 'implements' statements" % - (member.identifier.name, self), - [additionalMember.location, member.location]) - self.members.extend(additionalMembers) - iface.interfacesImplementingSelf.add(self) - - for ancestor in self.getInheritedInterfaces(): - ancestor.interfacesBasedOnSelf.add(self) - for ancestorConsequential in ancestor.getConsequentialInterfaces(): - ancestorConsequential.interfacesBasedOnSelf.add(self) - - # Deal with interfaces marked [Unforgeable], now that we have our full - # member list, except unforgeables pulled in from parents. We want to - # do this before we set "originatingInterface" on our unforgeable - # members. - if self.getExtendedAttribute("Unforgeable"): - # Check that the interface already has all the things the - # spec would otherwise require us to synthesize and is - # missing the ones we plan to synthesize. - if not any(m.isMethod() and m.isStringifier() for m in self.members): - raise WebIDLError("Unforgeable interface %s does not have a " - "stringifier" % self.identifier.name, - [self.location]) - - for m in self.members: - if ((m.isMethod() and m.isJsonifier()) or - m.identifier.name == "toJSON"): - raise WebIDLError("Unforgeable interface %s has a " - "jsonifier so we won't be able to add " - "one ourselves" % self.identifier.name, - [self.location, m.location]) - - if m.identifier.name == "valueOf" and not m.isStatic(): - raise WebIDLError("Unforgeable interface %s has a valueOf " - "member so we won't be able to add one " - "ourselves" % self.identifier.name, - [self.location, m.location]) - - for member in self.members: - if ((member.isAttr() or member.isMethod()) and - member.isUnforgeable() and - not hasattr(member, "originatingInterface")): - member.originatingInterface = self - - # Compute slot indices for our members before we pull in - # unforgeable members from our parent. - for member in self.members: - if (member.isAttr() and - (member.getExtendedAttribute("StoreInSlot") or - member.getExtendedAttribute("Cached"))): - member.slotIndex = self.totalMembersInSlots - self.totalMembersInSlots += 1 - if member.getExtendedAttribute("StoreInSlot"): - self._ownMembersInSlots += 1 - - if self.parent: - # Make sure we don't shadow any of the [Unforgeable] attributes on - # our ancestor interfaces. We don't have to worry about - # consequential interfaces here, because those have already been - # imported into the relevant .members lists. And we don't have to - # worry about anything other than our parent, because it has already - # imported its ancestors unforgeable attributes into its member - # list. - for unforgeableMember in (member for member in self.parent.members if - (member.isAttr() or member.isMethod()) and - member.isUnforgeable()): - shadows = [ m for m in self.members if - (m.isAttr() or m.isMethod()) and - not m.isStatic() and - m.identifier.name == unforgeableMember.identifier.name ] - if len(shadows) != 0: - locs = [unforgeableMember.location] + [ s.location for s - in shadows ] - raise WebIDLError("Interface %s shadows [Unforgeable] " - "members of %s" % - (self.identifier.name, - ancestor.identifier.name), - locs) - # And now just stick it in our members, since we won't be - # inheriting this down the proto chain. If we really cared we - # could try to do something where we set up the unforgeable - # attributes/methods of ancestor interfaces, with their - # corresponding getters, on our interface, but that gets pretty - # complicated and seems unnecessary. - self.members.append(unforgeableMember) - - # Ensure that there's at most one of each {named,indexed} - # {getter,setter,creator,deleter}, at most one stringifier, - # and at most one legacycaller. Note that this last is not - # quite per spec, but in practice no one overloads - # legacycallers. - specialMembersSeen = {} - for member in self.members: - if not member.isMethod(): - continue - - if member.isGetter(): - memberType = "getters" - elif member.isSetter(): - memberType = "setters" - elif member.isCreator(): - memberType = "creators" - elif member.isDeleter(): - memberType = "deleters" - elif member.isStringifier(): - memberType = "stringifiers" - elif member.isJsonifier(): - memberType = "jsonifiers" - elif member.isLegacycaller(): - memberType = "legacycallers" - else: - continue - - if (memberType != "stringifiers" and memberType != "legacycallers" and - memberType != "jsonifiers"): - if member.isNamed(): - memberType = "named " + memberType - else: - assert member.isIndexed() - memberType = "indexed " + memberType - - if memberType in specialMembersSeen: - raise WebIDLError("Multiple " + memberType + " on %s" % (self), - [self.location, - specialMembersSeen[memberType].location, - member.location]) - - specialMembersSeen[memberType] = member - - if self._isOnGlobalProtoChain: - # Make sure we have no named setters, creators, or deleters - for memberType in ["setter", "creator", "deleter"]: - memberId = "named " + memberType + "s" - if memberId in specialMembersSeen: - raise WebIDLError("Interface with [Global] has a named %s" % - memberType, - [self.location, - specialMembersSeen[memberId].location]) - # Make sure we're not [OverrideBuiltins] - if self.getExtendedAttribute("OverrideBuiltins"): - raise WebIDLError("Interface with [Global] also has " - "[OverrideBuiltins]", - [self.location]) - # Mark all of our ancestors as being on the global's proto chain too - parent = self.parent - while parent: - # Must not inherit from an interface with [OverrideBuiltins] - if parent.getExtendedAttribute("OverrideBuiltins"): - raise WebIDLError("Interface with [Global] inherits from " - "interface with [OverrideBuiltins]", - [self.location, parent.location]) - parent._isOnGlobalProtoChain = True - parent = parent.parent - - def validate(self): - # We don't support consequential unforgeable interfaces. Need to check - # this here, becaue in finish() an interface might not know yet that - # it's consequential. - if self.getExtendedAttribute("Unforgeable") and self.isConsequential(): - raise WebIDLError( - "%s is an unforgeable consequential interface" % - self.identifier.name, - [self.location] + - list(i.location for i in - (self.interfacesBasedOnSelf - { self }) )) - - # We also don't support inheriting from unforgeable interfaces. - if self.getExtendedAttribute("Unforgeable") and self.hasChildInterfaces(): - raise WebIDLError("%s is an unforgeable ancestor interface" % - self.identifier.name, - [self.location] + - list(i.location for i in - self.interfacesBasedOnSelf if i.parent == self)) - - - for member in self.members: - member.validate() - - # Check that PutForwards refers to another attribute and that no - # cycles exist in forwarded assignments. - if member.isAttr(): - iface = self - attr = member - putForwards = attr.getExtendedAttribute("PutForwards") - if putForwards and self.isCallback(): - raise WebIDLError("[PutForwards] used on an attribute " - "on interface %s which is a callback " - "interface" % self.identifier.name, - [self.location, member.location]) - - while putForwards is not None: - forwardIface = attr.type.unroll().inner - fowardAttr = None - - for forwardedMember in forwardIface.members: - if (not forwardedMember.isAttr() or - forwardedMember.identifier.name != putForwards[0]): - continue - if forwardedMember == member: - raise WebIDLError("Cycle detected in forwarded " - "assignments for attribute %s on " - "%s" % - (member.identifier.name, self), - [member.location]) - fowardAttr = forwardedMember - break - - if fowardAttr is None: - raise WebIDLError("Attribute %s on %s forwards to " - "missing attribute %s" % - (attr.identifier.name, iface, putForwards), - [attr.location]) - - iface = forwardIface - attr = fowardAttr - putForwards = attr.getExtendedAttribute("PutForwards") - - if (self.getExtendedAttribute("Pref") and - self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])): - raise WebIDLError("[Pref] used on an member that is not %s-only" % - self.parentScope.primaryGlobalName, - [self.location]) - - - def isInterface(self): - return True - - def isExternal(self): - return False - - def setIsConsequentialInterfaceOf(self, other): - self._consequential = True - self.interfacesBasedOnSelf.add(other) - - def isConsequential(self): - return self._consequential - - def setCallback(self, value): - self._callback = value - - def isCallback(self): - return self._callback - - def isSingleOperationInterface(self): - assert self.isCallback() or self.isJSImplemented() - return ( - # JS-implemented things should never need the - # this-handling weirdness of single-operation interfaces. - not self.isJSImplemented() and - # Not inheriting from another interface - not self.parent and - # No consequential interfaces - len(self.getConsequentialInterfaces()) == 0 and - # No attributes of any kinds - not any(m.isAttr() for m in self.members) and - # There is at least one regular operation, and all regular - # operations have the same identifier - len(set(m.identifier.name for m in self.members if - m.isMethod() and not m.isStatic())) == 1) - - def inheritanceDepth(self): - depth = 0 - parent = self.parent - while parent: - depth = depth + 1 - parent = parent.parent - return depth - - def hasConstants(self): - return any(m.isConst() for m in self.members) - - def hasInterfaceObject(self): - if self.isCallback(): - return self.hasConstants() - return not hasattr(self, "_noInterfaceObject") - - def hasInterfacePrototypeObject(self): - return not self.isCallback() and self.getUserData('hasConcreteDescendant', False) - - def addExtendedAttributes(self, attrs): - for attr in attrs: - identifier = attr.identifier() - - # Special cased attrs - if identifier == "TreatNonCallableAsNull": - raise WebIDLError("TreatNonCallableAsNull cannot be specified on interfaces", - [attr.location, self.location]) - if identifier == "TreatNonObjectAsNull": - raise WebIDLError("TreatNonObjectAsNull cannot be specified on interfaces", - [attr.location, self.location]) - elif identifier == "NoInterfaceObject": - if not attr.noArguments(): - raise WebIDLError("[NoInterfaceObject] must take no arguments", - [attr.location]) - - if self.ctor(): - raise WebIDLError("Constructor and NoInterfaceObject are incompatible", - [self.location]) - - self._noInterfaceObject = True - elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor": - if identifier == "Constructor" and not self.hasInterfaceObject(): - raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible", - [self.location]) - - if identifier == "NamedConstructor" and not attr.hasValue(): - raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list", - [attr.location]) - - if identifier == "ChromeConstructor" and not self.hasInterfaceObject(): - raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible", - [self.location]) - - args = attr.args() if attr.hasArgs() else [] - - retType = IDLWrapperType(self.location, self) - - if identifier == "Constructor" or identifier == "ChromeConstructor": - name = "constructor" - allowForbidden = True - else: - name = attr.value() - allowForbidden = False - - methodIdentifier = IDLUnresolvedIdentifier(self.location, name, - allowForbidden=allowForbidden) - - method = IDLMethod(self.location, methodIdentifier, retType, - args, static=True) - # Constructors are always NewObject and are always - # assumed to be able to throw (since there's no way to - # indicate otherwise) and never have any other - # extended attributes. - method.addExtendedAttributes( - [IDLExtendedAttribute(self.location, ("NewObject",)), - IDLExtendedAttribute(self.location, ("Throws",))]) - if identifier == "ChromeConstructor": - method.addExtendedAttributes( - [IDLExtendedAttribute(self.location, ("ChromeOnly",))]) - - if identifier == "Constructor" or identifier == "ChromeConstructor": - method.resolve(self) - else: - # We need to detect conflicts for NamedConstructors across - # interfaces. We first call resolve on the parentScope, - # which will merge all NamedConstructors with the same - # identifier accross interfaces as overloads. - method.resolve(self.parentScope) - - # Then we look up the identifier on the parentScope. If the - # result is the same as the method we're adding then it - # hasn't been added as an overload and it's the first time - # we've encountered a NamedConstructor with that identifier. - # If the result is not the same as the method we're adding - # then it has been added as an overload and we need to check - # whether the result is actually one of our existing - # NamedConstructors. - newMethod = self.parentScope.lookupIdentifier(method.identifier) - if newMethod == method: - self.namedConstructors.append(method) - elif not newMethod in self.namedConstructors: - raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface", - [method.location, newMethod.location]) - elif (identifier == "ArrayClass"): - if not attr.noArguments(): - raise WebIDLError("[ArrayClass] must take no arguments", - [attr.location]) - if self.parent: - raise WebIDLError("[ArrayClass] must not be specified on " - "an interface with inherited interfaces", - [attr.location, self.location]) - elif (identifier == "ExceptionClass"): - if not attr.noArguments(): - raise WebIDLError("[ExceptionClass] must take no arguments", - [attr.location]) - if self.parent: - raise WebIDLError("[ExceptionClass] must not be specified on " - "an interface with inherited interfaces", - [attr.location, self.location]) - elif identifier == "Global": - if attr.hasValue(): - self.globalNames = [ attr.value() ] - elif attr.hasArgs(): - self.globalNames = attr.args() - else: - self.globalNames = [ self.identifier.name ] - self.parentScope.globalNames.update(self.globalNames) - for globalName in self.globalNames: - self.parentScope.globalNameMapping[globalName].add(self.identifier.name) - self._isOnGlobalProtoChain = True - elif identifier == "PrimaryGlobal": - if not attr.noArguments(): - raise WebIDLError("[PrimaryGlobal] must take no arguments", - [attr.location]) - if self.parentScope.primaryGlobalAttr is not None: - raise WebIDLError( - "[PrimaryGlobal] specified twice", - [attr.location, - self.parentScope.primaryGlobalAttr.location]) - self.parentScope.primaryGlobalAttr = attr - self.parentScope.primaryGlobalName = self.identifier.name - self.parentScope.globalNames.add(self.identifier.name) - self.parentScope.globalNameMapping[self.identifier.name].add(self.identifier.name) - self._isOnGlobalProtoChain = True - elif (identifier == "NeedNewResolve" or - identifier == "OverrideBuiltins" or - identifier == "ChromeOnly" or - identifier == "Unforgeable" or - identifier == "LegacyEventInit"): - # Known extended attributes that do not take values - if not attr.noArguments(): - raise WebIDLError("[%s] must take no arguments" % identifier, - [attr.location]) - elif identifier == "Exposed": - convertExposedAttrToGlobalNameSet(attr, - self._exposureGlobalNames) - elif (identifier == "Pref" or - identifier == "JSImplementation" or - identifier == "HeaderFile" or - identifier == "NavigatorProperty" or - identifier == "AvailableIn" or - identifier == "Func" or - identifier == "CheckPermissions"): - # Known extended attributes that take a string value - if not attr.hasValue(): - raise WebIDLError("[%s] must have a value" % identifier, - [attr.location]) - else: - raise WebIDLError("Unknown extended attribute %s on interface" % identifier, - [attr.location]) - - attrlist = attr.listValue() - self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True - - def addImplementedInterface(self, implementedInterface): - assert(isinstance(implementedInterface, IDLInterface)) - self.implementedInterfaces.add(implementedInterface) - - def getInheritedInterfaces(self): - """ - Returns a list of the interfaces this interface inherits from - (not including this interface itself). The list is in order - from most derived to least derived. - """ - assert(self._finished) - if not self.parent: - return [] - parentInterfaces = self.parent.getInheritedInterfaces() - parentInterfaces.insert(0, self.parent) - return parentInterfaces - - def getConsequentialInterfaces(self): - assert(self._finished) - # The interfaces we implement directly - consequentialInterfaces = set(self.implementedInterfaces) - - # And their inherited interfaces - for iface in self.implementedInterfaces: - consequentialInterfaces |= set(iface.getInheritedInterfaces()) - - # And now collect up the consequential interfaces of all of those - temp = set() - for iface in consequentialInterfaces: - temp |= iface.getConsequentialInterfaces() - - return consequentialInterfaces | temp - - def findInterfaceLoopPoint(self, otherInterface): - """ - Finds an interface, amongst our ancestors and consequential interfaces, - that inherits from otherInterface or implements otherInterface - directly. If there is no such interface, returns None. - """ - if self.parent: - if self.parent == otherInterface: - return self - loopPoint = self.parent.findInterfaceLoopPoint(otherInterface) - if loopPoint: - return loopPoint - if otherInterface in self.implementedInterfaces: - return self - for iface in self.implementedInterfaces: - loopPoint = iface.findInterfaceLoopPoint(otherInterface) - if loopPoint: - return loopPoint - return None - - def getExtendedAttribute(self, name): - return self._extendedAttrDict.get(name, None) - - def setNonPartial(self, location, parent, members): - assert not parent or isinstance(parent, IDLIdentifierPlaceholder) - if self._isKnownNonPartial: - raise WebIDLError("Two non-partial definitions for the " - "same interface", - [location, self.location]) - self._isKnownNonPartial = True - # Now make it look like we were parsed at this new location, since - # that's the place where the interface is "really" defined - self.location = location - assert not self.parent - self.parent = parent - # Put the new members at the beginning - self.members = members + self.members - - def addPartialInterface(self, partial): - assert self.identifier.name == partial.identifier.name - self._partialInterfaces.append(partial) - - def getJSImplementation(self): - classId = self.getExtendedAttribute("JSImplementation") - if not classId: - return classId - assert isinstance(classId, list) - assert len(classId) == 1 - return classId[0] - - def isJSImplemented(self): - return bool(self.getJSImplementation()) - - def getNavigatorProperty(self): - naviProp = self.getExtendedAttribute("NavigatorProperty") - if not naviProp: - return None - assert len(naviProp) == 1 - assert isinstance(naviProp, list) - assert len(naviProp[0]) != 0 - return naviProp[0] - - def hasChildInterfaces(self): - return self._hasChildInterfaces - - def isOnGlobalProtoChain(self): - return self._isOnGlobalProtoChain - - def _getDependentObjects(self): - deps = set(self.members) - deps.union(self.implementedInterfaces) - if self.parent: - deps.add(self.parent) - return deps - - def hasMembersInSlots(self): - return self._ownMembersInSlots != 0 - -class IDLDictionary(IDLObjectWithScope): - def __init__(self, location, parentScope, name, parent, members): - assert isinstance(parentScope, IDLScope) - assert isinstance(name, IDLUnresolvedIdentifier) - assert not parent or isinstance(parent, IDLIdentifierPlaceholder) - - self.parent = parent - self._finished = False - self.members = list(members) - - IDLObjectWithScope.__init__(self, location, parentScope, name) - - def __str__(self): - return "Dictionary '%s'" % self.identifier.name - - def isDictionary(self): - return True; - - def finish(self, scope): - if self._finished: - return - - self._finished = True - - if self.parent: - assert isinstance(self.parent, IDLIdentifierPlaceholder) - oldParent = self.parent - self.parent = self.parent.finish(scope) - if not isinstance(self.parent, IDLDictionary): - raise WebIDLError("Dictionary %s has parent that is not a dictionary" % - self.identifier.name, - [oldParent.location, self.parent.location]) - - # Make sure the parent resolves all its members before we start - # looking at them. - self.parent.finish(scope) - - for member in self.members: - member.resolve(self) - if not member.isComplete(): - member.complete(scope) - assert member.type.isComplete() - - # Members of a dictionary are sorted in lexicographic order - self.members.sort(cmp=cmp, key=lambda x: x.identifier.name) - - inheritedMembers = [] - ancestor = self.parent - while ancestor: - if ancestor == self: - raise WebIDLError("Dictionary %s has itself as an ancestor" % - self.identifier.name, - [self.identifier.location]) - inheritedMembers.extend(ancestor.members) - ancestor = ancestor.parent - - # Catch name duplication - for inheritedMember in inheritedMembers: - for member in self.members: - if member.identifier.name == inheritedMember.identifier.name: - raise WebIDLError("Dictionary %s has two members with name %s" % - (self.identifier.name, member.identifier.name), - [member.location, inheritedMember.location]) - - def validate(self): - def typeContainsDictionary(memberType, dictionary): - """ - Returns a tuple whose: - - - First element is a Boolean value indicating whether - memberType contains dictionary. - - - Second element is: - A list of locations that leads from the type that was passed in - the memberType argument, to the dictionary being validated, - if the boolean value in the first element is True. - - None, if the boolean value in the first element is False. - """ - - if (memberType.nullable() or - memberType.isArray() or - memberType.isSequence() or - memberType.isMozMap()): - return typeContainsDictionary(memberType.inner, dictionary) - - if memberType.isDictionary(): - if memberType.inner == dictionary: - return (True, [memberType.location]) - - (contains, locations) = dictionaryContainsDictionary(memberType.inner, \ - dictionary) - if contains: - return (True, [memberType.location] + locations) - - if memberType.isUnion(): - for member in memberType.flatMemberTypes: - (contains, locations) = typeContainsDictionary(member, dictionary) - if contains: - return (True, locations) - - return (False, None) - - def dictionaryContainsDictionary(dictMember, dictionary): - for member in dictMember.members: - (contains, locations) = typeContainsDictionary(member.type, dictionary) - if contains: - return (True, [member.location] + locations) - - if dictMember.parent: - if dictMember.parent == dictionary: - return (True, [dictMember.location]) - else: - (contains, locations) = dictionaryContainsDictionary(dictMember.parent, dictionary) - if contains: - return (True, [dictMember.location] + locations) - - return (False, None) - - for member in self.members: - if member.type.isDictionary() and member.type.nullable(): - raise WebIDLError("Dictionary %s has member with nullable " - "dictionary type" % self.identifier.name, - [member.location]) - (contains, locations) = typeContainsDictionary(member.type, self) - if contains: - raise WebIDLError("Dictionary %s has member with itself as type." % - self.identifier.name, - [member.location] + locations) - - def addExtendedAttributes(self, attrs): - assert len(attrs) == 0 - - def _getDependentObjects(self): - deps = set(self.members) - if (self.parent): - deps.add(self.parent) - return deps - -class IDLEnum(IDLObjectWithIdentifier): - def __init__(self, location, parentScope, name, values): - assert isinstance(parentScope, IDLScope) - assert isinstance(name, IDLUnresolvedIdentifier) - - if len(values) != len(set(values)): - raise WebIDLError("Enum %s has multiple identical strings" % name.name, - [location]) - - IDLObjectWithIdentifier.__init__(self, location, parentScope, name) - self._values = values - - def values(self): - return self._values - - def finish(self, scope): - pass - - def validate(self): - pass - - def isEnum(self): - return True - - def addExtendedAttributes(self, attrs): - assert len(attrs) == 0 - - def _getDependentObjects(self): - return set() - -class IDLType(IDLObject): - Tags = enum( - # The integer types - 'int8', - 'uint8', - 'int16', - 'uint16', - 'int32', - 'uint32', - 'int64', - 'uint64', - # Additional primitive types - 'bool', - 'unrestricted_float', - 'float', - 'unrestricted_double', - # "double" last primitive type to match IDLBuiltinType - 'double', - # Other types - 'any', - 'domstring', - 'bytestring', - 'scalarvaluestring', - 'object', - 'date', - 'void', - # Funny stuff - 'interface', - 'dictionary', - 'enum', - 'callback', - 'union', - 'sequence', - 'mozmap', - 'array' - ) - - def __init__(self, location, name): - IDLObject.__init__(self, location) - self.name = name - self.builtin = False - - def __eq__(self, other): - return other and self.builtin == other.builtin and self.name == other.name - - def __ne__(self, other): - return not self == other - - def __str__(self): - return str(self.name) - - def isType(self): - return True - - def nullable(self): - return False - - def isPrimitive(self): - return False - - def isBoolean(self): - return False - - def isNumeric(self): - return False - - def isString(self): - return False - - def isByteString(self): - return False - - def isDOMString(self): - return False - - def isScalarValueString(self): - return False - - def isVoid(self): - return self.name == "Void" - - def isSequence(self): - return False - - def isMozMap(self): - return False - - def isArray(self): - return False - - def isArrayBuffer(self): - return False - - def isArrayBufferView(self): - return False - - def isTypedArray(self): - return False - - def isCallbackInterface(self): - return False - - def isNonCallbackInterface(self): - return False - - def isGeckoInterface(self): - """ Returns a boolean indicating whether this type is an 'interface' - type that is implemented in Gecko. At the moment, this returns - true for all interface types that are not types from the TypedArray - spec.""" - return self.isInterface() and not self.isSpiderMonkeyInterface() - - def isSpiderMonkeyInterface(self): - """ Returns a boolean indicating whether this type is an 'interface' - type that is implemented in Spidermonkey. At the moment, this - only returns true for the types from the TypedArray spec. """ - return self.isInterface() and (self.isArrayBuffer() or \ - self.isArrayBufferView() or \ - self.isTypedArray()) - - def isDictionary(self): - return False - - def isInterface(self): - return False - - def isAny(self): - return self.tag() == IDLType.Tags.any - - def isDate(self): - return self.tag() == IDLType.Tags.date - - def isObject(self): - return self.tag() == IDLType.Tags.object - - def isPromise(self): - return False - - def isComplete(self): - return True - - def includesRestrictedFloat(self): - return False - - def isFloat(self): - return False - - def isUnrestricted(self): - # Should only call this on float types - assert self.isFloat() - - def isSerializable(self): - return False - - def tag(self): - assert False # Override me! - - def treatNonCallableAsNull(self): - assert self.tag() == IDLType.Tags.callback - return self.nullable() and self.inner._treatNonCallableAsNull - - def treatNonObjectAsNull(self): - assert self.tag() == IDLType.Tags.callback - return self.nullable() and self.inner._treatNonObjectAsNull - - def addExtendedAttributes(self, attrs): - assert len(attrs) == 0 - - def resolveType(self, parentScope): - pass - - def unroll(self): - return self - - def isDistinguishableFrom(self, other): - raise TypeError("Can't tell whether a generic type is or is not " - "distinguishable from other things") - - def isExposedInAllOf(self, exposureSet): - return True - -class IDLUnresolvedType(IDLType): - """ - Unresolved types are interface types - """ - - def __init__(self, location, name, promiseInnerType=None): - IDLType.__init__(self, location, name) - self._promiseInnerType = promiseInnerType - - def isComplete(self): - return False - - def complete(self, scope): - obj = None - try: - obj = scope._lookupIdentifier(self.name) - except: - raise WebIDLError("Unresolved type '%s'." % self.name, - [self.location]) - - assert obj - if obj.isType(): - # obj itself might not be complete; deal with that. - assert obj != self - if not obj.isComplete(): - obj = obj.complete(scope) - return obj - - if self._promiseInnerType and not self._promiseInnerType.isComplete(): - self._promiseInnerType = self._promiseInnerType.complete(scope) - - name = self.name.resolve(scope, None) - return IDLWrapperType(self.location, obj, self._promiseInnerType) - - def isDistinguishableFrom(self, other): - raise TypeError("Can't tell whether an unresolved type is or is not " - "distinguishable from other things") - -class IDLNullableType(IDLType): - def __init__(self, location, innerType): - assert not innerType.isVoid() - assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any] - - IDLType.__init__(self, location, innerType.name) - self.inner = innerType - self.builtin = False - - def __eq__(self, other): - return isinstance(other, IDLNullableType) and self.inner == other.inner - - def __str__(self): - return self.inner.__str__() + "OrNull" - - def nullable(self): - return True - - def isCallback(self): - return self.inner.isCallback() - - def isPrimitive(self): - return self.inner.isPrimitive() - - def isBoolean(self): - return self.inner.isBoolean() - - def isNumeric(self): - return self.inner.isNumeric() - - def isString(self): - return self.inner.isString() - - def isByteString(self): - return self.inner.isByteString() - - def isDOMString(self): - return self.inner.isDOMString() - - def isScalarValueString(self): - return self.inner.isScalarValueString() - - def isFloat(self): - return self.inner.isFloat() - - def isUnrestricted(self): - return self.inner.isUnrestricted() - - def includesRestrictedFloat(self): - return self.inner.includesRestrictedFloat() - - def isInteger(self): - return self.inner.isInteger() - - def isVoid(self): - return False - - def isSequence(self): - return self.inner.isSequence() - - def isMozMap(self): - return self.inner.isMozMap() - - def isArray(self): - return self.inner.isArray() - - def isArrayBuffer(self): - return self.inner.isArrayBuffer() - - def isArrayBufferView(self): - return self.inner.isArrayBufferView() - - def isTypedArray(self): - return self.inner.isTypedArray() - - def isDictionary(self): - return self.inner.isDictionary() - - def isInterface(self): - return self.inner.isInterface() - - def isCallbackInterface(self): - return self.inner.isCallbackInterface() - - def isNonCallbackInterface(self): - return self.inner.isNonCallbackInterface() - - def isEnum(self): - return self.inner.isEnum() - - def isUnion(self): - return self.inner.isUnion() - - def isSerializable(self): - return self.inner.isSerializable() - - def tag(self): - return self.inner.tag() - - def resolveType(self, parentScope): - assert isinstance(parentScope, IDLScope) - self.inner.resolveType(parentScope) - - def isComplete(self): - return self.inner.isComplete() - - def complete(self, scope): - self.inner = self.inner.complete(scope) - if self.inner.nullable(): - raise WebIDLError("The inner type of a nullable type must not be " - "a nullable type", - [self.location, self.inner.location]) - if self.inner.isUnion(): - if self.inner.hasNullableType: - raise WebIDLError("The inner type of a nullable type must not " - "be a union type that itself has a nullable " - "type as a member type", [self.location]) - - self.name = self.inner.name - return self - - def unroll(self): - return self.inner.unroll() - - def isDistinguishableFrom(self, other): - if (other.nullable() or (other.isUnion() and other.hasNullableType) or - other.isDictionary()): - # Can't tell which type null should become - return False - return self.inner.isDistinguishableFrom(other) - - def _getDependentObjects(self): - return self.inner._getDependentObjects() - -class IDLSequenceType(IDLType): - def __init__(self, location, parameterType): - assert not parameterType.isVoid() - - IDLType.__init__(self, location, parameterType.name) - self.inner = parameterType - self.builtin = False - - def __eq__(self, other): - return isinstance(other, IDLSequenceType) and self.inner == other.inner - - def __str__(self): - return self.inner.__str__() + "Sequence" - - def nullable(self): - return False - - def isPrimitive(self): - return False; - - def isString(self): - return False; - - def isByteString(self): - return False - - def isDOMString(self): - return False - - def isScalarValueString(self): - return False - - def isVoid(self): - return False - - def isSequence(self): - return True - - def isArray(self): - return False - - def isDictionary(self): - return False - - def isInterface(self): - return False - - def isEnum(self): - return False - - def isSerializable(self): - return self.inner.isSerializable() - - def includesRestrictedFloat(self): - return self.inner.includesRestrictedFloat() - - def tag(self): - return IDLType.Tags.sequence - - def resolveType(self, parentScope): - assert isinstance(parentScope, IDLScope) - self.inner.resolveType(parentScope) - - def isComplete(self): - return self.inner.isComplete() - - def complete(self, scope): - self.inner = self.inner.complete(scope) - self.name = self.inner.name - return self - - def unroll(self): - return self.inner.unroll() - - def isDistinguishableFrom(self, other): - if other.isUnion(): - # Just forward to the union; it'll deal - return other.isDistinguishableFrom(self) - return (other.isPrimitive() or other.isString() or other.isEnum() or - other.isDate() or other.isNonCallbackInterface() or other.isMozMap()) - - def _getDependentObjects(self): - return self.inner._getDependentObjects() - -class IDLMozMapType(IDLType): - # XXXbz This is pretty similar to IDLSequenceType in various ways. - # And maybe to IDLNullableType. Should we have a superclass for - # "type containing this other type"? Bug 1015318. - def __init__(self, location, parameterType): - assert not parameterType.isVoid() - - IDLType.__init__(self, location, parameterType.name) - self.inner = parameterType - self.builtin = False - - def __eq__(self, other): - return isinstance(other, IDLMozMapType) and self.inner == other.inner - - def __str__(self): - return self.inner.__str__() + "MozMap" - - def isMozMap(self): - return True - - def includesRestrictedFloat(self): - return self.inner.includesRestrictedFloat() - - def tag(self): - return IDLType.Tags.mozmap - - def resolveType(self, parentScope): - assert isinstance(parentScope, IDLScope) - self.inner.resolveType(parentScope) - - def isComplete(self): - return self.inner.isComplete() - - def complete(self, scope): - self.inner = self.inner.complete(scope) - self.name = self.inner.name - return self - - def unroll(self): - # We do not unroll our inner. Just stop at ourselves. That - # lets us add headers for both ourselves and our inner as - # needed. - return self - - def isDistinguishableFrom(self, other): - if other.isUnion(): - # Just forward to the union; it'll deal - return other.isDistinguishableFrom(self) - return (other.isPrimitive() or other.isString() or other.isEnum() or - other.isDate() or other.isNonCallbackInterface() or other.isSequence()) - - def isExposedInAllOf(self, exposureSet): - return self.inner.unroll().isExposedInAllOf(exposureSet) - - def _getDependentObjects(self): - return self.inner._getDependentObjects() - -class IDLUnionType(IDLType): - def __init__(self, location, memberTypes): - IDLType.__init__(self, location, "") - self.memberTypes = memberTypes - self.hasNullableType = False - self.hasDictionaryType = False - self.flatMemberTypes = None - self.builtin = False - - def __eq__(self, other): - return isinstance(other, IDLUnionType) and self.memberTypes == other.memberTypes - - def isVoid(self): - return False - - def isUnion(self): - return True - - def isSerializable(self): - return all(m.isSerializable() for m in self.memberTypes) - - def includesRestrictedFloat(self): - return any(t.includesRestrictedFloat() for t in self.memberTypes) - - def tag(self): - return IDLType.Tags.union - - def resolveType(self, parentScope): - assert isinstance(parentScope, IDLScope) - for t in self.memberTypes: - t.resolveType(parentScope) - - def isComplete(self): - return self.flatMemberTypes is not None - - def complete(self, scope): - def typeName(type): - if isinstance(type, IDLNullableType): - return typeName(type.inner) + "OrNull" - if isinstance(type, IDLWrapperType): - return typeName(type._identifier.object()) - if isinstance(type, IDLObjectWithIdentifier): - return typeName(type.identifier) - if (isinstance(type, IDLType) and - (type.isArray() or type.isSequence() or type.isMozMap)): - return str(type) - return type.name - - for (i, type) in enumerate(self.memberTypes): - if not type.isComplete(): - self.memberTypes[i] = type.complete(scope) - - self.name = "Or".join(typeName(type) for type in self.memberTypes) - self.flatMemberTypes = list(self.memberTypes) - i = 0 - while i < len(self.flatMemberTypes): - if self.flatMemberTypes[i].nullable(): - if self.hasNullableType: - raise WebIDLError("Can't have more than one nullable types in a union", - [nullableType.location, self.flatMemberTypes[i].location]) - if self.hasDictionaryType: - raise WebIDLError("Can't have a nullable type and a " - "dictionary type in a union", - [dictionaryType.location, - self.flatMemberTypes[i].location]) - self.hasNullableType = True - nullableType = self.flatMemberTypes[i] - self.flatMemberTypes[i] = self.flatMemberTypes[i].inner - continue - if self.flatMemberTypes[i].isDictionary(): - if self.hasNullableType: - raise WebIDLError("Can't have a nullable type and a " - "dictionary type in a union", - [nullableType.location, - self.flatMemberTypes[i].location]) - self.hasDictionaryType = True - dictionaryType = self.flatMemberTypes[i] - elif self.flatMemberTypes[i].isUnion(): - self.flatMemberTypes[i:i + 1] = self.flatMemberTypes[i].memberTypes - continue - i += 1 - - for (i, t) in enumerate(self.flatMemberTypes[:-1]): - for u in self.flatMemberTypes[i + 1:]: - if not t.isDistinguishableFrom(u): - raise WebIDLError("Flat member types of a union should be " - "distinguishable, " + str(t) + " is not " - "distinguishable from " + str(u), - [self.location, t.location, u.location]) - - return self - - def isDistinguishableFrom(self, other): - if self.hasNullableType and other.nullable(): - # Can't tell which type null should become - return False - if other.isUnion(): - otherTypes = other.unroll().memberTypes - else: - otherTypes = [other] - # For every type in otherTypes, check that it's distinguishable from - # every type in our types - for u in otherTypes: - if any(not t.isDistinguishableFrom(u) for t in self.memberTypes): - return False - return True - - def isExposedInAllOf(self, exposureSet): - # We could have different member types in different globals. Just make sure that each thing in exposureSet has one of our member types exposed in it. - for globalName in exposureSet: - if not any(t.unroll().isExposedInAllOf(set([globalName])) for t - in self.flatMemberTypes): - return False - return True - - def _getDependentObjects(self): - return set(self.memberTypes) - -class IDLArrayType(IDLType): - def __init__(self, location, parameterType): - assert not parameterType.isVoid() - if parameterType.isSequence(): - raise WebIDLError("Array type cannot parameterize over a sequence type", - [location]) - if parameterType.isMozMap(): - raise WebIDLError("Array type cannot parameterize over a MozMap type", - [location]) - if parameterType.isDictionary(): - raise WebIDLError("Array type cannot parameterize over a dictionary type", - [location]) - - IDLType.__init__(self, location, parameterType.name) - self.inner = parameterType - self.builtin = False - - def __eq__(self, other): - return isinstance(other, IDLArrayType) and self.inner == other.inner - - def __str__(self): - return self.inner.__str__() + "Array" - - def nullable(self): - return False - - def isPrimitive(self): - return False - - def isString(self): - return False - - def isByteString(self): - return False - - def isDOMString(self): - return False - - def isScalarValueString(self): - return False - - def isVoid(self): - return False - - def isSequence(self): - assert not self.inner.isSequence() - return False - - def isArray(self): - return True - - def isDictionary(self): - assert not self.inner.isDictionary() - return False - - def isInterface(self): - return False - - def isEnum(self): - return False - - def tag(self): - return IDLType.Tags.array - - def resolveType(self, parentScope): - assert isinstance(parentScope, IDLScope) - self.inner.resolveType(parentScope) - - def isComplete(self): - return self.inner.isComplete() - - def complete(self, scope): - self.inner = self.inner.complete(scope) - self.name = self.inner.name - - if self.inner.isDictionary(): - raise WebIDLError("Array type must not contain " - "dictionary as element type.", - [self.inner.location]) - - assert not self.inner.isSequence() - - return self - - def unroll(self): - return self.inner.unroll() - - def isDistinguishableFrom(self, other): - if other.isUnion(): - # Just forward to the union; it'll deal - return other.isDistinguishableFrom(self) - return (other.isPrimitive() or other.isString() or other.isEnum() or - other.isDate() or other.isNonCallbackInterface()) - - def _getDependentObjects(self): - return self.inner._getDependentObjects() - -class IDLTypedefType(IDLType, IDLObjectWithIdentifier): - def __init__(self, location, innerType, name): - IDLType.__init__(self, location, innerType.name) - - identifier = IDLUnresolvedIdentifier(location, name) - - IDLObjectWithIdentifier.__init__(self, location, None, identifier) - - self.inner = innerType - self.name = name - self.builtin = False - - def __eq__(self, other): - return isinstance(other, IDLTypedefType) and self.inner == other.inner - - def __str__(self): - return self.identifier.name - - def nullable(self): - return self.inner.nullable() - - def isPrimitive(self): - return self.inner.isPrimitive() - - def isBoolean(self): - return self.inner.isBoolean() - - def isNumeric(self): - return self.inner.isNumeric() - - def isString(self): - return self.inner.isString() - - def isByteString(self): - return self.inner.isByteString() - - def isDOMString(self): - return self.inner.isDOMString() - - def isScalarValueString(self): - return self.inner.isScalarValueString() - - def isVoid(self): - return self.inner.isVoid() - - def isSequence(self): - return self.inner.isSequence() - - def isMozMap(self): - return self.inner.isMozMap() - - def isArray(self): - return self.inner.isArray() - - def isDictionary(self): - return self.inner.isDictionary() - - def isArrayBuffer(self): - return self.inner.isArrayBuffer() - - def isArrayBufferView(self): - return self.inner.isArrayBufferView() - - def isTypedArray(self): - return self.inner.isTypedArray() - - def isInterface(self): - return self.inner.isInterface() - - def isCallbackInterface(self): - return self.inner.isCallbackInterface() - - def isNonCallbackInterface(self): - return self.inner.isNonCallbackInterface() - - def isComplete(self): - return False - - def complete(self, parentScope): - if not self.inner.isComplete(): - self.inner = self.inner.complete(parentScope) - assert self.inner.isComplete() - return self.inner - - def finish(self, parentScope): - # Maybe the IDLObjectWithIdentifier for the typedef should be - # a separate thing from the type? If that happens, we can - # remove some hackery around avoiding isInterface() in - # Configuration.py. - self.complete(parentScope) - - def validate(self): - pass - - # Do we need a resolveType impl? I don't think it's particularly useful.... - - def tag(self): - return self.inner.tag() - - def unroll(self): - return self.inner.unroll() - - def isDistinguishableFrom(self, other): - return self.inner.isDistinguishableFrom(other) - - def _getDependentObjects(self): - return self.inner._getDependentObjects() - -class IDLWrapperType(IDLType): - def __init__(self, location, inner, promiseInnerType=None): - IDLType.__init__(self, location, inner.identifier.name) - self.inner = inner - self._identifier = inner.identifier - self.builtin = False - assert not promiseInnerType or inner.identifier.name == "Promise" - self._promiseInnerType = promiseInnerType - - def __eq__(self, other): - return isinstance(other, IDLWrapperType) and \ - self._identifier == other._identifier and \ - self.builtin == other.builtin - - def __str__(self): - return str(self.name) + " (Wrapper)" - - def nullable(self): - return False - - def isPrimitive(self): - return False - - def isString(self): - return False - - def isByteString(self): - return False - - def isDOMString(self): - return False - - def isScalarValueString(self): - return False - - def isVoid(self): - return False - - def isSequence(self): - return False - - def isArray(self): - return False - - def isDictionary(self): - return isinstance(self.inner, IDLDictionary) - - def isInterface(self): - return isinstance(self.inner, IDLInterface) or \ - isinstance(self.inner, IDLExternalInterface) - - def isCallbackInterface(self): - return self.isInterface() and self.inner.isCallback() - - def isNonCallbackInterface(self): - return self.isInterface() and not self.inner.isCallback() - - def isEnum(self): - return isinstance(self.inner, IDLEnum) - - def isPromise(self): - return isinstance(self.inner, IDLInterface) and \ - self.inner.identifier.name == "Promise" - - def isSerializable(self): - if self.isInterface(): - if self.inner.isExternal(): - return False - return any(m.isMethod() and m.isJsonifier() for m in self.inner.members) - elif self.isEnum(): - return True - elif self.isDictionary(): - return all(m.type.isSerializable() for m in self.inner.members) - else: - raise WebIDLError("IDLWrapperType wraps type %s that we don't know if " - "is serializable" % type(self.inner), [self.location]) - - def resolveType(self, parentScope): - assert isinstance(parentScope, IDLScope) - self.inner.resolve(parentScope) - - def isComplete(self): - return True - - def tag(self): - if self.isInterface(): - return IDLType.Tags.interface - elif self.isEnum(): - return IDLType.Tags.enum - elif self.isDictionary(): - return IDLType.Tags.dictionary - else: - assert False - - def isDistinguishableFrom(self, other): - if other.isUnion(): - # Just forward to the union; it'll deal - return other.isDistinguishableFrom(self) - assert self.isInterface() or self.isEnum() or self.isDictionary() - if self.isEnum(): - return (other.isPrimitive() or other.isInterface() or other.isObject() or - other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isArray() or - other.isDate()) - if self.isDictionary() and other.nullable(): - return False - if other.isPrimitive() or other.isString() or other.isEnum() or other.isDate(): - return True - if self.isDictionary(): - return other.isNonCallbackInterface() - - assert self.isInterface() - if other.isInterface(): - if other.isSpiderMonkeyInterface(): - # Just let |other| handle things - return other.isDistinguishableFrom(self) - assert self.isGeckoInterface() and other.isGeckoInterface() - if self.inner.isExternal() or other.unroll().inner.isExternal(): - return self != other - return (len(self.inner.interfacesBasedOnSelf & - other.unroll().inner.interfacesBasedOnSelf) == 0 and - (self.isNonCallbackInterface() or - other.isNonCallbackInterface())) - if (other.isDictionary() or other.isCallback() or - other.isSequence() or other.isMozMap() or other.isArray()): - return self.isNonCallbackInterface() - - # Not much else |other| can be - assert other.isObject() - return False - - def isExposedInAllOf(self, exposureSet): - if not self.isInterface(): - return True - iface = self.inner - if iface.isExternal(): - # Let's say true, though ideally we'd only do this when - # exposureSet contains the primary global's name. - return True - if (iface.identifier.name == "Promise" and - # Check the internal type - not self._promiseInnerType.unroll().isExposedInAllOf(exposureSet)): - return False - return iface.exposureSet.issuperset(exposureSet) - - def _getDependentObjects(self): - # NB: The codegen for an interface type depends on - # a) That the identifier is in fact an interface (as opposed to - # a dictionary or something else). - # b) The native type of the interface. - # If we depend on the interface object we will also depend on - # anything the interface depends on which is undesirable. We - # considered implementing a dependency just on the interface type - # file, but then every modification to an interface would cause this - # to be regenerated which is still undesirable. We decided not to - # depend on anything, reasoning that: - # 1) Changing the concrete type of the interface requires modifying - # Bindings.conf, which is still a global dependency. - # 2) Changing an interface to a dictionary (or vice versa) with the - # same identifier should be incredibly rare. - return set() - -class IDLBuiltinType(IDLType): - - Types = enum( - # The integer types - 'byte', - 'octet', - 'short', - 'unsigned_short', - 'long', - 'unsigned_long', - 'long_long', - 'unsigned_long_long', - # Additional primitive types - 'boolean', - 'unrestricted_float', - 'float', - 'unrestricted_double', - # IMPORTANT: "double" must be the last primitive type listed - 'double', - # Other types - 'any', - 'domstring', - 'bytestring', - 'scalarvaluestring', - 'object', - 'date', - 'void', - # Funny stuff - 'ArrayBuffer', - 'ArrayBufferView', - 'Int8Array', - 'Uint8Array', - 'Uint8ClampedArray', - 'Int16Array', - 'Uint16Array', - 'Int32Array', - 'Uint32Array', - 'Float32Array', - 'Float64Array' - ) - - TagLookup = { - Types.byte: IDLType.Tags.int8, - Types.octet: IDLType.Tags.uint8, - Types.short: IDLType.Tags.int16, - Types.unsigned_short: IDLType.Tags.uint16, - Types.long: IDLType.Tags.int32, - Types.unsigned_long: IDLType.Tags.uint32, - Types.long_long: IDLType.Tags.int64, - Types.unsigned_long_long: IDLType.Tags.uint64, - Types.boolean: IDLType.Tags.bool, - Types.unrestricted_float: IDLType.Tags.unrestricted_float, - Types.float: IDLType.Tags.float, - Types.unrestricted_double: IDLType.Tags.unrestricted_double, - Types.double: IDLType.Tags.double, - Types.any: IDLType.Tags.any, - Types.domstring: IDLType.Tags.domstring, - Types.bytestring: IDLType.Tags.bytestring, - Types.scalarvaluestring: IDLType.Tags.scalarvaluestring, - Types.object: IDLType.Tags.object, - Types.date: IDLType.Tags.date, - Types.void: IDLType.Tags.void, - Types.ArrayBuffer: IDLType.Tags.interface, - Types.ArrayBufferView: IDLType.Tags.interface, - Types.Int8Array: IDLType.Tags.interface, - Types.Uint8Array: IDLType.Tags.interface, - Types.Uint8ClampedArray: IDLType.Tags.interface, - Types.Int16Array: IDLType.Tags.interface, - Types.Uint16Array: IDLType.Tags.interface, - Types.Int32Array: IDLType.Tags.interface, - Types.Uint32Array: IDLType.Tags.interface, - Types.Float32Array: IDLType.Tags.interface, - Types.Float64Array: IDLType.Tags.interface - } - - def __init__(self, location, name, type): - IDLType.__init__(self, location, name) - self.builtin = True - self._typeTag = type - - def isPrimitive(self): - return self._typeTag <= IDLBuiltinType.Types.double - - def isBoolean(self): - return self._typeTag == IDLBuiltinType.Types.boolean - - def isNumeric(self): - return self.isPrimitive() and not self.isBoolean() - - def isString(self): - return self._typeTag == IDLBuiltinType.Types.domstring or \ - self._typeTag == IDLBuiltinType.Types.bytestring or \ - self._typeTag == IDLBuiltinType.Types.scalarvaluestring - - def isByteString(self): - return self._typeTag == IDLBuiltinType.Types.bytestring - - def isDOMString(self): - return self._typeTag == IDLBuiltinType.Types.domstring - - def isScalarValueString(self): - return self._typeTag == IDLBuiltinType.Types.scalarvaluestring - - def isInteger(self): - return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long - - def isArrayBuffer(self): - return self._typeTag == IDLBuiltinType.Types.ArrayBuffer - - def isArrayBufferView(self): - return self._typeTag == IDLBuiltinType.Types.ArrayBufferView - - def isTypedArray(self): - return self._typeTag >= IDLBuiltinType.Types.Int8Array and \ - self._typeTag <= IDLBuiltinType.Types.Float64Array - - def isInterface(self): - # TypedArray things are interface types per the TypedArray spec, - # but we handle them as builtins because SpiderMonkey implements - # all of it internally. - return self.isArrayBuffer() or \ - self.isArrayBufferView() or \ - self.isTypedArray() - - def isNonCallbackInterface(self): - # All the interfaces we can be are non-callback - return self.isInterface() - - def isFloat(self): - return self._typeTag == IDLBuiltinType.Types.float or \ - self._typeTag == IDLBuiltinType.Types.double or \ - self._typeTag == IDLBuiltinType.Types.unrestricted_float or \ - self._typeTag == IDLBuiltinType.Types.unrestricted_double - - def isUnrestricted(self): - assert self.isFloat() - return self._typeTag == IDLBuiltinType.Types.unrestricted_float or \ - self._typeTag == IDLBuiltinType.Types.unrestricted_double - - def isSerializable(self): - return self.isPrimitive() or self.isDOMString() or self.isDate() - - def includesRestrictedFloat(self): - return self.isFloat() and not self.isUnrestricted() - - def tag(self): - return IDLBuiltinType.TagLookup[self._typeTag] - - def isDistinguishableFrom(self, other): - if other.isUnion(): - # Just forward to the union; it'll deal - return other.isDistinguishableFrom(self) - if self.isBoolean(): - return (other.isNumeric() or other.isString() or other.isEnum() or - other.isInterface() or other.isObject() or - other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isArray() or - other.isDate()) - if self.isNumeric(): - return (other.isBoolean() or other.isString() or other.isEnum() or - other.isInterface() or other.isObject() or - other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isArray() or - other.isDate()) - if self.isString(): - return (other.isPrimitive() or other.isInterface() or - other.isObject() or - other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isArray() or - other.isDate()) - if self.isAny(): - # Can't tell "any" apart from anything - return False - if self.isObject(): - return other.isPrimitive() or other.isString() or other.isEnum() - if self.isDate(): - return (other.isPrimitive() or other.isString() or other.isEnum() or - other.isInterface() or other.isCallback() or - other.isDictionary() or other.isSequence() or - other.isMozMap() or other.isArray()) - if self.isVoid(): - return not other.isVoid() - # Not much else we could be! - assert self.isSpiderMonkeyInterface() - # Like interfaces, but we know we're not a callback - return (other.isPrimitive() or other.isString() or other.isEnum() or - other.isCallback() or other.isDictionary() or - other.isSequence() or other.isMozMap() or other.isArray() or - other.isDate() or - (other.isInterface() and ( - # ArrayBuffer is distinguishable from everything - # that's not an ArrayBuffer or a callback interface - (self.isArrayBuffer() and not other.isArrayBuffer()) or - # ArrayBufferView is distinguishable from everything - # that's not an ArrayBufferView or typed array. - (self.isArrayBufferView() and not other.isArrayBufferView() and - not other.isTypedArray()) or - # Typed arrays are distinguishable from everything - # except ArrayBufferView and the same type of typed - # array - (self.isTypedArray() and not other.isArrayBufferView() and not - (other.isTypedArray() and other.name == self.name))))) - - def _getDependentObjects(self): - return set() - -BuiltinTypes = { - IDLBuiltinType.Types.byte: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Byte", - IDLBuiltinType.Types.byte), - IDLBuiltinType.Types.octet: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Octet", - IDLBuiltinType.Types.octet), - IDLBuiltinType.Types.short: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Short", - IDLBuiltinType.Types.short), - IDLBuiltinType.Types.unsigned_short: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedShort", - IDLBuiltinType.Types.unsigned_short), - IDLBuiltinType.Types.long: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Long", - IDLBuiltinType.Types.long), - IDLBuiltinType.Types.unsigned_long: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLong", - IDLBuiltinType.Types.unsigned_long), - IDLBuiltinType.Types.long_long: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "LongLong", - IDLBuiltinType.Types.long_long), - IDLBuiltinType.Types.unsigned_long_long: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLongLong", - IDLBuiltinType.Types.unsigned_long_long), - IDLBuiltinType.Types.boolean: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Boolean", - IDLBuiltinType.Types.boolean), - IDLBuiltinType.Types.float: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float", - IDLBuiltinType.Types.float), - IDLBuiltinType.Types.unrestricted_float: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedFloat", - IDLBuiltinType.Types.unrestricted_float), - IDLBuiltinType.Types.double: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Double", - IDLBuiltinType.Types.double), - IDLBuiltinType.Types.unrestricted_double: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedDouble", - IDLBuiltinType.Types.unrestricted_double), - IDLBuiltinType.Types.any: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Any", - IDLBuiltinType.Types.any), - IDLBuiltinType.Types.domstring: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "String", - IDLBuiltinType.Types.domstring), - IDLBuiltinType.Types.bytestring: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "ByteString", - IDLBuiltinType.Types.bytestring), - IDLBuiltinType.Types.scalarvaluestring: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "ScalarValueString", - IDLBuiltinType.Types.scalarvaluestring), - IDLBuiltinType.Types.object: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object", - IDLBuiltinType.Types.object), - IDLBuiltinType.Types.date: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Date", - IDLBuiltinType.Types.date), - IDLBuiltinType.Types.void: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Void", - IDLBuiltinType.Types.void), - IDLBuiltinType.Types.ArrayBuffer: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBuffer", - IDLBuiltinType.Types.ArrayBuffer), - IDLBuiltinType.Types.ArrayBufferView: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBufferView", - IDLBuiltinType.Types.ArrayBufferView), - IDLBuiltinType.Types.Int8Array: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array", - IDLBuiltinType.Types.Int8Array), - IDLBuiltinType.Types.Uint8Array: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8Array", - IDLBuiltinType.Types.Uint8Array), - IDLBuiltinType.Types.Uint8ClampedArray: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8ClampedArray", - IDLBuiltinType.Types.Uint8ClampedArray), - IDLBuiltinType.Types.Int16Array: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int16Array", - IDLBuiltinType.Types.Int16Array), - IDLBuiltinType.Types.Uint16Array: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint16Array", - IDLBuiltinType.Types.Uint16Array), - IDLBuiltinType.Types.Int32Array: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int32Array", - IDLBuiltinType.Types.Int32Array), - IDLBuiltinType.Types.Uint32Array: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint32Array", - IDLBuiltinType.Types.Uint32Array), - IDLBuiltinType.Types.Float32Array: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float32Array", - IDLBuiltinType.Types.Float32Array), - IDLBuiltinType.Types.Float64Array: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float64Array", - IDLBuiltinType.Types.Float64Array) - } - - -integerTypeSizes = { - IDLBuiltinType.Types.byte: (-128, 127), - IDLBuiltinType.Types.octet: (0, 255), - IDLBuiltinType.Types.short: (-32768, 32767), - IDLBuiltinType.Types.unsigned_short: (0, 65535), - IDLBuiltinType.Types.long: (-2147483648, 2147483647), - IDLBuiltinType.Types.unsigned_long: (0, 4294967295), - IDLBuiltinType.Types.long_long: (-9223372036854775808, - 9223372036854775807), - IDLBuiltinType.Types.unsigned_long_long: (0, 18446744073709551615) - } - -def matchIntegerValueToType(value): - for type, extremes in integerTypeSizes.items(): - (min, max) = extremes - if value <= max and value >= min: - return BuiltinTypes[type] - - return None - -class IDLValue(IDLObject): - def __init__(self, location, type, value): - IDLObject.__init__(self, location) - self.type = type - assert isinstance(type, IDLType) - - self.value = value - - def coerceToType(self, type, location): - if type == self.type: - return self # Nothing to do - - # We first check for unions to ensure that even if the union is nullable - # we end up with the right flat member type, not the union's type. - if type.isUnion(): - # We use the flat member types here, because if we have a nullable - # member type, or a nested union, we want the type the value - # actually coerces to, not the nullable or nested union type. - for subtype in type.unroll().flatMemberTypes: - try: - coercedValue = self.coerceToType(subtype, location) - # Create a new IDLValue to make sure that we have the - # correct float/double type. This is necessary because we - # use the value's type when it is a default value of a - # union, and the union cares about the exact float type. - return IDLValue(self.location, subtype, coercedValue.value) - except: - pass - # If the type allows null, rerun this matching on the inner type, except - # nullable enums. We handle those specially, because we want our - # default string values to stay strings even when assigned to a nullable - # enum. - elif type.nullable() and not type.isEnum(): - innerValue = self.coerceToType(type.inner, location) - return IDLValue(self.location, type, innerValue.value) - - elif self.type.isInteger() and type.isInteger(): - # We're both integer types. See if we fit. - - (min, max) = integerTypeSizes[type._typeTag] - if self.value <= max and self.value >= min: - # Promote - return IDLValue(self.location, type, self.value) - else: - raise WebIDLError("Value %s is out of range for type %s." % - (self.value, type), [location]) - elif self.type.isInteger() and type.isFloat(): - # Convert an integer literal into float - if -2**24 <= self.value <= 2**24: - floatType = BuiltinTypes[IDLBuiltinType.Types.float] - return IDLValue(self.location, floatType, float(self.value)) - else: - raise WebIDLError("Converting value %s to %s will lose precision." % - (self.value, type), [location]) - elif self.type.isString() and type.isEnum(): - # Just keep our string, but make sure it's a valid value for this enum - enum = type.unroll().inner - if self.value not in enum.values(): - raise WebIDLError("'%s' is not a valid default value for enum %s" - % (self.value, enum.identifier.name), - [location, enum.location]) - return self - elif self.type.isFloat() and type.isFloat(): - if (not type.isUnrestricted() and - (self.value == float("inf") or self.value == float("-inf") or - math.isnan(self.value))): - raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted" - % self.value, [location]); - return self - elif self.type.isString() and type.isScalarValueString(): - # Allow ScalarValueStrings to use default value just like - # DOMString. No coercion is required in this case as Codegen.py - # treats ScalarValueString just like DOMString, but with an - # extra normalization step. - assert self.type.isDOMString() - return self - raise WebIDLError("Cannot coerce type %s to type %s." % - (self.type, type), [location]) - - def _getDependentObjects(self): - return set() - -class IDLNullValue(IDLObject): - def __init__(self, location): - IDLObject.__init__(self, location) - self.type = None - self.value = None - - def coerceToType(self, type, location): - if (not isinstance(type, IDLNullableType) and - not (type.isUnion() and type.hasNullableType) and - not (type.isUnion() and type.hasDictionaryType) and - not type.isDictionary() and - not type.isAny()): - raise WebIDLError("Cannot coerce null value to type %s." % type, - [location]) - - nullValue = IDLNullValue(self.location) - if type.isUnion() and not type.nullable() and type.hasDictionaryType: - # We're actually a default value for the union's dictionary member. - # Use its type. - for t in type.flatMemberTypes: - if t.isDictionary(): - nullValue.type = t - return nullValue - nullValue.type = type - return nullValue - - def _getDependentObjects(self): - return set() - -class IDLEmptySequenceValue(IDLObject): - def __init__(self, location): - IDLObject.__init__(self, location) - self.type = None - self.value = None - - def coerceToType(self, type, location): - if type.isUnion(): - # We use the flat member types here, because if we have a nullable - # member type, or a nested union, we want the type the value - # actually coerces to, not the nullable or nested union type. - for subtype in type.unroll().flatMemberTypes: - try: - return self.coerceToType(subtype, location) - except: - pass - - if not type.isSequence(): - raise WebIDLError("Cannot coerce empty sequence value to type %s." % type, - [location]) - - emptySequenceValue = IDLEmptySequenceValue(self.location) - emptySequenceValue.type = type - return emptySequenceValue - - def _getDependentObjects(self): - return set() - -class IDLUndefinedValue(IDLObject): - def __init__(self, location): - IDLObject.__init__(self, location) - self.type = None - self.value = None - - def coerceToType(self, type, location): - if not type.isAny(): - raise WebIDLError("Cannot coerce undefined value to type %s." % type, - [location]) - - undefinedValue = IDLUndefinedValue(self.location) - undefinedValue.type = type - return undefinedValue - - def _getDependentObjects(self): - return set() - -class IDLInterfaceMember(IDLObjectWithIdentifier): - - Tags = enum( - 'Const', - 'Attr', - 'Method' - ) - - Special = enum( - 'Static', - 'Stringifier' - ) - - def __init__(self, location, identifier, tag): - IDLObjectWithIdentifier.__init__(self, location, None, identifier) - self.tag = tag - self._extendedAttrDict = {} - # _exposureGlobalNames are the global names listed in our [Exposed] - # extended attribute. exposureSet is the exposure set as defined in the - # Web IDL spec: it contains interface names. - self._exposureGlobalNames = set() - self.exposureSet = set() - - def isMethod(self): - return self.tag == IDLInterfaceMember.Tags.Method - - def isAttr(self): - return self.tag == IDLInterfaceMember.Tags.Attr - - def isConst(self): - return self.tag == IDLInterfaceMember.Tags.Const - - def addExtendedAttributes(self, attrs): - for attr in attrs: - self.handleExtendedAttribute(attr) - attrlist = attr.listValue() - self._extendedAttrDict[attr.identifier()] = attrlist if len(attrlist) else True - - def handleExtendedAttribute(self, attr): - pass - - def getExtendedAttribute(self, name): - return self._extendedAttrDict.get(name, None) - - def finish(self, scope): - for globalName in self._exposureGlobalNames: - if globalName not in scope.globalNames: - raise WebIDLError("Unknown [Exposed] value %s" % globalName, - [self.location]) - globalNameSetToExposureSet(scope, self._exposureGlobalNames, - self.exposureSet) - self._scope = scope - - def validate(self): - if (self.getExtendedAttribute("Pref") and - self.exposureSet != set([self._scope.primaryGlobalName])): - raise WebIDLError("[Pref] used on an interface member that is not " - "%s-only" % self._scope.primaryGlobalName, - [self.location]) - -class IDLConst(IDLInterfaceMember): - def __init__(self, location, identifier, type, value): - IDLInterfaceMember.__init__(self, location, identifier, - IDLInterfaceMember.Tags.Const) - - assert isinstance(type, IDLType) - if type.isDictionary(): - raise WebIDLError("A constant cannot be of a dictionary type", - [self.location]) - self.type = type - self.value = value - - if identifier.name == "prototype": - raise WebIDLError("The identifier of a constant must not be 'prototype'", - [location]) - - def __str__(self): - return "'%s' const '%s'" % (self.type, self.identifier) - - def finish(self, scope): - IDLInterfaceMember.finish(self, scope) - - if not self.type.isComplete(): - type = self.type.complete(scope) - if not type.isPrimitive() and not type.isString(): - locations = [self.type.location, type.location] - try: - locations.append(type.inner.location) - except: - pass - raise WebIDLError("Incorrect type for constant", locations) - self.type = type - - # The value might not match the type - coercedValue = self.value.coerceToType(self.type, self.location) - assert coercedValue - - self.value = coercedValue - - def validate(self): - IDLInterfaceMember.validate(self) - - def handleExtendedAttribute(self, attr): - identifier = attr.identifier() - if identifier == "Exposed": - convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames) - elif (identifier == "Pref" or - identifier == "ChromeOnly" or - identifier == "Func" or - identifier == "AvailableIn" or - identifier == "CheckPermissions"): - # Known attributes that we don't need to do anything with here - pass - else: - raise WebIDLError("Unknown extended attribute %s on constant" % identifier, - [attr.location]) - IDLInterfaceMember.handleExtendedAttribute(self, attr) - - def _getDependentObjects(self): - return set([self.type, self.value]) - -class IDLAttribute(IDLInterfaceMember): - def __init__(self, location, identifier, type, readonly, inherit=False, - static=False, stringifier=False): - IDLInterfaceMember.__init__(self, location, identifier, - IDLInterfaceMember.Tags.Attr) - - assert isinstance(type, IDLType) - self.type = type - self.readonly = readonly - self.inherit = inherit - self.static = static - self.lenientThis = False - self._unforgeable = False - self.stringifier = stringifier - self.enforceRange = False - self.clamp = False - self.slotIndex = None - - if static and identifier.name == "prototype": - raise WebIDLError("The identifier of a static attribute must not be 'prototype'", - [location]) - - if readonly and inherit: - raise WebIDLError("An attribute cannot be both 'readonly' and 'inherit'", - [self.location]) - - def isStatic(self): - return self.static - - def __str__(self): - return "'%s' attribute '%s'" % (self.type, self.identifier) - - def finish(self, scope): - IDLInterfaceMember.finish(self, scope) - - if not self.type.isComplete(): - t = self.type.complete(scope) - - assert not isinstance(t, IDLUnresolvedType) - assert not isinstance(t, IDLTypedefType) - assert not isinstance(t.name, IDLUnresolvedIdentifier) - self.type = t - - if self.type.isDictionary() and not self.getExtendedAttribute("Cached"): - raise WebIDLError("An attribute cannot be of a dictionary type", - [self.location]) - if self.type.isSequence() and not self.getExtendedAttribute("Cached"): - raise WebIDLError("A non-cached attribute cannot be of a sequence " - "type", [self.location]) - if self.type.isMozMap() and not self.getExtendedAttribute("Cached"): - raise WebIDLError("A non-cached attribute cannot be of a MozMap " - "type", [self.location]) - if self.type.isUnion(): - for f in self.type.unroll().flatMemberTypes: - if f.isDictionary(): - raise WebIDLError("An attribute cannot be of a union " - "type if one of its member types (or " - "one of its member types's member " - "types, and so on) is a dictionary " - "type", [self.location, f.location]) - if f.isSequence(): - raise WebIDLError("An attribute cannot be of a union " - "type if one of its member types (or " - "one of its member types's member " - "types, and so on) is a sequence " - "type", [self.location, f.location]) - if f.isMozMap(): - raise WebIDLError("An attribute cannot be of a union " - "type if one of its member types (or " - "one of its member types's member " - "types, and so on) is a MozMap " - "type", [self.location, f.location]) - if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"): - raise WebIDLError("An attribute with [PutForwards] must have an " - "interface type as its type", [self.location]) - - if not self.type.isInterface() and self.getExtendedAttribute("SameObject"): - raise WebIDLError("An attribute with [SameObject] must have an " - "interface type as its type", [self.location]) - - def validate(self): - IDLInterfaceMember.validate(self) - - if ((self.getExtendedAttribute("Cached") or - self.getExtendedAttribute("StoreInSlot")) and - not self.getExtendedAttribute("Constant") and - not self.getExtendedAttribute("Pure")): - raise WebIDLError("Cached attributes and attributes stored in " - "slots must be constant or pure, since the " - "getter won't always be called.", - [self.location]) - if self.getExtendedAttribute("Frozen"): - if (not self.type.isSequence() and not self.type.isDictionary() and - not self.type.isMozMap()): - raise WebIDLError("[Frozen] is only allowed on " - "sequence-valued, dictionary-valued, and " - "MozMap-valued attributes", - [self.location]) - if not self.type.unroll().isExposedInAllOf(self.exposureSet): - raise WebIDLError("Attribute returns a type that is not exposed " - "everywhere where the attribute is exposed", - [self.location]) - - def handleExtendedAttribute(self, attr): - identifier = attr.identifier() - if identifier == "SetterThrows" and self.readonly: - raise WebIDLError("Readonly attributes must not be flagged as " - "[SetterThrows]", - [self.location]) - elif (((identifier == "Throws" or identifier == "GetterThrows") and - self.getExtendedAttribute("StoreInSlot")) or - (identifier == "StoreInSlot" and - (self.getExtendedAttribute("Throws") or - self.getExtendedAttribute("GetterThrows")))): - raise WebIDLError("Throwing things can't be [Pure] or [Constant] " - "or [SameObject] or [StoreInSlot]", - [attr.location]) - elif identifier == "LenientThis": - if not attr.noArguments(): - raise WebIDLError("[LenientThis] must take no arguments", - [attr.location]) - if self.isStatic(): - raise WebIDLError("[LenientThis] is only allowed on non-static " - "attributes", [attr.location, self.location]) - if self.getExtendedAttribute("CrossOriginReadable"): - raise WebIDLError("[LenientThis] is not allowed in combination " - "with [CrossOriginReadable]", - [attr.location, self.location]) - if self.getExtendedAttribute("CrossOriginWritable"): - raise WebIDLError("[LenientThis] is not allowed in combination " - "with [CrossOriginWritable]", - [attr.location, self.location]) - self.lenientThis = True - elif identifier == "Unforgeable": - if self.isStatic(): - raise WebIDLError("[Unforgeable] is only allowed on non-static " - "attributes", [attr.location, self.location]) - self._unforgeable = True - elif identifier == "SameObject" and not self.readonly: - raise WebIDLError("[SameObject] only allowed on readonly attributes", - [attr.location, self.location]) - elif identifier == "Constant" and not self.readonly: - raise WebIDLError("[Constant] only allowed on readonly attributes", - [attr.location, self.location]) - elif identifier == "PutForwards": - if not self.readonly: - raise WebIDLError("[PutForwards] is only allowed on readonly " - "attributes", [attr.location, self.location]) - if self.isStatic(): - raise WebIDLError("[PutForwards] is only allowed on non-static " - "attributes", [attr.location, self.location]) - if self.getExtendedAttribute("Replaceable") is not None: - raise WebIDLError("[PutForwards] and [Replaceable] can't both " - "appear on the same attribute", - [attr.location, self.location]) - if not attr.hasValue(): - raise WebIDLError("[PutForwards] takes an identifier", - [attr.location, self.location]) - elif identifier == "Replaceable": - if self.getExtendedAttribute("PutForwards") is not None: - raise WebIDLError("[PutForwards] and [Replaceable] can't both " - "appear on the same attribute", - [attr.location, self.location]) - elif identifier == "LenientFloat": - if self.readonly: - raise WebIDLError("[LenientFloat] used on a readonly attribute", - [attr.location, self.location]) - if not self.type.includesRestrictedFloat(): - raise WebIDLError("[LenientFloat] used on an attribute with a " - "non-restricted-float type", - [attr.location, self.location]) - elif identifier == "EnforceRange": - if self.readonly: - raise WebIDLError("[EnforceRange] used on a readonly attribute", - [attr.location, self.location]) - self.enforceRange = True - elif identifier == "Clamp": - if self.readonly: - raise WebIDLError("[Clamp] used on a readonly attribute", - [attr.location, self.location]) - self.clamp = True - elif identifier == "StoreInSlot": - if self.getExtendedAttribute("Cached"): - raise WebIDLError("[StoreInSlot] and [Cached] must not be " - "specified on the same attribute", - [attr.location, self.location]) - elif identifier == "Cached": - if self.getExtendedAttribute("StoreInSlot"): - raise WebIDLError("[Cached] and [StoreInSlot] must not be " - "specified on the same attribute", - [attr.location, self.location]) - elif (identifier == "CrossOriginReadable" or - identifier == "CrossOriginWritable"): - if not attr.noArguments() and identifier == "CrossOriginReadable": - raise WebIDLError("[%s] must take no arguments" % identifier, - [attr.location]) - if self.isStatic(): - raise WebIDLError("[%s] is only allowed on non-static " - "attributes" % identifier, - [attr.location, self.location]) - if self.getExtendedAttribute("LenientThis"): - raise WebIDLError("[LenientThis] is not allowed in combination " - "with [%s]" % identifier, - [attr.location, self.location]) - elif identifier == "Exposed": - convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames) - elif (identifier == "Pref" or - identifier == "SetterThrows" or - identifier == "Pure" or - identifier == "Throws" or - identifier == "GetterThrows" or - identifier == "ChromeOnly" or - identifier == "SameObject" or - identifier == "Constant" or - identifier == "Func" or - identifier == "Frozen" or - identifier == "AvailableIn" or - identifier == "NewObject" or - identifier == "CheckPermissions"): - # Known attributes that we don't need to do anything with here - pass - else: - raise WebIDLError("Unknown extended attribute %s on attribute" % identifier, - [attr.location]) - IDLInterfaceMember.handleExtendedAttribute(self, attr) - - def resolve(self, parentScope): - assert isinstance(parentScope, IDLScope) - self.type.resolveType(parentScope) - IDLObjectWithIdentifier.resolve(self, parentScope) - - def addExtendedAttributes(self, attrs): - attrs = self.checkForStringHandlingExtendedAttributes(attrs) - IDLInterfaceMember.addExtendedAttributes(self, attrs) - - def hasLenientThis(self): - return self.lenientThis - - def isUnforgeable(self): - return self._unforgeable - - def _getDependentObjects(self): - return set([self.type]) - -class IDLArgument(IDLObjectWithIdentifier): - def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False): - IDLObjectWithIdentifier.__init__(self, location, None, identifier) - - assert isinstance(type, IDLType) - self.type = type - - self.optional = optional - self.defaultValue = defaultValue - self.variadic = variadic - self.dictionaryMember = dictionaryMember - self._isComplete = False - self.enforceRange = False - self.clamp = False - self._allowTreatNonCallableAsNull = False - - assert not variadic or optional - - def addExtendedAttributes(self, attrs): - attrs = self.checkForStringHandlingExtendedAttributes( - attrs, - isDictionaryMember=self.dictionaryMember, - isOptional=self.optional) - for attribute in attrs: - identifier = attribute.identifier() - if identifier == "Clamp": - if not attribute.noArguments(): - raise WebIDLError("[Clamp] must take no arguments", - [attribute.location]) - if self.enforceRange: - raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive", - [self.location]); - self.clamp = True - elif identifier == "EnforceRange": - if not attribute.noArguments(): - raise WebIDLError("[EnforceRange] must take no arguments", - [attribute.location]) - if self.clamp: - raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive", - [self.location]); - self.enforceRange = True - elif identifier == "TreatNonCallableAsNull": - self._allowTreatNonCallableAsNull = True - else: - raise WebIDLError("Unhandled extended attribute on an argument", - [attribute.location]) - - def isComplete(self): - return self._isComplete - - def complete(self, scope): - if self._isComplete: - return - - self._isComplete = True - - if not self.type.isComplete(): - type = self.type.complete(scope) - assert not isinstance(type, IDLUnresolvedType) - assert not isinstance(type, IDLTypedefType) - assert not isinstance(type.name, IDLUnresolvedIdentifier) - self.type = type - - if ((self.type.isDictionary() or - self.type.isUnion() and self.type.unroll().hasDictionaryType) and - self.optional and not self.defaultValue): - # Default optional dictionaries to null, for simplicity, - # so the codegen doesn't have to special-case this. - self.defaultValue = IDLNullValue(self.location) - elif self.type.isAny(): - assert (self.defaultValue is None or - isinstance(self.defaultValue, IDLNullValue)) - # optional 'any' values always have a default value - if self.optional and not self.defaultValue and not self.variadic: - # Set the default value to undefined, for simplicity, so the - # codegen doesn't have to special-case this. - self.defaultValue = IDLUndefinedValue(self.location) - - # Now do the coercing thing; this needs to happen after the - # above creation of a default value. - if self.defaultValue: - self.defaultValue = self.defaultValue.coerceToType(self.type, - self.location) - assert self.defaultValue - - def allowTreatNonCallableAsNull(self): - return self._allowTreatNonCallableAsNull - - def _getDependentObjects(self): - deps = set([self.type]) - if self.defaultValue: - deps.add(self.defaultValue) - return deps - -class IDLCallbackType(IDLType, IDLObjectWithScope): - def __init__(self, location, parentScope, identifier, returnType, arguments): - assert isinstance(returnType, IDLType) - - IDLType.__init__(self, location, identifier.name) - - self._returnType = returnType - # Clone the list - self._arguments = list(arguments) - - IDLObjectWithScope.__init__(self, location, parentScope, identifier) - - for (returnType, arguments) in self.signatures(): - for argument in arguments: - argument.resolve(self) - - self._treatNonCallableAsNull = False - self._treatNonObjectAsNull = False - - def module(self): - return self.location.filename().split('/')[-1].split('.webidl')[0] + 'Binding' - - def isCallback(self): - return True - - def signatures(self): - return [(self._returnType, self._arguments)] - - def tag(self): - return IDLType.Tags.callback - - def finish(self, scope): - if not self._returnType.isComplete(): - type = self._returnType.complete(scope) - - assert not isinstance(type, IDLUnresolvedType) - assert not isinstance(type, IDLTypedefType) - assert not isinstance(type.name, IDLUnresolvedIdentifier) - self._returnType = type - - for argument in self._arguments: - if argument.type.isComplete(): - continue - - type = argument.type.complete(scope) - - assert not isinstance(type, IDLUnresolvedType) - assert not isinstance(type, IDLTypedefType) - assert not isinstance(type.name, IDLUnresolvedIdentifier) - argument.type = type - - def validate(self): - pass - - def isDistinguishableFrom(self, other): - if other.isUnion(): - # Just forward to the union; it'll deal - return other.isDistinguishableFrom(self) - return (other.isPrimitive() or other.isString() or other.isEnum() or - other.isNonCallbackInterface() or other.isDate()) - - def addExtendedAttributes(self, attrs): - unhandledAttrs = [] - for attr in attrs: - if attr.identifier() == "TreatNonCallableAsNull": - self._treatNonCallableAsNull = True - elif attr.identifier() == "TreatNonObjectAsNull": - self._treatNonObjectAsNull = True - else: - unhandledAttrs.append(attr) - if self._treatNonCallableAsNull and self._treatNonObjectAsNull: - raise WebIDLError("Cannot specify both [TreatNonCallableAsNull] " - "and [TreatNonObjectAsNull]", [self.location]) - if len(unhandledAttrs) != 0: - IDLType.addExtendedAttributes(self, unhandledAttrs) - - def _getDependentObjects(self): - return set([self._returnType] + self._arguments) - -class IDLMethodOverload: - """ - A class that represents a single overload of a WebIDL method. This is not - quite the same as an element of the "effective overload set" in the spec, - because separate IDLMethodOverloads are not created based on arguments being - optional. Rather, when multiple methods have the same name, there is an - IDLMethodOverload for each one, all hanging off an IDLMethod representing - the full set of overloads. - """ - def __init__(self, returnType, arguments, location): - self.returnType = returnType - # Clone the list of arguments, just in case - self.arguments = list(arguments) - self.location = location - - def _getDependentObjects(self): - deps = set(self.arguments) - deps.add(self.returnType) - return deps - -class IDLMethod(IDLInterfaceMember, IDLScope): - - Special = enum( - 'Getter', - 'Setter', - 'Creator', - 'Deleter', - 'LegacyCaller', - base=IDLInterfaceMember.Special - ) - - TypeSuffixModifier = enum( - 'None', - 'QMark', - 'Brackets' - ) - - NamedOrIndexed = enum( - 'Neither', - 'Named', - 'Indexed' - ) - - def __init__(self, location, identifier, returnType, arguments, - static=False, getter=False, setter=False, creator=False, - deleter=False, specialType=NamedOrIndexed.Neither, - legacycaller=False, stringifier=False, jsonifier=False): - # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up. - IDLInterfaceMember.__init__(self, location, identifier, - IDLInterfaceMember.Tags.Method) - - self._hasOverloads = False - - assert isinstance(returnType, IDLType) - - # self._overloads is a list of IDLMethodOverloads - self._overloads = [IDLMethodOverload(returnType, arguments, location)] - - assert isinstance(static, bool) - self._static = static - assert isinstance(getter, bool) - self._getter = getter - assert isinstance(setter, bool) - self._setter = setter - assert isinstance(creator, bool) - self._creator = creator - assert isinstance(deleter, bool) - self._deleter = deleter - assert isinstance(legacycaller, bool) - self._legacycaller = legacycaller - assert isinstance(stringifier, bool) - self._stringifier = stringifier - assert isinstance(jsonifier, bool) - self._jsonifier = jsonifier - self._specialType = specialType - self._unforgeable = False - - if static and identifier.name == "prototype": - raise WebIDLError("The identifier of a static operation must not be 'prototype'", - [location]) - - self.assertSignatureConstraints() - - def __str__(self): - return "Method '%s'" % self.identifier - - def assertSignatureConstraints(self): - if self._getter or self._deleter: - assert len(self._overloads) == 1 - overload = self._overloads[0] - arguments = overload.arguments - assert len(arguments) == 1 - assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \ - arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long] - assert not arguments[0].optional and not arguments[0].variadic - assert not self._getter or not overload.returnType.isVoid() - - if self._setter or self._creator: - assert len(self._overloads) == 1 - arguments = self._overloads[0].arguments - assert len(arguments) == 2 - assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \ - arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long] - assert not arguments[0].optional and not arguments[0].variadic - assert not arguments[1].optional and not arguments[1].variadic - - if self._stringifier: - assert len(self._overloads) == 1 - overload = self._overloads[0] - assert len(overload.arguments) == 0 - assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring] - - if self._jsonifier: - assert len(self._overloads) == 1 - overload = self._overloads[0] - assert len(overload.arguments) == 0 - assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.object] - - def isStatic(self): - return self._static - - def isGetter(self): - return self._getter - - def isSetter(self): - return self._setter - - def isCreator(self): - return self._creator - - def isDeleter(self): - return self._deleter - - def isNamed(self): - assert self._specialType == IDLMethod.NamedOrIndexed.Named or \ - self._specialType == IDLMethod.NamedOrIndexed.Indexed - return self._specialType == IDLMethod.NamedOrIndexed.Named - - def isIndexed(self): - assert self._specialType == IDLMethod.NamedOrIndexed.Named or \ - self._specialType == IDLMethod.NamedOrIndexed.Indexed - return self._specialType == IDLMethod.NamedOrIndexed.Indexed - - def isLegacycaller(self): - return self._legacycaller - - def isStringifier(self): - return self._stringifier - - def isJsonifier(self): - return self._jsonifier - - def hasOverloads(self): - return self._hasOverloads - - def isIdentifierLess(self): - return self.identifier.name[:2] == "__" and self.identifier.name != "__noSuchMethod__" - - def resolve(self, parentScope): - assert isinstance(parentScope, IDLScope) - IDLObjectWithIdentifier.resolve(self, parentScope) - IDLScope.__init__(self, self.location, parentScope, self.identifier) - for (returnType, arguments) in self.signatures(): - for argument in arguments: - argument.resolve(self) - - def addOverload(self, method): - assert len(method._overloads) == 1 - - if self._extendedAttrDict != method ._extendedAttrDict: - raise WebIDLError("Extended attributes differ on different " - "overloads of %s" % method.identifier, - [self.location, method.location]) - - self._overloads.extend(method._overloads) - - self._hasOverloads = True - - if self.isStatic() != method.isStatic(): - raise WebIDLError("Overloaded identifier %s appears with different values of the 'static' attribute" % method.identifier, - [method.location]) - - if self.isLegacycaller() != method.isLegacycaller(): - raise WebIDLError("Overloaded identifier %s appears with different values of the 'legacycaller' attribute" % method.identifier, - [method.location]) - - # Can't overload special things! - assert not self.isGetter() - assert not method.isGetter() - assert not self.isSetter() - assert not method.isSetter() - assert not self.isCreator() - assert not method.isCreator() - assert not self.isDeleter() - assert not method.isDeleter() - assert not self.isStringifier() - assert not method.isStringifier() - assert not self.isJsonifier() - assert not method.isJsonifier() - - return self - - def signatures(self): - return [(overload.returnType, overload.arguments) for overload in - self._overloads] - - def finish(self, scope): - IDLInterfaceMember.finish(self, scope) - - overloadWithPromiseReturnType = None - overloadWithoutPromiseReturnType = None - for overload in self._overloads: - variadicArgument = None - - arguments = overload.arguments - for (idx, argument) in enumerate(arguments): - if not argument.isComplete(): - argument.complete(scope) - assert argument.type.isComplete() - - if (argument.type.isDictionary() or - (argument.type.isUnion() and - argument.type.unroll().hasDictionaryType)): - # Dictionaries and unions containing dictionaries at the - # end of the list or followed by optional arguments must be - # optional. - if (not argument.optional and - all(arg.optional for arg in arguments[idx+1:])): - raise WebIDLError("Dictionary argument or union " - "argument containing a dictionary " - "not followed by a required argument " - "must be optional", - [argument.location]) - - # An argument cannot be a Nullable Dictionary - if argument.type.nullable(): - raise WebIDLError("An argument cannot be a nullable " - "dictionary or nullable union " - "containing a dictionary", - [argument.location]) - - # Only the last argument can be variadic - if variadicArgument: - raise WebIDLError("Variadic argument is not last argument", - [variadicArgument.location]) - if argument.variadic: - variadicArgument = argument - - returnType = overload.returnType - if not returnType.isComplete(): - returnType = returnType.complete(scope) - assert not isinstance(returnType, IDLUnresolvedType) - assert not isinstance(returnType, IDLTypedefType) - assert not isinstance(returnType.name, IDLUnresolvedIdentifier) - overload.returnType = returnType - - if returnType.isPromise(): - overloadWithPromiseReturnType = overload - else: - overloadWithoutPromiseReturnType = overload - - # Make sure either all our overloads return Promises or none do - if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType: - raise WebIDLError("We have overloads with both Promise and " - "non-Promise return types", - [overloadWithPromiseReturnType.location, - overloadWithoutPromiseReturnType.location]) - - if overloadWithPromiseReturnType and self._legacycaller: - raise WebIDLError("May not have a Promise return type for a " - "legacycaller.", - [overloadWithPromiseReturnType.location]) - - # Now compute various information that will be used by the - # WebIDL overload resolution algorithm. - self.maxArgCount = max(len(s[1]) for s in self.signatures()) - self.allowedArgCounts = [ i for i in range(self.maxArgCount+1) - if len(self.signaturesForArgCount(i)) != 0 ] - - def validate(self): - IDLInterfaceMember.validate(self) - - # Make sure our overloads are properly distinguishable and don't have - # different argument types before the distinguishing args. - for argCount in self.allowedArgCounts: - possibleOverloads = self.overloadsForArgCount(argCount) - if len(possibleOverloads) == 1: - continue - distinguishingIndex = self.distinguishingIndexForArgCount(argCount) - for idx in range(distinguishingIndex): - firstSigType = possibleOverloads[0].arguments[idx].type - for overload in possibleOverloads[1:]: - if overload.arguments[idx].type != firstSigType: - raise WebIDLError( - "Signatures for method '%s' with %d arguments have " - "different types of arguments at index %d, which " - "is before distinguishing index %d" % - (self.identifier.name, argCount, idx, - distinguishingIndex), - [self.location, overload.location]) - - for overload in self._overloads: - if not overload.returnType.unroll().isExposedInAllOf(self.exposureSet): - raise WebIDLError("Overload returns a type that is not exposed " - "everywhere where the method is exposed", - [overload.location]) - - def overloadsForArgCount(self, argc): - return [overload for overload in self._overloads if - len(overload.arguments) == argc or - (len(overload.arguments) > argc and - all(arg.optional for arg in overload.arguments[argc:])) or - (len(overload.arguments) < argc and - len(overload.arguments) > 0 and - overload.arguments[-1].variadic)] - - def signaturesForArgCount(self, argc): - return [(overload.returnType, overload.arguments) for overload - in self.overloadsForArgCount(argc)] - - def locationsForArgCount(self, argc): - return [overload.location for overload in self.overloadsForArgCount(argc)] - - def distinguishingIndexForArgCount(self, argc): - def isValidDistinguishingIndex(idx, signatures): - for (firstSigIndex, (firstRetval, firstArgs)) in enumerate(signatures[:-1]): - for (secondRetval, secondArgs) in signatures[firstSigIndex+1:]: - if idx < len(firstArgs): - firstType = firstArgs[idx].type - else: - assert(firstArgs[-1].variadic) - firstType = firstArgs[-1].type - if idx < len(secondArgs): - secondType = secondArgs[idx].type - else: - assert(secondArgs[-1].variadic) - secondType = secondArgs[-1].type - if not firstType.isDistinguishableFrom(secondType): - return False - return True - signatures = self.signaturesForArgCount(argc) - for idx in range(argc): - if isValidDistinguishingIndex(idx, signatures): - return idx - # No valid distinguishing index. Time to throw - locations = self.locationsForArgCount(argc) - raise WebIDLError("Signatures with %d arguments for method '%s' are not " - "distinguishable" % (argc, self.identifier.name), - locations) - - def handleExtendedAttribute(self, attr): - identifier = attr.identifier() - if identifier == "GetterThrows": - raise WebIDLError("Methods must not be flagged as " - "[GetterThrows]", - [attr.location, self.location]) - elif identifier == "SetterThrows": - raise WebIDLError("Methods must not be flagged as " - "[SetterThrows]", - [attr.location, self.location]) - elif identifier == "Unforgeable": - if self.isStatic(): - raise WebIDLError("[Unforgeable] is only allowed on non-static " - "methods", [attr.location, self.location]) - self._unforgeable = True - elif identifier == "SameObject": - raise WebIDLError("Methods must not be flagged as [SameObject]", - [attr.location, self.location]); - elif identifier == "Constant": - raise WebIDLError("Methods must not be flagged as [Constant]", - [attr.location, self.location]); - elif identifier == "PutForwards": - raise WebIDLError("Only attributes support [PutForwards]", - [attr.location, self.location]) - elif identifier == "LenientFloat": - # This is called before we've done overload resolution - assert len(self.signatures()) == 1 - sig = self.signatures()[0] - if not sig[0].isVoid(): - raise WebIDLError("[LenientFloat] used on a non-void method", - [attr.location, self.location]) - if not any(arg.type.includesRestrictedFloat() for arg in sig[1]): - raise WebIDLError("[LenientFloat] used on an operation with no " - "restricted float type arguments", - [attr.location, self.location]) - elif identifier == "Exposed": - convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames) - elif (identifier == "Pure" or - identifier == "CrossOriginCallable" or - identifier == "WebGLHandlesContextLoss"): - # Known no-argument attributes. - if not attr.noArguments(): - raise WebIDLError("[%s] must take no arguments" % identifier, - [attr.location]) - elif (identifier == "Throws" or - identifier == "NewObject" or - identifier == "ChromeOnly" or - identifier == "Pref" or - identifier == "Func" or - identifier == "AvailableIn" or - identifier == "CheckPermissions"): - # Known attributes that we don't need to do anything with here - pass - else: - raise WebIDLError("Unknown extended attribute %s on method" % identifier, - [attr.location]) - IDLInterfaceMember.handleExtendedAttribute(self, attr) - - def returnsPromise(self): - return self._overloads[0].returnType.isPromise() - - def isUnforgeable(self): - return self._unforgeable - - def _getDependentObjects(self): - deps = set() - for overload in self._overloads: - deps.union(overload._getDependentObjects()) - return deps - -class IDLImplementsStatement(IDLObject): - def __init__(self, location, implementor, implementee): - IDLObject.__init__(self, location) - self.implementor = implementor; - self.implementee = implementee - - def finish(self, scope): - assert(isinstance(self.implementor, IDLIdentifierPlaceholder)) - assert(isinstance(self.implementee, IDLIdentifierPlaceholder)) - implementor = self.implementor.finish(scope) - implementee = self.implementee.finish(scope) - # NOTE: we depend on not setting self.implementor and - # self.implementee here to keep track of the original - # locations. - if not isinstance(implementor, IDLInterface): - raise WebIDLError("Left-hand side of 'implements' is not an " - "interface", - [self.implementor.location]) - if implementor.isCallback(): - raise WebIDLError("Left-hand side of 'implements' is a callback " - "interface", - [self.implementor.location]) - if not isinstance(implementee, IDLInterface): - raise WebIDLError("Right-hand side of 'implements' is not an " - "interface", - [self.implementee.location]) - if implementee.isCallback(): - raise WebIDLError("Right-hand side of 'implements' is a callback " - "interface", - [self.implementee.location]) - implementor.addImplementedInterface(implementee) - - def validate(self): - pass - - def addExtendedAttributes(self, attrs): - assert len(attrs) == 0 - -class IDLExtendedAttribute(IDLObject): - """ - A class to represent IDL extended attributes so we can give them locations - """ - def __init__(self, location, tuple): - IDLObject.__init__(self, location) - self._tuple = tuple - - def identifier(self): - return self._tuple[0] - - def noArguments(self): - return len(self._tuple) == 1 - - def hasValue(self): - return len(self._tuple) >= 2 and isinstance(self._tuple[1], str) - - def value(self): - assert(self.hasValue()) - return self._tuple[1] - - def hasArgs(self): - return (len(self._tuple) == 2 and isinstance(self._tuple[1], list) or - len(self._tuple) == 3) - - def args(self): - assert(self.hasArgs()) - # Our args are our last element - return self._tuple[-1] - - def listValue(self): - """ - Backdoor for storing random data in _extendedAttrDict - """ - return list(self._tuple)[1:] - -# Parser - -class Tokenizer(object): - tokens = [ - "INTEGER", - "FLOATLITERAL", - "IDENTIFIER", - "STRING", - "WHITESPACE", - "OTHER" - ] - - def t_FLOATLITERAL(self, t): - r'(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+|Infinity))|NaN' - t.value = float(t.value) - return t - - def t_INTEGER(self, t): - r'-?(0([0-7]+|[Xx][0-9A-Fa-f]+)?|[1-9][0-9]*)' - try: - # Can't use int(), because that doesn't handle octal properly. - t.value = parseInt(t.value) - except: - raise WebIDLError("Invalid integer literal", - [Location(lexer=self.lexer, - lineno=self.lexer.lineno, - lexpos=self.lexer.lexpos, - filename=self._filename)]) - return t - - def t_IDENTIFIER(self, t): - r'[A-Z_a-z][0-9A-Z_a-z-]*' - t.type = self.keywords.get(t.value, 'IDENTIFIER') - return t - - def t_STRING(self, t): - r'"[^"]*"' - t.value = t.value[1:-1] - return t - - def t_WHITESPACE(self, t): - r'[\t\n\r ]+|[\t\n\r ]*((//[^\n]*|/\*.*?\*/)[\t\n\r ]*)+' - pass - - def t_ELLIPSIS(self, t): - r'\.\.\.' - t.type = self.keywords.get(t.value) - return t - - def t_OTHER(self, t): - r'[^\t\n\r 0-9A-Z_a-z]' - t.type = self.keywords.get(t.value, 'OTHER') - return t - - keywords = { - "module": "MODULE", - "interface": "INTERFACE", - "partial": "PARTIAL", - "dictionary": "DICTIONARY", - "exception": "EXCEPTION", - "enum": "ENUM", - "callback": "CALLBACK", - "typedef": "TYPEDEF", - "implements": "IMPLEMENTS", - "const": "CONST", - "null": "NULL", - "true": "TRUE", - "false": "FALSE", - "serializer": "SERIALIZER", - "stringifier": "STRINGIFIER", - "jsonifier": "JSONIFIER", - "unrestricted": "UNRESTRICTED", - "attribute": "ATTRIBUTE", - "readonly": "READONLY", - "inherit": "INHERIT", - "static": "STATIC", - "getter": "GETTER", - "setter": "SETTER", - "creator": "CREATOR", - "deleter": "DELETER", - "legacycaller": "LEGACYCALLER", - "optional": "OPTIONAL", - "...": "ELLIPSIS", - "::": "SCOPE", - "Date": "DATE", - "DOMString": "DOMSTRING", - "ByteString": "BYTESTRING", - "ScalarValueString": "SCALARVALUESTRING", - "any": "ANY", - "boolean": "BOOLEAN", - "byte": "BYTE", - "double": "DOUBLE", - "float": "FLOAT", - "long": "LONG", - "object": "OBJECT", - "octet": "OCTET", - "optional": "OPTIONAL", - "Promise": "PROMISE", - "sequence": "SEQUENCE", - "MozMap": "MOZMAP", - "short": "SHORT", - "unsigned": "UNSIGNED", - "void": "VOID", - ":": "COLON", - ";": "SEMICOLON", - "{": "LBRACE", - "}": "RBRACE", - "(": "LPAREN", - ")": "RPAREN", - "[": "LBRACKET", - "]": "RBRACKET", - "?": "QUESTIONMARK", - ",": "COMMA", - "=": "EQUALS", - "<": "LT", - ">": "GT", - "ArrayBuffer": "ARRAYBUFFER", - "or": "OR" - } - - tokens.extend(keywords.values()) - - def t_error(self, t): - raise WebIDLError("Unrecognized Input", - [Location(lexer=self.lexer, - lineno=self.lexer.lineno, - lexpos=self.lexer.lexpos, - filename = self.filename)]) - - def __init__(self, outputdir, lexer=None): - if lexer: - self.lexer = lexer - else: - self.lexer = lex.lex(object=self, - outputdir=outputdir, - lextab='webidllex', - reflags=re.DOTALL) - -class SqueakyCleanLogger(object): - errorWhitelist = [ - # Web IDL defines the WHITESPACE token, but doesn't actually - # use it ... so far. - "Token 'WHITESPACE' defined, but not used", - # And that means we have an unused token - "There is 1 unused token", - # Web IDL defines a OtherOrComma rule that's only used in - # ExtendedAttributeInner, which we don't use yet. - "Rule 'OtherOrComma' defined, but not used", - # And an unused rule - "There is 1 unused rule", - # And the OtherOrComma grammar symbol is unreachable. - "Symbol 'OtherOrComma' is unreachable", - # Which means the Other symbol is unreachable. - "Symbol 'Other' is unreachable", - ] - def __init__(self): - self.errors = [] - def debug(self, msg, *args, **kwargs): - pass - info = debug - def warning(self, msg, *args, **kwargs): - if msg == "%s:%d: Rule '%s' defined, but not used": - # Munge things so we don't have to hardcode filenames and - # line numbers in our whitelist. - whitelistmsg = "Rule '%s' defined, but not used" - whitelistargs = args[2:] - else: - whitelistmsg = msg - whitelistargs = args - if (whitelistmsg % whitelistargs) not in SqueakyCleanLogger.errorWhitelist: - self.errors.append(msg % args) - error = warning - - def reportGrammarErrors(self): - if self.errors: - raise WebIDLError("\n".join(self.errors), []) - -class Parser(Tokenizer): - def getLocation(self, p, i): - return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename) - - def globalScope(self): - return self._globalScope - - # The p_Foo functions here must match the WebIDL spec's grammar. - # It's acceptable to split things at '|' boundaries. - def p_Definitions(self, p): - """ - Definitions : ExtendedAttributeList Definition Definitions - """ - if p[2]: - p[0] = [p[2]] - p[2].addExtendedAttributes(p[1]) - else: - assert not p[1] - p[0] = [] - - p[0].extend(p[3]) - - def p_DefinitionsEmpty(self, p): - """ - Definitions : - """ - p[0] = [] - - def p_Definition(self, p): - """ - Definition : CallbackOrInterface - | PartialInterface - | Dictionary - | Exception - | Enum - | Typedef - | ImplementsStatement - """ - p[0] = p[1] - assert p[1] # We might not have implemented something ... - - def p_CallbackOrInterfaceCallback(self, p): - """ - CallbackOrInterface : CALLBACK CallbackRestOrInterface - """ - if p[2].isInterface(): - assert isinstance(p[2], IDLInterface) - p[2].setCallback(True) - - p[0] = p[2] - - def p_CallbackOrInterfaceInterface(self, p): - """ - CallbackOrInterface : Interface - """ - p[0] = p[1] - - def p_CallbackRestOrInterface(self, p): - """ - CallbackRestOrInterface : CallbackRest - | Interface - """ - assert p[1] - p[0] = p[1] - - def p_Interface(self, p): - """ - Interface : INTERFACE IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON - """ - location = self.getLocation(p, 1) - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) - members = p[5] - parent = p[3] - - try: - existingObj = self.globalScope()._lookupIdentifier(identifier) - if existingObj: - p[0] = existingObj - if not isinstance(p[0], IDLInterface): - raise WebIDLError("Interface has the same name as " - "non-interface object", - [location, p[0].location]) - p[0].setNonPartial(location, parent, members) - return - except Exception, ex: - if isinstance(ex, WebIDLError): - raise ex - pass - - p[0] = IDLInterface(location, self.globalScope(), identifier, parent, - members, isKnownNonPartial=True) - - def p_InterfaceForwardDecl(self, p): - """ - Interface : INTERFACE IDENTIFIER SEMICOLON - """ - location = self.getLocation(p, 1) - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) - - try: - if self.globalScope()._lookupIdentifier(identifier): - p[0] = self.globalScope()._lookupIdentifier(identifier) - if not isinstance(p[0], IDLExternalInterface): - raise WebIDLError("Name collision between external " - "interface declaration for identifier " - "%s and %s" % (identifier.name, p[0]), - [location, p[0].location]) - return - except Exception, ex: - if isinstance(ex, WebIDLError): - raise ex - pass - - p[0] = IDLExternalInterface(location, self.globalScope(), identifier) - - def p_PartialInterface(self, p): - """ - PartialInterface : PARTIAL INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON - """ - location = self.getLocation(p, 2) - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3]) - members = p[5] - - nonPartialInterface = None - try: - nonPartialInterface = self.globalScope()._lookupIdentifier(identifier) - if nonPartialInterface: - if not isinstance(nonPartialInterface, IDLInterface): - raise WebIDLError("Partial interface has the same name as " - "non-interface object", - [location, nonPartialInterface.location]) - except Exception, ex: - if isinstance(ex, WebIDLError): - raise ex - pass - - if not nonPartialInterface: - nonPartialInterface = IDLInterface(location, self.globalScope(), - identifier, None, - [], isKnownNonPartial=False) - partialInterface = IDLPartialInterface(location, identifier, members, - nonPartialInterface) - p[0] = partialInterface - - def p_Inheritance(self, p): - """ - Inheritance : COLON ScopedName - """ - p[0] = IDLIdentifierPlaceholder(self.getLocation(p, 2), p[2]) - - def p_InheritanceEmpty(self, p): - """ - Inheritance : - """ - pass - - def p_InterfaceMembers(self, p): - """ - InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers - """ - p[0] = [p[2]] if p[2] else [] - - assert not p[1] or p[2] - p[2].addExtendedAttributes(p[1]) - - p[0].extend(p[3]) - - def p_InterfaceMembersEmpty(self, p): - """ - InterfaceMembers : - """ - p[0] = [] - - def p_InterfaceMember(self, p): - """ - InterfaceMember : Const - | AttributeOrOperation - """ - p[0] = p[1] - - def p_Dictionary(self, p): - """ - Dictionary : DICTIONARY IDENTIFIER Inheritance LBRACE DictionaryMembers RBRACE SEMICOLON - """ - location = self.getLocation(p, 1) - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) - members = p[5] - p[0] = IDLDictionary(location, self.globalScope(), identifier, p[3], members) - - def p_DictionaryMembers(self, p): - """ - DictionaryMembers : ExtendedAttributeList DictionaryMember DictionaryMembers - | - """ - if len(p) == 1: - # We're at the end of the list - p[0] = [] - return - # Add our extended attributes - p[2].addExtendedAttributes(p[1]) - p[0] = [p[2]] - p[0].extend(p[3]) - - def p_DictionaryMember(self, p): - """ - DictionaryMember : Type IDENTIFIER Default SEMICOLON - """ - # These quack a lot like optional arguments, so just treat them that way. - t = p[1] - assert isinstance(t, IDLType) - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) - defaultValue = p[3] - - p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True, - defaultValue=defaultValue, variadic=False, - dictionaryMember=True) - - def p_Default(self, p): - """ - Default : EQUALS DefaultValue - | - """ - if len(p) > 1: - p[0] = p[2] - else: - p[0] = None - - def p_DefaultValue(self, p): - """ - DefaultValue : ConstValue - | LBRACKET RBRACKET - """ - if len(p) == 2: - p[0] = p[1] - else: - assert len(p) == 3 # Must be [] - p[0] = IDLEmptySequenceValue(self.getLocation(p, 1)) - - def p_Exception(self, p): - """ - Exception : EXCEPTION IDENTIFIER Inheritance LBRACE ExceptionMembers RBRACE SEMICOLON - """ - pass - - def p_Enum(self, p): - """ - Enum : ENUM IDENTIFIER LBRACE EnumValueList RBRACE SEMICOLON - """ - location = self.getLocation(p, 1) - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) - - values = p[4] - assert values - p[0] = IDLEnum(location, self.globalScope(), identifier, values) - - def p_EnumValueList(self, p): - """ - EnumValueList : STRING EnumValueListComma - """ - p[0] = [p[1]] - p[0].extend(p[2]) - - def p_EnumValueListComma(self, p): - """ - EnumValueListComma : COMMA EnumValueListString - """ - p[0] = p[2] - - def p_EnumValueListCommaEmpty(self, p): - """ - EnumValueListComma : - """ - p[0] = [] - - def p_EnumValueListString(self, p): - """ - EnumValueListString : STRING EnumValueListComma - """ - p[0] = [p[1]] - p[0].extend(p[2]) - - def p_EnumValueListStringEmpty(self, p): - """ - EnumValueListString : - """ - p[0] = [] - - def p_CallbackRest(self, p): - """ - CallbackRest : IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON - """ - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) - p[0] = IDLCallbackType(self.getLocation(p, 1), self.globalScope(), - identifier, p[3], p[5]) - - def p_ExceptionMembers(self, p): - """ - ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers - | - """ - pass - - def p_Typedef(self, p): - """ - Typedef : TYPEDEF Type IDENTIFIER SEMICOLON - """ - typedef = IDLTypedefType(self.getLocation(p, 1), p[2], p[3]) - typedef.resolve(self.globalScope()) - p[0] = typedef - - def p_ImplementsStatement(self, p): - """ - ImplementsStatement : ScopedName IMPLEMENTS ScopedName SEMICOLON - """ - assert(p[2] == "implements") - implementor = IDLIdentifierPlaceholder(self.getLocation(p, 1), p[1]) - implementee = IDLIdentifierPlaceholder(self.getLocation(p, 3), p[3]) - p[0] = IDLImplementsStatement(self.getLocation(p, 1), implementor, - implementee) - - def p_Const(self, p): - """ - Const : CONST ConstType IDENTIFIER EQUALS ConstValue SEMICOLON - """ - location = self.getLocation(p, 1) - type = p[2] - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3]) - value = p[5] - p[0] = IDLConst(location, identifier, type, value) - - def p_ConstValueBoolean(self, p): - """ - ConstValue : BooleanLiteral - """ - location = self.getLocation(p, 1) - booleanType = BuiltinTypes[IDLBuiltinType.Types.boolean] - p[0] = IDLValue(location, booleanType, p[1]) - - def p_ConstValueInteger(self, p): - """ - ConstValue : INTEGER - """ - location = self.getLocation(p, 1) - - # We don't know ahead of time what type the integer literal is. - # Determine the smallest type it could possibly fit in and use that. - integerType = matchIntegerValueToType(p[1]) - if integerType == None: - raise WebIDLError("Integer literal out of range", [location]) - - p[0] = IDLValue(location, integerType, p[1]) - - def p_ConstValueFloat(self, p): - """ - ConstValue : FLOATLITERAL - """ - location = self.getLocation(p, 1) - p[0] = IDLValue(location, BuiltinTypes[IDLBuiltinType.Types.unrestricted_float], p[1]) - - def p_ConstValueString(self, p): - """ - ConstValue : STRING - """ - location = self.getLocation(p, 1) - stringType = BuiltinTypes[IDLBuiltinType.Types.domstring] - p[0] = IDLValue(location, stringType, p[1]) - - def p_ConstValueNull(self, p): - """ - ConstValue : NULL - """ - p[0] = IDLNullValue(self.getLocation(p, 1)) - - def p_BooleanLiteralTrue(self, p): - """ - BooleanLiteral : TRUE - """ - p[0] = True - - def p_BooleanLiteralFalse(self, p): - """ - BooleanLiteral : FALSE - """ - p[0] = False - - def p_AttributeOrOperation(self, p): - """ - AttributeOrOperation : Attribute - | Operation - """ - p[0] = p[1] - - def p_AttributeWithQualifier(self, p): - """ - Attribute : Qualifier AttributeRest - """ - static = IDLInterfaceMember.Special.Static in p[1] - stringifier = IDLInterfaceMember.Special.Stringifier in p[1] - (location, identifier, type, readonly) = p[2] - p[0] = IDLAttribute(location, identifier, type, readonly, static=static, - stringifier=stringifier) - - def p_Attribute(self, p): - """ - Attribute : Inherit AttributeRest - """ - (location, identifier, type, readonly) = p[2] - p[0] = IDLAttribute(location, identifier, type, readonly, inherit=p[1]) - - def p_AttributeRest(self, p): - """ - AttributeRest : ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON - """ - location = self.getLocation(p, 2) - readonly = p[1] - t = p[3] - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 4), p[4]) - p[0] = (location, identifier, t, readonly) - - def p_ReadOnly(self, p): - """ - ReadOnly : READONLY - """ - p[0] = True - - def p_ReadOnlyEmpty(self, p): - """ - ReadOnly : - """ - p[0] = False - - def p_Inherit(self, p): - """ - Inherit : INHERIT - """ - p[0] = True - - def p_InheritEmpty(self, p): - """ - Inherit : - """ - p[0] = False - - def p_Operation(self, p): - """ - Operation : Qualifiers OperationRest - """ - qualifiers = p[1] - - # Disallow duplicates in the qualifier set - if not len(set(qualifiers)) == len(qualifiers): - raise WebIDLError("Duplicate qualifiers are not allowed", - [self.getLocation(p, 1)]) - - static = IDLInterfaceMember.Special.Static in p[1] - # If static is there that's all that's allowed. This is disallowed - # by the parser, so we can assert here. - assert not static or len(qualifiers) == 1 - - stringifier = IDLInterfaceMember.Special.Stringifier in p[1] - # If stringifier is there that's all that's allowed. This is disallowed - # by the parser, so we can assert here. - assert not stringifier or len(qualifiers) == 1 - - getter = True if IDLMethod.Special.Getter in p[1] else False - setter = True if IDLMethod.Special.Setter in p[1] else False - creator = True if IDLMethod.Special.Creator in p[1] else False - deleter = True if IDLMethod.Special.Deleter in p[1] else False - legacycaller = True if IDLMethod.Special.LegacyCaller in p[1] else False - - if getter or deleter: - if setter or creator: - raise WebIDLError("getter and deleter are incompatible with setter and creator", - [self.getLocation(p, 1)]) - - (returnType, identifier, arguments) = p[2] - - assert isinstance(returnType, IDLType) - - specialType = IDLMethod.NamedOrIndexed.Neither - - if getter or deleter: - if len(arguments) != 1: - raise WebIDLError("%s has wrong number of arguments" % - ("getter" if getter else "deleter"), - [self.getLocation(p, 2)]) - argType = arguments[0].type - if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]: - specialType = IDLMethod.NamedOrIndexed.Named - elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]: - specialType = IDLMethod.NamedOrIndexed.Indexed - else: - raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" % - ("getter" if getter else "deleter"), - [arguments[0].location]) - if arguments[0].optional or arguments[0].variadic: - raise WebIDLError("%s cannot have %s argument" % - ("getter" if getter else "deleter", - "optional" if arguments[0].optional else "variadic"), - [arguments[0].location]) - if getter: - if returnType.isVoid(): - raise WebIDLError("getter cannot have void return type", - [self.getLocation(p, 2)]) - if setter or creator: - if len(arguments) != 2: - raise WebIDLError("%s has wrong number of arguments" % - ("setter" if setter else "creator"), - [self.getLocation(p, 2)]) - argType = arguments[0].type - if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]: - specialType = IDLMethod.NamedOrIndexed.Named - elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]: - specialType = IDLMethod.NamedOrIndexed.Indexed - else: - raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" % - ("setter" if setter else "creator"), - [arguments[0].location]) - if arguments[0].optional or arguments[0].variadic: - raise WebIDLError("%s cannot have %s argument" % - ("setter" if setter else "creator", - "optional" if arguments[0].optional else "variadic"), - [arguments[0].location]) - if arguments[1].optional or arguments[1].variadic: - raise WebIDLError("%s cannot have %s argument" % - ("setter" if setter else "creator", - "optional" if arguments[1].optional else "variadic"), - [arguments[1].location]) - - if stringifier: - if len(arguments) != 0: - raise WebIDLError("stringifier has wrong number of arguments", - [self.getLocation(p, 2)]) - if not returnType.isDOMString(): - raise WebIDLError("stringifier must have DOMString return type", - [self.getLocation(p, 2)]) - - # identifier might be None. This is only permitted for special methods. - if not identifier: - if not getter and not setter and not creator and \ - not deleter and not legacycaller and not stringifier: - raise WebIDLError("Identifier required for non-special methods", - [self.getLocation(p, 2)]) - - location = BuiltinLocation("<auto-generated-identifier>") - identifier = IDLUnresolvedIdentifier(location, "__%s%s%s%s%s%s%s" % - ("named" if specialType == IDLMethod.NamedOrIndexed.Named else \ - "indexed" if specialType == IDLMethod.NamedOrIndexed.Indexed else "", - "getter" if getter else "", - "setter" if setter else "", - "deleter" if deleter else "", - "creator" if creator else "", - "legacycaller" if legacycaller else "", - "stringifier" if stringifier else ""), allowDoubleUnderscore=True) - - method = IDLMethod(self.getLocation(p, 2), identifier, returnType, arguments, - static=static, getter=getter, setter=setter, creator=creator, - deleter=deleter, specialType=specialType, - legacycaller=legacycaller, stringifier=stringifier) - p[0] = method - - def p_Stringifier(self, p): - """ - Operation : STRINGIFIER SEMICOLON - """ - identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), - "__stringifier", - allowDoubleUnderscore=True) - method = IDLMethod(self.getLocation(p, 1), - identifier, - returnType=BuiltinTypes[IDLBuiltinType.Types.domstring], - arguments=[], - stringifier=True) - p[0] = method - - def p_Jsonifier(self, p): - """ - Operation : JSONIFIER SEMICOLON - """ - identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), - "__jsonifier", allowDoubleUnderscore=True) - method = IDLMethod(self.getLocation(p, 1), - identifier, - returnType=BuiltinTypes[IDLBuiltinType.Types.object], - arguments=[], - jsonifier=True) - p[0] = method - - def p_QualifierStatic(self, p): - """ - Qualifier : STATIC - """ - p[0] = [IDLInterfaceMember.Special.Static] - - def p_QualifierStringifier(self, p): - """ - Qualifier : STRINGIFIER - """ - p[0] = [IDLInterfaceMember.Special.Stringifier] - - def p_Qualifiers(self, p): - """ - Qualifiers : Qualifier - | Specials - """ - p[0] = p[1] - - def p_Specials(self, p): - """ - Specials : Special Specials - """ - p[0] = [p[1]] - p[0].extend(p[2]) - - def p_SpecialsEmpty(self, p): - """ - Specials : - """ - p[0] = [] - - def p_SpecialGetter(self, p): - """ - Special : GETTER - """ - p[0] = IDLMethod.Special.Getter - - def p_SpecialSetter(self, p): - """ - Special : SETTER - """ - p[0] = IDLMethod.Special.Setter - - def p_SpecialCreator(self, p): - """ - Special : CREATOR - """ - p[0] = IDLMethod.Special.Creator - - def p_SpecialDeleter(self, p): - """ - Special : DELETER - """ - p[0] = IDLMethod.Special.Deleter - - def p_SpecialLegacyCaller(self, p): - """ - Special : LEGACYCALLER - """ - p[0] = IDLMethod.Special.LegacyCaller - - def p_OperationRest(self, p): - """ - OperationRest : ReturnType OptionalIdentifier LPAREN ArgumentList RPAREN SEMICOLON - """ - p[0] = (p[1], p[2], p[4]) - - def p_OptionalIdentifier(self, p): - """ - OptionalIdentifier : IDENTIFIER - """ - p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) - - def p_OptionalIdentifierEmpty(self, p): - """ - OptionalIdentifier : - """ - pass - - def p_ArgumentList(self, p): - """ - ArgumentList : Argument Arguments - """ - p[0] = [p[1]] if p[1] else [] - p[0].extend(p[2]) - - def p_ArgumentListEmpty(self, p): - """ - ArgumentList : - """ - p[0] = [] - - def p_Arguments(self, p): - """ - Arguments : COMMA Argument Arguments - """ - p[0] = [p[2]] if p[2] else [] - p[0].extend(p[3]) - - def p_ArgumentsEmpty(self, p): - """ - Arguments : - """ - p[0] = [] - - def p_Argument(self, p): - """ - Argument : ExtendedAttributeList Optional Type Ellipsis ArgumentName Default - """ - t = p[3] - assert isinstance(t, IDLType) - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 5), p[5]) - - optional = p[2] - variadic = p[4] - defaultValue = p[6] - - if not optional and defaultValue: - raise WebIDLError("Mandatory arguments can't have a default value.", - [self.getLocation(p, 6)]) - - # We can't test t.isAny() here and give it a default value as needed, - # since at this point t is not a fully resolved type yet (e.g. it might - # be a typedef). We'll handle the 'any' case in IDLArgument.complete. - - if variadic: - if optional: - raise WebIDLError("Variadic arguments should not be marked optional.", - [self.getLocation(p, 2)]) - optional = variadic - - p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic) - p[0].addExtendedAttributes(p[1]) - - def p_ArgumentName(self, p): - """ - ArgumentName : IDENTIFIER - | ATTRIBUTE - | CALLBACK - | CONST - | CREATOR - | DELETER - | DICTIONARY - | ENUM - | EXCEPTION - | GETTER - | IMPLEMENTS - | INHERIT - | INTERFACE - | LEGACYCALLER - | PARTIAL - | SERIALIZER - | SETTER - | STATIC - | STRINGIFIER - | JSONIFIER - | TYPEDEF - | UNRESTRICTED - """ - p[0] = p[1] - - def p_Optional(self, p): - """ - Optional : OPTIONAL - """ - p[0] = True - - def p_OptionalEmpty(self, p): - """ - Optional : - """ - p[0] = False - - def p_Ellipsis(self, p): - """ - Ellipsis : ELLIPSIS - """ - p[0] = True - - def p_EllipsisEmpty(self, p): - """ - Ellipsis : - """ - p[0] = False - - def p_ExceptionMember(self, p): - """ - ExceptionMember : Const - | ExceptionField - """ - pass - - def p_ExceptionField(self, p): - """ - ExceptionField : Type IDENTIFIER SEMICOLON - """ - pass - - def p_ExtendedAttributeList(self, p): - """ - ExtendedAttributeList : LBRACKET ExtendedAttribute ExtendedAttributes RBRACKET - """ - p[0] = [p[2]] - if p[3]: - p[0].extend(p[3]) - - def p_ExtendedAttributeListEmpty(self, p): - """ - ExtendedAttributeList : - """ - p[0] = [] - - def p_ExtendedAttribute(self, p): - """ - ExtendedAttribute : ExtendedAttributeNoArgs - | ExtendedAttributeArgList - | ExtendedAttributeIdent - | ExtendedAttributeNamedArgList - | ExtendedAttributeIdentList - """ - p[0] = IDLExtendedAttribute(self.getLocation(p, 1), p[1]) - - def p_ExtendedAttributeEmpty(self, p): - """ - ExtendedAttribute : - """ - pass - - def p_ExtendedAttributes(self, p): - """ - ExtendedAttributes : COMMA ExtendedAttribute ExtendedAttributes - """ - p[0] = [p[2]] if p[2] else [] - p[0].extend(p[3]) - - def p_ExtendedAttributesEmpty(self, p): - """ - ExtendedAttributes : - """ - p[0] = [] - - def p_Other(self, p): - """ - Other : INTEGER - | FLOATLITERAL - | IDENTIFIER - | STRING - | OTHER - | ELLIPSIS - | COLON - | SCOPE - | SEMICOLON - | LT - | EQUALS - | GT - | QUESTIONMARK - | DATE - | DOMSTRING - | BYTESTRING - | SCALARVALUESTRING - | ANY - | ATTRIBUTE - | BOOLEAN - | BYTE - | LEGACYCALLER - | CONST - | CREATOR - | DELETER - | DOUBLE - | EXCEPTION - | FALSE - | FLOAT - | GETTER - | IMPLEMENTS - | INHERIT - | INTERFACE - | LONG - | MODULE - | NULL - | OBJECT - | OCTET - | OPTIONAL - | SEQUENCE - | MOZMAP - | SETTER - | SHORT - | STATIC - | STRINGIFIER - | JSONIFIER - | TRUE - | TYPEDEF - | UNSIGNED - | VOID - """ - pass - - def p_OtherOrComma(self, p): - """ - OtherOrComma : Other - | COMMA - """ - pass - - def p_TypeSingleType(self, p): - """ - Type : SingleType - """ - p[0] = p[1] - - def p_TypeUnionType(self, p): - """ - Type : UnionType TypeSuffix - """ - p[0] = self.handleModifiers(p[1], p[2]) - - def p_SingleTypeNonAnyType(self, p): - """ - SingleType : NonAnyType - """ - p[0] = p[1] - - def p_SingleTypeAnyType(self, p): - """ - SingleType : ANY TypeSuffixStartingWithArray - """ - p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.any], p[2]) - - def p_UnionType(self, p): - """ - UnionType : LPAREN UnionMemberType OR UnionMemberType UnionMemberTypes RPAREN - """ - types = [p[2], p[4]] - types.extend(p[5]) - p[0] = IDLUnionType(self.getLocation(p, 1), types) - - def p_UnionMemberTypeNonAnyType(self, p): - """ - UnionMemberType : NonAnyType - """ - p[0] = p[1] - - def p_UnionMemberTypeArrayOfAny(self, p): - """ - UnionMemberTypeArrayOfAny : ANY LBRACKET RBRACKET - """ - p[0] = IDLArrayType(self.getLocation(p, 2), - BuiltinTypes[IDLBuiltinType.Types.any]) - - def p_UnionMemberType(self, p): - """ - UnionMemberType : UnionType TypeSuffix - | UnionMemberTypeArrayOfAny TypeSuffix - """ - p[0] = self.handleModifiers(p[1], p[2]) - - def p_UnionMemberTypes(self, p): - """ - UnionMemberTypes : OR UnionMemberType UnionMemberTypes - """ - p[0] = [p[2]] - p[0].extend(p[3]) - - def p_UnionMemberTypesEmpty(self, p): - """ - UnionMemberTypes : - """ - p[0] = [] - - def p_NonAnyType(self, p): - """ - NonAnyType : PrimitiveOrStringType TypeSuffix - | ARRAYBUFFER TypeSuffix - | OBJECT TypeSuffix - """ - if p[1] == "object": - type = BuiltinTypes[IDLBuiltinType.Types.object] - elif p[1] == "ArrayBuffer": - type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer] - else: - type = BuiltinTypes[p[1]] - - p[0] = self.handleModifiers(type, p[2]) - - def p_NonAnyTypeSequenceType(self, p): - """ - NonAnyType : SEQUENCE LT Type GT Null - """ - innerType = p[3] - type = IDLSequenceType(self.getLocation(p, 1), innerType) - if p[5]: - type = IDLNullableType(self.getLocation(p, 5), type) - p[0] = type - - # Note: Promise<void> is allowed, so we want to parametrize on - # ReturnType, not Type. Also, we want this to end up picking up - # the Promise interface for now, hence the games with IDLUnresolvedType. - def p_NonAnyTypePromiseType(self, p): - """ - NonAnyType : PROMISE LT ReturnType GT Null - """ - innerType = p[3] - promiseIdent = IDLUnresolvedIdentifier(self.getLocation(p, 1), "Promise") - type = IDLUnresolvedType(self.getLocation(p, 1), promiseIdent, p[3]) - if p[5]: - type = IDLNullableType(self.getLocation(p, 5), type) - p[0] = type - - def p_NonAnyTypeMozMapType(self, p): - """ - NonAnyType : MOZMAP LT Type GT Null - """ - innerType = p[3] - type = IDLMozMapType(self.getLocation(p, 1), innerType) - if p[5]: - type = IDLNullableType(self.getLocation(p, 5), type) - p[0] = type - - def p_NonAnyTypeScopedName(self, p): - """ - NonAnyType : ScopedName TypeSuffix - """ - assert isinstance(p[1], IDLUnresolvedIdentifier) - - if p[1].name == "Promise": - raise WebIDLError("Promise used without saying what it's " - "parametrized over", - [self.getLocation(p, 1)]) - - type = None - - try: - if self.globalScope()._lookupIdentifier(p[1]): - obj = self.globalScope()._lookupIdentifier(p[1]) - if obj.isType(): - type = obj - else: - type = IDLWrapperType(self.getLocation(p, 1), p[1]) - p[0] = self.handleModifiers(type, p[2]) - return - except: - pass - - type = IDLUnresolvedType(self.getLocation(p, 1), p[1]) - p[0] = self.handleModifiers(type, p[2]) - - def p_NonAnyTypeDate(self, p): - """ - NonAnyType : DATE TypeSuffix - """ - p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.date], - p[2]) - - def p_ConstType(self, p): - """ - ConstType : PrimitiveOrStringType Null - """ - type = BuiltinTypes[p[1]] - if p[2]: - type = IDLNullableType(self.getLocation(p, 1), type) - p[0] = type - - def p_ConstTypeIdentifier(self, p): - """ - ConstType : IDENTIFIER Null - """ - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) - - type = IDLUnresolvedType(self.getLocation(p, 1), identifier) - if p[2]: - type = IDLNullableType(self.getLocation(p, 1), type) - p[0] = type - - def p_PrimitiveOrStringTypeUint(self, p): - """ - PrimitiveOrStringType : UnsignedIntegerType - """ - p[0] = p[1] - - def p_PrimitiveOrStringTypeBoolean(self, p): - """ - PrimitiveOrStringType : BOOLEAN - """ - p[0] = IDLBuiltinType.Types.boolean - - def p_PrimitiveOrStringTypeByte(self, p): - """ - PrimitiveOrStringType : BYTE - """ - p[0] = IDLBuiltinType.Types.byte - - def p_PrimitiveOrStringTypeOctet(self, p): - """ - PrimitiveOrStringType : OCTET - """ - p[0] = IDLBuiltinType.Types.octet - - def p_PrimitiveOrStringTypeFloat(self, p): - """ - PrimitiveOrStringType : FLOAT - """ - p[0] = IDLBuiltinType.Types.float - - def p_PrimitiveOrStringTypeUnrestictedFloat(self, p): - """ - PrimitiveOrStringType : UNRESTRICTED FLOAT - """ - p[0] = IDLBuiltinType.Types.unrestricted_float - - def p_PrimitiveOrStringTypeDouble(self, p): - """ - PrimitiveOrStringType : DOUBLE - """ - p[0] = IDLBuiltinType.Types.double - - def p_PrimitiveOrStringTypeUnrestictedDouble(self, p): - """ - PrimitiveOrStringType : UNRESTRICTED DOUBLE - """ - p[0] = IDLBuiltinType.Types.unrestricted_double - - def p_PrimitiveOrStringTypeDOMString(self, p): - """ - PrimitiveOrStringType : DOMSTRING - """ - p[0] = IDLBuiltinType.Types.domstring - - def p_PrimitiveOrStringTypeBytestring(self, p): - """ - PrimitiveOrStringType : BYTESTRING - """ - p[0] = IDLBuiltinType.Types.bytestring - - def p_PrimitiveOrStringTypeScalarValueString(self, p): - """ - PrimitiveOrStringType : SCALARVALUESTRING - """ - p[0] = IDLBuiltinType.Types.scalarvaluestring - - def p_UnsignedIntegerTypeUnsigned(self, p): - """ - UnsignedIntegerType : UNSIGNED IntegerType - """ - p[0] = p[2] + 1 # Adding one to a given signed integer type - # gets you the unsigned type. - - def p_UnsignedIntegerType(self, p): - """ - UnsignedIntegerType : IntegerType - """ - p[0] = p[1] - - def p_IntegerTypeShort(self, p): - """ - IntegerType : SHORT - """ - p[0] = IDLBuiltinType.Types.short - - def p_IntegerTypeLong(self, p): - """ - IntegerType : LONG OptionalLong - """ - if p[2]: - p[0] = IDLBuiltinType.Types.long_long - else: - p[0] = IDLBuiltinType.Types.long - - def p_OptionalLong(self, p): - """ - OptionalLong : LONG - """ - p[0] = True - - def p_OptionalLongEmpty(self, p): - """ - OptionalLong : - """ - p[0] = False - - def p_TypeSuffixBrackets(self, p): - """ - TypeSuffix : LBRACKET RBRACKET TypeSuffix - """ - p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))] - p[0].extend(p[3]) - - def p_TypeSuffixQMark(self, p): - """ - TypeSuffix : QUESTIONMARK TypeSuffixStartingWithArray - """ - p[0] = [(IDLMethod.TypeSuffixModifier.QMark, self.getLocation(p, 1))] - p[0].extend(p[2]) - - def p_TypeSuffixEmpty(self, p): - """ - TypeSuffix : - """ - p[0] = [] - - def p_TypeSuffixStartingWithArray(self, p): - """ - TypeSuffixStartingWithArray : LBRACKET RBRACKET TypeSuffix - """ - p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))] - p[0].extend(p[3]) - - def p_TypeSuffixStartingWithArrayEmpty(self, p): - """ - TypeSuffixStartingWithArray : - """ - p[0] = [] - - def p_Null(self, p): - """ - Null : QUESTIONMARK - | - """ - if len(p) > 1: - p[0] = True - else: - p[0] = False - - def p_ReturnTypeType(self, p): - """ - ReturnType : Type - """ - p[0] = p[1] - - def p_ReturnTypeVoid(self, p): - """ - ReturnType : VOID - """ - p[0] = BuiltinTypes[IDLBuiltinType.Types.void] - - def p_ScopedName(self, p): - """ - ScopedName : AbsoluteScopedName - | RelativeScopedName - """ - p[0] = p[1] - - def p_AbsoluteScopedName(self, p): - """ - AbsoluteScopedName : SCOPE IDENTIFIER ScopedNameParts - """ - assert False - pass - - def p_RelativeScopedName(self, p): - """ - RelativeScopedName : IDENTIFIER ScopedNameParts - """ - assert not p[2] # Not implemented! - - p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) - - def p_ScopedNameParts(self, p): - """ - ScopedNameParts : SCOPE IDENTIFIER ScopedNameParts - """ - assert False - pass - - def p_ScopedNamePartsEmpty(self, p): - """ - ScopedNameParts : - """ - p[0] = None - - def p_ExtendedAttributeNoArgs(self, p): - """ - ExtendedAttributeNoArgs : IDENTIFIER - """ - p[0] = (p[1],) - - def p_ExtendedAttributeArgList(self, p): - """ - ExtendedAttributeArgList : IDENTIFIER LPAREN ArgumentList RPAREN - """ - p[0] = (p[1], p[3]) - - def p_ExtendedAttributeIdent(self, p): - """ - ExtendedAttributeIdent : IDENTIFIER EQUALS STRING - | IDENTIFIER EQUALS IDENTIFIER - """ - p[0] = (p[1], p[3]) - - def p_ExtendedAttributeNamedArgList(self, p): - """ - ExtendedAttributeNamedArgList : IDENTIFIER EQUALS IDENTIFIER LPAREN ArgumentList RPAREN - """ - p[0] = (p[1], p[3], p[5]) - - def p_ExtendedAttributeIdentList(self, p): - """ - ExtendedAttributeIdentList : IDENTIFIER EQUALS LPAREN IdentifierList RPAREN - """ - p[0] = (p[1], p[4]) - - def p_IdentifierList(self, p): - """ - IdentifierList : IDENTIFIER Identifiers - """ - idents = list(p[2]) - idents.insert(0, p[1]) - p[0] = idents - - def p_IdentifiersList(self, p): - """ - Identifiers : COMMA IDENTIFIER Identifiers - """ - idents = list(p[3]) - idents.insert(0, p[2]) - p[0] = idents - - def p_IdentifiersEmpty(self, p): - """ - Identifiers : - """ - p[0] = [] - - def p_error(self, p): - if not p: - raise WebIDLError("Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both", - [self._filename]) - else: - raise WebIDLError("invalid syntax", [Location(self.lexer, p.lineno, p.lexpos, self._filename)]) - - def __init__(self, outputdir='', lexer=None): - Tokenizer.__init__(self, outputdir, lexer) - - logger = SqueakyCleanLogger() - self.parser = yacc.yacc(module=self, - outputdir=outputdir, - tabmodule='webidlyacc', - errorlog=logger - # Pickling the grammar is a speedup in - # some cases (older Python?) but a - # significant slowdown in others. - # We're not pickling for now, until it - # becomes a speedup again. - # , picklefile='WebIDLGrammar.pkl' - ) - logger.reportGrammarErrors() - - self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None) - # To make our test harness work, pretend like we have a primary global already. Note that we _don't_ set _globalScope.primaryGlobalAttr, so we'll still be able to detect multiple PrimaryGlobal extended attributes. - self._globalScope.primaryGlobalName = "FakeTestPrimaryGlobal" - self._globalScope.globalNames.add("FakeTestPrimaryGlobal") - self._globalScope.globalNameMapping["FakeTestPrimaryGlobal"].add("FakeTestPrimaryGlobal") - self._installBuiltins(self._globalScope) - self._productions = [] - - self._filename = "<builtin>" - self.lexer.input(Parser._builtins) - self._filename = None - - self.parser.parse(lexer=self.lexer,tracking=True) - - def _installBuiltins(self, scope): - assert isinstance(scope, IDLScope) - - # xrange omits the last value. - for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1): - builtin = BuiltinTypes[x] - name = builtin.name - - typedef = IDLTypedefType(BuiltinLocation("<builtin type>"), builtin, name) - typedef.resolve(scope) - - @ staticmethod - def handleModifiers(type, modifiers): - for (modifier, modifierLocation) in modifiers: - assert modifier == IDLMethod.TypeSuffixModifier.QMark or \ - modifier == IDLMethod.TypeSuffixModifier.Brackets - - if modifier == IDLMethod.TypeSuffixModifier.QMark: - type = IDLNullableType(modifierLocation, type) - elif modifier == IDLMethod.TypeSuffixModifier.Brackets: - type = IDLArrayType(modifierLocation, type) - - return type - - def parse(self, t, filename=None): - self.lexer.input(t) - - #for tok in iter(self.lexer.token, None): - # print tok - - self._filename = filename - self._productions.extend(self.parser.parse(lexer=self.lexer,tracking=True)) - self._filename = None - - def finish(self): - # First, finish all the IDLImplementsStatements. In particular, we - # have to make sure we do those before we do the IDLInterfaces. - # XXX khuey hates this bit and wants to nuke it from orbit. - implementsStatements = [ p for p in self._productions if - isinstance(p, IDLImplementsStatement)] - otherStatements = [ p for p in self._productions if - not isinstance(p, IDLImplementsStatement)] - for production in implementsStatements: - production.finish(self.globalScope()) - for production in otherStatements: - production.finish(self.globalScope()) - - # Do any post-finish validation we need to do - for production in self._productions: - production.validate() - - # De-duplicate self._productions, without modifying its order. - seen = set() - result = [] - for p in self._productions: - if p not in seen: - seen.add(p) - result.append(p) - return result - - def reset(self): - return Parser(lexer=self.lexer) - - # Builtin IDL defined by WebIDL - _builtins = """ - typedef unsigned long long DOMTimeStamp; - """ - -def main(): - # Parse arguments. - from optparse import OptionParser - usageString = "usage: %prog [options] files" - o = OptionParser(usage=usageString) - o.add_option("--cachedir", dest='cachedir', default=None, - help="Directory in which to cache lex/parse tables.") - o.add_option("--verbose-errors", action='store_true', default=False, - help="When an error happens, display the Python traceback.") - (options, args) = o.parse_args() - - if len(args) < 1: - o.error(usageString) - - fileList = args - baseDir = os.getcwd() - - # Parse the WebIDL. - parser = Parser(options.cachedir) - try: - for filename in fileList: - fullPath = os.path.normpath(os.path.join(baseDir, filename)) - f = open(fullPath, 'rb') - lines = f.readlines() - f.close() - print fullPath - parser.parse(''.join(lines), fullPath) - parser.finish() - except WebIDLError, e: - if options.verbose_errors: - traceback.print_exc() - else: - print e - -if __name__ == '__main__': - main() diff --git a/src/components/script/dom/bindings/codegen/parser/external.patch b/src/components/script/dom/bindings/codegen/parser/external.patch deleted file mode 100644 index 9464511a9d0..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/external.patch +++ /dev/null @@ -1,49 +0,0 @@ ---- WebIDL.py -+++ WebIDL.py -@@ -450,44 +450,8 @@ class IDLIdentifierPlaceholder(IDLObjectWithIdentifier): - - class IDLExternalInterface(IDLObjectWithIdentifier): - def __init__(self, location, parentScope, identifier): -- assert isinstance(identifier, IDLUnresolvedIdentifier) -- assert isinstance(parentScope, IDLScope) -- self.parent = None -- IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier) -- IDLObjectWithIdentifier.resolve(self, parentScope) -- -- def finish(self, scope): -- pass -- -- def validate(self): -- pass -- -- def isExternal(self): -- return True -- -- def isInterface(self): -- return True -- -- def isConsequential(self): -- return False -- -- def addExtendedAttributes(self, attrs): -- assert len(attrs) == 0 -- -- def resolve(self, parentScope): -- pass -- -- def getJSImplementation(self): -- return None -- -- def isJSImplemented(self): -- return False -- -- def getNavigatorProperty(self): -- return None -- -- def _getDependentObjects(self): -- return set() -+ raise WebIDLError("Servo does not support external interfaces.", -+ [self.location]) - - class IDLPartialInterface(IDLObject): - def __init__(self, location, name, members, nonPartialInterface): diff --git a/src/components/script/dom/bindings/codegen/parser/module.patch b/src/components/script/dom/bindings/codegen/parser/module.patch deleted file mode 100644 index 977947b4c63..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/module.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- WebIDL.py -+++ WebIDL.py -@@ -3398,6 +3398,9 @@ class IDLCallbackType(IDLType, IDLObjectWithScope): - self._treatNonCallableAsNull = False - self._treatNonObjectAsNull = False - -+ def module(self): -+ return self.location.filename().split('/')[-1].split('.webidl')[0] + 'Binding' -+ - def isCallback(self): - return True - diff --git a/src/components/script/dom/bindings/codegen/parser/runtests.py b/src/components/script/dom/bindings/codegen/parser/runtests.py deleted file mode 100644 index 98a7d2b81d3..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/runtests.py +++ /dev/null @@ -1,79 +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/. - -import os, sys -import glob -import optparse -import traceback -import WebIDL - -class TestHarness(object): - def __init__(self, test, verbose): - self.test = test - self.verbose = verbose - self.printed_intro = False - - def start(self): - if self.verbose: - self.maybe_print_intro() - - def finish(self): - if self.verbose or self.printed_intro: - print "Finished test %s" % self.test - - def maybe_print_intro(self): - if not self.printed_intro: - print "Starting test %s" % self.test - self.printed_intro = True - - def test_pass(self, msg): - if self.verbose: - print "TEST-PASS | %s" % msg - - def test_fail(self, msg): - self.maybe_print_intro() - print "TEST-UNEXPECTED-FAIL | %s" % msg - - def ok(self, condition, msg): - if condition: - self.test_pass(msg) - else: - self.test_fail(msg) - - def check(self, a, b, msg): - if a == b: - self.test_pass(msg) - else: - self.test_fail(msg) - print "\tGot %s expected %s" % (a, b) - -def run_tests(tests, verbose): - testdir = os.path.join(os.path.dirname(__file__), 'tests') - if not tests: - tests = glob.iglob(os.path.join(testdir, "*.py")) - sys.path.append(testdir) - - for test in tests: - (testpath, ext) = os.path.splitext(os.path.basename(test)) - _test = __import__(testpath, globals(), locals(), ['WebIDLTest']) - - harness = TestHarness(test, verbose) - harness.start() - try: - _test.WebIDLTest.__call__(WebIDL.Parser(), harness) - except Exception, ex: - print "TEST-UNEXPECTED-FAIL | Unhandled exception in test %s: %s" % (testpath, ex) - traceback.print_exc() - finally: - harness.finish() - -if __name__ == '__main__': - usage = """%prog [OPTIONS] [TESTS] - Where TESTS are relative to the tests directory.""" - parser = optparse.OptionParser(usage=usage) - parser.add_option('-q', '--quiet', action='store_false', dest='verbose', default=True, - help="Don't print passing tests.") - options, tests = parser.parse_args() - - run_tests(tests, verbose=options.verbose) diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_any_null.py b/src/components/script/dom/bindings/codegen/parser/tests/test_any_null.py deleted file mode 100644 index e3b690bf6f1..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_any_null.py +++ /dev/null @@ -1,14 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface DoubleNull { - attribute any? foo; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_argument_identifier_conflicts.py b/src/components/script/dom/bindings/codegen/parser/tests/test_argument_identifier_conflicts.py deleted file mode 100644 index eb1f6d3c92e..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_argument_identifier_conflicts.py +++ /dev/null @@ -1,14 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface ArgumentIdentifierConflict { - void foo(boolean arg1, boolean arg1); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_argument_novoid.py b/src/components/script/dom/bindings/codegen/parser/tests/test_argument_novoid.py deleted file mode 100644 index ef8c2229aed..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_argument_novoid.py +++ /dev/null @@ -1,14 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface VoidArgument1 { - void foo(void arg2); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_array_of_interface.py b/src/components/script/dom/bindings/codegen/parser/tests/test_array_of_interface.py deleted file mode 100644 index 26528984595..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_array_of_interface.py +++ /dev/null @@ -1,13 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface A { - attribute long a; - }; - - interface B { - attribute A[] b; - }; - """); - parser.finish() diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_arraybuffer.py b/src/components/script/dom/bindings/codegen/parser/tests/test_arraybuffer.py deleted file mode 100644 index 5b8e56f86ca..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_arraybuffer.py +++ /dev/null @@ -1,84 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestArrayBuffer { - attribute ArrayBuffer bufferAttr; - void bufferMethod(ArrayBuffer arg1, ArrayBuffer? arg2, ArrayBuffer[] arg3, sequence<ArrayBuffer> arg4); - - attribute ArrayBufferView viewAttr; - void viewMethod(ArrayBufferView arg1, ArrayBufferView? arg2, ArrayBufferView[] arg3, sequence<ArrayBufferView> arg4); - - attribute Int8Array int8ArrayAttr; - void int8ArrayMethod(Int8Array arg1, Int8Array? arg2, Int8Array[] arg3, sequence<Int8Array> arg4); - - attribute Uint8Array uint8ArrayAttr; - void uint8ArrayMethod(Uint8Array arg1, Uint8Array? arg2, Uint8Array[] arg3, sequence<Uint8Array> arg4); - - attribute Uint8ClampedArray uint8ClampedArrayAttr; - void uint8ClampedArrayMethod(Uint8ClampedArray arg1, Uint8ClampedArray? arg2, Uint8ClampedArray[] arg3, sequence<Uint8ClampedArray> arg4); - - attribute Int16Array int16ArrayAttr; - void int16ArrayMethod(Int16Array arg1, Int16Array? arg2, Int16Array[] arg3, sequence<Int16Array> arg4); - - attribute Uint16Array uint16ArrayAttr; - void uint16ArrayMethod(Uint16Array arg1, Uint16Array? arg2, Uint16Array[] arg3, sequence<Uint16Array> arg4); - - attribute Int32Array int32ArrayAttr; - void int32ArrayMethod(Int32Array arg1, Int32Array? arg2, Int32Array[] arg3, sequence<Int32Array> arg4); - - attribute Uint32Array uint32ArrayAttr; - void uint32ArrayMethod(Uint32Array arg1, Uint32Array? arg2, Uint32Array[] arg3, sequence<Uint32Array> arg4); - - attribute Float32Array float32ArrayAttr; - void float32ArrayMethod(Float32Array arg1, Float32Array? arg2, Float32Array[] arg3, sequence<Float32Array> arg4); - - attribute Float64Array float64ArrayAttr; - void float64ArrayMethod(Float64Array arg1, Float64Array? arg2, Float64Array[] arg3, sequence<Float64Array> arg4); - }; - """) - - results = parser.finish() - - iface = results[0] - - harness.ok(True, "TestArrayBuffer interface parsed without error") - harness.check(len(iface.members), 22, "Interface should have twenty two members") - - members = iface.members - - def checkStuff(attr, method, t): - harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Expect an IDLAttribute") - harness.ok(isinstance(method, WebIDL.IDLMethod), "Expect an IDLMethod") - - harness.check(str(attr.type), t, "Expect an ArrayBuffer type") - harness.ok(attr.type.isSpiderMonkeyInterface(), "Should test as a js interface") - - (retType, arguments) = method.signatures()[0] - harness.ok(retType.isVoid(), "Should have a void return type") - harness.check(len(arguments), 4, "Expect 4 arguments") - - harness.check(str(arguments[0].type), t, "Expect an ArrayBuffer type") - harness.ok(arguments[0].type.isSpiderMonkeyInterface(), "Should test as a js interface") - - harness.check(str(arguments[1].type), t + "OrNull", "Expect an ArrayBuffer type") - harness.ok(arguments[1].type.inner.isSpiderMonkeyInterface(), "Should test as a js interface") - - harness.check(str(arguments[2].type), t + "Array", "Expect an ArrayBuffer type") - harness.ok(arguments[2].type.inner.isSpiderMonkeyInterface(), "Should test as a js interface") - - harness.check(str(arguments[3].type), t + "Sequence", "Expect an ArrayBuffer type") - harness.ok(arguments[3].type.inner.isSpiderMonkeyInterface(), "Should test as a js interface") - - - checkStuff(members[0], members[1], "ArrayBuffer") - checkStuff(members[2], members[3], "ArrayBufferView") - checkStuff(members[4], members[5], "Int8Array") - checkStuff(members[6], members[7], "Uint8Array") - checkStuff(members[8], members[9], "Uint8ClampedArray") - checkStuff(members[10], members[11], "Int16Array") - checkStuff(members[12], members[13], "Uint16Array") - checkStuff(members[14], members[15], "Int32Array") - checkStuff(members[16], members[17], "Uint32Array") - checkStuff(members[18], members[19], "Float32Array") - checkStuff(members[20], members[21], "Float64Array") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_attr.py b/src/components/script/dom/bindings/codegen/parser/tests/test_attr.py deleted file mode 100644 index 6b6142b6243..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_attr.py +++ /dev/null @@ -1,302 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - testData = [("::TestAttr%s::b", "b", "Byte%s", False), - ("::TestAttr%s::rb", "rb", "Byte%s", True), - ("::TestAttr%s::o", "o", "Octet%s", False), - ("::TestAttr%s::ro", "ro", "Octet%s", True), - ("::TestAttr%s::s", "s", "Short%s", False), - ("::TestAttr%s::rs", "rs", "Short%s", True), - ("::TestAttr%s::us", "us", "UnsignedShort%s", False), - ("::TestAttr%s::rus", "rus", "UnsignedShort%s", True), - ("::TestAttr%s::l", "l", "Long%s", False), - ("::TestAttr%s::rl", "rl", "Long%s", True), - ("::TestAttr%s::ul", "ul", "UnsignedLong%s", False), - ("::TestAttr%s::rul", "rul", "UnsignedLong%s", True), - ("::TestAttr%s::ll", "ll", "LongLong%s", False), - ("::TestAttr%s::rll", "rll", "LongLong%s", True), - ("::TestAttr%s::ull", "ull", "UnsignedLongLong%s", False), - ("::TestAttr%s::rull", "rull", "UnsignedLongLong%s", True), - ("::TestAttr%s::str", "str", "String%s", False), - ("::TestAttr%s::rstr", "rstr", "String%s", True), - ("::TestAttr%s::obj", "obj", "Object%s", False), - ("::TestAttr%s::robj", "robj", "Object%s", True), - ("::TestAttr%s::object", "object", "Object%s", False), - ("::TestAttr%s::f", "f", "Float%s", False), - ("::TestAttr%s::rf", "rf", "Float%s", True)] - - parser.parse(""" - interface TestAttr { - attribute byte b; - readonly attribute byte rb; - attribute octet o; - readonly attribute octet ro; - attribute short s; - readonly attribute short rs; - attribute unsigned short us; - readonly attribute unsigned short rus; - attribute long l; - readonly attribute long rl; - attribute unsigned long ul; - readonly attribute unsigned long rul; - attribute long long ll; - readonly attribute long long rll; - attribute unsigned long long ull; - readonly attribute unsigned long long rull; - attribute DOMString str; - readonly attribute DOMString rstr; - attribute object obj; - readonly attribute object robj; - attribute object _object; - attribute float f; - readonly attribute float rf; - }; - - interface TestAttrNullable { - attribute byte? b; - readonly attribute byte? rb; - attribute octet? o; - readonly attribute octet? ro; - attribute short? s; - readonly attribute short? rs; - attribute unsigned short? us; - readonly attribute unsigned short? rus; - attribute long? l; - readonly attribute long? rl; - attribute unsigned long? ul; - readonly attribute unsigned long? rul; - attribute long long? ll; - readonly attribute long long? rll; - attribute unsigned long long? ull; - readonly attribute unsigned long long? rull; - attribute DOMString? str; - readonly attribute DOMString? rstr; - attribute object? obj; - readonly attribute object? robj; - attribute object? _object; - attribute float? f; - readonly attribute float? rf; - }; - - interface TestAttrArray { - attribute byte[] b; - readonly attribute byte[] rb; - attribute octet[] o; - readonly attribute octet[] ro; - attribute short[] s; - readonly attribute short[] rs; - attribute unsigned short[] us; - readonly attribute unsigned short[] rus; - attribute long[] l; - readonly attribute long[] rl; - attribute unsigned long[] ul; - readonly attribute unsigned long[] rul; - attribute long long[] ll; - readonly attribute long long[] rll; - attribute unsigned long long[] ull; - readonly attribute unsigned long long[] rull; - attribute DOMString[] str; - readonly attribute DOMString[] rstr; - attribute object[] obj; - readonly attribute object[] robj; - attribute object[] _object; - attribute float[] f; - readonly attribute float[] rf; - }; - - interface TestAttrNullableArray { - attribute byte[]? b; - readonly attribute byte[]? rb; - attribute octet[]? o; - readonly attribute octet[]? ro; - attribute short[]? s; - readonly attribute short[]? rs; - attribute unsigned short[]? us; - readonly attribute unsigned short[]? rus; - attribute long[]? l; - readonly attribute long[]? rl; - attribute unsigned long[]? ul; - readonly attribute unsigned long[]? rul; - attribute long long[]? ll; - readonly attribute long long[]? rll; - attribute unsigned long long[]? ull; - readonly attribute unsigned long long[]? rull; - attribute DOMString[]? str; - readonly attribute DOMString[]? rstr; - attribute object[]? obj; - readonly attribute object[]? robj; - attribute object[]? _object; - attribute float[]? f; - readonly attribute float[]? rf; - }; - - interface TestAttrArrayOfNullableTypes { - attribute byte?[] b; - readonly attribute byte?[] rb; - attribute octet?[] o; - readonly attribute octet?[] ro; - attribute short?[] s; - readonly attribute short?[] rs; - attribute unsigned short?[] us; - readonly attribute unsigned short?[] rus; - attribute long?[] l; - readonly attribute long?[] rl; - attribute unsigned long?[] ul; - readonly attribute unsigned long?[] rul; - attribute long long?[] ll; - readonly attribute long long?[] rll; - attribute unsigned long long?[] ull; - readonly attribute unsigned long long?[] rull; - attribute DOMString?[] str; - readonly attribute DOMString?[] rstr; - attribute object?[] obj; - readonly attribute object?[] robj; - attribute object?[] _object; - attribute float?[] f; - readonly attribute float?[] rf; - }; - - interface TestAttrNullableArrayOfNullableTypes { - attribute byte?[]? b; - readonly attribute byte?[]? rb; - attribute octet?[]? o; - readonly attribute octet?[]? ro; - attribute short?[]? s; - readonly attribute short?[]? rs; - attribute unsigned short?[]? us; - readonly attribute unsigned short?[]? rus; - attribute long?[]? l; - readonly attribute long?[]? rl; - attribute unsigned long?[]? ul; - readonly attribute unsigned long?[]? rul; - attribute long long?[]? ll; - readonly attribute long long?[]? rll; - attribute unsigned long long?[]? ull; - readonly attribute unsigned long long?[]? rull; - attribute DOMString?[]? str; - readonly attribute DOMString?[]? rstr; - attribute object?[]? obj; - readonly attribute object?[]? robj; - attribute object?[]? _object; - attribute float?[]? f; - readonly attribute float?[]? rf; - }; - """) - - results = parser.finish() - - def checkAttr(attr, QName, name, type, readonly): - harness.ok(isinstance(attr, WebIDL.IDLAttribute), - "Should be an IDLAttribute") - harness.ok(attr.isAttr(), "Attr is an Attr") - harness.ok(not attr.isMethod(), "Attr is not an method") - harness.ok(not attr.isConst(), "Attr is not a const") - harness.check(attr.identifier.QName(), QName, "Attr has the right QName") - harness.check(attr.identifier.name, name, "Attr has the right name") - harness.check(str(attr.type), type, "Attr has the right type") - harness.check(attr.readonly, readonly, "Attr's readonly state is correct") - - harness.ok(True, "TestAttr interface parsed without error.") - harness.check(len(results), 6, "Should be six productions.") - iface = results[0] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestAttr", "Interface has the right QName") - harness.check(iface.identifier.name, "TestAttr", "Interface has the right name") - harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData)) - - attrs = iface.members - - for i in range(len(attrs)): - data = testData[i] - attr = attrs[i] - (QName, name, type, readonly) = data - checkAttr(attr, QName % "", name, type % "", readonly) - - iface = results[1] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestAttrNullable", "Interface has the right QName") - harness.check(iface.identifier.name, "TestAttrNullable", "Interface has the right name") - harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData)) - - attrs = iface.members - - for i in range(len(attrs)): - data = testData[i] - attr = attrs[i] - (QName, name, type, readonly) = data - checkAttr(attr, QName % "Nullable", name, type % "OrNull", readonly) - - iface = results[2] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestAttrArray", "Interface has the right QName") - harness.check(iface.identifier.name, "TestAttrArray", "Interface has the right name") - harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData)) - - attrs = iface.members - - for i in range(len(attrs)): - data = testData[i] - attr = attrs[i] - (QName, name, type, readonly) = data - checkAttr(attr, QName % "Array", name, type % "Array", readonly) - - iface = results[3] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestAttrNullableArray", "Interface has the right QName") - harness.check(iface.identifier.name, "TestAttrNullableArray", "Interface has the right name") - harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData)) - - attrs = iface.members - - for i in range(len(attrs)): - data = testData[i] - attr = attrs[i] - (QName, name, type, readonly) = data - checkAttr(attr, QName % "NullableArray", name, type % "ArrayOrNull", readonly) - - iface = results[4] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestAttrArrayOfNullableTypes", "Interface has the right QName") - harness.check(iface.identifier.name, "TestAttrArrayOfNullableTypes", "Interface has the right name") - harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData)) - - attrs = iface.members - - for i in range(len(attrs)): - data = testData[i] - attr = attrs[i] - (QName, name, type, readonly) = data - checkAttr(attr, QName % "ArrayOfNullableTypes", name, type % "OrNullArray", readonly) - - iface = results[5] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestAttrNullableArrayOfNullableTypes", "Interface has the right QName") - harness.check(iface.identifier.name, "TestAttrNullableArrayOfNullableTypes", "Interface has the right name") - harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData)) - - attrs = iface.members - - for i in range(len(attrs)): - data = testData[i] - attr = attrs[i] - (QName, name, type, readonly) = data - checkAttr(attr, QName % "NullableArrayOfNullableTypes", name, type % "OrNullArrayOrNull", readonly) - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A { - [SetterInfallible] readonly attribute boolean foo; - }; - """) - results = parser.finish() - except Exception, x: - threw = True - harness.ok(threw, "Should not allow [SetterInfallible] on readonly attributes") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_attr_sequence_type.py b/src/components/script/dom/bindings/codegen/parser/tests/test_attr_sequence_type.py deleted file mode 100644 index fb1b97812bc..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_attr_sequence_type.py +++ /dev/null @@ -1,67 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface AttrSequenceType { - attribute sequence<object> foo; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Attribute type must not be a sequence type") - - parser.reset() - - threw = False - try: - parser.parse(""" - interface AttrUnionWithSequenceType { - attribute (sequence<object> or DOMString) foo; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Attribute type must not be a union with a sequence member type") - - parser.reset() - - threw = False - try: - parser.parse(""" - interface AttrNullableUnionWithSequenceType { - attribute (sequence<object>? or DOMString) foo; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Attribute type must not be a union with a nullable sequence " - "member type") - - parser.reset() - - threw = False - try: - parser.parse(""" - interface AttrUnionWithUnionWithSequenceType { - attribute ((sequence<object> or DOMString) or AttrUnionWithUnionWithSequenceType) foo; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Attribute type must not be a union type with a union member " - "type that has a sequence member type") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_builtin_filename.py b/src/components/script/dom/bindings/codegen/parser/tests/test_builtin_filename.py deleted file mode 100644 index 631e52eba0b..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_builtin_filename.py +++ /dev/null @@ -1,11 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface Test { - attribute long b; - }; - """); - - attr = parser.finish()[0].members[0] - harness.check(attr.type.filename(), '<builtin>', 'Filename on builtin type') diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_builtins.py b/src/components/script/dom/bindings/codegen/parser/tests/test_builtins.py deleted file mode 100644 index f8563fc2d9b..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_builtins.py +++ /dev/null @@ -1,41 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestBuiltins { - attribute boolean b; - attribute byte s8; - attribute octet u8; - attribute short s16; - attribute unsigned short u16; - attribute long s32; - attribute unsigned long u32; - attribute long long s64; - attribute unsigned long long u64; - attribute DOMTimeStamp ts; - }; - """) - - results = parser.finish() - - harness.ok(True, "TestBuiltins interface parsed without error.") - harness.check(len(results), 1, "Should be one production") - harness.ok(isinstance(results[0], WebIDL.IDLInterface), - "Should be an IDLInterface") - iface = results[0] - harness.check(iface.identifier.QName(), "::TestBuiltins", "Interface has the right QName") - harness.check(iface.identifier.name, "TestBuiltins", "Interface has the right name") - harness.check(iface.parent, None, "Interface has no parent") - - members = iface.members - harness.check(len(members), 10, "Should be one production") - - names = ["b", "s8", "u8", "s16", "u16", "s32", "u32", "s64", "u64", "ts"] - types = ["Boolean", "Byte", "Octet", "Short", "UnsignedShort", "Long", "UnsignedLong", "LongLong", "UnsignedLongLong", "UnsignedLongLong"] - for i in range(10): - attr = members[i] - harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute") - harness.check(attr.identifier.QName(), "::TestBuiltins::" + names[i], "Attr has correct QName") - harness.check(attr.identifier.name, names[i], "Attr has correct name") - harness.check(str(attr.type), types[i], "Attr type is the correct name") - harness.ok(attr.type.isPrimitive(), "Should be a primitive type") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_callback.py b/src/components/script/dom/bindings/codegen/parser/tests/test_callback.py deleted file mode 100644 index 267d27dc087..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_callback.py +++ /dev/null @@ -1,34 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestCallback { - attribute CallbackType? listener; - }; - - callback CallbackType = boolean (unsigned long arg); - """) - - results = parser.finish() - - harness.ok(True, "TestCallback interface parsed without error.") - harness.check(len(results), 2, "Should be one production.") - iface = results[0] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestCallback", "Interface has the right QName") - harness.check(iface.identifier.name, "TestCallback", "Interface has the right name") - harness.check(len(iface.members), 1, "Expect %s members" % 1) - - attr = iface.members[0] - harness.ok(isinstance(attr, WebIDL.IDLAttribute), - "Should be an IDLAttribute") - harness.ok(attr.isAttr(), "Should be an attribute") - harness.ok(not attr.isMethod(), "Attr is not an method") - harness.ok(not attr.isConst(), "Attr is not a const") - harness.check(attr.identifier.QName(), "::TestCallback::listener", "Attr has the right QName") - harness.check(attr.identifier.name, "listener", "Attr has the right name") - t = attr.type - harness.ok(not isinstance(t, WebIDL.IDLWrapperType), "Attr has the right type") - harness.ok(isinstance(t, WebIDL.IDLNullableType), "Attr has the right type") - harness.ok(t.isCallback(), "Attr has the right type") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_callback_interface.py b/src/components/script/dom/bindings/codegen/parser/tests/test_callback_interface.py deleted file mode 100644 index 80896ca1edb..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_callback_interface.py +++ /dev/null @@ -1,47 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - callback interface TestCallbackInterface { - attribute boolean bool; - }; - """) - - results = parser.finish() - - iface = results[0] - - harness.ok(iface.isCallback(), "Interface should be a callback") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface TestInterface { - }; - callback interface TestCallbackInterface : TestInterface { - attribute boolean bool; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow non-callback parent of callback interface") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface TestInterface : TestCallbackInterface { - }; - callback interface TestCallbackInterface { - attribute boolean bool; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow callback parent of non-callback interface") - diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_const.py b/src/components/script/dom/bindings/codegen/parser/tests/test_const.py deleted file mode 100644 index 12f411363fb..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_const.py +++ /dev/null @@ -1,64 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestConsts { - const byte zero = 0; - const byte b = -1; - const octet o = 2; - const short s = -3; - const unsigned short us = 0x4; - const long l = -0X5; - const unsigned long ul = 6; - const unsigned long long ull = 7; - const long long ll = -010; - const boolean t = true; - const boolean f = false; - const boolean? n = null; - const boolean? nt = true; - const boolean? nf = false; - }; - """) - - results = parser.finish() - - harness.ok(True, "TestConsts interface parsed without error.") - harness.check(len(results), 1, "Should be one production.") - iface = results[0] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestConsts", "Interface has the right QName") - harness.check(iface.identifier.name, "TestConsts", "Interface has the right name") - harness.check(len(iface.members), 14, "Expect 14 members") - - consts = iface.members - - def checkConst(const, QName, name, type, value): - harness.ok(isinstance(const, WebIDL.IDLConst), - "Should be an IDLConst") - harness.ok(const.isConst(), "Const is a const") - harness.ok(not const.isAttr(), "Const is not an attr") - harness.ok(not const.isMethod(), "Const is not a method") - harness.check(const.identifier.QName(), QName, "Const has the right QName") - harness.check(const.identifier.name, name, "Const has the right name") - harness.check(str(const.type), type, "Const has the right type") - harness.ok(const.type.isPrimitive(), "All consts should be primitive") - harness.check(str(const.value.type), str(const.type), - "Const's value has the same type as the type") - harness.check(const.value.value, value, "Const value has the right value.") - - checkConst(consts[0], "::TestConsts::zero", "zero", "Byte", 0) - checkConst(consts[1], "::TestConsts::b", "b", "Byte", -1) - checkConst(consts[2], "::TestConsts::o", "o", "Octet", 2) - checkConst(consts[3], "::TestConsts::s", "s", "Short", -3) - checkConst(consts[4], "::TestConsts::us", "us", "UnsignedShort", 4) - checkConst(consts[5], "::TestConsts::l", "l", "Long", -5) - checkConst(consts[6], "::TestConsts::ul", "ul", "UnsignedLong", 6) - checkConst(consts[7], "::TestConsts::ull", "ull", "UnsignedLongLong", 7) - checkConst(consts[8], "::TestConsts::ll", "ll", "LongLong", -8) - checkConst(consts[9], "::TestConsts::t", "t", "Boolean", True) - checkConst(consts[10], "::TestConsts::f", "f", "Boolean", False) - checkConst(consts[11], "::TestConsts::n", "n", "BooleanOrNull", None) - checkConst(consts[12], "::TestConsts::nt", "nt", "BooleanOrNull", True) - checkConst(consts[13], "::TestConsts::nf", "nf", "BooleanOrNull", False) - diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_constructor.py b/src/components/script/dom/bindings/codegen/parser/tests/test_constructor.py deleted file mode 100644 index 6ec1be1871b..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_constructor.py +++ /dev/null @@ -1,75 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - def checkArgument(argument, QName, name, type, optional, variadic): - harness.ok(isinstance(argument, WebIDL.IDLArgument), - "Should be an IDLArgument") - harness.check(argument.identifier.QName(), QName, "Argument has the right QName") - harness.check(argument.identifier.name, name, "Argument has the right name") - harness.check(str(argument.type), type, "Argument has the right return type") - harness.check(argument.optional, optional, "Argument has the right optional value") - harness.check(argument.variadic, variadic, "Argument has the right variadic value") - - def checkMethod(method, QName, name, signatures, - static=False, getter=False, setter=False, creator=False, - deleter=False, legacycaller=False, stringifier=False): - harness.ok(isinstance(method, WebIDL.IDLMethod), - "Should be an IDLMethod") - harness.ok(method.isMethod(), "Method is a method") - harness.ok(not method.isAttr(), "Method is not an attr") - harness.ok(not method.isConst(), "Method is not a const") - harness.check(method.identifier.QName(), QName, "Method has the right QName") - harness.check(method.identifier.name, name, "Method has the right name") - harness.check(method.isStatic(), static, "Method has the correct static value") - harness.check(method.isGetter(), getter, "Method has the correct getter value") - harness.check(method.isSetter(), setter, "Method has the correct setter value") - harness.check(method.isCreator(), creator, "Method has the correct creator value") - harness.check(method.isDeleter(), deleter, "Method has the correct deleter value") - harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value") - harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value") - harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures") - - sigpairs = zip(method.signatures(), signatures) - for (gotSignature, expectedSignature) in sigpairs: - (gotRetType, gotArgs) = gotSignature - (expectedRetType, expectedArgs) = expectedSignature - - harness.check(str(gotRetType), expectedRetType, - "Method has the expected return type.") - - for i in range(0, len(gotArgs)): - (QName, name, type, optional, variadic) = expectedArgs[i] - checkArgument(gotArgs[i], QName, name, type, optional, variadic) - - parser.parse(""" - [Constructor] - interface TestConstructorNoArgs { - }; - - [Constructor(DOMString name)] - interface TestConstructorWithArgs { - }; - - [Constructor(object foo), Constructor(boolean bar)] - interface TestConstructorOverloads { - }; - """) - results = parser.finish() - harness.check(len(results), 3, "Should be two productions") - harness.ok(isinstance(results[0], WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.ok(isinstance(results[1], WebIDL.IDLInterface), - "Should be an IDLInterface") - - checkMethod(results[0].ctor(), "::TestConstructorNoArgs::constructor", - "constructor", [("TestConstructorNoArgs (Wrapper)", [])]) - checkMethod(results[1].ctor(), "::TestConstructorWithArgs::constructor", - "constructor", - [("TestConstructorWithArgs (Wrapper)", - [("::TestConstructorWithArgs::constructor::name", "name", "String", False, False)])]) - checkMethod(results[2].ctor(), "::TestConstructorOverloads::constructor", - "constructor", - [("TestConstructorOverloads (Wrapper)", - [("::TestConstructorOverloads::constructor::foo", "foo", "Object", False, False)]), - ("TestConstructorOverloads (Wrapper)", - [("::TestConstructorOverloads::constructor::bar", "bar", "Boolean", False, False)])]) diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_constructor_no_interface_object.py b/src/components/script/dom/bindings/codegen/parser/tests/test_constructor_no_interface_object.py deleted file mode 100644 index 192c5f6f97b..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_constructor_no_interface_object.py +++ /dev/null @@ -1,28 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - [Constructor, NoInterfaceObject] - interface TestConstructorNoInterfaceObject { - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - [NoInterfaceObject, Constructor] - interface TestConstructorNoInterfaceObject { - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_deduplicate.py b/src/components/script/dom/bindings/codegen/parser/tests/test_deduplicate.py deleted file mode 100644 index 6249d36fb8f..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_deduplicate.py +++ /dev/null @@ -1,15 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface Foo; - interface Bar; - interface Foo; - """); - - results = parser.finish() - - # There should be no duplicate interfaces in the result. - expectedNames = sorted(['Foo', 'Bar']) - actualNames = sorted(map(lambda iface: iface.identifier.name, results)) - harness.check(actualNames, expectedNames, "Parser shouldn't output duplicate names.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_dictionary.py b/src/components/script/dom/bindings/codegen/parser/tests/test_dictionary.py deleted file mode 100644 index 9ae9eb2b66f..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_dictionary.py +++ /dev/null @@ -1,198 +0,0 @@ -def WebIDLTest(parser, harness): - parser.parse(""" - dictionary Dict2 : Dict1 { - long child = 5; - Dict1 aaandAnother; - }; - dictionary Dict1 { - long parent; - double otherParent; - }; - """) - results = parser.finish() - - dict1 = results[1]; - dict2 = results[0]; - - harness.check(len(dict1.members), 2, "Dict1 has two members") - harness.check(len(dict2.members), 2, "Dict2 has four members") - - harness.check(dict1.members[0].identifier.name, "otherParent", - "'o' comes before 'p'") - harness.check(dict1.members[1].identifier.name, "parent", - "'o' really comes before 'p'") - harness.check(dict2.members[0].identifier.name, "aaandAnother", - "'a' comes before 'c'") - harness.check(dict2.members[1].identifier.name, "child", - "'a' really comes before 'c'") - - # Now reset our parser - parser = parser.reset() - threw = False - try: - parser.parse(""" - dictionary Dict { - long prop = 5; - long prop; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow name duplication in a dictionary") - - # Now reset our parser again - parser = parser.reset() - threw = False - try: - parser.parse(""" - dictionary Dict1 : Dict2 { - long prop = 5; - }; - dictionary Dict2 : Dict3 { - long prop2; - }; - dictionary Dict3 { - double prop; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow name duplication in a dictionary and " - "its ancestor") - - # More reset - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface Iface {}; - dictionary Dict : Iface { - long prop; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow non-dictionary parents for dictionaries") - - # Even more reset - parser = parser.reset() - threw = False - try: - parser.parse(""" - dictionary A : B {}; - dictionary B : A {}; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow cycles in dictionary inheritance chains") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - dictionary A { - [TreatNullAs=EmptyString] DOMString foo; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow [TreatNullAs] on dictionary members"); - - parser = parser.reset() - threw = False - try: - parser.parse(""" - dictionary A { - [TreatUndefinedAs=EmptyString] DOMString foo; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow [TreatUndefinedAs] on dictionary members"); - - parser = parser.reset() - threw = False - try: - parser.parse(""" - dictionary A { - }; - interface X { - void doFoo(A arg); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Trailing dictionary arg must be optional") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - dictionary A { - }; - interface X { - void doFoo(A arg1, optional long arg2); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Dictionary arg followed by optional arg must be optional") - - parser = parser.reset() - parser.parse(""" - dictionary A { - }; - interface X { - void doFoo(A arg1, long arg2); - }; - """) - results = parser.finish() - harness.ok(True, "Dictionary arg followed by required arg can be required") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - dictionary A { - }; - interface X { - void doFoo(optional A? arg1); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Dictionary arg must not be nullable") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - dictionary A { - }; - interface X { - void doFoo((A or long)? arg1); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Dictionary arg must not be in a nullable union") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_distinguishability.py b/src/components/script/dom/bindings/codegen/parser/tests/test_distinguishability.py deleted file mode 100644 index 86847800631..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_distinguishability.py +++ /dev/null @@ -1,150 +0,0 @@ -def firstArgType(method): - return method.signatures()[0][1][0].type - -def WebIDLTest(parser, harness): - parser.parse(""" - dictionary Dict { - }; - callback interface Foo { - }; - interface Bar { - // Bit of a pain to get things that have dictionary types - void passDict(optional Dict arg); - void passFoo(Foo arg); - void passNullableUnion((object? or DOMString) arg); - void passNullable(Foo? arg); - }; - """) - results = parser.finish() - - iface = results[2] - harness.ok(iface.isInterface(), "Should have interface") - dictMethod = iface.members[0] - ifaceMethod = iface.members[1] - nullableUnionMethod = iface.members[2] - nullableIfaceMethod = iface.members[3] - - dictType = firstArgType(dictMethod) - ifaceType = firstArgType(ifaceMethod) - - harness.ok(dictType.isDictionary(), "Should have dictionary type"); - harness.ok(ifaceType.isInterface(), "Should have interface type"); - harness.ok(ifaceType.isCallbackInterface(), "Should have callback interface type"); - - harness.ok(not dictType.isDistinguishableFrom(ifaceType), - "Dictionary not distinguishable from callback interface") - harness.ok(not ifaceType.isDistinguishableFrom(dictType), - "Callback interface not distinguishable from dictionary") - - nullableUnionType = firstArgType(nullableUnionMethod) - nullableIfaceType = firstArgType(nullableIfaceMethod) - - harness.ok(nullableUnionType.isUnion(), "Should have union type"); - harness.ok(nullableIfaceType.isInterface(), "Should have interface type"); - harness.ok(nullableIfaceType.nullable(), "Should have nullable type"); - - harness.ok(not nullableUnionType.isDistinguishableFrom(nullableIfaceType), - "Nullable type not distinguishable from union with nullable " - "member type") - harness.ok(not nullableIfaceType.isDistinguishableFrom(nullableUnionType), - "Union with nullable member type not distinguishable from " - "nullable type") - - parser = parser.reset() - parser.parse(""" - interface TestIface { - void passKid(Kid arg); - void passParent(Parent arg); - void passGrandparent(Grandparent arg); - void passImplemented(Implemented arg); - void passImplementedParent(ImplementedParent arg); - void passUnrelated1(Unrelated1 arg); - void passUnrelated2(Unrelated2 arg); - void passArrayBuffer(ArrayBuffer arg); - void passArrayBuffer(ArrayBufferView arg); - }; - - interface Kid : Parent {}; - interface Parent : Grandparent {}; - interface Grandparent {}; - interface Implemented : ImplementedParent {}; - Parent implements Implemented; - interface ImplementedParent {}; - interface Unrelated1 {}; - interface Unrelated2 {}; - """) - results = parser.finish() - - iface = results[0] - harness.ok(iface.isInterface(), "Should have interface") - argTypes = [firstArgType(method) for method in iface.members] - unrelatedTypes = [firstArgType(method) for method in iface.members[-3:]] - - for type1 in argTypes: - for type2 in argTypes: - distinguishable = (type1 is not type2 and - (type1 in unrelatedTypes or - type2 in unrelatedTypes)) - - harness.check(type1.isDistinguishableFrom(type2), - distinguishable, - "Type %s should %sbe distinguishable from type %s" % - (type1, "" if distinguishable else "not ", type2)) - harness.check(type2.isDistinguishableFrom(type1), - distinguishable, - "Type %s should %sbe distinguishable from type %s" % - (type2, "" if distinguishable else "not ", type1)) - - parser = parser.reset() - parser.parse(""" - interface Dummy {}; - interface TestIface { - void method(long arg1, TestIface arg2); - void method(long arg1, long arg2); - void method(long arg1, Dummy arg2); - void method(DOMString arg1, DOMString arg2, DOMString arg3); - }; - """) - results = parser.finish() - harness.check(len(results[1].members), 1, - "Should look like we have one method") - harness.check(len(results[1].members[0].signatures()), 4, - "Should have four signatures") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface Dummy {}; - interface TestIface { - void method(long arg1, TestIface arg2); - void method(long arg1, long arg2); - void method(any arg1, Dummy arg2); - void method(DOMString arg1, DOMString arg2, DOMString arg3); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Should throw when args before the distinguishing arg are not " - "all the same type") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface Dummy {}; - interface TestIface { - void method(long arg1, TestIface arg2); - void method(long arg1, long arg2); - void method(any arg1, DOMString arg2); - void method(DOMString arg1, DOMString arg2, DOMString arg3); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should throw when there is no distinguishing index") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_double_null.py b/src/components/script/dom/bindings/codegen/parser/tests/test_double_null.py deleted file mode 100644 index 700c7eade00..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_double_null.py +++ /dev/null @@ -1,14 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface DoubleNull { - attribute byte?? foo; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_duplicate_qualifiers.py b/src/components/script/dom/bindings/codegen/parser/tests/test_duplicate_qualifiers.py deleted file mode 100644 index 799f2e0e0ed..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_duplicate_qualifiers.py +++ /dev/null @@ -1,84 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface DuplicateQualifiers1 { - getter getter byte foo(unsigned long index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface DuplicateQualifiers2 { - setter setter byte foo(unsigned long index, byte value); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface DuplicateQualifiers3 { - creator creator byte foo(unsigned long index, byte value); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface DuplicateQualifiers4 { - deleter deleter byte foo(unsigned long index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface DuplicateQualifiers5 { - getter deleter getter byte foo(unsigned long index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - results = parser.parse(""" - interface DuplicateQualifiers6 { - creator setter creator byte foo(unsigned long index, byte value); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_empty_enum.py b/src/components/script/dom/bindings/codegen/parser/tests/test_empty_enum.py deleted file mode 100644 index ee0079f06da..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_empty_enum.py +++ /dev/null @@ -1,14 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - try: - parser.parse(""" - enum TestEmptyEnum { - }; - """) - - harness.ok(False, "Should have thrown!") - except: - harness.ok(True, "Parsing TestEmptyEnum enum should fail") - - results = parser.finish() diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_enum.py b/src/components/script/dom/bindings/codegen/parser/tests/test_enum.py deleted file mode 100644 index 69a6932062d..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_enum.py +++ /dev/null @@ -1,81 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - enum TestEnum { - "", - "foo", - "bar" - }; - - interface TestEnumInterface { - TestEnum doFoo(boolean arg); - readonly attribute TestEnum foo; - }; - """) - - results = parser.finish() - - harness.ok(True, "TestEnumInterfaces interface parsed without error.") - harness.check(len(results), 2, "Should be one production") - harness.ok(isinstance(results[0], WebIDL.IDLEnum), - "Should be an IDLEnum") - harness.ok(isinstance(results[1], WebIDL.IDLInterface), - "Should be an IDLInterface") - - enum = results[0] - harness.check(enum.identifier.QName(), "::TestEnum", "Enum has the right QName") - harness.check(enum.identifier.name, "TestEnum", "Enum has the right name") - harness.check(enum.values(), ["", "foo", "bar"], "Enum has the right values") - - iface = results[1] - - harness.check(iface.identifier.QName(), "::TestEnumInterface", "Interface has the right QName") - harness.check(iface.identifier.name, "TestEnumInterface", "Interface has the right name") - harness.check(iface.parent, None, "Interface has no parent") - - members = iface.members - harness.check(len(members), 2, "Should be one production") - harness.ok(isinstance(members[0], WebIDL.IDLMethod), - "Should be an IDLMethod") - method = members[0] - harness.check(method.identifier.QName(), "::TestEnumInterface::doFoo", - "Method has correct QName") - harness.check(method.identifier.name, "doFoo", "Method has correct name") - - signatures = method.signatures() - harness.check(len(signatures), 1, "Expect one signature") - - (returnType, arguments) = signatures[0] - harness.check(str(returnType), "TestEnum (Wrapper)", "Method type is the correct name") - harness.check(len(arguments), 1, "Method has the right number of arguments") - arg = arguments[0] - harness.ok(isinstance(arg, WebIDL.IDLArgument), "Should be an IDLArgument") - harness.check(str(arg.type), "Boolean", "Argument has the right type") - - attr = members[1] - harness.check(attr.identifier.QName(), "::TestEnumInterface::foo", - "Attr has correct QName") - harness.check(attr.identifier.name, "foo", "Attr has correct name") - - harness.check(str(attr.type), "TestEnum (Wrapper)", "Attr type is the correct name") - - # Now reset our parser - parser = parser.reset() - threw = False - try: - parser.parse(""" - enum Enum { - "a", - "b", - "c" - }; - interface TestInterface { - void foo(optional Enum e = "d"); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow a bogus default value for an enum") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_enum_duplicate_values.py b/src/components/script/dom/bindings/codegen/parser/tests/test_enum_duplicate_values.py deleted file mode 100644 index 51205d209e7..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_enum_duplicate_values.py +++ /dev/null @@ -1,13 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - try: - parser.parse(""" - enum TestEnumDuplicateValue { - "", - "" - }; - """) - harness.ok(False, "Should have thrown!") - except: - harness.ok(True, "Enum TestEnumDuplicateValue should throw") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_error_colno.py b/src/components/script/dom/bindings/codegen/parser/tests/test_error_colno.py deleted file mode 100644 index ca0674aec04..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_error_colno.py +++ /dev/null @@ -1,20 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - # Check that error messages put the '^' in the right place. - - threw = False - input = 'interface ?' - try: - parser.parse(input) - results = parser.finish() - except WebIDL.WebIDLError, e: - threw = True - lines = str(e).split('\n') - - harness.check(len(lines), 3, 'Expected number of lines in error message') - harness.check(lines[1], input, 'Second line shows error') - harness.check(lines[2], ' ' * (len(input) - 1) + '^', - 'Correct column pointer in error message') - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_error_lineno.py b/src/components/script/dom/bindings/codegen/parser/tests/test_error_lineno.py deleted file mode 100644 index f11222e7a4d..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_error_lineno.py +++ /dev/null @@ -1,28 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - # Check that error messages put the '^' in the right place. - - threw = False - input = """\ -// This is a comment. -interface Foo { -}; - -/* This is also a comment. */ -interface ?""" - try: - parser.parse(input) - results = parser.finish() - except WebIDL.WebIDLError, e: - threw = True - lines = str(e).split('\n') - - harness.check(len(lines), 3, 'Expected number of lines in error message') - harness.ok(lines[0].endswith('line 6:10'), 'First line of error should end with "line 6:10", but was "%s".' % lines[0]) - harness.check(lines[1], 'interface ?', 'Second line of error message is the line which caused the error.') - harness.check(lines[2], ' ' * (len('interface ?') - 1) + '^', - 'Correct column pointer in error message.') - - harness.ok(threw, "Should have thrown.") - diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_extended_attributes.py b/src/components/script/dom/bindings/codegen/parser/tests/test_extended_attributes.py deleted file mode 100644 index 5c6887331e7..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_extended_attributes.py +++ /dev/null @@ -1,107 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - [Flippety] - interface TestExtendedAttr { - [Foopy] attribute byte b; - }; - """) - - results = parser.finish() - - parser = parser.reset() - parser.parse(""" - [Flippety="foo.bar",Floppety=flop] - interface TestExtendedAttr { - [Foopy="foo.bar"] attribute byte b; - }; - """) - - results = parser.finish() - - parser = parser.reset() - parser.parse(""" - interface TestLenientThis { - [LenientThis] attribute byte b; - }; - """) - - results = parser.finish() - harness.ok(results[0].members[0].hasLenientThis(), - "Should have a lenient this") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface TestLenientThis2 { - [LenientThis=something] attribute byte b; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "[LenientThis] must take no arguments") - - parser = parser.reset() - parser.parse(""" - interface TestClamp { - void testClamp([Clamp] long foo); - void testNotClamp(long foo); - }; - """) - - results = parser.finish() - # Pull out the first argument out of the arglist of the first (and - # only) signature. - harness.ok(results[0].members[0].signatures()[0][1][0].clamp, - "Should be clamped") - harness.ok(not results[0].members[1].signatures()[0][1][0].clamp, - "Should not be clamped") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface TestClamp2 { - void testClamp([Clamp=something] long foo); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "[Clamp] must take no arguments") - - parser = parser.reset() - parser.parse(""" - interface TestEnforceRange { - void testEnforceRange([EnforceRange] long foo); - void testNotEnforceRange(long foo); - }; - """) - - results = parser.finish() - # Pull out the first argument out of the arglist of the first (and - # only) signature. - harness.ok(results[0].members[0].signatures()[0][1][0].enforceRange, - "Should be enforceRange") - harness.ok(not results[0].members[1].signatures()[0][1][0].enforceRange, - "Should not be enforceRange") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface TestEnforceRange2 { - void testEnforceRange([EnforceRange=something] long foo); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "[EnforceRange] must take no arguments") - diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_forward_decl.py b/src/components/script/dom/bindings/codegen/parser/tests/test_forward_decl.py deleted file mode 100644 index cac24c832cc..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_forward_decl.py +++ /dev/null @@ -1,15 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface ForwardDeclared; - interface ForwardDeclared; - - interface TestForwardDecl { - attribute ForwardDeclared foo; - }; - """) - - results = parser.finish() - - harness.ok(True, "TestForwardDeclared interface parsed without error.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_implements.py b/src/components/script/dom/bindings/codegen/parser/tests/test_implements.py deleted file mode 100644 index 04c47d92abe..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_implements.py +++ /dev/null @@ -1,216 +0,0 @@ -# Import the WebIDL module, so we can do isinstance checks and whatnot -import WebIDL - -def WebIDLTest(parser, harness): - # Basic functionality - threw = False - try: - parser.parse(""" - A implements B; - interface B { - attribute long x; - }; - interface A { - attribute long y; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(not threw, "Should not have thrown on implements statement " - "before interfaces") - harness.check(len(results), 3, "We have three statements") - harness.ok(isinstance(results[1], WebIDL.IDLInterface), "B is an interface") - harness.check(len(results[1].members), 1, "B has one member") - A = results[2] - harness.ok(isinstance(A, WebIDL.IDLInterface), "A is an interface") - harness.check(len(A.members), 2, "A has two members") - harness.check(A.members[0].identifier.name, "y", "First member is 'y'") - harness.check(A.members[1].identifier.name, "x", "Second member is 'x'") - - # Duplicated member names not allowed - threw = False - try: - parser.parse(""" - C implements D; - interface D { - attribute long x; - }; - interface C { - attribute long x; - }; - """) - parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown on implemented interface duplicating " - "a name on base interface") - - # Same, but duplicated across implemented interfaces - threw = False - try: - parser.parse(""" - E implements F; - E implements G; - interface F { - attribute long x; - }; - interface G { - attribute long x; - }; - interface E {}; - """) - parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown on implemented interfaces " - "duplicating each other's member names") - - # Same, but duplicated across indirectly implemented interfaces - threw = False - try: - parser.parse(""" - H implements I; - H implements J; - I implements K; - interface K { - attribute long x; - }; - interface L { - attribute long x; - }; - interface I {}; - interface J : L {}; - interface H {}; - """) - parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown on indirectly implemented interfaces " - "duplicating each other's member names") - - # Same, but duplicated across an implemented interface and its parent - threw = False - try: - parser.parse(""" - M implements N; - interface O { - attribute long x; - }; - interface N : O { - attribute long x; - }; - interface M {}; - """) - parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown on implemented interface and its " - "ancestor duplicating member names") - - # Reset the parser so we can actually find things where we expect - # them in the list - parser = parser.reset() - - # Diamonds should be allowed - threw = False - try: - parser.parse(""" - P implements Q; - P implements R; - Q implements S; - R implements S; - interface Q {}; - interface R {}; - interface S { - attribute long x; - }; - interface P {}; - """) - results = parser.finish() - except: - threw = True - - harness.ok(not threw, "Diamond inheritance is fine") - harness.check(results[6].identifier.name, "S", "We should be looking at 'S'") - harness.check(len(results[6].members), 1, "S should have one member") - harness.check(results[6].members[0].identifier.name, "x", - "S's member should be 'x'") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface TestInterface { - }; - callback interface TestCallbackInterface { - }; - TestInterface implements TestCallbackInterface; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Should not allow callback interfaces on the right-hand side " - "of 'implements'") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface TestInterface { - }; - callback interface TestCallbackInterface { - }; - TestCallbackInterface implements TestInterface; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Should not allow callback interfaces on the left-hand side of " - "'implements'") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface TestInterface { - }; - dictionary Dict { - }; - Dict implements TestInterface; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Should not allow non-interfaces on the left-hand side " - "of 'implements'") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface TestInterface { - }; - dictionary Dict { - }; - TestInterface implements Dict; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Should not allow non-interfaces on the right-hand side " - "of 'implements'") - diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_incomplete_parent.py b/src/components/script/dom/bindings/codegen/parser/tests/test_incomplete_parent.py deleted file mode 100644 index 1f520a28e16..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_incomplete_parent.py +++ /dev/null @@ -1,18 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestIncompleteParent : NotYetDefined { - void foo(); - }; - - interface NotYetDefined : EvenHigherOnTheChain { - }; - - interface EvenHigherOnTheChain { - }; - """) - - parser.finish() - - harness.ok(True, "TestIncompleteParent interface parsed without error.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_incomplete_types.py b/src/components/script/dom/bindings/codegen/parser/tests/test_incomplete_types.py deleted file mode 100644 index fdc39604070..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_incomplete_types.py +++ /dev/null @@ -1,44 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestIncompleteTypes { - attribute FooInterface attr1; - - FooInterface method1(FooInterface arg); - }; - - interface FooInterface { - }; - """) - - results = parser.finish() - - harness.ok(True, "TestIncompleteTypes interface parsed without error.") - harness.check(len(results), 2, "Should be two productions.") - iface = results[0] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestIncompleteTypes", "Interface has the right QName") - harness.check(iface.identifier.name, "TestIncompleteTypes", "Interface has the right name") - harness.check(len(iface.members), 2, "Expect 2 members") - - attr = iface.members[0] - harness.ok(isinstance(attr, WebIDL.IDLAttribute), - "Should be an IDLAttribute") - method = iface.members[1] - harness.ok(isinstance(method, WebIDL.IDLMethod), - "Should be an IDLMethod") - - harness.check(attr.identifier.QName(), "::TestIncompleteTypes::attr1", - "Attribute has the right QName") - harness.check(attr.type.name, "FooInterface", - "Previously unresolved type has the right name") - - harness.check(method.identifier.QName(), "::TestIncompleteTypes::method1", - "Attribute has the right QName") - (returnType, args) = method.signatures()[0] - harness.check(returnType.name, "FooInterface", - "Previously unresolved type has the right name") - harness.check(args[0].type.name, "FooInterface", - "Previously unresolved type has the right name") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_interface.py b/src/components/script/dom/bindings/codegen/parser/tests/test_interface.py deleted file mode 100644 index 5b07172c636..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_interface.py +++ /dev/null @@ -1,188 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse("interface Foo { };") - results = parser.finish() - harness.ok(True, "Empty interface parsed without error.") - harness.check(len(results), 1, "Should be one production") - harness.ok(isinstance(results[0], WebIDL.IDLInterface), - "Should be an IDLInterface") - iface = results[0] - harness.check(iface.identifier.QName(), "::Foo", "Interface has the right QName") - harness.check(iface.identifier.name, "Foo", "Interface has the right name") - harness.check(iface.parent, None, "Interface has no parent") - - parser.parse("interface Bar : Foo { };") - results = parser.finish() - harness.ok(True, "Empty interface parsed without error.") - harness.check(len(results), 2, "Should be two productions") - harness.ok(isinstance(results[1], WebIDL.IDLInterface), - "Should be an IDLInterface") - iface = results[1] - harness.check(iface.identifier.QName(), "::Bar", "Interface has the right QName") - harness.check(iface.identifier.name, "Bar", "Interface has the right name") - harness.ok(isinstance(iface.parent, WebIDL.IDLInterface), - "Interface has a parent") - - parser = parser.reset() - parser.parse(""" - interface QNameBase { - attribute long foo; - }; - - interface QNameDerived : QNameBase { - attribute long long foo; - attribute byte bar; - }; - """) - results = parser.finish() - harness.check(len(results), 2, "Should be two productions") - harness.ok(isinstance(results[0], WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.ok(isinstance(results[1], WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(results[1].parent, results[0], "Inheritance chain is right") - harness.check(len(results[0].members), 1, "Expect 1 productions") - harness.check(len(results[1].members), 2, "Expect 2 productions") - base = results[0] - derived = results[1] - harness.check(base.members[0].identifier.QName(), "::QNameBase::foo", - "Member has the right QName") - harness.check(derived.members[0].identifier.QName(), "::QNameDerived::foo", - "Member has the right QName") - harness.check(derived.members[1].identifier.QName(), "::QNameDerived::bar", - "Member has the right QName") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A : B {}; - interface B : A {}; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow cycles in interface inheritance chains") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A : C {}; - interface C : B {}; - interface B : A {}; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow indirect cycles in interface inheritance chains") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A {}; - interface B {}; - A implements B; - B implements A; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow cycles via implements") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A {}; - interface C {}; - interface B {}; - A implements C; - C implements B; - B implements A; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow indirect cycles via implements") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A : B {}; - interface B {}; - B implements A; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow inheriting from an interface that implements us") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A : B {}; - interface B {}; - interface C {}; - B implements C; - C implements A; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow inheriting from an interface that indirectly implements us") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A : B {}; - interface B : C {}; - interface C {}; - C implements A; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow indirectly inheriting from an interface that implements us") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A : B {}; - interface B : C {}; - interface C {}; - interface D {}; - C implements D; - D implements A; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow indirectly inheriting from an interface that indirectly implements us") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A; - interface B : A {}; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should not allow inheriting from an interface that is only forward declared") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_interface_const_identifier_conflicts.py b/src/components/script/dom/bindings/codegen/parser/tests/test_interface_const_identifier_conflicts.py deleted file mode 100644 index db944e7aaf7..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_interface_const_identifier_conflicts.py +++ /dev/null @@ -1,15 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface IdentifierConflict { - const byte thing1 = 1; - const unsigned long thing1 = 1; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_interface_identifier_conflicts_across_members.py b/src/components/script/dom/bindings/codegen/parser/tests/test_interface_identifier_conflicts_across_members.py deleted file mode 100644 index 1a73fb917ed..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_interface_identifier_conflicts_across_members.py +++ /dev/null @@ -1,60 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface IdentifierConflictAcrossMembers1 { - const byte thing1 = 1; - readonly attribute long thing1; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface IdentifierConflictAcrossMembers2 { - readonly attribute long thing1; - const byte thing1 = 1; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface IdentifierConflictAcrossMembers3 { - getter boolean thing1(DOMString name); - readonly attribute long thing1; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface IdentifierConflictAcrossMembers1 { - const byte thing1 = 1; - long thing1(); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_method.py b/src/components/script/dom/bindings/codegen/parser/tests/test_method.py deleted file mode 100644 index 40b2d2cf8b9..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_method.py +++ /dev/null @@ -1,145 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestMethods { - void basic(); - static void basicStatic(); - void basicWithSimpleArgs(boolean arg1, byte arg2, unsigned long arg3); - boolean basicBoolean(); - static boolean basicStaticBoolean(); - boolean basicBooleanWithSimpleArgs(boolean arg1, byte arg2, unsigned long arg3); - void optionalArg(optional byte? arg1, optional sequence<byte> arg2); - void variadicArg(byte?... arg1); - void crazyTypes(sequence<long?[]>? arg1, boolean?[][]? arg2); - object getObject(); - void setObject(object arg1); - void setAny(any arg1); - float doFloats(float arg1); - }; - """) - - results = parser.finish() - - harness.ok(True, "TestMethods interface parsed without error.") - harness.check(len(results), 1, "Should be one production.") - iface = results[0] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestMethods", "Interface has the right QName") - harness.check(iface.identifier.name, "TestMethods", "Interface has the right name") - harness.check(len(iface.members), 13, "Expect 13 members") - - methods = iface.members - - def checkArgument(argument, QName, name, type, optional, variadic): - harness.ok(isinstance(argument, WebIDL.IDLArgument), - "Should be an IDLArgument") - harness.check(argument.identifier.QName(), QName, "Argument has the right QName") - harness.check(argument.identifier.name, name, "Argument has the right name") - harness.check(str(argument.type), type, "Argument has the right return type") - harness.check(argument.optional, optional, "Argument has the right optional value") - harness.check(argument.variadic, variadic, "Argument has the right variadic value") - - def checkMethod(method, QName, name, signatures, - static=False, getter=False, setter=False, creator=False, - deleter=False, legacycaller=False, stringifier=False): - harness.ok(isinstance(method, WebIDL.IDLMethod), - "Should be an IDLMethod") - harness.ok(method.isMethod(), "Method is a method") - harness.ok(not method.isAttr(), "Method is not an attr") - harness.ok(not method.isConst(), "Method is not a const") - harness.check(method.identifier.QName(), QName, "Method has the right QName") - harness.check(method.identifier.name, name, "Method has the right name") - harness.check(method.isStatic(), static, "Method has the correct static value") - harness.check(method.isGetter(), getter, "Method has the correct getter value") - harness.check(method.isSetter(), setter, "Method has the correct setter value") - harness.check(method.isCreator(), creator, "Method has the correct creator value") - harness.check(method.isDeleter(), deleter, "Method has the correct deleter value") - harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value") - harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value") - harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures") - - sigpairs = zip(method.signatures(), signatures) - for (gotSignature, expectedSignature) in sigpairs: - (gotRetType, gotArgs) = gotSignature - (expectedRetType, expectedArgs) = expectedSignature - - harness.check(str(gotRetType), expectedRetType, - "Method has the expected return type.") - - for i in range(0, len(gotArgs)): - (QName, name, type, optional, variadic) = expectedArgs[i] - checkArgument(gotArgs[i], QName, name, type, optional, variadic) - - checkMethod(methods[0], "::TestMethods::basic", "basic", [("Void", [])]) - checkMethod(methods[1], "::TestMethods::basicStatic", "basicStatic", - [("Void", [])], static=True) - checkMethod(methods[2], "::TestMethods::basicWithSimpleArgs", - "basicWithSimpleArgs", - [("Void", - [("::TestMethods::basicWithSimpleArgs::arg1", "arg1", "Boolean", False, False), - ("::TestMethods::basicWithSimpleArgs::arg2", "arg2", "Byte", False, False), - ("::TestMethods::basicWithSimpleArgs::arg3", "arg3", "UnsignedLong", False, False)])]) - checkMethod(methods[3], "::TestMethods::basicBoolean", "basicBoolean", [("Boolean", [])]) - checkMethod(methods[4], "::TestMethods::basicStaticBoolean", "basicStaticBoolean", [("Boolean", [])], static=True) - checkMethod(methods[5], "::TestMethods::basicBooleanWithSimpleArgs", - "basicBooleanWithSimpleArgs", - [("Boolean", - [("::TestMethods::basicBooleanWithSimpleArgs::arg1", "arg1", "Boolean", False, False), - ("::TestMethods::basicBooleanWithSimpleArgs::arg2", "arg2", "Byte", False, False), - ("::TestMethods::basicBooleanWithSimpleArgs::arg3", "arg3", "UnsignedLong", False, False)])]) - checkMethod(methods[6], "::TestMethods::optionalArg", - "optionalArg", - [("Void", - [("::TestMethods::optionalArg::arg1", "arg1", "ByteOrNull", True, False), - ("::TestMethods::optionalArg::arg2", "arg2", "ByteSequence", True, False)])]) - checkMethod(methods[7], "::TestMethods::variadicArg", - "variadicArg", - [("Void", - [("::TestMethods::variadicArg::arg1", "arg1", "ByteOrNull", True, True)])]) - checkMethod(methods[8], "::TestMethods::crazyTypes", - "crazyTypes", - [("Void", - [("::TestMethods::crazyTypes::arg1", "arg1", "LongOrNullArraySequenceOrNull", False, False), - ("::TestMethods::crazyTypes::arg2", "arg2", "BooleanOrNullArrayArrayOrNull", False, False)])]) - checkMethod(methods[9], "::TestMethods::getObject", - "getObject", [("Object", [])]) - checkMethod(methods[10], "::TestMethods::setObject", - "setObject", - [("Void", - [("::TestMethods::setObject::arg1", "arg1", "Object", False, False)])]) - checkMethod(methods[11], "::TestMethods::setAny", - "setAny", - [("Void", - [("::TestMethods::setAny::arg1", "arg1", "Any", False, False)])]) - checkMethod(methods[12], "::TestMethods::doFloats", - "doFloats", - [("Float", - [("::TestMethods::doFloats::arg1", "arg1", "Float", False, False)])]) - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A { - [GetterInfallible] void foo(); - }; - """) - results = parser.finish() - except Exception, x: - threw = True - harness.ok(threw, "Should not allow [GetterInfallible] on methods") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface A { - [SetterInfallible] void foo(); - }; - """) - results = parser.finish() - except Exception, x: - threw = True - harness.ok(threw, "Should not allow [SetterInfallible] on methods") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_nullable_equivalency.py b/src/components/script/dom/bindings/codegen/parser/tests/test_nullable_equivalency.py deleted file mode 100644 index 3366b9fbbbd..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_nullable_equivalency.py +++ /dev/null @@ -1,126 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestNullableEquivalency1 { - attribute long a; - attribute long? b; - }; - - interface TestNullableEquivalency2 { - attribute ArrayBuffer a; - attribute ArrayBuffer? b; - }; - - /* Can't have dictionary-valued attributes, so can't test that here */ - - enum TestNullableEquivalency4Enum { - "Foo", - "Bar" - }; - - interface TestNullableEquivalency4 { - attribute TestNullableEquivalency4Enum a; - attribute TestNullableEquivalency4Enum? b; - }; - - interface TestNullableEquivalency5 { - attribute TestNullableEquivalency4 a; - attribute TestNullableEquivalency4? b; - }; - - interface TestNullableEquivalency6 { - attribute boolean a; - attribute boolean? b; - }; - - interface TestNullableEquivalency7 { - attribute DOMString a; - attribute DOMString? b; - }; - - /* Not implemented. */ - /*interface TestNullableEquivalency8 { - attribute float a; - attribute float? b; - };*/ - - interface TestNullableEquivalency8 { - attribute double a; - attribute double? b; - }; - - interface TestNullableEquivalency9 { - attribute object a; - attribute object? b; - }; - - interface TestNullableEquivalency10 { - attribute double[] a; - attribute double[]? b; - }; - - interface TestNullableEquivalency11 { - attribute TestNullableEquivalency9[] a; - attribute TestNullableEquivalency9[]? b; - }; - """) - - for decl in parser.finish(): - if decl.isInterface(): - checkEquivalent(decl, harness) - -def checkEquivalent(iface, harness): - type1 = iface.members[0].type - type2 = iface.members[1].type - - harness.check(type1.nullable(), False, 'attr1 should not be nullable') - harness.check(type2.nullable(), True, 'attr2 should be nullable') - - # We don't know about type1, but type2, the nullable type, definitely - # shouldn't be builtin. - harness.check(type2.builtin, False, 'attr2 should not be builtin') - - # Ensure that all attributes of type2 match those in type1, except for: - # - names on an ignore list, - # - names beginning with '_', - # - functions which throw when called with no args, and - # - class-level non-callables ("static variables"). - # - # Yes, this is an ugly, fragile hack. But it finds bugs... - for attr in dir(type1): - if attr.startswith('_') or \ - attr in ['nullable', 'builtin', 'filename', 'location', - 'inner', 'QName'] or \ - (hasattr(type(type1), attr) and not callable(getattr(type1, attr))): - continue - - a1 = getattr(type1, attr) - - if callable(a1): - try: - v1 = a1() - except: - # Can't call a1 with no args, so skip this attriute. - continue - - try: - a2 = getattr(type2, attr) - except: - harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface)) - continue - - if not callable(a2): - harness.ok(False, "%s attribute on type %s in %s wasn't callable" % (attr, type2, iface)) - continue - - v2 = a2() - harness.check(v2, v1, '%s method return value' % attr) - else: - try: - a2 = getattr(type2, attr) - except: - harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface)) - continue - - harness.check(a2, a1, '%s attribute should match' % attr) diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_nullable_void.py b/src/components/script/dom/bindings/codegen/parser/tests/test_nullable_void.py deleted file mode 100644 index 961ff825e9f..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_nullable_void.py +++ /dev/null @@ -1,14 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface NullableVoid { - void? foo(); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_optional_constraints.py b/src/components/script/dom/bindings/codegen/parser/tests/test_optional_constraints.py deleted file mode 100644 index 1dcdc7fb8a5..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_optional_constraints.py +++ /dev/null @@ -1,14 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface OptionalConstraints1 { - void foo(optional byte arg1, byte arg2); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_overload.py b/src/components/script/dom/bindings/codegen/parser/tests/test_overload.py deleted file mode 100644 index 59d9be54e53..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_overload.py +++ /dev/null @@ -1,47 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface TestOverloads { - void basic(); - void basic(long arg1); - boolean abitharder(TestOverloads foo); - boolean abitharder(boolean foo); - void abitharder(ArrayBuffer? foo); - }; - """) - - results = parser.finish() - - harness.ok(True, "TestOverloads interface parsed without error.") - harness.check(len(results), 1, "Should be one production.") - iface = results[0] - harness.ok(isinstance(iface, WebIDL.IDLInterface), - "Should be an IDLInterface") - harness.check(iface.identifier.QName(), "::TestOverloads", "Interface has the right QName") - harness.check(iface.identifier.name, "TestOverloads", "Interface has the right name") - harness.check(len(iface.members), 2, "Expect %s members" % 2) - - member = iface.members[0] - harness.check(member.identifier.QName(), "::TestOverloads::basic", "Method has the right QName") - harness.check(member.identifier.name, "basic", "Method has the right name") - harness.check(member.hasOverloads(), True, "Method has overloads") - - signatures = member.signatures() - harness.check(len(signatures), 2, "Method should have 2 signatures") - - (retval, argumentSet) = signatures[0] - - harness.check(str(retval), "Void", "Expect a void retval") - harness.check(len(argumentSet), 0, "Expect an empty argument set") - - (retval, argumentSet) = signatures[1] - harness.check(str(retval), "Void", "Expect a void retval") - harness.check(len(argumentSet), 1, "Expect an argument set with one argument") - - argument = argumentSet[0] - harness.ok(isinstance(argument, WebIDL.IDLArgument), - "Should be an IDLArgument") - harness.check(argument.identifier.QName(), "::TestOverloads::basic::arg1", "Argument has the right QName") - harness.check(argument.identifier.name, "arg1", "Argument has the right name") - harness.check(str(argument.type), "Long", "Argument has the right type") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_sanity.py b/src/components/script/dom/bindings/codegen/parser/tests/test_sanity.py deleted file mode 100644 index d3184c00731..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_sanity.py +++ /dev/null @@ -1,7 +0,0 @@ -def WebIDLTest(parser, harness): - parser.parse("") - parser.finish() - harness.ok(True, "Parsing nothing doesn't throw.") - parser.parse("interface Foo {};") - parser.finish() - harness.ok(True, "Parsing a silly interface doesn't throw.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_special_method_signature_mismatch.py b/src/components/script/dom/bindings/codegen/parser/tests/test_special_method_signature_mismatch.py deleted file mode 100644 index 5ea1743d36a..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_special_method_signature_mismatch.py +++ /dev/null @@ -1,294 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch1 { - getter long long foo(long index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch2 { - getter void foo(unsigned long index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch3 { - getter boolean foo(unsigned long index, boolean extraArg); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch4 { - getter boolean foo(unsigned long... index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch5 { - getter boolean foo(optional unsigned long index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch6 { - getter boolean foo(); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch7 { - deleter long long foo(long index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch9 { - deleter boolean foo(unsigned long index, boolean extraArg); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch10 { - deleter boolean foo(unsigned long... index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch11 { - deleter boolean foo(optional unsigned long index); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch12 { - deleter boolean foo(); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch13 { - setter long long foo(long index, long long value); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch15 { - setter boolean foo(unsigned long index, boolean value, long long extraArg); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch16 { - setter boolean foo(unsigned long index, boolean... value); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch17 { - setter boolean foo(unsigned long index, optional boolean value); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch18 { - setter boolean foo(); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch20 { - creator long long foo(long index, long long value); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch22 { - creator boolean foo(unsigned long index, boolean value, long long extraArg); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch23 { - creator boolean foo(unsigned long index, boolean... value); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch24 { - creator boolean foo(unsigned long index, optional boolean value); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodSignatureMismatch25 { - creator boolean foo(); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_special_methods.py b/src/components/script/dom/bindings/codegen/parser/tests/test_special_methods.py deleted file mode 100644 index 695cfe4f250..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_special_methods.py +++ /dev/null @@ -1,73 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - interface SpecialMethods { - getter long long (unsigned long index); - setter long long (unsigned long index, long long value); - creator long long (unsigned long index, long long value); - deleter long long (unsigned long index); - getter boolean (DOMString name); - setter boolean (DOMString name, boolean value); - creator boolean (DOMString name, boolean value); - deleter boolean (DOMString name); - }; - - interface SpecialMethodsCombination { - getter deleter long long (unsigned long index); - setter creator long long (unsigned long index, long long value); - getter deleter boolean (DOMString name); - setter creator boolean (DOMString name, boolean value); - }; - """) - - results = parser.finish() - - def checkMethod(method, QName, name, - static=False, getter=False, setter=False, creator=False, - deleter=False, legacycaller=False, stringifier=False): - harness.ok(isinstance(method, WebIDL.IDLMethod), - "Should be an IDLMethod") - harness.check(method.identifier.QName(), QName, "Method has the right QName") - harness.check(method.identifier.name, name, "Method has the right name") - harness.check(method.isStatic(), static, "Method has the correct static value") - harness.check(method.isGetter(), getter, "Method has the correct getter value") - harness.check(method.isSetter(), setter, "Method has the correct setter value") - harness.check(method.isCreator(), creator, "Method has the correct creator value") - harness.check(method.isDeleter(), deleter, "Method has the correct deleter value") - harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value") - harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value") - - harness.check(len(results), 2, "Expect 2 interfaces") - - iface = results[0] - harness.check(len(iface.members), 8, "Expect 8 members") - - checkMethod(iface.members[0], "::SpecialMethods::__indexedgetter", "__indexedgetter", - getter=True) - checkMethod(iface.members[1], "::SpecialMethods::__indexedsetter", "__indexedsetter", - setter=True) - checkMethod(iface.members[2], "::SpecialMethods::__indexedcreator", "__indexedcreator", - creator=True) - checkMethod(iface.members[3], "::SpecialMethods::__indexeddeleter", "__indexeddeleter", - deleter=True) - checkMethod(iface.members[4], "::SpecialMethods::__namedgetter", "__namedgetter", - getter=True) - checkMethod(iface.members[5], "::SpecialMethods::__namedsetter", "__namedsetter", - setter=True) - checkMethod(iface.members[6], "::SpecialMethods::__namedcreator", "__namedcreator", - creator=True) - checkMethod(iface.members[7], "::SpecialMethods::__nameddeleter", "__nameddeleter", - deleter=True) - - iface = results[1] - harness.check(len(iface.members), 4, "Expect 4 members") - - checkMethod(iface.members[0], "::SpecialMethodsCombination::__indexedgetterdeleter", - "__indexedgetterdeleter", getter=True, deleter=True) - checkMethod(iface.members[1], "::SpecialMethodsCombination::__indexedsettercreator", - "__indexedsettercreator", setter=True, creator=True) - checkMethod(iface.members[2], "::SpecialMethodsCombination::__namedgetterdeleter", - "__namedgetterdeleter", getter=True, deleter=True) - checkMethod(iface.members[3], "::SpecialMethodsCombination::__namedsettercreator", - "__namedsettercreator", setter=True, creator=True) diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_special_methods_uniqueness.py b/src/components/script/dom/bindings/codegen/parser/tests/test_special_methods_uniqueness.py deleted file mode 100644 index 42e2c5bb71b..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_special_methods_uniqueness.py +++ /dev/null @@ -1,62 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface SpecialMethodUniqueness1 { - getter deleter boolean (DOMString name); - getter boolean (DOMString name); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodUniqueness1 { - deleter boolean (DOMString name); - getter deleter boolean (DOMString name); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodUniqueness1 { - setter creator boolean (DOMString name); - creator boolean (DOMString name); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - parser.parse(""" - interface SpecialMethodUniqueness1 { - setter boolean (DOMString name); - creator setter boolean (DOMString name); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_treatNonCallableAsNull.py b/src/components/script/dom/bindings/codegen/parser/tests/test_treatNonCallableAsNull.py deleted file mode 100644 index 3d0e5ca479f..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_treatNonCallableAsNull.py +++ /dev/null @@ -1,56 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - callback Function = any(any... arguments); - - interface TestTreatNonCallableAsNull1 { - [TreatNonCallableAsNull] attribute Function? onfoo; - attribute Function? onbar; - }; - """) - - results = parser.finish() - - iface = results[1] - attr = iface.members[0] - harness.check(attr.type.treatNonCallableAsNull(), True, "Got the expected value") - attr = iface.members[1] - harness.check(attr.type.treatNonCallableAsNull(), False, "Got the expected value") - - parser = parser.reset() - - threw = False - try: - parser.parse(""" - callback Function = any(any... arguments); - - interface TestTreatNonCallableAsNull2 { - [TreatNonCallableAsNull] attribute Function onfoo; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - parser = parser.reset() - - threw = False - try: - parser.parse(""" - callback Function = any(any... arguments); - - [TreatNonCallableAsNull] - interface TestTreatNonCallableAsNull3 { - attribute Function onfoo; - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_typedef.py b/src/components/script/dom/bindings/codegen/parser/tests/test_typedef.py deleted file mode 100644 index 9d2f3b3c2ce..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_typedef.py +++ /dev/null @@ -1,76 +0,0 @@ -def WebIDLTest(parser, harness): - parser.parse(""" - typedef long mylong; - typedef long? mynullablelong; - interface Foo { - const mylong X = 5; - const mynullablelong Y = 7; - const mynullablelong Z = null; - void foo(mylong arg); - }; - """) - - results = parser.finish() - - harness.check(results[2].members[1].type.name, "Long", - "Should expand typedefs") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - typedef long? mynullablelong; - interface Foo { - void foo(mynullablelong? Y); - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown on nullable inside nullable arg.") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - typedef long? mynullablelong; - interface Foo { - const mynullablelong? X = 5; - }; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown on nullable inside nullable const.") - - parser = parser.reset() - threw = False - try: - parser.parse(""" - interface Foo { - const mynullablelong? X = 5; - }; - typedef long? mynullablelong; - """) - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Should have thrown on nullable inside nullable const typedef " - "after interface.") - - parser = parser.reset() - parser.parse(""" - interface Foo { - const mylong X = 5; - }; - typedef long mylong; - """) - - results = parser.finish() - - harness.check(results[0].members[0].type.name, "Long", - "Should expand typedefs that come before interface") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_union.py b/src/components/script/dom/bindings/codegen/parser/tests/test_union.py deleted file mode 100644 index 68c2bcade8c..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_union.py +++ /dev/null @@ -1,169 +0,0 @@ -import WebIDL -import itertools -import string - -# We'd like to use itertools.chain but it's 2.6 or higher. -def chain(*iterables): - # chain('ABC', 'DEF') --> A B C D E F - for it in iterables: - for element in it: - yield element - -# We'd like to use itertools.combinations but it's 2.6 or higher. -def combinations(iterable, r): - # combinations('ABCD', 2) --> AB AC AD BC BD CD - # combinations(range(4), 3) --> 012 013 023 123 - pool = tuple(iterable) - n = len(pool) - if r > n: - return - indices = range(r) - yield tuple(pool[i] for i in indices) - while True: - for i in reversed(range(r)): - if indices[i] != i + n - r: - break - else: - return - indices[i] += 1 - for j in range(i+1, r): - indices[j] = indices[j-1] + 1 - yield tuple(pool[i] for i in indices) - -# We'd like to use itertools.combinations_with_replacement but it's 2.7 or -# higher. -def combinations_with_replacement(iterable, r): - # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC - pool = tuple(iterable) - n = len(pool) - if not n and r: - return - indices = [0] * r - yield tuple(pool[i] for i in indices) - while True: - for i in reversed(range(r)): - if indices[i] != n - 1: - break - else: - return - indices[i:] = [indices[i] + 1] * (r - i) - yield tuple(pool[i] for i in indices) - -def WebIDLTest(parser, harness): - types = ["float", - "double", - "short", - "unsigned short", - "long", - "unsigned long", - "long long", - "unsigned long long", - "boolean", - "byte", - "octet", - "DOMString", - #"sequence<float>", - "object", - "ArrayBuffer", - #"Date", - "TestInterface1", - "TestInterface2"] - - testPre = """ - interface TestInterface1 { - }; - interface TestInterface2 { - }; - """ - - interface = testPre + """ - interface PrepareForTest { - """ - for (i, type) in enumerate(types): - interface += string.Template(""" - readonly attribute ${type} attr${i}; - """).substitute(i=i, type=type) - interface += """ - }; - """ - - parser.parse(interface) - results = parser.finish() - - iface = results[2] - - parser = parser.reset() - - def typesAreDistinguishable(t): - return all(u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2)) - def typesAreNotDistinguishable(t): - return any(not u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2)) - def unionTypeName(t): - if len(t) > 2: - t[0:2] = [unionTypeName(t[0:2])] - return "(" + " or ".join(t) + ")" - - # typeCombinations is an iterable of tuples containing the name of the type - # as a string and the parsed IDL type. - def unionTypes(typeCombinations, predicate): - for c in typeCombinations: - if predicate(t[1] for t in c): - yield unionTypeName([t[0] for t in c]) - - # We limit invalid union types with a union member type to the subset of 3 - # types with one invalid combination. - # typeCombinations is an iterable of tuples containing the name of the type - # as a string and the parsed IDL type. - def invalidUnionWithUnion(typeCombinations): - for c in typeCombinations: - if (typesAreNotDistinguishable((c[0][1], c[1][1])) and - typesAreDistinguishable((c[1][1], c[2][1])) and - typesAreDistinguishable((c[0][1], c[2][1]))): - yield unionTypeName([t[0] for t in c]) - - # Create a list of tuples containing the name of the type as a string and - # the parsed IDL type. - types = zip(types, (a.type for a in iface.members)) - - validUnionTypes = chain(unionTypes(combinations(types, 2), typesAreDistinguishable), - unionTypes(combinations(types, 3), typesAreDistinguishable)) - invalidUnionTypes = chain(unionTypes(combinations_with_replacement(types, 2), typesAreNotDistinguishable), - invalidUnionWithUnion(combinations(types, 3))) - interface = testPre + """ - interface TestUnion { - """ - for (i, type) in enumerate(validUnionTypes): - interface += string.Template(""" - void method${i}(${type} arg); - ${type} returnMethod${i}(); - attribute ${type} attr${i}; - void arrayMethod${i}(${type}[] arg); - ${type}[] arrayReturnMethod${i}(); - attribute ${type}[] arrayAttr${i}; - void optionalMethod${i}(${type}? arg); - """).substitute(i=i, type=type) - interface += """ - }; - """ - parser.parse(interface) - results = parser.finish() - - parser = parser.reset() - - for invalid in invalidUnionTypes: - interface = testPre + string.Template(""" - interface TestUnion { - void method(${type} arg); - }; - """).substitute(type=invalid) - - threw = False - try: - parser.parse(interface) - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - parser = parser.reset() diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_union_any.py b/src/components/script/dom/bindings/codegen/parser/tests/test_union_any.py deleted file mode 100644 index e34cadab470..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_union_any.py +++ /dev/null @@ -1,14 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface AnyNotInUnion { - void foo((any or DOMString) arg); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_union_nullable.py b/src/components/script/dom/bindings/codegen/parser/tests/test_union_nullable.py deleted file mode 100644 index 08430a94a2e..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_union_nullable.py +++ /dev/null @@ -1,53 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - parser.parse(""" - interface OneNullableInUnion { - void foo((object? or DOMString?) arg); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "Two nullable member types of a union should have thrown.") - - parser.reset() - threw = False - - try: - parser.parse(""" - interface NullableInNullableUnion { - void foo((object? or DOMString)? arg); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "A nullable union type with a nullable member type should have " - "thrown.") - - parser.reset() - threw = False - - try: - parser.parse(""" - interface NullableInUnionNullableUnionHelper { - }; - interface NullableInUnionNullableUnion { - void foo(((object? or DOMString) or NullableInUnionNullableUnionHelper)? arg); - }; - """) - - results = parser.finish() - except: - threw = True - - harness.ok(threw, - "A nullable union type with a nullable member type should have " - "thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_variadic_callback.py b/src/components/script/dom/bindings/codegen/parser/tests/test_variadic_callback.py deleted file mode 100644 index d9a78db2043..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_variadic_callback.py +++ /dev/null @@ -1,10 +0,0 @@ -import WebIDL - -def WebIDLTest(parser, harness): - parser.parse(""" - callback TestVariadicCallback = any(any... arguments); - """) - - results = parser.finish() - - harness.ok(True, "TestVariadicCallback callback parsed without error.") diff --git a/src/components/script/dom/bindings/codegen/parser/tests/test_variadic_constraints.py b/src/components/script/dom/bindings/codegen/parser/tests/test_variadic_constraints.py deleted file mode 100644 index 9cba22c5842..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/tests/test_variadic_constraints.py +++ /dev/null @@ -1,39 +0,0 @@ -def WebIDLTest(parser, harness): - threw = False - try: - results = parser.parse(""" - interface VariadicConstraints1 { - void foo(byte... arg1, byte arg2); - }; - """) - - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - results = parser.parse(""" - interface VariadicConstraints2 { - void foo(byte... arg1, optional byte arg2); - }; - """) - - except: - threw = True - - harness.ok(threw, "Should have thrown.") - - threw = False - try: - results = parser.parse(""" - interface VariadicConstraints3 { - void foo(optional byte... arg1); - }; - """) - - except: - threw = True - - harness.ok(threw, "Should have thrown.") diff --git a/src/components/script/dom/bindings/codegen/parser/update.sh b/src/components/script/dom/bindings/codegen/parser/update.sh deleted file mode 100755 index 5dd513812e1..00000000000 --- a/src/components/script/dom/bindings/codegen/parser/update.sh +++ /dev/null @@ -1,3 +0,0 @@ -wget https://mxr.mozilla.org/mozilla-central/source/dom/bindings/parser/WebIDL.py?raw=1 -O WebIDL.py -patch < external.patch -patch < module.patch diff --git a/src/components/script/dom/bindings/codegen/ply/COPYING b/src/components/script/dom/bindings/codegen/ply/COPYING deleted file mode 100644 index 3b107de4508..00000000000 --- a/src/components/script/dom/bindings/codegen/ply/COPYING +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (C) 2001-2009, -David M. Beazley (Dabeaz LLC) -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the David Beazley or Dabeaz LLC may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/components/script/dom/bindings/codegen/ply/README b/src/components/script/dom/bindings/codegen/ply/README deleted file mode 100644 index 2459c490197..00000000000 --- a/src/components/script/dom/bindings/codegen/ply/README +++ /dev/null @@ -1,9 +0,0 @@ -David Beazley's PLY (Python Lex-Yacc) -http://www.dabeaz.com/ply/ - -Licensed under BSD. - -This directory contains just the code and license from PLY version 3.3; -the full distribution (see the URL) also contains examples, tests, -documentation, and a longer README. - diff --git a/src/components/script/dom/bindings/codegen/ply/ply/__init__.py b/src/components/script/dom/bindings/codegen/ply/ply/__init__.py deleted file mode 100644 index 853a985542b..00000000000 --- a/src/components/script/dom/bindings/codegen/ply/ply/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# PLY package -# Author: David Beazley (dave@dabeaz.com) - -__all__ = ['lex','yacc'] diff --git a/src/components/script/dom/bindings/codegen/ply/ply/lex.py b/src/components/script/dom/bindings/codegen/ply/ply/lex.py deleted file mode 100644 index 267ec100fc2..00000000000 --- a/src/components/script/dom/bindings/codegen/ply/ply/lex.py +++ /dev/null @@ -1,1058 +0,0 @@ -# ----------------------------------------------------------------------------- -# ply: lex.py -# -# Copyright (C) 2001-2009, -# David M. Beazley (Dabeaz LLC) -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the David Beazley or Dabeaz LLC may be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# ----------------------------------------------------------------------------- - -__version__ = "3.3" -__tabversion__ = "3.2" # Version of table file used - -import re, sys, types, copy, os - -# This tuple contains known string types -try: - # Python 2.6 - StringTypes = (types.StringType, types.UnicodeType) -except AttributeError: - # Python 3.0 - StringTypes = (str, bytes) - -# Extract the code attribute of a function. Different implementations -# are for Python 2/3 compatibility. - -if sys.version_info[0] < 3: - def func_code(f): - return f.func_code -else: - def func_code(f): - return f.__code__ - -# This regular expression is used to match valid token names -_is_identifier = re.compile(r'^[a-zA-Z0-9_]+$') - -# Exception thrown when invalid token encountered and no default error -# handler is defined. - -class LexError(Exception): - def __init__(self,message,s): - self.args = (message,) - self.text = s - -# Token class. This class is used to represent the tokens produced. -class LexToken(object): - def __str__(self): - return "LexToken(%s,%r,%d,%d)" % (self.type,self.value,self.lineno,self.lexpos) - def __repr__(self): - return str(self) - -# This object is a stand-in for a logging object created by the -# logging module. - -class PlyLogger(object): - def __init__(self,f): - self.f = f - def critical(self,msg,*args,**kwargs): - self.f.write((msg % args) + "\n") - - def warning(self,msg,*args,**kwargs): - self.f.write("WARNING: "+ (msg % args) + "\n") - - def error(self,msg,*args,**kwargs): - self.f.write("ERROR: " + (msg % args) + "\n") - - info = critical - debug = critical - -# Null logger is used when no output is generated. Does nothing. -class NullLogger(object): - def __getattribute__(self,name): - return self - def __call__(self,*args,**kwargs): - return self - -# ----------------------------------------------------------------------------- -# === Lexing Engine === -# -# The following Lexer class implements the lexer runtime. There are only -# a few public methods and attributes: -# -# input() - Store a new string in the lexer -# token() - Get the next token -# clone() - Clone the lexer -# -# lineno - Current line number -# lexpos - Current position in the input string -# ----------------------------------------------------------------------------- - -class Lexer: - def __init__(self): - self.lexre = None # Master regular expression. This is a list of - # tuples (re,findex) where re is a compiled - # regular expression and findex is a list - # mapping regex group numbers to rules - self.lexretext = None # Current regular expression strings - self.lexstatere = {} # Dictionary mapping lexer states to master regexs - self.lexstateretext = {} # Dictionary mapping lexer states to regex strings - self.lexstaterenames = {} # Dictionary mapping lexer states to symbol names - self.lexstate = "INITIAL" # Current lexer state - self.lexstatestack = [] # Stack of lexer states - self.lexstateinfo = None # State information - self.lexstateignore = {} # Dictionary of ignored characters for each state - self.lexstateerrorf = {} # Dictionary of error functions for each state - self.lexreflags = 0 # Optional re compile flags - self.lexdata = None # Actual input data (as a string) - self.lexpos = 0 # Current position in input text - self.lexlen = 0 # Length of the input text - self.lexerrorf = None # Error rule (if any) - self.lextokens = None # List of valid tokens - self.lexignore = "" # Ignored characters - self.lexliterals = "" # Literal characters that can be passed through - self.lexmodule = None # Module - self.lineno = 1 # Current line number - self.lexoptimize = 0 # Optimized mode - - def clone(self,object=None): - c = copy.copy(self) - - # If the object parameter has been supplied, it means we are attaching the - # lexer to a new object. In this case, we have to rebind all methods in - # the lexstatere and lexstateerrorf tables. - - if object: - newtab = { } - for key, ritem in self.lexstatere.items(): - newre = [] - for cre, findex in ritem: - newfindex = [] - for f in findex: - if not f or not f[0]: - newfindex.append(f) - continue - newfindex.append((getattr(object,f[0].__name__),f[1])) - newre.append((cre,newfindex)) - newtab[key] = newre - c.lexstatere = newtab - c.lexstateerrorf = { } - for key, ef in self.lexstateerrorf.items(): - c.lexstateerrorf[key] = getattr(object,ef.__name__) - c.lexmodule = object - return c - - # ------------------------------------------------------------ - # writetab() - Write lexer information to a table file - # ------------------------------------------------------------ - def writetab(self,tabfile,outputdir=""): - if isinstance(tabfile,types.ModuleType): - return - basetabfilename = tabfile.split(".")[-1] - filename = os.path.join(outputdir,basetabfilename)+".py" - tf = open(filename,"w") - tf.write("# %s.py. This file automatically created by PLY (version %s). Don't edit!\n" % (tabfile,__version__)) - tf.write("_tabversion = %s\n" % repr(__version__)) - tf.write("_lextokens = %s\n" % repr(self.lextokens)) - tf.write("_lexreflags = %s\n" % repr(self.lexreflags)) - tf.write("_lexliterals = %s\n" % repr(self.lexliterals)) - tf.write("_lexstateinfo = %s\n" % repr(self.lexstateinfo)) - - tabre = { } - # Collect all functions in the initial state - initial = self.lexstatere["INITIAL"] - initialfuncs = [] - for part in initial: - for f in part[1]: - if f and f[0]: - initialfuncs.append(f) - - for key, lre in self.lexstatere.items(): - titem = [] - for i in range(len(lre)): - titem.append((self.lexstateretext[key][i],_funcs_to_names(lre[i][1],self.lexstaterenames[key][i]))) - tabre[key] = titem - - tf.write("_lexstatere = %s\n" % repr(tabre)) - tf.write("_lexstateignore = %s\n" % repr(self.lexstateignore)) - - taberr = { } - for key, ef in self.lexstateerrorf.items(): - if ef: - taberr[key] = ef.__name__ - else: - taberr[key] = None - tf.write("_lexstateerrorf = %s\n" % repr(taberr)) - tf.close() - - # ------------------------------------------------------------ - # readtab() - Read lexer information from a tab file - # ------------------------------------------------------------ - def readtab(self,tabfile,fdict): - if isinstance(tabfile,types.ModuleType): - lextab = tabfile - else: - if sys.version_info[0] < 3: - exec("import %s as lextab" % tabfile) - else: - env = { } - exec("import %s as lextab" % tabfile, env,env) - lextab = env['lextab'] - - if getattr(lextab,"_tabversion","0.0") != __version__: - raise ImportError("Inconsistent PLY version") - - self.lextokens = lextab._lextokens - self.lexreflags = lextab._lexreflags - self.lexliterals = lextab._lexliterals - self.lexstateinfo = lextab._lexstateinfo - self.lexstateignore = lextab._lexstateignore - self.lexstatere = { } - self.lexstateretext = { } - for key,lre in lextab._lexstatere.items(): - titem = [] - txtitem = [] - for i in range(len(lre)): - titem.append((re.compile(lre[i][0],lextab._lexreflags | re.VERBOSE),_names_to_funcs(lre[i][1],fdict))) - txtitem.append(lre[i][0]) - self.lexstatere[key] = titem - self.lexstateretext[key] = txtitem - self.lexstateerrorf = { } - for key,ef in lextab._lexstateerrorf.items(): - self.lexstateerrorf[key] = fdict[ef] - self.begin('INITIAL') - - # ------------------------------------------------------------ - # input() - Push a new string into the lexer - # ------------------------------------------------------------ - def input(self,s): - # Pull off the first character to see if s looks like a string - c = s[:1] - if not isinstance(c,StringTypes): - raise ValueError("Expected a string") - self.lexdata = s - self.lexpos = 0 - self.lexlen = len(s) - - # ------------------------------------------------------------ - # begin() - Changes the lexing state - # ------------------------------------------------------------ - def begin(self,state): - if not state in self.lexstatere: - raise ValueError("Undefined state") - self.lexre = self.lexstatere[state] - self.lexretext = self.lexstateretext[state] - self.lexignore = self.lexstateignore.get(state,"") - self.lexerrorf = self.lexstateerrorf.get(state,None) - self.lexstate = state - - # ------------------------------------------------------------ - # push_state() - Changes the lexing state and saves old on stack - # ------------------------------------------------------------ - def push_state(self,state): - self.lexstatestack.append(self.lexstate) - self.begin(state) - - # ------------------------------------------------------------ - # pop_state() - Restores the previous state - # ------------------------------------------------------------ - def pop_state(self): - self.begin(self.lexstatestack.pop()) - - # ------------------------------------------------------------ - # current_state() - Returns the current lexing state - # ------------------------------------------------------------ - def current_state(self): - return self.lexstate - - # ------------------------------------------------------------ - # skip() - Skip ahead n characters - # ------------------------------------------------------------ - def skip(self,n): - self.lexpos += n - - # ------------------------------------------------------------ - # opttoken() - Return the next token from the Lexer - # - # Note: This function has been carefully implemented to be as fast - # as possible. Don't make changes unless you really know what - # you are doing - # ------------------------------------------------------------ - def token(self): - # Make local copies of frequently referenced attributes - lexpos = self.lexpos - lexlen = self.lexlen - lexignore = self.lexignore - lexdata = self.lexdata - - while lexpos < lexlen: - # This code provides some short-circuit code for whitespace, tabs, and other ignored characters - if lexdata[lexpos] in lexignore: - lexpos += 1 - continue - - # Look for a regular expression match - for lexre,lexindexfunc in self.lexre: - m = lexre.match(lexdata,lexpos) - if not m: continue - - # Create a token for return - tok = LexToken() - tok.value = m.group() - tok.lineno = self.lineno - tok.lexpos = lexpos - - i = m.lastindex - func,tok.type = lexindexfunc[i] - - if not func: - # If no token type was set, it's an ignored token - if tok.type: - self.lexpos = m.end() - return tok - else: - lexpos = m.end() - break - - lexpos = m.end() - - # If token is processed by a function, call it - - tok.lexer = self # Set additional attributes useful in token rules - self.lexmatch = m - self.lexpos = lexpos - - newtok = func(tok) - - # Every function must return a token, if nothing, we just move to next token - if not newtok: - lexpos = self.lexpos # This is here in case user has updated lexpos. - lexignore = self.lexignore # This is here in case there was a state change - break - - # Verify type of the token. If not in the token map, raise an error - if not self.lexoptimize: - if not newtok.type in self.lextokens: - raise LexError("%s:%d: Rule '%s' returned an unknown token type '%s'" % ( - func_code(func).co_filename, func_code(func).co_firstlineno, - func.__name__, newtok.type),lexdata[lexpos:]) - - return newtok - else: - # No match, see if in literals - if lexdata[lexpos] in self.lexliterals: - tok = LexToken() - tok.value = lexdata[lexpos] - tok.lineno = self.lineno - tok.type = tok.value - tok.lexpos = lexpos - self.lexpos = lexpos + 1 - return tok - - # No match. Call t_error() if defined. - if self.lexerrorf: - tok = LexToken() - tok.value = self.lexdata[lexpos:] - tok.lineno = self.lineno - tok.type = "error" - tok.lexer = self - tok.lexpos = lexpos - self.lexpos = lexpos - newtok = self.lexerrorf(tok) - if lexpos == self.lexpos: - # Error method didn't change text position at all. This is an error. - raise LexError("Scanning error. Illegal character '%s'" % (lexdata[lexpos]), lexdata[lexpos:]) - lexpos = self.lexpos - if not newtok: continue - return newtok - - self.lexpos = lexpos - raise LexError("Illegal character '%s' at index %d" % (lexdata[lexpos],lexpos), lexdata[lexpos:]) - - self.lexpos = lexpos + 1 - if self.lexdata is None: - raise RuntimeError("No input string given with input()") - return None - - # Iterator interface - def __iter__(self): - return self - - def next(self): - t = self.token() - if t is None: - raise StopIteration - return t - - __next__ = next - -# ----------------------------------------------------------------------------- -# ==== Lex Builder === -# -# The functions and classes below are used to collect lexing information -# and build a Lexer object from it. -# ----------------------------------------------------------------------------- - -# ----------------------------------------------------------------------------- -# get_caller_module_dict() -# -# This function returns a dictionary containing all of the symbols defined within -# a caller further down the call stack. This is used to get the environment -# associated with the yacc() call if none was provided. -# ----------------------------------------------------------------------------- - -def get_caller_module_dict(levels): - try: - raise RuntimeError - except RuntimeError: - e,b,t = sys.exc_info() - f = t.tb_frame - while levels > 0: - f = f.f_back - levels -= 1 - ldict = f.f_globals.copy() - if f.f_globals != f.f_locals: - ldict.update(f.f_locals) - - return ldict - -# ----------------------------------------------------------------------------- -# _funcs_to_names() -# -# Given a list of regular expression functions, this converts it to a list -# suitable for output to a table file -# ----------------------------------------------------------------------------- - -def _funcs_to_names(funclist,namelist): - result = [] - for f,name in zip(funclist,namelist): - if f and f[0]: - result.append((name, f[1])) - else: - result.append(f) - return result - -# ----------------------------------------------------------------------------- -# _names_to_funcs() -# -# Given a list of regular expression function names, this converts it back to -# functions. -# ----------------------------------------------------------------------------- - -def _names_to_funcs(namelist,fdict): - result = [] - for n in namelist: - if n and n[0]: - result.append((fdict[n[0]],n[1])) - else: - result.append(n) - return result - -# ----------------------------------------------------------------------------- -# _form_master_re() -# -# This function takes a list of all of the regex components and attempts to -# form the master regular expression. Given limitations in the Python re -# module, it may be necessary to break the master regex into separate expressions. -# ----------------------------------------------------------------------------- - -def _form_master_re(relist,reflags,ldict,toknames): - if not relist: return [] - regex = "|".join(relist) - try: - lexre = re.compile(regex,re.VERBOSE | reflags) - - # Build the index to function map for the matching engine - lexindexfunc = [ None ] * (max(lexre.groupindex.values())+1) - lexindexnames = lexindexfunc[:] - - for f,i in lexre.groupindex.items(): - handle = ldict.get(f,None) - if type(handle) in (types.FunctionType, types.MethodType): - lexindexfunc[i] = (handle,toknames[f]) - lexindexnames[i] = f - elif handle is not None: - lexindexnames[i] = f - if f.find("ignore_") > 0: - lexindexfunc[i] = (None,None) - else: - lexindexfunc[i] = (None, toknames[f]) - - return [(lexre,lexindexfunc)],[regex],[lexindexnames] - except Exception: - m = int(len(relist)/2) - if m == 0: m = 1 - llist, lre, lnames = _form_master_re(relist[:m],reflags,ldict,toknames) - rlist, rre, rnames = _form_master_re(relist[m:],reflags,ldict,toknames) - return llist+rlist, lre+rre, lnames+rnames - -# ----------------------------------------------------------------------------- -# def _statetoken(s,names) -# -# Given a declaration name s of the form "t_" and a dictionary whose keys are -# state names, this function returns a tuple (states,tokenname) where states -# is a tuple of state names and tokenname is the name of the token. For example, -# calling this with s = "t_foo_bar_SPAM" might return (('foo','bar'),'SPAM') -# ----------------------------------------------------------------------------- - -def _statetoken(s,names): - nonstate = 1 - parts = s.split("_") - for i in range(1,len(parts)): - if not parts[i] in names and parts[i] != 'ANY': break - if i > 1: - states = tuple(parts[1:i]) - else: - states = ('INITIAL',) - - if 'ANY' in states: - states = tuple(names) - - tokenname = "_".join(parts[i:]) - return (states,tokenname) - - -# ----------------------------------------------------------------------------- -# LexerReflect() -# -# This class represents information needed to build a lexer as extracted from a -# user's input file. -# ----------------------------------------------------------------------------- -class LexerReflect(object): - def __init__(self,ldict,log=None,reflags=0): - self.ldict = ldict - self.error_func = None - self.tokens = [] - self.reflags = reflags - self.stateinfo = { 'INITIAL' : 'inclusive'} - self.files = {} - self.error = 0 - - if log is None: - self.log = PlyLogger(sys.stderr) - else: - self.log = log - - # Get all of the basic information - def get_all(self): - self.get_tokens() - self.get_literals() - self.get_states() - self.get_rules() - - # Validate all of the information - def validate_all(self): - self.validate_tokens() - self.validate_literals() - self.validate_rules() - return self.error - - # Get the tokens map - def get_tokens(self): - tokens = self.ldict.get("tokens",None) - if not tokens: - self.log.error("No token list is defined") - self.error = 1 - return - - if not isinstance(tokens,(list, tuple)): - self.log.error("tokens must be a list or tuple") - self.error = 1 - return - - if not tokens: - self.log.error("tokens is empty") - self.error = 1 - return - - self.tokens = tokens - - # Validate the tokens - def validate_tokens(self): - terminals = {} - for n in self.tokens: - if not _is_identifier.match(n): - self.log.error("Bad token name '%s'",n) - self.error = 1 - if n in terminals: - self.log.warning("Token '%s' multiply defined", n) - terminals[n] = 1 - - # Get the literals specifier - def get_literals(self): - self.literals = self.ldict.get("literals","") - - # Validate literals - def validate_literals(self): - try: - for c in self.literals: - if not isinstance(c,StringTypes) or len(c) > 1: - self.log.error("Invalid literal %s. Must be a single character", repr(c)) - self.error = 1 - continue - - except TypeError: - self.log.error("Invalid literals specification. literals must be a sequence of characters") - self.error = 1 - - def get_states(self): - self.states = self.ldict.get("states",None) - # Build statemap - if self.states: - if not isinstance(self.states,(tuple,list)): - self.log.error("states must be defined as a tuple or list") - self.error = 1 - else: - for s in self.states: - if not isinstance(s,tuple) or len(s) != 2: - self.log.error("Invalid state specifier %s. Must be a tuple (statename,'exclusive|inclusive')",repr(s)) - self.error = 1 - continue - name, statetype = s - if not isinstance(name,StringTypes): - self.log.error("State name %s must be a string", repr(name)) - self.error = 1 - continue - if not (statetype == 'inclusive' or statetype == 'exclusive'): - self.log.error("State type for state %s must be 'inclusive' or 'exclusive'",name) - self.error = 1 - continue - if name in self.stateinfo: - self.log.error("State '%s' already defined",name) - self.error = 1 - continue - self.stateinfo[name] = statetype - - # Get all of the symbols with a t_ prefix and sort them into various - # categories (functions, strings, error functions, and ignore characters) - - def get_rules(self): - tsymbols = [f for f in self.ldict if f[:2] == 't_' ] - - # Now build up a list of functions and a list of strings - - self.toknames = { } # Mapping of symbols to token names - self.funcsym = { } # Symbols defined as functions - self.strsym = { } # Symbols defined as strings - self.ignore = { } # Ignore strings by state - self.errorf = { } # Error functions by state - - for s in self.stateinfo: - self.funcsym[s] = [] - self.strsym[s] = [] - - if len(tsymbols) == 0: - self.log.error("No rules of the form t_rulename are defined") - self.error = 1 - return - - for f in tsymbols: - t = self.ldict[f] - states, tokname = _statetoken(f,self.stateinfo) - self.toknames[f] = tokname - - if hasattr(t,"__call__"): - if tokname == 'error': - for s in states: - self.errorf[s] = t - elif tokname == 'ignore': - line = func_code(t).co_firstlineno - file = func_code(t).co_filename - self.log.error("%s:%d: Rule '%s' must be defined as a string",file,line,t.__name__) - self.error = 1 - else: - for s in states: - self.funcsym[s].append((f,t)) - elif isinstance(t, StringTypes): - if tokname == 'ignore': - for s in states: - self.ignore[s] = t - if "\\" in t: - self.log.warning("%s contains a literal backslash '\\'",f) - - elif tokname == 'error': - self.log.error("Rule '%s' must be defined as a function", f) - self.error = 1 - else: - for s in states: - self.strsym[s].append((f,t)) - else: - self.log.error("%s not defined as a function or string", f) - self.error = 1 - - # Sort the functions by line number - for f in self.funcsym.values(): - if sys.version_info[0] < 3: - f.sort(lambda x,y: cmp(func_code(x[1]).co_firstlineno,func_code(y[1]).co_firstlineno)) - else: - # Python 3.0 - f.sort(key=lambda x: func_code(x[1]).co_firstlineno) - - # Sort the strings by regular expression length - for s in self.strsym.values(): - if sys.version_info[0] < 3: - s.sort(lambda x,y: (len(x[1]) < len(y[1])) - (len(x[1]) > len(y[1]))) - else: - # Python 3.0 - s.sort(key=lambda x: len(x[1]),reverse=True) - - # Validate all of the t_rules collected - def validate_rules(self): - for state in self.stateinfo: - # Validate all rules defined by functions - - - - for fname, f in self.funcsym[state]: - line = func_code(f).co_firstlineno - file = func_code(f).co_filename - self.files[file] = 1 - - tokname = self.toknames[fname] - if isinstance(f, types.MethodType): - reqargs = 2 - else: - reqargs = 1 - nargs = func_code(f).co_argcount - if nargs > reqargs: - self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,f.__name__) - self.error = 1 - continue - - if nargs < reqargs: - self.log.error("%s:%d: Rule '%s' requires an argument", file,line,f.__name__) - self.error = 1 - continue - - if not f.__doc__: - self.log.error("%s:%d: No regular expression defined for rule '%s'",file,line,f.__name__) - self.error = 1 - continue - - try: - c = re.compile("(?P<%s>%s)" % (fname,f.__doc__), re.VERBOSE | self.reflags) - if c.match(""): - self.log.error("%s:%d: Regular expression for rule '%s' matches empty string", file,line,f.__name__) - self.error = 1 - except re.error: - _etype, e, _etrace = sys.exc_info() - self.log.error("%s:%d: Invalid regular expression for rule '%s'. %s", file,line,f.__name__,e) - if '#' in f.__doc__: - self.log.error("%s:%d. Make sure '#' in rule '%s' is escaped with '\\#'",file,line, f.__name__) - self.error = 1 - - # Validate all rules defined by strings - for name,r in self.strsym[state]: - tokname = self.toknames[name] - if tokname == 'error': - self.log.error("Rule '%s' must be defined as a function", name) - self.error = 1 - continue - - if not tokname in self.tokens and tokname.find("ignore_") < 0: - self.log.error("Rule '%s' defined for an unspecified token %s",name,tokname) - self.error = 1 - continue - - try: - c = re.compile("(?P<%s>%s)" % (name,r),re.VERBOSE | self.reflags) - if (c.match("")): - self.log.error("Regular expression for rule '%s' matches empty string",name) - self.error = 1 - except re.error: - _etype, e, _etrace = sys.exc_info() - self.log.error("Invalid regular expression for rule '%s'. %s",name,e) - if '#' in r: - self.log.error("Make sure '#' in rule '%s' is escaped with '\\#'",name) - self.error = 1 - - if not self.funcsym[state] and not self.strsym[state]: - self.log.error("No rules defined for state '%s'",state) - self.error = 1 - - # Validate the error function - efunc = self.errorf.get(state,None) - if efunc: - f = efunc - line = func_code(f).co_firstlineno - file = func_code(f).co_filename - self.files[file] = 1 - - if isinstance(f, types.MethodType): - reqargs = 2 - else: - reqargs = 1 - nargs = func_code(f).co_argcount - if nargs > reqargs: - self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,f.__name__) - self.error = 1 - - if nargs < reqargs: - self.log.error("%s:%d: Rule '%s' requires an argument", file,line,f.__name__) - self.error = 1 - - for f in self.files: - self.validate_file(f) - - - # ----------------------------------------------------------------------------- - # validate_file() - # - # This checks to see if there are duplicated t_rulename() functions or strings - # in the parser input file. This is done using a simple regular expression - # match on each line in the given file. - # ----------------------------------------------------------------------------- - - def validate_file(self,filename): - import os.path - base,ext = os.path.splitext(filename) - if ext != '.py': return # No idea what the file is. Return OK - - try: - f = open(filename) - lines = f.readlines() - f.close() - except IOError: - return # Couldn't find the file. Don't worry about it - - fre = re.compile(r'\s*def\s+(t_[a-zA-Z_0-9]*)\(') - sre = re.compile(r'\s*(t_[a-zA-Z_0-9]*)\s*=') - - counthash = { } - linen = 1 - for l in lines: - m = fre.match(l) - if not m: - m = sre.match(l) - if m: - name = m.group(1) - prev = counthash.get(name) - if not prev: - counthash[name] = linen - else: - self.log.error("%s:%d: Rule %s redefined. Previously defined on line %d",filename,linen,name,prev) - self.error = 1 - linen += 1 - -# ----------------------------------------------------------------------------- -# lex(module) -# -# Build all of the regular expression rules from definitions in the supplied module -# ----------------------------------------------------------------------------- -def lex(module=None,object=None,debug=0,optimize=0,lextab="lextab",reflags=0,nowarn=0,outputdir="", debuglog=None, errorlog=None): - global lexer - ldict = None - stateinfo = { 'INITIAL' : 'inclusive'} - lexobj = Lexer() - lexobj.lexoptimize = optimize - global token,input - - if errorlog is None: - errorlog = PlyLogger(sys.stderr) - - if debug: - if debuglog is None: - debuglog = PlyLogger(sys.stderr) - - # Get the module dictionary used for the lexer - if object: module = object - - if module: - _items = [(k,getattr(module,k)) for k in dir(module)] - ldict = dict(_items) - else: - ldict = get_caller_module_dict(2) - - # Collect parser information from the dictionary - linfo = LexerReflect(ldict,log=errorlog,reflags=reflags) - linfo.get_all() - if not optimize: - if linfo.validate_all(): - raise SyntaxError("Can't build lexer") - - if optimize and lextab: - try: - lexobj.readtab(lextab,ldict) - token = lexobj.token - input = lexobj.input - lexer = lexobj - return lexobj - - except ImportError: - pass - - # Dump some basic debugging information - if debug: - debuglog.info("lex: tokens = %r", linfo.tokens) - debuglog.info("lex: literals = %r", linfo.literals) - debuglog.info("lex: states = %r", linfo.stateinfo) - - # Build a dictionary of valid token names - lexobj.lextokens = { } - for n in linfo.tokens: - lexobj.lextokens[n] = 1 - - # Get literals specification - if isinstance(linfo.literals,(list,tuple)): - lexobj.lexliterals = type(linfo.literals[0])().join(linfo.literals) - else: - lexobj.lexliterals = linfo.literals - - # Get the stateinfo dictionary - stateinfo = linfo.stateinfo - - regexs = { } - # Build the master regular expressions - for state in stateinfo: - regex_list = [] - - # Add rules defined by functions first - for fname, f in linfo.funcsym[state]: - line = func_code(f).co_firstlineno - file = func_code(f).co_filename - regex_list.append("(?P<%s>%s)" % (fname,f.__doc__)) - if debug: - debuglog.info("lex: Adding rule %s -> '%s' (state '%s')",fname,f.__doc__, state) - - # Now add all of the simple rules - for name,r in linfo.strsym[state]: - regex_list.append("(?P<%s>%s)" % (name,r)) - if debug: - debuglog.info("lex: Adding rule %s -> '%s' (state '%s')",name,r, state) - - regexs[state] = regex_list - - # Build the master regular expressions - - if debug: - debuglog.info("lex: ==== MASTER REGEXS FOLLOW ====") - - for state in regexs: - lexre, re_text, re_names = _form_master_re(regexs[state],reflags,ldict,linfo.toknames) - lexobj.lexstatere[state] = lexre - lexobj.lexstateretext[state] = re_text - lexobj.lexstaterenames[state] = re_names - if debug: - for i in range(len(re_text)): - debuglog.info("lex: state '%s' : regex[%d] = '%s'",state, i, re_text[i]) - - # For inclusive states, we need to add the regular expressions from the INITIAL state - for state,stype in stateinfo.items(): - if state != "INITIAL" and stype == 'inclusive': - lexobj.lexstatere[state].extend(lexobj.lexstatere['INITIAL']) - lexobj.lexstateretext[state].extend(lexobj.lexstateretext['INITIAL']) - lexobj.lexstaterenames[state].extend(lexobj.lexstaterenames['INITIAL']) - - lexobj.lexstateinfo = stateinfo - lexobj.lexre = lexobj.lexstatere["INITIAL"] - lexobj.lexretext = lexobj.lexstateretext["INITIAL"] - lexobj.lexreflags = reflags - - # Set up ignore variables - lexobj.lexstateignore = linfo.ignore - lexobj.lexignore = lexobj.lexstateignore.get("INITIAL","") - - # Set up error functions - lexobj.lexstateerrorf = linfo.errorf - lexobj.lexerrorf = linfo.errorf.get("INITIAL",None) - if not lexobj.lexerrorf: - errorlog.warning("No t_error rule is defined") - - # Check state information for ignore and error rules - for s,stype in stateinfo.items(): - if stype == 'exclusive': - if not s in linfo.errorf: - errorlog.warning("No error rule is defined for exclusive state '%s'", s) - if not s in linfo.ignore and lexobj.lexignore: - errorlog.warning("No ignore rule is defined for exclusive state '%s'", s) - elif stype == 'inclusive': - if not s in linfo.errorf: - linfo.errorf[s] = linfo.errorf.get("INITIAL",None) - if not s in linfo.ignore: - linfo.ignore[s] = linfo.ignore.get("INITIAL","") - - # Create global versions of the token() and input() functions - token = lexobj.token - input = lexobj.input - lexer = lexobj - - # If in optimize mode, we write the lextab - if lextab and optimize: - lexobj.writetab(lextab,outputdir) - - return lexobj - -# ----------------------------------------------------------------------------- -# runmain() -# -# This runs the lexer as a main program -# ----------------------------------------------------------------------------- - -def runmain(lexer=None,data=None): - if not data: - try: - filename = sys.argv[1] - f = open(filename) - data = f.read() - f.close() - except IndexError: - sys.stdout.write("Reading from standard input (type EOF to end):\n") - data = sys.stdin.read() - - if lexer: - _input = lexer.input - else: - _input = input - _input(data) - if lexer: - _token = lexer.token - else: - _token = token - - while 1: - tok = _token() - if not tok: break - sys.stdout.write("(%s,%r,%d,%d)\n" % (tok.type, tok.value, tok.lineno,tok.lexpos)) - -# ----------------------------------------------------------------------------- -# @TOKEN(regex) -# -# This decorator function can be used to set the regex expression on a function -# when its docstring might need to be set in an alternative way -# ----------------------------------------------------------------------------- - -def TOKEN(r): - def set_doc(f): - if hasattr(r,"__call__"): - f.__doc__ = r.__doc__ - else: - f.__doc__ = r - return f - return set_doc - -# Alternative spelling of the TOKEN decorator -Token = TOKEN - diff --git a/src/components/script/dom/bindings/codegen/ply/ply/yacc.py b/src/components/script/dom/bindings/codegen/ply/ply/yacc.py deleted file mode 100644 index e9f5c657551..00000000000 --- a/src/components/script/dom/bindings/codegen/ply/ply/yacc.py +++ /dev/null @@ -1,3276 +0,0 @@ -# ----------------------------------------------------------------------------- -# ply: yacc.py -# -# Copyright (C) 2001-2009, -# David M. Beazley (Dabeaz LLC) -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the David Beazley or Dabeaz LLC may be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# ----------------------------------------------------------------------------- -# -# This implements an LR parser that is constructed from grammar rules defined -# as Python functions. The grammer is specified by supplying the BNF inside -# Python documentation strings. The inspiration for this technique was borrowed -# from John Aycock's Spark parsing system. PLY might be viewed as cross between -# Spark and the GNU bison utility. -# -# The current implementation is only somewhat object-oriented. The -# LR parser itself is defined in terms of an object (which allows multiple -# parsers to co-exist). However, most of the variables used during table -# construction are defined in terms of global variables. Users shouldn't -# notice unless they are trying to define multiple parsers at the same -# time using threads (in which case they should have their head examined). -# -# This implementation supports both SLR and LALR(1) parsing. LALR(1) -# support was originally implemented by Elias Ioup (ezioup@alumni.uchicago.edu), -# using the algorithm found in Aho, Sethi, and Ullman "Compilers: Principles, -# Techniques, and Tools" (The Dragon Book). LALR(1) has since been replaced -# by the more efficient DeRemer and Pennello algorithm. -# -# :::::::: WARNING ::::::: -# -# Construction of LR parsing tables is fairly complicated and expensive. -# To make this module run fast, a *LOT* of work has been put into -# optimization---often at the expensive of readability and what might -# consider to be good Python "coding style." Modify the code at your -# own risk! -# ---------------------------------------------------------------------------- - -__version__ = "3.3" -__tabversion__ = "3.2" # Table version - -#----------------------------------------------------------------------------- -# === User configurable parameters === -# -# Change these to modify the default behavior of yacc (if you wish) -#----------------------------------------------------------------------------- - -yaccdebug = 1 # Debugging mode. If set, yacc generates a - # a 'parser.out' file in the current directory - -debug_file = 'parser.out' # Default name of the debugging file -tab_module = 'parsetab' # Default name of the table module -default_lr = 'LALR' # Default LR table generation method - -error_count = 3 # Number of symbols that must be shifted to leave recovery mode - -yaccdevel = 0 # Set to True if developing yacc. This turns off optimized - # implementations of certain functions. - -resultlimit = 40 # Size limit of results when running in debug mode. - -pickle_protocol = 0 # Protocol to use when writing pickle files - -import re, types, sys, os.path - -# Compatibility function for python 2.6/3.0 -if sys.version_info[0] < 3: - def func_code(f): - return f.func_code -else: - def func_code(f): - return f.__code__ - -# Compatibility -try: - MAXINT = sys.maxint -except AttributeError: - MAXINT = sys.maxsize - -# Python 2.x/3.0 compatibility. -def load_ply_lex(): - if sys.version_info[0] < 3: - import lex - else: - import ply.lex as lex - return lex - -# This object is a stand-in for a logging object created by the -# logging module. PLY will use this by default to create things -# such as the parser.out file. If a user wants more detailed -# information, they can create their own logging object and pass -# it into PLY. - -class PlyLogger(object): - def __init__(self,f): - self.f = f - def debug(self,msg,*args,**kwargs): - self.f.write((msg % args) + "\n") - info = debug - - def warning(self,msg,*args,**kwargs): - self.f.write("WARNING: "+ (msg % args) + "\n") - - def error(self,msg,*args,**kwargs): - self.f.write("ERROR: " + (msg % args) + "\n") - - critical = debug - -# Null logger is used when no output is generated. Does nothing. -class NullLogger(object): - def __getattribute__(self,name): - return self - def __call__(self,*args,**kwargs): - return self - -# Exception raised for yacc-related errors -class YaccError(Exception): pass - -# Format the result message that the parser produces when running in debug mode. -def format_result(r): - repr_str = repr(r) - if '\n' in repr_str: repr_str = repr(repr_str) - if len(repr_str) > resultlimit: - repr_str = repr_str[:resultlimit]+" ..." - result = "<%s @ 0x%x> (%s)" % (type(r).__name__,id(r),repr_str) - return result - - -# Format stack entries when the parser is running in debug mode -def format_stack_entry(r): - repr_str = repr(r) - if '\n' in repr_str: repr_str = repr(repr_str) - if len(repr_str) < 16: - return repr_str - else: - return "<%s @ 0x%x>" % (type(r).__name__,id(r)) - -#----------------------------------------------------------------------------- -# === LR Parsing Engine === -# -# The following classes are used for the LR parser itself. These are not -# used during table construction and are independent of the actual LR -# table generation algorithm -#----------------------------------------------------------------------------- - -# This class is used to hold non-terminal grammar symbols during parsing. -# It normally has the following attributes set: -# .type = Grammar symbol type -# .value = Symbol value -# .lineno = Starting line number -# .endlineno = Ending line number (optional, set automatically) -# .lexpos = Starting lex position -# .endlexpos = Ending lex position (optional, set automatically) - -class YaccSymbol: - def __str__(self): return self.type - def __repr__(self): return str(self) - -# This class is a wrapper around the objects actually passed to each -# grammar rule. Index lookup and assignment actually assign the -# .value attribute of the underlying YaccSymbol object. -# The lineno() method returns the line number of a given -# item (or 0 if not defined). The linespan() method returns -# a tuple of (startline,endline) representing the range of lines -# for a symbol. The lexspan() method returns a tuple (lexpos,endlexpos) -# representing the range of positional information for a symbol. - -class YaccProduction: - def __init__(self,s,stack=None): - self.slice = s - self.stack = stack - self.lexer = None - self.parser= None - def __getitem__(self,n): - if n >= 0: return self.slice[n].value - else: return self.stack[n].value - - def __setitem__(self,n,v): - self.slice[n].value = v - - def __getslice__(self,i,j): - return [s.value for s in self.slice[i:j]] - - def __len__(self): - return len(self.slice) - - def lineno(self,n): - return getattr(self.slice[n],"lineno",0) - - def set_lineno(self,n,lineno): - self.slice[n].lineno = lineno - - def linespan(self,n): - startline = getattr(self.slice[n],"lineno",0) - endline = getattr(self.slice[n],"endlineno",startline) - return startline,endline - - def lexpos(self,n): - return getattr(self.slice[n],"lexpos",0) - - def lexspan(self,n): - startpos = getattr(self.slice[n],"lexpos",0) - endpos = getattr(self.slice[n],"endlexpos",startpos) - return startpos,endpos - - def error(self): - raise SyntaxError - - -# ----------------------------------------------------------------------------- -# == LRParser == -# -# The LR Parsing engine. -# ----------------------------------------------------------------------------- - -class LRParser: - def __init__(self,lrtab,errorf): - self.productions = lrtab.lr_productions - self.action = lrtab.lr_action - self.goto = lrtab.lr_goto - self.errorfunc = errorf - - def errok(self): - self.errorok = 1 - - def restart(self): - del self.statestack[:] - del self.symstack[:] - sym = YaccSymbol() - sym.type = '$end' - self.symstack.append(sym) - self.statestack.append(0) - - def parse(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None): - if debug or yaccdevel: - if isinstance(debug,int): - debug = PlyLogger(sys.stderr) - return self.parsedebug(input,lexer,debug,tracking,tokenfunc) - elif tracking: - return self.parseopt(input,lexer,debug,tracking,tokenfunc) - else: - return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc) - - - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # parsedebug(). - # - # This is the debugging enabled version of parse(). All changes made to the - # parsing engine should be made here. For the non-debugging version, - # copy this code to a method parseopt() and delete all of the sections - # enclosed in: - # - # #--! DEBUG - # statements - # #--! DEBUG - # - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - def parsedebug(self,input=None,lexer=None,debug=None,tracking=0,tokenfunc=None): - lookahead = None # Current lookahead symbol - lookaheadstack = [ ] # Stack of lookahead symbols - actions = self.action # Local reference to action table (to avoid lookup on self.) - goto = self.goto # Local reference to goto table (to avoid lookup on self.) - prod = self.productions # Local reference to production list (to avoid lookup on self.) - pslice = YaccProduction(None) # Production object passed to grammar rules - errorcount = 0 # Used during error recovery - - # --! DEBUG - debug.info("PLY: PARSE DEBUG START") - # --! DEBUG - - # If no lexer was given, we will try to use the lex module - if not lexer: - lex = load_ply_lex() - lexer = lex.lexer - - # Set up the lexer and parser objects on pslice - pslice.lexer = lexer - pslice.parser = self - - # If input was supplied, pass to lexer - if input is not None: - lexer.input(input) - - if tokenfunc is None: - # Tokenize function - get_token = lexer.token - else: - get_token = tokenfunc - - # Set up the state and symbol stacks - - statestack = [ ] # Stack of parsing states - self.statestack = statestack - symstack = [ ] # Stack of grammar symbols - self.symstack = symstack - - pslice.stack = symstack # Put in the production - errtoken = None # Err token - - # The start state is assumed to be (0,$end) - - statestack.append(0) - sym = YaccSymbol() - sym.type = "$end" - symstack.append(sym) - state = 0 - while 1: - # Get the next symbol on the input. If a lookahead symbol - # is already set, we just use that. Otherwise, we'll pull - # the next token off of the lookaheadstack or from the lexer - - # --! DEBUG - debug.debug('') - debug.debug('State : %s', state) - # --! DEBUG - - if not lookahead: - if not lookaheadstack: - lookahead = get_token() # Get the next token - else: - lookahead = lookaheadstack.pop() - if not lookahead: - lookahead = YaccSymbol() - lookahead.type = "$end" - - # --! DEBUG - debug.debug('Stack : %s', - ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip()) - # --! DEBUG - - # Check the action table - ltype = lookahead.type - t = actions[state].get(ltype) - - if t is not None: - if t > 0: - # shift a symbol on the stack - statestack.append(t) - state = t - - # --! DEBUG - debug.debug("Action : Shift and goto state %s", t) - # --! DEBUG - - symstack.append(lookahead) - lookahead = None - - # Decrease error count on successful shift - if errorcount: errorcount -=1 - continue - - if t < 0: - # reduce a symbol on the stack, emit a production - p = prod[-t] - pname = p.name - plen = p.len - - # Get production function - sym = YaccSymbol() - sym.type = pname # Production name - sym.value = None - - # --! DEBUG - if plen: - debug.info("Action : Reduce rule [%s] with %s and goto state %d", p.str, "["+",".join([format_stack_entry(_v.value) for _v in symstack[-plen:]])+"]",-t) - else: - debug.info("Action : Reduce rule [%s] with %s and goto state %d", p.str, [],-t) - - # --! DEBUG - - if plen: - targ = symstack[-plen-1:] - targ[0] = sym - - # --! TRACKING - if tracking: - t1 = targ[1] - sym.lineno = t1.lineno - sym.lexpos = t1.lexpos - t1 = targ[-1] - sym.endlineno = getattr(t1,"endlineno",t1.lineno) - sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos) - - # --! TRACKING - - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # The code enclosed in this section is duplicated - # below as a performance optimization. Make sure - # changes get made in both locations. - - pslice.slice = targ - - try: - # Call the grammar rule with our special slice object - del symstack[-plen:] - del statestack[-plen:] - p.callable(pslice) - # --! DEBUG - debug.info("Result : %s", format_result(pslice[0])) - # --! DEBUG - symstack.append(sym) - state = goto[statestack[-1]][pname] - statestack.append(state) - except SyntaxError: - # If an error was set. Enter error recovery state - lookaheadstack.append(lookahead) - symstack.pop() - statestack.pop() - state = statestack[-1] - sym.type = 'error' - lookahead = sym - errorcount = error_count - self.errorok = 0 - continue - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - else: - - # --! TRACKING - if tracking: - sym.lineno = lexer.lineno - sym.lexpos = lexer.lexpos - # --! TRACKING - - targ = [ sym ] - - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # The code enclosed in this section is duplicated - # above as a performance optimization. Make sure - # changes get made in both locations. - - pslice.slice = targ - - try: - # Call the grammar rule with our special slice object - p.callable(pslice) - # --! DEBUG - debug.info("Result : %s", format_result(pslice[0])) - # --! DEBUG - symstack.append(sym) - state = goto[statestack[-1]][pname] - statestack.append(state) - except SyntaxError: - # If an error was set. Enter error recovery state - lookaheadstack.append(lookahead) - symstack.pop() - statestack.pop() - state = statestack[-1] - sym.type = 'error' - lookahead = sym - errorcount = error_count - self.errorok = 0 - continue - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - if t == 0: - n = symstack[-1] - result = getattr(n,"value",None) - # --! DEBUG - debug.info("Done : Returning %s", format_result(result)) - debug.info("PLY: PARSE DEBUG END") - # --! DEBUG - return result - - if t == None: - - # --! DEBUG - debug.error('Error : %s', - ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip()) - # --! DEBUG - - # We have some kind of parsing error here. To handle - # this, we are going to push the current token onto - # the tokenstack and replace it with an 'error' token. - # If there are any synchronization rules, they may - # catch it. - # - # In addition to pushing the error token, we call call - # the user defined p_error() function if this is the - # first syntax error. This function is only called if - # errorcount == 0. - if errorcount == 0 or self.errorok: - errorcount = error_count - self.errorok = 0 - errtoken = lookahead - if errtoken.type == "$end": - errtoken = None # End of file! - if self.errorfunc: - global errok,token,restart - errok = self.errok # Set some special functions available in error recovery - token = get_token - restart = self.restart - if errtoken and not hasattr(errtoken,'lexer'): - errtoken.lexer = lexer - tok = self.errorfunc(errtoken) - del errok, token, restart # Delete special functions - - if self.errorok: - # User must have done some kind of panic - # mode recovery on their own. The - # returned token is the next lookahead - lookahead = tok - errtoken = None - continue - else: - if errtoken: - if hasattr(errtoken,"lineno"): lineno = lookahead.lineno - else: lineno = 0 - if lineno: - sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type)) - else: - sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type) - else: - sys.stderr.write("yacc: Parse error in input. EOF\n") - return - - else: - errorcount = error_count - - # case 1: the statestack only has 1 entry on it. If we're in this state, the - # entire parse has been rolled back and we're completely hosed. The token is - # discarded and we just keep going. - - if len(statestack) <= 1 and lookahead.type != "$end": - lookahead = None - errtoken = None - state = 0 - # Nuke the pushback stack - del lookaheadstack[:] - continue - - # case 2: the statestack has a couple of entries on it, but we're - # at the end of the file. nuke the top entry and generate an error token - - # Start nuking entries on the stack - if lookahead.type == "$end": - # Whoa. We're really hosed here. Bail out - return - - if lookahead.type != 'error': - sym = symstack[-1] - if sym.type == 'error': - # Hmmm. Error is on top of stack, we'll just nuke input - # symbol and continue - lookahead = None - continue - t = YaccSymbol() - t.type = 'error' - if hasattr(lookahead,"lineno"): - t.lineno = lookahead.lineno - t.value = lookahead - lookaheadstack.append(lookahead) - lookahead = t - else: - symstack.pop() - statestack.pop() - state = statestack[-1] # Potential bug fix - - continue - - # Call an error function here - raise RuntimeError("yacc: internal parser error!!!\n") - - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # parseopt(). - # - # Optimized version of parse() method. DO NOT EDIT THIS CODE DIRECTLY. - # Edit the debug version above, then copy any modifications to the method - # below while removing #--! DEBUG sections. - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - - def parseopt(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None): - lookahead = None # Current lookahead symbol - lookaheadstack = [ ] # Stack of lookahead symbols - actions = self.action # Local reference to action table (to avoid lookup on self.) - goto = self.goto # Local reference to goto table (to avoid lookup on self.) - prod = self.productions # Local reference to production list (to avoid lookup on self.) - pslice = YaccProduction(None) # Production object passed to grammar rules - errorcount = 0 # Used during error recovery - - # If no lexer was given, we will try to use the lex module - if not lexer: - lex = load_ply_lex() - lexer = lex.lexer - - # Set up the lexer and parser objects on pslice - pslice.lexer = lexer - pslice.parser = self - - # If input was supplied, pass to lexer - if input is not None: - lexer.input(input) - - if tokenfunc is None: - # Tokenize function - get_token = lexer.token - else: - get_token = tokenfunc - - # Set up the state and symbol stacks - - statestack = [ ] # Stack of parsing states - self.statestack = statestack - symstack = [ ] # Stack of grammar symbols - self.symstack = symstack - - pslice.stack = symstack # Put in the production - errtoken = None # Err token - - # The start state is assumed to be (0,$end) - - statestack.append(0) - sym = YaccSymbol() - sym.type = '$end' - symstack.append(sym) - state = 0 - while 1: - # Get the next symbol on the input. If a lookahead symbol - # is already set, we just use that. Otherwise, we'll pull - # the next token off of the lookaheadstack or from the lexer - - if not lookahead: - if not lookaheadstack: - lookahead = get_token() # Get the next token - else: - lookahead = lookaheadstack.pop() - if not lookahead: - lookahead = YaccSymbol() - lookahead.type = '$end' - - # Check the action table - ltype = lookahead.type - t = actions[state].get(ltype) - - if t is not None: - if t > 0: - # shift a symbol on the stack - statestack.append(t) - state = t - - symstack.append(lookahead) - lookahead = None - - # Decrease error count on successful shift - if errorcount: errorcount -=1 - continue - - if t < 0: - # reduce a symbol on the stack, emit a production - p = prod[-t] - pname = p.name - plen = p.len - - # Get production function - sym = YaccSymbol() - sym.type = pname # Production name - sym.value = None - - if plen: - targ = symstack[-plen-1:] - targ[0] = sym - - # --! TRACKING - if tracking: - t1 = targ[1] - sym.lineno = t1.lineno - sym.lexpos = t1.lexpos - t1 = targ[-1] - sym.endlineno = getattr(t1,"endlineno",t1.lineno) - sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos) - - # --! TRACKING - - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # The code enclosed in this section is duplicated - # below as a performance optimization. Make sure - # changes get made in both locations. - - pslice.slice = targ - - try: - # Call the grammar rule with our special slice object - del symstack[-plen:] - del statestack[-plen:] - p.callable(pslice) - symstack.append(sym) - state = goto[statestack[-1]][pname] - statestack.append(state) - except SyntaxError: - # If an error was set. Enter error recovery state - lookaheadstack.append(lookahead) - symstack.pop() - statestack.pop() - state = statestack[-1] - sym.type = 'error' - lookahead = sym - errorcount = error_count - self.errorok = 0 - continue - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - else: - - # --! TRACKING - if tracking: - sym.lineno = lexer.lineno - sym.lexpos = lexer.lexpos - # --! TRACKING - - targ = [ sym ] - - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # The code enclosed in this section is duplicated - # above as a performance optimization. Make sure - # changes get made in both locations. - - pslice.slice = targ - - try: - # Call the grammar rule with our special slice object - p.callable(pslice) - symstack.append(sym) - state = goto[statestack[-1]][pname] - statestack.append(state) - except SyntaxError: - # If an error was set. Enter error recovery state - lookaheadstack.append(lookahead) - symstack.pop() - statestack.pop() - state = statestack[-1] - sym.type = 'error' - lookahead = sym - errorcount = error_count - self.errorok = 0 - continue - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - if t == 0: - n = symstack[-1] - return getattr(n,"value",None) - - if t == None: - - # We have some kind of parsing error here. To handle - # this, we are going to push the current token onto - # the tokenstack and replace it with an 'error' token. - # If there are any synchronization rules, they may - # catch it. - # - # In addition to pushing the error token, we call call - # the user defined p_error() function if this is the - # first syntax error. This function is only called if - # errorcount == 0. - if errorcount == 0 or self.errorok: - errorcount = error_count - self.errorok = 0 - errtoken = lookahead - if errtoken.type == '$end': - errtoken = None # End of file! - if self.errorfunc: - global errok,token,restart - errok = self.errok # Set some special functions available in error recovery - token = get_token - restart = self.restart - if errtoken and not hasattr(errtoken,'lexer'): - errtoken.lexer = lexer - tok = self.errorfunc(errtoken) - del errok, token, restart # Delete special functions - - if self.errorok: - # User must have done some kind of panic - # mode recovery on their own. The - # returned token is the next lookahead - lookahead = tok - errtoken = None - continue - else: - if errtoken: - if hasattr(errtoken,"lineno"): lineno = lookahead.lineno - else: lineno = 0 - if lineno: - sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type)) - else: - sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type) - else: - sys.stderr.write("yacc: Parse error in input. EOF\n") - return - - else: - errorcount = error_count - - # case 1: the statestack only has 1 entry on it. If we're in this state, the - # entire parse has been rolled back and we're completely hosed. The token is - # discarded and we just keep going. - - if len(statestack) <= 1 and lookahead.type != '$end': - lookahead = None - errtoken = None - state = 0 - # Nuke the pushback stack - del lookaheadstack[:] - continue - - # case 2: the statestack has a couple of entries on it, but we're - # at the end of the file. nuke the top entry and generate an error token - - # Start nuking entries on the stack - if lookahead.type == '$end': - # Whoa. We're really hosed here. Bail out - return - - if lookahead.type != 'error': - sym = symstack[-1] - if sym.type == 'error': - # Hmmm. Error is on top of stack, we'll just nuke input - # symbol and continue - lookahead = None - continue - t = YaccSymbol() - t.type = 'error' - if hasattr(lookahead,"lineno"): - t.lineno = lookahead.lineno - t.value = lookahead - lookaheadstack.append(lookahead) - lookahead = t - else: - symstack.pop() - statestack.pop() - state = statestack[-1] # Potential bug fix - - continue - - # Call an error function here - raise RuntimeError("yacc: internal parser error!!!\n") - - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # parseopt_notrack(). - # - # Optimized version of parseopt() with line number tracking removed. - # DO NOT EDIT THIS CODE DIRECTLY. Copy the optimized version and remove - # code in the #--! TRACKING sections - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - def parseopt_notrack(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None): - lookahead = None # Current lookahead symbol - lookaheadstack = [ ] # Stack of lookahead symbols - actions = self.action # Local reference to action table (to avoid lookup on self.) - goto = self.goto # Local reference to goto table (to avoid lookup on self.) - prod = self.productions # Local reference to production list (to avoid lookup on self.) - pslice = YaccProduction(None) # Production object passed to grammar rules - errorcount = 0 # Used during error recovery - - # If no lexer was given, we will try to use the lex module - if not lexer: - lex = load_ply_lex() - lexer = lex.lexer - - # Set up the lexer and parser objects on pslice - pslice.lexer = lexer - pslice.parser = self - - # If input was supplied, pass to lexer - if input is not None: - lexer.input(input) - - if tokenfunc is None: - # Tokenize function - get_token = lexer.token - else: - get_token = tokenfunc - - # Set up the state and symbol stacks - - statestack = [ ] # Stack of parsing states - self.statestack = statestack - symstack = [ ] # Stack of grammar symbols - self.symstack = symstack - - pslice.stack = symstack # Put in the production - errtoken = None # Err token - - # The start state is assumed to be (0,$end) - - statestack.append(0) - sym = YaccSymbol() - sym.type = '$end' - symstack.append(sym) - state = 0 - while 1: - # Get the next symbol on the input. If a lookahead symbol - # is already set, we just use that. Otherwise, we'll pull - # the next token off of the lookaheadstack or from the lexer - - if not lookahead: - if not lookaheadstack: - lookahead = get_token() # Get the next token - else: - lookahead = lookaheadstack.pop() - if not lookahead: - lookahead = YaccSymbol() - lookahead.type = '$end' - - # Check the action table - ltype = lookahead.type - t = actions[state].get(ltype) - - if t is not None: - if t > 0: - # shift a symbol on the stack - statestack.append(t) - state = t - - symstack.append(lookahead) - lookahead = None - - # Decrease error count on successful shift - if errorcount: errorcount -=1 - continue - - if t < 0: - # reduce a symbol on the stack, emit a production - p = prod[-t] - pname = p.name - plen = p.len - - # Get production function - sym = YaccSymbol() - sym.type = pname # Production name - sym.value = None - - if plen: - targ = symstack[-plen-1:] - targ[0] = sym - - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # The code enclosed in this section is duplicated - # below as a performance optimization. Make sure - # changes get made in both locations. - - pslice.slice = targ - - try: - # Call the grammar rule with our special slice object - del symstack[-plen:] - del statestack[-plen:] - p.callable(pslice) - symstack.append(sym) - state = goto[statestack[-1]][pname] - statestack.append(state) - except SyntaxError: - # If an error was set. Enter error recovery state - lookaheadstack.append(lookahead) - symstack.pop() - statestack.pop() - state = statestack[-1] - sym.type = 'error' - lookahead = sym - errorcount = error_count - self.errorok = 0 - continue - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - else: - - targ = [ sym ] - - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # The code enclosed in this section is duplicated - # above as a performance optimization. Make sure - # changes get made in both locations. - - pslice.slice = targ - - try: - # Call the grammar rule with our special slice object - p.callable(pslice) - symstack.append(sym) - state = goto[statestack[-1]][pname] - statestack.append(state) - except SyntaxError: - # If an error was set. Enter error recovery state - lookaheadstack.append(lookahead) - symstack.pop() - statestack.pop() - state = statestack[-1] - sym.type = 'error' - lookahead = sym - errorcount = error_count - self.errorok = 0 - continue - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - if t == 0: - n = symstack[-1] - return getattr(n,"value",None) - - if t == None: - - # We have some kind of parsing error here. To handle - # this, we are going to push the current token onto - # the tokenstack and replace it with an 'error' token. - # If there are any synchronization rules, they may - # catch it. - # - # In addition to pushing the error token, we call call - # the user defined p_error() function if this is the - # first syntax error. This function is only called if - # errorcount == 0. - if errorcount == 0 or self.errorok: - errorcount = error_count - self.errorok = 0 - errtoken = lookahead - if errtoken.type == '$end': - errtoken = None # End of file! - if self.errorfunc: - global errok,token,restart - errok = self.errok # Set some special functions available in error recovery - token = get_token - restart = self.restart - if errtoken and not hasattr(errtoken,'lexer'): - errtoken.lexer = lexer - tok = self.errorfunc(errtoken) - del errok, token, restart # Delete special functions - - if self.errorok: - # User must have done some kind of panic - # mode recovery on their own. The - # returned token is the next lookahead - lookahead = tok - errtoken = None - continue - else: - if errtoken: - if hasattr(errtoken,"lineno"): lineno = lookahead.lineno - else: lineno = 0 - if lineno: - sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type)) - else: - sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type) - else: - sys.stderr.write("yacc: Parse error in input. EOF\n") - return - - else: - errorcount = error_count - - # case 1: the statestack only has 1 entry on it. If we're in this state, the - # entire parse has been rolled back and we're completely hosed. The token is - # discarded and we just keep going. - - if len(statestack) <= 1 and lookahead.type != '$end': - lookahead = None - errtoken = None - state = 0 - # Nuke the pushback stack - del lookaheadstack[:] - continue - - # case 2: the statestack has a couple of entries on it, but we're - # at the end of the file. nuke the top entry and generate an error token - - # Start nuking entries on the stack - if lookahead.type == '$end': - # Whoa. We're really hosed here. Bail out - return - - if lookahead.type != 'error': - sym = symstack[-1] - if sym.type == 'error': - # Hmmm. Error is on top of stack, we'll just nuke input - # symbol and continue - lookahead = None - continue - t = YaccSymbol() - t.type = 'error' - if hasattr(lookahead,"lineno"): - t.lineno = lookahead.lineno - t.value = lookahead - lookaheadstack.append(lookahead) - lookahead = t - else: - symstack.pop() - statestack.pop() - state = statestack[-1] # Potential bug fix - - continue - - # Call an error function here - raise RuntimeError("yacc: internal parser error!!!\n") - -# ----------------------------------------------------------------------------- -# === Grammar Representation === -# -# The following functions, classes, and variables are used to represent and -# manipulate the rules that make up a grammar. -# ----------------------------------------------------------------------------- - -import re - -# regex matching identifiers -_is_identifier = re.compile(r'^[a-zA-Z0-9_-]+$') - -# ----------------------------------------------------------------------------- -# class Production: -# -# This class stores the raw information about a single production or grammar rule. -# A grammar rule refers to a specification such as this: -# -# expr : expr PLUS term -# -# Here are the basic attributes defined on all productions -# -# name - Name of the production. For example 'expr' -# prod - A list of symbols on the right side ['expr','PLUS','term'] -# prec - Production precedence level -# number - Production number. -# func - Function that executes on reduce -# file - File where production function is defined -# lineno - Line number where production function is defined -# -# The following attributes are defined or optional. -# -# len - Length of the production (number of symbols on right hand side) -# usyms - Set of unique symbols found in the production -# ----------------------------------------------------------------------------- - -class Production(object): - reduced = 0 - def __init__(self,number,name,prod,precedence=('right',0),func=None,file='',line=0): - self.name = name - self.prod = tuple(prod) - self.number = number - self.func = func - self.callable = None - self.file = file - self.line = line - self.prec = precedence - - # Internal settings used during table construction - - self.len = len(self.prod) # Length of the production - - # Create a list of unique production symbols used in the production - self.usyms = [ ] - for s in self.prod: - if s not in self.usyms: - self.usyms.append(s) - - # List of all LR items for the production - self.lr_items = [] - self.lr_next = None - - # Create a string representation - if self.prod: - self.str = "%s -> %s" % (self.name," ".join(self.prod)) - else: - self.str = "%s -> <empty>" % self.name - - def __str__(self): - return self.str - - def __repr__(self): - return "Production("+str(self)+")" - - def __len__(self): - return len(self.prod) - - def __nonzero__(self): - return 1 - - def __getitem__(self,index): - return self.prod[index] - - # Return the nth lr_item from the production (or None if at the end) - def lr_item(self,n): - if n > len(self.prod): return None - p = LRItem(self,n) - - # Precompute the list of productions immediately following. Hack. Remove later - try: - p.lr_after = Prodnames[p.prod[n+1]] - except (IndexError,KeyError): - p.lr_after = [] - try: - p.lr_before = p.prod[n-1] - except IndexError: - p.lr_before = None - - return p - - # Bind the production function name to a callable - def bind(self,pdict): - if self.func: - self.callable = pdict[self.func] - -# This class serves as a minimal standin for Production objects when -# reading table data from files. It only contains information -# actually used by the LR parsing engine, plus some additional -# debugging information. -class MiniProduction(object): - def __init__(self,str,name,len,func,file,line): - self.name = name - self.len = len - self.func = func - self.callable = None - self.file = file - self.line = line - self.str = str - def __str__(self): - return self.str - def __repr__(self): - return "MiniProduction(%s)" % self.str - - # Bind the production function name to a callable - def bind(self,pdict): - if self.func: - self.callable = pdict[self.func] - - -# ----------------------------------------------------------------------------- -# class LRItem -# -# This class represents a specific stage of parsing a production rule. For -# example: -# -# expr : expr . PLUS term -# -# In the above, the "." represents the current location of the parse. Here -# basic attributes: -# -# name - Name of the production. For example 'expr' -# prod - A list of symbols on the right side ['expr','.', 'PLUS','term'] -# number - Production number. -# -# lr_next Next LR item. Example, if we are ' expr -> expr . PLUS term' -# then lr_next refers to 'expr -> expr PLUS . term' -# lr_index - LR item index (location of the ".") in the prod list. -# lookaheads - LALR lookahead symbols for this item -# len - Length of the production (number of symbols on right hand side) -# lr_after - List of all productions that immediately follow -# lr_before - Grammar symbol immediately before -# ----------------------------------------------------------------------------- - -class LRItem(object): - def __init__(self,p,n): - self.name = p.name - self.prod = list(p.prod) - self.number = p.number - self.lr_index = n - self.lookaheads = { } - self.prod.insert(n,".") - self.prod = tuple(self.prod) - self.len = len(self.prod) - self.usyms = p.usyms - - def __str__(self): - if self.prod: - s = "%s -> %s" % (self.name," ".join(self.prod)) - else: - s = "%s -> <empty>" % self.name - return s - - def __repr__(self): - return "LRItem("+str(self)+")" - -# ----------------------------------------------------------------------------- -# rightmost_terminal() -# -# Return the rightmost terminal from a list of symbols. Used in add_production() -# ----------------------------------------------------------------------------- -def rightmost_terminal(symbols, terminals): - i = len(symbols) - 1 - while i >= 0: - if symbols[i] in terminals: - return symbols[i] - i -= 1 - return None - -# ----------------------------------------------------------------------------- -# === GRAMMAR CLASS === -# -# The following class represents the contents of the specified grammar along -# with various computed properties such as first sets, follow sets, LR items, etc. -# This data is used for critical parts of the table generation process later. -# ----------------------------------------------------------------------------- - -class GrammarError(YaccError): pass - -class Grammar(object): - def __init__(self,terminals): - self.Productions = [None] # A list of all of the productions. The first - # entry is always reserved for the purpose of - # building an augmented grammar - - self.Prodnames = { } # A dictionary mapping the names of nonterminals to a list of all - # productions of that nonterminal. - - self.Prodmap = { } # A dictionary that is only used to detect duplicate - # productions. - - self.Terminals = { } # A dictionary mapping the names of terminal symbols to a - # list of the rules where they are used. - - for term in terminals: - self.Terminals[term] = [] - - self.Terminals['error'] = [] - - self.Nonterminals = { } # A dictionary mapping names of nonterminals to a list - # of rule numbers where they are used. - - self.First = { } # A dictionary of precomputed FIRST(x) symbols - - self.Follow = { } # A dictionary of precomputed FOLLOW(x) symbols - - self.Precedence = { } # Precedence rules for each terminal. Contains tuples of the - # form ('right',level) or ('nonassoc', level) or ('left',level) - - self.UsedPrecedence = { } # Precedence rules that were actually used by the grammer. - # This is only used to provide error checking and to generate - # a warning about unused precedence rules. - - self.Start = None # Starting symbol for the grammar - - - def __len__(self): - return len(self.Productions) - - def __getitem__(self,index): - return self.Productions[index] - - # ----------------------------------------------------------------------------- - # set_precedence() - # - # Sets the precedence for a given terminal. assoc is the associativity such as - # 'left','right', or 'nonassoc'. level is a numeric level. - # - # ----------------------------------------------------------------------------- - - def set_precedence(self,term,assoc,level): - assert self.Productions == [None],"Must call set_precedence() before add_production()" - if term in self.Precedence: - raise GrammarError("Precedence already specified for terminal '%s'" % term) - if assoc not in ['left','right','nonassoc']: - raise GrammarError("Associativity must be one of 'left','right', or 'nonassoc'") - self.Precedence[term] = (assoc,level) - - # ----------------------------------------------------------------------------- - # add_production() - # - # Given an action function, this function assembles a production rule and - # computes its precedence level. - # - # The production rule is supplied as a list of symbols. For example, - # a rule such as 'expr : expr PLUS term' has a production name of 'expr' and - # symbols ['expr','PLUS','term']. - # - # Precedence is determined by the precedence of the right-most non-terminal - # or the precedence of a terminal specified by %prec. - # - # A variety of error checks are performed to make sure production symbols - # are valid and that %prec is used correctly. - # ----------------------------------------------------------------------------- - - def add_production(self,prodname,syms,func=None,file='',line=0): - - if prodname in self.Terminals: - raise GrammarError("%s:%d: Illegal rule name '%s'. Already defined as a token" % (file,line,prodname)) - if prodname == 'error': - raise GrammarError("%s:%d: Illegal rule name '%s'. error is a reserved word" % (file,line,prodname)) - if not _is_identifier.match(prodname): - raise GrammarError("%s:%d: Illegal rule name '%s'" % (file,line,prodname)) - - # Look for literal tokens - for n,s in enumerate(syms): - if s[0] in "'\"": - try: - c = eval(s) - if (len(c) > 1): - raise GrammarError("%s:%d: Literal token %s in rule '%s' may only be a single character" % (file,line,s, prodname)) - if not c in self.Terminals: - self.Terminals[c] = [] - syms[n] = c - continue - except SyntaxError: - pass - if not _is_identifier.match(s) and s != '%prec': - raise GrammarError("%s:%d: Illegal name '%s' in rule '%s'" % (file,line,s, prodname)) - - # Determine the precedence level - if '%prec' in syms: - if syms[-1] == '%prec': - raise GrammarError("%s:%d: Syntax error. Nothing follows %%prec" % (file,line)) - if syms[-2] != '%prec': - raise GrammarError("%s:%d: Syntax error. %%prec can only appear at the end of a grammar rule" % (file,line)) - precname = syms[-1] - prodprec = self.Precedence.get(precname,None) - if not prodprec: - raise GrammarError("%s:%d: Nothing known about the precedence of '%s'" % (file,line,precname)) - else: - self.UsedPrecedence[precname] = 1 - del syms[-2:] # Drop %prec from the rule - else: - # If no %prec, precedence is determined by the rightmost terminal symbol - precname = rightmost_terminal(syms,self.Terminals) - prodprec = self.Precedence.get(precname,('right',0)) - - # See if the rule is already in the rulemap - map = "%s -> %s" % (prodname,syms) - if map in self.Prodmap: - m = self.Prodmap[map] - raise GrammarError("%s:%d: Duplicate rule %s. " % (file,line, m) + - "Previous definition at %s:%d" % (m.file, m.line)) - - # From this point on, everything is valid. Create a new Production instance - pnumber = len(self.Productions) - if not prodname in self.Nonterminals: - self.Nonterminals[prodname] = [ ] - - # Add the production number to Terminals and Nonterminals - for t in syms: - if t in self.Terminals: - self.Terminals[t].append(pnumber) - else: - if not t in self.Nonterminals: - self.Nonterminals[t] = [ ] - self.Nonterminals[t].append(pnumber) - - # Create a production and add it to the list of productions - p = Production(pnumber,prodname,syms,prodprec,func,file,line) - self.Productions.append(p) - self.Prodmap[map] = p - - # Add to the global productions list - try: - self.Prodnames[prodname].append(p) - except KeyError: - self.Prodnames[prodname] = [ p ] - return 0 - - # ----------------------------------------------------------------------------- - # set_start() - # - # Sets the starting symbol and creates the augmented grammar. Production - # rule 0 is S' -> start where start is the start symbol. - # ----------------------------------------------------------------------------- - - def set_start(self,start=None): - if not start: - start = self.Productions[1].name - if start not in self.Nonterminals: - raise GrammarError("start symbol %s undefined" % start) - self.Productions[0] = Production(0,"S'",[start]) - self.Nonterminals[start].append(0) - self.Start = start - - # ----------------------------------------------------------------------------- - # find_unreachable() - # - # Find all of the nonterminal symbols that can't be reached from the starting - # symbol. Returns a list of nonterminals that can't be reached. - # ----------------------------------------------------------------------------- - - def find_unreachable(self): - - # Mark all symbols that are reachable from a symbol s - def mark_reachable_from(s): - if reachable[s]: - # We've already reached symbol s. - return - reachable[s] = 1 - for p in self.Prodnames.get(s,[]): - for r in p.prod: - mark_reachable_from(r) - - reachable = { } - for s in list(self.Terminals) + list(self.Nonterminals): - reachable[s] = 0 - - mark_reachable_from( self.Productions[0].prod[0] ) - - return [s for s in list(self.Nonterminals) - if not reachable[s]] - - # ----------------------------------------------------------------------------- - # infinite_cycles() - # - # This function looks at the various parsing rules and tries to detect - # infinite recursion cycles (grammar rules where there is no possible way - # to derive a string of only terminals). - # ----------------------------------------------------------------------------- - - def infinite_cycles(self): - terminates = {} - - # Terminals: - for t in self.Terminals: - terminates[t] = 1 - - terminates['$end'] = 1 - - # Nonterminals: - - # Initialize to false: - for n in self.Nonterminals: - terminates[n] = 0 - - # Then propagate termination until no change: - while 1: - some_change = 0 - for (n,pl) in self.Prodnames.items(): - # Nonterminal n terminates iff any of its productions terminates. - for p in pl: - # Production p terminates iff all of its rhs symbols terminate. - for s in p.prod: - if not terminates[s]: - # The symbol s does not terminate, - # so production p does not terminate. - p_terminates = 0 - break - else: - # didn't break from the loop, - # so every symbol s terminates - # so production p terminates. - p_terminates = 1 - - if p_terminates: - # symbol n terminates! - if not terminates[n]: - terminates[n] = 1 - some_change = 1 - # Don't need to consider any more productions for this n. - break - - if not some_change: - break - - infinite = [] - for (s,term) in terminates.items(): - if not term: - if not s in self.Prodnames and not s in self.Terminals and s != 'error': - # s is used-but-not-defined, and we've already warned of that, - # so it would be overkill to say that it's also non-terminating. - pass - else: - infinite.append(s) - - return infinite - - - # ----------------------------------------------------------------------------- - # undefined_symbols() - # - # Find all symbols that were used the grammar, but not defined as tokens or - # grammar rules. Returns a list of tuples (sym, prod) where sym in the symbol - # and prod is the production where the symbol was used. - # ----------------------------------------------------------------------------- - def undefined_symbols(self): - result = [] - for p in self.Productions: - if not p: continue - - for s in p.prod: - if not s in self.Prodnames and not s in self.Terminals and s != 'error': - result.append((s,p)) - return result - - # ----------------------------------------------------------------------------- - # unused_terminals() - # - # Find all terminals that were defined, but not used by the grammar. Returns - # a list of all symbols. - # ----------------------------------------------------------------------------- - def unused_terminals(self): - unused_tok = [] - for s,v in self.Terminals.items(): - if s != 'error' and not v: - unused_tok.append(s) - - return unused_tok - - # ------------------------------------------------------------------------------ - # unused_rules() - # - # Find all grammar rules that were defined, but not used (maybe not reachable) - # Returns a list of productions. - # ------------------------------------------------------------------------------ - - def unused_rules(self): - unused_prod = [] - for s,v in self.Nonterminals.items(): - if not v: - p = self.Prodnames[s][0] - unused_prod.append(p) - return unused_prod - - # ----------------------------------------------------------------------------- - # unused_precedence() - # - # Returns a list of tuples (term,precedence) corresponding to precedence - # rules that were never used by the grammar. term is the name of the terminal - # on which precedence was applied and precedence is a string such as 'left' or - # 'right' corresponding to the type of precedence. - # ----------------------------------------------------------------------------- - - def unused_precedence(self): - unused = [] - for termname in self.Precedence: - if not (termname in self.Terminals or termname in self.UsedPrecedence): - unused.append((termname,self.Precedence[termname][0])) - - return unused - - # ------------------------------------------------------------------------- - # _first() - # - # Compute the value of FIRST1(beta) where beta is a tuple of symbols. - # - # During execution of compute_first1, the result may be incomplete. - # Afterward (e.g., when called from compute_follow()), it will be complete. - # ------------------------------------------------------------------------- - def _first(self,beta): - - # We are computing First(x1,x2,x3,...,xn) - result = [ ] - for x in beta: - x_produces_empty = 0 - - # Add all the non-<empty> symbols of First[x] to the result. - for f in self.First[x]: - if f == '<empty>': - x_produces_empty = 1 - else: - if f not in result: result.append(f) - - if x_produces_empty: - # We have to consider the next x in beta, - # i.e. stay in the loop. - pass - else: - # We don't have to consider any further symbols in beta. - break - else: - # There was no 'break' from the loop, - # so x_produces_empty was true for all x in beta, - # so beta produces empty as well. - result.append('<empty>') - - return result - - # ------------------------------------------------------------------------- - # compute_first() - # - # Compute the value of FIRST1(X) for all symbols - # ------------------------------------------------------------------------- - def compute_first(self): - if self.First: - return self.First - - # Terminals: - for t in self.Terminals: - self.First[t] = [t] - - self.First['$end'] = ['$end'] - - # Nonterminals: - - # Initialize to the empty set: - for n in self.Nonterminals: - self.First[n] = [] - - # Then propagate symbols until no change: - while 1: - some_change = 0 - for n in self.Nonterminals: - for p in self.Prodnames[n]: - for f in self._first(p.prod): - if f not in self.First[n]: - self.First[n].append( f ) - some_change = 1 - if not some_change: - break - - return self.First - - # --------------------------------------------------------------------- - # compute_follow() - # - # Computes all of the follow sets for every non-terminal symbol. The - # follow set is the set of all symbols that might follow a given - # non-terminal. See the Dragon book, 2nd Ed. p. 189. - # --------------------------------------------------------------------- - def compute_follow(self,start=None): - # If already computed, return the result - if self.Follow: - return self.Follow - - # If first sets not computed yet, do that first. - if not self.First: - self.compute_first() - - # Add '$end' to the follow list of the start symbol - for k in self.Nonterminals: - self.Follow[k] = [ ] - - if not start: - start = self.Productions[1].name - - self.Follow[start] = [ '$end' ] - - while 1: - didadd = 0 - for p in self.Productions[1:]: - # Here is the production set - for i in range(len(p.prod)): - B = p.prod[i] - if B in self.Nonterminals: - # Okay. We got a non-terminal in a production - fst = self._first(p.prod[i+1:]) - hasempty = 0 - for f in fst: - if f != '<empty>' and f not in self.Follow[B]: - self.Follow[B].append(f) - didadd = 1 - if f == '<empty>': - hasempty = 1 - if hasempty or i == (len(p.prod)-1): - # Add elements of follow(a) to follow(b) - for f in self.Follow[p.name]: - if f not in self.Follow[B]: - self.Follow[B].append(f) - didadd = 1 - if not didadd: break - return self.Follow - - - # ----------------------------------------------------------------------------- - # build_lritems() - # - # This function walks the list of productions and builds a complete set of the - # LR items. The LR items are stored in two ways: First, they are uniquely - # numbered and placed in the list _lritems. Second, a linked list of LR items - # is built for each production. For example: - # - # E -> E PLUS E - # - # Creates the list - # - # [E -> . E PLUS E, E -> E . PLUS E, E -> E PLUS . E, E -> E PLUS E . ] - # ----------------------------------------------------------------------------- - - def build_lritems(self): - for p in self.Productions: - lastlri = p - i = 0 - lr_items = [] - while 1: - if i > len(p): - lri = None - else: - lri = LRItem(p,i) - # Precompute the list of productions immediately following - try: - lri.lr_after = self.Prodnames[lri.prod[i+1]] - except (IndexError,KeyError): - lri.lr_after = [] - try: - lri.lr_before = lri.prod[i-1] - except IndexError: - lri.lr_before = None - - lastlri.lr_next = lri - if not lri: break - lr_items.append(lri) - lastlri = lri - i += 1 - p.lr_items = lr_items - -# ----------------------------------------------------------------------------- -# == Class LRTable == -# -# This basic class represents a basic table of LR parsing information. -# Methods for generating the tables are not defined here. They are defined -# in the derived class LRGeneratedTable. -# ----------------------------------------------------------------------------- - -class VersionError(YaccError): pass - -class LRTable(object): - def __init__(self): - self.lr_action = None - self.lr_goto = None - self.lr_productions = None - self.lr_method = None - - def read_table(self,module): - if isinstance(module,types.ModuleType): - parsetab = module - else: - if sys.version_info[0] < 3: - exec("import %s as parsetab" % module) - else: - env = { } - exec("import %s as parsetab" % module, env, env) - parsetab = env['parsetab'] - - if parsetab._tabversion != __tabversion__: - raise VersionError("yacc table file version is out of date") - - self.lr_action = parsetab._lr_action - self.lr_goto = parsetab._lr_goto - - self.lr_productions = [] - for p in parsetab._lr_productions: - self.lr_productions.append(MiniProduction(*p)) - - self.lr_method = parsetab._lr_method - return parsetab._lr_signature - - def read_pickle(self,filename): - try: - import cPickle as pickle - except ImportError: - import pickle - - in_f = open(filename,"rb") - - tabversion = pickle.load(in_f) - if tabversion != __tabversion__: - raise VersionError("yacc table file version is out of date") - self.lr_method = pickle.load(in_f) - signature = pickle.load(in_f) - self.lr_action = pickle.load(in_f) - self.lr_goto = pickle.load(in_f) - productions = pickle.load(in_f) - - self.lr_productions = [] - for p in productions: - self.lr_productions.append(MiniProduction(*p)) - - in_f.close() - return signature - - # Bind all production function names to callable objects in pdict - def bind_callables(self,pdict): - for p in self.lr_productions: - p.bind(pdict) - -# ----------------------------------------------------------------------------- -# === LR Generator === -# -# The following classes and functions are used to generate LR parsing tables on -# a grammar. -# ----------------------------------------------------------------------------- - -# ----------------------------------------------------------------------------- -# digraph() -# traverse() -# -# The following two functions are used to compute set valued functions -# of the form: -# -# F(x) = F'(x) U U{F(y) | x R y} -# -# This is used to compute the values of Read() sets as well as FOLLOW sets -# in LALR(1) generation. -# -# Inputs: X - An input set -# R - A relation -# FP - Set-valued function -# ------------------------------------------------------------------------------ - -def digraph(X,R,FP): - N = { } - for x in X: - N[x] = 0 - stack = [] - F = { } - for x in X: - if N[x] == 0: traverse(x,N,stack,F,X,R,FP) - return F - -def traverse(x,N,stack,F,X,R,FP): - stack.append(x) - d = len(stack) - N[x] = d - F[x] = FP(x) # F(X) <- F'(x) - - rel = R(x) # Get y's related to x - for y in rel: - if N[y] == 0: - traverse(y,N,stack,F,X,R,FP) - N[x] = min(N[x],N[y]) - for a in F.get(y,[]): - if a not in F[x]: F[x].append(a) - if N[x] == d: - N[stack[-1]] = MAXINT - F[stack[-1]] = F[x] - element = stack.pop() - while element != x: - N[stack[-1]] = MAXINT - F[stack[-1]] = F[x] - element = stack.pop() - -class LALRError(YaccError): pass - -# ----------------------------------------------------------------------------- -# == LRGeneratedTable == -# -# This class implements the LR table generation algorithm. There are no -# public methods except for write() -# ----------------------------------------------------------------------------- - -class LRGeneratedTable(LRTable): - def __init__(self,grammar,method='LALR',log=None): - if method not in ['SLR','LALR']: - raise LALRError("Unsupported method %s" % method) - - self.grammar = grammar - self.lr_method = method - - # Set up the logger - if not log: - log = NullLogger() - self.log = log - - # Internal attributes - self.lr_action = {} # Action table - self.lr_goto = {} # Goto table - self.lr_productions = grammar.Productions # Copy of grammar Production array - self.lr_goto_cache = {} # Cache of computed gotos - self.lr0_cidhash = {} # Cache of closures - - self._add_count = 0 # Internal counter used to detect cycles - - # Diagonistic information filled in by the table generator - self.sr_conflict = 0 - self.rr_conflict = 0 - self.conflicts = [] # List of conflicts - - self.sr_conflicts = [] - self.rr_conflicts = [] - - # Build the tables - self.grammar.build_lritems() - self.grammar.compute_first() - self.grammar.compute_follow() - self.lr_parse_table() - - # Compute the LR(0) closure operation on I, where I is a set of LR(0) items. - - def lr0_closure(self,I): - self._add_count += 1 - - # Add everything in I to J - J = I[:] - didadd = 1 - while didadd: - didadd = 0 - for j in J: - for x in j.lr_after: - if getattr(x,"lr0_added",0) == self._add_count: continue - # Add B --> .G to J - J.append(x.lr_next) - x.lr0_added = self._add_count - didadd = 1 - - return J - - # Compute the LR(0) goto function goto(I,X) where I is a set - # of LR(0) items and X is a grammar symbol. This function is written - # in a way that guarantees uniqueness of the generated goto sets - # (i.e. the same goto set will never be returned as two different Python - # objects). With uniqueness, we can later do fast set comparisons using - # id(obj) instead of element-wise comparison. - - def lr0_goto(self,I,x): - # First we look for a previously cached entry - g = self.lr_goto_cache.get((id(I),x),None) - if g: return g - - # Now we generate the goto set in a way that guarantees uniqueness - # of the result - - s = self.lr_goto_cache.get(x,None) - if not s: - s = { } - self.lr_goto_cache[x] = s - - gs = [ ] - for p in I: - n = p.lr_next - if n and n.lr_before == x: - s1 = s.get(id(n),None) - if not s1: - s1 = { } - s[id(n)] = s1 - gs.append(n) - s = s1 - g = s.get('$end',None) - if not g: - if gs: - g = self.lr0_closure(gs) - s['$end'] = g - else: - s['$end'] = gs - self.lr_goto_cache[(id(I),x)] = g - return g - - # Compute the LR(0) sets of item function - def lr0_items(self): - - C = [ self.lr0_closure([self.grammar.Productions[0].lr_next]) ] - i = 0 - for I in C: - self.lr0_cidhash[id(I)] = i - i += 1 - - # Loop over the items in C and each grammar symbols - i = 0 - while i < len(C): - I = C[i] - i += 1 - - # Collect all of the symbols that could possibly be in the goto(I,X) sets - asyms = { } - for ii in I: - for s in ii.usyms: - asyms[s] = None - - for x in asyms: - g = self.lr0_goto(I,x) - if not g: continue - if id(g) in self.lr0_cidhash: continue - self.lr0_cidhash[id(g)] = len(C) - C.append(g) - - return C - - # ----------------------------------------------------------------------------- - # ==== LALR(1) Parsing ==== - # - # LALR(1) parsing is almost exactly the same as SLR except that instead of - # relying upon Follow() sets when performing reductions, a more selective - # lookahead set that incorporates the state of the LR(0) machine is utilized. - # Thus, we mainly just have to focus on calculating the lookahead sets. - # - # The method used here is due to DeRemer and Pennelo (1982). - # - # DeRemer, F. L., and T. J. Pennelo: "Efficient Computation of LALR(1) - # Lookahead Sets", ACM Transactions on Programming Languages and Systems, - # Vol. 4, No. 4, Oct. 1982, pp. 615-649 - # - # Further details can also be found in: - # - # J. Tremblay and P. Sorenson, "The Theory and Practice of Compiler Writing", - # McGraw-Hill Book Company, (1985). - # - # ----------------------------------------------------------------------------- - - # ----------------------------------------------------------------------------- - # compute_nullable_nonterminals() - # - # Creates a dictionary containing all of the non-terminals that might produce - # an empty production. - # ----------------------------------------------------------------------------- - - def compute_nullable_nonterminals(self): - nullable = {} - num_nullable = 0 - while 1: - for p in self.grammar.Productions[1:]: - if p.len == 0: - nullable[p.name] = 1 - continue - for t in p.prod: - if not t in nullable: break - else: - nullable[p.name] = 1 - if len(nullable) == num_nullable: break - num_nullable = len(nullable) - return nullable - - # ----------------------------------------------------------------------------- - # find_nonterminal_trans(C) - # - # Given a set of LR(0) items, this functions finds all of the non-terminal - # transitions. These are transitions in which a dot appears immediately before - # a non-terminal. Returns a list of tuples of the form (state,N) where state - # is the state number and N is the nonterminal symbol. - # - # The input C is the set of LR(0) items. - # ----------------------------------------------------------------------------- - - def find_nonterminal_transitions(self,C): - trans = [] - for state in range(len(C)): - for p in C[state]: - if p.lr_index < p.len - 1: - t = (state,p.prod[p.lr_index+1]) - if t[1] in self.grammar.Nonterminals: - if t not in trans: trans.append(t) - state = state + 1 - return trans - - # ----------------------------------------------------------------------------- - # dr_relation() - # - # Computes the DR(p,A) relationships for non-terminal transitions. The input - # is a tuple (state,N) where state is a number and N is a nonterminal symbol. - # - # Returns a list of terminals. - # ----------------------------------------------------------------------------- - - def dr_relation(self,C,trans,nullable): - dr_set = { } - state,N = trans - terms = [] - - g = self.lr0_goto(C[state],N) - for p in g: - if p.lr_index < p.len - 1: - a = p.prod[p.lr_index+1] - if a in self.grammar.Terminals: - if a not in terms: terms.append(a) - - # This extra bit is to handle the start state - if state == 0 and N == self.grammar.Productions[0].prod[0]: - terms.append('$end') - - return terms - - # ----------------------------------------------------------------------------- - # reads_relation() - # - # Computes the READS() relation (p,A) READS (t,C). - # ----------------------------------------------------------------------------- - - def reads_relation(self,C, trans, empty): - # Look for empty transitions - rel = [] - state, N = trans - - g = self.lr0_goto(C[state],N) - j = self.lr0_cidhash.get(id(g),-1) - for p in g: - if p.lr_index < p.len - 1: - a = p.prod[p.lr_index + 1] - if a in empty: - rel.append((j,a)) - - return rel - - # ----------------------------------------------------------------------------- - # compute_lookback_includes() - # - # Determines the lookback and includes relations - # - # LOOKBACK: - # - # This relation is determined by running the LR(0) state machine forward. - # For example, starting with a production "N : . A B C", we run it forward - # to obtain "N : A B C ." We then build a relationship between this final - # state and the starting state. These relationships are stored in a dictionary - # lookdict. - # - # INCLUDES: - # - # Computes the INCLUDE() relation (p,A) INCLUDES (p',B). - # - # This relation is used to determine non-terminal transitions that occur - # inside of other non-terminal transition states. (p,A) INCLUDES (p', B) - # if the following holds: - # - # B -> LAT, where T -> epsilon and p' -L-> p - # - # L is essentially a prefix (which may be empty), T is a suffix that must be - # able to derive an empty string. State p' must lead to state p with the string L. - # - # ----------------------------------------------------------------------------- - - def compute_lookback_includes(self,C,trans,nullable): - - lookdict = {} # Dictionary of lookback relations - includedict = {} # Dictionary of include relations - - # Make a dictionary of non-terminal transitions - dtrans = {} - for t in trans: - dtrans[t] = 1 - - # Loop over all transitions and compute lookbacks and includes - for state,N in trans: - lookb = [] - includes = [] - for p in C[state]: - if p.name != N: continue - - # Okay, we have a name match. We now follow the production all the way - # through the state machine until we get the . on the right hand side - - lr_index = p.lr_index - j = state - while lr_index < p.len - 1: - lr_index = lr_index + 1 - t = p.prod[lr_index] - - # Check to see if this symbol and state are a non-terminal transition - if (j,t) in dtrans: - # Yes. Okay, there is some chance that this is an includes relation - # the only way to know for certain is whether the rest of the - # production derives empty - - li = lr_index + 1 - while li < p.len: - if p.prod[li] in self.grammar.Terminals: break # No forget it - if not p.prod[li] in nullable: break - li = li + 1 - else: - # Appears to be a relation between (j,t) and (state,N) - includes.append((j,t)) - - g = self.lr0_goto(C[j],t) # Go to next set - j = self.lr0_cidhash.get(id(g),-1) # Go to next state - - # When we get here, j is the final state, now we have to locate the production - for r in C[j]: - if r.name != p.name: continue - if r.len != p.len: continue - i = 0 - # This look is comparing a production ". A B C" with "A B C ." - while i < r.lr_index: - if r.prod[i] != p.prod[i+1]: break - i = i + 1 - else: - lookb.append((j,r)) - for i in includes: - if not i in includedict: includedict[i] = [] - includedict[i].append((state,N)) - lookdict[(state,N)] = lookb - - return lookdict,includedict - - # ----------------------------------------------------------------------------- - # compute_read_sets() - # - # Given a set of LR(0) items, this function computes the read sets. - # - # Inputs: C = Set of LR(0) items - # ntrans = Set of nonterminal transitions - # nullable = Set of empty transitions - # - # Returns a set containing the read sets - # ----------------------------------------------------------------------------- - - def compute_read_sets(self,C, ntrans, nullable): - FP = lambda x: self.dr_relation(C,x,nullable) - R = lambda x: self.reads_relation(C,x,nullable) - F = digraph(ntrans,R,FP) - return F - - # ----------------------------------------------------------------------------- - # compute_follow_sets() - # - # Given a set of LR(0) items, a set of non-terminal transitions, a readset, - # and an include set, this function computes the follow sets - # - # Follow(p,A) = Read(p,A) U U {Follow(p',B) | (p,A) INCLUDES (p',B)} - # - # Inputs: - # ntrans = Set of nonterminal transitions - # readsets = Readset (previously computed) - # inclsets = Include sets (previously computed) - # - # Returns a set containing the follow sets - # ----------------------------------------------------------------------------- - - def compute_follow_sets(self,ntrans,readsets,inclsets): - FP = lambda x: readsets[x] - R = lambda x: inclsets.get(x,[]) - F = digraph(ntrans,R,FP) - return F - - # ----------------------------------------------------------------------------- - # add_lookaheads() - # - # Attaches the lookahead symbols to grammar rules. - # - # Inputs: lookbacks - Set of lookback relations - # followset - Computed follow set - # - # This function directly attaches the lookaheads to productions contained - # in the lookbacks set - # ----------------------------------------------------------------------------- - - def add_lookaheads(self,lookbacks,followset): - for trans,lb in lookbacks.items(): - # Loop over productions in lookback - for state,p in lb: - if not state in p.lookaheads: - p.lookaheads[state] = [] - f = followset.get(trans,[]) - for a in f: - if a not in p.lookaheads[state]: p.lookaheads[state].append(a) - - # ----------------------------------------------------------------------------- - # add_lalr_lookaheads() - # - # This function does all of the work of adding lookahead information for use - # with LALR parsing - # ----------------------------------------------------------------------------- - - def add_lalr_lookaheads(self,C): - # Determine all of the nullable nonterminals - nullable = self.compute_nullable_nonterminals() - - # Find all non-terminal transitions - trans = self.find_nonterminal_transitions(C) - - # Compute read sets - readsets = self.compute_read_sets(C,trans,nullable) - - # Compute lookback/includes relations - lookd, included = self.compute_lookback_includes(C,trans,nullable) - - # Compute LALR FOLLOW sets - followsets = self.compute_follow_sets(trans,readsets,included) - - # Add all of the lookaheads - self.add_lookaheads(lookd,followsets) - - # ----------------------------------------------------------------------------- - # lr_parse_table() - # - # This function constructs the parse tables for SLR or LALR - # ----------------------------------------------------------------------------- - def lr_parse_table(self): - Productions = self.grammar.Productions - Precedence = self.grammar.Precedence - goto = self.lr_goto # Goto array - action = self.lr_action # Action array - log = self.log # Logger for output - - actionp = { } # Action production array (temporary) - - log.info("Parsing method: %s", self.lr_method) - - # Step 1: Construct C = { I0, I1, ... IN}, collection of LR(0) items - # This determines the number of states - - C = self.lr0_items() - - if self.lr_method == 'LALR': - self.add_lalr_lookaheads(C) - - # Build the parser table, state by state - st = 0 - for I in C: - # Loop over each production in I - actlist = [ ] # List of actions - st_action = { } - st_actionp = { } - st_goto = { } - log.info("") - log.info("state %d", st) - log.info("") - for p in I: - log.info(" (%d) %s", p.number, str(p)) - log.info("") - - for p in I: - if p.len == p.lr_index + 1: - if p.name == "S'": - # Start symbol. Accept! - st_action["$end"] = 0 - st_actionp["$end"] = p - else: - # We are at the end of a production. Reduce! - if self.lr_method == 'LALR': - laheads = p.lookaheads[st] - else: - laheads = self.grammar.Follow[p.name] - for a in laheads: - actlist.append((a,p,"reduce using rule %d (%s)" % (p.number,p))) - r = st_action.get(a,None) - if r is not None: - # Whoa. Have a shift/reduce or reduce/reduce conflict - if r > 0: - # Need to decide on shift or reduce here - # By default we favor shifting. Need to add - # some precedence rules here. - sprec,slevel = Productions[st_actionp[a].number].prec - rprec,rlevel = Precedence.get(a,('right',0)) - if (slevel < rlevel) or ((slevel == rlevel) and (rprec == 'left')): - # We really need to reduce here. - st_action[a] = -p.number - st_actionp[a] = p - if not slevel and not rlevel: - log.info(" ! shift/reduce conflict for %s resolved as reduce",a) - self.sr_conflicts.append((st,a,'reduce')) - Productions[p.number].reduced += 1 - elif (slevel == rlevel) and (rprec == 'nonassoc'): - st_action[a] = None - else: - # Hmmm. Guess we'll keep the shift - if not rlevel: - log.info(" ! shift/reduce conflict for %s resolved as shift",a) - self.sr_conflicts.append((st,a,'shift')) - elif r < 0: - # Reduce/reduce conflict. In this case, we favor the rule - # that was defined first in the grammar file - oldp = Productions[-r] - pp = Productions[p.number] - if oldp.line > pp.line: - st_action[a] = -p.number - st_actionp[a] = p - chosenp,rejectp = pp,oldp - Productions[p.number].reduced += 1 - Productions[oldp.number].reduced -= 1 - else: - chosenp,rejectp = oldp,pp - self.rr_conflicts.append((st,chosenp,rejectp)) - log.info(" ! reduce/reduce conflict for %s resolved using rule %d (%s)", a,st_actionp[a].number, st_actionp[a]) - else: - raise LALRError("Unknown conflict in state %d" % st) - else: - st_action[a] = -p.number - st_actionp[a] = p - Productions[p.number].reduced += 1 - else: - i = p.lr_index - a = p.prod[i+1] # Get symbol right after the "." - if a in self.grammar.Terminals: - g = self.lr0_goto(I,a) - j = self.lr0_cidhash.get(id(g),-1) - if j >= 0: - # We are in a shift state - actlist.append((a,p,"shift and go to state %d" % j)) - r = st_action.get(a,None) - if r is not None: - # Whoa have a shift/reduce or shift/shift conflict - if r > 0: - if r != j: - raise LALRError("Shift/shift conflict in state %d" % st) - elif r < 0: - # Do a precedence check. - # - if precedence of reduce rule is higher, we reduce. - # - if precedence of reduce is same and left assoc, we reduce. - # - otherwise we shift - rprec,rlevel = Productions[st_actionp[a].number].prec - sprec,slevel = Precedence.get(a,('right',0)) - if (slevel > rlevel) or ((slevel == rlevel) and (rprec == 'right')): - # We decide to shift here... highest precedence to shift - Productions[st_actionp[a].number].reduced -= 1 - st_action[a] = j - st_actionp[a] = p - if not rlevel: - log.info(" ! shift/reduce conflict for %s resolved as shift",a) - self.sr_conflicts.append((st,a,'shift')) - elif (slevel == rlevel) and (rprec == 'nonassoc'): - st_action[a] = None - else: - # Hmmm. Guess we'll keep the reduce - if not slevel and not rlevel: - log.info(" ! shift/reduce conflict for %s resolved as reduce",a) - self.sr_conflicts.append((st,a,'reduce')) - - else: - raise LALRError("Unknown conflict in state %d" % st) - else: - st_action[a] = j - st_actionp[a] = p - - # Print the actions associated with each terminal - _actprint = { } - for a,p,m in actlist: - if a in st_action: - if p is st_actionp[a]: - log.info(" %-15s %s",a,m) - _actprint[(a,m)] = 1 - log.info("") - # Print the actions that were not used. (debugging) - not_used = 0 - for a,p,m in actlist: - if a in st_action: - if p is not st_actionp[a]: - if not (a,m) in _actprint: - log.debug(" ! %-15s [ %s ]",a,m) - not_used = 1 - _actprint[(a,m)] = 1 - if not_used: - log.debug("") - - # Construct the goto table for this state - - nkeys = { } - for ii in I: - for s in ii.usyms: - if s in self.grammar.Nonterminals: - nkeys[s] = None - for n in nkeys: - g = self.lr0_goto(I,n) - j = self.lr0_cidhash.get(id(g),-1) - if j >= 0: - st_goto[n] = j - log.info(" %-30s shift and go to state %d",n,j) - - action[st] = st_action - actionp[st] = st_actionp - goto[st] = st_goto - st += 1 - - - # ----------------------------------------------------------------------------- - # write() - # - # This function writes the LR parsing tables to a file - # ----------------------------------------------------------------------------- - - def write_table(self,modulename,outputdir='',signature=""): - basemodulename = modulename.split(".")[-1] - filename = os.path.join(outputdir,basemodulename) + ".py" - try: - f = open(filename,"w") - - f.write(""" -# %s -# This file is automatically generated. Do not edit. -_tabversion = %r - -_lr_method = %r - -_lr_signature = %r - """ % (filename, __tabversion__, self.lr_method, signature)) - - # Change smaller to 0 to go back to original tables - smaller = 1 - - # Factor out names to try and make smaller - if smaller: - items = { } - - for s,nd in self.lr_action.items(): - for name,v in nd.items(): - i = items.get(name) - if not i: - i = ([],[]) - items[name] = i - i[0].append(s) - i[1].append(v) - - f.write("\n_lr_action_items = {") - for k,v in items.items(): - f.write("%r:([" % k) - for i in v[0]: - f.write("%r," % i) - f.write("],[") - for i in v[1]: - f.write("%r," % i) - - f.write("]),") - f.write("}\n") - - f.write(""" -_lr_action = { } -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = { } - _lr_action[_x][_k] = _y -del _lr_action_items -""") - - else: - f.write("\n_lr_action = { "); - for k,v in self.lr_action.items(): - f.write("(%r,%r):%r," % (k[0],k[1],v)) - f.write("}\n"); - - if smaller: - # Factor out names to try and make smaller - items = { } - - for s,nd in self.lr_goto.items(): - for name,v in nd.items(): - i = items.get(name) - if not i: - i = ([],[]) - items[name] = i - i[0].append(s) - i[1].append(v) - - f.write("\n_lr_goto_items = {") - for k,v in items.items(): - f.write("%r:([" % k) - for i in v[0]: - f.write("%r," % i) - f.write("],[") - for i in v[1]: - f.write("%r," % i) - - f.write("]),") - f.write("}\n") - - f.write(""" -_lr_goto = { } -for _k, _v in _lr_goto_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_goto: _lr_goto[_x] = { } - _lr_goto[_x][_k] = _y -del _lr_goto_items -""") - else: - f.write("\n_lr_goto = { "); - for k,v in self.lr_goto.items(): - f.write("(%r,%r):%r," % (k[0],k[1],v)) - f.write("}\n"); - - # Write production table - f.write("_lr_productions = [\n") - for p in self.lr_productions: - if p.func: - f.write(" (%r,%r,%d,%r,%r,%d),\n" % (p.str,p.name, p.len, p.func,p.file,p.line)) - else: - f.write(" (%r,%r,%d,None,None,None),\n" % (str(p),p.name, p.len)) - f.write("]\n") - f.close() - - except IOError: - e = sys.exc_info()[1] - sys.stderr.write("Unable to create '%s'\n" % filename) - sys.stderr.write(str(e)+"\n") - return - - - # ----------------------------------------------------------------------------- - # pickle_table() - # - # This function pickles the LR parsing tables to a supplied file object - # ----------------------------------------------------------------------------- - - def pickle_table(self,filename,signature=""): - try: - import cPickle as pickle - except ImportError: - import pickle - outf = open(filename,"wb") - pickle.dump(__tabversion__,outf,pickle_protocol) - pickle.dump(self.lr_method,outf,pickle_protocol) - pickle.dump(signature,outf,pickle_protocol) - pickle.dump(self.lr_action,outf,pickle_protocol) - pickle.dump(self.lr_goto,outf,pickle_protocol) - - outp = [] - for p in self.lr_productions: - if p.func: - outp.append((p.str,p.name, p.len, p.func,p.file,p.line)) - else: - outp.append((str(p),p.name,p.len,None,None,None)) - pickle.dump(outp,outf,pickle_protocol) - outf.close() - -# ----------------------------------------------------------------------------- -# === INTROSPECTION === -# -# The following functions and classes are used to implement the PLY -# introspection features followed by the yacc() function itself. -# ----------------------------------------------------------------------------- - -# ----------------------------------------------------------------------------- -# get_caller_module_dict() -# -# This function returns a dictionary containing all of the symbols defined within -# a caller further down the call stack. This is used to get the environment -# associated with the yacc() call if none was provided. -# ----------------------------------------------------------------------------- - -def get_caller_module_dict(levels): - try: - raise RuntimeError - except RuntimeError: - e,b,t = sys.exc_info() - f = t.tb_frame - while levels > 0: - f = f.f_back - levels -= 1 - ldict = f.f_globals.copy() - if f.f_globals != f.f_locals: - ldict.update(f.f_locals) - - return ldict - -# ----------------------------------------------------------------------------- -# parse_grammar() -# -# This takes a raw grammar rule string and parses it into production data -# ----------------------------------------------------------------------------- -def parse_grammar(doc,file,line): - grammar = [] - # Split the doc string into lines - pstrings = doc.splitlines() - lastp = None - dline = line - for ps in pstrings: - dline += 1 - p = ps.split() - if not p: continue - try: - if p[0] == '|': - # This is a continuation of a previous rule - if not lastp: - raise SyntaxError("%s:%d: Misplaced '|'" % (file,dline)) - prodname = lastp - syms = p[1:] - else: - prodname = p[0] - lastp = prodname - syms = p[2:] - assign = p[1] - if assign != ':' and assign != '::=': - raise SyntaxError("%s:%d: Syntax error. Expected ':'" % (file,dline)) - - grammar.append((file,dline,prodname,syms)) - except SyntaxError: - raise - except Exception: - raise SyntaxError("%s:%d: Syntax error in rule '%s'" % (file,dline,ps.strip())) - - return grammar - -# ----------------------------------------------------------------------------- -# ParserReflect() -# -# This class represents information extracted for building a parser including -# start symbol, error function, tokens, precedence list, action functions, -# etc. -# ----------------------------------------------------------------------------- -class ParserReflect(object): - def __init__(self,pdict,log=None): - self.pdict = pdict - self.start = None - self.error_func = None - self.tokens = None - self.files = {} - self.grammar = [] - self.error = 0 - - if log is None: - self.log = PlyLogger(sys.stderr) - else: - self.log = log - - # Get all of the basic information - def get_all(self): - self.get_start() - self.get_error_func() - self.get_tokens() - self.get_precedence() - self.get_pfunctions() - - # Validate all of the information - def validate_all(self): - self.validate_start() - self.validate_error_func() - self.validate_tokens() - self.validate_precedence() - self.validate_pfunctions() - self.validate_files() - return self.error - - # Compute a signature over the grammar - def signature(self): - try: - from hashlib import md5 - except ImportError: - from md5 import md5 - try: - sig = md5() - if self.start: - sig.update(self.start.encode('latin-1')) - if self.prec: - sig.update("".join(["".join(p) for p in self.prec]).encode('latin-1')) - if self.tokens: - sig.update(" ".join(self.tokens).encode('latin-1')) - for f in self.pfuncs: - if f[3]: - sig.update(f[3].encode('latin-1')) - except (TypeError,ValueError): - pass - return sig.digest() - - # ----------------------------------------------------------------------------- - # validate_file() - # - # This method checks to see if there are duplicated p_rulename() functions - # in the parser module file. Without this function, it is really easy for - # users to make mistakes by cutting and pasting code fragments (and it's a real - # bugger to try and figure out why the resulting parser doesn't work). Therefore, - # we just do a little regular expression pattern matching of def statements - # to try and detect duplicates. - # ----------------------------------------------------------------------------- - - def validate_files(self): - # Match def p_funcname( - fre = re.compile(r'\s*def\s+(p_[a-zA-Z_0-9]*)\(') - - for filename in self.files.keys(): - base,ext = os.path.splitext(filename) - if ext != '.py': return 1 # No idea. Assume it's okay. - - try: - f = open(filename) - lines = f.readlines() - f.close() - except IOError: - continue - - counthash = { } - for linen,l in enumerate(lines): - linen += 1 - m = fre.match(l) - if m: - name = m.group(1) - prev = counthash.get(name) - if not prev: - counthash[name] = linen - else: - self.log.warning("%s:%d: Function %s redefined. Previously defined on line %d", filename,linen,name,prev) - - # Get the start symbol - def get_start(self): - self.start = self.pdict.get('start') - - # Validate the start symbol - def validate_start(self): - if self.start is not None: - if not isinstance(self.start,str): - self.log.error("'start' must be a string") - - # Look for error handler - def get_error_func(self): - self.error_func = self.pdict.get('p_error') - - # Validate the error function - def validate_error_func(self): - if self.error_func: - if isinstance(self.error_func,types.FunctionType): - ismethod = 0 - elif isinstance(self.error_func, types.MethodType): - ismethod = 1 - else: - self.log.error("'p_error' defined, but is not a function or method") - self.error = 1 - return - - eline = func_code(self.error_func).co_firstlineno - efile = func_code(self.error_func).co_filename - self.files[efile] = 1 - - if (func_code(self.error_func).co_argcount != 1+ismethod): - self.log.error("%s:%d: p_error() requires 1 argument",efile,eline) - self.error = 1 - - # Get the tokens map - def get_tokens(self): - tokens = self.pdict.get("tokens",None) - if not tokens: - self.log.error("No token list is defined") - self.error = 1 - return - - if not isinstance(tokens,(list, tuple)): - self.log.error("tokens must be a list or tuple") - self.error = 1 - return - - if not tokens: - self.log.error("tokens is empty") - self.error = 1 - return - - self.tokens = tokens - - # Validate the tokens - def validate_tokens(self): - # Validate the tokens. - if 'error' in self.tokens: - self.log.error("Illegal token name 'error'. Is a reserved word") - self.error = 1 - return - - terminals = {} - for n in self.tokens: - if n in terminals: - self.log.warning("Token '%s' multiply defined", n) - terminals[n] = 1 - - # Get the precedence map (if any) - def get_precedence(self): - self.prec = self.pdict.get("precedence",None) - - # Validate and parse the precedence map - def validate_precedence(self): - preclist = [] - if self.prec: - if not isinstance(self.prec,(list,tuple)): - self.log.error("precedence must be a list or tuple") - self.error = 1 - return - for level,p in enumerate(self.prec): - if not isinstance(p,(list,tuple)): - self.log.error("Bad precedence table") - self.error = 1 - return - - if len(p) < 2: - self.log.error("Malformed precedence entry %s. Must be (assoc, term, ..., term)",p) - self.error = 1 - return - assoc = p[0] - if not isinstance(assoc,str): - self.log.error("precedence associativity must be a string") - self.error = 1 - return - for term in p[1:]: - if not isinstance(term,str): - self.log.error("precedence items must be strings") - self.error = 1 - return - preclist.append((term,assoc,level+1)) - self.preclist = preclist - - # Get all p_functions from the grammar - def get_pfunctions(self): - p_functions = [] - for name, item in self.pdict.items(): - if name[:2] != 'p_': continue - if name == 'p_error': continue - if isinstance(item,(types.FunctionType,types.MethodType)): - line = func_code(item).co_firstlineno - file = func_code(item).co_filename - p_functions.append((line,file,name,item.__doc__)) - - # Sort all of the actions by line number - p_functions.sort() - self.pfuncs = p_functions - - - # Validate all of the p_functions - def validate_pfunctions(self): - grammar = [] - # Check for non-empty symbols - if len(self.pfuncs) == 0: - self.log.error("no rules of the form p_rulename are defined") - self.error = 1 - return - - for line, file, name, doc in self.pfuncs: - func = self.pdict[name] - if isinstance(func, types.MethodType): - reqargs = 2 - else: - reqargs = 1 - if func_code(func).co_argcount > reqargs: - self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,func.__name__) - self.error = 1 - elif func_code(func).co_argcount < reqargs: - self.log.error("%s:%d: Rule '%s' requires an argument",file,line,func.__name__) - self.error = 1 - elif not func.__doc__: - self.log.warning("%s:%d: No documentation string specified in function '%s' (ignored)",file,line,func.__name__) - else: - try: - parsed_g = parse_grammar(doc,file,line) - for g in parsed_g: - grammar.append((name, g)) - except SyntaxError: - e = sys.exc_info()[1] - self.log.error(str(e)) - self.error = 1 - - # Looks like a valid grammar rule - # Mark the file in which defined. - self.files[file] = 1 - - # Secondary validation step that looks for p_ definitions that are not functions - # or functions that look like they might be grammar rules. - - for n,v in self.pdict.items(): - if n[0:2] == 'p_' and isinstance(v, (types.FunctionType, types.MethodType)): continue - if n[0:2] == 't_': continue - if n[0:2] == 'p_' and n != 'p_error': - self.log.warning("'%s' not defined as a function", n) - if ((isinstance(v,types.FunctionType) and func_code(v).co_argcount == 1) or - (isinstance(v,types.MethodType) and func_code(v).co_argcount == 2)): - try: - doc = v.__doc__.split(" ") - if doc[1] == ':': - self.log.warning("%s:%d: Possible grammar rule '%s' defined without p_ prefix", - func_code(v).co_filename, func_code(v).co_firstlineno,n) - except Exception: - pass - - self.grammar = grammar - -# ----------------------------------------------------------------------------- -# yacc(module) -# -# Build a parser -# ----------------------------------------------------------------------------- - -def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, start=None, - check_recursion=1, optimize=0, write_tables=1, debugfile=debug_file,outputdir='', - debuglog=None, errorlog = None, picklefile=None): - - global parse # Reference to the parsing method of the last built parser - - # If pickling is enabled, table files are not created - - if picklefile: - write_tables = 0 - - if errorlog is None: - errorlog = PlyLogger(sys.stderr) - - # Get the module dictionary used for the parser - if module: - _items = [(k,getattr(module,k)) for k in dir(module)] - pdict = dict(_items) - else: - pdict = get_caller_module_dict(2) - - # Collect parser information from the dictionary - pinfo = ParserReflect(pdict,log=errorlog) - pinfo.get_all() - - if pinfo.error: - raise YaccError("Unable to build parser") - - # Check signature against table files (if any) - signature = pinfo.signature() - - # Read the tables - try: - lr = LRTable() - if picklefile: - read_signature = lr.read_pickle(picklefile) - else: - read_signature = lr.read_table(tabmodule) - if optimize or (read_signature == signature): - try: - lr.bind_callables(pinfo.pdict) - parser = LRParser(lr,pinfo.error_func) - parse = parser.parse - return parser - except Exception: - e = sys.exc_info()[1] - errorlog.warning("There was a problem loading the table file: %s", repr(e)) - except VersionError: - e = sys.exc_info() - errorlog.warning(str(e)) - except Exception: - pass - - if debuglog is None: - if debug: - debuglog = PlyLogger(open(debugfile,"w")) - else: - debuglog = NullLogger() - - debuglog.info("Created by PLY version %s (http://www.dabeaz.com/ply)", __version__) - - - errors = 0 - - # Validate the parser information - if pinfo.validate_all(): - raise YaccError("Unable to build parser") - - if not pinfo.error_func: - errorlog.warning("no p_error() function is defined") - - # Create a grammar object - grammar = Grammar(pinfo.tokens) - - # Set precedence level for terminals - for term, assoc, level in pinfo.preclist: - try: - grammar.set_precedence(term,assoc,level) - except GrammarError: - e = sys.exc_info()[1] - errorlog.warning("%s",str(e)) - - # Add productions to the grammar - for funcname, gram in pinfo.grammar: - file, line, prodname, syms = gram - try: - grammar.add_production(prodname,syms,funcname,file,line) - except GrammarError: - e = sys.exc_info()[1] - errorlog.error("%s",str(e)) - errors = 1 - - # Set the grammar start symbols - try: - if start is None: - grammar.set_start(pinfo.start) - else: - grammar.set_start(start) - except GrammarError: - e = sys.exc_info()[1] - errorlog.error(str(e)) - errors = 1 - - if errors: - raise YaccError("Unable to build parser") - - # Verify the grammar structure - undefined_symbols = grammar.undefined_symbols() - for sym, prod in undefined_symbols: - errorlog.error("%s:%d: Symbol '%s' used, but not defined as a token or a rule",prod.file,prod.line,sym) - errors = 1 - - unused_terminals = grammar.unused_terminals() - if unused_terminals: - debuglog.info("") - debuglog.info("Unused terminals:") - debuglog.info("") - for term in unused_terminals: - errorlog.warning("Token '%s' defined, but not used", term) - debuglog.info(" %s", term) - - # Print out all productions to the debug log - if debug: - debuglog.info("") - debuglog.info("Grammar") - debuglog.info("") - for n,p in enumerate(grammar.Productions): - debuglog.info("Rule %-5d %s", n, p) - - # Find unused non-terminals - unused_rules = grammar.unused_rules() - for prod in unused_rules: - errorlog.warning("%s:%d: Rule '%s' defined, but not used", prod.file, prod.line, prod.name) - - if len(unused_terminals) == 1: - errorlog.warning("There is 1 unused token") - if len(unused_terminals) > 1: - errorlog.warning("There are %d unused tokens", len(unused_terminals)) - - if len(unused_rules) == 1: - errorlog.warning("There is 1 unused rule") - if len(unused_rules) > 1: - errorlog.warning("There are %d unused rules", len(unused_rules)) - - if debug: - debuglog.info("") - debuglog.info("Terminals, with rules where they appear") - debuglog.info("") - terms = list(grammar.Terminals) - terms.sort() - for term in terms: - debuglog.info("%-20s : %s", term, " ".join([str(s) for s in grammar.Terminals[term]])) - - debuglog.info("") - debuglog.info("Nonterminals, with rules where they appear") - debuglog.info("") - nonterms = list(grammar.Nonterminals) - nonterms.sort() - for nonterm in nonterms: - debuglog.info("%-20s : %s", nonterm, " ".join([str(s) for s in grammar.Nonterminals[nonterm]])) - debuglog.info("") - - if check_recursion: - unreachable = grammar.find_unreachable() - for u in unreachable: - errorlog.warning("Symbol '%s' is unreachable",u) - - infinite = grammar.infinite_cycles() - for inf in infinite: - errorlog.error("Infinite recursion detected for symbol '%s'", inf) - errors = 1 - - unused_prec = grammar.unused_precedence() - for term, assoc in unused_prec: - errorlog.error("Precedence rule '%s' defined for unknown symbol '%s'", assoc, term) - errors = 1 - - if errors: - raise YaccError("Unable to build parser") - - # Run the LRGeneratedTable on the grammar - if debug: - errorlog.debug("Generating %s tables", method) - - lr = LRGeneratedTable(grammar,method,debuglog) - - if debug: - num_sr = len(lr.sr_conflicts) - - # Report shift/reduce and reduce/reduce conflicts - if num_sr == 1: - errorlog.warning("1 shift/reduce conflict") - elif num_sr > 1: - errorlog.warning("%d shift/reduce conflicts", num_sr) - - num_rr = len(lr.rr_conflicts) - if num_rr == 1: - errorlog.warning("1 reduce/reduce conflict") - elif num_rr > 1: - errorlog.warning("%d reduce/reduce conflicts", num_rr) - - # Write out conflicts to the output file - if debug and (lr.sr_conflicts or lr.rr_conflicts): - debuglog.warning("") - debuglog.warning("Conflicts:") - debuglog.warning("") - - for state, tok, resolution in lr.sr_conflicts: - debuglog.warning("shift/reduce conflict for %s in state %d resolved as %s", tok, state, resolution) - - already_reported = {} - for state, rule, rejected in lr.rr_conflicts: - if (state,id(rule),id(rejected)) in already_reported: - continue - debuglog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule) - debuglog.warning("rejected rule (%s) in state %d", rejected,state) - errorlog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule) - errorlog.warning("rejected rule (%s) in state %d", rejected, state) - already_reported[state,id(rule),id(rejected)] = 1 - - warned_never = [] - for state, rule, rejected in lr.rr_conflicts: - if not rejected.reduced and (rejected not in warned_never): - debuglog.warning("Rule (%s) is never reduced", rejected) - errorlog.warning("Rule (%s) is never reduced", rejected) - warned_never.append(rejected) - - # Write the table file if requested - if write_tables: - lr.write_table(tabmodule,outputdir,signature) - - # Write a pickled version of the tables - if picklefile: - lr.pickle_table(picklefile,signature) - - # Build the parser - lr.bind_callables(pinfo.pdict) - parser = LRParser(lr,pinfo.error_func) - - parse = parser.parse - return parser diff --git a/src/components/script/dom/bindings/codegen/pythonpath.py b/src/components/script/dom/bindings/codegen/pythonpath.py deleted file mode 100644 index 49b2d2f740f..00000000000 --- a/src/components/script/dom/bindings/codegen/pythonpath.py +++ /dev/null @@ -1,60 +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/. - -""" -Run a python script, adding extra directories to the python path. -""" - - -def main(args): - def usage(): - print >>sys.stderr, "pythonpath.py -I directory script.py [args...]" - sys.exit(150) - - paths = [] - - while True: - try: - arg = args[0] - except IndexError: - usage() - - if arg == '-I': - args.pop(0) - try: - path = args.pop(0) - except IndexError: - usage() - - paths.append(os.path.abspath(path)) - continue - - if arg.startswith('-I'): - paths.append(os.path.abspath(args.pop(0)[2:])) - continue - - if arg.startswith('-D'): - os.chdir(args.pop(0)[2:]) - continue - - break - - script = args[0] - - sys.path[0:0] = [os.path.abspath(os.path.dirname(script))] + paths - sys.argv = args - sys.argc = len(args) - - frozenglobals['__name__'] = '__main__' - frozenglobals['__file__'] = script - - execfile(script, frozenglobals) - -# Freeze scope here ... why this makes things work I have no idea ... -frozenglobals = globals() - -import sys, os - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/src/components/script/dom/bindings/codegen/stubgenerator/Skeleton.cpp b/src/components/script/dom/bindings/codegen/stubgenerator/Skeleton.cpp deleted file mode 100644 index dfa17d23400..00000000000 --- a/src/components/script/dom/bindings/codegen/stubgenerator/Skeleton.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 "Skeleton.h" -#include "mozilla/dom/SkeletonBinding.h" -#include "nsContentUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(Skeleton) -NS_IMPL_CYCLE_COLLECTING_ADDREF(Skeleton) -NS_IMPL_CYCLE_COLLECTING_RELEASE(Skeleton) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Skeleton) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -Skeleton::Skeleton() -{ - SetIsDOMBinding(); -} - -Skeleton::~Skeleton() -{ -} - -JSObject* -Skeleton::WrapObject(JSContext* aCx, JSObject* aScope, - bool* aTriedToWrap) -{ - return SkeletonBinding::Wrap(aCx, aScope, this, aTriedToWrap); -} - -} -} - diff --git a/src/components/script/dom/bindings/codegen/stubgenerator/Skeleton.h b/src/components/script/dom/bindings/codegen/stubgenerator/Skeleton.h deleted file mode 100644 index 286cff9af4a..00000000000 --- a/src/components/script/dom/bindings/codegen/stubgenerator/Skeleton.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#pragma once - -#include "nsWrapperCache.h" -#include "nsCycleCollectionParticipant.h" -#include "mozilla/Attributes.h" - -struct JSContext; - -namespace mozilla { -namespace dom { - -class Skeleton MOZ_FINAL : public nsISupports, - public nsWrapperCache -{ -public: - Skeleton(); - ~Skeleton(); - - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Skeleton) - - void* GetParentObject() const - { - // TODO: return something sensible here, and change the return type - return somethingSensible; - } - - virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope, - bool* aTriedToWrap); -}; - -} -} - diff --git a/src/components/script/dom/bindings/codegen/stubgenerator/generate.sh b/src/components/script/dom/bindings/codegen/stubgenerator/generate.sh deleted file mode 100644 index 52577f6f42f..00000000000 --- a/src/components/script/dom/bindings/codegen/stubgenerator/generate.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -# This script creates a skeleton implementation for a C++ class which -# implements a Web IDL interface. - -# This script is released into the public domain. - -if [ -z "$1" ]; then - echo usage: ./generate.sh ClassName - exit 1 -fi - -expression="s/Skeleton/$1/g" - -sed "$expression" < Skeleton.h > "$1.h" -sed "$expression" < Skeleton.cpp > "$1.cpp" - diff --git a/src/components/script/dom/bindings/codegen/test/Makefile.in b/src/components/script/dom/bindings/codegen/test/Makefile.in deleted file mode 100644 index d8104db5ffd..00000000000 --- a/src/components/script/dom/bindings/codegen/test/Makefile.in +++ /dev/null @@ -1,87 +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/. - -DEPTH = @DEPTH@ -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ -relativesrcdir = @relativesrcdir@ - -MODULE = dom -LIBRARY_NAME = dombindings_test_s -LIBXUL_LIBRARY = 1 -FORCE_STATIC_LIB = 1 -# Do NOT export this library. We don't actually want our test code -# being added to libxul or anything. - -include $(DEPTH)/config/autoconf.mk - -# Need this to find all our DOM source files. -include $(topsrcdir)/dom/dom-config.mk - -# And need this for $(test_webidl_files) -include $(topsrcdir)/dom/webidl/WebIDL.mk - -# But the webidl actually lives in our parent dir -test_webidl_files := $(addprefix ../,$(test_webidl_files)) - -CPPSRCS := $(subst .webidl,Binding.cpp,$(test_webidl_files)) - -LOCAL_INCLUDES += \ - -I$(topsrcdir)/js/xpconnect/src \ - -I$(topsrcdir)/js/xpconnect/wrappers \ - -I$(topsrcdir)/dom/bindings \ - $(NULL) - - -# If you change bindinggen_dependencies here, change it in -# dom/bindings/Makefile.in too. But note that we include ../Makefile -# here manually, since $(GLOBAL_DEPS) won't cover it. -bindinggen_dependencies := \ - ../BindingGen.py \ - ../Bindings.conf \ - ../Configuration.py \ - ../Codegen.py \ - ../parser/WebIDL.py \ - ../ParserResults.pkl \ - ../Makefile \ - $(GLOBAL_DEPS) \ - $(NULL) - -MOCHITEST_FILES := \ - test_bug773326.html \ - test_enums.html \ - test_integers.html \ - test_interfaceToString.html \ - test_lookupGetter.html \ - test_InstanceOf.html \ - test_traceProtos.html \ - test_forOf.html \ - forOf_iframe.html \ - test_sequence_wrapping.html \ - file_bug775543.html \ - test_bug788369.html \ - $(NULL) - -MOCHITEST_CHROME_FILES = \ - test_bug775543.html \ - $(NULL) - -# Include rules.mk before any of our targets so our first target is coming from -# rules.mk and running make with no target in this dir does the right thing. -include $(topsrcdir)/config/rules.mk - -$(CPPSRCS): ../%Binding.cpp: $(bindinggen_dependencies) \ - ../%.webidl \ - $(NULL) - $(MAKE) -C .. $*Binding.h - $(MAKE) -C .. $*Binding.cpp - -check:: - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py - -check-interactive: - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py -q diff --git a/src/components/script/dom/bindings/codegen/test/TestBindingHeader.h b/src/components/script/dom/bindings/codegen/test/TestBindingHeader.h deleted file mode 100644 index 1fbab0a9fb8..00000000000 --- a/src/components/script/dom/bindings/codegen/test/TestBindingHeader.h +++ /dev/null @@ -1,653 +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 TestBindingHeader_h -#define TestBindingHeader_h - -#include "nsWrapperCache.h" -#include "mozilla/ErrorResult.h" -#include "mozilla/dom/BindingUtils.h" -#include "mozilla/dom/TypedArray.h" -#include "nsCOMPtr.h" -// We don't export TestCodeGenBinding.h, but it's right in our parent dir. -#include "../TestCodeGenBinding.h" -#include "mozilla/dom/UnionTypes.h" - -namespace mozilla { -namespace dom { - -// IID for the TestNonCastableInterface -#define NS_TEST_NONCASTABLE_INTERFACE_IID \ -{ 0x7c9f8ee2, 0xc9bf, 0x46ca, \ - { 0xa0, 0xa9, 0x03, 0xa8, 0xd6, 0x30, 0x0e, 0xde } } - -class TestNonCastableInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_TEST_NONCASTABLE_INTERFACE_IID) - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); -}; - -// IID for the IndirectlyImplementedInterface -#define NS_INDIRECTLY_IMPLEMENTED_INTERFACE_IID \ -{ 0xfed55b69, 0x7012, 0x4849, \ - { 0xaf, 0x56, 0x4b, 0xa9, 0xee, 0x41, 0x30, 0x89 } } - -class IndirectlyImplementedInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_INDIRECTLY_IMPLEMENTED_INTERFACE_IID) - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - bool IndirectlyImplementedProperty(); - void IndirectlyImplementedProperty(bool); - void IndirectlyImplementedMethod(); -}; - -// IID for the TestExternalInterface -#define NS_TEST_EXTERNAL_INTERFACE_IID \ -{ 0xd5ba0c99, 0x9b1d, 0x4e71, \ - { 0x8a, 0x94, 0x56, 0x38, 0x6c, 0xa3, 0xda, 0x3d } } -class TestExternalInterface : public nsISupports -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_TEST_EXTERNAL_INTERFACE_IID) - NS_DECL_ISUPPORTS -}; - -// IID for the TestCallbackInterface -#define NS_TEST_CALLBACK_INTERFACE_IID \ -{ 0xbf711ba4, 0xc8f6, 0x46cf, \ - { 0xba, 0x5b, 0xaa, 0xe2, 0x78, 0x18, 0xe6, 0x4a } } -class TestCallbackInterface : public nsISupports -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_TEST_CALLBACK_INTERFACE_IID) - NS_DECL_ISUPPORTS -}; - -class TestNonWrapperCacheInterface : public nsISupports -{ -public: - NS_DECL_ISUPPORTS - - virtual JSObject* WrapObject(JSContext* cx, JSObject* scope); -}; - -class OnlyForUseInConstructor : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); -}; - -class TestInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - // And now our actual WebIDL API - // Constructors - static - already_AddRefed<TestInterface> Constructor(nsISupports*, ErrorResult&); - static - already_AddRefed<TestInterface> Constructor(nsISupports*, const nsAString&, - ErrorResult&); - static - already_AddRefed<TestInterface> Constructor(nsISupports*, uint32_t, - Nullable<bool>&, ErrorResult&); - static - already_AddRefed<TestInterface> Constructor(nsISupports*, TestInterface*, - ErrorResult&); - static - already_AddRefed<TestInterface> Constructor(nsISupports*, - TestNonCastableInterface&, - ErrorResult&); - /* static - already_AddRefed<TestInterface> Constructor(nsISupports*, - uint32_t, uint32_t, - const TestInterfaceOrOnlyForUseInConstructor&, - ErrorResult&); - */ - - // Integer types - int8_t ReadonlyByte(); - int8_t WritableByte(); - void SetWritableByte(int8_t); - void PassByte(int8_t); - int8_t ReceiveByte(); - void PassOptionalByte(const Optional<int8_t>&); - void PassOptionalByteWithDefault(int8_t); - void PassNullableByte(Nullable<int8_t>&); - void PassOptionalNullableByte(const Optional< Nullable<int8_t> >&); - - int16_t ReadonlyShort(); - int16_t WritableShort(); - void SetWritableShort(int16_t); - void PassShort(int16_t); - int16_t ReceiveShort(); - void PassOptionalShort(const Optional<int16_t>&); - void PassOptionalShortWithDefault(int16_t); - - int32_t ReadonlyLong(); - int32_t WritableLong(); - void SetWritableLong(int32_t); - void PassLong(int32_t); - int16_t ReceiveLong(); - void PassOptionalLong(const Optional<int32_t>&); - void PassOptionalLongWithDefault(int32_t); - - int64_t ReadonlyLongLong(); - int64_t WritableLongLong(); - void SetWritableLongLong(int64_t); - void PassLongLong(int64_t); - int64_t ReceiveLongLong(); - void PassOptionalLongLong(const Optional<int64_t>&); - void PassOptionalLongLongWithDefault(int64_t); - - uint8_t ReadonlyOctet(); - uint8_t WritableOctet(); - void SetWritableOctet(uint8_t); - void PassOctet(uint8_t); - uint8_t ReceiveOctet(); - void PassOptionalOctet(const Optional<uint8_t>&); - void PassOptionalOctetWithDefault(uint8_t); - - uint16_t ReadonlyUnsignedShort(); - uint16_t WritableUnsignedShort(); - void SetWritableUnsignedShort(uint16_t); - void PassUnsignedShort(uint16_t); - uint16_t ReceiveUnsignedShort(); - void PassOptionalUnsignedShort(const Optional<uint16_t>&); - void PassOptionalUnsignedShortWithDefault(uint16_t); - - uint32_t ReadonlyUnsignedLong(); - uint32_t WritableUnsignedLong(); - void SetWritableUnsignedLong(uint32_t); - void PassUnsignedLong(uint32_t); - uint32_t ReceiveUnsignedLong(); - void PassOptionalUnsignedLong(const Optional<uint32_t>&); - void PassOptionalUnsignedLongWithDefault(uint32_t); - - uint64_t ReadonlyUnsignedLongLong(); - uint64_t WritableUnsignedLongLong(); - void SetWritableUnsignedLongLong(uint64_t); - void PassUnsignedLongLong(uint64_t); - uint64_t ReceiveUnsignedLongLong(); - void PassOptionalUnsignedLongLong(const Optional<uint64_t>&); - void PassOptionalUnsignedLongLongWithDefault(uint64_t); - - // Interface types - already_AddRefed<TestInterface> ReceiveSelf(); - already_AddRefed<TestInterface> ReceiveNullableSelf(); - TestInterface* ReceiveWeakSelf(); - TestInterface* ReceiveWeakNullableSelf(); - void PassSelf(TestInterface&); - void PassSelf2(NonNull<TestInterface>&); - void PassNullableSelf(TestInterface*); - already_AddRefed<TestInterface> NonNullSelf(); - void SetNonNullSelf(TestInterface&); - already_AddRefed<TestInterface> GetNullableSelf(); - void SetNullableSelf(TestInterface*); - void PassOptionalSelf(const Optional<TestInterface*> &); - void PassOptionalNonNullSelf(const Optional<NonNull<TestInterface> >&); - void PassOptionalSelfWithDefault(TestInterface*); - - already_AddRefed<TestNonWrapperCacheInterface> ReceiveNonWrapperCacheInterface(); - already_AddRefed<TestNonWrapperCacheInterface> ReceiveNullableNonWrapperCacheInterface(); - void ReceiveNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&); - void ReceiveNullableNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&); - void ReceiveNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&); - void ReceiveNullableNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&); - - already_AddRefed<TestNonCastableInterface> ReceiveOther(); - already_AddRefed<TestNonCastableInterface> ReceiveNullableOther(); - TestNonCastableInterface* ReceiveWeakOther(); - TestNonCastableInterface* ReceiveWeakNullableOther(); - void PassOther(TestNonCastableInterface&); - void PassOther2(NonNull<TestNonCastableInterface>&); - void PassNullableOther(TestNonCastableInterface*); - already_AddRefed<TestNonCastableInterface> NonNullOther(); - void SetNonNullOther(TestNonCastableInterface&); - already_AddRefed<TestNonCastableInterface> GetNullableOther(); - void SetNullableOther(TestNonCastableInterface*); - void PassOptionalOther(const Optional<TestNonCastableInterface*>&); - void PassOptionalNonNullOther(const Optional<NonNull<TestNonCastableInterface> >&); - void PassOptionalOtherWithDefault(TestNonCastableInterface*); - - already_AddRefed<TestExternalInterface> ReceiveExternal(); - already_AddRefed<TestExternalInterface> ReceiveNullableExternal(); - TestExternalInterface* ReceiveWeakExternal(); - TestExternalInterface* ReceiveWeakNullableExternal(); - void PassExternal(TestExternalInterface*); - void PassExternal2(TestExternalInterface*); - void PassNullableExternal(TestExternalInterface*); - already_AddRefed<TestExternalInterface> NonNullExternal(); - void SetNonNullExternal(TestExternalInterface*); - already_AddRefed<TestExternalInterface> GetNullableExternal(); - void SetNullableExternal(TestExternalInterface*); - void PassOptionalExternal(const Optional<TestExternalInterface*>&); - void PassOptionalNonNullExternal(const Optional<TestExternalInterface*>&); - void PassOptionalExternalWithDefault(TestExternalInterface*); - - already_AddRefed<TestCallbackInterface> ReceiveCallbackInterface(); - already_AddRefed<TestCallbackInterface> ReceiveNullableCallbackInterface(); - TestCallbackInterface* ReceiveWeakCallbackInterface(); - TestCallbackInterface* ReceiveWeakNullableCallbackInterface(); - void PassCallbackInterface(TestCallbackInterface&); - void PassCallbackInterface2(OwningNonNull<TestCallbackInterface>); - void PassNullableCallbackInterface(TestCallbackInterface*); - already_AddRefed<TestCallbackInterface> NonNullCallbackInterface(); - void SetNonNullCallbackInterface(TestCallbackInterface&); - already_AddRefed<TestCallbackInterface> GetNullableCallbackInterface(); - void SetNullableCallbackInterface(TestCallbackInterface*); - void PassOptionalCallbackInterface(const Optional<nsRefPtr<TestCallbackInterface> >&); - void PassOptionalNonNullCallbackInterface(const Optional<OwningNonNull<TestCallbackInterface> >&); - void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterface*); - - already_AddRefed<IndirectlyImplementedInterface> ReceiveConsequentialInterface(); - void PassConsequentialInterface(IndirectlyImplementedInterface&); - - // Sequence types - void ReceiveSequence(nsTArray<int32_t>&); - void ReceiveNullableSequence(Nullable< nsTArray<int32_t> >&); - void ReceiveSequenceOfNullableInts(nsTArray< Nullable<int32_t> >&); - void ReceiveNullableSequenceOfNullableInts(Nullable< nsTArray< Nullable<int32_t> > >&); - void PassSequence(const Sequence<int32_t> &); - void PassNullableSequence(const Nullable< Sequence<int32_t> >&); - void PassSequenceOfNullableInts(const Sequence<Nullable<int32_t> >&); - void PassOptionalSequenceOfNullableInts(const Optional<Sequence<Nullable<int32_t> > > &); - void PassOptionalNullableSequenceOfNullableInts(const Optional<Nullable<Sequence<Nullable<int32_t> > > > &); - void ReceiveCastableObjectSequence(nsTArray< nsRefPtr<TestInterface> > &); - void ReceiveNullableCastableObjectSequence(nsTArray< nsRefPtr<TestInterface> > &); - void ReceiveCastableObjectNullableSequence(Nullable< nsTArray< nsRefPtr<TestInterface> > >&); - void ReceiveNullableCastableObjectNullableSequence(Nullable< nsTArray< nsRefPtr<TestInterface> > >&); - void ReceiveWeakCastableObjectSequence(nsTArray<TestInterface*> &); - void ReceiveWeakNullableCastableObjectSequence(nsTArray<TestInterface*> &); - void ReceiveWeakCastableObjectNullableSequence(Nullable< nsTArray<TestInterface*> >&); - void ReceiveWeakNullableCastableObjectNullableSequence(Nullable< nsTArray<TestInterface*> >&); - void PassCastableObjectSequence(const Sequence< OwningNonNull<TestInterface> >&); - void PassNullableCastableObjectSequence(const Sequence< nsRefPtr<TestInterface> > &); - void PassCastableObjectNullableSequence(const Nullable< Sequence< OwningNonNull<TestInterface> > >&); - void PassNullableCastableObjectNullableSequence(const Nullable< Sequence< nsRefPtr<TestInterface> > >&); - void PassOptionalSequence(const Optional<Sequence<int32_t> >&); - void PassOptionalNullableSequence(const Optional<Nullable<Sequence<int32_t> > >&); - void PassOptionalNullableSequenceWithDefaultValue(const Nullable< Sequence<int32_t> >&); - void PassOptionalObjectSequence(const Optional<Sequence<OwningNonNull<TestInterface> > >&); - - void ReceiveStringSequence(nsTArray<nsString>&); - void PassStringSequence(const Sequence<nsString>&); - - void ReceiveAnySequence(JSContext*, nsTArray<JS::Value>&); - void ReceiveNullableAnySequence(JSContext*, Nullable<nsTArray<JS::Value> >); - - // Typed array types - void PassArrayBuffer(ArrayBuffer&); - void PassNullableArrayBuffer(ArrayBuffer*); - void PassOptionalArrayBuffer(const Optional<ArrayBuffer>&); - void PassOptionalNullableArrayBuffer(const Optional<ArrayBuffer*>&); - void PassOptionalNullableArrayBufferWithDefaultValue(ArrayBuffer*); - void PassArrayBufferView(ArrayBufferView&); - void PassInt8Array(Int8Array&); - void PassInt16Array(Int16Array&); - void PassInt32Array(Int32Array&); - void PassUint8Array(Uint8Array&); - void PassUint16Array(Uint16Array&); - void PassUint32Array(Uint32Array&); - void PassUint8ClampedArray(Uint8ClampedArray&); - void PassFloat32Array(Float32Array&); - void PassFloat64Array(Float64Array&); - JSObject* ReceiveUint8Array(JSContext*); - - // String types - void PassString(const nsAString&); - void PassNullableString(const nsAString&); - void PassOptionalString(const Optional<nsAString>&); - void PassOptionalStringWithDefaultValue(const nsAString&); - void PassOptionalNullableString(const Optional<nsAString>&); - void PassOptionalNullableStringWithDefaultValue(const nsAString&); - - // Enumarated types - void PassEnum(TestEnum); - void PassOptionalEnum(const Optional<TestEnum>&); - void PassEnumWithDefault(TestEnum); - TestEnum ReceiveEnum(); - TestEnum EnumAttribute(); - TestEnum ReadonlyEnumAttribute(); - void SetEnumAttribute(TestEnum); - - // Callback types - void PassCallback(JSContext*, JSObject*); - void PassNullableCallback(JSContext*, JSObject*); - void PassOptionalCallback(JSContext*, const Optional<JSObject*>&); - void PassOptionalNullableCallback(JSContext*, const Optional<JSObject*>&); - void PassOptionalNullableCallbackWithDefaultValue(JSContext*, JSObject*); - JSObject* ReceiveCallback(JSContext*); - JSObject* ReceiveNullableCallback(JSContext*); - - // Any types - void PassAny(JSContext*, JS::Value); - void PassOptionalAny(JSContext*, const Optional<JS::Value>&); - void PassAnyDefaultNull(JSContext*, JS::Value); - JS::Value ReceiveAny(JSContext*); - - // object types - void PassObject(JSContext*, JSObject&); - void PassNullableObject(JSContext*, JSObject*); - void PassOptionalObject(JSContext*, const Optional<NonNull<JSObject> >&); - void PassOptionalNullableObject(JSContext*, const Optional<JSObject*>&); - void PassOptionalNullableObjectWithDefaultValue(JSContext*, JSObject*); - JSObject* ReceiveObject(JSContext*); - JSObject* ReceiveNullableObject(JSContext*); - - // Union types - void PassUnion(JSContext*, const ObjectOrLong& arg); - void PassUnionWithNullable(JSContext*, const ObjectOrNullOrLong& arg) - { - ObjectOrLong returnValue; - if (arg.IsNull()) { - } else if (arg.IsObject()) { - JSObject& obj = (JSObject&)arg.GetAsObject(); - JS_GetClass(&obj); - //returnValue.SetAsObject(&obj); - } else { - int32_t i = arg.GetAsLong(); - i += 1; - } - } - void PassNullableUnion(JSContext*, const Nullable<ObjectOrLong>&); - void PassOptionalUnion(JSContext*, const Optional<ObjectOrLong>&); - void PassOptionalNullableUnion(JSContext*, const Optional<Nullable<ObjectOrLong> >&); - void PassOptionalNullableUnionWithDefaultValue(JSContext*, const Nullable<ObjectOrLong>&); - //void PassUnionWithInterfaces(const TestInterfaceOrTestExternalInterface& arg); - //void PassUnionWithInterfacesAndNullable(const TestInterfaceOrNullOrTestExternalInterface& arg); - void PassUnionWithArrayBuffer(const ArrayBufferOrLong&); - void PassUnionWithString(JSContext*, const StringOrObject&); - //void PassUnionWithEnum(JSContext*, const TestEnumOrObject&); - void PassUnionWithCallback(JSContext*, const TestCallbackOrLong&); - void PassUnionWithObject(JSContext*, const ObjectOrLong&); - - // binaryNames tests - void MethodRenamedTo(); - void MethodRenamedTo(int8_t); - int8_t AttributeGetterRenamedTo(); - int8_t AttributeRenamedTo(); - void SetAttributeRenamedTo(int8_t); - - // Dictionary tests - void PassDictionary(const Dict&); - void PassOtherDictionary(const GrandparentDict&); - void PassSequenceOfDictionaries(const Sequence<Dict>&); - void PassDictionaryOrLong(const Dict&); - void PassDictionaryOrLong(int32_t); - void PassDictContainingDict(const DictContainingDict&); - void PassDictContainingSequence(const DictContainingSequence&); - - // Typedefs - void ExerciseTypedefInterfaces1(TestInterface&); - already_AddRefed<TestInterface> ExerciseTypedefInterfaces2(TestInterface*); - void ExerciseTypedefInterfaces3(TestInterface&); - - // Miscellania - int32_t AttrWithLenientThis(); - void SetAttrWithLenientThis(int32_t); - - // Methods and properties imported via "implements" - bool ImplementedProperty(); - void SetImplementedProperty(bool); - void ImplementedMethod(); - bool ImplementedParentProperty(); - void SetImplementedParentProperty(bool); - void ImplementedParentMethod(); - bool IndirectlyImplementedProperty(); - void SetIndirectlyImplementedProperty(bool); - void IndirectlyImplementedMethod(); - uint32_t DiamondImplementedProperty(); - - // Test EnforceRange/Clamp - void DontEnforceRangeOrClamp(int8_t); - void DoEnforceRange(int8_t); - void DoClamp(int8_t); - -private: - // We add signatures here that _could_ start matching if the codegen - // got data types wrong. That way if it ever does we'll have a call - // to these private deleted methods and compilation will fail. - void SetReadonlyByte(int8_t) MOZ_DELETE; - template<typename T> - void SetWritableByte(T) MOZ_DELETE; - template<typename T> - void PassByte(T) MOZ_DELETE; - template<typename T> - void PassOptionalByte(const Optional<T>&) MOZ_DELETE; - template<typename T> - void PassOptionalByteWithDefault(T) MOZ_DELETE; - - void SetReadonlyShort(int16_t) MOZ_DELETE; - template<typename T> - void SetWritableShort(T) MOZ_DELETE; - template<typename T> - void PassShort(T) MOZ_DELETE; - template<typename T> - void PassOptionalShort(const Optional<T>&) MOZ_DELETE; - template<typename T> - void PassOptionalShortWithDefault(T) MOZ_DELETE; - - void SetReadonlyLong(int32_t) MOZ_DELETE; - template<typename T> - void SetWritableLong(T) MOZ_DELETE; - template<typename T> - void PassLong(T) MOZ_DELETE; - template<typename T> - void PassOptionalLong(const Optional<T>&) MOZ_DELETE; - template<typename T> - void PassOptionalLongWithDefault(T) MOZ_DELETE; - - void SetReadonlyLongLong(int64_t) MOZ_DELETE; - template<typename T> - void SetWritableLongLong(T) MOZ_DELETE; - template<typename T> - void PassLongLong(T) MOZ_DELETE; - template<typename T> - void PassOptionalLongLong(const Optional<T>&) MOZ_DELETE; - template<typename T> - void PassOptionalLongLongWithDefault(T) MOZ_DELETE; - - void SetReadonlyOctet(uint8_t) MOZ_DELETE; - template<typename T> - void SetWritableOctet(T) MOZ_DELETE; - template<typename T> - void PassOctet(T) MOZ_DELETE; - template<typename T> - void PassOptionalOctet(const Optional<T>&) MOZ_DELETE; - template<typename T> - void PassOptionalOctetWithDefault(T) MOZ_DELETE; - - void SetReadonlyUnsignedShort(uint16_t) MOZ_DELETE; - template<typename T> - void SetWritableUnsignedShort(T) MOZ_DELETE; - template<typename T> - void PassUnsignedShort(T) MOZ_DELETE; - template<typename T> - void PassOptionalUnsignedShort(const Optional<T>&) MOZ_DELETE; - template<typename T> - void PassOptionalUnsignedShortWithDefault(T) MOZ_DELETE; - - void SetReadonlyUnsignedLong(uint32_t) MOZ_DELETE; - template<typename T> - void SetWritableUnsignedLong(T) MOZ_DELETE; - template<typename T> - void PassUnsignedLong(T) MOZ_DELETE; - template<typename T> - void PassOptionalUnsignedLong(const Optional<T>&) MOZ_DELETE; - template<typename T> - void PassOptionalUnsignedLongWithDefault(T) MOZ_DELETE; - - void SetReadonlyUnsignedLongLong(uint64_t) MOZ_DELETE; - template<typename T> - void SetWritableUnsignedLongLong(T) MOZ_DELETE; - template<typename T> - void PassUnsignedLongLong(T) MOZ_DELETE; - template<typename T> - void PassOptionalUnsignedLongLong(const Optional<T>&) MOZ_DELETE; - template<typename T> - void PassOptionalUnsignedLongLongWithDefault(T) MOZ_DELETE; - - // Enforce that only const things are passed for sequences - void PassSequence(Sequence<int32_t> &) MOZ_DELETE; - void PassNullableSequence(Nullable< Sequence<int32_t> >&) MOZ_DELETE; - void PassOptionalNullableSequenceWithDefaultValue(Nullable< Sequence<int32_t> >&) MOZ_DELETE; - - // Enforce that only const things are passed for optional - void PassOptionalByte(Optional<int8_t>&) MOZ_DELETE; - void PassOptionalNullableByte(Optional<Nullable<int8_t> >&) MOZ_DELETE; - void PassOptionalShort(Optional<int16_t>&) MOZ_DELETE; - void PassOptionalLong(Optional<int32_t>&) MOZ_DELETE; - void PassOptionalLongLong(Optional<int64_t>&) MOZ_DELETE; - void PassOptionalOctet(Optional<uint8_t>&) MOZ_DELETE; - void PassOptionalUnsignedShort(Optional<uint16_t>&) MOZ_DELETE; - void PassOptionalUnsignedLong(Optional<uint32_t>&) MOZ_DELETE; - void PassOptionalUnsignedLongLong(Optional<uint64_t>&) MOZ_DELETE; - void PassOptionalSelf(Optional<TestInterface*> &) MOZ_DELETE; - void PassOptionalNonNullSelf(Optional<NonNull<TestInterface> >&) MOZ_DELETE; - void PassOptionalOther(Optional<TestNonCastableInterface*>&); - void PassOptionalNonNullOther(Optional<NonNull<TestNonCastableInterface> >&); - void PassOptionalExternal(Optional<TestExternalInterface*>&) MOZ_DELETE; - void PassOptionalNonNullExternal(Optional<TestExternalInterface*>&) MOZ_DELETE; - void PassOptionalSequence(Optional<Sequence<int32_t> >&) MOZ_DELETE; - void PassOptionalNullableSequence(Optional<Nullable<Sequence<int32_t> > >&) MOZ_DELETE; - void PassOptionalObjectSequence(Optional<Sequence<OwningNonNull<TestInterface> > >&) MOZ_DELETE; - void PassOptionalArrayBuffer(Optional<ArrayBuffer>&) MOZ_DELETE; - void PassOptionalNullableArrayBuffer(Optional<ArrayBuffer*>&) MOZ_DELETE; - void PassOptionalEnum(Optional<TestEnum>&) MOZ_DELETE; - void PassOptionalCallback(JSContext*, Optional<JSObject*>&) MOZ_DELETE; - void PassOptionalNullableCallback(JSContext*, Optional<JSObject*>&) MOZ_DELETE; - void PassOptionalAny(Optional<JS::Value>&) MOZ_DELETE; - - // And test that string stuff is always const - void PassString(nsAString&) MOZ_DELETE; - void PassNullableString(nsAString&) MOZ_DELETE; - void PassOptionalString(Optional<nsAString>&) MOZ_DELETE; - void PassOptionalStringWithDefaultValue(nsAString&) MOZ_DELETE; - void PassOptionalNullableString(Optional<nsAString>&) MOZ_DELETE; - void PassOptionalNullableStringWithDefaultValue(nsAString&) MOZ_DELETE; - -}; - -class TestIndexedGetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - uint32_t IndexedGetter(uint32_t, bool&); - uint32_t IndexedGetter(uint32_t&) MOZ_DELETE; - uint32_t Item(uint32_t&); - uint32_t Item(uint32_t, bool&) MOZ_DELETE; - uint32_t Length(); -}; - -class TestNamedGetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void NamedGetter(const nsAString&, bool&, nsAString&); -}; - -class TestIndexedAndNamedGetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - uint32_t IndexedGetter(uint32_t, bool&); - void NamedGetter(const nsAString&, bool&, nsAString&); - void NamedItem(const nsAString&, nsAString&); - uint32_t Length(); -}; - -class TestIndexedSetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void IndexedSetter(uint32_t, const nsAString&); - void SetItem(uint32_t, const nsAString&); -}; - -class TestNamedSetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void NamedSetter(const nsAString&, TestIndexedSetterInterface&); -}; - -class TestIndexedAndNamedSetterInterface : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_ISUPPORTS - - // We need a GetParentObject to make binding codegen happy - virtual nsISupports* GetParentObject(); - - void IndexedSetter(uint32_t, TestIndexedSetterInterface&); - void NamedSetter(const nsAString&, TestIndexedSetterInterface&); - void SetNamedItem(const nsAString&, TestIndexedSetterInterface&); -}; - -class TestIndexedAndNamedGetterAndSetterInterface : public TestIndexedSetterInterface -{ -public: - uint32_t IndexedGetter(uint32_t, bool&); - uint32_t Item(uint32_t); - void NamedGetter(const nsAString&, bool&, nsAString&); - void NamedItem(const nsAString&, nsAString&); - void IndexedSetter(uint32_t, int32_t&); - void IndexedSetter(uint32_t, const nsAString&) MOZ_DELETE; - void NamedSetter(const nsAString&, const nsAString&); - void Stringify(nsAString&); - uint32_t Length(); -}; - -} // namespace dom -} // namespace mozilla - -#endif /* TestBindingHeader_h */ diff --git a/src/components/script/dom/bindings/codegen/test/TestCodeGen.webidl b/src/components/script/dom/bindings/codegen/test/TestCodeGen.webidl deleted file mode 100644 index 8c2b3c1b6b4..00000000000 --- a/src/components/script/dom/bindings/codegen/test/TestCodeGen.webidl +++ /dev/null @@ -1,442 +0,0 @@ -/* -*- Mode: IDL; 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/. - */ - -typedef long myLong; -typedef TestInterface AnotherNameForTestInterface; -typedef TestInterface? NullableTestInterface; - -interface TestExternalInterface; - -interface TestNonCastableInterface { -}; - -callback interface TestCallbackInterface { - readonly attribute long foo; - void doSomething(); -}; - -enum TestEnum { - "a", - "b" -}; - -callback TestCallback = void(); - -TestInterface implements ImplementedInterface; - -// This interface is only for use in the constructor below -interface OnlyForUseInConstructor { -}; - -[Constructor, - Constructor(DOMString str), - Constructor(unsigned long num, boolean? bool), - Constructor(TestInterface? iface), - Constructor(TestNonCastableInterface iface) - // , Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3) - ] -interface TestInterface { - // Integer types - // XXXbz add tests for throwing versions of all the integer stuff - readonly attribute byte readonlyByte; - attribute byte writableByte; - void passByte(byte arg); - byte receiveByte(); - void passOptionalByte(optional byte arg); - void passOptionalByteWithDefault(optional byte arg = 0); - void passNullableByte(byte? arg); - void passOptionalNullableByte(optional byte? arg); - - readonly attribute short readonlyShort; - attribute short writableShort; - void passShort(short arg); - short receiveShort(); - void passOptionalShort(optional short arg); - void passOptionalShortWithDefault(optional short arg = 5); - - readonly attribute long readonlyLong; - attribute long writableLong; - void passLong(long arg); - long receiveLong(); - void passOptionalLong(optional long arg); - void passOptionalLongWithDefault(optional long arg = 7); - - readonly attribute long long readonlyLongLong; - attribute long long writableLongLong; - void passLongLong(long long arg); - long long receiveLongLong(); - void passOptionalLongLong(optional long long arg); - void passOptionalLongLongWithDefault(optional long long arg = -12); - - readonly attribute octet readonlyOctet; - attribute octet writableOctet; - void passOctet(octet arg); - octet receiveOctet(); - void passOptionalOctet(optional octet arg); - void passOptionalOctetWithDefault(optional octet arg = 19); - - readonly attribute unsigned short readonlyUnsignedShort; - attribute unsigned short writableUnsignedShort; - void passUnsignedShort(unsigned short arg); - unsigned short receiveUnsignedShort(); - void passOptionalUnsignedShort(optional unsigned short arg); - void passOptionalUnsignedShortWithDefault(optional unsigned short arg = 2); - - readonly attribute unsigned long readonlyUnsignedLong; - attribute unsigned long writableUnsignedLong; - void passUnsignedLong(unsigned long arg); - unsigned long receiveUnsignedLong(); - void passOptionalUnsignedLong(optional unsigned long arg); - void passOptionalUnsignedLongWithDefault(optional unsigned long arg = 6); - - readonly attribute unsigned long long readonlyUnsignedLongLong; - attribute unsigned long long writableUnsignedLongLong; - void passUnsignedLongLong(unsigned long long arg); - unsigned long long receiveUnsignedLongLong(); - void passOptionalUnsignedLongLong(optional unsigned long long arg); - void passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17); - - // Castable interface types - // XXXbz add tests for throwing versions of all the castable interface stuff - TestInterface receiveSelf(); - TestInterface? receiveNullableSelf(); - TestInterface receiveWeakSelf(); - TestInterface? receiveWeakNullableSelf(); - // A verstion to test for casting to TestInterface& - void passSelf(TestInterface arg); - // A version we can use to test for the exact type passed in - void passSelf2(TestInterface arg); - void passNullableSelf(TestInterface? arg); - attribute TestInterface nonNullSelf; - attribute TestInterface? nullableSelf; - // Optional arguments - void passOptionalSelf(optional TestInterface? arg); - void passOptionalNonNullSelf(optional TestInterface arg); - void passOptionalSelfWithDefault(optional TestInterface? arg = null); - - // Non-wrapper-cache interface types - [Creator] - TestNonWrapperCacheInterface receiveNonWrapperCacheInterface(); - [Creator] - TestNonWrapperCacheInterface? receiveNullableNonWrapperCacheInterface(); - [Creator] - sequence<TestNonWrapperCacheInterface> receiveNonWrapperCacheInterfaceSequence(); - [Creator] - sequence<TestNonWrapperCacheInterface?> receiveNullableNonWrapperCacheInterfaceSequence(); - [Creator] - sequence<TestNonWrapperCacheInterface>? receiveNonWrapperCacheInterfaceNullableSequence(); - [Creator] - sequence<TestNonWrapperCacheInterface?>? receiveNullableNonWrapperCacheInterfaceNullableSequence(); - - // Non-castable interface types - TestNonCastableInterface receiveOther(); - TestNonCastableInterface? receiveNullableOther(); - TestNonCastableInterface receiveWeakOther(); - TestNonCastableInterface? receiveWeakNullableOther(); - // A verstion to test for casting to TestNonCastableInterface& - void passOther(TestNonCastableInterface arg); - // A version we can use to test for the exact type passed in - void passOther2(TestNonCastableInterface arg); - void passNullableOther(TestNonCastableInterface? arg); - attribute TestNonCastableInterface nonNullOther; - attribute TestNonCastableInterface? nullableOther; - // Optional arguments - void passOptionalOther(optional TestNonCastableInterface? arg); - void passOptionalNonNullOther(optional TestNonCastableInterface arg); - void passOptionalOtherWithDefault(optional TestNonCastableInterface? arg = null); - - // External interface types - TestExternalInterface receiveExternal(); - TestExternalInterface? receiveNullableExternal(); - TestExternalInterface receiveWeakExternal(); - TestExternalInterface? receiveWeakNullableExternal(); - // A verstion to test for casting to TestExternalInterface& - void passExternal(TestExternalInterface arg); - // A version we can use to test for the exact type passed in - void passExternal2(TestExternalInterface arg); - void passNullableExternal(TestExternalInterface? arg); - attribute TestExternalInterface nonNullExternal; - attribute TestExternalInterface? nullableExternal; - // Optional arguments - void passOptionalExternal(optional TestExternalInterface? arg); - void passOptionalNonNullExternal(optional TestExternalInterface arg); - void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null); - - // Callback interface types - TestCallbackInterface receiveCallbackInterface(); - TestCallbackInterface? receiveNullableCallbackInterface(); - TestCallbackInterface receiveWeakCallbackInterface(); - TestCallbackInterface? receiveWeakNullableCallbackInterface(); - // A verstion to test for casting to TestCallbackInterface& - void passCallbackInterface(TestCallbackInterface arg); - // A version we can use to test for the exact type passed in - void passCallbackInterface2(TestCallbackInterface arg); - void passNullableCallbackInterface(TestCallbackInterface? arg); - attribute TestCallbackInterface nonNullCallbackInterface; - attribute TestCallbackInterface? nullableCallbackInterface; - // Optional arguments - void passOptionalCallbackInterface(optional TestCallbackInterface? arg); - void passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg); - void passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null); - - // Miscellaneous interface tests - IndirectlyImplementedInterface receiveConsequentialInterface(); - void passConsequentialInterface(IndirectlyImplementedInterface arg); - - // Sequence types - sequence<long> receiveSequence(); - sequence<long>? receiveNullableSequence(); - sequence<long?> receiveSequenceOfNullableInts(); - sequence<long?>? receiveNullableSequenceOfNullableInts(); - void passSequence(sequence<long> arg); - void passNullableSequence(sequence<long>? arg); - void passSequenceOfNullableInts(sequence<long?> arg); - void passOptionalSequenceOfNullableInts(optional sequence<long?> arg); - void passOptionalNullableSequenceOfNullableInts(optional sequence<long?>? arg); - sequence<TestInterface> receiveCastableObjectSequence(); - sequence<TestInterface?> receiveNullableCastableObjectSequence(); - sequence<TestInterface>? receiveCastableObjectNullableSequence(); - sequence<TestInterface?>? receiveNullableCastableObjectNullableSequence(); - sequence<TestInterface> receiveWeakCastableObjectSequence(); - sequence<TestInterface?> receiveWeakNullableCastableObjectSequence(); - sequence<TestInterface>? receiveWeakCastableObjectNullableSequence(); - sequence<TestInterface?>? receiveWeakNullableCastableObjectNullableSequence(); - void passCastableObjectSequence(sequence<TestInterface> arg); - void passNullableCastableObjectSequence(sequence<TestInterface?> arg); - void passCastableObjectNullableSequence(sequence<TestInterface>? arg); - void passNullableCastableObjectNullableSequence(sequence<TestInterface?>? arg); - void passOptionalSequence(optional sequence<long> arg); - void passOptionalNullableSequence(optional sequence<long>? arg); - void passOptionalNullableSequenceWithDefaultValue(optional sequence<long>? arg = null); - void passOptionalObjectSequence(optional sequence<TestInterface> arg); - - sequence<DOMString> receiveStringSequence(); - void passStringSequence(sequence<DOMString> arg); - - sequence<any> receiveAnySequence(); - sequence<any>? receiveNullableAnySequence(); - - // Typed array types - void passArrayBuffer(ArrayBuffer arg); - void passNullableArrayBuffer(ArrayBuffer? arg); - void passOptionalArrayBuffer(optional ArrayBuffer arg); - void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg); - void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null); - void passArrayBufferView(ArrayBufferView arg); - void passInt8Array(Int8Array arg); - void passInt16Array(Int16Array arg); - void passInt32Array(Int32Array arg); - void passUint8Array(Uint8Array arg); - void passUint16Array(Uint16Array arg); - void passUint32Array(Uint32Array arg); - void passUint8ClampedArray(Uint8ClampedArray arg); - void passFloat32Array(Float32Array arg); - void passFloat64Array(Float64Array arg); - Uint8Array receiveUint8Array(); - - // String types - void passString(DOMString arg); - void passNullableString(DOMString? arg); - void passOptionalString(optional DOMString arg); - void passOptionalStringWithDefaultValue(optional DOMString arg = "abc"); - void passOptionalNullableString(optional DOMString? arg); - void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null); - - // Enumerated types - void passEnum(TestEnum arg); - // No support for nullable enums yet - // void passNullableEnum(TestEnum? arg); - void passOptionalEnum(optional TestEnum arg); - void passEnumWithDefault(optional TestEnum arg = "a"); - // void passOptionalNullableEnum(optional TestEnum? arg); - // void passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null); - TestEnum receiveEnum(); - attribute TestEnum enumAttribute; - readonly attribute TestEnum readonlyEnumAttribute; - - // Callback types - void passCallback(TestCallback arg); - void passNullableCallback(TestCallback? arg); - void passOptionalCallback(optional TestCallback arg); - void passOptionalNullableCallback(optional TestCallback? arg); - void passOptionalNullableCallbackWithDefaultValue(optional TestCallback? arg = null); - TestCallback receiveCallback(); - TestCallback? receiveNullableCallback(); - - // Any types - void passAny(any arg); - void passOptionalAny(optional any arg); - void passAnyDefaultNull(optional any arg = null); - any receiveAny(); - - // object types - void passObject(object arg); - void passNullableObject(object? arg); - void passOptionalObject(optional object arg); - void passOptionalNullableObject(optional object? arg); - void passOptionalNullableObjectWithDefaultValue(optional object? arg = null); - object receiveObject(); - object? receiveNullableObject(); - - // Union types - void passUnion((object or long) arg); - void passUnionWithNullable((object? or long) arg); - void passNullableUnion((object or long)? arg); - void passOptionalUnion(optional (object or long) arg); - void passOptionalNullableUnion(optional (object or long)? arg); - void passOptionalNullableUnionWithDefaultValue(optional (object or long)? arg = null); - //void passUnionWithInterfaces((TestInterface or TestExternalInterface) arg); - //void passUnionWithInterfacesAndNullable((TestInterface? or TestExternalInterface) arg); - //void passUnionWithSequence((sequence<object> or long) arg); - void passUnionWithArrayBuffer((ArrayBuffer or long) arg); - void passUnionWithString((DOMString or object) arg); - //void passUnionWithEnum((TestEnum or object) arg); - void passUnionWithCallback((TestCallback or long) arg); - void passUnionWithObject((object or long) arg); - //void passUnionWithDict((Dict or long) arg); - - // binaryNames tests - void methodRenamedFrom(); - void methodRenamedFrom(byte argument); - readonly attribute byte attributeGetterRenamedFrom; - attribute byte attributeRenamedFrom; - - void passDictionary(optional Dict x); - void passOtherDictionary(optional GrandparentDict x); - void passSequenceOfDictionaries(sequence<Dict> x); - void passDictionaryOrLong(optional Dict x); - void passDictionaryOrLong(long x); - - void passDictContainingDict(optional DictContainingDict arg); - void passDictContainingSequence(optional DictContainingSequence arg); - - // EnforceRange/Clamp tests - void dontEnforceRangeOrClamp(byte arg); - void doEnforceRange([EnforceRange] byte arg); - void doClamp([Clamp] byte arg); - - // Typedefs - const myLong myLongConstant = 5; - void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg); - AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg); - void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg); - - // Miscellania - [LenientThis] attribute long attrWithLenientThis; -}; - -interface TestNonWrapperCacheInterface { -}; - -interface ImplementedInterfaceParent { - void implementedParentMethod(); - attribute boolean implementedParentProperty; - - const long implementedParentConstant = 8; -}; - -ImplementedInterfaceParent implements IndirectlyImplementedInterface; - -[NoInterfaceObject] -interface IndirectlyImplementedInterface { - void indirectlyImplementedMethod(); - attribute boolean indirectlyImplementedProperty; - - const long indirectlyImplementedConstant = 9; -}; - -interface ImplementedInterface : ImplementedInterfaceParent { - void implementedMethod(); - attribute boolean implementedProperty; - - const long implementedConstant = 5; -}; - -interface DiamondImplements { - readonly attribute long diamondImplementedProperty; -}; -interface DiamondBranch1A { -}; -interface DiamondBranch1B { -}; -interface DiamondBranch2A : DiamondImplements { -}; -interface DiamondBranch2B : DiamondImplements { -}; -TestInterface implements DiamondBranch1A; -TestInterface implements DiamondBranch1B; -TestInterface implements DiamondBranch2A; -TestInterface implements DiamondBranch2B; -DiamondBranch1A implements DiamondImplements; -DiamondBranch1B implements DiamondImplements; - -dictionary Dict : ParentDict { - TestEnum someEnum; - long x; - long a; - long b = 8; - long z = 9; - DOMString str; - DOMString empty = ""; - TestEnum otherEnum = "b"; - DOMString otherStr = "def"; - DOMString? yetAnotherStr = null; -}; - -dictionary ParentDict : GrandparentDict { - long c = 5; - TestInterface someInterface; - TestExternalInterface someExternalInterface; -}; - -dictionary DictContainingDict { - Dict memberDict; -}; - -dictionary DictContainingSequence { - sequence<long> ourSequence; -}; - -interface TestIndexedGetterInterface { - getter long item(unsigned long index); - [Infallible] - readonly attribute unsigned long length; -}; - -interface TestNamedGetterInterface { - getter DOMString (DOMString name); -}; - -interface TestIndexedAndNamedGetterInterface { - getter long (unsigned long index); - getter DOMString namedItem(DOMString name); - [Infallible] - readonly attribute unsigned long length; -}; - -interface TestIndexedSetterInterface { - setter creator void setItem(unsigned long index, DOMString item); -}; - -interface TestNamedSetterInterface { - setter creator void (DOMString name, TestIndexedSetterInterface item); -}; - -interface TestIndexedAndNamedSetterInterface { - setter creator void (unsigned long index, TestIndexedSetterInterface item); - setter creator void setNamedItem(DOMString name, TestIndexedSetterInterface item); -}; - -interface TestIndexedAndNamedGetterAndSetterInterface : TestIndexedSetterInterface { - getter long item(unsigned long index); - getter DOMString namedItem(DOMString name); - setter creator void (unsigned long index, long item); - setter creator void (DOMString name, DOMString item); - [Infallible] - stringifier DOMString (); - [Infallible] - readonly attribute unsigned long length; -}; diff --git a/src/components/script/dom/bindings/codegen/test/TestDictionary.webidl b/src/components/script/dom/bindings/codegen/test/TestDictionary.webidl deleted file mode 100644 index 3dd91bd6500..00000000000 --- a/src/components/script/dom/bindings/codegen/test/TestDictionary.webidl +++ /dev/null @@ -1,9 +0,0 @@ -/* -*- Mode: IDL; 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/. - */ - -dictionary GrandparentDict { - double someNum; -};
\ No newline at end of file diff --git a/src/components/script/dom/bindings/codegen/test/TestTypedef.webidl b/src/components/script/dom/bindings/codegen/test/TestTypedef.webidl deleted file mode 100644 index 7f758c79e8f..00000000000 --- a/src/components/script/dom/bindings/codegen/test/TestTypedef.webidl +++ /dev/null @@ -1,7 +0,0 @@ -/* -*- Mode: IDL; 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/. - */ - -typedef TestInterface YetAnotherNameForTestInterface; diff --git a/src/components/script/dom/bindings/codegen/test/file_bug775543.html b/src/components/script/dom/bindings/codegen/test/file_bug775543.html deleted file mode 100644 index ee8c14c4d9c..00000000000 --- a/src/components/script/dom/bindings/codegen/test/file_bug775543.html +++ /dev/null @@ -1,5 +0,0 @@ -<body> -<script> -worker = new Worker("a"); -</script> -</body> diff --git a/src/components/script/dom/bindings/codegen/test/forOf_iframe.html b/src/components/script/dom/bindings/codegen/test/forOf_iframe.html deleted file mode 100644 index 91417aba0e8..00000000000 --- a/src/components/script/dom/bindings/codegen/test/forOf_iframe.html +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>iframe content for test_forOf_iframe.html</title> -</head> -<body> - <div id="basket"> - <span id="egg0"></span> - <span id="egg1"><span id="duckling1"></span></span> - <span id="egg2"></span> - </div> -</body> -</html> diff --git a/src/components/script/dom/bindings/codegen/test/test_InstanceOf.html b/src/components/script/dom/bindings/codegen/test/test_InstanceOf.html deleted file mode 100644 index 3a5a76b1b21..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_InstanceOf.html +++ /dev/null @@ -1,28 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=748983 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 748983</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=748983">Mozilla Bug 748983</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -<script type="application/javascript"> - -/** Test for Bug 748983 **/ -ok(document instanceof EventTarget, "document is an event target") -ok(new XMLHttpRequest() instanceof XMLHttpRequest, "instanceof should work on XHR"); - -</script> -</pre> -</body> -</html> diff --git a/src/components/script/dom/bindings/codegen/test/test_bug773326.html b/src/components/script/dom/bindings/codegen/test/test_bug773326.html deleted file mode 100644 index 2e3b1ea304d..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_bug773326.html +++ /dev/null @@ -1,11 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>Test for Bug 773326</title> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<div id=log></div> -<script> -test(function() { - new Worker("data:text/javascript,new XMLHttpRequest(42)"); -}, "Should not crash") -</script> diff --git a/src/components/script/dom/bindings/codegen/test/test_bug775543.html b/src/components/script/dom/bindings/codegen/test/test_bug775543.html deleted file mode 100644 index d8df05f630f..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_bug775543.html +++ /dev/null @@ -1,37 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=775543 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 775543</title> - <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=775543">Mozilla Bug 775543</a> -<p id="display"></p> -<div id="content" style="display: none"> -<iframe id="t" src="http://example.org/tests/dom/bindings/test/file_bug775543.html" onload="test();"></iframe> -</div> -<pre id="test"> -<script type="application/javascript"> - -/** Test for Bug 775543 **/ - -function test() -{ - var a = XPCNativeWrapper(document.getElementById("t").contentWindow.wrappedJSObject.worker); - isnot(XPCNativeWrapper.unwrap(a), a, "XPCNativeWrapper(Worker) should be an Xray wrapper"); - a.toString(); - ok(true, "Shouldn't crash when calling a method on an Xray wrapper around a worker"); - SimpleTest.finish(); -} - -SimpleTest.waitForExplicitFinish(); - -</script> -</pre> -</body> -</html> diff --git a/src/components/script/dom/bindings/codegen/test/test_bug788369.html b/src/components/script/dom/bindings/codegen/test/test_bug788369.html deleted file mode 100644 index 787bd28fe34..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_bug788369.html +++ /dev/null @@ -1,30 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=788369 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 788369</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=788369">Mozilla Bug 788369</a> -<p id="display"></p> -<div id="content" style="display: none"> -</div> -<pre id="test"> -<script type="application/javascript"> - -/** Test for Bug 788369 **/ -try { - var xhr = new(window.ActiveXObject || XMLHttpRequest)("Microsoft.XMLHTTP"); - ok(xhr instanceof XMLHttpRequest, "Should have an XHR object"); -} catch (e) { - ok(false, "Should not throw exception when constructing: " + e); -} -</script> -</pre> -</body> -</html> diff --git a/src/components/script/dom/bindings/codegen/test/test_enums.html b/src/components/script/dom/bindings/codegen/test/test_enums.html deleted file mode 100644 index e5dc519a0c9..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_enums.html +++ /dev/null @@ -1,15 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>Enums</title> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<div id=log></div> -<script> -test(function() { - var xhr = new XMLHttpRequest(); - xhr.open("get", "foo") - assert_equals(xhr.responseType, ""); - xhr.responseType = "foo"; - assert_equals(xhr.responseType, ""); -}, "Assigning an invalid value to an enum attribute should not throw."); -</script> diff --git a/src/components/script/dom/bindings/codegen/test/test_forOf.html b/src/components/script/dom/bindings/codegen/test/test_forOf.html deleted file mode 100644 index b1a3032a385..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_forOf.html +++ /dev/null @@ -1,94 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=725907 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 725907</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=725907">Mozilla Bug 725907</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<div id="basket"> - <span id="egg0"></span> - <span id="egg1"><span id="duckling1"></span></span> - <span id="egg2"></span> -</div> -<pre id="test"> -<script type="application/javascript"> - -/** Test for Bug 725907 **/ - -function runTestsForDocument(document, msgSuffix) { - function is(a, b, msg) { SimpleTest.is(a, b, msg + msgSuffix); } - function isnot(a, b, msg) { SimpleTest.isnot(a, b, msg + msgSuffix); } - - var basket = document.getElementById("basket"); - var egg3 = document.createElement("span"); - egg3.id = "egg3"; - - var log = ''; - for (var x of basket.childNodes) { - if (x.nodeType != x.TEXT_NODE) - log += x.id + ";"; - } - is(log, "egg0;egg1;egg2;", "'for (x of div.childNodes)' should iterate over child nodes"); - - log = ''; - for (var x of basket.childNodes) { - if (x.nodeType != x.TEXT_NODE) { - log += x.id + ";"; - if (x.id == "egg1") - basket.appendChild(egg3); - } - } - is(log, "egg0;egg1;egg2;egg3;", "'for (x of div.childNodes)' should see elements added during iteration"); - - var iter1 = basket.childNodes.iterator(); - var iter2 = basket.childNodes.iterator(); - isnot(iter1, iter2, "nodelist.iterator() returns a new iterator each time"); - - log = ''; - basket.appendChild(document.createTextNode("some text")); - for (var x of basket.children) - log += x.id + ";"; - is(log, "egg0;egg1;egg2;egg3;", "'for (x of div.children)' should iterate over child elements"); - - var iter1 = basket.children.iterator(); - var iter2 = basket.children.iterator(); - isnot(iter1, iter2, ".iterator() returns a new iterator each time"); - - var count = 0; - for (var x of document.getElementsByClassName("hazardous-materials")) - count++; - is(count, 0, "'for (x of emptyNodeList)' loop should run zero times"); - - var log = ''; - for (var x of document.querySelectorAll("span")) - log += x.id + ";"; - is(log, "egg0;egg1;duckling1;egg2;egg3;", "for-of loop should work with a querySelectorAll() NodeList"); -} - -/* All the tests run twice. First, in this document, so without any wrappers. */ -runTestsForDocument(document, ""); - -/* And once using the document of an iframe, so working with cross-compartment wrappers. */ -SimpleTest.waitForExplicitFinish(); -function iframeLoaded(iframe) { - runTestsForDocument(iframe.contentWindow.document, " (in iframe)"); - SimpleTest.finish(); -} - -</script> - -<iframe src="forOf_iframe.html" onload="iframeLoaded(this)"></iframe> - -</pre> -</body> -</html> diff --git a/src/components/script/dom/bindings/codegen/test/test_integers.html b/src/components/script/dom/bindings/codegen/test/test_integers.html deleted file mode 100644 index 6799fd791a8..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_integers.html +++ /dev/null @@ -1,45 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <meta charset="utf-8"> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<p id="display"></p> -<div id="content" style="display: none"> - <canvas id="c" width="1" height="1"></canvas> -</div> -<pre id="test"> -<script type="application/javascript"> - - function testInt64NonFinite(arg) { - // We can use a WebGLRenderingContext to test conversion to 64-bit signed - // ints edge cases. - try { - var gl = $("c").getContext("experimental-webgl"); - } catch (ex) { - // No WebGL support on MacOS 10.5. Just skip this test - todo(false, "WebGL not supported"); - return; - } - is(gl.getError(), 0, "Should not start in an error state"); - - var b = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, b); - - var a = new Float32Array(1); - gl.bufferData(gl.ARRAY_BUFFER, a, gl.STATIC_DRAW); - - gl.bufferSubData(gl.ARRAY_BUFFER, arg, a); - - is(gl.getError(), 0, "Should have treated non-finite double as 0"); - } - - testInt64NonFinite(NaN); - testInt64NonFinite(Infinity); - testInt64NonFinite(-Infinity); -</script> -</pre> -</body> -</html> diff --git a/src/components/script/dom/bindings/codegen/test/test_interfaceToString.html b/src/components/script/dom/bindings/codegen/test/test_interfaceToString.html deleted file mode 100644 index cf670bf2d54..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_interfaceToString.html +++ /dev/null @@ -1,38 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=742156 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 742156</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742156">Mozilla Bug 742156</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -<script type="application/javascript"> - -/** Test for Bug 742156 **/ - -var nativeToString = ("" + String.replace).replace("replace", "EventTarget"); -try { - var eventTargetToString = "" + EventTarget; - is(eventTargetToString, nativeToString, - "Stringifying a DOM interface object should return the same string" + - "as stringifying a native function."); -} -catch (e) { - ok(false, "Stringifying a DOM interface object shouldn't throw."); -} - - -</script> -</pre> -</body> -</html> diff --git a/src/components/script/dom/bindings/codegen/test/test_lookupGetter.html b/src/components/script/dom/bindings/codegen/test/test_lookupGetter.html deleted file mode 100644 index 306ee4f643c..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_lookupGetter.html +++ /dev/null @@ -1,49 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=462428 ---> -<head> - <title>Test for Bug 462428</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=462428">Mozilla Bug 462428</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -<script type="application/javascript"> - -/** Test for Bug 462428 **/ -var x = new XMLHttpRequest; -x.open("GET", ""); -var getter = x.__lookupGetter__('readyState'); -ok(getter !== undefined, "But able to look it up the normal way"); -ok(!x.hasOwnProperty('readyState'), "property should still be on the prototype"); - -var sawProp = false; -for (var i in x) { - if (i === "readyState") { - sawProp = true; - } -} - -ok(sawProp, "property should be enumerable"); - -is(getter.call(x), 1, "the getter actually works"); - -Object.getPrototypeOf(x).__defineSetter__('readyState', function() {}); -is(getter.call(x), 1, "the getter works after defineSetter"); - -is(x.responseType, "", "Should have correct responseType up front"); -var setter = x.__lookupSetter__('responseType'); -setter.call(x, "document"); -is(x.responseType, "document", "the setter is bound correctly"); - -</script> -</pre> -</body> -</html> diff --git a/src/components/script/dom/bindings/codegen/test/test_sequence_wrapping.html b/src/components/script/dom/bindings/codegen/test/test_sequence_wrapping.html deleted file mode 100644 index e4f18f9986c..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_sequence_wrapping.html +++ /dev/null @@ -1,60 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=775852 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 775852</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=775852">Mozilla Bug 775852</a> -<p id="display"></p> -<div id="content" style="display: none"> - <canvas width="1" height="1" id="c"></canvas> -</div> -<pre id="test"> -<script type="application/javascript"> - -/** Test for Bug 775852 **/ -function doTest() { - try { - var gl = $("c").getContext("experimental-webgl"); - } catch (e) { - // No WebGL support on MacOS 10.5. Just skip this test - todo(false, "WebGL not supported"); - return; - } - var setterCalled = false; - - extLength = gl.getSupportedExtensions().length; - ok(extLength > 0, - "This test won't work right if we have no supported extensions"); - - Object.defineProperty(Array.prototype, "0", - { - set: function(val) { - setterCalled = true; - } - }); - - // Test that our property got defined correctly - var arr = [] - arr[0] = 5; - is(setterCalled, true, "Setter should be called when setting prop on array"); - - setterCalled = false; - - is(gl.getSupportedExtensions().length, extLength, - "We should still have the same number of extensions"); - - is(setterCalled, false, - "Setter should not be called when getting supported extensions"); -} -doTest(); -</script> -</pre> -</body> -</html> diff --git a/src/components/script/dom/bindings/codegen/test/test_traceProtos.html b/src/components/script/dom/bindings/codegen/test/test_traceProtos.html deleted file mode 100644 index 195876744d6..00000000000 --- a/src/components/script/dom/bindings/codegen/test/test_traceProtos.html +++ /dev/null @@ -1,37 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=744772 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 744772</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=744772">Mozilla Bug 744772</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -<script type="application/javascript"> - -/** Test for Bug 744772 **/ - -SimpleTest.waitForExplicitFinish(); - -function callback() { - new XMLHttpRequest().upload; - ok(true, "Accessing unreferenced DOM interface objects shouldn't crash"); - SimpleTest.finish(); -} - -delete window.XMLHttpRequestUpload; -SpecialPowers.exactGC(window, callback); - -</script> -</pre> -</body> -</html> |