mirror of
https://github.com/roytam1/mozilla45esr.git
synced 2026-05-26 06:25:03 +00:00
import changes from tenfourfox-history:
- #469: expose adblock pref in UI (3c7ba565e) (partly) - #483: speculative GC/CC retuning (851222ca4) - enable intel atomic operations (8fba598e8) - #482: better bidi M1358275 M1392181 M1428774 + backbugs (e88a717ab) - #482: note to self (d70096a7c) - #483: wrong way on purple buffer (otherwise OOMs result) (d1ee9ade1) - #478 chemspill: M1446062 fixes M1446068 (d2a1328e6) - #469: more hosts for adblock (d8ada86ef) - M1252374 reduce mallocs in displayList generation (78a7470f6) - #485: mostly working destructuring nested rest assignment (2edc0af3d) - closes #486: amp up hashtables M1352889 M1352890 M1379282 (1a6015752) - #469: more hosts and a miner for basic adblock (3b1a55df8) - #405: fix idl (1dab98d2e) - #469, #399: more adblock hosts, faster StringBegins/End, any-link, base/srcdoc M1247359 M843579 M1238804 (610226ea6) - #334, closes #489: enable TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for amtrak.com (595021326) - #399: remove padding-box support M1166728 (845e1834f) - #399: disable SPDY/3.1 M1287132 (540f47f9c) - #488: basic support for DOM iterables, {NodeList,DOMTokenList}.forEach M1216751 M1290636 (8409d1511) - closes #488: M1257849 M1244328 finish DOMTokenList transition, bustage fixes (6b1b6131e) - #491: update certs and pins (d2003d9a6) - closes #492: rc4 bad, increase throttle, update UAs, reduce font URL overhead, nerdwallet ATSUI font block (8f7a0cce0) - #469: some more hosts for adblock (c1af11d1a)
This commit is contained in:
@@ -707,6 +707,17 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
// https://github.com/AdguardTeam/AdguardFilters/issues/1278
|
||||
// this may also be true for adziff.com
|
||||
|
||||
// don't block kxcdn
|
||||
// https://github.com/EFForg/privacybadger/issues/1381
|
||||
|
||||
// miners
|
||||
BLOK("coinhive.com") ||
|
||||
BLOK("www.freecontent.stream") ||
|
||||
BLOK("www.freecontent.stream.") ||
|
||||
BLOK("allfontshere.press") || // caused crashes on VCF
|
||||
BLOK("www.allfontshere.press") ||
|
||||
|
||||
// other obnoxious things
|
||||
BLOK("c.amazon-adsystem.com") ||
|
||||
|
||||
BLOK("google-analytics.com") ||
|
||||
@@ -746,6 +757,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
BLOK("ad.doubleclick.net") ||
|
||||
BLOK("static.doubleclick.net") ||
|
||||
BLOK("stats.g.doubleclick.net") ||
|
||||
BLOK("pubads.g.doubleclick.net") ||
|
||||
BLOK("googleads.g.doubleclick.net") ||
|
||||
BLOK("securepubads.g.doubleclick.net") ||
|
||||
|
||||
@@ -802,6 +814,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
BLOK("cdn.revcontent.com") ||
|
||||
|
||||
BLOK("cas.criteo.com") ||
|
||||
BLOK("rtax.criteo.com") ||
|
||||
BLOK("static.criteo.net") ||
|
||||
|
||||
BLOK("jsc.idealmedia.com") ||
|
||||
@@ -850,6 +863,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
|
||||
BLOK("www.npttech.com") ||
|
||||
|
||||
BLOK("fw.adsafeprotected.com") ||
|
||||
BLOK("cdn.adsafeprotected.com") ||
|
||||
BLOK("pixel.adsafeprotected.com") ||
|
||||
BLOK("static.adsafeprotected.com") ||
|
||||
@@ -884,6 +898,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
BLOK("cdn.mediavoice.com") ||
|
||||
BLOK("plugin.mediavoice.com") ||
|
||||
|
||||
BLOK("api-us-east.zqtk.net") ||
|
||||
BLOK("segment-data.zqtk.net") ||
|
||||
|
||||
BLOK("d.turn.com") ||
|
||||
@@ -904,6 +919,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
BLOK("se.monetate.net") ||
|
||||
|
||||
BLOK("ad.crwdcntrl.net") ||
|
||||
BLOK("bcp.crwdcntrl.net") ||
|
||||
BLOK("tags.crwdcntrl.net") ||
|
||||
|
||||
BLOK("cdn.nsstatic.net") ||
|
||||
@@ -919,6 +935,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
BLOK("stats.cloudwp.io") ||
|
||||
|
||||
BLOK("ap.lijit.com") ||
|
||||
BLOK("ce.lijit.com") ||
|
||||
|
||||
BLOK("tlx.3lift.com") ||
|
||||
|
||||
@@ -984,14 +1001,12 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
BLOK("cdata.carambo.la") ||
|
||||
BLOK("route.carambo.la") ||
|
||||
|
||||
BLOK("us-u.openx.net") ||
|
||||
BLOK("uk-ads.openx.net") ||
|
||||
BLOK("us-ads.openx.net") ||
|
||||
|
||||
BLOK("s-static.innovid.com") ||
|
||||
|
||||
// This is controversial, but I'm pretty sure we
|
||||
// don't want this.
|
||||
BLOK("coinhive.com") ||
|
||||
|
||||
BLOK("ustatik.com") ||
|
||||
BLOK("cdn.ustatik.com") ||
|
||||
|
||||
@@ -1007,6 +1022,42 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
BLOK("t.neodatagroup.com") ||
|
||||
|
||||
BLOK("ads.servebom.com") ||
|
||||
|
||||
BLOK("a.mailmunch.co") ||
|
||||
|
||||
BLOK("ads.adthrive.com") ||
|
||||
|
||||
BLOK("js.agkn.com") ||
|
||||
|
||||
BLOK("htl.bid") ||
|
||||
|
||||
BLOK("rtb.districtm.io") ||
|
||||
BLOK("prebid.districtm.ca") ||
|
||||
|
||||
BLOK("speednetwork14.adk2.co") ||
|
||||
BLOK("speednetwork14.adk2x.com") ||
|
||||
|
||||
BLOK("deloton.com") ||
|
||||
|
||||
BLOK("clickiocdn.com") ||
|
||||
BLOK("clickioadve.com") ||
|
||||
|
||||
BLOK("cti.w55c.net") ||
|
||||
BLOK("cdn.w55c.net") ||
|
||||
|
||||
BLOK("mobpushup.com") ||
|
||||
|
||||
BLOK("sc.iasds01.com") ||
|
||||
|
||||
BLOK("cdn.optimizely.com") ||
|
||||
BLOK("cdn3.optimizely.com") ||
|
||||
|
||||
BLOK("p.d.emn0.com") ||
|
||||
BLOK("p.w.emn0.com") ||
|
||||
|
||||
BLOK("api.b2c.com") ||
|
||||
|
||||
BLOK("bounceexchange.com") ||
|
||||
0) {
|
||||
#undef BLOK
|
||||
// Yup.
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/* -*- 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Definitions of supported tokens data types for nsDOMTokenList. This is in a
|
||||
* separate header so Element.h can include it too.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_dom_DOMTokenListSupportedTokens_h
|
||||
#define mozilla_dom_DOMTokenListSupportedTokens_h
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// A single supported token.
|
||||
typedef const char* const DOMTokenListSupportedToken;
|
||||
|
||||
// An array of supported tokens. This should end with a null
|
||||
// DOMTokenListSupportedToken to indicate array termination. A null value for
|
||||
// the DOMTokenListSupportedTokenArray means there is no definition of supported
|
||||
// tokens for the given DOMTokenList. This should generally be a static table,
|
||||
// or at least outlive the DOMTokenList whose constructor it's passed to.
|
||||
typedef DOMTokenListSupportedToken* DOMTokenListSupportedTokenArray;
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_DOMTokenListSupportedTokens_h
|
||||
+12
-12
@@ -44,7 +44,6 @@
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsContentList.h"
|
||||
#include "nsVariant.h"
|
||||
#include "nsDOMSettableTokenList.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsError.h"
|
||||
@@ -3086,11 +3085,11 @@ Element::GetLinkTarget(nsAString& aTarget)
|
||||
}
|
||||
|
||||
static void
|
||||
nsDOMSettableTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
|
||||
void *aPropertyValue, void *aData)
|
||||
nsDOMTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
|
||||
void *aPropertyValue, void *aData)
|
||||
{
|
||||
nsDOMSettableTokenList* list =
|
||||
static_cast<nsDOMSettableTokenList*>(aPropertyValue);
|
||||
nsDOMTokenList* list =
|
||||
static_cast<nsDOMTokenList*>(aPropertyValue);
|
||||
NS_RELEASE(list);
|
||||
}
|
||||
|
||||
@@ -3113,8 +3112,9 @@ Element::HTMLSVGPropertiesToTraverseAndUnlink()
|
||||
return sPropertiesToTraverseAndUnlink;
|
||||
}
|
||||
|
||||
nsDOMSettableTokenList*
|
||||
Element::GetTokenList(nsIAtom* aAtom)
|
||||
nsDOMTokenList*
|
||||
Element::GetTokenList(nsIAtom* aAtom,
|
||||
const DOMTokenListSupportedTokenArray aSupportedTokens)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsIAtom*** props =
|
||||
@@ -3129,14 +3129,14 @@ Element::GetTokenList(nsIAtom* aAtom)
|
||||
MOZ_ASSERT(found, "Trying to use an unknown tokenlist!");
|
||||
#endif
|
||||
|
||||
nsDOMSettableTokenList* list = nullptr;
|
||||
nsDOMTokenList* list = nullptr;
|
||||
if (HasProperties()) {
|
||||
list = static_cast<nsDOMSettableTokenList*>(GetProperty(aAtom));
|
||||
list = static_cast<nsDOMTokenList*>(GetProperty(aAtom));
|
||||
}
|
||||
if (!list) {
|
||||
list = new nsDOMSettableTokenList(this, aAtom);
|
||||
list = new nsDOMTokenList(this, aAtom, aSupportedTokens);
|
||||
NS_ADDREF(list);
|
||||
SetProperty(aAtom, list, nsDOMSettableTokenListPropertyDestructor);
|
||||
SetProperty(aAtom, list, nsDOMTokenListPropertyDestructor);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -3153,7 +3153,7 @@ Element::GetTokenList(nsIAtom* aAtom, nsIVariant** aResult)
|
||||
nsresult
|
||||
Element::SetTokenList(nsIAtom* aAtom, nsIVariant* aValue)
|
||||
{
|
||||
nsDOMSettableTokenList* itemType = GetTokenList(aAtom);
|
||||
nsDOMTokenList* itemType = GetTokenList(aAtom);
|
||||
nsAutoString string;
|
||||
aValue->GetAsAString(string);
|
||||
ErrorResult rv;
|
||||
|
||||
+3
-2
@@ -34,6 +34,7 @@
|
||||
#include "nsAttrValue.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/DOMTokenListSupportedTokens.h"
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "mozilla/dom/ElementBinding.h"
|
||||
#include "Units.h"
|
||||
@@ -44,7 +45,6 @@ class nsIURI;
|
||||
class nsIScrollableFrame;
|
||||
class nsAttrValueOrString;
|
||||
class nsContentList;
|
||||
class nsDOMSettableTokenList;
|
||||
class nsDOMTokenList;
|
||||
struct nsRect;
|
||||
class nsFocusManager;
|
||||
@@ -1342,7 +1342,8 @@ protected:
|
||||
*/
|
||||
virtual void GetLinkTarget(nsAString& aTarget);
|
||||
|
||||
nsDOMSettableTokenList* GetTokenList(nsIAtom* aAtom);
|
||||
nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
|
||||
const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
|
||||
void GetTokenList(nsIAtom* aAtom, nsIVariant** aResult);
|
||||
nsresult SetTokenList(nsIAtom* aAtom, nsIVariant* aValue);
|
||||
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
class ContentUnbinder;
|
||||
class nsContentList;
|
||||
class nsDOMAttributeMap;
|
||||
class nsDOMTokenList;
|
||||
class nsIControllers;
|
||||
class nsICSSDeclaration;
|
||||
class nsIDocument;
|
||||
class nsDOMStringMap;
|
||||
class nsDOMTokenList;
|
||||
class nsIURI;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* -*- 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* NOTE: no include guard; this file is meant to maybe be included multiple
|
||||
times. It has a list of the sandbox keywords we support, with their
|
||||
corresponding sandbox flags. */
|
||||
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
// Each entry has the sandbox keyword as a string, the corresponding nsGkAtoms
|
||||
// atom name, and the corresponding sandbox flags.
|
||||
SANDBOX_KEYWORD("allow-same-origin", allowsameorigin, SANDBOXED_ORIGIN)
|
||||
SANDBOX_KEYWORD("allow-forms", allowforms, SANDBOXED_FORMS)
|
||||
SANDBOX_KEYWORD("allow-scripts", allowscripts,
|
||||
SANDBOXED_SCRIPTS | SANDBOXED_AUTOMATIC_FEATURES)
|
||||
SANDBOX_KEYWORD("allow-top-navigation", allowtopnavigation,
|
||||
SANDBOXED_TOPLEVEL_NAVIGATION)
|
||||
SANDBOX_KEYWORD("allow-pointer-lock", allowpointerlock, SANDBOXED_POINTER_LOCK)
|
||||
SANDBOX_KEYWORD("allow-orientation-lock", alloworientationlock,
|
||||
SANDBOXED_ORIENTATION_LOCK)
|
||||
SANDBOX_KEYWORD("allow-popups", allowpopups, SANDBOXED_AUXILIARY_NAVIGATION)
|
||||
+3
-1
@@ -45,6 +45,7 @@ EXPORTS += [
|
||||
'AutocompleteFieldList.h',
|
||||
'Crypto.h',
|
||||
'HTMLSplitOnSpacesTokenizer.h',
|
||||
'IframeSandboxKeywordList.h',
|
||||
'mozAutoDocUpdate.h',
|
||||
'mozFlushType.h',
|
||||
'nsAtomListUtils.h',
|
||||
@@ -74,6 +75,7 @@ EXPORTS += [
|
||||
'nsDOMJSUtils.h',
|
||||
'nsDOMNavigationTiming.h',
|
||||
'nsDOMString.h',
|
||||
'nsDOMTokenList.h',
|
||||
'nsFocusManager.h',
|
||||
'nsFormData.h',
|
||||
'nsFrameMessageManager.h',
|
||||
@@ -174,6 +176,7 @@ EXPORTS.mozilla.dom += [
|
||||
'DOMRect.h',
|
||||
'DOMRequest.h',
|
||||
'DOMStringList.h',
|
||||
'DOMTokenListSupportedTokens.h',
|
||||
'Element.h',
|
||||
'ElementInlines.h',
|
||||
'EventSource.h',
|
||||
@@ -278,7 +281,6 @@ UNIFIED_SOURCES += [
|
||||
'nsDOMNavigationTiming.cpp',
|
||||
'nsDOMScriptObjectFactory.cpp',
|
||||
'nsDOMSerializer.cpp',
|
||||
'nsDOMSettableTokenList.cpp',
|
||||
'nsDOMTokenList.cpp',
|
||||
'nsDOMWindowList.cpp',
|
||||
'nsFocusManager.cpp',
|
||||
|
||||
@@ -1362,19 +1362,13 @@ nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* sandboxAttr)
|
||||
| SANDBOXED_DOMAIN;
|
||||
|
||||
// Macro for updating the flag according to the keywords
|
||||
#define IF_KEYWORD(atom, flags) \
|
||||
#define SANDBOX_KEYWORD(string, atom, flags) \
|
||||
if (sandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { out &= ~(flags); }
|
||||
|
||||
IF_KEYWORD(allowsameorigin, SANDBOXED_ORIGIN)
|
||||
IF_KEYWORD(allowforms, SANDBOXED_FORMS)
|
||||
IF_KEYWORD(allowscripts, SANDBOXED_SCRIPTS | SANDBOXED_AUTOMATIC_FEATURES)
|
||||
IF_KEYWORD(allowtopnavigation, SANDBOXED_TOPLEVEL_NAVIGATION)
|
||||
IF_KEYWORD(allowpointerlock, SANDBOXED_POINTER_LOCK)
|
||||
IF_KEYWORD(alloworientationlock, SANDBOXED_ORIENTATION_LOCK)
|
||||
IF_KEYWORD(allowpopups, SANDBOXED_AUXILIARY_NAVIGATION)
|
||||
#include "IframeSandboxKeywordList.h"
|
||||
|
||||
return out;
|
||||
#undef IF_KEYWORD
|
||||
#undef SANDBOX_KEYWORD
|
||||
}
|
||||
|
||||
nsIBidiKeyboard*
|
||||
|
||||
+170
-61
@@ -9,20 +9,25 @@
|
||||
*/
|
||||
|
||||
#include "nsDOMTokenList.h"
|
||||
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsAttrValue.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsError.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/DOMTokenListBinding.h"
|
||||
#include "mozilla/BloomFilter.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
nsDOMTokenList::nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom)
|
||||
nsDOMTokenList::nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom,
|
||||
const DOMTokenListSupportedTokenArray aSupportedTokens)
|
||||
: mElement(aElement),
|
||||
mAttrAtom(aAttrAtom)
|
||||
mAttrAtom(aAttrAtom),
|
||||
mSupportedTokens(aSupportedTokens)
|
||||
{
|
||||
// We don't add a reference to our element. If it goes away,
|
||||
// we'll be told to drop our reference
|
||||
@@ -50,6 +55,45 @@ nsDOMTokenList::GetParsedAttr()
|
||||
return mElement->GetAttrInfo(kNameSpaceID_None, mAttrAtom).mValue;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMTokenList::RemoveDuplicates(const nsAttrValue* aAttr)
|
||||
{
|
||||
if (!aAttr || aAttr->Type() != nsAttrValue::eAtomArray) {
|
||||
return;
|
||||
}
|
||||
|
||||
BloomFilter<8, nsIAtom> filter;
|
||||
nsAttrValue::AtomArray* array = aAttr->GetAtomArrayValue();
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
nsIAtom* atom = array->ElementAt(i);
|
||||
if (filter.mightContain(atom)) {
|
||||
// Start again, with a hashtable
|
||||
RemoveDuplicatesInternal(array, i);
|
||||
return;
|
||||
} else {
|
||||
filter.add(atom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMTokenList::RemoveDuplicatesInternal(nsAttrValue::AtomArray* aArray,
|
||||
uint32_t aStart)
|
||||
{
|
||||
nsDataHashtable<nsPtrHashKey<nsIAtom>, bool> tokens;
|
||||
|
||||
for (uint32_t i = 0; i < aArray->Length(); i++) {
|
||||
nsIAtom* atom = aArray->ElementAt(i);
|
||||
// No need to check the hashtable below aStart
|
||||
if (i >= aStart && tokens.Get(atom)) {
|
||||
aArray->RemoveElementAt(i);
|
||||
i--;
|
||||
} else {
|
||||
tokens.Put(atom, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsDOMTokenList::Length()
|
||||
{
|
||||
@@ -58,6 +102,7 @@ nsDOMTokenList::Length()
|
||||
return 0;
|
||||
}
|
||||
|
||||
RemoveDuplicates(attr);
|
||||
return attr->GetAtomCount();
|
||||
}
|
||||
|
||||
@@ -66,6 +111,13 @@ nsDOMTokenList::IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aResult)
|
||||
{
|
||||
const nsAttrValue* attr = GetParsedAttr();
|
||||
|
||||
if (!attr || aIndex >= static_cast<uint32_t>(attr->GetAtomCount())) {
|
||||
aFound = false;
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveDuplicates(attr);
|
||||
|
||||
if (attr && aIndex < static_cast<uint32_t>(attr->GetAtomCount())) {
|
||||
aFound = true;
|
||||
attr->AtomAt(aIndex)->ToString(aResult);
|
||||
@@ -74,6 +126,16 @@ nsDOMTokenList::IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aResult)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMTokenList::SetValue(const nsAString& aValue, ErrorResult& rv)
|
||||
{
|
||||
if (!mElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = mElement->SetAttr(kNameSpaceID_None, mAttrAtom, aValue, true);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMTokenList::CheckToken(const nsAString& aStr)
|
||||
{
|
||||
@@ -130,10 +192,15 @@ nsDOMTokenList::AddInternal(const nsAttrValue* aAttr,
|
||||
nsAutoString resultStr;
|
||||
|
||||
if (aAttr) {
|
||||
aAttr->ToString(resultStr);
|
||||
RemoveDuplicates(aAttr);
|
||||
for (uint32_t i = 0; i < aAttr->GetAtomCount(); i++) {
|
||||
if (i != 0) {
|
||||
resultStr.AppendLiteral(" ");
|
||||
}
|
||||
resultStr.Append(nsDependentAtomString(aAttr->AtomAt(i)));
|
||||
}
|
||||
}
|
||||
|
||||
bool oneWasAdded = false;
|
||||
nsAutoTArray<nsString, 10> addedClasses;
|
||||
|
||||
for (uint32_t i = 0, l = aTokens.Length(); i < l; ++i) {
|
||||
@@ -144,16 +211,11 @@ nsDOMTokenList::AddInternal(const nsAttrValue* aAttr,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (oneWasAdded ||
|
||||
(!resultStr.IsEmpty() &&
|
||||
!nsContentUtils::IsHTMLWhitespace(resultStr.Last()))) {
|
||||
if (!resultStr.IsEmpty()) {
|
||||
resultStr.Append(' ');
|
||||
resultStr.Append(aToken);
|
||||
} else {
|
||||
resultStr.Append(aToken);
|
||||
}
|
||||
resultStr.Append(aToken);
|
||||
|
||||
oneWasAdded = true;
|
||||
addedClasses.AppendElement(aToken);
|
||||
}
|
||||
|
||||
@@ -186,60 +248,20 @@ nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
|
||||
{
|
||||
MOZ_ASSERT(aAttr, "Need an attribute");
|
||||
|
||||
nsAutoString input;
|
||||
aAttr->ToString(input);
|
||||
RemoveDuplicates(aAttr);
|
||||
|
||||
nsAString::const_iterator copyStart, tokenStart, iter, end;
|
||||
input.BeginReading(iter);
|
||||
input.EndReading(end);
|
||||
copyStart = iter;
|
||||
|
||||
nsAutoString output;
|
||||
bool lastTokenRemoved = false;
|
||||
|
||||
while (iter != end) {
|
||||
// skip whitespace.
|
||||
while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
|
||||
++iter;
|
||||
nsAutoString resultStr;
|
||||
for (uint32_t i = 0; i < aAttr->GetAtomCount(); i++) {
|
||||
if (aTokens.Contains(nsDependentAtomString(aAttr->AtomAt(i)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (iter == end) {
|
||||
// At this point we're sure the last seen token (if any) wasn't to be
|
||||
// removed. So the trailing spaces will need to be kept.
|
||||
MOZ_ASSERT(!lastTokenRemoved, "How did this happen?");
|
||||
|
||||
output.Append(Substring(copyStart, end));
|
||||
break;
|
||||
}
|
||||
|
||||
tokenStart = iter;
|
||||
do {
|
||||
++iter;
|
||||
} while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter));
|
||||
|
||||
if (aTokens.Contains(Substring(tokenStart, iter))) {
|
||||
|
||||
// Skip whitespace after the token, it will be collapsed.
|
||||
while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
|
||||
++iter;
|
||||
}
|
||||
copyStart = iter;
|
||||
lastTokenRemoved = true;
|
||||
|
||||
} else {
|
||||
|
||||
if (lastTokenRemoved && !output.IsEmpty()) {
|
||||
MOZ_ASSERT(!nsContentUtils::IsHTMLWhitespace(output.Last()),
|
||||
"Invalid last output token");
|
||||
output.Append(char16_t(' '));
|
||||
}
|
||||
lastTokenRemoved = false;
|
||||
output.Append(Substring(copyStart, iter));
|
||||
copyStart = iter;
|
||||
if (!resultStr.IsEmpty()) {
|
||||
resultStr.AppendLiteral(" ");
|
||||
}
|
||||
resultStr.Append(nsDependentAtomString(aAttr->AtomAt(i)));
|
||||
}
|
||||
|
||||
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, output, true);
|
||||
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, resultStr, true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -299,6 +321,93 @@ nsDOMTokenList::Toggle(const nsAString& aToken,
|
||||
return isPresent;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMTokenList::Replace(const nsAString& aToken,
|
||||
const nsAString& aNewToken,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
// Doing this here instead of using `CheckToken` because if aToken had invalid
|
||||
// characters, and aNewToken is empty, the returned error should be a
|
||||
// SyntaxError, not an InvalidCharacterError.
|
||||
if (aNewToken.IsEmpty()) {
|
||||
aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
aError = CheckToken(aToken);
|
||||
if (aError.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aError = CheckToken(aNewToken);
|
||||
if (aError.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nsAttrValue* attr = GetParsedAttr();
|
||||
if (!attr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReplaceInternal(attr, aToken, aNewToken);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMTokenList::ReplaceInternal(const nsAttrValue* aAttr,
|
||||
const nsAString& aToken,
|
||||
const nsAString& aNewToken)
|
||||
{
|
||||
RemoveDuplicates(aAttr);
|
||||
|
||||
bool sawIt = false;
|
||||
nsAutoString resultStr;
|
||||
for (uint32_t i = 0; i < aAttr->GetAtomCount(); i++) {
|
||||
if (aAttr->AtomAt(i)->Equals(aToken) ||
|
||||
aAttr->AtomAt(i)->Equals(aNewToken)) {
|
||||
if (sawIt) {
|
||||
// We keep only the first
|
||||
continue;
|
||||
}
|
||||
sawIt = true;
|
||||
if (!resultStr.IsEmpty()) {
|
||||
resultStr.AppendLiteral(" ");
|
||||
}
|
||||
resultStr.Append(aNewToken);
|
||||
continue;
|
||||
}
|
||||
if (!resultStr.IsEmpty()) {
|
||||
resultStr.AppendLiteral(" ");
|
||||
}
|
||||
resultStr.Append(nsDependentAtomString(aAttr->AtomAt(i)));
|
||||
}
|
||||
|
||||
if (sawIt) {
|
||||
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, resultStr, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsDOMTokenList::Supports(const nsAString& aToken,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
if (!mSupportedTokens) {
|
||||
aError.ThrowTypeError<MSG_TOKENLIST_NO_SUPPORTED_TOKENS>(
|
||||
mElement->LocalName(),
|
||||
nsDependentAtomString(mAttrAtom));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (DOMTokenListSupportedToken* supportedToken = mSupportedTokens;
|
||||
*supportedToken;
|
||||
++supportedToken) {
|
||||
if (aToken.LowerCaseEqualsASCII(*supportedToken)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMTokenList::Stringify(nsAString& aResult)
|
||||
{
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMString.h"
|
||||
#include "nsDOMString.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/DOMTokenListSupportedTokens.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
@@ -26,7 +28,7 @@ class nsAttrValue;
|
||||
class nsIAtom;
|
||||
|
||||
// nsISupports must be on the primary inheritance chain
|
||||
// because nsDOMSettableTokenList is traversed by Element.
|
||||
|
||||
class nsDOMTokenList : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
@@ -37,7 +39,8 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMTokenList)
|
||||
|
||||
nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom);
|
||||
nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom,
|
||||
const mozilla::dom::DOMTokenListSupportedTokenArray = nullptr);
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
@@ -46,6 +49,7 @@ public:
|
||||
return mElement;
|
||||
}
|
||||
|
||||
void RemoveDuplicates(const nsAttrValue* aAttr);
|
||||
uint32_t Length();
|
||||
void Item(uint32_t aIndex, nsAString& aResult)
|
||||
{
|
||||
@@ -63,9 +67,17 @@ public:
|
||||
void Remove(const nsAString& aToken, mozilla::ErrorResult& aError);
|
||||
void Remove(const nsTArray<nsString>& aTokens,
|
||||
mozilla::ErrorResult& aError);
|
||||
void Replace(const nsAString& aToken,
|
||||
const nsAString& aNewToken,
|
||||
mozilla::ErrorResult& aError);
|
||||
bool Toggle(const nsAString& aToken,
|
||||
const mozilla::dom::Optional<bool>& force,
|
||||
mozilla::ErrorResult& aError);
|
||||
bool Supports(const nsAString& aToken,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
void GetValue(nsAString& aResult) { Stringify(aResult); }
|
||||
void SetValue(const nsAString& aValue, mozilla::ErrorResult& rv);
|
||||
void Stringify(nsAString& aResult);
|
||||
|
||||
protected:
|
||||
@@ -73,14 +85,20 @@ protected:
|
||||
|
||||
nsresult CheckToken(const nsAString& aStr);
|
||||
nsresult CheckTokens(const nsTArray<nsString>& aStr);
|
||||
void RemoveDuplicatesInternal(nsTArray<nsCOMPtr<nsIAtom>>* aArray,
|
||||
uint32_t aStart);
|
||||
void AddInternal(const nsAttrValue* aAttr,
|
||||
const nsTArray<nsString>& aTokens);
|
||||
void RemoveInternal(const nsAttrValue* aAttr,
|
||||
const nsTArray<nsString>& aTokens);
|
||||
void ReplaceInternal(const nsAttrValue* aAttr,
|
||||
const nsAString& aToken,
|
||||
const nsAString& aNewToken);
|
||||
inline const nsAttrValue* GetParsedAttr();
|
||||
|
||||
nsCOMPtr<Element> mElement;
|
||||
nsCOMPtr<nsIAtom> mAttrAtom;
|
||||
const mozilla::dom::DOMTokenListSupportedTokenArray mSupportedTokens;
|
||||
};
|
||||
|
||||
#endif // nsDOMTokenList_h___
|
||||
|
||||
+21
-6
@@ -347,17 +347,32 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base URI for relative URIs in the document (the document uri
|
||||
* unless it's overridden by SetBaseURI, HTML <base> tags, etc.). The
|
||||
* returned URI could be null if there is no document URI. If the document
|
||||
* is a srcdoc document, return the parent document's base URL.
|
||||
* Return the fallback base URL for this document, as defined in the HTML
|
||||
* specification. Note that this can return null if there is no document URI.
|
||||
*
|
||||
* XXXbz: This doesn't implement the bits for about:blank yet.
|
||||
*/
|
||||
nsIURI* GetDocBaseURI() const
|
||||
nsIURI* GetFallbackBaseURI() const
|
||||
{
|
||||
if (mIsSrcdocDocument && mParentDocument) {
|
||||
return mParentDocument->GetDocBaseURI();
|
||||
}
|
||||
return mDocumentBaseURI ? mDocumentBaseURI : mDocumentURI;
|
||||
return mDocumentURI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base URI for relative URIs in the document (the document uri
|
||||
* unless it's overridden by SetBaseURI, HTML <base> tags, etc.). The
|
||||
* returned URI could be null if there is no document URI. If the document is
|
||||
* a srcdoc document and has no explicit base URL, return the parent
|
||||
* document's base URL.
|
||||
*/
|
||||
nsIURI* GetDocBaseURI() const
|
||||
{
|
||||
if (mDocumentBaseURI) {
|
||||
return mDocumentBaseURI;
|
||||
}
|
||||
return GetFallbackBaseURI();
|
||||
}
|
||||
virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
|
||||
|
||||
|
||||
@@ -93,16 +93,16 @@ const size_t gStackSize = 8192;
|
||||
|
||||
// The amount of time we wait from the first request to GC to actually
|
||||
// doing the first GC.
|
||||
#define NS_FIRST_GC_DELAY 10000 // ms
|
||||
#define NS_FIRST_GC_DELAY 30000 // ms
|
||||
|
||||
#define NS_FULL_GC_DELAY 60000 // ms
|
||||
#define NS_FULL_GC_DELAY 100000 // ms
|
||||
|
||||
// The default amount of time to wait from the user being idle to starting a
|
||||
// shrinking GC.
|
||||
#define NS_DEAULT_INACTIVE_GC_DELAY 300000 // ms
|
||||
|
||||
// Maximum amount of time that should elapse between incremental GC slices
|
||||
#define NS_INTERSLICE_GC_DELAY 100 // ms
|
||||
#define NS_INTERSLICE_GC_DELAY 1000 // ms
|
||||
|
||||
// If we haven't painted in 100ms, we allow for a longer GC budget
|
||||
#define NS_INTERSLICE_GC_BUDGET 40 // ms
|
||||
@@ -111,13 +111,13 @@ const size_t gStackSize = 8192;
|
||||
// and doing the actual CC.
|
||||
#define NS_CC_DELAY 6000 // ms
|
||||
|
||||
#define NS_CC_SKIPPABLE_DELAY 250 // ms
|
||||
#define NS_CC_SKIPPABLE_DELAY 2500 // ms
|
||||
|
||||
// Maximum amount of time that should elapse between incremental CC slices
|
||||
static const int64_t kICCIntersliceDelay = 32; // ms
|
||||
static const int64_t kICCIntersliceDelay = 1000; // ms
|
||||
|
||||
// Time budget for an incremental CC slice
|
||||
static const int64_t kICCSliceBudget = 5; // ms
|
||||
static const int64_t kICCSliceBudget = 100; // ms
|
||||
|
||||
// Maximum total duration for an ICC
|
||||
static const uint32_t kMaxICCDuration = 2000; // ms
|
||||
@@ -125,7 +125,7 @@ static const uint32_t kMaxICCDuration = 2000; // ms
|
||||
// Force a CC after this long if there's more than NS_CC_FORCED_PURPLE_LIMIT
|
||||
// objects in the purple buffer.
|
||||
#define NS_CC_FORCED (2 * 60 * PR_USEC_PER_SEC) // 2 min
|
||||
#define NS_CC_FORCED_PURPLE_LIMIT 10
|
||||
#define NS_CC_FORCED_PURPLE_LIMIT 9
|
||||
|
||||
// Don't allow an incremental GC to lock out the CC for too long.
|
||||
#define NS_MAX_CC_LOCKEDOUT_TIME (30 * PR_USEC_PER_SEC) // 30 seconds
|
||||
|
||||
@@ -149,7 +149,9 @@ nsStyleLinkElement::IsImportEnabled()
|
||||
}
|
||||
|
||||
static uint32_t ToLinkMask(const nsAString& aLink, nsIPrincipal* aPrincipal)
|
||||
{
|
||||
{
|
||||
// Keep this in sync with sRelValues in HTMLLinkElement.cpp
|
||||
// XXX: "icon" and "search" are supported, but not listed here.
|
||||
if (aLink.EqualsLiteral("prefetch"))
|
||||
return nsStyleLinkElement::ePREFETCH;
|
||||
else if (aLink.EqualsLiteral("dns-prefetch"))
|
||||
|
||||
+24
-34
@@ -334,22 +334,22 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
|
||||
|
||||
// Should we optimize for aData.Length() == 0?
|
||||
|
||||
CheckedUint32 length = mState.mLength;
|
||||
length += aLength;
|
||||
|
||||
if (!length.isValid()) {
|
||||
return false;
|
||||
// FYI: Don't use CheckedInt in this method since here is very hot path
|
||||
// in some performance tests.
|
||||
if (MOZ_UNLIKELY(NS_MAX_TEXT_FRAGMENT_LENGTH - mState.mLength < aLength)) {
|
||||
return false; // Would be overflown if we'd keep handling.
|
||||
}
|
||||
|
||||
if (mState.mIs2b) {
|
||||
length *= sizeof(char16_t);
|
||||
if (!length.isValid()) {
|
||||
return false;
|
||||
size_t size = mState.mLength + aLength;
|
||||
if (MOZ_UNLIKELY(SIZE_MAX / sizeof(char16_t) < size)) {
|
||||
return false; // Would be overflown if we'd keep handling.
|
||||
}
|
||||
size *= sizeof(char16_t);
|
||||
|
||||
// Already a 2-byte string so the result will be too
|
||||
char16_t* buff = static_cast<char16_t*>(realloc(m2b, length.value()));
|
||||
if (!buff) {
|
||||
char16_t* buff = static_cast<char16_t*>(realloc(m2b, size));
|
||||
if (MOZ_UNLIKELY(!buff)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -368,15 +368,16 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
|
||||
int32_t first16bit = FirstNon8Bit(aBuffer, aBuffer + aLength);
|
||||
|
||||
if (first16bit != -1) { // aBuffer contains no non-8bit character
|
||||
length *= sizeof(char16_t);
|
||||
if (!length.isValid()) {
|
||||
return false;
|
||||
size_t size = mState.mLength + aLength;
|
||||
if (MOZ_UNLIKELY((SIZE_MAX / sizeof(char16_t)) < size)) {
|
||||
return false; // Would be overflown if we'd keep handling.
|
||||
}
|
||||
size *= sizeof(char16_t);
|
||||
|
||||
// The old data was 1-byte, but the new is not so we have to expand it
|
||||
// all to 2-byte
|
||||
char16_t* buff = static_cast<char16_t*>(malloc(length.value()));
|
||||
if (!buff) {
|
||||
char16_t* buff = static_cast<char16_t*>(malloc(size));
|
||||
if (MOZ_UNLIKELY(!buff)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -403,16 +404,18 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
|
||||
}
|
||||
|
||||
// The new and the old data is all 1-byte
|
||||
size_t size = mState.mLength + aLength;
|
||||
MOZ_ASSERT(sizeof(char) == 1);
|
||||
char* buff;
|
||||
if (mState.mInHeap) {
|
||||
buff = static_cast<char*>(realloc(const_cast<char*>(m1b), length.value()));
|
||||
if (!buff) {
|
||||
buff = static_cast<char*>(realloc(const_cast<char*>(m1b), size));
|
||||
if (MOZ_UNLIKELY(!buff)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
buff = static_cast<char*>(malloc(length.value()));
|
||||
if (!buff) {
|
||||
buff = static_cast<char*>(malloc(size));
|
||||
if (MOZ_UNLIKELY(!buff)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -450,21 +453,8 @@ void
|
||||
nsTextFragment::UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength)
|
||||
{
|
||||
if (mState.mIs2b && !mState.mIsBidi) {
|
||||
const char16_t* cp = aBuffer;
|
||||
const char16_t* end = cp + aLength;
|
||||
while (cp < end) {
|
||||
char16_t ch1 = *cp++;
|
||||
uint32_t utf32Char = ch1;
|
||||
if (NS_IS_HIGH_SURROGATE(ch1) &&
|
||||
cp < end &&
|
||||
NS_IS_LOW_SURROGATE(*cp)) {
|
||||
char16_t ch2 = *cp++;
|
||||
utf32Char = SURROGATE_TO_UCS4(ch1, ch2);
|
||||
}
|
||||
if (UTF32_CHAR_IS_BIDI(utf32Char) || IsBidiControl(utf32Char)) {
|
||||
mState.mIsBidi = true;
|
||||
break;
|
||||
}
|
||||
if (HasRTLChars(aBuffer, aLength)) {
|
||||
mState.mIsBidi = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,9 +213,13 @@ public:
|
||||
uint32_t mInHeap : 1;
|
||||
uint32_t mIs2b : 1;
|
||||
uint32_t mIsBidi : 1;
|
||||
// Note that when you change the bits of mLength, you also need to change
|
||||
// NS_MAX_TEXT_FRAGMENT_LENGTH.
|
||||
uint32_t mLength : 29;
|
||||
};
|
||||
|
||||
#define NS_MAX_TEXT_FRAGMENT_LENGTH (static_cast<uint32_t>(0x1FFFFFFF))
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -441,10 +441,6 @@ DOMInterfaces = {
|
||||
'implicitJSContext': [ 'then' ],
|
||||
},
|
||||
|
||||
'DOMSettableTokenList': {
|
||||
'nativeType': 'nsDOMSettableTokenList',
|
||||
},
|
||||
|
||||
'DOMStringMap': {
|
||||
'nativeType': 'nsDOMStringMap'
|
||||
},
|
||||
|
||||
+79
-35
@@ -1136,11 +1136,13 @@ class CGHeaders(CGWrapper):
|
||||
if desc.interface.maplikeOrSetlikeOrIterable:
|
||||
# We need ToJSValue.h for maplike/setlike type conversions
|
||||
bindingHeaders.add("mozilla/dom/ToJSValue.h")
|
||||
# Add headers for the key and value types of the maplike, since
|
||||
# they'll be needed for convenience functions
|
||||
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.keyType,
|
||||
desc, None))
|
||||
if desc.interface.maplikeOrSetlikeOrIterable.valueType:
|
||||
# Add headers for the key and value types of the
|
||||
# maplike/setlike/iterable, since they'll be needed for
|
||||
# convenience functions
|
||||
if desc.interface.maplikeOrSetlikeOrIterable.hasKeyType():
|
||||
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.keyType,
|
||||
desc, None))
|
||||
if desc.interface.maplikeOrSetlikeOrIterable.hasValueType():
|
||||
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.valueType,
|
||||
desc, None))
|
||||
|
||||
@@ -2269,34 +2271,50 @@ class MethodDefiner(PropertyDefiner):
|
||||
"condition": MemberCondition()
|
||||
})
|
||||
|
||||
# Generate the maplike/setlike iterator, if one wasn't already
|
||||
# generated by a method. If we already have an @@iterator symbol, fail.
|
||||
if descriptor.interface.maplikeOrSetlikeOrIterable:
|
||||
if hasIterator(methods, self.regular):
|
||||
raise TypeError("Cannot have maplike/setlike/iterable interface with "
|
||||
"other members that generate @@iterator "
|
||||
"on interface %s, such as indexed getters "
|
||||
"or aliased functions." %
|
||||
self.descriptor.interface.identifier.name)
|
||||
for m in methods:
|
||||
if (m.isMaplikeOrSetlikeOrIterableMethod() and
|
||||
(((m.maplikeOrSetlikeOrIterable.isMaplike() or
|
||||
(m.maplikeOrSetlikeOrIterable.isIterable() and
|
||||
m.maplikeOrSetlikeOrIterable.hasValueType())) and
|
||||
m.identifier.name == "entries") or
|
||||
(((m.maplikeOrSetlikeOrIterable.isSetlike() or
|
||||
(m.maplikeOrSetlikeOrIterable.isIterable() and
|
||||
not m.maplikeOrSetlikeOrIterable.hasValueType()))) and
|
||||
m.identifier.name == "values"))):
|
||||
self.regular.append({
|
||||
"name": "@@iterator",
|
||||
"methodName": m.identifier.name,
|
||||
"length": methodLength(m),
|
||||
"flags": "0",
|
||||
"condition": PropertyDefiner.getControllingCondition(m,
|
||||
descriptor),
|
||||
})
|
||||
break
|
||||
# Generate the keys/values/entries aliases for value iterables.
|
||||
maplikeOrSetlikeOrIterable = descriptor.interface.maplikeOrSetlikeOrIterable
|
||||
if (not static and
|
||||
not unforgeable and
|
||||
maplikeOrSetlikeOrIterable and
|
||||
maplikeOrSetlikeOrIterable.isIterable() and
|
||||
maplikeOrSetlikeOrIterable.isValueIterator()):
|
||||
# Add our keys/values/entries/forEach
|
||||
self.regular.append({
|
||||
"name": "keys",
|
||||
"methodInfo": False,
|
||||
"selfHostedName": "ArrayKeys",
|
||||
"length": 0,
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"condition": PropertyDefiner.getControllingCondition(m,
|
||||
descriptor)
|
||||
})
|
||||
self.regular.append({
|
||||
"name": "values",
|
||||
"methodInfo": False,
|
||||
"selfHostedName": "ArrayValues",
|
||||
"length": 0,
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"condition": PropertyDefiner.getControllingCondition(m,
|
||||
descriptor)
|
||||
})
|
||||
self.regular.append({
|
||||
"name": "entries",
|
||||
"methodInfo": False,
|
||||
"selfHostedName": "ArrayEntries",
|
||||
"length": 0,
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"condition": PropertyDefiner.getControllingCondition(m,
|
||||
descriptor)
|
||||
})
|
||||
self.regular.append({
|
||||
"name": "forEach",
|
||||
"methodInfo": False,
|
||||
"selfHostedName": "ArrayForEach",
|
||||
"length": 1,
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"condition": PropertyDefiner.getControllingCondition(m,
|
||||
descriptor)
|
||||
})
|
||||
|
||||
if not static:
|
||||
stringifier = descriptor.operations['Stringifier']
|
||||
@@ -13008,8 +13026,9 @@ class CGForwardDeclarations(CGWrapper):
|
||||
# arguments to helper functions, and they'll need to be forward
|
||||
# declared in the header.
|
||||
if d.interface.maplikeOrSetlikeOrIterable:
|
||||
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.keyType,
|
||||
config)
|
||||
if d.interface.maplikeOrSetlikeOrIterable.hasKeyType():
|
||||
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.keyType,
|
||||
config)
|
||||
if d.interface.maplikeOrSetlikeOrIterable.hasValueType():
|
||||
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.valueType,
|
||||
config)
|
||||
@@ -15735,6 +15754,31 @@ class CGIterableMethodGenerator(CGGeneric):
|
||||
using CGCallGenerator.
|
||||
"""
|
||||
def __init__(self, descriptor, iterable, methodName):
|
||||
if methodName == "forEach":
|
||||
CGGeneric.__init__(self, fill(
|
||||
"""
|
||||
if (!JS::IsCallable(arg0)) {
|
||||
ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 1 of ${ifaceName}.forEach");
|
||||
return false;
|
||||
}
|
||||
JS::AutoValueArray<3> callArgs(cx);
|
||||
callArgs[2].setObject(*obj);
|
||||
JS::Rooted<JS::Value> ignoredReturnVal(cx);
|
||||
for (size_t i = 0; i < self->GetIterableLength(); ++i) {
|
||||
if (!ToJSValue(cx, self->GetValueAtIndex(i), callArgs[0])) {
|
||||
return false;
|
||||
}
|
||||
if (!ToJSValue(cx, self->GetKeyAtIndex(i), callArgs[1])) {
|
||||
return false;
|
||||
}
|
||||
if (!JS::Call(cx, arg1, arg0, JS::HandleValueArray(callArgs),
|
||||
&ignoredReturnVal)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
""",
|
||||
ifaceName=descriptor.interface.identifier.name))
|
||||
return
|
||||
CGGeneric.__init__(self, fill(
|
||||
"""
|
||||
typedef ${iterClass} itrType;
|
||||
|
||||
@@ -893,8 +893,5 @@ def getAllTypes(descriptors, dictionaries, callbacks):
|
||||
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)
|
||||
assert iterableDecl.isPairIterator()
|
||||
return "mozilla::dom::IterableIterator<%s>" % descriptor.nativeType
|
||||
|
||||
@@ -92,3 +92,4 @@ MSG_DEF(MSG_IS_NOT_PROMISE, 1, JSEXN_TYPEERR, "{0} is not a Promise")
|
||||
MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} encountered an error during installation.")
|
||||
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
|
||||
MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a typed array on SharedArrayBuffer")
|
||||
MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")
|
||||
|
||||
+71
-164
@@ -6,19 +6,17 @@
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* iterable<> member defined with two types (so a pair iterator). 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 with a pair iterator, the implementation class will
|
||||
* need to implement these two 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
|
||||
*
|
||||
@@ -60,13 +58,77 @@ protected:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class IterableIterator : public IterableIteratorBase
|
||||
class IterableIterator final : public IterableIteratorBase
|
||||
{
|
||||
public:
|
||||
explicit IterableIterator(T* aIterableObj)
|
||||
typedef bool (*WrapFunc)(JSContext* aCx,
|
||||
IterableIterator<T>* aObject,
|
||||
JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aReflector);
|
||||
|
||||
explicit IterableIterator(T* aIterableObj,
|
||||
IterableIteratorType aIteratorType,
|
||||
WrapFunc aWrapFunc)
|
||||
: mIterableObj(aIterableObj)
|
||||
, mIteratorType(aIteratorType)
|
||||
, mWrapFunc(aWrapFunc)
|
||||
, mIndex(0)
|
||||
{
|
||||
MOZ_ASSERT(mIterableObj);
|
||||
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:
|
||||
@@ -128,161 +190,6 @@ protected:
|
||||
|
||||
// Binding Implementation object that we're iterating over.
|
||||
RefPtr<T> mIterableObj;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class OneTypeIterableIterator final : public IterableIterator<T>
|
||||
{
|
||||
public:
|
||||
typedef typename IterableIterator<T>::IterableIteratorType 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:
|
||||
typedef typename IterableIterator<T>::IterableIteratorType 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.
|
||||
|
||||
+100
-25
@@ -1089,7 +1089,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
|
||||
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
|
||||
# this here, because in finish() an interface might not know yet that
|
||||
# it's consequential.
|
||||
if self.getExtendedAttribute("Unforgeable") and self.isConsequential():
|
||||
raise WebIDLError(
|
||||
@@ -1108,6 +1108,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
self.identifier.name,
|
||||
locations)
|
||||
|
||||
indexedGetter = None
|
||||
hasLengthAttribute = False
|
||||
for member in self.members:
|
||||
member.validate()
|
||||
|
||||
@@ -1118,8 +1120,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
[self.location, member.location])
|
||||
|
||||
# Check that PutForwards refers to another attribute and that no
|
||||
# cycles exist in forwarded assignments.
|
||||
# cycles exist in forwarded assignments. Also check for a
|
||||
# integer-typed "length" attribute.
|
||||
if member.isAttr():
|
||||
if (member.identifier.name == "length" and
|
||||
member.type.isInteger()):
|
||||
hasLengthAttribute = True
|
||||
|
||||
iface = self
|
||||
attr = member
|
||||
putForwards = attr.getExtendedAttribute("PutForwards")
|
||||
@@ -1157,8 +1164,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
putForwards = attr.getExtendedAttribute("PutForwards")
|
||||
|
||||
# Check that the name of an [Alias] doesn't conflict with an
|
||||
# interface member.
|
||||
# interface member and whether we support indexed properties.
|
||||
if member.isMethod():
|
||||
if member.isGetter() and member.isIndexed():
|
||||
indexedGetter = member
|
||||
|
||||
for alias in member.aliases:
|
||||
if self.isOnGlobalProtoChain():
|
||||
raise WebIDLError("[Alias] must not be used on a "
|
||||
@@ -1219,6 +1229,35 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
"exposed conditionally",
|
||||
[self.location])
|
||||
|
||||
# Value iterators are only allowed on interfaces with indexed getters,
|
||||
# and pair iterators are only allowed on interfaces without indexed
|
||||
# getters.
|
||||
if self.isIterable():
|
||||
iterableDecl = self.maplikeOrSetlikeOrIterable
|
||||
if iterableDecl.isValueIterator():
|
||||
if not indexedGetter:
|
||||
raise WebIDLError("Interface with value iterator does not "
|
||||
"support indexed properties",
|
||||
[self.location])
|
||||
|
||||
if iterableDecl.valueType != indexedGetter.signatures()[0][0]:
|
||||
raise WebIDLError("Iterable type does not match indexed "
|
||||
"getter type",
|
||||
[iterableDecl.location,
|
||||
indexedGetter.location])
|
||||
|
||||
if not hasLengthAttribute:
|
||||
raise WebIDLError('Interface with value iterator does not '
|
||||
'have an integer-typed "length" attribute',
|
||||
[self.location])
|
||||
else:
|
||||
assert iterableDecl.isPairIterator()
|
||||
if indexedGetter:
|
||||
raise WebIDLError("Interface with pair iterator supports "
|
||||
"indexed properties",
|
||||
[self.location, iterableDecl.location,
|
||||
indexedGetter.location])
|
||||
|
||||
def isInterface(self):
|
||||
return True
|
||||
|
||||
@@ -3408,7 +3447,10 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
|
||||
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
|
||||
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
|
||||
assert isinstance(keyType, IDLType)
|
||||
if keyType is not None:
|
||||
assert isinstance(keyType, IDLType)
|
||||
else:
|
||||
assert valueType is not None
|
||||
assert ifaceType in ['maplike', 'setlike', 'iterable']
|
||||
if valueType is not None:
|
||||
assert isinstance(valueType, IDLType)
|
||||
@@ -3427,6 +3469,9 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
def isIterable(self):
|
||||
return self.maplikeOrSetlikeOrIterableType == "iterable"
|
||||
|
||||
def hasKeyType(self):
|
||||
return self.keyType is not None
|
||||
|
||||
def hasValueType(self):
|
||||
return self.valueType is not None
|
||||
|
||||
@@ -3451,7 +3496,8 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
[self.location, member.location])
|
||||
|
||||
def addMethod(self, name, members, allowExistingOperations, returnType, args=[],
|
||||
chromeOnly=False, isPure=False, affectsNothing=False, newObject=False):
|
||||
chromeOnly=False, isPure=False, affectsNothing=False, newObject=False,
|
||||
isIteratorAlias=False):
|
||||
"""
|
||||
Create an IDLMethod based on the parameters passed in.
|
||||
|
||||
@@ -3511,16 +3557,20 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
if newObject:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("NewObject",))])
|
||||
if isIteratorAlias:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("Alias", "@@iterator"))])
|
||||
members.append(method)
|
||||
|
||||
def resolve(self, parentScope):
|
||||
self.keyType.resolveType(parentScope)
|
||||
if self.keyType:
|
||||
self.keyType.resolveType(parentScope)
|
||||
if self.valueType:
|
||||
self.valueType.resolveType(parentScope)
|
||||
|
||||
def finish(self, scope):
|
||||
IDLInterfaceMember.finish(self, scope)
|
||||
if not self.keyType.isComplete():
|
||||
if self.keyType and not self.keyType.isComplete():
|
||||
t = self.keyType.complete(scope)
|
||||
|
||||
assert not isinstance(t, IDLUnresolvedType)
|
||||
@@ -3542,9 +3592,23 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
IDLInterfaceMember.handleExtendedAttribute(self, attr)
|
||||
|
||||
def _getDependentObjects(self):
|
||||
deps = set()
|
||||
if self.keyType:
|
||||
deps.add(self.keyType)
|
||||
if self.valueType:
|
||||
return set([self.keyType, self.valueType])
|
||||
return set([self.keyType])
|
||||
deps.add(self.valueType)
|
||||
return deps
|
||||
|
||||
def getForEachArguments(self):
|
||||
return [IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||
"callback"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.object]),
|
||||
IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||
"thisArg"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.any],
|
||||
optional=True)]
|
||||
|
||||
# Iterable adds ES6 iterator style functions and traits
|
||||
# (keys/values/entries/@@iterator) to an interface.
|
||||
@@ -3565,9 +3629,15 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
we generate our functions as if they were part of the interface
|
||||
specification during parsing.
|
||||
"""
|
||||
# We only need to add entries/keys/values here if we're a pair iterator.
|
||||
# Value iterators just copy these from %ArrayPrototype% instead.
|
||||
if not self.isPairIterator():
|
||||
return
|
||||
|
||||
# object entries()
|
||||
self.addMethod("entries", members, False, self.iteratorType,
|
||||
affectsNothing=True, newObject=True)
|
||||
affectsNothing=True, newObject=True,
|
||||
isIteratorAlias=True)
|
||||
# object keys()
|
||||
self.addMethod("keys", members, False, self.iteratorType,
|
||||
affectsNothing=True, newObject=True)
|
||||
@@ -3575,6 +3645,17 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
self.addMethod("values", members, False, self.iteratorType,
|
||||
affectsNothing=True, newObject=True)
|
||||
|
||||
# void forEach(callback(valueType, keyType), optional any thisArg)
|
||||
self.addMethod("forEach", members, False,
|
||||
BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
self.getForEachArguments())
|
||||
|
||||
def isValueIterator(self):
|
||||
return not self.isPairIterator()
|
||||
|
||||
def isPairIterator(self):
|
||||
return self.hasKeyType()
|
||||
|
||||
# MaplikeOrSetlike adds ES6 map-or-set-like traits to an interface.
|
||||
class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
|
||||
@@ -3611,26 +3692,17 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
|
||||
# object entries()
|
||||
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
affectsNothing=True)
|
||||
affectsNothing=True, isIteratorAlias=self.isMaplike())
|
||||
# object keys()
|
||||
self.addMethod("keys", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
affectsNothing=True)
|
||||
# object values()
|
||||
self.addMethod("values", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
affectsNothing=True)
|
||||
affectsNothing=True, isIteratorAlias=self.isSetlike())
|
||||
|
||||
# void forEach(callback(valueType, keyType), thisVal)
|
||||
foreachArguments = [IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||
"callback"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.object]),
|
||||
IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||
"thisArg"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.any],
|
||||
optional=True)]
|
||||
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
foreachArguments)
|
||||
self.getForEachArguments())
|
||||
|
||||
def getKeyArg():
|
||||
return IDLArgument(self.location,
|
||||
@@ -5436,10 +5508,13 @@ class Parser(Tokenizer):
|
||||
location = self.getLocation(p, 2)
|
||||
identifier = IDLUnresolvedIdentifier(location, "__iterable",
|
||||
allowDoubleUnderscore=True)
|
||||
keyType = p[3]
|
||||
valueType = None
|
||||
if (len(p) > 6):
|
||||
keyType = p[3]
|
||||
valueType = p[5]
|
||||
else:
|
||||
keyType = None
|
||||
valueType = p[3]
|
||||
|
||||
p[0] = IDLIterable(location, identifier, keyType, valueType, self.globalScope())
|
||||
|
||||
def p_Setlike(self, p):
|
||||
@@ -6509,7 +6584,7 @@ class Parser(Tokenizer):
|
||||
if isinstance(m, IDLIterable):
|
||||
iterable = m
|
||||
break
|
||||
if iterable:
|
||||
if iterable and iterable.isPairIterator():
|
||||
def simpleExtendedAttr(str):
|
||||
return IDLExtendedAttribute(iface.location, (str, ))
|
||||
nextMethod = IDLMethod(
|
||||
|
||||
@@ -55,17 +55,22 @@ TestInterfaceIterableSingle::GetParentObject() const
|
||||
return mParent;
|
||||
}
|
||||
|
||||
size_t
|
||||
TestInterfaceIterableSingle::GetIterableLength() const
|
||||
uint32_t
|
||||
TestInterfaceIterableSingle::Length() const
|
||||
{
|
||||
return mValues.Length();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TestInterfaceIterableSingle::GetValueAtIndex(uint32_t index) const
|
||||
int32_t
|
||||
TestInterfaceIterableSingle::IndexedGetter(uint32_t aIndex, bool& aFound) const
|
||||
{
|
||||
MOZ_ASSERT(index < mValues.Length());
|
||||
return mValues.ElementAt(index);
|
||||
if (aIndex >= mValues.Length()) {
|
||||
aFound = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
aFound = true;
|
||||
return mValues[aIndex];
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -36,12 +36,13 @@ public:
|
||||
static already_AddRefed<TestInterfaceIterableSingle>
|
||||
Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
|
||||
|
||||
size_t GetIterableLength() const;
|
||||
uint32_t GetValueAtIndex(uint32_t aIndex) const;
|
||||
uint32_t Length() const;
|
||||
int32_t IndexedGetter(uint32_t aIndex, bool& aFound) const;
|
||||
|
||||
private:
|
||||
virtual ~TestInterfaceIterableSingle() {}
|
||||
nsCOMPtr<nsPIDOMWindow> mParent;
|
||||
nsTArray<uint32_t> mValues;
|
||||
nsTArray<int32_t> mValues;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -39,6 +39,12 @@ ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
|
||||
|
||||
#undef ANCHOR_ELEMENT_FLAG_BIT
|
||||
|
||||
// static
|
||||
const DOMTokenListSupportedToken HTMLAnchorElement::sSupportedRelValues[] = {
|
||||
"noreferrer",
|
||||
nullptr
|
||||
};
|
||||
|
||||
HTMLAnchorElement::~HTMLAnchorElement()
|
||||
{
|
||||
}
|
||||
@@ -302,7 +308,7 @@ nsDOMTokenList*
|
||||
HTMLAnchorElement::RelList()
|
||||
{
|
||||
if (!mRelList) {
|
||||
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel);
|
||||
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues);
|
||||
}
|
||||
return mRelList;
|
||||
}
|
||||
|
||||
@@ -227,6 +227,8 @@ public:
|
||||
GetHref(aResult);
|
||||
}
|
||||
|
||||
static DOMTokenListSupportedToken sSupportedRelValues[];
|
||||
|
||||
protected:
|
||||
virtual ~HTMLAnchorElement();
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "mozilla/dom/HTMLAreaElement.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||
#include "mozilla/dom/HTMLAreaElementBinding.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
@@ -122,7 +123,8 @@ nsDOMTokenList*
|
||||
HTMLAreaElement::RelList()
|
||||
{
|
||||
if (!mRelList) {
|
||||
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel);
|
||||
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel,
|
||||
HTMLAnchorElement::sSupportedRelValues);
|
||||
}
|
||||
return mRelList;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,15 @@ NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame)
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// static
|
||||
const DOMTokenListSupportedToken HTMLIFrameElement::sSupportedSandboxTokens[] =
|
||||
{
|
||||
#define SANDBOX_KEYWORD(string, atom, flags) string,
|
||||
#include "IframeSandboxKeywordList.h"
|
||||
#undef SANDBOX_KEYWORD
|
||||
nullptr
|
||||
};
|
||||
|
||||
HTMLIFrameElement::HTMLIFrameElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
|
||||
FromParser aFromParser)
|
||||
: nsGenericHTMLFrameElement(aNodeInfo, aFromParser)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsGenericHTMLFrameElement.h"
|
||||
#include "nsIDOMHTMLIFrameElement.h"
|
||||
#include "nsDOMSettableTokenList.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@@ -84,9 +84,9 @@ public:
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::name, aName, aError);
|
||||
}
|
||||
nsDOMSettableTokenList* Sandbox()
|
||||
nsDOMTokenList* Sandbox()
|
||||
{
|
||||
return GetTokenList(nsGkAtoms::sandbox);
|
||||
return GetTokenList(nsGkAtoms::sandbox, sSupportedSandboxTokens);
|
||||
}
|
||||
bool AllowFullscreen() const
|
||||
{
|
||||
@@ -202,6 +202,8 @@ protected:
|
||||
private:
|
||||
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
nsRuleData* aData);
|
||||
|
||||
static const DOMTokenListSupportedToken sSupportedSandboxTokens[];
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsStyleLinkElement.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
#define LINK_ELEMENT_FLAG_BIT(n_) \
|
||||
@@ -499,11 +500,30 @@ HTMLLinkElement::GetLinkTarget(nsAString& aTarget)
|
||||
}
|
||||
}
|
||||
|
||||
static const DOMTokenListSupportedToken sSupportedRelValues[] = {
|
||||
// Keep this in sync with ToLinkMask in nsStyleLinkElement.cpp.
|
||||
// "import" must come first because it's conditional.
|
||||
"import"
|
||||
"prefetch",
|
||||
"dns-prefetch",
|
||||
"stylesheet",
|
||||
"next",
|
||||
"alternate",
|
||||
"preconnect",
|
||||
"icon",
|
||||
"search",
|
||||
nullptr
|
||||
};
|
||||
|
||||
nsDOMTokenList*
|
||||
HTMLLinkElement::RelList()
|
||||
{
|
||||
if (!mRelList) {
|
||||
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel);
|
||||
const DOMTokenListSupportedTokenArray relValues =
|
||||
nsStyleLinkElement::IsImportEnabled() ?
|
||||
sSupportedRelValues : &sSupportedRelValues[1];
|
||||
|
||||
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, relValues);
|
||||
}
|
||||
return mRelList;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::hreflang, aHreflang, aRv);
|
||||
}
|
||||
nsDOMSettableTokenList* Sizes()
|
||||
nsDOMTokenList* Sizes()
|
||||
{
|
||||
return GetTokenList(nsGkAtoms::sizes);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/HTMLMenuItemElementBinding.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(MenuItem)
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "mozilla/dom/HTMLFormElement.h"
|
||||
#include "mozilla/dom/HTMLOutputElementBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMSettableTokenList.h"
|
||||
#include "nsFormSubmission.h"
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output)
|
||||
@@ -166,11 +165,11 @@ HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult&
|
||||
}
|
||||
}
|
||||
|
||||
nsDOMSettableTokenList*
|
||||
nsDOMTokenList*
|
||||
HTMLOutputElement::HtmlFor()
|
||||
{
|
||||
if (!mTokenList) {
|
||||
mTokenList = new nsDOMSettableTokenList(this, nsGkAtoms::_for);
|
||||
mTokenList = new nsDOMTokenList(this, nsGkAtoms::_for);
|
||||
}
|
||||
return mTokenList;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// WebIDL
|
||||
nsDOMSettableTokenList* HtmlFor();
|
||||
nsDOMTokenList* HtmlFor();
|
||||
// nsGenericHTMLFormElement::GetForm is fine.
|
||||
void GetName(nsAString& aName)
|
||||
{
|
||||
@@ -108,7 +108,7 @@ protected:
|
||||
ValueModeFlag mValueModeFlag;
|
||||
bool mIsDoneAddingChildren;
|
||||
nsString mDefaultValue;
|
||||
RefPtr<nsDOMSettableTokenList> mTokenList;
|
||||
RefPtr<nsDOMTokenList> mTokenList;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsVariant.h"
|
||||
#include "nsDOMSettableTokenList.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
#include "nsAttrValue.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "mozilla/dom/HTMLPropertiesCollectionBinding.h"
|
||||
|
||||
@@ -164,14 +164,15 @@ SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch)
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve the <base> element's href relative to our document URI
|
||||
// Resolve the <base> element's href relative to our document's
|
||||
// fallback base URI.
|
||||
nsAutoString href;
|
||||
child->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
|
||||
|
||||
nsCOMPtr<nsIURI> newBaseURI;
|
||||
nsContentUtils::NewURIWithDocumentCharset(
|
||||
getter_AddRefs(newBaseURI), href, aDocument,
|
||||
aDocument->GetDocumentURI());
|
||||
aDocument->GetFallbackBaseURI());
|
||||
|
||||
// Try to set our base URI. If that fails, try to set base URI to null
|
||||
nsresult rv = aDocument->SetBaseURI(newBaseURI);
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
{
|
||||
SetUnsignedIntAttr(nsGkAtoms::rowspan, aRowSpan, aError);
|
||||
}
|
||||
//already_AddRefed<nsDOMSettableTokenList> Headers() const;
|
||||
//already_AddRefed<nsDOMTokenList> Headers() const;
|
||||
void GetHeaders(DOMString& aHeaders)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::headers, aHeaders);
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
#include "HTMLPropertiesCollection.h"
|
||||
#include "nsVariant.h"
|
||||
#include "nsDOMSettableTokenList.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "mozilla/dom/ValidityState.h"
|
||||
#include "mozilla/dom/ElementInlines.h"
|
||||
|
||||
class nsDOMSettableTokenList;
|
||||
class nsDOMTokenList;
|
||||
class nsIDOMHTMLMenuElement;
|
||||
class nsIEditor;
|
||||
class nsIFormControlFrame;
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
{
|
||||
SetHTMLBoolAttr(nsGkAtoms::itemscope, aItemScope, aError);
|
||||
}
|
||||
nsDOMSettableTokenList* ItemType()
|
||||
nsDOMTokenList* ItemType()
|
||||
{
|
||||
return GetTokenList(nsGkAtoms::itemtype);
|
||||
}
|
||||
@@ -116,11 +116,11 @@ public:
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::itemid, aItemID, aError);
|
||||
}
|
||||
nsDOMSettableTokenList* ItemRef()
|
||||
nsDOMTokenList* ItemRef()
|
||||
{
|
||||
return GetTokenList(nsGkAtoms::itemref);
|
||||
}
|
||||
nsDOMSettableTokenList* ItemProp()
|
||||
nsDOMTokenList* ItemProp()
|
||||
{
|
||||
return GetTokenList(nsGkAtoms::itemprop);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ interface nsIDOMHTMLElement : nsIDOMElement
|
||||
attribute nsIVariant itemType;
|
||||
attribute DOMString itemId;
|
||||
readonly attribute nsISupports properties;
|
||||
// The following attributes are really nsDOMSettableTokenList, which has
|
||||
// The following attributes are really nsDOMTokenList, which has
|
||||
// PutForwards, so we express them as nsIVariants to deal with this.
|
||||
attribute nsIVariant itemValue;
|
||||
attribute nsIVariant itemProp;
|
||||
|
||||
@@ -20,6 +20,13 @@ interface DOMTokenList {
|
||||
[Throws]
|
||||
void remove(DOMString... tokens);
|
||||
[Throws]
|
||||
void replace(DOMString token, DOMString newToken);
|
||||
[Throws]
|
||||
boolean toggle(DOMString token, optional boolean force);
|
||||
[Throws]
|
||||
boolean supports(DOMString token);
|
||||
[SetterThrows]
|
||||
attribute DOMString value;
|
||||
stringifier DOMString ();
|
||||
iterable<DOMString?>;
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ interface Element : Node {
|
||||
attribute DOMString id;
|
||||
[Pure]
|
||||
attribute DOMString className;
|
||||
[Constant]
|
||||
[Constant, PutForwards=value]
|
||||
readonly attribute DOMTokenList classList;
|
||||
|
||||
[SameObject]
|
||||
|
||||
@@ -23,6 +23,7 @@ interface HTMLAnchorElement : HTMLElement {
|
||||
attribute DOMString rel;
|
||||
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
||||
attribute DOMString referrerPolicy;
|
||||
[PutForwards=value]
|
||||
readonly attribute DOMTokenList relList;
|
||||
[SetterThrows]
|
||||
attribute DOMString hreflang;
|
||||
|
||||
@@ -30,6 +30,7 @@ interface HTMLAreaElement : HTMLElement {
|
||||
attribute DOMString rel;
|
||||
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
||||
attribute DOMString referrerPolicy;
|
||||
[PutForwards=value]
|
||||
readonly attribute DOMTokenList relList;
|
||||
};
|
||||
|
||||
|
||||
@@ -28,11 +28,11 @@ interface HTMLElement : Element {
|
||||
// microdata
|
||||
[SetterThrows, Pure]
|
||||
attribute boolean itemScope;
|
||||
[PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemType;
|
||||
[PutForwards=value,Constant] readonly attribute DOMTokenList itemType;
|
||||
[SetterThrows, Pure]
|
||||
attribute DOMString itemId;
|
||||
[PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemRef;
|
||||
[PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemProp;
|
||||
[PutForwards=value,Constant] readonly attribute DOMTokenList itemRef;
|
||||
[PutForwards=value,Constant] readonly attribute DOMTokenList itemProp;
|
||||
[Constant]
|
||||
readonly attribute HTMLPropertiesCollection properties;
|
||||
[Throws]
|
||||
@@ -54,7 +54,7 @@ interface HTMLElement : Element {
|
||||
readonly attribute DOMString accessKeyLabel;
|
||||
[SetterThrows, Pure]
|
||||
attribute boolean draggable;
|
||||
//[PutForwards=value] readonly attribute DOMSettableTokenList dropzone;
|
||||
//[PutForwards=value] readonly attribute DOMTokenList dropzone;
|
||||
[SetterThrows, Pure]
|
||||
attribute DOMString contentEditable;
|
||||
[Pure]
|
||||
|
||||
@@ -18,7 +18,7 @@ interface HTMLIFrameElement : HTMLElement {
|
||||
attribute DOMString srcdoc;
|
||||
[SetterThrows, Pure]
|
||||
attribute DOMString name;
|
||||
[PutForwards=value] readonly attribute DOMSettableTokenList sandbox;
|
||||
[PutForwards=value] readonly attribute DOMTokenList sandbox;
|
||||
// attribute boolean seamless;
|
||||
[SetterThrows, Pure]
|
||||
attribute boolean allowFullscreen;
|
||||
|
||||
@@ -21,6 +21,7 @@ interface HTMLLinkElement : HTMLElement {
|
||||
attribute DOMString? crossOrigin;
|
||||
[SetterThrows, Pure]
|
||||
attribute DOMString rel;
|
||||
[PutForwards=value]
|
||||
readonly attribute DOMTokenList relList;
|
||||
[SetterThrows, Pure]
|
||||
attribute DOMString media;
|
||||
@@ -28,7 +29,7 @@ interface HTMLLinkElement : HTMLElement {
|
||||
attribute DOMString hreflang;
|
||||
[SetterThrows, Pure]
|
||||
attribute DOMString type;
|
||||
[PutForwards=value] readonly attribute DOMSettableTokenList sizes;
|
||||
[PutForwards=value] readonly attribute DOMTokenList sizes;
|
||||
};
|
||||
HTMLLinkElement implements LinkStyle;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#the-output-element
|
||||
interface HTMLOutputElement : HTMLElement {
|
||||
[PutForwards=value, Constant]
|
||||
readonly attribute DOMSettableTokenList htmlFor;
|
||||
readonly attribute DOMTokenList htmlFor;
|
||||
readonly attribute HTMLFormElement? form;
|
||||
[SetterThrows, Pure]
|
||||
attribute DOMString name;
|
||||
|
||||
@@ -16,7 +16,7 @@ interface HTMLTableCellElement : HTMLElement {
|
||||
attribute unsigned long colSpan;
|
||||
[SetterThrows]
|
||||
attribute unsigned long rowSpan;
|
||||
//[PutForwards=value] readonly attribute DOMSettableTokenList headers;
|
||||
//[PutForwards=value] readonly attribute DOMTokenList headers;
|
||||
[SetterThrows]
|
||||
attribute DOMString headers;
|
||||
readonly attribute long cellIndex;
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
interface NodeList {
|
||||
getter Node? item(unsigned long index);
|
||||
readonly attribute unsigned long length;
|
||||
iterable<Node?>;
|
||||
};
|
||||
|
||||
@@ -50,6 +50,8 @@ interface TestInterfaceSetlikeNode {
|
||||
Pref="dom.expose_test_interfaces"]
|
||||
interface TestInterfaceIterableSingle {
|
||||
iterable<long>;
|
||||
getter long(unsigned long index);
|
||||
readonly attribute unsigned long length;
|
||||
};
|
||||
|
||||
[Constructor(),
|
||||
|
||||
@@ -132,7 +132,6 @@ WEBIDL_FILES = [
|
||||
'DOMRect.webidl',
|
||||
'DOMRectList.webidl',
|
||||
'DOMRequest.webidl',
|
||||
'DOMSettableTokenList.webidl',
|
||||
'DOMStringList.webidl',
|
||||
'DOMStringMap.webidl',
|
||||
'DOMTokenList.webidl',
|
||||
|
||||
@@ -183,21 +183,21 @@ gfxPlatformMac::MakePlatformFont(const nsAString& aFontName,
|
||||
|
||||
// Automates a whole buncha boilerplate.
|
||||
// Since HTTPS is becoming more common, check that first.
|
||||
#define HTTP_OR_HTTPS_SUBDIR(x) \
|
||||
#define HTTP_OR_HTTPS_SUBDIR(x, y) \
|
||||
{ \
|
||||
NS_NAMED_LITERAL_CSTRING(https_, "https://" x); \
|
||||
spec.Left(loc, https_.Length()); \
|
||||
if (loc.Equals(https_)) { \
|
||||
if (hostname.Equals(x)) { \
|
||||
NS_NAMED_LITERAL_CSTRING(https_, "https://" x y); \
|
||||
if (StringBeginsWith(spec, https_)) { \
|
||||
failed = true; \
|
||||
goto halt_font; \
|
||||
} else { \
|
||||
NS_NAMED_LITERAL_CSTRING(http_, "http://" x); \
|
||||
spec.Left(loc, http_.Length()); \
|
||||
if (loc.Equals(http_)) { \
|
||||
NS_NAMED_LITERAL_CSTRING(http_, "http://" x y); \
|
||||
if (StringBeginsWith(spec, http_)) { \
|
||||
failed = true; \
|
||||
goto halt_font; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
// TenFourFox issue 477: deal with changing infix version URLs, such as latimes.com
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "nsBidiUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
static const uint32_t kMinRTLChar = 0x0590;
|
||||
} // namespace mozilla;
|
||||
|
||||
#define ARABIC_TO_HINDI_DIGIT_INCREMENT (START_HINDI_DIGITS - START_ARABIC_DIGITS)
|
||||
#define PERSIAN_TO_HINDI_DIGIT_INCREMENT (START_HINDI_DIGITS - START_FARSI_DIGITS)
|
||||
#define ARABIC_TO_PERSIAN_DIGIT_INCREMENT (START_FARSI_DIGITS - START_ARABIC_DIGITS)
|
||||
@@ -82,16 +86,18 @@ nsresult HandleNumbers(char16_t* aBuffer, uint32_t aSize, uint32_t aNumFlag)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool HasRTLChars(const nsAString& aString)
|
||||
bool HasRTLChars(const char16_t* aText, uint32_t aLength)
|
||||
{
|
||||
// This is used to determine whether to enable bidi if a string has
|
||||
// right-to-left characters. To simplify things, anything that could be a
|
||||
// surrogate or RTL presentation form is covered just by testing >= 0xD800).
|
||||
// It's fine to enable bidi in rare cases where it actually isn't needed.
|
||||
int32_t length = aString.Length();
|
||||
for (int32_t i = 0; i < length; i++) {
|
||||
char16_t ch = aString.CharAt(i);
|
||||
if (ch >= 0xD800 || IS_IN_BMP_RTL_BLOCK(ch)) {
|
||||
// This is used to determine whether a string has right-to-left characters
|
||||
// that mean it will require bidi processing.
|
||||
const char16_t* cp = aText;
|
||||
const char16_t* end = cp + aLength;
|
||||
while (cp < end) {
|
||||
char16_t ch = *cp++;
|
||||
if (ch < mozilla::kMinRTLChar) {
|
||||
continue;
|
||||
}
|
||||
if (UTF16_CODE_UNIT_IS_BIDI(ch) || IsBidiControlRTL(ch)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,10 +110,19 @@ typedef enum nsCharType nsCharType;
|
||||
* Return false, otherwise
|
||||
*/
|
||||
#define LRM_CHAR 0x200e
|
||||
#define RLM_CHAR 0x200f
|
||||
|
||||
#define LRE_CHAR 0x202a
|
||||
#define RLE_CHAR 0x202b
|
||||
#define PDF_CHAR 0x202c
|
||||
#define LRO_CHAR 0x202d
|
||||
#define RLO_CHAR 0x202e
|
||||
|
||||
#define LRI_CHAR 0x2066
|
||||
#define RLI_CHAR 0x2067
|
||||
#define FSI_CHAR 0x2068
|
||||
#define PDI_CHAR 0x2069
|
||||
|
||||
#define ALM_CHAR 0x061C
|
||||
inline bool IsBidiControl(uint32_t aChar) {
|
||||
return ((LRE_CHAR <= aChar && aChar <= RLO_CHAR) ||
|
||||
@@ -123,10 +132,32 @@ typedef enum nsCharType nsCharType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give an nsString.
|
||||
* Give a UTF-16 codepoint (changed for TenFourFox; we don't use this for
|
||||
* UTF-32 characters, so the conversion is unnecessary).
|
||||
* Return true if the codepoint is a Bidi control character that may result
|
||||
* in RTL directionality and therefore needs to trigger bidi resolution;
|
||||
* return false otherwise.
|
||||
*/
|
||||
inline bool IsBidiControlRTL(char16_t aChar) {
|
||||
return aChar == RLM_CHAR ||
|
||||
aChar == RLE_CHAR ||
|
||||
aChar == RLO_CHAR ||
|
||||
aChar == RLI_CHAR ||
|
||||
aChar == ALM_CHAR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give a 16-bit (UTF-16) text buffer and length
|
||||
* @return true if the string contains right-to-left characters
|
||||
*/
|
||||
bool HasRTLChars(const nsAString& aString);
|
||||
bool HasRTLChars(const char16_t* aText, uint32_t aLength);
|
||||
|
||||
/**
|
||||
* Convenience function to call the above on an nsAString.
|
||||
*/
|
||||
inline bool HasRTLChars(const nsAString& aString) {
|
||||
return HasRTLChars(aString.BeginReading(), aString.Length());
|
||||
}
|
||||
|
||||
// These values are shared with Preferences dialog
|
||||
// ------------------
|
||||
@@ -248,6 +279,17 @@ typedef enum nsCharType nsCharType;
|
||||
((0xfe70 <= (c)) && ((c) <= 0xfefc)))
|
||||
#define IS_IN_SMP_RTL_BLOCK(c) (((0x10800 <= (c)) && ((c) <= 0x10fff)) || \
|
||||
((0x1e800 <= (c)) && ((c) <= 0x1eFFF)))
|
||||
// Due to the supplementary-plane RTL blocks being identifiable from the
|
||||
// high surrogate without examining the low surrogate, it is correct to
|
||||
// use this by-code-unit check on potentially astral text without doing
|
||||
// the math to decode surrogate pairs into code points. However, unpaired
|
||||
// high surrogates that are RTL high surrogates then count as RTL even
|
||||
// though, if replaced by the REPLACEMENT CHARACTER, it would not be
|
||||
// RTL.
|
||||
#define UTF16_CODE_UNIT_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \
|
||||
(IS_RTL_PRESENTATION_FORM(c)) || \
|
||||
(c) == 0xD802 || (c) == 0xD803 || \
|
||||
(c) == 0xD83A || (c) == 0xD83B)
|
||||
#define UCS2_CHAR_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \
|
||||
(IS_RTL_PRESENTATION_FORM(c)))
|
||||
#define UTF32_CHAR_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \
|
||||
|
||||
@@ -3761,7 +3761,6 @@ BytecodeEmitter::emitDestructuringDeclsWithEmitter(JSOp prologueOp, ParseNode* p
|
||||
continue;
|
||||
ParseNode* target = element;
|
||||
if (element->isKind(PNK_SPREAD)) {
|
||||
MOZ_ASSERT(element->pn_kid->isKind(PNK_NAME));
|
||||
target = element->pn_kid;
|
||||
}
|
||||
if (target->isKind(PNK_ASSIGN))
|
||||
|
||||
@@ -4276,11 +4276,6 @@ Parser<FullParseHandler>::checkDestructuringArray(BindData<FullParseHandler>* da
|
||||
return false;
|
||||
}
|
||||
target = element->pn_kid;
|
||||
|
||||
if (handler.isUnparenthesizedDestructuringPattern(target)) {
|
||||
report(ParseError, false, target, JSMSG_BAD_DESTRUCT_TARGET);
|
||||
return false;
|
||||
}
|
||||
} else if (handler.isUnparenthesizedAssignment(element)) {
|
||||
target = element->pn_left;
|
||||
} else {
|
||||
|
||||
@@ -49,6 +49,23 @@ assertIterable([5,5,4,4],
|
||||
it => { var [,,...rest] = it; return rest; },
|
||||
[3,4]);
|
||||
|
||||
// the iterator should be exhausted before any error is thrown
|
||||
if(0) {
|
||||
// XXX: this doesn't throw right now. just test syntax below.
|
||||
// plan to reenable this for issue 485
|
||||
assertIterable([5,5,4,4],
|
||||
it => {
|
||||
assertThrowsInstanceOf(function () {
|
||||
"use strict";
|
||||
[...{0: "".x}] = it;
|
||||
}, TypeError);
|
||||
return [];
|
||||
},
|
||||
[]);
|
||||
} else {
|
||||
assertIterable([5,5,4,4], it => { [...{0: "".x}] = it; return []; }, []);
|
||||
}
|
||||
|
||||
var arraycalls = 0;
|
||||
var ArrayIterator = Array.prototype[Symbol.iterator];
|
||||
Array.prototype[Symbol.iterator] = function () {
|
||||
@@ -58,7 +75,11 @@ Array.prototype[Symbol.iterator] = function () {
|
||||
// [...rest] should not call Array#@@iterator for the LHS
|
||||
var [...rest] = iterable;
|
||||
assertEq(arraycalls, 0, 'calls to Array#@@iterator');
|
||||
|
||||
// [...[...rest]] should do so, since it creates an implicit array for the
|
||||
// first rest pattern, then destructures that again using @@iterator() for the
|
||||
// second rest pattern.
|
||||
var [...[...rest]] = iterable;
|
||||
assertEq(arraycalls, 1, 'calls to Array#@@iterator');
|
||||
|
||||
// loop `fn` a few times, to get it JIT-compiled
|
||||
function loop(fn) {
|
||||
@@ -67,7 +88,7 @@ function loop(fn) {
|
||||
}
|
||||
|
||||
loop(() => { doneafter = 4; var [a] = iterable; return a; });
|
||||
loop(() => { doneafter = 4; var [a,b,...rest] = iterable; return rest; });
|
||||
loop(() => { doneafter = 4; var [a,b,...[...rest]] = iterable; return rest; });
|
||||
|
||||
|
||||
// destructuring assignment should always use iterators and not optimize
|
||||
|
||||
@@ -4,8 +4,6 @@ load(libdir + 'eqArrayHelper.js');
|
||||
|
||||
assertThrowsInstanceOf(() => new Function('[...a, ,] = []'), SyntaxError, 'trailing elision');
|
||||
assertThrowsInstanceOf(() => new Function('[a, ...b, c] = []'), SyntaxError, 'trailing param');
|
||||
assertThrowsInstanceOf(() => new Function('[...[a]] = []'), SyntaxError, 'nested arraypattern');
|
||||
assertThrowsInstanceOf(() => new Function('[...{a}] = []'), SyntaxError, 'nested objectpattern');
|
||||
assertThrowsInstanceOf(() => new Function('[...a=b] = []'), SyntaxError, 'assignment expression');
|
||||
assertThrowsInstanceOf(() => new Function('[...a()] = []'), SyntaxError, 'call expression');
|
||||
assertThrowsInstanceOf(() => new Function('[...(a,b)] = []'), SyntaxError, 'comma expression');
|
||||
@@ -22,6 +20,14 @@ assertThrowsInstanceOf(() =>
|
||||
assertThrowsInstanceOf(() => new Function('[...b,] = []'), SyntaxError)
|
||||
, Error);
|
||||
|
||||
assertThrowsInstanceOf(() => {
|
||||
try {
|
||||
eval('let [...[...x]] = (() => { throw "foo"; } )();');
|
||||
} catch(e) {
|
||||
assertEq(e, "foo");
|
||||
}
|
||||
x;
|
||||
}, ReferenceError);
|
||||
|
||||
var inputArray = [1, 2, 3];
|
||||
var inputDeep = [1, inputArray];
|
||||
@@ -45,6 +51,11 @@ function testAll(fn) {
|
||||
assertEqArray(fn('[, ...(o.prop)]', inputArray, 'o.prop'), expected);
|
||||
o.prop = null;
|
||||
assertEqArray(fn('[, ...(o.call().prop)]', inputArray, 'o.prop'), expected);
|
||||
|
||||
o.prop = null;
|
||||
assertEqArray(fn('[, ...[...(o.prop)]]', inputArray, 'o.prop'), expected);
|
||||
o.prop = null;
|
||||
assertEqArray(fn('[, ...[...(o.call().prop)]]', inputArray, 'o.prop'), expected);
|
||||
}
|
||||
function testDeclaration(fn) {
|
||||
testStr(fn);
|
||||
@@ -53,10 +64,24 @@ function testDeclaration(fn) {
|
||||
assertEqArray(fn('[, ...rest]', inputGenerator()), expected);
|
||||
assertEqArray(fn('[, [, ...rest]]', inputDeep), expected);
|
||||
assertEqArray(fn('{a: [, ...rest]}', inputObject), expected);
|
||||
|
||||
assertEqArray(fn('[, ...[...rest]]', inputArray), expected);
|
||||
assertEqArray(fn('[, ...[...rest]]', inputGenerator()), expected);
|
||||
assertEqArray(fn('[, [, ...[...rest]]]', inputDeep), expected);
|
||||
assertEqArray(fn('{a: [, ...[...rest]]}', inputObject), expected);
|
||||
|
||||
assertEqArray(fn('[, ...{0: a, 1: b}]', inputArray, '[a, b]'), expected);
|
||||
assertEqArray(fn('[, ...{0: a, 1: b}]', inputGenerator(), '[a, b]'), expected);
|
||||
assertEqArray(fn('[, [, ...{0: a, 1: b}]]', inputDeep, '[a, b]'), expected);
|
||||
assertEqArray(fn('{a: [, ...{0: a, 1: b}]}', inputObject, '[a, b]'), expected);
|
||||
}
|
||||
|
||||
function testStr(fn) {
|
||||
assertEqArray(fn('[, ...rest]', inputStr), expectedStr);
|
||||
|
||||
assertEqArray(fn('[, ...[...rest]]', inputStr), expectedStr);
|
||||
|
||||
assertEqArray(fn('[, ...{0: a, 1: b}]', inputStr, '[a, b]'), expectedStr);
|
||||
}
|
||||
|
||||
function testForIn(pattern, input, binding) {
|
||||
@@ -88,8 +113,9 @@ testAll(testGlobal);
|
||||
|
||||
function testClosure(pattern, input, binding) {
|
||||
binding = binding || 'rest';
|
||||
const decl = binding.replace('[', '').replace(']', '');
|
||||
return new Function('input',
|
||||
'var ' + binding + '; (function () {' +
|
||||
'var ' + decl + '; (function () {' +
|
||||
'(' + pattern + ' = input);' +
|
||||
'})();' +
|
||||
'return ' + binding
|
||||
|
||||
@@ -305,7 +305,11 @@ AtomicOperations::isLockfree(int32_t size)
|
||||
|| defined(__ppc__) || defined(__PPC__)
|
||||
# include "jit/none/AtomicOperations-ppc.h"
|
||||
#elif defined(JS_CODEGEN_NONE)
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
# include "jit/x86-shared/AtomicOperations-x86-shared.h"
|
||||
#else
|
||||
# include "jit/none/AtomicOperations-none.h"
|
||||
#endif
|
||||
#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
|
||||
# include "jit/x86-shared/AtomicOperations-x86-shared.h"
|
||||
#else
|
||||
|
||||
@@ -110,6 +110,7 @@ struct BidiParagraphData {
|
||||
nsTArray<nsLineBox*> mLinePerFrame;
|
||||
nsDataHashtable<nsISupportsHashKey, int32_t> mContentToFrameIndex;
|
||||
bool mIsVisual;
|
||||
bool mRequiresBidi;
|
||||
bool mReset;
|
||||
nsBidiLevel mParaLevel;
|
||||
nsIContent* mPrevContent;
|
||||
@@ -121,10 +122,14 @@ struct BidiParagraphData {
|
||||
void Init(nsBlockFrame *aBlockFrame)
|
||||
{
|
||||
mBidiEngine = new nsBidi();
|
||||
mRequiresBidi = false;
|
||||
mPrevContent = nullptr;
|
||||
mParagraphDepth = 0;
|
||||
|
||||
mParaLevel = nsBidiPresUtils::BidiLevelFromStyle(aBlockFrame->StyleContext());
|
||||
if (mParaLevel > 0) {
|
||||
mRequiresBidi = true;
|
||||
}
|
||||
|
||||
mIsVisual = aBlockFrame->PresContext()->IsVisualMode();
|
||||
if (mIsVisual) {
|
||||
@@ -664,14 +669,67 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
char16_t ch = GetBidiControl(aBlockFrame->StyleContext(), kOverride);
|
||||
if (ch != 0) {
|
||||
bpd.PushBidiControl(ch);
|
||||
bpd.mRequiresBidi = true;
|
||||
} else if (!bpd.mRequiresBidi) {
|
||||
// If there are no unicode-bidi properties and no RTL characters in the
|
||||
// block's content, then it is pure LTR and we can skip the rest of bidi
|
||||
// resolution.
|
||||
nsIContent* currContent = nullptr;
|
||||
for (nsBlockFrame* block = aBlockFrame; block;
|
||||
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
|
||||
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||
if (/* !bpd.mRequiresBidi && */
|
||||
ChildListMayRequireBidi(block->PrincipalChildList().FirstChild(),
|
||||
&currContent)) {
|
||||
bpd.mRequiresBidi = true;
|
||||
|
||||
// Optimization for TenFourFox issue 482:
|
||||
// It's safe to break here if mRequiresBidi is true because we'll
|
||||
// pull the state bits off in the loop below (if we didn't, we would
|
||||
// essentially cause bug 1362423). This also allows us to reduce
|
||||
// checking mRequiresBidi all the time.
|
||||
break;
|
||||
}
|
||||
#if(0)
|
||||
// XXX: Unnecessary work given that the below isn't executed.
|
||||
// If we need bidi support for overflow, we need to enable this too.
|
||||
/* if (!bpd.mRequiresBidi) { */
|
||||
nsBlockFrame::FrameLines* overflowLines = block->GetOverflowLines();
|
||||
if (overflowLines) { // XXX: see below
|
||||
if (ChildListMayRequireBidi(overflowLines->mFrames.FirstChild(),
|
||||
&currContent)) {
|
||||
bpd.mRequiresBidi = true;
|
||||
break; // as above
|
||||
}
|
||||
}
|
||||
/* } */
|
||||
#endif
|
||||
}
|
||||
// Moving the below here so that we can keep partial work causes RTL
|
||||
// to get munged. It seems we really do have to iterate through all the
|
||||
// frames again from the beginning if any are RTL.
|
||||
if (!bpd.mRequiresBidi) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
for (nsBlockFrame* block = aBlockFrame; block;
|
||||
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
|
||||
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||
nsBlockInFlowLineIterator lineIter(block, block->begin_lines());
|
||||
bpd.ResetForNewBlock();
|
||||
TraverseFrames(aBlockFrame, &lineIter, block->GetFirstPrincipalChild(), &bpd);
|
||||
// XXX what about overflow lines?
|
||||
#if(0)
|
||||
nsBlockFrame::FrameLines* overflowLines = block->GetOverflowLines();
|
||||
// XXX: Not sure if this is going to break anything.
|
||||
// It's safe to do above (from bug 1358275) because that doesn't actually
|
||||
// bidi-process the overflow lines; it just checks if we need to.
|
||||
if (overflowLines) {
|
||||
nsBlockInFlowLineIterator it(block, overflowLines->mLines.begin(), true);
|
||||
bpd.ResetForNewBlock();
|
||||
TraverseFrames(aBlockFrame, &it, overflowLines->mFrames.FirstChild(), &bpd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ch != 0) {
|
||||
@@ -1241,6 +1299,56 @@ nsBidiPresUtils::TraverseFrames(nsBlockFrame* aBlockFrame,
|
||||
MOZ_ASSERT(initialLineContainer == aLineIter->GetContainer());
|
||||
}
|
||||
|
||||
bool
|
||||
nsBidiPresUtils::ChildListMayRequireBidi(nsIFrame* aFirstChild,
|
||||
nsIContent** aCurrContent)
|
||||
{
|
||||
MOZ_ASSERT(!aFirstChild || !aFirstChild->GetPrevSibling(),
|
||||
"Expecting to traverse from the start of a child list");
|
||||
|
||||
for (nsIFrame* childFrame = aFirstChild; childFrame;
|
||||
childFrame = childFrame->GetNextSibling()) {
|
||||
|
||||
nsIFrame* frame = childFrame;
|
||||
|
||||
// If the real frame for a placeholder is a first-letter frame, we need to
|
||||
// consider its contents for potential Bidi resolution.
|
||||
if (childFrame->GetType() == nsGkAtoms::placeholderFrame) {
|
||||
nsIFrame* realFrame =
|
||||
nsPlaceholderFrame::GetRealFrameForPlaceholder(childFrame);
|
||||
if (realFrame->GetType() == nsGkAtoms::letterFrame) {
|
||||
frame = realFrame;
|
||||
}
|
||||
}
|
||||
|
||||
// If unicode-bidi properties are present, we should do bidi resolution.
|
||||
nsStyleContext* sc = frame->StyleContext();
|
||||
if (GetBidiControl(sc, kOverrideOrEmbed)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsBidiLeaf(frame)) {
|
||||
if (frame->GetType() == nsGkAtoms::textFrame) {
|
||||
// Check whether the text frame has any RTL characters; if so, bidi
|
||||
// resolution will be needed.
|
||||
nsIContent* content = frame->GetContent();
|
||||
if (content != *aCurrContent) {
|
||||
*aCurrContent = content;
|
||||
const nsTextFragment* txt = content->GetText();
|
||||
if (txt->Is2b() && HasRTLChars(txt->Get2b(), txt->GetLength())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ChildListMayRequireBidi(frame->PrincipalChildList().FirstChild(),
|
||||
aCurrContent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame,
|
||||
BidiParagraphData* aBpd)
|
||||
|
||||
@@ -399,6 +399,23 @@ private:
|
||||
nsIFrame* aCurrentFrame,
|
||||
BidiParagraphData* aBpd);
|
||||
|
||||
/**
|
||||
* Perform a recursive "pre-traversal" of the child frames of a block or
|
||||
* inline container frame, to determine whether full bidi resolution is
|
||||
* actually needed.
|
||||
* This explores the same frames as TraverseFrames (above), but is less
|
||||
* expensive and may allow us to avoid performing the full TraverseFrames
|
||||
* operation.
|
||||
* @param aFirstChild frame to start traversal from
|
||||
* @param[in/out] aCurrContent the content node that we've most recently
|
||||
* scanned for RTL characters (so that when descendant frames refer
|
||||
* to the same content, we can avoid repeatedly scanning it).
|
||||
* @return true if it finds that bidi is (or may be) required,
|
||||
* false if no potentially-bidi content is present.
|
||||
*/
|
||||
static bool ChildListMayRequireBidi(nsIFrame* aFirstChild,
|
||||
nsIContent** aCurrContent);
|
||||
|
||||
/**
|
||||
* Position ruby content frames (ruby base/text frame).
|
||||
* Called from RepositionRubyFrame.
|
||||
|
||||
@@ -647,7 +647,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
mAsyncPanZoomEnabled(nsLayoutUtils::AsyncPanZoomEnabled(aReferenceFrame))
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
||||
PL_InitArenaPool(&mPool, "displayListArena", 1024,
|
||||
PL_InitArenaPool(&mPool, "displayListArena", 4096,
|
||||
std::max(NS_ALIGNMENT_OF(void*),NS_ALIGNMENT_OF(double))-1);
|
||||
|
||||
nsPresContext* pc = aReferenceFrame->PresContext();
|
||||
|
||||
@@ -935,7 +935,7 @@ nsRefreshDriver::GetThrottledTimerInterval()
|
||||
if (rate <= 0) {
|
||||
rate = DEFAULT_THROTTLED_FRAME_RATE;
|
||||
}
|
||||
return 3000.0 / rate;
|
||||
return 10000.0 / rate;
|
||||
}
|
||||
|
||||
/* static */ mozilla::TimeDuration
|
||||
|
||||
@@ -1176,10 +1176,13 @@ GetStatesForPseudoClass(const nsAString& aStatePseudo)
|
||||
|
||||
nsCOMPtr<nsIAtom> atom = do_GetAtom(aStatePseudo);
|
||||
|
||||
// Ignore :moz-any-link so we don't give the element simultaneous
|
||||
// Ignore :any-link so we don't give the element simultaneous
|
||||
// visited and unvisited style state
|
||||
if (nsCSSPseudoClasses::GetPseudoType(atom) ==
|
||||
nsCSSPseudoClasses::ePseudoClass_mozAnyLink) {
|
||||
nsCSSPseudoClasses::ePseudoClass_mozAnyLink ||
|
||||
// XXX: this could be cleaned up. do it once it's building
|
||||
nsCSSPseudoClasses::GetPseudoType(atom) ==
|
||||
nsCSSPseudoClasses::ePseudoClass_anyLink) {
|
||||
return EventStates();
|
||||
}
|
||||
// Our array above is long enough that indexing into it with
|
||||
|
||||
@@ -991,7 +991,6 @@ const KTableEntry nsCSSProps::kBoxShadowTypeKTable[] = {
|
||||
const KTableEntry nsCSSProps::kBoxSizingKTable[] = {
|
||||
{ eCSSKeyword_content_box, uint8_t(StyleBoxSizing::Content) },
|
||||
{ eCSSKeyword_border_box, uint8_t(StyleBoxSizing::Border) },
|
||||
{ eCSSKeyword_padding_box, uint8_t(StyleBoxSizing::Padding) },
|
||||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
|
||||
@@ -142,6 +142,8 @@ CSS_STATE_PSEUDO_CLASS(link, ":link", 0, "", NS_EVENT_STATE_UNVISITED)
|
||||
// what matches :link or :visited
|
||||
CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link", 0, "",
|
||||
NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)
|
||||
CSS_STATE_PSEUDO_CLASS(anyLink, ":any-link", 0, "",
|
||||
NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)
|
||||
CSS_STATE_PSEUDO_CLASS(visited, ":visited", 0, "", NS_EVENT_STATE_VISITED)
|
||||
|
||||
CSS_STATE_PSEUDO_CLASS(active, ":active", 0, "", NS_EVENT_STATE_ACTIVE)
|
||||
|
||||
@@ -1420,7 +1420,7 @@ pref("network.http.bypass-cachelock-threshold", 250);
|
||||
|
||||
// Try and use SPDY when using SSL
|
||||
pref("network.http.spdy.enabled", true);
|
||||
pref("network.http.spdy.enabled.v3-1", true);
|
||||
pref("network.http.spdy.enabled.v3-1", false);
|
||||
pref("network.http.spdy.enabled.http2", true);
|
||||
pref("network.http.spdy.enabled.deps", true);
|
||||
pref("network.http.spdy.enforce-tls-profile", true);
|
||||
@@ -5145,4 +5145,4 @@ pref("toolkit.pageThumbs.minWidth", 0);
|
||||
pref("toolkit.pageThumbs.minHeight", 0);
|
||||
|
||||
pref("tenfourfox.adblock.enabled", false);
|
||||
pref("tenfourfox.adblock.logging.enabled", true);
|
||||
pref("tenfourfox.adblock.logging.enabled", false);
|
||||
|
||||
@@ -20,18 +20,19 @@ pref("security.ssl.enable_alpn", true);
|
||||
pref("security.ssl3.ecdhe_rsa_aes_128_gcm_sha256", true);
|
||||
pref("security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256", true);
|
||||
pref("security.ssl3.ecdhe_rsa_aes_128_sha", true);
|
||||
pref("security.ssl3.ecdhe_rsa_aes_128_sha256", true);
|
||||
pref("security.ssl3.ecdhe_ecdsa_aes_128_sha", true);
|
||||
pref("security.ssl3.ecdhe_rsa_aes_256_sha", true);
|
||||
pref("security.ssl3.ecdhe_ecdsa_aes_256_sha", true);
|
||||
pref("security.ssl3.dhe_rsa_aes_128_sha", true);
|
||||
pref("security.ssl3.dhe_rsa_aes_256_sha", true);
|
||||
pref("security.ssl3.ecdhe_rsa_rc4_128_sha", true);
|
||||
pref("security.ssl3.ecdhe_ecdsa_rc4_128_sha", true);
|
||||
pref("security.ssl3.ecdhe_rsa_rc4_128_sha", false);
|
||||
pref("security.ssl3.ecdhe_ecdsa_rc4_128_sha", false);
|
||||
pref("security.ssl3.rsa_aes_128_sha", true);
|
||||
pref("security.ssl3.rsa_aes_256_sha", true);
|
||||
pref("security.ssl3.rsa_des_ede3_sha", true);
|
||||
pref("security.ssl3.rsa_rc4_128_sha", true);
|
||||
pref("security.ssl3.rsa_rc4_128_md5", true);
|
||||
pref("security.ssl3.rsa_rc4_128_sha", false);
|
||||
pref("security.ssl3.rsa_rc4_128_md5", false);
|
||||
|
||||
pref("security.default_personal_cert", "Ask Every Time");
|
||||
pref("security.remember_cert_checkbox_default_setting", true);
|
||||
|
||||
@@ -1184,4 +1184,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
||||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1528837162062000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1530217066204000);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -59,6 +59,13 @@ interface nsIDatePicker : nsISupports
|
||||
*/
|
||||
attribute AString maxDate;
|
||||
|
||||
/**
|
||||
* The selected date.
|
||||
*
|
||||
* @return Returns the date currently selected.
|
||||
*/
|
||||
readonly attribute AString selectedDate;
|
||||
|
||||
/**
|
||||
* Show date dialog. The dialog is displayed modally.
|
||||
*
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
@@ -71,7 +72,7 @@ PLDHashTable::HashStringKey(PLDHashTable* aTable, const void* aKey)
|
||||
/* static */ PLDHashNumber
|
||||
PLDHashTable::HashVoidPtrKeyStub(PLDHashTable* aTable, const void* aKey)
|
||||
{
|
||||
return (PLDHashNumber)(ptrdiff_t)aKey >> 2;
|
||||
return mozilla::HashGeneric(aKey);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
@@ -256,15 +257,38 @@ PLDHashTable::Hash1(PLDHashNumber aHash0)
|
||||
return aHash0 >> mHashShift;
|
||||
}
|
||||
|
||||
// Double hashing needs the second hash code to be relatively prime to table
|
||||
// size, so we simply make hash2 odd.
|
||||
void
|
||||
PLDHashTable::Hash2(PLDHashNumber aHash,
|
||||
PLDHashTable::Hash2(PLDHashNumber aHash0,
|
||||
uint32_t& aHash2Out, uint32_t& aSizeMaskOut)
|
||||
{
|
||||
uint32_t sizeLog2 = kHashBits - mHashShift;
|
||||
aHash2Out = ((aHash << sizeLog2) >> mHashShift) | 1;
|
||||
aSizeMaskOut = (PLDHashNumber(1) << sizeLog2) - 1;
|
||||
uint32_t sizeMask = (PLDHashNumber(1) << sizeLog2) - 1;
|
||||
aSizeMaskOut = sizeMask;
|
||||
|
||||
// The incoming aHash0 always has the low bit unset (since we leave it
|
||||
// free for the collision flag), and should have reasonably random
|
||||
// data in the other 31 bits. We used the high bits of aHash0 for
|
||||
// Hash1, so we use the low bits here. If the table size is large,
|
||||
// the bits we use may overlap, but that's still more random than
|
||||
// filling with 0s.
|
||||
//
|
||||
// Since the result of Hash2 controls how far we jump around the table
|
||||
// to build a chain after starting at a location determined by Hash1,
|
||||
// we'd like to keep it small, to improve cache behavior.
|
||||
// Keep the jumps from the second hash small, to improve cache behavior.
|
||||
const uint32_t kHash2MaskMaxBits = 6;
|
||||
uint32_t hash2Mask;
|
||||
if (sizeLog2 >= kHash2MaskMaxBits) {
|
||||
hash2Mask = (PLDHashNumber(1) << kHash2MaskMaxBits) - 1;
|
||||
} else {
|
||||
hash2Mask = sizeMask;
|
||||
}
|
||||
// Double hashing needs the second hash code to be relatively prime to table
|
||||
// size, so we simply make hash2 odd.
|
||||
//
|
||||
// This also conveniently covers up the fact that we have the low bit
|
||||
// unset since aHash0 has the low bit unset.
|
||||
aHash2Out = (aHash0 & hash2Mask) | 1;
|
||||
}
|
||||
|
||||
// Reserve mKeyHash 0 for free entries and 1 for removed-entry sentinels. Note
|
||||
|
||||
@@ -1026,6 +1026,17 @@ CountCharInReadable(const nsACString& aStr, char aChar)
|
||||
return count;
|
||||
}
|
||||
|
||||
bool
|
||||
StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring)
|
||||
{
|
||||
nsAString::size_type src_len = aSource.Length(),
|
||||
sub_len = aSubstring.Length();
|
||||
if (sub_len > src_len) {
|
||||
return false;
|
||||
}
|
||||
return Substring(aSource, 0, sub_len).Equals(aSubstring);
|
||||
}
|
||||
|
||||
bool
|
||||
StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||
const nsStringComparator& aComparator)
|
||||
@@ -1038,6 +1049,17 @@ StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||
return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
|
||||
}
|
||||
|
||||
bool
|
||||
StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring)
|
||||
{
|
||||
nsACString::size_type src_len = aSource.Length(),
|
||||
sub_len = aSubstring.Length();
|
||||
if (sub_len > src_len) {
|
||||
return false;
|
||||
}
|
||||
return Substring(aSource, 0, sub_len).Equals(aSubstring);
|
||||
}
|
||||
|
||||
bool
|
||||
StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||
const nsCStringComparator& aComparator)
|
||||
@@ -1050,6 +1072,17 @@ StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||
return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
|
||||
}
|
||||
|
||||
bool
|
||||
StringEndsWith(const nsAString& aSource, const nsAString& aSubstring)
|
||||
{
|
||||
nsAString::size_type src_len = aSource.Length(),
|
||||
sub_len = aSubstring.Length();
|
||||
if (sub_len > src_len) {
|
||||
return false;
|
||||
}
|
||||
return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring);
|
||||
}
|
||||
|
||||
bool
|
||||
StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||
const nsStringComparator& aComparator)
|
||||
@@ -1063,6 +1096,17 @@ StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||
aComparator);
|
||||
}
|
||||
|
||||
bool
|
||||
StringEndsWith(const nsACString& aSource, const nsACString& aSubstring)
|
||||
{
|
||||
nsACString::size_type src_len = aSource.Length(),
|
||||
sub_len = aSubstring.Length();
|
||||
if (sub_len > src_len) {
|
||||
return false;
|
||||
}
|
||||
return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring);
|
||||
}
|
||||
|
||||
bool
|
||||
StringEndsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||
const nsCStringComparator& aComparator)
|
||||
|
||||
@@ -386,18 +386,18 @@ uint32_t CountCharInReadable(const nsAString& aStr,
|
||||
uint32_t CountCharInReadable(const nsACString& aStr,
|
||||
char aChar);
|
||||
|
||||
bool StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring);
|
||||
bool StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||
const nsStringComparator& aComparator =
|
||||
nsDefaultStringComparator());
|
||||
const nsStringComparator& aComparator);
|
||||
bool StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring);
|
||||
bool StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||
const nsCStringComparator& aComparator =
|
||||
nsDefaultCStringComparator());
|
||||
const nsCStringComparator& aComparator);
|
||||
bool StringEndsWith(const nsAString& aSource, const nsAString& aSubstring);
|
||||
bool StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||
const nsStringComparator& aComparator =
|
||||
nsDefaultStringComparator());
|
||||
const nsStringComparator& aComparator);
|
||||
bool StringEndsWith(const nsACString& aSource, const nsACString& aSubstring);
|
||||
bool StringEndsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||
const nsCStringComparator& aComparator =
|
||||
nsDefaultCStringComparator());
|
||||
const nsCStringComparator& aComparator);
|
||||
|
||||
const nsAFlatString& EmptyString();
|
||||
const nsAFlatCString& EmptyCString();
|
||||
|
||||
Reference in New Issue
Block a user