Merge inbound to mozilla-central. a=merge

This commit is contained in:
Bogdan Tara 2018-09-07 06:36:44 +03:00
Родитель 8022e747ad ea6e6b7d15
Коммит 2cab48f64d
18 изменённых файлов: 342 добавлений и 292 удалений

Просмотреть файл

@ -2428,34 +2428,6 @@ function getLocalHandlerApp(aFile) {
return localHandlerApp;
}
/**
* An enumeration of items in a JS array.
*
* FIXME: use ArrayConverter once it lands (bug 380839).
*
* @constructor
*/
function ArrayEnumerator(aItems) {
this._index = 0;
this._contents = aItems;
}
ArrayEnumerator.prototype = {
_index: 0,
[Symbol.iterator]() {
return this._contents.values();
},
hasMoreElements() {
return this._index < this._contents.length;
},
getNext() {
return this._contents[this._index++];
},
};
function isFeedType(t) {
return t == TYPE_MAYBE_FEED || t == TYPE_MAYBE_VIDEO_FEED || t == TYPE_MAYBE_AUDIO_FEED;
}
@ -3006,7 +2978,7 @@ class FeedHandlerInfo extends HandlerInfoWrapper {
},
enumerate() {
return new ArrayEnumerator(this._inner);
return this._inner.values();
},
appendElement(aHandlerApp, aWeak) {

Просмотреть файл

@ -11,6 +11,7 @@
#include "xpcprivate.h"
#include "nsIScriptError.h"
#include "nsISimpleEnumerator.h"
#include "nsWrapperCache.h"
#include "nsJSUtils.h"
#include "nsQueryObject.h"

Просмотреть файл

@ -611,6 +611,29 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
return rv;
}
// If we're asked to QI to nsISimpleEnumerator and the wrapped object does not have a
// QueryInterface method, assume it is a JS iterator, and wrap it into an equivalent
// nsISimpleEnumerator.
if (aIID.Equals(NS_GET_IID(nsISimpleEnumerator))) {
bool found;
XPCJSContext* xpccx = ccx.GetContext();
if (JS_HasPropertyById(aes.cx(), obj,
xpccx->GetStringID(xpccx->IDX_QUERY_INTERFACE),
&found) && !found) {
nsresult rv;
nsCOMPtr<nsIJSEnumerator> jsEnum;
if (!XPCConvert::JSObject2NativeInterface(aes.cx(),
getter_AddRefs(jsEnum), obj,
&NS_GET_IID(nsIJSEnumerator),
nullptr, &rv)) {
return rv;
}
nsCOMPtr<nsISimpleEnumerator> res = new XPCWrappedJSIterator(jsEnum);
res.forget(aInstancePtr);
return NS_OK;
}
}
// else we do the more expensive stuff...
// check if the JSObject claims to implement this interface

Просмотреть файл

