author | Boris Zbarsky <bzbarsky@mit.edu> |
Fri, 16 Oct 2015 16:16:36 -0400 | |
changeset 268120 | 7f2e5ec068f70139a0534d8d5113454d4f001a83 |
parent 268119 | dba4e2f06001d4ecae3a44d3676eaacb33fcbf8e |
child 268121 | 09e059daabae5ad4df486a1ce2bf8e83c22188d2 |
push id | 66704 |
push user | bzbarsky@mozilla.com |
push date | Fri, 16 Oct 2015 20:16:44 +0000 |
treeherder | mozilla-inbound@7f2e5ec068f7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1215559 |
milestone | 44.0a1 |
backs out | 5985a47177581ad830879c9eb2b7908900130c51 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -7,17 +7,17 @@ import os import re import string import math import textwrap import functools from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLInterfaceMember, IDLUndefinedValue, IDLEmptySequenceValue, IDLDictionary -from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, getAllTypes, Descriptor, MemberIsUnforgeable, iteratorNativeType +from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, getAllTypes, Descriptor, MemberIsUnforgeable AUTOGENERATED_WARNING_COMMENT = \ "/* THIS FILE IS AUTOGENERATED BY Codegen.py - DO NOT EDIT */\n\n" AUTOGENERATED_WITH_SOURCE_WARNING_COMMENT = \ "/* THIS FILE IS AUTOGENERATED FROM %s BY Codegen.py - DO NOT EDIT */\n\n" ADDPROPERTY_HOOK_NAME = '_addProperty' FINALIZE_HOOK_NAME = '_finalize' OBJECT_MOVED_HOOK_NAME = '_objectMoved' @@ -15467,22 +15467,22 @@ class CGIterableMethodGenerator(CGGeneri Creates methods for iterable interfaces. Unwrapping/wrapping will be taken care of by the usual method generation machinery in CGMethodCall/CGPerSignatureCall. Functionality is filled in here instead of using CGCallGenerator. """ def __init__(self, descriptor, iterable, methodName): CGGeneric.__init__(self, fill( """ - typedef ${iterClass} itrType; + typedef IterableIterator<${nativeType}> itrType; nsRefPtr<itrType> result(new itrType(self, itrType::IterableIteratorType::${itrMethod}, &${ifaceName}IteratorBinding::Wrap)); """, - iterClass=iteratorNativeType(descriptor), + nativeType=descriptor.nativeType, ifaceName=descriptor.interface.identifier.name, itrMethod=methodName.title())) class GlobalGenRoots(): """ Roots for global codegen.
--- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -355,17 +355,18 @@ class Descriptor(DescriptorProvider): # For generated iterator interfaces for other iterable interfaces, we # just use IterableIterator as the native type, templated on the # nativeType of the iterable interface. That way we can have a # templated implementation for all the duplicated iterator # functionality. if self.interface.isIteratorInterface(): itrName = self.interface.iterableInterface.identifier.name itrDesc = self.getDescriptor(itrName) - nativeTypeDefault = iteratorNativeType(itrDesc) + nativeTypeDefault = ("mozilla::dom::IterableIterator<%s>" + % itrDesc.nativeType) elif self.interface.isExternal(): assert not self.workers nativeTypeDefault = "nsIDOM" + ifaceName elif self.interface.isCallback(): nativeTypeDefault = "mozilla::dom::" + ifaceName else: if self.workers: @@ -884,17 +885,8 @@ def getAllTypes(descriptors, dictionarie 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 iteratorNativeType(descriptor): - assert descriptor.interface.isIterable() - iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable - if iterableDecl.valueType is None: - iterClass = "OneTypeIterableIterator" - else: - iterClass = "TwoTypeIterableIterator" - return "mozilla::dom::%s<%s>" % (iterClass, descriptor.nativeType)
--- a/dom/bindings/IterableIterator.h +++ b/dom/bindings/IterableIterator.h @@ -4,28 +4,26 @@ * 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 IterableIterator class is used for WebIDL interfaces that have a * iterable<> member defined. It handles the ES6 Iterator-like functions that * are generated for the iterable interface. * - * For iterable interfaces, the implementation class will need to - * implement these two functions: + * For iterable interfaces, the implementation class will need to contain three + * functions: * * - size_t GetIterableLength() * - Returns the number of elements available to iterate over - * - [type] GetValueAtIndex(size_t index) - * - Returns the value at the requested index. - * - * If this is a two-type iterator, then the implementation class will also need to implement: - * * - [type] GetKeyAtIndex(size_t index) * - Returns the key at the requested index + * - [type] GetValueAtIndex(size_t index) + * - Returns the value at the requested index, or the key again if this is + * a single type iterator. * * Examples of iterable interface implementations can be found in the bindings * test directory. */ #ifndef mozilla_dom_IterableIterator_h #define mozilla_dom_IterableIterator_h @@ -55,243 +53,140 @@ public: protected: virtual ~IterableIteratorBase() {} virtual void UnlinkHelper() = 0; virtual void TraverseHelper(nsCycleCollectionTraversalCallback& cb) = 0; }; template <typename T> -class IterableIterator : public IterableIteratorBase +class IterableIterator final : public IterableIteratorBase { public: - IterableIterator(T* aIterableObj) - : mIterableObj(aIterableObj) + + typedef bool (*WrapFunc)(JSContext* aCx, + mozilla::dom::IterableIterator<T>* aObject, + JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aReflector); + IterableIterator(T* aIterableObj, IterableIteratorType aIteratorType, WrapFunc aWrapFunc) + : mIteratorType(aIteratorType) + , mIterableObj(aIterableObj) + , mIndex(0) + , mWrapFunc(aWrapFunc) { MOZ_ASSERT(mIterableObj); + MOZ_ASSERT(mWrapFunc); } -protected: - static void + void DictReturn(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, bool aDone, JS::Handle<JS::Value> aValue, ErrorResult& aRv) { RootedDictionary<IterableKeyOrValueResult> dict(aCx); dict.mDone = aDone; dict.mValue = aValue; JS::Rooted<JS::Value> dictValue(aCx); if (!ToJSValue(aCx, dict, &dictValue)) { aRv.Throw(NS_ERROR_FAILURE); return; } aResult.set(&dictValue.toObject()); } - static void - KeyAndValueReturn(JSContext* aCx, JS::Handle<JS::Value> aKey, - JS::Handle<JS::Value> aValue, - JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv) + void + Next(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv) { - RootedDictionary<IterableKeyAndValueResult> dict(aCx); - dict.mDone = false; - // Dictionary values are a Sequence, which is a FallibleTArray, so we need - // to check returns when appending. - if (!dict.mValue.AppendElement(aKey, mozilla::fallible)) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + JS::Rooted<JS::Value> value(aCx, JS::UndefinedValue()); + if (mIndex >= mIterableObj->GetIterableLength()) { + DictReturn(aCx, aResult, true, value, aRv); return; } - if (!dict.mValue.AppendElement(aValue, mozilla::fallible)) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; + switch (mIteratorType) { + case IterableIteratorType::Keys: + { + if (!ToJSValue(aCx, mIterableObj->GetKeyAtIndex(mIndex), &value)) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + DictReturn(aCx, aResult, false, value, aRv); + break; + } + case IterableIteratorType::Values: + { + if (!ToJSValue(aCx, mIterableObj->GetValueAtIndex(mIndex), &value)) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + DictReturn(aCx, aResult, false, value, aRv); + break; } - JS::Rooted<JS::Value> dictValue(aCx); - if (!ToJSValue(aCx, dict, &dictValue)) { - aRv.Throw(NS_ERROR_FAILURE); - return; + case IterableIteratorType::Entries: + { + JS::Rooted<JS::Value> key(aCx); + if (!ToJSValue(aCx, mIterableObj->GetKeyAtIndex(mIndex), &key)) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + if (!ToJSValue(aCx, mIterableObj->GetValueAtIndex(mIndex), &value)) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + RootedDictionary<IterableKeyAndValueResult> dict(aCx); + dict.mDone = false; + // Dictionary values are a Sequence, which is a FallibleTArray, so we need + // to check returns when appending. + if (!dict.mValue.AppendElement(key, mozilla::fallible)) { + aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + return; + } + if (!dict.mValue.AppendElement(value, mozilla::fallible)) { + aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + return; + } + JS::Rooted<JS::Value> dictValue(aCx); + if (!ToJSValue(aCx, dict, &dictValue)) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + aResult.set(&dictValue.toObject()); + break; } - aResult.set(&dictValue.toObject()); + default: + MOZ_CRASH("Invalid iterator type!"); + } + ++mIndex; + } + virtual ~IterableIterator() {} + + bool + WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aObj) + { + return (*mWrapFunc)(aCx, this, aGivenProto, aObj); } protected: - virtual ~IterableIterator() {} + // Tells whether this is a key, value, or entries iterator. + IterableIteratorType mIteratorType; + // Binding Implementation Object that we're iterating over. + nsRefPtr<T> mIterableObj; + // Current index of iteration. + uint32_t mIndex; + // Function pointer to binding-type-specific Wrap() call for this iterator. + WrapFunc mWrapFunc; // Since we're templated on a binding, we need to possibly CC it, but can't do // that through macros. So it happens here. virtual void UnlinkHelper() final { mIterableObj = nullptr; } virtual void TraverseHelper(nsCycleCollectionTraversalCallback& cb) override { IterableIterator<T>* tmp = this; NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIterableObj); } - - // Binding Implementation object that we're iterating over. - nsRefPtr<T> mIterableObj; -}; - -template<typename T> -class OneTypeIterableIterator final : public IterableIterator<T> -{ -public: - using typename IterableIterator<T>::IterableIteratorType; - using IterableIterator<T>::DictReturn; - using IterableIterator<T>::KeyAndValueReturn; - typedef bool (*WrapFunc)(JSContext* aCx, - OneTypeIterableIterator<T>* aObject, - JS::Handle<JSObject*> aGivenProto, - JS::MutableHandle<JSObject*> aReflector); - - OneTypeIterableIterator(T* aIterableObj, - IterableIteratorType aIteratorType, - WrapFunc aWrapFunc) - : IterableIterator<T>(aIterableObj) - , mIteratorType(aIteratorType) - , mWrapFunc(aWrapFunc) - , mIndex(0) - { - MOZ_ASSERT(mWrapFunc); - } - - void - Next(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv) - { - JS::Rooted<JS::Value> value(aCx, JS::UndefinedValue()); - if (mIndex >= this->mIterableObj->GetIterableLength()) { - DictReturn(aCx, aResult, true, value, aRv); - return; - } - - switch (mIteratorType) { - case IterableIteratorType::Keys: - case IterableIteratorType::Values: - { - if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) { - aRv.Throw(NS_ERROR_FAILURE); - return; - } - DictReturn(aCx, aResult, false, value, aRv); - break; - } - case IterableIteratorType::Entries: - { - if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) { - aRv.Throw(NS_ERROR_FAILURE); - return; - } - KeyAndValueReturn(aCx, value, value, aResult, aRv); - break; - } - default: - MOZ_CRASH("Invalid iterator type!"); - } - ++mIndex; - } - - bool - WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aObj) - { - return (*mWrapFunc)(aCx, this, aGivenProto, aObj); - } - -protected: - virtual ~OneTypeIterableIterator() {} - - // Tells whether this is a key, value, or entries iterator. - IterableIteratorType mIteratorType; - // Function pointer to binding-type-specific Wrap() call for this iterator. - WrapFunc mWrapFunc; - // Current index of iteration. - uint32_t mIndex; -}; - -template<typename T> -class TwoTypeIterableIterator final : public IterableIterator<T> -{ -public: - using typename IterableIterator<T>::IterableIteratorType; - using IterableIterator<T>::DictReturn; - using IterableIterator<T>::KeyAndValueReturn; - typedef bool (*WrapFunc)(JSContext* aCx, - TwoTypeIterableIterator<T>* aObject, - JS::Handle<JSObject*> aGivenProto, - JS::MutableHandle<JSObject*> aReflector); - - TwoTypeIterableIterator(T* aIterableObj, IterableIteratorType aIteratorType, - WrapFunc aWrapFunc) - : IterableIterator<T>(aIterableObj) - , mIteratorType(aIteratorType) - , mWrapFunc(aWrapFunc) - , mIndex(0) - { - MOZ_ASSERT(mWrapFunc); - } - - void - Next(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv) - { - JS::Rooted<JS::Value> value(aCx, JS::UndefinedValue()); - if (mIndex >= this->mIterableObj->GetIterableLength()) { - DictReturn(aCx, aResult, true, value, aRv); - return; - } - switch (mIteratorType) { - case IterableIteratorType::Keys: - { - if (!ToJSValue(aCx, this->mIterableObj->GetKeyAtIndex(mIndex), &value)) { - aRv.Throw(NS_ERROR_FAILURE); - return; - } - DictReturn(aCx, aResult, false, value, aRv); - break; - } - case IterableIteratorType::Values: - { - if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) { - aRv.Throw(NS_ERROR_FAILURE); - return; - } - DictReturn(aCx, aResult, false, value, aRv); - break; - } - case IterableIteratorType::Entries: - { - JS::Rooted<JS::Value> key(aCx); - if (!ToJSValue(aCx, this->mIterableObj->GetKeyAtIndex(mIndex), &key)) { - aRv.Throw(NS_ERROR_FAILURE); - return; - } - if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) { - aRv.Throw(NS_ERROR_FAILURE); - return; - } - KeyAndValueReturn(aCx, key, value, aResult, aRv); - break; - } - default: - MOZ_CRASH("Invalid iterator type!"); - } - ++mIndex; - } - - bool - WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aObj) - { - return (*mWrapFunc)(aCx, this, aGivenProto, aObj); - } - -protected: - virtual ~TwoTypeIterableIterator() {} - - // Tells whether this is a key, value, or entries iterator. - IterableIteratorType mIteratorType; - // Function pointer to binding-type-specific Wrap() call for this iterator. - WrapFunc mWrapFunc; - // Current index of iteration. - uint32_t mIndex; }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_IterableIterator_h
--- a/dom/bindings/test/TestInterfaceIterableSingle.cpp +++ b/dom/bindings/test/TestInterfaceIterableSingle.cpp @@ -57,16 +57,22 @@ TestInterfaceIterableSingle::GetParentOb size_t TestInterfaceIterableSingle::GetIterableLength() const { return mValues.Length(); } uint32_t -TestInterfaceIterableSingle::GetValueAtIndex(uint32_t index) const +TestInterfaceIterableSingle::GetKeyAtIndex(uint32_t index) const { MOZ_ASSERT(index < mValues.Length()); return mValues.ElementAt(index); } +uint32_t +TestInterfaceIterableSingle::GetValueAtIndex(uint32_t index) const +{ + return GetKeyAtIndex(index); +} + } // namespace dom } // namespace mozilla
--- a/dom/bindings/test/TestInterfaceIterableSingle.h +++ b/dom/bindings/test/TestInterfaceIterableSingle.h @@ -32,16 +32,17 @@ public: explicit TestInterfaceIterableSingle(nsPIDOMWindow* aParent); nsPIDOMWindow* GetParentObject() const; virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; static already_AddRefed<TestInterfaceIterableSingle> Constructor(const GlobalObject& aGlobal, ErrorResult& rv); size_t GetIterableLength() const; + uint32_t GetKeyAtIndex(uint32_t aIndex) const; uint32_t GetValueAtIndex(uint32_t aIndex) const; private: virtual ~TestInterfaceIterableSingle() {} nsCOMPtr<nsPIDOMWindow> mParent; nsTArray<uint32_t> mValues; }; } // namespace dom