mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-09-09 04:54:33 +00:00
commit
b61caed0c3
@ -18,6 +18,9 @@
|
||||
<preference id="tenfourfox.ua.template"
|
||||
name="tenfourfox.ua.template"
|
||||
type="string"/>
|
||||
<preference id="tenfourfox.adblock.enabled"
|
||||
name="tenfourfox.adblock.enabled"
|
||||
type="bool"/>
|
||||
|
||||
</preferences>
|
||||
|
||||
@ -69,3 +72,12 @@
|
||||
</menulist>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<groupbox id="adBlockGroup" data-category="paneTenFourFox" hidden="true">
|
||||
<caption><label>&TFFadBlock.title;</label></caption>
|
||||
<vbox>
|
||||
<checkbox id="tenFourFoxAdBlockCheckbox"
|
||||
label="&TFFadBlock.prompt;"
|
||||
preference="tenfourfox.adblock.enabled"/>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
|
@ -1 +1 @@
|
||||
45.15.0
|
||||
45.16.0
|
||||
|
@ -1 +1 @@
|
||||
Feature Parity Release 6
|
||||
Feature Parity Release 7
|
||||
|
@ -705,7 +705,17 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
|
||||
// blocking zdbb.net seems to be problematic
|
||||
// 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.") ||
|
||||
|
||||
// other obnoxious things
|
||||
BLOK("c.amazon-adsystem.com") ||
|
||||
|
||||
BLOK("google-analytics.com") ||
|
||||
@ -793,6 +803,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
BLOK("cdn.segment.com") ||
|
||||
|
||||
BLOK("cdn-gl.imrworldwide.com") ||
|
||||
BLOK("secure-us.imrworldwide.com") ||
|
||||
BLOK("secure-dcr.imrworldwide.com") ||
|
||||
|
||||
BLOK("labs-cdn.revcontent.com") ||
|
||||
@ -800,6 +811,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") ||
|
||||
@ -848,6 +860,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") ||
|
||||
@ -902,6 +915,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") ||
|
||||
@ -917,6 +931,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
BLOK("stats.cloudwp.io") ||
|
||||
|
||||
BLOK("ap.lijit.com") ||
|
||||
BLOK("ce.lijit.com") ||
|
||||
|
||||
BLOK("tlx.3lift.com") ||
|
||||
|
||||
@ -982,14 +997,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") ||
|
||||
|
||||
@ -997,6 +1010,43 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
|
||||
BLOK("s.spoutable.com") ||
|
||||
BLOK("cdn.spoutable.com") ||
|
||||
|
||||
BLOK("ads.pubmatic.com") ||
|
||||
|
||||
BLOK("track.netshelter.net") ||
|
||||
|
||||
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") ||
|
||||
0) {
|
||||
#undef BLOK
|
||||
// Yup.
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
45.15.0
|
||||
45.16.0
|
||||
|
@ -6630,9 +6630,17 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh, nsI
|
||||
*/
|
||||
loadInfo->SetReferrer(mCurrentURI);
|
||||
|
||||
/* Don't ever "guess" on which owner to use to avoid picking
|
||||
* the current owner.
|
||||
*/
|
||||
// Set the triggering pricipal to aPrincipal if available, or current
|
||||
// document's principal otherwise.
|
||||
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
|
||||
if (!principal) {
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
if (MOZ_UNLIKELY(!doc)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
principal = doc->NodePrincipal();
|
||||
}
|
||||
loadInfo->SetOwner(principal); // equivalent for SetTriggeringPrincipal
|
||||
loadInfo->SetOwnerIsExplicit(true);
|
||||
|
||||
/* Check if this META refresh causes a redirection
|
||||
@ -6660,13 +6668,6 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh, nsI
|
||||
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
|
||||
}
|
||||
|
||||
// If the principal is null, the refresh will have a triggeringPrincipal
|
||||
// derived from the referrer URI, or will be set to the system principal
|
||||
// if there is no refererrer. See LoadURI()
|
||||
if (aPrincipal) {
|
||||
loadInfo->SetOwner(aPrincipal); // as called prior to bug 1286472
|
||||
}
|
||||
|
||||
/*
|
||||
* LoadURI(...) will cancel all refresh timers... This causes the
|
||||
* Timer and its refreshData instance to be released...
|
||||
|
@ -19,9 +19,8 @@ interface nsIRefreshURI : nsISupports {
|
||||
*
|
||||
* @param aUri The uri to refresh.
|
||||
* @param aPrincipal The triggeringPrincipal for the refresh load
|
||||
* May be null, in which case a principal will be built based on the
|
||||
* referrer URI of the previous docshell load, or will use the system
|
||||
* principal when there is no referrer.
|
||||
* May be null, in which case the principal of current document will be
|
||||
* applied.
|
||||
* @param aMillis The number of milliseconds to wait.
|
||||
* @param aRepeat Flag to indicate if the uri is to be
|
||||
* repeatedly refreshed every aMillis milliseconds.
|
||||
@ -37,9 +36,8 @@ interface nsIRefreshURI : nsISupports {
|
||||
*
|
||||
* @param aURI The URI to refresh.
|
||||
* @param aPrincipal The triggeringPrincipal for the refresh load
|
||||
* May be null, in which case a principal will be built based on the
|
||||
* referrer URI of the previous docshell load, or will use the system
|
||||
* principal when there is no referrer.
|
||||
* May be null, in which case the principal of current document will be
|
||||
* applied.
|
||||
* @param aMillis The number of milliseconds by which this refresh would
|
||||
* be delayed if it were not being forced.
|
||||
* @param aMetaRefresh Flag to indicate if this is a meta refresh.
|
||||
@ -70,9 +68,8 @@ interface nsIRefreshURI : nsISupports {
|
||||
*
|
||||
* @param aBaseURI base URI to resolve refresh uri with.
|
||||
* @param aPrincipal The triggeringPrincipal for the refresh load
|
||||
* May be null, in which case a principal will be built based on the
|
||||
* referrer URI of the previous docshell load, or will use the system
|
||||
* principal when there is no referrer.
|
||||
* May be null, in which case the principal of current document will be
|
||||
* applied.
|
||||
* @param aHeader The meta refresh header string.
|
||||
*/
|
||||
void setupRefreshURIFromHeader(in nsIURI aBaseURI,
|
||||
|
31
dom/base/DOMTokenListSupportedTokens.h
Normal file
31
dom/base/DOMTokenListSupportedTokens.h
Normal file
@ -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
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
24
dom/base/IframeSandboxKeywordList.h
Normal file
24
dom/base/IframeSandboxKeywordList.h
Normal file
@ -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)
|
@ -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*
|
||||
|
@ -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___
|
||||
|
@ -562,7 +562,7 @@ nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
|
||||
}
|
||||
|
||||
if (!aDontSerializeRoot) {
|
||||
rv = SerializeNodeEnd(node, aStr);
|
||||
rv = SerializeNodeEnd(maybeFixedNode, aStr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -150,6 +150,8 @@ 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"))
|
||||
|
@ -345,22 +345,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;
|
||||
}
|
||||
|
||||
@ -379,15 +379,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;
|
||||
}
|
||||
|
||||
@ -414,16 +415,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;
|
||||
}
|
||||
|
||||
@ -461,21 +464,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'
|
||||
},
|
||||
|
@ -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")
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -79,7 +79,7 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
|
||||
return aPlane.mWidth <= PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
aPlane.mHeight <= PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
aPlane.mWidth * aPlane.mHeight < MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
|
||||
aPlane.mStride > 0;
|
||||
aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
|
@ -460,6 +460,18 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem,
|
||||
float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS];
|
||||
domItem->ToSVGPathSegEncodedData(segAsRaw);
|
||||
|
||||
if (AnimListMirrorsBaseList()) {
|
||||
// The anim val list is in sync with the base val list - remove mirroring
|
||||
// animVal item if necessary. We do this *before* touching InternalList()
|
||||
// so the removed item can correctly store its internal value.
|
||||
DOMSVGPathSegList* animVal =
|
||||
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
|
||||
if (animVal->ItemAt(aIndex)) {
|
||||
animVal->ItemAt(aIndex)->RemovingFromList();
|
||||
animVal->ItemAt(aIndex) = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!InternalList().mData.ReplaceElementsAt(internalIndex, 1 + oldArgCount,
|
||||
segAsRaw, 1 + newArgCount,
|
||||
fallible)) {
|
||||
@ -474,8 +486,13 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem,
|
||||
|
||||
int32_t delta = newArgCount - oldArgCount;
|
||||
if (delta != 0) {
|
||||
for (uint32_t i = aIndex + 1; i < LengthNoFlush(); ++i) {
|
||||
mItems[i].mInternalDataIndex += delta;
|
||||
// Sync up the internal indexes of all ItemProxys that come after aIndex:
|
||||
UpdateListIndicesFromIndex(aIndex + 1, delta);
|
||||
if (AnimListMirrorsBaseList()) {
|
||||
// The anim val list is in sync with the base val list
|
||||
DOMSVGPathSegList* animVal =
|
||||
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
|
||||
animVal->UpdateListIndicesFromIndex(aIndex + 1, delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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',
|
||||
|
@ -176,7 +176,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsEditor)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventListener)
|
||||
|
||||
if (tmp->mEventListener) {
|
||||
nsEditorEventListener* listener =
|
||||
reinterpret_cast<nsEditorEventListener*>(tmp->mEventListener.get());
|
||||
listener->Disconnect();
|
||||
tmp->mEventListener = nullptr;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEditor)
|
||||
|
@ -430,12 +430,15 @@ static void
|
||||
CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
|
||||
const gfx::IntSize &aSize, int32_t aStride, int32_t aSkip)
|
||||
{
|
||||
int32_t height = aSize.height;
|
||||
int32_t width = aSize.width;
|
||||
|
||||
MOZ_RELEASE_ASSERT(width <= aStride);
|
||||
|
||||
if (!aSkip) {
|
||||
// Fast path: planar input.
|
||||
memcpy(aDst, aSrc, aSize.height * aStride);
|
||||
memcpy(aDst, aSrc, height * aStride);
|
||||
} else {
|
||||
int32_t height = aSize.height;
|
||||
int32_t width = aSize.width;
|
||||
for (int y = 0; y < height; ++y) {
|
||||
const uint8_t *src = aSrc;
|
||||
uint8_t *dst = aDst;
|
||||
@ -453,13 +456,11 @@ CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
|
||||
bool
|
||||
RecyclingPlanarYCbCrImage::CopyData(const Data& aData)
|
||||
{
|
||||
mData = aData;
|
||||
|
||||
// update buffer size
|
||||
// Use uint32_t throughout to match AllocateBuffer's param and mBufferSize
|
||||
const auto checkedSize =
|
||||
CheckedInt<uint32_t>(mData.mCbCrStride) * mData.mCbCrSize.height * 2 +
|
||||
CheckedInt<uint32_t>(mData.mYStride) * mData.mYSize.height;
|
||||
CheckedInt<uint32_t>(aData.mCbCrStride) * aData.mCbCrSize.height * 2 +
|
||||
CheckedInt<uint32_t>(aData.mYStride) * aData.mYSize.height;
|
||||
|
||||
if (!checkedSize.isValid())
|
||||
return false;
|
||||
@ -468,22 +469,24 @@ RecyclingPlanarYCbCrImage::CopyData(const Data& aData)
|
||||
|
||||
// get new buffer
|
||||
mBuffer = AllocateBuffer(size);
|
||||
if (!mBuffer)
|
||||
if (MOZ_UNLIKELY(!mBuffer))
|
||||
return false;
|
||||
|
||||
// update buffer size
|
||||
mBufferSize = size;
|
||||
|
||||
mData = aData;
|
||||
mData.mYChannel = mBuffer.get();
|
||||
mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
|
||||
mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
|
||||
mData.mYSkip = mData.mCbSkip = mData.mCrSkip = 0;
|
||||
|
||||
CopyPlane(mData.mYChannel, aData.mYChannel,
|
||||
mData.mYSize, mData.mYStride, mData.mYSkip);
|
||||
aData.mYSize, aData.mYStride, aData.mYSkip);
|
||||
CopyPlane(mData.mCbChannel, aData.mCbChannel,
|
||||
mData.mCbCrSize, mData.mCbCrStride, mData.mCbSkip);
|
||||
aData.mCbCrSize, aData.mCbCrStride, aData.mCbSkip);
|
||||
CopyPlane(mData.mCrChannel, aData.mCrChannel,
|
||||
mData.mCbCrSize, mData.mCbCrStride, mData.mCrSkip);
|
||||
aData.mCbCrSize, aData.mCbCrStride, aData.mCrSkip);
|
||||
|
||||
mSize = aData.mPicSize;
|
||||
return true;
|
||||
|
@ -152,7 +152,17 @@ nsBIG5ToUnicode::GetMaxLength(const char* aSrc,
|
||||
{
|
||||
// The length of the output in UTF-16 code units never exceeds the length
|
||||
// of the input in bytes.
|
||||
*aDestLength = aSrcLength + (mPendingTrail ? 1 : 0) + (mBig5Lead ? 1 : 0);
|
||||
mozilla::CheckedInt32 length = aSrcLength;
|
||||
if (mPendingTrail) {
|
||||
length += 1;
|
||||
}
|
||||
if (mBig5Lead) {
|
||||
length += 1;
|
||||
}
|
||||
if (!length.isValid()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aDestLength = length.value();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -211,12 +211,21 @@ nsUnicodeToBIG5::GetMaxLength(const char16_t* aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t* aDestLength)
|
||||
{
|
||||
*aDestLength = (aSrcLength * 2) +
|
||||
(mPendingTrail ? 1 : 0) +
|
||||
// If the lead ends up being paired, the bytes produced
|
||||
// are already included above.
|
||||
// If not, it produces a single '?'.
|
||||
(mUtf16Lead ? 1 : 0);
|
||||
mozilla::CheckedInt32 length = aSrcLength;
|
||||
length *= 2;
|
||||
if (mPendingTrail) {
|
||||
length += 1;
|
||||
}
|
||||
// If the lead ends up being paired, the bytes produced
|
||||
// are already included above.
|
||||
// If not, it produces a single '?'.
|
||||
if (mUtf16Lead) {
|
||||
length += 1;
|
||||
}
|
||||
if (!length.isValid()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aDestLength = length.value();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -1824,6 +1824,12 @@ jit::ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph)
|
||||
bool
|
||||
jit::MakeMRegExpHoistable(MIRGraph& graph)
|
||||
{
|
||||
// If we are compiling try blocks, regular expressions may be observable
|
||||
// from catch blocks (which Ion does not compile). For now just disable the
|
||||
// pass in this case.
|
||||
if (graph.hasTryBlock())
|
||||
return true;
|
||||
|
||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||
for (MDefinitionIterator iter(*block); iter; iter++) {
|
||||
if (!iter->isRegExp())
|
||||
|
@ -1124,6 +1124,10 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge
|
||||
|
||||
RootedObject self(cx, this);
|
||||
|
||||
Shape* existingShape = self->ensureShape(cx);
|
||||
if (!existingShape)
|
||||
return false;
|
||||
|
||||
if (isNative() && as<NativeObject>().inDictionaryMode()) {
|
||||
if (generateShape == GENERATE_SHAPE && !as<NativeObject>().generateOwnShape(cx))
|
||||
return false;
|
||||
@ -1137,10 +1141,6 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape* existingShape = self->ensureShape(cx);
|
||||
if (!existingShape)
|
||||
return false;
|
||||
|
||||
Shape* newShape = Shape::setObjectFlags(cx, flags, self->getTaggedProto(), existingShape);
|
||||
if (!newShape)
|
||||
return false;
|
||||
|
@ -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();
|
||||
|
@ -9345,9 +9345,13 @@ nsTextFrame::GetRenderedText(uint32_t aStartOffset,
|
||||
startOffset = aStartOffset;
|
||||
endOffset = std::min<uint32_t>(INT32_MAX, aEndOffset);
|
||||
}
|
||||
|
||||
// If startOffset and/or endOffset are inside of trimmedOffsets' range,
|
||||
// then clamp the edges of trimmedOffsets accordingly.
|
||||
int32_t origTrimmedOffsetsEnd = trimmedOffsets.GetEnd();
|
||||
trimmedOffsets.mStart = std::max<uint32_t>(trimmedOffsets.mStart,
|
||||
startOffset);
|
||||
trimmedOffsets.mLength = std::min<uint32_t>(trimmedOffsets.GetEnd(),
|
||||
trimmedOffsets.mLength = std::min<uint32_t>(origTrimmedOffsetsEnd,
|
||||
endOffset) - trimmedOffsets.mStart;
|
||||
if (trimmedOffsets.mLength <= 0) {
|
||||
offsetInRenderedString = nextOffsetInRenderedString;
|
||||
|
@ -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)
|
||||
|
@ -387,7 +387,7 @@ long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||
t[i] = book->valuelist+entry[i]*book->dim;
|
||||
}
|
||||
for(i=0,o=0;i<book->dim;i++,o+=step)
|
||||
for (j=0;j<step;j++)
|
||||
for (j=0;o+j<n && j<step;j++)
|
||||
a[o+j]+=t[j][i];
|
||||
}
|
||||
return(0);
|
||||
@ -399,41 +399,12 @@ long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||
int i,j,entry;
|
||||
float *t;
|
||||
|
||||
if(book->dim>8){
|
||||
for(i=0;i<n;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
t = book->valuelist+entry*book->dim;
|
||||
for (j=0;j<book->dim;)
|
||||
a[i++]+=t[j++];
|
||||
}
|
||||
}else{
|
||||
for(i=0;i<n;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
t = book->valuelist+entry*book->dim;
|
||||
j=0;
|
||||
switch((int)book->dim){
|
||||
case 8:
|
||||
a[i++]+=t[j++];
|
||||
case 7:
|
||||
a[i++]+=t[j++];
|
||||
case 6:
|
||||
a[i++]+=t[j++];
|
||||
case 5:
|
||||
a[i++]+=t[j++];
|
||||
case 4:
|
||||
a[i++]+=t[j++];
|
||||
case 3:
|
||||
a[i++]+=t[j++];
|
||||
case 2:
|
||||
a[i++]+=t[j++];
|
||||
case 1:
|
||||
a[i++]+=t[j++];
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i=0;i<n;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
t = book->valuelist+entry*book->dim;
|
||||
for(j=0;i<n && j<book->dim;)
|
||||
a[i++]+=t[j++];
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
@ -471,12 +442,13 @@ long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
|
||||
long i,j,entry;
|
||||
int chptr=0;
|
||||
if(book->used_entries>0){
|
||||
for(i=offset/ch;i<(offset+n)/ch;){
|
||||
int m=(offset+n)/ch;
|
||||
for(i=offset/ch;i<m;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
{
|
||||
const float *t = book->valuelist+entry*book->dim;
|
||||
for (j=0;j<book->dim;j++){
|
||||
for (j=0;i<m && j<book->dim;j++){
|
||||
a[chptr++][i]+=t[j];
|
||||
if(chptr==ch){
|
||||
chptr=0;
|
||||
|
@ -186,7 +186,7 @@ cglobal quantize_%1, 0, %2, 15, coeff, ncoeff, skip, zbin, round, quant, \
|
||||
pshuflw m7, m8, 0x1
|
||||
pmaxsw m8, m7
|
||||
pextrw r6, m8, 0
|
||||
mov [r2], r6
|
||||
mov [r2], r6w
|
||||
RET
|
||||
|
||||
; skip-block, i.e. just write all zeroes
|
||||
|
@ -1412,7 +1412,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);
|
||||
@ -5137,4 +5137,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);
|
||||
|
@ -19,6 +19,7 @@ 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);
|
||||
|
@ -1014,6 +1014,15 @@ Http2Session::CleanupStream(Http2Stream *aStream, nsresult aResult,
|
||||
return;
|
||||
}
|
||||
|
||||
Http2PushedStream *pushSource = aStream->PushSource();
|
||||
if (pushSource) {
|
||||
// aStream is a synthetic attached to an even push
|
||||
MOZ_ASSERT(pushSource->GetConsumerStream() == aStream);
|
||||
MOZ_ASSERT(!aStream->StreamID());
|
||||
MOZ_ASSERT(!(pushSource->StreamID() & 0x1));
|
||||
aStream->ClearPushSource();
|
||||
}
|
||||
|
||||
if (aStream->DeferCleanup(aResult)) {
|
||||
LOG3(("Http2Session::CleanupStream 0x%X deferred\n", aStream->StreamID()));
|
||||
return;
|
||||
@ -1024,15 +1033,6 @@ Http2Session::CleanupStream(Http2Stream *aStream, nsresult aResult,
|
||||
return;
|
||||
}
|
||||
|
||||
Http2PushedStream *pushSource = aStream->PushSource();
|
||||
if (pushSource) {
|
||||
// aStream is a synthetic attached to an even push
|
||||
MOZ_ASSERT(pushSource->GetConsumerStream() == aStream);
|
||||
MOZ_ASSERT(!aStream->StreamID());
|
||||
MOZ_ASSERT(!(pushSource->StreamID() & 0x1));
|
||||
pushSource->SetConsumerStream(nullptr);
|
||||
}
|
||||
|
||||
if (!aStream->RecvdFin() && !aStream->RecvdReset() && aStream->StreamID()) {
|
||||
LOG3(("Stream had not processed recv FIN, sending RST code %X\n", aResetCode));
|
||||
GenerateRstStream(aResetCode, aStream->StreamID());
|
||||
|
@ -101,10 +101,20 @@ Http2Stream::Http2Stream(nsAHttpTransaction *httpTransaction,
|
||||
|
||||
Http2Stream::~Http2Stream()
|
||||
{
|
||||
ClearPushSource();
|
||||
ClearTransactionsBlockedOnTunnel();
|
||||
mStreamID = Http2Session::kDeadStreamID;
|
||||
}
|
||||
|
||||
void
|
||||
Http2Stream::ClearPushSource()
|
||||
{
|
||||
if (mPushSource) {
|
||||
mPushSource->SetConsumerStream(nullptr);
|
||||
mPushSource = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ReadSegments() is used to write data down the socket. Generally, HTTP
|
||||
// request data is pulled from the approriate transaction and
|
||||
// converted to HTTP/2 data. Sometimes control data like a window-update is
|
||||
@ -1091,6 +1101,10 @@ Http2Stream::ConvertPushHeaders(Http2Decompressor *decompressor,
|
||||
void
|
||||
Http2Stream::Close(nsresult reason)
|
||||
{
|
||||
// In case we are connected to a push, make sure the push knows we are closed,
|
||||
// so it doesn't try to give us any more DATA that comes on it after our close.
|
||||
ClearPushSource();
|
||||
|
||||
mTransaction->Close(reason);
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ public:
|
||||
|
||||
uint32_t StreamID() { return mStreamID; }
|
||||
Http2PushedStream *PushSource() { return mPushSource; }
|
||||
void ClearPushSource();
|
||||
|
||||
stateType HTTPState() { return mState; }
|
||||
void SetHTTPState(stateType val) { mState = val; }
|
||||
|
@ -1032,6 +1032,7 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
||||
{ "goto.google.com", true, false, false, -1, &kPinset_google_root_pems },
|
||||
{ "gr.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
|
||||
{ "groups.google.com", true, false, false, -1, &kPinset_google_root_pems },
|
||||
{ "gstatic.cn", true, false, false, -1, &kPinset_google_root_pems },
|
||||
{ "gstatic.com", true, false, false, -1, &kPinset_google_root_pems },
|
||||
{ "gvt1.com", true, false, false, -1, &kPinset_google_root_pems },
|
||||
{ "gvt2.com", true, false, false, -1, &kPinset_google_root_pems },
|
||||
@ -1179,8 +1180,8 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
||||
{ "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
|
||||
};
|
||||
|
||||
// Pinning Preload List Length = 477;
|
||||
// Pinning Preload List Length = 478;
|
||||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1527453921095000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1528837162062000);
|
||||
|
@ -30,8 +30,10 @@ using namespace mozilla::psm;
|
||||
|
||||
extern PRLogModuleInfo* gPIPNSSLog;
|
||||
|
||||
#if (0) // TenFourFox issue 334
|
||||
static void AccumulateCipherSuite(Telemetry::ID probe,
|
||||
const SSLChannelInfo& channelInfo);
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
@ -1027,6 +1029,7 @@ CanFalseStartCallback(PRFileDesc* fd, void* client_data, PRBool *canFalseStart)
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
#if(0) // TenFourFox issue 334
|
||||
static void
|
||||
AccumulateNonECCKeySize(Telemetry::ID probe, uint32_t bits)
|
||||
{
|
||||
@ -1076,6 +1079,7 @@ AccumulateCipherSuite(Telemetry::ID probe, const SSLChannelInfo& channelInfo)
|
||||
case TLS_ECDHE_RSA_WITH_RC4_128_SHA: value = 8; break;
|
||||
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: value = 9; break;
|
||||
case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: value = 10; break;
|
||||
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: value = 11; break; // just in case, issue 489
|
||||
// DHE key exchange
|
||||
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: value = 21; break;
|
||||
case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: value = 22; break;
|
||||
@ -1114,6 +1118,7 @@ AccumulateCipherSuite(Telemetry::ID probe, const SSLChannelInfo& channelInfo)
|
||||
MOZ_ASSERT(value != 0);
|
||||
Telemetry::Accumulate(probe, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
@ -1146,6 +1151,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||
rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo));
|
||||
MOZ_ASSERT(rv == SECSuccess);
|
||||
if (rv == SECSuccess) {
|
||||
#if(0) // TenFourFox issue 334
|
||||
// Get the protocol version for telemetry
|
||||
// 1=tls1, 2=tls1.1, 3=tls1.2
|
||||
unsigned int versionEnum = channelInfo.protocolVersion & 0xFF;
|
||||
@ -1155,6 +1161,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||
infoObject->IsFullHandshake() ? Telemetry::SSL_CIPHER_SUITE_FULL
|
||||
: Telemetry::SSL_CIPHER_SUITE_RESUMED,
|
||||
channelInfo);
|
||||
#endif
|
||||
|
||||
SSLCipherSuiteInfo cipherInfo;
|
||||
rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
|
||||
@ -1163,17 +1170,20 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||
if (rv == SECSuccess) {
|
||||
usesWeakCipher = cipherInfo.symCipher == ssl_calg_rc4;
|
||||
|
||||
#if(0)
|
||||
// keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4
|
||||
Telemetry::Accumulate(
|
||||
infoObject->IsFullHandshake()
|
||||
? Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_FULL
|
||||
: Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED,
|
||||
cipherInfo.keaType);
|
||||
#endif
|
||||
|
||||
DebugOnly<int16_t> KEAUsed;
|
||||
MOZ_ASSERT(NS_SUCCEEDED(infoObject->GetKEAUsed(&KEAUsed)) &&
|
||||
(KEAUsed == cipherInfo.keaType));
|
||||
|
||||
#if(0)
|
||||
if (infoObject->IsFullHandshake()) {
|
||||
switch (cipherInfo.keaType) {
|
||||
case ssl_kea_rsa:
|
||||
@ -1223,6 +1233,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||
? Telemetry::SSL_SYMMETRIC_CIPHER_FULL
|
||||
: Telemetry::SSL_SYMMETRIC_CIPHER_RESUMED,
|
||||
cipherInfo.symCipher);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -623,6 +623,9 @@ static const CipherPref sCipherPrefs[] = {
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, true },
|
||||
{ "security.ssl3.ecdhe_ecdsa_aes_128_sha",
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, true },
|
||||
// stopgap for TenFourFox issue 489 pending ChaCha20/Poly1305 implementation
|
||||
{ "security.ssl3.ecdhe_rsa_aes_128_sha256",
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, true },
|
||||
|
||||
{ "security.ssl3.ecdhe_rsa_aes_256_sha",
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, true },
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,7 +29,7 @@ if (versionNum.substr(0,3) == "45.") {
|
||||
// FPR series
|
||||
var vf = 0 + versionNum.substr(3);
|
||||
var pl = ""+ (vf - (vf|0));
|
||||
pl = 0 + pl.substr(1);
|
||||
pl = ((0 + pl.substr(1) * 10)+0.001)|0; // damn float rounding
|
||||
vf = vf|0; vf -= 9;
|
||||
// XXX localize me
|
||||
version.textContent = "Feature Parity Release "+vf+
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user