@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
/* 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 "xpcprivate.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/dom/IteratorResultBinding.h"
#include "mozilla/dom/ScriptSettings.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace xpc;
NS_IMPL_CYCLE_COLLECTION(XPCWrappedJSIterator, mEnum, mGlobal, mNext)
NS_IMPL_CYCLE_COLLECTING_ADDREF(XPCWrappedJSIterator)
NS_IMPL_CYCLE_COLLECTING_RELEASE(XPCWrappedJSIterator)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPCWrappedJSIterator)
NS_INTERFACE_MAP_ENTRY(nsISimpleEnumerator)
NS_INTERFACE_MAP_ENTRY(nsISimpleEnumeratorBase)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, XPCWrappedJSIterator)
NS_INTERFACE_MAP_END
XPCWrappedJSIterator::XPCWrappedJSIterator(nsIJSEnumerator* aEnum)
: mEnum(aEnum)
{
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(aEnum);
MOZ_ASSERT(wrapped);
mGlobal = NativeGlobal(wrapped->GetJSObjectGlobal());
}
nsresult
XPCWrappedJSIterator::HasMoreElements(bool* aRetVal)
{
if (mHasNext.isNothing()) {
AutoJSAPI jsapi;
MOZ_ALWAYS_TRUE(jsapi.Init(mGlobal));
JSContext* cx = jsapi.cx();
JS::RootedValue val(cx);
MOZ_TRY(mEnum->Next(cx, &val));
RootedDictionary<IteratorResult> result(cx);
if (!result.Init(cx, val)) {
return NS_ERROR_FAILURE;
}
if (!result.mDone) {
if (result.mValue.isObject()) {
JS::RootedObject obj(cx, &result.mValue.toObject());
nsresult rv;
if (!XPCConvert::JSObject2NativeInterface(
cx, getter_AddRefs(mNext), obj,
&NS_GET_IID(nsISupports), nullptr,
&rv)) {
return rv;
}
} else {
mNext = XPCVariant::newVariant(cx, result.mValue);
}
}
mHasNext = Some(!result.mDone);
}
*aRetVal = *mHasNext;
return NS_OK;
}
nsresult
XPCWrappedJSIterator::GetNext(nsISupports** aRetVal)
{
bool hasMore;
MOZ_TRY(HasMoreElements(&hasMore));
if (!hasMore) {
return NS_ERROR_FAILURE;
}
mNext.forget(aRetVal);
mHasNext = Nothing();
return NS_OK;
}
nsresult
XPCWrappedJSIterator::Iterator(nsIJSEnumerator** aRetVal)
{
nsCOMPtr<nsIJSEnumerator> jsEnum = mEnum;
jsEnum.forget(aRetVal);
return NS_OK;
}
nsresult
XPCWrappedJSIterator::Entries(const nsID&, nsIJSEnumerator** aRetVal)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

Просмотреть файл

@ -35,6 +35,7 @@ UNIFIED_SOURCES += [
'XPCVariant.cpp',
'XPCWrappedJS.cpp',
'XPCWrappedJSClass.cpp',
'XPCWrappedJSIterator.cpp',
'XPCWrappedNative.cpp',
'XPCWrappedNativeInfo.cpp',
'XPCWrappedNativeJSOps.cpp',

Просмотреть файл

@ -108,6 +108,7 @@
#include "nsIComponentManager.h"
#include "nsIComponentRegistrar.h"
#include "nsISupportsPrimitives.h"
#include "nsISimpleEnumerator.h"
#include "nsMemory.h"
#include "nsIXPConnect.h"
#include "nsIXPCScriptable.h"
@ -1944,6 +1945,31 @@ private:
nsCOMPtr<nsIVariant> mValue;
};
namespace xpc {
// A wrapper around JS iterators which presents an equivalent
// nsISimpleEnumerator interface for their contents.
class XPCWrappedJSIterator final : public nsISimpleEnumerator
{
public:
NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedJSIterator)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
NS_DECL_NSISIMPLEENUMERATORBASE
explicit XPCWrappedJSIterator(nsIJSEnumerator* aEnum);
private:
~XPCWrappedJSIterator() = default;
nsCOMPtr<nsIJSEnumerator> mEnum;
nsCOMPtr<nsIGlobalObject> mGlobal;
nsCOMPtr<nsISupports> mNext;
mozilla::Maybe<bool> mHasNext;
};
} // namespace xpc
/***************************************************************************/
// class here just for static methods
class XPCConvert

Просмотреть файл

