Bug 1484496: Part 4a - Add JS iterator support to nsISimpleEnumerator. r=mccr8

This patch adds simple stubs to convert between the nsISimpleEnumerator
iteration protocol and the JS iteration protocol.

Each iterable object is required to have an @@iterator method which returns an
object implementing the iterator protocol. The later objects, by convention,
also have such a method which returns the object itself.

This patch adds both a @@iterator() and entries() methods to
nsISimpleEnumerator. The former returns an iterator which returns plain
nsISupports objects. The latter accepts an IID and queries each element to
that IID before returning it. If any element fails to query, the error is
propagated to the caller.

Differential Revision: https://phabricator.services.mozilla.com/D3727

--HG--
extra : rebase_source : 340eb43a1c5e6d7ae69fa8ee486d66d31d079b14
extra : histedit_source : f3efc6c265851a563968ee410e4626e0540f55c0
This commit is contained in:
Kris Maglione 2018-08-18 16:02:49 -07:00
parent 0425e42aa8
commit c943b2a5c4
9 changed files with 139 additions and 4 deletions

View File

@ -0,0 +1,14 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 https://mozilla.org/MPL/2.0/. */
/**
* A dictionary which represents the result of a call to a next() method on a
* JS iterator object.
*/
dictionary IteratorResult {
required boolean done;
any value;
};

View File

@ -34,6 +34,7 @@ WEBIDL_FILES = [
'DominatorTree.webidl',
'HeapSnapshot.webidl',
'InspectorUtils.webidl',
'IteratorResult.webidl',
'MatchGlob.webidl',
'MatchPattern.webidl',
'MessageManager.webidl',

View File

@ -5130,6 +5130,9 @@ nsSimpleEnumerator.prototype =
return this._items[this._nextIndex++];
},
[Symbol.iterator]() {
return this._items.values();
},
QueryInterface: function(aIID)
{
if (Ci.nsISimpleEnumerator.equals(aIID) ||

View File

@ -214,12 +214,15 @@ MockFilePickerInstance.prototype = {
return {
index: 0,
QueryInterface: ChromeUtils.generateQI([Ci.nsISimpleEnumerator]),
[Symbol.iterator]() {
return Array.from(MockFilePicker.returnData, d => d.nsIFile).values();
},
hasMoreElements() {
return this.index < MockFilePicker.returnData.length;
},
getNext() {
if (!MockFilePicker.returnData[this.index].nsIFile) {
return null;
throw Components.Exception("", Cr.NS_ERROR_FAILURE);
}
return MockFilePicker.returnData[this.index++].nsIFile;
}

View File

@ -14,8 +14,38 @@
* @version 1.0
*/
/**
* A wrapper for an nsISimpleEnumerator instance which implements the
* JavaScript iteration protocol.
*/
[scriptable, uuid(4432e8ae-d4d3-42a6-a4d1-829f1c29512b)]
interface nsIJSEnumerator : nsISupports {
[symbol]
nsIJSEnumerator iterator();
[implicit_jscontext]
jsval next();
};
[scriptable, uuid(796f340d-0a2a-490b-9c60-640765e99782)]
interface nsISimpleEnumeratorBase : nsISupports {
/**
* Returns a JavaScript iterator for all remaining entries in the enumerator.
* Each entry is queried only to nsISupports.
*/
[symbol]
nsIJSEnumerator iterator();
/**
* Returns JavaScript iterator for all remaining entries in the enumerator.
* Each entry is queried only to the supplied interface. If any element
* fails to query to that interface, the error is propagated to the caller.
*/
nsIJSEnumerator entries(in nsIIDRef aIface);
};
[scriptable, uuid(D1899240-F9D2-11D2-BDD6-000064657374)]
interface nsISimpleEnumerator : nsISupports {
interface nsISimpleEnumerator : nsISimpleEnumeratorBase {
/**
* Called to determine whether or not the enumerator has
* any elements that can be returned via getNext(). This method
@ -27,7 +57,7 @@ interface nsISimpleEnumerator : nsISupports {
* @see getNext()
* @return true if there are remaining elements in the enumerator.
* false if there are no more elements in the enumerator.
*/
*/
boolean hasMoreElements();
/**

View File

@ -6,4 +6,82 @@
#include "nsSimpleEnumerator.h"
NS_IMPL_ISUPPORTS(nsSimpleEnumerator, nsISimpleEnumerator)
#include "mozilla/dom/IteratorResultBinding.h"
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/ResultExtensions.h"
#include "nsContentUtils.h"
using namespace mozilla;
using namespace mozilla::dom;
namespace {
class JSEnumerator final : public nsIJSEnumerator
{
NS_DECL_ISUPPORTS
NS_DECL_NSIJSENUMERATOR
explicit JSEnumerator(nsISimpleEnumerator* aEnumerator, const nsID& aIID)
: mEnumerator(aEnumerator)
, mIID(aIID)
{}
private:
~JSEnumerator() = default;
nsCOMPtr<nsISimpleEnumerator> mEnumerator;
const nsID mIID;
};
} // anonymous namespace
nsresult
JSEnumerator::Iterator(nsIJSEnumerator** aResult)
{
RefPtr<JSEnumerator> result(this);
result.forget(aResult);
return NS_OK;
}
nsresult
JSEnumerator::Next(JSContext* aCx, JS::MutableHandleValue aResult)
{
RootedDictionary<IteratorResult> result(aCx);
nsCOMPtr<nsISupports> elem;
if (NS_FAILED(mEnumerator->GetNext(getter_AddRefs(elem)))) {
result.mDone = true;
} else {
result.mDone = false;
JS::RootedValue value(aCx);
MOZ_TRY(nsContentUtils::WrapNative(aCx, elem, &mIID, &value));
result.mValue = value;
}
if (!ToJSValue(aCx, result, aResult)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
NS_IMPL_ISUPPORTS(JSEnumerator, nsIJSEnumerator)
nsresult
nsSimpleEnumerator::Iterator(nsIJSEnumerator **aResult)
{
auto result = MakeRefPtr<JSEnumerator>(this, NS_GET_IID(nsISupports));
result.forget(aResult);
return NS_OK;
}
nsresult
nsSimpleEnumerator::Entries(const nsIID& aIface, nsIJSEnumerator **aResult)
{
auto result = MakeRefPtr<JSEnumerator>(this, aIface);
result.forget(aResult);
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsSimpleEnumerator, nsISimpleEnumerator, nsISimpleEnumeratorBase)

View File

@ -12,6 +12,7 @@
class nsSimpleEnumerator : public nsISimpleEnumerator
{
NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATORBASE
protected:
virtual ~nsSimpleEnumerator() = default;

View File

@ -108,6 +108,8 @@ public:
NS_IMETHOD Init(nsLocalFile* aParent, bool aIgnored);
NS_FORWARD_NSISIMPLEENUMERATORBASE(nsSimpleEnumerator::)
private:
~nsDirEnumeratorUnix() override;

View File

@ -238,6 +238,7 @@ public:
nsDriveEnumerator();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSISIMPLEENUMERATOR
NS_FORWARD_NSISIMPLEENUMERATORBASE(nsSimpleEnumerator::)
nsresult Init();
NS_IMETHOD GetNextFile(nsIFile** aResult) override
@ -694,6 +695,8 @@ private:
public:
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_NSISIMPLEENUMERATORBASE(nsSimpleEnumerator::)
nsDirEnumerator() : mDir(nullptr)
{
}