@ -0,0 +1,57 @@
"use strict";
// Tests that JS iterators are automatically wrapped into
// equivalent nsISimpleEnumerator objects.
const Variant = Components.Constructor("@mozilla.org/variant;1",
"nsIWritableVariant",
"setFromVariant");
const SupportsInterfacePointer = Components.Constructor(
"@mozilla.org/supports-interface-pointer;1", "nsISupportsInterfacePointer");
function wrapEnumerator(iter) {
var ip = SupportsInterfacePointer();
ip.data = iter;
return ip.data.QueryInterface(Ci.nsISimpleEnumerator);
}
function enumToArray(iter) {
let result = [];
while (iter.hasMoreElements()) {
result.push(iter.getNext().QueryInterface(Ci.nsIVariant));
}
return result;
}
add_task(async function test_wrapped_js_enumerator() {
let array = [1, 2, 3, 4];
// Test a plain JS iterator. This should automatically be wrapped into
// an equivalent nsISimpleEnumerator.
{
let iter = wrapEnumerator(array.values());
let result = enumToArray(iter);
deepEqual(result, array, "Got correct result");
}
// Test an object with a QueryInterface method, which implements
// nsISimpleEnumerator. This should be wrapped and used directly.
{
let obj = {
QueryInterface: ChromeUtils.generateQI(["nsISimpleEnumerator"]),
_idx: 0,
hasMoreElements() {
return this._idx < array.length;
},
getNext() {
return Variant(array[this._idx++]);
},
};
let iter = wrapEnumerator(obj);
let result = enumToArray(iter);
deepEqual(result, array, "Got correct result");
}
});

Просмотреть файл

@ -148,3 +148,4 @@ head = head_watchdog.js
[test_SubscriptLoaderSandboxEnvironment.js]
[test_SubscriptLoaderJSMEnvironment.js]
[test_ComponentEnvironment.js]
[test_wrapped_js_enumerator.js]

Просмотреть файл

@ -137,19 +137,7 @@ DirectoryProvider.prototype = {
let result = [];
this._appendDistroSearchDirs(result);
return {
QueryInterface: ChromeUtils.generateQI([Ci.nsISimpleEnumerator]),
[Symbol.iterator]() {
return result.values();
},
hasMoreElements: function() {
return result.length > 0;
},
getNext: function() {
return result.shift();
}
};
return result.values();
},
_getDistributionDirectories: function() {

Просмотреть файл

@ -138,7 +138,7 @@ FilePicker.prototype = {
},
get files() {
return this.getEnumerator([this.file]);
return [this.file].values();
},
// We don't support directory selection yet.
@ -147,7 +147,7 @@ FilePicker.prototype = {
},
get domFileOrDirectoryEnumerator() {
return this.getEnumerator([this._domFile]);
return [this._domFile].values();
},
get addToRecentDocs() {
@ -248,26 +248,6 @@ FilePicker.prototype = {
});
},
getEnumerator: function(files) {
return {
QueryInterface: ChromeUtils.generateQI([Ci.nsISimpleEnumerator]),
mFiles: files,
mIndex: 0,
[Symbol.iterator]() {
return this.mFiles.values();
},
hasMoreElements: function() {
return (this.mIndex < this.mFiles.length);
},
getNext: function() {
if (this.mIndex >= this.mFiles.length) {
throw Cr.NS_ERROR_FAILURE;
}
return this.mFiles[this.mIndex++];
}
};
},
fireDialogEvent: function(aDomWin, aEventName) {
// accessing the document object can throw if this window no longer exists. See bug 789888.
try {

Просмотреть файл

@ -865,36 +865,17 @@ FilePickerDelegate.prototype = {
return Services.io.newFileURI(this.file);
},
_getEnumerator(aDOMFile) {
* _getEnumerator(aDOMFile) {
if (!this._files) {
throw Cr.NS_ERROR_NOT_AVAILABLE;
}
return {
QueryInterface: ChromeUtils.generateQI([Ci.nsISimpleEnumerator]),
_owner: this,
_index: 0,
* [Symbol.iterator]() {
for (let file of this._owner._files) {
if (aDOMFile) {
yield this._owner._getDOMFile(file);
}
yield new FileUtils.File(file);
}
},
hasMoreElements: function() {
return this._index < this._owner._files.length;
},
getNext: function() {
let files = this._owner._files;
if (this._index >= files.length) {
throw Cr.NS_ERROR_FAILURE;
}
if (aDOMFile) {
return this._owner._getDOMFile(files[this._index++]);
}
return new FileUtils.File(files[this._index++]);
for (let file of this._files) {
if (aDOMFile) {
yield this._getDOMFile(file);
}
};
yield new FileUtils.File(file);
}
},
get files() {

Просмотреть файл

@ -19,6 +19,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/dom/PContent.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/HashTable.h"
#include "mozilla/Logging.h"
#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
@ -538,15 +539,6 @@ public:
// Other operations.
bool MatchEntry(const char* aPrefName)
{
if (!mName || !aPrefName) {
return false;
}
return strcmp(mName, aPrefName) == 0;
}
bool GetBoolValue(PrefValueKind aKind = PrefValueKind::User) const
{
MOZ_ASSERT(IsTypeBool());
@ -955,33 +947,20 @@ private:
PrefValue mUserValue;
};
class PrefEntry : public PLDHashEntryHdr
struct PrefHasher
{
public:
Pref* mPref; // Note: this is never null in a live entry.
using Key = mozilla::UniquePtr<Pref>;
using Lookup = const char*;
static bool MatchEntry(const PLDHashEntryHdr* aEntry, const void* aKey)
static HashNumber hash(const Lookup& aLookup) { return HashString(aLookup); }
static bool match(const Key& aKey, const Lookup& aLookup)
{
auto entry = static_cast<const PrefEntry*>(aEntry);
auto prefName = static_cast<const char*>(aKey);
if (!aLookup || !aKey->Name()) {
return false;
}
return entry->mPref->MatchEntry(prefName);
}
static void InitEntry(PLDHashEntryHdr* aEntry, const void* aKey)
{
auto entry = static_cast<PrefEntry*>(aEntry);
auto prefName = static_cast<const char*>(aKey);
entry->mPref = new Pref(prefName);
}
static void ClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
{
auto entry = static_cast<PrefEntry*>(aEntry);
delete entry->mPref;
entry->mPref = nullptr;
return strcmp(aLookup, aKey->Name()) == 0;
}
};
@ -1301,7 +1280,9 @@ private:
uintptr_t mNextAndMatchKind;
};
static PLDHashTable* gHashTable;
using PrefsHashTable = mozilla::HashSet<mozilla::UniquePtr<Pref>, PrefHasher>;
static PrefsHashTable* gHashTable;
// The callback list contains all the priority callbacks followed by the
// non-priority callbacks. gLastPriorityNode records where the first part ends.
@ -1349,22 +1330,16 @@ AddAccessCount(const char* aPrefName)
static bool gCallbacksInProgress = false;
static bool gShouldCleanupDeadNodes = false;
static PLDHashTableOps pref_HashTableOps = {
PLDHashTable::HashStringKey, PrefEntry::MatchEntry,
PLDHashTable::MoveEntryStub, PrefEntry::ClearEntry,
PrefEntry::InitEntry,
};
class PrefsHashIter
{
using Iterator = decltype(gHashTable->Iter());
using Iterator = decltype(gHashTable->modIter());
using ElemType = Pref*;
Iterator mIter;
public:
explicit PrefsHashIter(PLDHashTable* aTable)
: mIter(aTable->Iter())
explicit PrefsHashIter(PrefsHashTable* aTable)
: mIter(aTable->modIter())
{
}
@ -1391,7 +1366,7 @@ public:
if (mDone) {
return nullptr;
}
return static_cast<PrefEntry*>(Iter().Get())->mPref;
return Iter().get().get();
}
ElemType get() const { return const_cast<Elem*>(this)->get(); }
@ -1400,13 +1375,13 @@ public:
operator ElemType() { return get(); }
void Remove() { Iter().Remove(); }
void Remove() { Iter().remove(); }
Elem& operator++()
{
MOZ_ASSERT(!mDone);
Iter().Next();
mDone = Iter().Done();
Iter().next();
mDone = Iter().done();
return *this;
}
@ -1416,14 +1391,14 @@ public:
}
};
Elem begin() { return Elem(*this, mIter.Done()); }
Elem begin() { return Elem(*this, mIter.done()); }
Elem end() { return Elem(*this, true); }
};
class PrefsIter
{
using Iterator = decltype(gHashTable->Iter());
using Iterator = decltype(gHashTable->iter());
using ElemType = PrefWrapper;
using HashElem = PrefsHashIter::Elem;
@ -1432,7 +1407,7 @@ class PrefsIter
using ElemTypeVariant = Variant<HashElem, SharedElem>;
SharedPrefMap* mSharedMap;
PLDHashTable* mHashTable;
PrefsHashTable* mHashTable;
PrefsHashIter mIter;
ElemTypeVariant mPos;
@ -1441,7 +1416,7 @@ class PrefsIter
Maybe<PrefWrapper> mEntry;
public:
PrefsIter(PLDHashTable* aHashTable, SharedPrefMap* aSharedMap)
PrefsIter(PrefsHashTable* aHashTable, SharedPrefMap* aSharedMap)
: mSharedMap(aSharedMap)
, mHashTable(aHashTable)
, mIter(aHashTable)
@ -1531,9 +1506,9 @@ public:
void SkipDuplicates()
{
while (!mDone && (mParent.IteratingBase()
? !!mParent.mHashTable->Search(ref().Name())
: ref().IsTypeNone())) {
while (!mDone &&
(mParent.IteratingBase() ? mParent.mHashTable->has(ref().Name())
: ref().IsTypeNone())) {
Next();
}
}
@ -1621,7 +1596,7 @@ pref_savePrefs()
{
MOZ_ASSERT(NS_IsMainThread());
PrefSaveData savedPrefs(gHashTable->EntryCount());
PrefSaveData savedPrefs(gHashTable->count());
for (auto& pref : PrefsIter(gHashTable, gSharedMap)) {
nsAutoCString prefValueStr;
@ -1649,25 +1624,19 @@ static bool gContentProcessPrefsAreInited = false;
#endif // DEBUG
static PrefEntry*
pref_HashTableLookupInner(const char* aPrefName)
static Pref*
pref_HashTableLookup(const char* aPrefName)
{
MOZ_ASSERT(NS_IsMainThread() || mozilla::ServoStyleSet::IsInServoTraversal());
MOZ_ASSERT_IF(!XRE_IsParentProcess(), gContentProcessPrefsAreInited);
return static_cast<PrefEntry*>(gHashTable->Search(aPrefName));
}
static Pref*
pref_HashTableLookup(const char* aPrefName)
{
PrefEntry* entry = pref_HashTableLookupInner(aPrefName);
if (!entry) {
return nullptr;
}
return entry->mPref;
// We use readonlyThreadsafeLookup() because we often have concurrent lookups
// from multiple Stylo threads. This is safe because those threads cannot
// modify gHashTable, and the main thread is blocked while Stylo threads are
// doing these lookups.
auto p = gHashTable->readonlyThreadsafeLookup(aPrefName);
return p ? p->get() : nullptr;
}
// While notifying preference callbacks, this holds the wrapper for the
@ -1718,11 +1687,11 @@ pref_LookupForModify(const char* aPrefName,
return wrapper->as<Pref*>();
}
auto entry = static_cast<PrefEntry*>(gHashTable->Add(aPrefName, fallible));
if (!entry) {
Pref* pref = new Pref(aPrefName);
if (!gHashTable->putNew(aPrefName, pref)) {
delete pref;
return Err(NS_ERROR_OUT_OF_MEMORY);
}
Pref* pref = entry->mPref;
pref->FromWrapper(*wrapper);
return pref;
}
@ -1755,15 +1724,16 @@ pref_SetPref(const char* aPrefName,
}
if (!pref) {
auto entry = static_cast<PrefEntry*>(gHashTable->Add(aPrefName, fallible));
if (!entry) {
return NS_ERROR_OUT_OF_MEMORY;
}
pref = entry->mPref;
if (pref->IsTypeNone()) {
// New entry. Set the type.
auto p = gHashTable->lookupForAdd(aPrefName);
if (!p) {
pref = new Pref(aPrefName);
pref->SetType(aType);
if (!gHashTable->add(p, pref)) {
delete pref;
return NS_ERROR_OUT_OF_MEMORY;
}
} else {
pref = p->get();
}
}
@ -2882,16 +2852,14 @@ nsPrefBranch::DeleteBranch(const char* aStartingAt)
const nsACString& branchNameNoDot =
Substring(branchName, 0, branchName.Length() - 1);
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
for (auto iter = gHashTable->modIter(); !iter.done(); iter.next()) {
// The first disjunct matches branches: e.g. a branch name "foo.bar."
// matches a name "foo.bar.baz" (but it won't match "foo.barrel.baz").
// The second disjunct matches leaf nodes: e.g. a branch name "foo.bar."
// matches a name "foo.bar" (by ignoring the trailing '.').
nsDependentCString name(pref->Name());
nsDependentCString name(iter.get()->Name());
if (StringBeginsWith(name, branchName) || name.Equals(branchNameNoDot)) {
iter.Remove();
iter.remove();
// The saved callback pref may be invalid now.
gCallbackPref = nullptr;
}
@ -2943,8 +2911,8 @@ nsPrefBranch::GetChildList(const char* aStartingAt,
// back to us because if they do we are going to add mPrefRoot again.
const nsCString& element = prefArray[dwIndex];
outArray[dwIndex] =
(char*) moz_xmemdup(element.get() + mPrefRoot.Length(),
element.Length() - mPrefRoot.Length() + 1);
(char*)moz_xmemdup(element.get() + mPrefRoot.Length(),
element.Length() - mPrefRoot.Length() + 1);
}
*aChildArray = outArray;
}
@ -3535,10 +3503,9 @@ PreferenceServiceReporter::CollectReports(
Preferences::AddSizeOfIncludingThis(mallocSizeOf, sizes);
if (gHashTable) {
sizes.mHashTable += gHashTable->ShallowSizeOfIncludingThis(mallocSizeOf);
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
pref->AddSizeOfIncludingThis(mallocSizeOf, sizes);
sizes.mHashTable += gHashTable->shallowSizeOfIncludingThis(mallocSizeOf);
for (auto iter = gHashTable->iter(); !iter.done(); iter.next()) {
iter.get()->AddSizeOfIncludingThis(mallocSizeOf, sizes);
}
}
@ -3850,10 +3817,8 @@ Preferences::GetInstanceForService()
MOZ_ASSERT(!gHashTable);
gHashTable =
new PLDHashTable(&pref_HashTableOps,
sizeof(PrefEntry),
(XRE_IsParentProcess() ? kHashTableInitialLengthParent
: kHashTableInitialLengthContent));
new PrefsHashTable(XRE_IsParentProcess() ? kHashTableInitialLengthParent
: kHashTableInitialLengthContent);
gTelemetryLoadData =
new nsDataHashtable<nsCStringHashKey, TelemetryLoadData>();
@ -4018,8 +3983,8 @@ Preferences::SerializePreferences(nsCString& aStr)
aStr.Truncate();
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
for (auto iter = gHashTable->iter(); !iter.done(); iter.next()) {
Pref* pref = iter.get().get();
if (!pref->IsTypeNone() && pref->HasAdvisablySizedValues()) {
pref->SerializeAndAppend(aStr);
}
@ -4061,10 +4026,8 @@ Preferences::EnsureSnapshot(size_t* aSize)
if (!gSharedMap) {
SharedPrefMapBuilder builder;
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
pref->AddToMap(builder);
for (auto iter = gHashTable->iter(); !iter.done(); iter.next()) {
iter.get()->AddToMap(builder);
}
gSharedMap = new SharedPrefMap(std::move(builder));
@ -4078,7 +4041,9 @@ Preferences::EnsureSnapshot(size_t* aSize)
// we can initialize the hashtable with the expected number of per-session
// changed preferences, rather than the expected total number of
// preferences.
gHashTable->ClearAndPrepareForLength(kHashTableInitialLengthContent);
gHashTable->clearAndCompact();
Unused << gHashTable->reserve(kHashTableInitialLengthContent);
gPrefNameArena.Clear();
}
@ -4197,7 +4162,9 @@ Preferences::ResetPrefs()
return NS_ERROR_NOT_AVAILABLE;
}
gHashTable->ClearAndPrepareForLength(kHashTableInitialLengthParent);
gHashTable->clearAndCompact();
Unused << gHashTable->reserve(kHashTableInitialLengthParent);
gPrefNameArena.Clear();
return InitInitialObjects(/* isStartup */ false).isOk() ? NS_OK
@ -4212,8 +4179,8 @@ Preferences::ResetUserPrefs()
MOZ_ASSERT(NS_IsMainThread());
Vector<const char*> prefNames;
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
for (auto iter = gHashTable->modIter(); !iter.done(); iter.next()) {
Pref* pref = iter.get().get();
if (pref->HasUserValue()) {
if (!prefNames.append(pref->Name())) {
@ -4222,7 +4189,7 @@ Preferences::ResetUserPrefs()
pref->ClearUserValue();
if (!pref->HasDefaultValue()) {
iter.Remove();
iter.remove();
}
}
}
@ -4290,13 +4257,18 @@ Preferences::SetPreference(const dom::Pref& aDomPref)
const char* prefName = aDomPref.name().get();
auto entry = static_cast<PrefEntry*>(gHashTable->Add(prefName, fallible));
if (!entry) {
return;
Pref* pref;
auto p = gHashTable->lookupForAdd(prefName);
if (!p) {
pref = new Pref(prefName);
if (!gHashTable->add(p, pref)) {
delete pref;
return;
}
} else {
pref = p->get();
}
Pref* pref = entry->mPref;
bool valueChanged = false;
pref->FromDomPref(aDomPref, &valueChanged);
@ -4316,7 +4288,7 @@ Preferences::SetPreference(const dom::Pref& aDomPref)
if (gSharedMap->Has(pref->Name())) {
pref->SetType(PrefType::None);
} else {
gHashTable->RemoveEntry(entry);
gHashTable->remove(prefName);
}
pref = nullptr;
}
@ -5269,7 +5241,7 @@ Preferences::ClearUser(const char* aPrefName)
if (!pref->HasDefaultValue()) {
if (!gSharedMap || !gSharedMap->Has(pref->Name())) {
gHashTable->Remove(aPrefName);
gHashTable->remove(aPrefName);
} else {
pref->SetType(PrefType::None);
}

Просмотреть файл

@ -318,7 +318,8 @@ class SharedPrefMap
uint8_t mIsSticky : 1;
// True if the preference is locked, as defined by the preference service.
uint8_t mIsLocked : 1;
// True if the preference's default value has changed since it was first set.
// True if the preference's default value has changed since it was first
// set.
uint8_t mDefaultChanged : 1;
};

Просмотреть файл

@ -210,44 +210,22 @@ MockFilePickerInstance.prototype = {
return null;
},
get files() {
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) {
throw Components.Exception("", Cr.NS_ERROR_FAILURE);
}
return MockFilePicker.returnData[this.index++].nsIFile;
* getFiles(asDOM) {
for (let d of MockFilePicker.returnData) {
if (asDOM) {
yield d.domFile || d.domDirectory;
} else if (d.nsIFile) {
yield d.nsIFile;
} else {
throw Components.Exception("", Cr.NS_ERROR_FAILURE);
}
};
}
},
get files() {
return this.getFiles(false);
},
get domFileOrDirectoryEnumerator() {
return {
index: 0,
QueryInterface: ChromeUtils.generateQI([Ci.nsISimpleEnumerator]),
hasMoreElements() {
return this.index < MockFilePicker.returnData.length;
},
getNext() {
// window.File does not implement nsIFile
if (MockFilePicker.returnData[this.index].domFile) {
return MockFilePicker.returnData[this.index++].domFile;
}
if (MockFilePicker.returnData[this.index].domDirectory) {
return MockFilePicker.returnData[this.index++].domDirectory;
}
return null;
}
};
return this.getFiles(true);
},
open(aFilePickerShownCallback) {
MockFilePicker.showing = true;

Просмотреть файл

@ -96,21 +96,11 @@ function installAddonEngine(name = "engine-addon") {
},
getFiles(prop) {
let result = [];
switch (prop) {
case XRE_EXTENSIONS_DIR_LIST:
result.push(addonDir);
break;
default:
throw Cr.NS_ERROR_FAILURE;
if (prop == XRE_EXTENSIONS_DIR_LIST) {
return [addonDir].values();
}
return {
QueryInterface: ChromeUtils.generateQI([Ci.nsISimpleEnumerator]),
hasMoreElements: () => result.length > 0,
getNext: () => result.shift(),
};
throw Cr.NS_ERROR_FAILURE;
},
});
}

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 825 B

После

Ширина:  |  Высота:  |  Размер: 825 B

Просмотреть файл

@ -87,7 +87,7 @@ if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
if CONFIG['OS_ARCH'] == 'Linux' or CONFIG['OS_ARCH'] == 'SunOS':
FINAL_TARGET_FILES += [
'/toolkit/themes/windows/global/throbber/Throbber-small.gif',
'Throbber-small.gif',
]
DEFINES['BIN_SUFFIX'] = '"%s"' % CONFIG['BIN_SUFFIX']

Просмотреть файл

@ -810,38 +810,6 @@ function cleanupActiveUpdate() {
cleanUpUpdatesDir();
}
/**
* An enumeration of items in a JS array.
* @constructor
*/
function ArrayEnumerator(aItems) {
this._index = 0;
if (aItems) {
for (var i = 0; i < aItems.length; ++i) {
if (!aItems[i])
aItems.splice(i, 1);
}
}
this._contents = aItems;
}
ArrayEnumerator.prototype = {
_index: 0,
_contents: [],
[Symbol.iterator]() {
return this._contents.values();
},
hasMoreElements: function ArrayEnumerator_hasMoreElements() {
return this._index < this._contents.length;
},
getNext: function ArrayEnumerator_getNext() {
return this._contents[this._index++];
},
};
/**
* Writes a string of text to a file. A newline will be appended to the data
* written to the file. This function only works with ASCII text.
@ -1158,10 +1126,16 @@ UpdatePatch.prototype = {
* See nsIPropertyBag.idl
*/
get enumerator() {
var properties = [];
for (var p in this._properties)
properties.push(this._properties[p].data);
return new ArrayEnumerator(properties);
return this.enumerate();
},
* enumerate() {
for (var p in this._properties) {
let prop = this.properties[p].data;
if (prop) {
yield prop;
}
}
},
/**
@ -1479,11 +1453,16 @@ Update.prototype = {
* See nsIPropertyBag.idl
*/
get enumerator() {
var properties = [];
for (let p in this._properties) {
properties.push(this._properties[p].data);
return this.enumerate();
},
* enumerate() {
for (var p in this._properties) {
let prop = this.properties[p].data;
if (prop) {
yield prop;
}
}
return new ArrayEnumerator(properties);
},
/**