mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-06-25 20:29:33 +00:00
commit
b61caed0c3
|
@ -18,6 +18,9 @@
|
||||||
<preference id="tenfourfox.ua.template"
|
<preference id="tenfourfox.ua.template"
|
||||||
name="tenfourfox.ua.template"
|
name="tenfourfox.ua.template"
|
||||||
type="string"/>
|
type="string"/>
|
||||||
|
<preference id="tenfourfox.adblock.enabled"
|
||||||
|
name="tenfourfox.adblock.enabled"
|
||||||
|
type="bool"/>
|
||||||
|
|
||||||
</preferences>
|
</preferences>
|
||||||
|
|
||||||
|
@ -69,3 +72,12 @@
|
||||||
</menulist>
|
</menulist>
|
||||||
</hbox>
|
</hbox>
|
||||||
</groupbox>
|
</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
|
// blocking zdbb.net seems to be problematic
|
||||||
// https://github.com/AdguardTeam/AdguardFilters/issues/1278
|
// 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("c.amazon-adsystem.com") ||
|
||||||
|
|
||||||
BLOK("google-analytics.com") ||
|
BLOK("google-analytics.com") ||
|
||||||
|
@ -793,6 +803,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||||
BLOK("cdn.segment.com") ||
|
BLOK("cdn.segment.com") ||
|
||||||
|
|
||||||
BLOK("cdn-gl.imrworldwide.com") ||
|
BLOK("cdn-gl.imrworldwide.com") ||
|
||||||
|
BLOK("secure-us.imrworldwide.com") ||
|
||||||
BLOK("secure-dcr.imrworldwide.com") ||
|
BLOK("secure-dcr.imrworldwide.com") ||
|
||||||
|
|
||||||
BLOK("labs-cdn.revcontent.com") ||
|
BLOK("labs-cdn.revcontent.com") ||
|
||||||
|
@ -800,6 +811,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||||
BLOK("cdn.revcontent.com") ||
|
BLOK("cdn.revcontent.com") ||
|
||||||
|
|
||||||
BLOK("cas.criteo.com") ||
|
BLOK("cas.criteo.com") ||
|
||||||
|
BLOK("rtax.criteo.com") ||
|
||||||
BLOK("static.criteo.net") ||
|
BLOK("static.criteo.net") ||
|
||||||
|
|
||||||
BLOK("jsc.idealmedia.com") ||
|
BLOK("jsc.idealmedia.com") ||
|
||||||
|
@ -848,6 +860,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||||
|
|
||||||
BLOK("www.npttech.com") ||
|
BLOK("www.npttech.com") ||
|
||||||
|
|
||||||
|
BLOK("fw.adsafeprotected.com") ||
|
||||||
BLOK("cdn.adsafeprotected.com") ||
|
BLOK("cdn.adsafeprotected.com") ||
|
||||||
BLOK("pixel.adsafeprotected.com") ||
|
BLOK("pixel.adsafeprotected.com") ||
|
||||||
BLOK("static.adsafeprotected.com") ||
|
BLOK("static.adsafeprotected.com") ||
|
||||||
|
@ -902,6 +915,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||||
BLOK("se.monetate.net") ||
|
BLOK("se.monetate.net") ||
|
||||||
|
|
||||||
BLOK("ad.crwdcntrl.net") ||
|
BLOK("ad.crwdcntrl.net") ||
|
||||||
|
BLOK("bcp.crwdcntrl.net") ||
|
||||||
BLOK("tags.crwdcntrl.net") ||
|
BLOK("tags.crwdcntrl.net") ||
|
||||||
|
|
||||||
BLOK("cdn.nsstatic.net") ||
|
BLOK("cdn.nsstatic.net") ||
|
||||||
|
@ -917,6 +931,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||||
BLOK("stats.cloudwp.io") ||
|
BLOK("stats.cloudwp.io") ||
|
||||||
|
|
||||||
BLOK("ap.lijit.com") ||
|
BLOK("ap.lijit.com") ||
|
||||||
|
BLOK("ce.lijit.com") ||
|
||||||
|
|
||||||
BLOK("tlx.3lift.com") ||
|
BLOK("tlx.3lift.com") ||
|
||||||
|
|
||||||
|
@ -982,14 +997,12 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||||
BLOK("cdata.carambo.la") ||
|
BLOK("cdata.carambo.la") ||
|
||||||
BLOK("route.carambo.la") ||
|
BLOK("route.carambo.la") ||
|
||||||
|
|
||||||
|
BLOK("us-u.openx.net") ||
|
||||||
|
BLOK("uk-ads.openx.net") ||
|
||||||
BLOK("us-ads.openx.net") ||
|
BLOK("us-ads.openx.net") ||
|
||||||
|
|
||||||
BLOK("s-static.innovid.com") ||
|
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("ustatik.com") ||
|
||||||
BLOK("cdn.ustatik.com") ||
|
BLOK("cdn.ustatik.com") ||
|
||||||
|
|
||||||
|
@ -997,6 +1010,43 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||||
|
|
||||||
BLOK("s.spoutable.com") ||
|
BLOK("s.spoutable.com") ||
|
||||||
BLOK("cdn.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) {
|
0) {
|
||||||
#undef BLOK
|
#undef BLOK
|
||||||
// Yup.
|
// Yup.
|
||||||
|
|
|
@ -10,4 +10,4 @@
|
||||||
# hardcoded milestones in the tree from these two files.
|
# 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);
|
loadInfo->SetReferrer(mCurrentURI);
|
||||||
|
|
||||||
/* Don't ever "guess" on which owner to use to avoid picking
|
// Set the triggering pricipal to aPrincipal if available, or current
|
||||||
* the current owner.
|
// 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);
|
loadInfo->SetOwnerIsExplicit(true);
|
||||||
|
|
||||||
/* Check if this META refresh causes a redirection
|
/* 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);
|
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
|
* LoadURI(...) will cancel all refresh timers... This causes the
|
||||||
* Timer and its refreshData instance to be released...
|
* Timer and its refreshData instance to be released...
|
||||||
|
|
|
@ -19,9 +19,8 @@ interface nsIRefreshURI : nsISupports {
|
||||||
*
|
*
|
||||||
* @param aUri The uri to refresh.
|
* @param aUri The uri to refresh.
|
||||||
* @param aPrincipal The triggeringPrincipal for the refresh load
|
* @param aPrincipal The triggeringPrincipal for the refresh load
|
||||||
* May be null, in which case a principal will be built based on the
|
* May be null, in which case the principal of current document will be
|
||||||
* referrer URI of the previous docshell load, or will use the system
|
* applied.
|
||||||
* principal when there is no referrer.
|
|
||||||
* @param aMillis The number of milliseconds to wait.
|
* @param aMillis The number of milliseconds to wait.
|
||||||
* @param aRepeat Flag to indicate if the uri is to be
|
* @param aRepeat Flag to indicate if the uri is to be
|
||||||
* repeatedly refreshed every aMillis milliseconds.
|
* repeatedly refreshed every aMillis milliseconds.
|
||||||
|
@ -37,9 +36,8 @@ interface nsIRefreshURI : nsISupports {
|
||||||
*
|
*
|
||||||
* @param aURI The URI to refresh.
|
* @param aURI The URI to refresh.
|
||||||
* @param aPrincipal The triggeringPrincipal for the refresh load
|
* @param aPrincipal The triggeringPrincipal for the refresh load
|
||||||
* May be null, in which case a principal will be built based on the
|
* May be null, in which case the principal of current document will be
|
||||||
* referrer URI of the previous docshell load, or will use the system
|
* applied.
|
||||||
* principal when there is no referrer.
|
|
||||||
* @param aMillis The number of milliseconds by which this refresh would
|
* @param aMillis The number of milliseconds by which this refresh would
|
||||||
* be delayed if it were not being forced.
|
* be delayed if it were not being forced.
|
||||||
* @param aMetaRefresh Flag to indicate if this is a meta refresh.
|
* @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 aBaseURI base URI to resolve refresh uri with.
|
||||||
* @param aPrincipal The triggeringPrincipal for the refresh load
|
* @param aPrincipal The triggeringPrincipal for the refresh load
|
||||||
* May be null, in which case a principal will be built based on the
|
* May be null, in which case the principal of current document will be
|
||||||
* referrer URI of the previous docshell load, or will use the system
|
* applied.
|
||||||
* principal when there is no referrer.
|
|
||||||
* @param aHeader The meta refresh header string.
|
* @param aHeader The meta refresh header string.
|
||||||
*/
|
*/
|
||||||
void setupRefreshURIFromHeader(in nsIURI aBaseURI,
|
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 "nsNameSpaceManager.h"
|
||||||
#include "nsContentList.h"
|
#include "nsContentList.h"
|
||||||
#include "nsVariant.h"
|
#include "nsVariant.h"
|
||||||
#include "nsDOMSettableTokenList.h"
|
|
||||||
#include "nsDOMTokenList.h"
|
#include "nsDOMTokenList.h"
|
||||||
#include "nsXBLPrototypeBinding.h"
|
#include "nsXBLPrototypeBinding.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
|
@ -3086,11 +3085,11 @@ Element::GetLinkTarget(nsAString& aTarget)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nsDOMSettableTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
|
nsDOMTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
|
||||||
void *aPropertyValue, void *aData)
|
void *aPropertyValue, void *aData)
|
||||||
{
|
{
|
||||||
nsDOMSettableTokenList* list =
|
nsDOMTokenList* list =
|
||||||
static_cast<nsDOMSettableTokenList*>(aPropertyValue);
|
static_cast<nsDOMTokenList*>(aPropertyValue);
|
||||||
NS_RELEASE(list);
|
NS_RELEASE(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3113,8 +3112,9 @@ Element::HTMLSVGPropertiesToTraverseAndUnlink()
|
||||||
return sPropertiesToTraverseAndUnlink;
|
return sPropertiesToTraverseAndUnlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsDOMSettableTokenList*
|
nsDOMTokenList*
|
||||||
Element::GetTokenList(nsIAtom* aAtom)
|
Element::GetTokenList(nsIAtom* aAtom,
|
||||||
|
const DOMTokenListSupportedTokenArray aSupportedTokens)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
nsIAtom*** props =
|
nsIAtom*** props =
|
||||||
|
@ -3129,14 +3129,14 @@ Element::GetTokenList(nsIAtom* aAtom)
|
||||||
MOZ_ASSERT(found, "Trying to use an unknown tokenlist!");
|
MOZ_ASSERT(found, "Trying to use an unknown tokenlist!");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsDOMSettableTokenList* list = nullptr;
|
nsDOMTokenList* list = nullptr;
|
||||||
if (HasProperties()) {
|
if (HasProperties()) {
|
||||||
list = static_cast<nsDOMSettableTokenList*>(GetProperty(aAtom));
|
list = static_cast<nsDOMTokenList*>(GetProperty(aAtom));
|
||||||
}
|
}
|
||||||
if (!list) {
|
if (!list) {
|
||||||
list = new nsDOMSettableTokenList(this, aAtom);
|
list = new nsDOMTokenList(this, aAtom, aSupportedTokens);
|
||||||
NS_ADDREF(list);
|
NS_ADDREF(list);
|
||||||
SetProperty(aAtom, list, nsDOMSettableTokenListPropertyDestructor);
|
SetProperty(aAtom, list, nsDOMTokenListPropertyDestructor);
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -3153,7 +3153,7 @@ Element::GetTokenList(nsIAtom* aAtom, nsIVariant** aResult)
|
||||||
nsresult
|
nsresult
|
||||||
Element::SetTokenList(nsIAtom* aAtom, nsIVariant* aValue)
|
Element::SetTokenList(nsIAtom* aAtom, nsIVariant* aValue)
|
||||||
{
|
{
|
||||||
nsDOMSettableTokenList* itemType = GetTokenList(aAtom);
|
nsDOMTokenList* itemType = GetTokenList(aAtom);
|
||||||
nsAutoString string;
|
nsAutoString string;
|
||||||
aValue->GetAsAString(string);
|
aValue->GetAsAString(string);
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "nsAttrValue.h"
|
#include "nsAttrValue.h"
|
||||||
#include "mozilla/EventForwards.h"
|
#include "mozilla/EventForwards.h"
|
||||||
#include "mozilla/dom/BindingDeclarations.h"
|
#include "mozilla/dom/BindingDeclarations.h"
|
||||||
|
#include "mozilla/dom/DOMTokenListSupportedTokens.h"
|
||||||
#include "mozilla/dom/WindowBinding.h"
|
#include "mozilla/dom/WindowBinding.h"
|
||||||
#include "mozilla/dom/ElementBinding.h"
|
#include "mozilla/dom/ElementBinding.h"
|
||||||
#include "Units.h"
|
#include "Units.h"
|
||||||
|
@ -44,7 +45,6 @@ class nsIURI;
|
||||||
class nsIScrollableFrame;
|
class nsIScrollableFrame;
|
||||||
class nsAttrValueOrString;
|
class nsAttrValueOrString;
|
||||||
class nsContentList;
|
class nsContentList;
|
||||||
class nsDOMSettableTokenList;
|
|
||||||
class nsDOMTokenList;
|
class nsDOMTokenList;
|
||||||
struct nsRect;
|
struct nsRect;
|
||||||
class nsFocusManager;
|
class nsFocusManager;
|
||||||
|
@ -1342,7 +1342,8 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual void GetLinkTarget(nsAString& aTarget);
|
virtual void GetLinkTarget(nsAString& aTarget);
|
||||||
|
|
||||||
nsDOMSettableTokenList* GetTokenList(nsIAtom* aAtom);
|
nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
|
||||||
|
const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
|
||||||
void GetTokenList(nsIAtom* aAtom, nsIVariant** aResult);
|
void GetTokenList(nsIAtom* aAtom, nsIVariant** aResult);
|
||||||
nsresult SetTokenList(nsIAtom* aAtom, nsIVariant* aValue);
|
nsresult SetTokenList(nsIAtom* aAtom, nsIVariant* aValue);
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,11 @@
|
||||||
class ContentUnbinder;
|
class ContentUnbinder;
|
||||||
class nsContentList;
|
class nsContentList;
|
||||||
class nsDOMAttributeMap;
|
class nsDOMAttributeMap;
|
||||||
class nsDOMTokenList;
|
|
||||||
class nsIControllers;
|
class nsIControllers;
|
||||||
class nsICSSDeclaration;
|
class nsICSSDeclaration;
|
||||||
class nsIDocument;
|
class nsIDocument;
|
||||||
class nsDOMStringMap;
|
class nsDOMStringMap;
|
||||||
|
class nsDOMTokenList;
|
||||||
class nsIURI;
|
class nsIURI;
|
||||||
|
|
||||||
namespace mozilla {
|
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',
|
'AutocompleteFieldList.h',
|
||||||
'Crypto.h',
|
'Crypto.h',
|
||||||
'HTMLSplitOnSpacesTokenizer.h',
|
'HTMLSplitOnSpacesTokenizer.h',
|
||||||
|
'IframeSandboxKeywordList.h',
|
||||||
'mozAutoDocUpdate.h',
|
'mozAutoDocUpdate.h',
|
||||||
'mozFlushType.h',
|
'mozFlushType.h',
|
||||||
'nsAtomListUtils.h',
|
'nsAtomListUtils.h',
|
||||||
|
@ -74,6 +75,7 @@ EXPORTS += [
|
||||||
'nsDOMJSUtils.h',
|
'nsDOMJSUtils.h',
|
||||||
'nsDOMNavigationTiming.h',
|
'nsDOMNavigationTiming.h',
|
||||||
'nsDOMString.h',
|
'nsDOMString.h',
|
||||||
|
'nsDOMTokenList.h',
|
||||||
'nsFocusManager.h',
|
'nsFocusManager.h',
|
||||||
'nsFormData.h',
|
'nsFormData.h',
|
||||||
'nsFrameMessageManager.h',
|
'nsFrameMessageManager.h',
|
||||||
|
@ -174,6 +176,7 @@ EXPORTS.mozilla.dom += [
|
||||||
'DOMRect.h',
|
'DOMRect.h',
|
||||||
'DOMRequest.h',
|
'DOMRequest.h',
|
||||||
'DOMStringList.h',
|
'DOMStringList.h',
|
||||||
|
'DOMTokenListSupportedTokens.h',
|
||||||
'Element.h',
|
'Element.h',
|
||||||
'ElementInlines.h',
|
'ElementInlines.h',
|
||||||
'EventSource.h',
|
'EventSource.h',
|
||||||
|
@ -278,7 +281,6 @@ UNIFIED_SOURCES += [
|
||||||
'nsDOMNavigationTiming.cpp',
|
'nsDOMNavigationTiming.cpp',
|
||||||
'nsDOMScriptObjectFactory.cpp',
|
'nsDOMScriptObjectFactory.cpp',
|
||||||
'nsDOMSerializer.cpp',
|
'nsDOMSerializer.cpp',
|
||||||
'nsDOMSettableTokenList.cpp',
|
|
||||||
'nsDOMTokenList.cpp',
|
'nsDOMTokenList.cpp',
|
||||||
'nsDOMWindowList.cpp',
|
'nsDOMWindowList.cpp',
|
||||||
'nsFocusManager.cpp',
|
'nsFocusManager.cpp',
|
||||||
|
|
|
@ -1362,19 +1362,13 @@ nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* sandboxAttr)
|
||||||
| SANDBOXED_DOMAIN;
|
| SANDBOXED_DOMAIN;
|
||||||
|
|
||||||
// Macro for updating the flag according to the keywords
|
// 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 (sandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { out &= ~(flags); }
|
||||||
|
|
||||||
IF_KEYWORD(allowsameorigin, SANDBOXED_ORIGIN)
|
#include "IframeSandboxKeywordList.h"
|
||||||
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)
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
#undef IF_KEYWORD
|
#undef SANDBOX_KEYWORD
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIBidiKeyboard*
|
nsIBidiKeyboard*
|
||||||
|
|
|
@ -9,20 +9,25 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsDOMTokenList.h"
|
#include "nsDOMTokenList.h"
|
||||||
|
#include "nsAttrValueInlines.h"
|
||||||
|
#include "nsDataHashtable.h"
|
||||||
#include "nsAttrValue.h"
|
#include "nsAttrValue.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
|
#include "nsHashKeys.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/DOMTokenListBinding.h"
|
#include "mozilla/dom/DOMTokenListBinding.h"
|
||||||
|
#include "mozilla/BloomFilter.h"
|
||||||
#include "mozilla/ErrorResult.h"
|
#include "mozilla/ErrorResult.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
nsDOMTokenList::nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom)
|
nsDOMTokenList::nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom,
|
||||||
|
const DOMTokenListSupportedTokenArray aSupportedTokens)
|
||||||
: mElement(aElement),
|
: mElement(aElement),
|
||||||
mAttrAtom(aAttrAtom)
|
mAttrAtom(aAttrAtom),
|
||||||
|
mSupportedTokens(aSupportedTokens)
|
||||||
{
|
{
|
||||||
// We don't add a reference to our element. If it goes away,
|
// We don't add a reference to our element. If it goes away,
|
||||||
// we'll be told to drop our reference
|
// we'll be told to drop our reference
|
||||||
|
@ -50,6 +55,45 @@ nsDOMTokenList::GetParsedAttr()
|
||||||
return mElement->GetAttrInfo(kNameSpaceID_None, mAttrAtom).mValue;
|
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
|
uint32_t
|
||||||
nsDOMTokenList::Length()
|
nsDOMTokenList::Length()
|
||||||
{
|
{
|
||||||
|
@ -58,6 +102,7 @@ nsDOMTokenList::Length()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RemoveDuplicates(attr);
|
||||||
return attr->GetAtomCount();
|
return attr->GetAtomCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +111,13 @@ nsDOMTokenList::IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aResult)
|
||||||
{
|
{
|
||||||
const nsAttrValue* attr = GetParsedAttr();
|
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())) {
|
if (attr && aIndex < static_cast<uint32_t>(attr->GetAtomCount())) {
|
||||||
aFound = true;
|
aFound = true;
|
||||||
attr->AtomAt(aIndex)->ToString(aResult);
|
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
|
nsresult
|
||||||
nsDOMTokenList::CheckToken(const nsAString& aStr)
|
nsDOMTokenList::CheckToken(const nsAString& aStr)
|
||||||
{
|
{
|
||||||
|
@ -130,10 +192,15 @@ nsDOMTokenList::AddInternal(const nsAttrValue* aAttr,
|
||||||
nsAutoString resultStr;
|
nsAutoString resultStr;
|
||||||
|
|
||||||
if (aAttr) {
|
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;
|
nsAutoTArray<nsString, 10> addedClasses;
|
||||||
|
|
||||||
for (uint32_t i = 0, l = aTokens.Length(); i < l; ++i) {
|
for (uint32_t i = 0, l = aTokens.Length(); i < l; ++i) {
|
||||||
|
@ -144,16 +211,11 @@ nsDOMTokenList::AddInternal(const nsAttrValue* aAttr,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oneWasAdded ||
|
if (!resultStr.IsEmpty()) {
|
||||||
(!resultStr.IsEmpty() &&
|
|
||||||
!nsContentUtils::IsHTMLWhitespace(resultStr.Last()))) {
|
|
||||||
resultStr.Append(' ');
|
resultStr.Append(' ');
|
||||||
resultStr.Append(aToken);
|
|
||||||
} else {
|
|
||||||
resultStr.Append(aToken);
|
|
||||||
}
|
}
|
||||||
|
resultStr.Append(aToken);
|
||||||
|
|
||||||
oneWasAdded = true;
|
|
||||||
addedClasses.AppendElement(aToken);
|
addedClasses.AppendElement(aToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,60 +248,20 @@ nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aAttr, "Need an attribute");
|
MOZ_ASSERT(aAttr, "Need an attribute");
|
||||||
|
|
||||||
nsAutoString input;
|
RemoveDuplicates(aAttr);
|
||||||
aAttr->ToString(input);
|
|
||||||
|
|
||||||
nsAString::const_iterator copyStart, tokenStart, iter, end;
|
nsAutoString resultStr;
|
||||||
input.BeginReading(iter);
|
for (uint32_t i = 0; i < aAttr->GetAtomCount(); i++) {
|
||||||
input.EndReading(end);
|
if (aTokens.Contains(nsDependentAtomString(aAttr->AtomAt(i)))) {
|
||||||
copyStart = iter;
|
continue;
|
||||||
|
}
|
||||||
nsAutoString output;
|
if (!resultStr.IsEmpty()) {
|
||||||
bool lastTokenRemoved = false;
|
resultStr.AppendLiteral(" ");
|
||||||
|
}
|
||||||
while (iter != end) {
|
resultStr.Append(nsDependentAtomString(aAttr->AtomAt(i)));
|
||||||
// skip whitespace.
|
|
||||||
while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
|
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter == end) {
|
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, resultStr, true);
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, output, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -299,6 +321,93 @@ nsDOMTokenList::Toggle(const nsAString& aToken,
|
||||||
return isPresent;
|
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
|
void
|
||||||
nsDOMTokenList::Stringify(nsAString& aResult)
|
nsDOMTokenList::Stringify(nsAString& aResult)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,9 +13,11 @@
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsDOMString.h"
|
#include "nsDOMString.h"
|
||||||
|
#include "nsDOMString.h"
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/BindingDeclarations.h"
|
#include "mozilla/dom/BindingDeclarations.h"
|
||||||
|
#include "mozilla/dom/DOMTokenListSupportedTokens.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class ErrorResult;
|
class ErrorResult;
|
||||||
|
@ -26,7 +28,7 @@ class nsAttrValue;
|
||||||
class nsIAtom;
|
class nsIAtom;
|
||||||
|
|
||||||
// nsISupports must be on the primary inheritance chain
|
// nsISupports must be on the primary inheritance chain
|
||||||
// because nsDOMSettableTokenList is traversed by Element.
|
|
||||||
class nsDOMTokenList : public nsISupports,
|
class nsDOMTokenList : public nsISupports,
|
||||||
public nsWrapperCache
|
public nsWrapperCache
|
||||||
{
|
{
|
||||||
|
@ -37,7 +39,8 @@ public:
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMTokenList)
|
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;
|
virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
@ -46,6 +49,7 @@ public:
|
||||||
return mElement;
|
return mElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoveDuplicates(const nsAttrValue* aAttr);
|
||||||
uint32_t Length();
|
uint32_t Length();
|
||||||
void Item(uint32_t aIndex, nsAString& aResult)
|
void Item(uint32_t aIndex, nsAString& aResult)
|
||||||
{
|
{
|
||||||
|
@ -63,9 +67,17 @@ public:
|
||||||
void Remove(const nsAString& aToken, mozilla::ErrorResult& aError);
|
void Remove(const nsAString& aToken, mozilla::ErrorResult& aError);
|
||||||
void Remove(const nsTArray<nsString>& aTokens,
|
void Remove(const nsTArray<nsString>& aTokens,
|
||||||
mozilla::ErrorResult& aError);
|
mozilla::ErrorResult& aError);
|
||||||
|
void Replace(const nsAString& aToken,
|
||||||
|
const nsAString& aNewToken,
|
||||||
|
mozilla::ErrorResult& aError);
|
||||||
bool Toggle(const nsAString& aToken,
|
bool Toggle(const nsAString& aToken,
|
||||||
const mozilla::dom::Optional<bool>& force,
|
const mozilla::dom::Optional<bool>& force,
|
||||||
mozilla::ErrorResult& aError);
|
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);
|
void Stringify(nsAString& aResult);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -73,14 +85,20 @@ protected:
|
||||||
|
|
||||||
nsresult CheckToken(const nsAString& aStr);
|
nsresult CheckToken(const nsAString& aStr);
|
||||||
nsresult CheckTokens(const nsTArray<nsString>& aStr);
|
nsresult CheckTokens(const nsTArray<nsString>& aStr);
|
||||||
|
void RemoveDuplicatesInternal(nsTArray<nsCOMPtr<nsIAtom>>* aArray,
|
||||||
|
uint32_t aStart);
|
||||||
void AddInternal(const nsAttrValue* aAttr,
|
void AddInternal(const nsAttrValue* aAttr,
|
||||||
const nsTArray<nsString>& aTokens);
|
const nsTArray<nsString>& aTokens);
|
||||||
void RemoveInternal(const nsAttrValue* aAttr,
|
void RemoveInternal(const nsAttrValue* aAttr,
|
||||||
const nsTArray<nsString>& aTokens);
|
const nsTArray<nsString>& aTokens);
|
||||||
|
void ReplaceInternal(const nsAttrValue* aAttr,
|
||||||
|
const nsAString& aToken,
|
||||||
|
const nsAString& aNewToken);
|
||||||
inline const nsAttrValue* GetParsedAttr();
|
inline const nsAttrValue* GetParsedAttr();
|
||||||
|
|
||||||
nsCOMPtr<Element> mElement;
|
nsCOMPtr<Element> mElement;
|
||||||
nsCOMPtr<nsIAtom> mAttrAtom;
|
nsCOMPtr<nsIAtom> mAttrAtom;
|
||||||
|
const mozilla::dom::DOMTokenListSupportedTokenArray mSupportedTokens;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsDOMTokenList_h___
|
#endif // nsDOMTokenList_h___
|
||||||
|
|
|
@ -562,7 +562,7 @@ nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aDontSerializeRoot) {
|
if (!aDontSerializeRoot) {
|
||||||
rv = SerializeNodeEnd(node, aStr);
|
rv = SerializeNodeEnd(maybeFixedNode, aStr);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -347,17 +347,32 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the base URI for relative URIs in the document (the document uri
|
* Return the fallback base URL for this document, as defined in the HTML
|
||||||
* unless it's overridden by SetBaseURI, HTML <base> tags, etc.). The
|
* specification. Note that this can return null if there is no document URI.
|
||||||
* 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.
|
* XXXbz: This doesn't implement the bits for about:blank yet.
|
||||||
*/
|
*/
|
||||||
nsIURI* GetDocBaseURI() const
|
nsIURI* GetFallbackBaseURI() const
|
||||||
{
|
{
|
||||||
if (mIsSrcdocDocument && mParentDocument) {
|
if (mIsSrcdocDocument && mParentDocument) {
|
||||||
return mParentDocument->GetDocBaseURI();
|
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;
|
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
|
// The amount of time we wait from the first request to GC to actually
|
||||||
// doing the first GC.
|
// 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
|
// The default amount of time to wait from the user being idle to starting a
|
||||||
// shrinking GC.
|
// shrinking GC.
|
||||||
#define NS_DEAULT_INACTIVE_GC_DELAY 300000 // ms
|
#define NS_DEAULT_INACTIVE_GC_DELAY 300000 // ms
|
||||||
|
|
||||||
// Maximum amount of time that should elapse between incremental GC slices
|
// 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
|
// If we haven't painted in 100ms, we allow for a longer GC budget
|
||||||
#define NS_INTERSLICE_GC_BUDGET 40 // ms
|
#define NS_INTERSLICE_GC_BUDGET 40 // ms
|
||||||
|
@ -111,13 +111,13 @@ const size_t gStackSize = 8192;
|
||||||
// and doing the actual CC.
|
// and doing the actual CC.
|
||||||
#define NS_CC_DELAY 6000 // ms
|
#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
|
// 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
|
// 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
|
// Maximum total duration for an ICC
|
||||||
static const uint32_t kMaxICCDuration = 2000; // ms
|
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
|
// Force a CC after this long if there's more than NS_CC_FORCED_PURPLE_LIMIT
|
||||||
// objects in the purple buffer.
|
// objects in the purple buffer.
|
||||||
#define NS_CC_FORCED (2 * 60 * PR_USEC_PER_SEC) // 2 min
|
#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.
|
// 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
|
#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)
|
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"))
|
if (aLink.EqualsLiteral("prefetch"))
|
||||||
return nsStyleLinkElement::ePREFETCH;
|
return nsStyleLinkElement::ePREFETCH;
|
||||||
else if (aLink.EqualsLiteral("dns-prefetch"))
|
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?
|
// Should we optimize for aData.Length() == 0?
|
||||||
|
|
||||||
CheckedUint32 length = mState.mLength;
|
// FYI: Don't use CheckedInt in this method since here is very hot path
|
||||||
length += aLength;
|
// in some performance tests.
|
||||||
|
if (MOZ_UNLIKELY(NS_MAX_TEXT_FRAGMENT_LENGTH - mState.mLength < aLength)) {
|
||||||
if (!length.isValid()) {
|
return false; // Would be overflown if we'd keep handling.
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mState.mIs2b) {
|
if (mState.mIs2b) {
|
||||||
length *= sizeof(char16_t);
|
size_t size = mState.mLength + aLength;
|
||||||
if (!length.isValid()) {
|
if (MOZ_UNLIKELY(SIZE_MAX / sizeof(char16_t) < size)) {
|
||||||
return false;
|
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
|
// Already a 2-byte string so the result will be too
|
||||||
char16_t* buff = static_cast<char16_t*>(realloc(m2b, length.value()));
|
char16_t* buff = static_cast<char16_t*>(realloc(m2b, size));
|
||||||
if (!buff) {
|
if (MOZ_UNLIKELY(!buff)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,15 +379,16 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
|
||||||
int32_t first16bit = FirstNon8Bit(aBuffer, aBuffer + aLength);
|
int32_t first16bit = FirstNon8Bit(aBuffer, aBuffer + aLength);
|
||||||
|
|
||||||
if (first16bit != -1) { // aBuffer contains no non-8bit character
|
if (first16bit != -1) { // aBuffer contains no non-8bit character
|
||||||
length *= sizeof(char16_t);
|
size_t size = mState.mLength + aLength;
|
||||||
if (!length.isValid()) {
|
if (MOZ_UNLIKELY((SIZE_MAX / sizeof(char16_t)) < size)) {
|
||||||
return false;
|
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
|
// The old data was 1-byte, but the new is not so we have to expand it
|
||||||
// all to 2-byte
|
// all to 2-byte
|
||||||
char16_t* buff = static_cast<char16_t*>(malloc(length.value()));
|
char16_t* buff = static_cast<char16_t*>(malloc(size));
|
||||||
if (!buff) {
|
if (MOZ_UNLIKELY(!buff)) {
|
||||||
return false;
|
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
|
// The new and the old data is all 1-byte
|
||||||
|
size_t size = mState.mLength + aLength;
|
||||||
|
MOZ_ASSERT(sizeof(char) == 1);
|
||||||
char* buff;
|
char* buff;
|
||||||
if (mState.mInHeap) {
|
if (mState.mInHeap) {
|
||||||
buff = static_cast<char*>(realloc(const_cast<char*>(m1b), length.value()));
|
buff = static_cast<char*>(realloc(const_cast<char*>(m1b), size));
|
||||||
if (!buff) {
|
if (MOZ_UNLIKELY(!buff)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buff = static_cast<char*>(malloc(length.value()));
|
buff = static_cast<char*>(malloc(size));
|
||||||
if (!buff) {
|
if (MOZ_UNLIKELY(!buff)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,21 +464,8 @@ void
|
||||||
nsTextFragment::UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength)
|
nsTextFragment::UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength)
|
||||||
{
|
{
|
||||||
if (mState.mIs2b && !mState.mIsBidi) {
|
if (mState.mIs2b && !mState.mIsBidi) {
|
||||||
const char16_t* cp = aBuffer;
|
if (HasRTLChars(aBuffer, aLength)) {
|
||||||
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;
|
mState.mIsBidi = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,9 +213,13 @@ public:
|
||||||
uint32_t mInHeap : 1;
|
uint32_t mInHeap : 1;
|
||||||
uint32_t mIs2b : 1;
|
uint32_t mIs2b : 1;
|
||||||
uint32_t mIsBidi : 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;
|
uint32_t mLength : 29;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NS_MAX_TEXT_FRAGMENT_LENGTH (static_cast<uint32_t>(0x1FFFFFFF))
|
||||||
|
|
||||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -441,10 +441,6 @@ DOMInterfaces = {
|
||||||
'implicitJSContext': [ 'then' ],
|
'implicitJSContext': [ 'then' ],
|
||||||
},
|
},
|
||||||
|
|
||||||
'DOMSettableTokenList': {
|
|
||||||
'nativeType': 'nsDOMSettableTokenList',
|
|
||||||
},
|
|
||||||
|
|
||||||
'DOMStringMap': {
|
'DOMStringMap': {
|
||||||
'nativeType': 'nsDOMStringMap'
|
'nativeType': 'nsDOMStringMap'
|
||||||
},
|
},
|
||||||
|
|
|
@ -1136,11 +1136,13 @@ class CGHeaders(CGWrapper):
|
||||||
if desc.interface.maplikeOrSetlikeOrIterable:
|
if desc.interface.maplikeOrSetlikeOrIterable:
|
||||||
# We need ToJSValue.h for maplike/setlike type conversions
|
# We need ToJSValue.h for maplike/setlike type conversions
|
||||||
bindingHeaders.add("mozilla/dom/ToJSValue.h")
|
bindingHeaders.add("mozilla/dom/ToJSValue.h")
|
||||||
# Add headers for the key and value types of the maplike, since
|
# Add headers for the key and value types of the
|
||||||
# they'll be needed for convenience functions
|
# maplike/setlike/iterable, since they'll be needed for
|
||||||
|
# convenience functions
|
||||||
|
if desc.interface.maplikeOrSetlikeOrIterable.hasKeyType():
|
||||||
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.keyType,
|
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.keyType,
|
||||||
desc, None))
|
desc, None))
|
||||||
if desc.interface.maplikeOrSetlikeOrIterable.valueType:
|
if desc.interface.maplikeOrSetlikeOrIterable.hasValueType():
|
||||||
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.valueType,
|
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.valueType,
|
||||||
desc, None))
|
desc, None))
|
||||||
|
|
||||||
|
@ -2269,34 +2271,50 @@ class MethodDefiner(PropertyDefiner):
|
||||||
"condition": MemberCondition()
|
"condition": MemberCondition()
|
||||||
})
|
})
|
||||||
|
|
||||||
# Generate the maplike/setlike iterator, if one wasn't already
|
# Generate the keys/values/entries aliases for value iterables.
|
||||||
# generated by a method. If we already have an @@iterator symbol, fail.
|
maplikeOrSetlikeOrIterable = descriptor.interface.maplikeOrSetlikeOrIterable
|
||||||
if descriptor.interface.maplikeOrSetlikeOrIterable:
|
if (not static and
|
||||||
if hasIterator(methods, self.regular):
|
not unforgeable and
|
||||||
raise TypeError("Cannot have maplike/setlike/iterable interface with "
|
maplikeOrSetlikeOrIterable and
|
||||||
"other members that generate @@iterator "
|
maplikeOrSetlikeOrIterable.isIterable() and
|
||||||
"on interface %s, such as indexed getters "
|
maplikeOrSetlikeOrIterable.isValueIterator()):
|
||||||
"or aliased functions." %
|
# Add our keys/values/entries/forEach
|
||||||
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({
|
self.regular.append({
|
||||||
"name": "@@iterator",
|
"name": "keys",
|
||||||
"methodName": m.identifier.name,
|
"methodInfo": False,
|
||||||
"length": methodLength(m),
|
"selfHostedName": "ArrayKeys",
|
||||||
"flags": "0",
|
"length": 0,
|
||||||
|
"flags": "JSPROP_ENUMERATE",
|
||||||
"condition": PropertyDefiner.getControllingCondition(m,
|
"condition": PropertyDefiner.getControllingCondition(m,
|
||||||
descriptor),
|
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)
|
||||||
})
|
})
|
||||||
break
|
|
||||||
|
|
||||||
if not static:
|
if not static:
|
||||||
stringifier = descriptor.operations['Stringifier']
|
stringifier = descriptor.operations['Stringifier']
|
||||||
|
@ -13008,6 +13026,7 @@ class CGForwardDeclarations(CGWrapper):
|
||||||
# arguments to helper functions, and they'll need to be forward
|
# arguments to helper functions, and they'll need to be forward
|
||||||
# declared in the header.
|
# declared in the header.
|
||||||
if d.interface.maplikeOrSetlikeOrIterable:
|
if d.interface.maplikeOrSetlikeOrIterable:
|
||||||
|
if d.interface.maplikeOrSetlikeOrIterable.hasKeyType():
|
||||||
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.keyType,
|
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.keyType,
|
||||||
config)
|
config)
|
||||||
if d.interface.maplikeOrSetlikeOrIterable.hasValueType():
|
if d.interface.maplikeOrSetlikeOrIterable.hasValueType():
|
||||||
|
@ -15735,6 +15754,31 @@ class CGIterableMethodGenerator(CGGeneric):
|
||||||
using CGCallGenerator.
|
using CGCallGenerator.
|
||||||
"""
|
"""
|
||||||
def __init__(self, descriptor, iterable, methodName):
|
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(
|
CGGeneric.__init__(self, fill(
|
||||||
"""
|
"""
|
||||||
typedef ${iterClass} itrType;
|
typedef ${iterClass} itrType;
|
||||||
|
|
|
@ -893,8 +893,5 @@ def getAllTypes(descriptors, dictionaries, callbacks):
|
||||||
def iteratorNativeType(descriptor):
|
def iteratorNativeType(descriptor):
|
||||||
assert descriptor.interface.isIterable()
|
assert descriptor.interface.isIterable()
|
||||||
iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
|
iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
|
||||||
if iterableDecl.valueType is None:
|
assert iterableDecl.isPairIterator()
|
||||||
iterClass = "OneTypeIterableIterator"
|
return "mozilla::dom::IterableIterator<%s>" % descriptor.nativeType
|
||||||
else:
|
|
||||||
iterClass = "TwoTypeIterableIterator"
|
|
||||||
return "mozilla::dom::%s<%s>" % (iterClass, 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_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_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_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
|
* The IterableIterator class is used for WebIDL interfaces that have a
|
||||||
* iterable<> member defined. It handles the ES6 Iterator-like functions that
|
* iterable<> member defined with two types (so a pair iterator). It handles
|
||||||
* are generated for the iterable interface.
|
* the ES6 Iterator-like functions that are generated for the iterable
|
||||||
|
* interface.
|
||||||
*
|
*
|
||||||
* For iterable interfaces, the implementation class will need to
|
* For iterable interfaces with a pair iterator, the implementation class will
|
||||||
* implement these two functions:
|
* need to implement these two functions:
|
||||||
*
|
*
|
||||||
* - size_t GetIterableLength()
|
* - size_t GetIterableLength()
|
||||||
* - Returns the number of elements available to iterate over
|
* - Returns the number of elements available to iterate over
|
||||||
* - [type] GetValueAtIndex(size_t index)
|
* - [type] GetValueAtIndex(size_t index)
|
||||||
* - Returns the value at the requested 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)
|
* - [type] GetKeyAtIndex(size_t index)
|
||||||
* - Returns the key at the requested index
|
* - Returns the key at the requested index
|
||||||
*
|
*
|
||||||
|
@ -60,13 +58,77 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class IterableIterator : public IterableIteratorBase
|
class IterableIterator final : public IterableIteratorBase
|
||||||
{
|
{
|
||||||
public:
|
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)
|
: mIterableObj(aIterableObj)
|
||||||
|
, mIteratorType(aIteratorType)
|
||||||
|
, mWrapFunc(aWrapFunc)
|
||||||
|
, mIndex(0)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mIterableObj);
|
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:
|
protected:
|
||||||
|
@ -128,161 +190,6 @@ protected:
|
||||||
|
|
||||||
// Binding Implementation object that we're iterating over.
|
// Binding Implementation object that we're iterating over.
|
||||||
RefPtr<T> mIterableObj;
|
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.
|
// Tells whether this is a key, value, or entries iterator.
|
||||||
IterableIteratorType mIteratorType;
|
IterableIteratorType mIteratorType;
|
||||||
// Function pointer to binding-type-specific Wrap() call for this iterator.
|
// Function pointer to binding-type-specific Wrap() call for this iterator.
|
||||||
|
|
|
@ -1089,7 +1089,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
# We don't support consequential unforgeable interfaces. Need to check
|
# 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.
|
# it's consequential.
|
||||||
if self.getExtendedAttribute("Unforgeable") and self.isConsequential():
|
if self.getExtendedAttribute("Unforgeable") and self.isConsequential():
|
||||||
raise WebIDLError(
|
raise WebIDLError(
|
||||||
|
@ -1108,6 +1108,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
self.identifier.name,
|
self.identifier.name,
|
||||||
locations)
|
locations)
|
||||||
|
|
||||||
|
indexedGetter = None
|
||||||
|
hasLengthAttribute = False
|
||||||
for member in self.members:
|
for member in self.members:
|
||||||
member.validate()
|
member.validate()
|
||||||
|
|
||||||
|
@ -1118,8 +1120,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
[self.location, member.location])
|
[self.location, member.location])
|
||||||
|
|
||||||
# Check that PutForwards refers to another attribute and that no
|
# 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.isAttr():
|
||||||
|
if (member.identifier.name == "length" and
|
||||||
|
member.type.isInteger()):
|
||||||
|
hasLengthAttribute = True
|
||||||
|
|
||||||
iface = self
|
iface = self
|
||||||
attr = member
|
attr = member
|
||||||
putForwards = attr.getExtendedAttribute("PutForwards")
|
putForwards = attr.getExtendedAttribute("PutForwards")
|
||||||
|
@ -1157,8 +1164,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
putForwards = attr.getExtendedAttribute("PutForwards")
|
putForwards = attr.getExtendedAttribute("PutForwards")
|
||||||
|
|
||||||
# Check that the name of an [Alias] doesn't conflict with an
|
# 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.isMethod():
|
||||||
|
if member.isGetter() and member.isIndexed():
|
||||||
|
indexedGetter = member
|
||||||
|
|
||||||
for alias in member.aliases:
|
for alias in member.aliases:
|
||||||
if self.isOnGlobalProtoChain():
|
if self.isOnGlobalProtoChain():
|
||||||
raise WebIDLError("[Alias] must not be used on a "
|
raise WebIDLError("[Alias] must not be used on a "
|
||||||
|
@ -1219,6 +1229,35 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
"exposed conditionally",
|
"exposed conditionally",
|
||||||
[self.location])
|
[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):
|
def isInterface(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -3408,7 +3447,10 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
|
|
||||||
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
|
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
|
||||||
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
|
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
|
||||||
|
if keyType is not None:
|
||||||
assert isinstance(keyType, IDLType)
|
assert isinstance(keyType, IDLType)
|
||||||
|
else:
|
||||||
|
assert valueType is not None
|
||||||
assert ifaceType in ['maplike', 'setlike', 'iterable']
|
assert ifaceType in ['maplike', 'setlike', 'iterable']
|
||||||
if valueType is not None:
|
if valueType is not None:
|
||||||
assert isinstance(valueType, IDLType)
|
assert isinstance(valueType, IDLType)
|
||||||
|
@ -3427,6 +3469,9 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
def isIterable(self):
|
def isIterable(self):
|
||||||
return self.maplikeOrSetlikeOrIterableType == "iterable"
|
return self.maplikeOrSetlikeOrIterableType == "iterable"
|
||||||
|
|
||||||
|
def hasKeyType(self):
|
||||||
|
return self.keyType is not None
|
||||||
|
|
||||||
def hasValueType(self):
|
def hasValueType(self):
|
||||||
return self.valueType is not None
|
return self.valueType is not None
|
||||||
|
|
||||||
|
@ -3451,7 +3496,8 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
[self.location, member.location])
|
[self.location, member.location])
|
||||||
|
|
||||||
def addMethod(self, name, members, allowExistingOperations, returnType, args=[],
|
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.
|
Create an IDLMethod based on the parameters passed in.
|
||||||
|
|
||||||
|
@ -3511,16 +3557,20 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
if newObject:
|
if newObject:
|
||||||
method.addExtendedAttributes(
|
method.addExtendedAttributes(
|
||||||
[IDLExtendedAttribute(self.location, ("NewObject",))])
|
[IDLExtendedAttribute(self.location, ("NewObject",))])
|
||||||
|
if isIteratorAlias:
|
||||||
|
method.addExtendedAttributes(
|
||||||
|
[IDLExtendedAttribute(self.location, ("Alias", "@@iterator"))])
|
||||||
members.append(method)
|
members.append(method)
|
||||||
|
|
||||||
def resolve(self, parentScope):
|
def resolve(self, parentScope):
|
||||||
|
if self.keyType:
|
||||||
self.keyType.resolveType(parentScope)
|
self.keyType.resolveType(parentScope)
|
||||||
if self.valueType:
|
if self.valueType:
|
||||||
self.valueType.resolveType(parentScope)
|
self.valueType.resolveType(parentScope)
|
||||||
|
|
||||||
def finish(self, scope):
|
def finish(self, scope):
|
||||||
IDLInterfaceMember.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)
|
t = self.keyType.complete(scope)
|
||||||
|
|
||||||
assert not isinstance(t, IDLUnresolvedType)
|
assert not isinstance(t, IDLUnresolvedType)
|
||||||
|
@ -3542,9 +3592,23 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
IDLInterfaceMember.handleExtendedAttribute(self, attr)
|
IDLInterfaceMember.handleExtendedAttribute(self, attr)
|
||||||
|
|
||||||
def _getDependentObjects(self):
|
def _getDependentObjects(self):
|
||||||
|
deps = set()
|
||||||
|
if self.keyType:
|
||||||
|
deps.add(self.keyType)
|
||||||
if self.valueType:
|
if self.valueType:
|
||||||
return set([self.keyType, self.valueType])
|
deps.add(self.valueType)
|
||||||
return set([self.keyType])
|
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
|
# Iterable adds ES6 iterator style functions and traits
|
||||||
# (keys/values/entries/@@iterator) to an interface.
|
# (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
|
we generate our functions as if they were part of the interface
|
||||||
specification during parsing.
|
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()
|
# object entries()
|
||||||
self.addMethod("entries", members, False, self.iteratorType,
|
self.addMethod("entries", members, False, self.iteratorType,
|
||||||
affectsNothing=True, newObject=True)
|
affectsNothing=True, newObject=True,
|
||||||
|
isIteratorAlias=True)
|
||||||
# object keys()
|
# object keys()
|
||||||
self.addMethod("keys", members, False, self.iteratorType,
|
self.addMethod("keys", members, False, self.iteratorType,
|
||||||
affectsNothing=True, newObject=True)
|
affectsNothing=True, newObject=True)
|
||||||
|
@ -3575,6 +3645,17 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||||
self.addMethod("values", members, False, self.iteratorType,
|
self.addMethod("values", members, False, self.iteratorType,
|
||||||
affectsNothing=True, newObject=True)
|
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.
|
# MaplikeOrSetlike adds ES6 map-or-set-like traits to an interface.
|
||||||
class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
||||||
|
|
||||||
|
@ -3611,26 +3692,17 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
||||||
|
|
||||||
# object entries()
|
# object entries()
|
||||||
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||||
affectsNothing=True)
|
affectsNothing=True, isIteratorAlias=self.isMaplike())
|
||||||
# object keys()
|
# object keys()
|
||||||
self.addMethod("keys", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
self.addMethod("keys", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||||
affectsNothing=True)
|
affectsNothing=True)
|
||||||
# object values()
|
# object values()
|
||||||
self.addMethod("values", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
self.addMethod("values", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||||
affectsNothing=True)
|
affectsNothing=True, isIteratorAlias=self.isSetlike())
|
||||||
|
|
||||||
# void forEach(callback(valueType, keyType), thisVal)
|
# 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],
|
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||||
foreachArguments)
|
self.getForEachArguments())
|
||||||
|
|
||||||
def getKeyArg():
|
def getKeyArg():
|
||||||
return IDLArgument(self.location,
|
return IDLArgument(self.location,
|
||||||
|
@ -5436,10 +5508,13 @@ class Parser(Tokenizer):
|
||||||
location = self.getLocation(p, 2)
|
location = self.getLocation(p, 2)
|
||||||
identifier = IDLUnresolvedIdentifier(location, "__iterable",
|
identifier = IDLUnresolvedIdentifier(location, "__iterable",
|
||||||
allowDoubleUnderscore=True)
|
allowDoubleUnderscore=True)
|
||||||
keyType = p[3]
|
|
||||||
valueType = None
|
|
||||||
if (len(p) > 6):
|
if (len(p) > 6):
|
||||||
|
keyType = p[3]
|
||||||
valueType = p[5]
|
valueType = p[5]
|
||||||
|
else:
|
||||||
|
keyType = None
|
||||||
|
valueType = p[3]
|
||||||
|
|
||||||
p[0] = IDLIterable(location, identifier, keyType, valueType, self.globalScope())
|
p[0] = IDLIterable(location, identifier, keyType, valueType, self.globalScope())
|
||||||
|
|
||||||
def p_Setlike(self, p):
|
def p_Setlike(self, p):
|
||||||
|
@ -6509,7 +6584,7 @@ class Parser(Tokenizer):
|
||||||
if isinstance(m, IDLIterable):
|
if isinstance(m, IDLIterable):
|
||||||
iterable = m
|
iterable = m
|
||||||
break
|
break
|
||||||
if iterable:
|
if iterable and iterable.isPairIterator():
|
||||||
def simpleExtendedAttr(str):
|
def simpleExtendedAttr(str):
|
||||||
return IDLExtendedAttribute(iface.location, (str, ))
|
return IDLExtendedAttribute(iface.location, (str, ))
|
||||||
nextMethod = IDLMethod(
|
nextMethod = IDLMethod(
|
||||||
|
|
|
@ -55,17 +55,22 @@ TestInterfaceIterableSingle::GetParentObject() const
|
||||||
return mParent;
|
return mParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
uint32_t
|
||||||
TestInterfaceIterableSingle::GetIterableLength() const
|
TestInterfaceIterableSingle::Length() const
|
||||||
{
|
{
|
||||||
return mValues.Length();
|
return mValues.Length();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
int32_t
|
||||||
TestInterfaceIterableSingle::GetValueAtIndex(uint32_t index) const
|
TestInterfaceIterableSingle::IndexedGetter(uint32_t aIndex, bool& aFound) const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(index < mValues.Length());
|
if (aIndex >= mValues.Length()) {
|
||||||
return mValues.ElementAt(index);
|
aFound = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFound = true;
|
||||||
|
return mValues[aIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -36,12 +36,13 @@ public:
|
||||||
static already_AddRefed<TestInterfaceIterableSingle>
|
static already_AddRefed<TestInterfaceIterableSingle>
|
||||||
Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
|
Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
|
||||||
|
|
||||||
size_t GetIterableLength() const;
|
uint32_t Length() const;
|
||||||
uint32_t GetValueAtIndex(uint32_t aIndex) const;
|
int32_t IndexedGetter(uint32_t aIndex, bool& aFound) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~TestInterfaceIterableSingle() {}
|
virtual ~TestInterfaceIterableSingle() {}
|
||||||
nsCOMPtr<nsPIDOMWindow> mParent;
|
nsCOMPtr<nsPIDOMWindow> mParent;
|
||||||
nsTArray<uint32_t> mValues;
|
nsTArray<int32_t> mValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -39,6 +39,12 @@ ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
|
||||||
|
|
||||||
#undef ANCHOR_ELEMENT_FLAG_BIT
|
#undef ANCHOR_ELEMENT_FLAG_BIT
|
||||||
|
|
||||||
|
// static
|
||||||
|
const DOMTokenListSupportedToken HTMLAnchorElement::sSupportedRelValues[] = {
|
||||||
|
"noreferrer",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
HTMLAnchorElement::~HTMLAnchorElement()
|
HTMLAnchorElement::~HTMLAnchorElement()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -302,7 +308,7 @@ nsDOMTokenList*
|
||||||
HTMLAnchorElement::RelList()
|
HTMLAnchorElement::RelList()
|
||||||
{
|
{
|
||||||
if (!mRelList) {
|
if (!mRelList) {
|
||||||
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel);
|
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues);
|
||||||
}
|
}
|
||||||
return mRelList;
|
return mRelList;
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,6 +227,8 @@ public:
|
||||||
GetHref(aResult);
|
GetHref(aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DOMTokenListSupportedToken sSupportedRelValues[];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~HTMLAnchorElement();
|
virtual ~HTMLAnchorElement();
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "mozilla/dom/HTMLAreaElement.h"
|
#include "mozilla/dom/HTMLAreaElement.h"
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||||
#include "mozilla/dom/HTMLAreaElementBinding.h"
|
#include "mozilla/dom/HTMLAreaElementBinding.h"
|
||||||
#include "mozilla/EventDispatcher.h"
|
#include "mozilla/EventDispatcher.h"
|
||||||
#include "mozilla/EventStates.h"
|
#include "mozilla/EventStates.h"
|
||||||
|
@ -122,7 +123,8 @@ nsDOMTokenList*
|
||||||
HTMLAreaElement::RelList()
|
HTMLAreaElement::RelList()
|
||||||
{
|
{
|
||||||
if (!mRelList) {
|
if (!mRelList) {
|
||||||
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel);
|
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel,
|
||||||
|
HTMLAnchorElement::sSupportedRelValues);
|
||||||
}
|
}
|
||||||
return mRelList;
|
return mRelList;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,15 @@ NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame)
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
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,
|
HTMLIFrameElement::HTMLIFrameElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
|
||||||
FromParser aFromParser)
|
FromParser aFromParser)
|
||||||
: nsGenericHTMLFrameElement(aNodeInfo, aFromParser)
|
: nsGenericHTMLFrameElement(aNodeInfo, aFromParser)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "nsGenericHTMLFrameElement.h"
|
#include "nsGenericHTMLFrameElement.h"
|
||||||
#include "nsIDOMHTMLIFrameElement.h"
|
#include "nsIDOMHTMLIFrameElement.h"
|
||||||
#include "nsDOMSettableTokenList.h"
|
#include "nsDOMTokenList.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -84,9 +84,9 @@ public:
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::name, aName, aError);
|
SetHTMLAttr(nsGkAtoms::name, aName, aError);
|
||||||
}
|
}
|
||||||
nsDOMSettableTokenList* Sandbox()
|
nsDOMTokenList* Sandbox()
|
||||||
{
|
{
|
||||||
return GetTokenList(nsGkAtoms::sandbox);
|
return GetTokenList(nsGkAtoms::sandbox, sSupportedSandboxTokens);
|
||||||
}
|
}
|
||||||
bool AllowFullscreen() const
|
bool AllowFullscreen() const
|
||||||
{
|
{
|
||||||
|
@ -202,6 +202,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||||
nsRuleData* aData);
|
nsRuleData* aData);
|
||||||
|
|
||||||
|
static const DOMTokenListSupportedToken sSupportedSandboxTokens[];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
#include "nsStyleConsts.h"
|
#include "nsStyleConsts.h"
|
||||||
|
#include "nsStyleLinkElement.h"
|
||||||
#include "nsUnicharUtils.h"
|
#include "nsUnicharUtils.h"
|
||||||
|
|
||||||
#define LINK_ELEMENT_FLAG_BIT(n_) \
|
#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*
|
nsDOMTokenList*
|
||||||
HTMLLinkElement::RelList()
|
HTMLLinkElement::RelList()
|
||||||
{
|
{
|
||||||
if (!mRelList) {
|
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;
|
return mRelList;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ public:
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::hreflang, aHreflang, aRv);
|
SetHTMLAttr(nsGkAtoms::hreflang, aHreflang, aRv);
|
||||||
}
|
}
|
||||||
nsDOMSettableTokenList* Sizes()
|
nsDOMTokenList* Sizes()
|
||||||
{
|
{
|
||||||
return GetTokenList(nsGkAtoms::sizes);
|
return GetTokenList(nsGkAtoms::sizes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "mozilla/dom/HTMLMenuItemElementBinding.h"
|
#include "mozilla/dom/HTMLMenuItemElementBinding.h"
|
||||||
#include "nsAttrValueInlines.h"
|
#include "nsAttrValueInlines.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsDOMTokenList.h"
|
||||||
|
|
||||||
|
|
||||||
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(MenuItem)
|
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(MenuItem)
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "mozilla/dom/HTMLFormElement.h"
|
#include "mozilla/dom/HTMLFormElement.h"
|
||||||
#include "mozilla/dom/HTMLOutputElementBinding.h"
|
#include "mozilla/dom/HTMLOutputElementBinding.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsDOMSettableTokenList.h"
|
|
||||||
#include "nsFormSubmission.h"
|
#include "nsFormSubmission.h"
|
||||||
|
|
||||||
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output)
|
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output)
|
||||||
|
@ -166,11 +165,11 @@ HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsDOMSettableTokenList*
|
nsDOMTokenList*
|
||||||
HTMLOutputElement::HtmlFor()
|
HTMLOutputElement::HtmlFor()
|
||||||
{
|
{
|
||||||
if (!mTokenList) {
|
if (!mTokenList) {
|
||||||
mTokenList = new nsDOMSettableTokenList(this, nsGkAtoms::_for);
|
mTokenList = new nsDOMTokenList(this, nsGkAtoms::_for);
|
||||||
}
|
}
|
||||||
return mTokenList;
|
return mTokenList;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
// WebIDL
|
// WebIDL
|
||||||
nsDOMSettableTokenList* HtmlFor();
|
nsDOMTokenList* HtmlFor();
|
||||||
// nsGenericHTMLFormElement::GetForm is fine.
|
// nsGenericHTMLFormElement::GetForm is fine.
|
||||||
void GetName(nsAString& aName)
|
void GetName(nsAString& aName)
|
||||||
{
|
{
|
||||||
|
@ -108,7 +108,7 @@ protected:
|
||||||
ValueModeFlag mValueModeFlag;
|
ValueModeFlag mValueModeFlag;
|
||||||
bool mIsDoneAddingChildren;
|
bool mIsDoneAddingChildren;
|
||||||
nsString mDefaultValue;
|
nsString mDefaultValue;
|
||||||
RefPtr<nsDOMSettableTokenList> mTokenList;
|
RefPtr<nsDOMTokenList> mTokenList;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsGenericHTMLElement.h"
|
#include "nsGenericHTMLElement.h"
|
||||||
#include "nsVariant.h"
|
#include "nsVariant.h"
|
||||||
#include "nsDOMSettableTokenList.h"
|
#include "nsDOMTokenList.h"
|
||||||
#include "nsAttrValue.h"
|
#include "nsAttrValue.h"
|
||||||
#include "nsWrapperCacheInlines.h"
|
#include "nsWrapperCacheInlines.h"
|
||||||
#include "mozilla/dom/HTMLPropertiesCollectionBinding.h"
|
#include "mozilla/dom/HTMLPropertiesCollectionBinding.h"
|
||||||
|
|
|
@ -164,14 +164,15 @@ SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch)
|
||||||
return;
|
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;
|
nsAutoString href;
|
||||||
child->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
|
child->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> newBaseURI;
|
nsCOMPtr<nsIURI> newBaseURI;
|
||||||
nsContentUtils::NewURIWithDocumentCharset(
|
nsContentUtils::NewURIWithDocumentCharset(
|
||||||
getter_AddRefs(newBaseURI), href, aDocument,
|
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
|
// Try to set our base URI. If that fails, try to set base URI to null
|
||||||
nsresult rv = aDocument->SetBaseURI(newBaseURI);
|
nsresult rv = aDocument->SetBaseURI(newBaseURI);
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
{
|
{
|
||||||
SetUnsignedIntAttr(nsGkAtoms::rowspan, aRowSpan, aError);
|
SetUnsignedIntAttr(nsGkAtoms::rowspan, aRowSpan, aError);
|
||||||
}
|
}
|
||||||
//already_AddRefed<nsDOMSettableTokenList> Headers() const;
|
//already_AddRefed<nsDOMTokenList> Headers() const;
|
||||||
void GetHeaders(DOMString& aHeaders)
|
void GetHeaders(DOMString& aHeaders)
|
||||||
{
|
{
|
||||||
GetHTMLAttr(nsGkAtoms::headers, aHeaders);
|
GetHTMLAttr(nsGkAtoms::headers, aHeaders);
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
|
|
||||||
#include "HTMLPropertiesCollection.h"
|
#include "HTMLPropertiesCollection.h"
|
||||||
#include "nsVariant.h"
|
#include "nsVariant.h"
|
||||||
#include "nsDOMSettableTokenList.h"
|
#include "nsDOMTokenList.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "mozilla/dom/ValidityState.h"
|
#include "mozilla/dom/ValidityState.h"
|
||||||
#include "mozilla/dom/ElementInlines.h"
|
#include "mozilla/dom/ElementInlines.h"
|
||||||
|
|
||||||
class nsDOMSettableTokenList;
|
class nsDOMTokenList;
|
||||||
class nsIDOMHTMLMenuElement;
|
class nsIDOMHTMLMenuElement;
|
||||||
class nsIEditor;
|
class nsIEditor;
|
||||||
class nsIFormControlFrame;
|
class nsIFormControlFrame;
|
||||||
|
@ -104,7 +104,7 @@ public:
|
||||||
{
|
{
|
||||||
SetHTMLBoolAttr(nsGkAtoms::itemscope, aItemScope, aError);
|
SetHTMLBoolAttr(nsGkAtoms::itemscope, aItemScope, aError);
|
||||||
}
|
}
|
||||||
nsDOMSettableTokenList* ItemType()
|
nsDOMTokenList* ItemType()
|
||||||
{
|
{
|
||||||
return GetTokenList(nsGkAtoms::itemtype);
|
return GetTokenList(nsGkAtoms::itemtype);
|
||||||
}
|
}
|
||||||
|
@ -116,11 +116,11 @@ public:
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::itemid, aItemID, aError);
|
SetHTMLAttr(nsGkAtoms::itemid, aItemID, aError);
|
||||||
}
|
}
|
||||||
nsDOMSettableTokenList* ItemRef()
|
nsDOMTokenList* ItemRef()
|
||||||
{
|
{
|
||||||
return GetTokenList(nsGkAtoms::itemref);
|
return GetTokenList(nsGkAtoms::itemref);
|
||||||
}
|
}
|
||||||
nsDOMSettableTokenList* ItemProp()
|
nsDOMTokenList* ItemProp()
|
||||||
{
|
{
|
||||||
return GetTokenList(nsGkAtoms::itemprop);
|
return GetTokenList(nsGkAtoms::itemprop);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ interface nsIDOMHTMLElement : nsIDOMElement
|
||||||
attribute nsIVariant itemType;
|
attribute nsIVariant itemType;
|
||||||
attribute DOMString itemId;
|
attribute DOMString itemId;
|
||||||
readonly attribute nsISupports properties;
|
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.
|
// PutForwards, so we express them as nsIVariants to deal with this.
|
||||||
attribute nsIVariant itemValue;
|
attribute nsIVariant itemValue;
|
||||||
attribute nsIVariant itemProp;
|
attribute nsIVariant itemProp;
|
||||||
|
|
|
@ -79,7 +79,7 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
|
||||||
return aPlane.mWidth <= PlanarYCbCrImage::MAX_DIMENSION &&
|
return aPlane.mWidth <= PlanarYCbCrImage::MAX_DIMENSION &&
|
||||||
aPlane.mHeight <= PlanarYCbCrImage::MAX_DIMENSION &&
|
aPlane.mHeight <= PlanarYCbCrImage::MAX_DIMENSION &&
|
||||||
aPlane.mWidth * aPlane.mHeight < MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
|
aPlane.mWidth * aPlane.mHeight < MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
|
||||||
aPlane.mStride > 0;
|
aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
|
|
@ -460,6 +460,18 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem,
|
||||||
float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS];
|
float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS];
|
||||||
domItem->ToSVGPathSegEncodedData(segAsRaw);
|
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,
|
if (!InternalList().mData.ReplaceElementsAt(internalIndex, 1 + oldArgCount,
|
||||||
segAsRaw, 1 + newArgCount,
|
segAsRaw, 1 + newArgCount,
|
||||||
fallible)) {
|
fallible)) {
|
||||||
|
@ -474,8 +486,13 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem,
|
||||||
|
|
||||||
int32_t delta = newArgCount - oldArgCount;
|
int32_t delta = newArgCount - oldArgCount;
|
||||||
if (delta != 0) {
|
if (delta != 0) {
|
||||||
for (uint32_t i = aIndex + 1; i < LengthNoFlush(); ++i) {
|
// Sync up the internal indexes of all ItemProxys that come after aIndex:
|
||||||
mItems[i].mInternalDataIndex += delta;
|
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]
|
[Throws]
|
||||||
void remove(DOMString... tokens);
|
void remove(DOMString... tokens);
|
||||||
[Throws]
|
[Throws]
|
||||||
|
void replace(DOMString token, DOMString newToken);
|
||||||
|
[Throws]
|
||||||
boolean toggle(DOMString token, optional boolean force);
|
boolean toggle(DOMString token, optional boolean force);
|
||||||
|
[Throws]
|
||||||
|
boolean supports(DOMString token);
|
||||||
|
[SetterThrows]
|
||||||
|
attribute DOMString value;
|
||||||
stringifier DOMString ();
|
stringifier DOMString ();
|
||||||
|
iterable<DOMString?>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@ interface Element : Node {
|
||||||
attribute DOMString id;
|
attribute DOMString id;
|
||||||
[Pure]
|
[Pure]
|
||||||
attribute DOMString className;
|
attribute DOMString className;
|
||||||
[Constant]
|
[Constant, PutForwards=value]
|
||||||
readonly attribute DOMTokenList classList;
|
readonly attribute DOMTokenList classList;
|
||||||
|
|
||||||
[SameObject]
|
[SameObject]
|
||||||
|
|
|
@ -23,6 +23,7 @@ interface HTMLAnchorElement : HTMLElement {
|
||||||
attribute DOMString rel;
|
attribute DOMString rel;
|
||||||
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
||||||
attribute DOMString referrerPolicy;
|
attribute DOMString referrerPolicy;
|
||||||
|
[PutForwards=value]
|
||||||
readonly attribute DOMTokenList relList;
|
readonly attribute DOMTokenList relList;
|
||||||
[SetterThrows]
|
[SetterThrows]
|
||||||
attribute DOMString hreflang;
|
attribute DOMString hreflang;
|
||||||
|
|
|
@ -30,6 +30,7 @@ interface HTMLAreaElement : HTMLElement {
|
||||||
attribute DOMString rel;
|
attribute DOMString rel;
|
||||||
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
||||||
attribute DOMString referrerPolicy;
|
attribute DOMString referrerPolicy;
|
||||||
|
[PutForwards=value]
|
||||||
readonly attribute DOMTokenList relList;
|
readonly attribute DOMTokenList relList;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,11 @@ interface HTMLElement : Element {
|
||||||
// microdata
|
// microdata
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute boolean itemScope;
|
attribute boolean itemScope;
|
||||||
[PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemType;
|
[PutForwards=value,Constant] readonly attribute DOMTokenList itemType;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute DOMString itemId;
|
attribute DOMString itemId;
|
||||||
[PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemRef;
|
[PutForwards=value,Constant] readonly attribute DOMTokenList itemRef;
|
||||||
[PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemProp;
|
[PutForwards=value,Constant] readonly attribute DOMTokenList itemProp;
|
||||||
[Constant]
|
[Constant]
|
||||||
readonly attribute HTMLPropertiesCollection properties;
|
readonly attribute HTMLPropertiesCollection properties;
|
||||||
[Throws]
|
[Throws]
|
||||||
|
@ -54,7 +54,7 @@ interface HTMLElement : Element {
|
||||||
readonly attribute DOMString accessKeyLabel;
|
readonly attribute DOMString accessKeyLabel;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute boolean draggable;
|
attribute boolean draggable;
|
||||||
//[PutForwards=value] readonly attribute DOMSettableTokenList dropzone;
|
//[PutForwards=value] readonly attribute DOMTokenList dropzone;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute DOMString contentEditable;
|
attribute DOMString contentEditable;
|
||||||
[Pure]
|
[Pure]
|
||||||
|
|
|
@ -18,7 +18,7 @@ interface HTMLIFrameElement : HTMLElement {
|
||||||
attribute DOMString srcdoc;
|
attribute DOMString srcdoc;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute DOMString name;
|
attribute DOMString name;
|
||||||
[PutForwards=value] readonly attribute DOMSettableTokenList sandbox;
|
[PutForwards=value] readonly attribute DOMTokenList sandbox;
|
||||||
// attribute boolean seamless;
|
// attribute boolean seamless;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute boolean allowFullscreen;
|
attribute boolean allowFullscreen;
|
||||||
|
|
|
@ -21,6 +21,7 @@ interface HTMLLinkElement : HTMLElement {
|
||||||
attribute DOMString? crossOrigin;
|
attribute DOMString? crossOrigin;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute DOMString rel;
|
attribute DOMString rel;
|
||||||
|
[PutForwards=value]
|
||||||
readonly attribute DOMTokenList relList;
|
readonly attribute DOMTokenList relList;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute DOMString media;
|
attribute DOMString media;
|
||||||
|
@ -28,7 +29,7 @@ interface HTMLLinkElement : HTMLElement {
|
||||||
attribute DOMString hreflang;
|
attribute DOMString hreflang;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute DOMString type;
|
attribute DOMString type;
|
||||||
[PutForwards=value] readonly attribute DOMSettableTokenList sizes;
|
[PutForwards=value] readonly attribute DOMTokenList sizes;
|
||||||
};
|
};
|
||||||
HTMLLinkElement implements LinkStyle;
|
HTMLLinkElement implements LinkStyle;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
// http://www.whatwg.org/specs/web-apps/current-work/#the-output-element
|
// http://www.whatwg.org/specs/web-apps/current-work/#the-output-element
|
||||||
interface HTMLOutputElement : HTMLElement {
|
interface HTMLOutputElement : HTMLElement {
|
||||||
[PutForwards=value, Constant]
|
[PutForwards=value, Constant]
|
||||||
readonly attribute DOMSettableTokenList htmlFor;
|
readonly attribute DOMTokenList htmlFor;
|
||||||
readonly attribute HTMLFormElement? form;
|
readonly attribute HTMLFormElement? form;
|
||||||
[SetterThrows, Pure]
|
[SetterThrows, Pure]
|
||||||
attribute DOMString name;
|
attribute DOMString name;
|
||||||
|
|
|
@ -16,7 +16,7 @@ interface HTMLTableCellElement : HTMLElement {
|
||||||
attribute unsigned long colSpan;
|
attribute unsigned long colSpan;
|
||||||
[SetterThrows]
|
[SetterThrows]
|
||||||
attribute unsigned long rowSpan;
|
attribute unsigned long rowSpan;
|
||||||
//[PutForwards=value] readonly attribute DOMSettableTokenList headers;
|
//[PutForwards=value] readonly attribute DOMTokenList headers;
|
||||||
[SetterThrows]
|
[SetterThrows]
|
||||||
attribute DOMString headers;
|
attribute DOMString headers;
|
||||||
readonly attribute long cellIndex;
|
readonly attribute long cellIndex;
|
||||||
|
|
|
@ -13,4 +13,5 @@
|
||||||
interface NodeList {
|
interface NodeList {
|
||||||
getter Node? item(unsigned long index);
|
getter Node? item(unsigned long index);
|
||||||
readonly attribute unsigned long length;
|
readonly attribute unsigned long length;
|
||||||
|
iterable<Node?>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,6 +50,8 @@ interface TestInterfaceSetlikeNode {
|
||||||
Pref="dom.expose_test_interfaces"]
|
Pref="dom.expose_test_interfaces"]
|
||||||
interface TestInterfaceIterableSingle {
|
interface TestInterfaceIterableSingle {
|
||||||
iterable<long>;
|
iterable<long>;
|
||||||
|
getter long(unsigned long index);
|
||||||
|
readonly attribute unsigned long length;
|
||||||
};
|
};
|
||||||
|
|
||||||
[Constructor(),
|
[Constructor(),
|
||||||
|
|
|
@ -132,7 +132,6 @@ WEBIDL_FILES = [
|
||||||
'DOMRect.webidl',
|
'DOMRect.webidl',
|
||||||
'DOMRectList.webidl',
|
'DOMRectList.webidl',
|
||||||
'DOMRequest.webidl',
|
'DOMRequest.webidl',
|
||||||
'DOMSettableTokenList.webidl',
|
|
||||||
'DOMStringList.webidl',
|
'DOMStringList.webidl',
|
||||||
'DOMStringMap.webidl',
|
'DOMStringMap.webidl',
|
||||||
'DOMTokenList.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(mEditorObservers)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget)
|
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_UNLINK_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEditor)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEditor)
|
||||||
|
|
|
@ -430,12 +430,15 @@ static void
|
||||||
CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
|
CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
|
||||||
const gfx::IntSize &aSize, int32_t aStride, int32_t aSkip)
|
const gfx::IntSize &aSize, int32_t aStride, int32_t aSkip)
|
||||||
{
|
{
|
||||||
if (!aSkip) {
|
|
||||||
// Fast path: planar input.
|
|
||||||
memcpy(aDst, aSrc, aSize.height * aStride);
|
|
||||||
} else {
|
|
||||||
int32_t height = aSize.height;
|
int32_t height = aSize.height;
|
||||||
int32_t width = aSize.width;
|
int32_t width = aSize.width;
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(width <= aStride);
|
||||||
|
|
||||||
|
if (!aSkip) {
|
||||||
|
// Fast path: planar input.
|
||||||
|
memcpy(aDst, aSrc, height * aStride);
|
||||||
|
} else {
|
||||||
for (int y = 0; y < height; ++y) {
|
for (int y = 0; y < height; ++y) {
|
||||||
const uint8_t *src = aSrc;
|
const uint8_t *src = aSrc;
|
||||||
uint8_t *dst = aDst;
|
uint8_t *dst = aDst;
|
||||||
|
@ -453,13 +456,11 @@ CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
|
||||||
bool
|
bool
|
||||||
RecyclingPlanarYCbCrImage::CopyData(const Data& aData)
|
RecyclingPlanarYCbCrImage::CopyData(const Data& aData)
|
||||||
{
|
{
|
||||||
mData = aData;
|
|
||||||
|
|
||||||
// update buffer size
|
// update buffer size
|
||||||
// Use uint32_t throughout to match AllocateBuffer's param and mBufferSize
|
// Use uint32_t throughout to match AllocateBuffer's param and mBufferSize
|
||||||
const auto checkedSize =
|
const auto checkedSize =
|
||||||
CheckedInt<uint32_t>(mData.mCbCrStride) * mData.mCbCrSize.height * 2 +
|
CheckedInt<uint32_t>(aData.mCbCrStride) * aData.mCbCrSize.height * 2 +
|
||||||
CheckedInt<uint32_t>(mData.mYStride) * mData.mYSize.height;
|
CheckedInt<uint32_t>(aData.mYStride) * aData.mYSize.height;
|
||||||
|
|
||||||
if (!checkedSize.isValid())
|
if (!checkedSize.isValid())
|
||||||
return false;
|
return false;
|
||||||
|
@ -468,22 +469,24 @@ RecyclingPlanarYCbCrImage::CopyData(const Data& aData)
|
||||||
|
|
||||||
// get new buffer
|
// get new buffer
|
||||||
mBuffer = AllocateBuffer(size);
|
mBuffer = AllocateBuffer(size);
|
||||||
if (!mBuffer)
|
if (MOZ_UNLIKELY(!mBuffer))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// update buffer size
|
// update buffer size
|
||||||
mBufferSize = size;
|
mBufferSize = size;
|
||||||
|
|
||||||
|
mData = aData;
|
||||||
mData.mYChannel = mBuffer.get();
|
mData.mYChannel = mBuffer.get();
|
||||||
mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
|
mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
|
||||||
mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
|
mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
|
||||||
|
mData.mYSkip = mData.mCbSkip = mData.mCrSkip = 0;
|
||||||
|
|
||||||
CopyPlane(mData.mYChannel, aData.mYChannel,
|
CopyPlane(mData.mYChannel, aData.mYChannel,
|
||||||
mData.mYSize, mData.mYStride, mData.mYSkip);
|
aData.mYSize, aData.mYStride, aData.mYSkip);
|
||||||
CopyPlane(mData.mCbChannel, aData.mCbChannel,
|
CopyPlane(mData.mCbChannel, aData.mCbChannel,
|
||||||
mData.mCbCrSize, mData.mCbCrStride, mData.mCbSkip);
|
aData.mCbCrSize, aData.mCbCrStride, aData.mCbSkip);
|
||||||
CopyPlane(mData.mCrChannel, aData.mCrChannel,
|
CopyPlane(mData.mCrChannel, aData.mCrChannel,
|
||||||
mData.mCbCrSize, mData.mCbCrStride, mData.mCrSkip);
|
aData.mCbCrSize, aData.mCbCrStride, aData.mCrSkip);
|
||||||
|
|
||||||
mSize = aData.mPicSize;
|
mSize = aData.mPicSize;
|
||||||
return true;
|
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
|
// The length of the output in UTF-16 code units never exceeds the length
|
||||||
// of the input in bytes.
|
// 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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -211,12 +211,21 @@ nsUnicodeToBIG5::GetMaxLength(const char16_t* aSrc,
|
||||||
int32_t aSrcLength,
|
int32_t aSrcLength,
|
||||||
int32_t* aDestLength)
|
int32_t* aDestLength)
|
||||||
{
|
{
|
||||||
*aDestLength = (aSrcLength * 2) +
|
mozilla::CheckedInt32 length = aSrcLength;
|
||||||
(mPendingTrail ? 1 : 0) +
|
length *= 2;
|
||||||
|
if (mPendingTrail) {
|
||||||
|
length += 1;
|
||||||
|
}
|
||||||
// If the lead ends up being paired, the bytes produced
|
// If the lead ends up being paired, the bytes produced
|
||||||
// are already included above.
|
// are already included above.
|
||||||
// If not, it produces a single '?'.
|
// If not, it produces a single '?'.
|
||||||
(mUtf16Lead ? 1 : 0);
|
if (mUtf16Lead) {
|
||||||
|
length += 1;
|
||||||
|
}
|
||||||
|
if (!length.isValid()) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
*aDestLength = length.value();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "nsBidiUtils.h"
|
#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 ARABIC_TO_HINDI_DIGIT_INCREMENT (START_HINDI_DIGITS - START_ARABIC_DIGITS)
|
||||||
#define PERSIAN_TO_HINDI_DIGIT_INCREMENT (START_HINDI_DIGITS - START_FARSI_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)
|
#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;
|
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
|
// This is used to determine whether a string has right-to-left characters
|
||||||
// right-to-left characters. To simplify things, anything that could be a
|
// that mean it will require bidi processing.
|
||||||
// surrogate or RTL presentation form is covered just by testing >= 0xD800).
|
const char16_t* cp = aText;
|
||||||
// It's fine to enable bidi in rare cases where it actually isn't needed.
|
const char16_t* end = cp + aLength;
|
||||||
int32_t length = aString.Length();
|
while (cp < end) {
|
||||||
for (int32_t i = 0; i < length; i++) {
|
char16_t ch = *cp++;
|
||||||
char16_t ch = aString.CharAt(i);
|
if (ch < mozilla::kMinRTLChar) {
|
||||||
if (ch >= 0xD800 || IS_IN_BMP_RTL_BLOCK(ch)) {
|
continue;
|
||||||
|
}
|
||||||
|
if (UTF16_CODE_UNIT_IS_BIDI(ch) || IsBidiControlRTL(ch)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,10 +110,19 @@ typedef enum nsCharType nsCharType;
|
||||||
* Return false, otherwise
|
* Return false, otherwise
|
||||||
*/
|
*/
|
||||||
#define LRM_CHAR 0x200e
|
#define LRM_CHAR 0x200e
|
||||||
|
#define RLM_CHAR 0x200f
|
||||||
|
|
||||||
#define LRE_CHAR 0x202a
|
#define LRE_CHAR 0x202a
|
||||||
|
#define RLE_CHAR 0x202b
|
||||||
|
#define PDF_CHAR 0x202c
|
||||||
|
#define LRO_CHAR 0x202d
|
||||||
#define RLO_CHAR 0x202e
|
#define RLO_CHAR 0x202e
|
||||||
|
|
||||||
#define LRI_CHAR 0x2066
|
#define LRI_CHAR 0x2066
|
||||||
|
#define RLI_CHAR 0x2067
|
||||||
|
#define FSI_CHAR 0x2068
|
||||||
#define PDI_CHAR 0x2069
|
#define PDI_CHAR 0x2069
|
||||||
|
|
||||||
#define ALM_CHAR 0x061C
|
#define ALM_CHAR 0x061C
|
||||||
inline bool IsBidiControl(uint32_t aChar) {
|
inline bool IsBidiControl(uint32_t aChar) {
|
||||||
return ((LRE_CHAR <= aChar && aChar <= RLO_CHAR) ||
|
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
|
* @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
|
// These values are shared with Preferences dialog
|
||||||
// ------------------
|
// ------------------
|
||||||
|
@ -248,6 +279,17 @@ typedef enum nsCharType nsCharType;
|
||||||
((0xfe70 <= (c)) && ((c) <= 0xfefc)))
|
((0xfe70 <= (c)) && ((c) <= 0xfefc)))
|
||||||
#define IS_IN_SMP_RTL_BLOCK(c) (((0x10800 <= (c)) && ((c) <= 0x10fff)) || \
|
#define IS_IN_SMP_RTL_BLOCK(c) (((0x10800 <= (c)) && ((c) <= 0x10fff)) || \
|
||||||
((0x1e800 <= (c)) && ((c) <= 0x1eFFF)))
|
((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)) || \
|
#define UCS2_CHAR_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \
|
||||||
(IS_RTL_PRESENTATION_FORM(c)))
|
(IS_RTL_PRESENTATION_FORM(c)))
|
||||||
#define UTF32_CHAR_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \
|
#define UTF32_CHAR_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \
|
||||||
|
|
|
@ -3761,7 +3761,6 @@ BytecodeEmitter::emitDestructuringDeclsWithEmitter(JSOp prologueOp, ParseNode* p
|
||||||
continue;
|
continue;
|
||||||
ParseNode* target = element;
|
ParseNode* target = element;
|
||||||
if (element->isKind(PNK_SPREAD)) {
|
if (element->isKind(PNK_SPREAD)) {
|
||||||
MOZ_ASSERT(element->pn_kid->isKind(PNK_NAME));
|
|
||||||
target = element->pn_kid;
|
target = element->pn_kid;
|
||||||
}
|
}
|
||||||
if (target->isKind(PNK_ASSIGN))
|
if (target->isKind(PNK_ASSIGN))
|
||||||
|
|
|
@ -4276,11 +4276,6 @@ Parser<FullParseHandler>::checkDestructuringArray(BindData<FullParseHandler>* da
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
target = element->pn_kid;
|
target = element->pn_kid;
|
||||||
|
|
||||||
if (handler.isUnparenthesizedDestructuringPattern(target)) {
|
|
||||||
report(ParseError, false, target, JSMSG_BAD_DESTRUCT_TARGET);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (handler.isUnparenthesizedAssignment(element)) {
|
} else if (handler.isUnparenthesizedAssignment(element)) {
|
||||||
target = element->pn_left;
|
target = element->pn_left;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -49,6 +49,23 @@ assertIterable([5,5,4,4],
|
||||||
it => { var [,,...rest] = it; return rest; },
|
it => { var [,,...rest] = it; return rest; },
|
||||||
[3,4]);
|
[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 arraycalls = 0;
|
||||||
var ArrayIterator = Array.prototype[Symbol.iterator];
|
var ArrayIterator = Array.prototype[Symbol.iterator];
|
||||||
Array.prototype[Symbol.iterator] = function () {
|
Array.prototype[Symbol.iterator] = function () {
|
||||||
|
@ -58,7 +75,11 @@ Array.prototype[Symbol.iterator] = function () {
|
||||||
// [...rest] should not call Array#@@iterator for the LHS
|
// [...rest] should not call Array#@@iterator for the LHS
|
||||||
var [...rest] = iterable;
|
var [...rest] = iterable;
|
||||||
assertEq(arraycalls, 0, 'calls to Array#@@iterator');
|
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
|
// loop `fn` a few times, to get it JIT-compiled
|
||||||
function loop(fn) {
|
function loop(fn) {
|
||||||
|
@ -67,7 +88,7 @@ function loop(fn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
loop(() => { doneafter = 4; var [a] = iterable; return a; });
|
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
|
// 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, ,] = []'), SyntaxError, 'trailing elision');
|
||||||
assertThrowsInstanceOf(() => new Function('[a, ...b, c] = []'), SyntaxError, 'trailing param');
|
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=b] = []'), SyntaxError, 'assignment expression');
|
||||||
assertThrowsInstanceOf(() => new Function('[...a()] = []'), SyntaxError, 'call expression');
|
assertThrowsInstanceOf(() => new Function('[...a()] = []'), SyntaxError, 'call expression');
|
||||||
assertThrowsInstanceOf(() => new Function('[...(a,b)] = []'), SyntaxError, 'comma expression');
|
assertThrowsInstanceOf(() => new Function('[...(a,b)] = []'), SyntaxError, 'comma expression');
|
||||||
|
@ -22,6 +20,14 @@ assertThrowsInstanceOf(() =>
|
||||||
assertThrowsInstanceOf(() => new Function('[...b,] = []'), SyntaxError)
|
assertThrowsInstanceOf(() => new Function('[...b,] = []'), SyntaxError)
|
||||||
, Error);
|
, Error);
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => {
|
||||||
|
try {
|
||||||
|
eval('let [...[...x]] = (() => { throw "foo"; } )();');
|
||||||
|
} catch(e) {
|
||||||
|
assertEq(e, "foo");
|
||||||
|
}
|
||||||
|
x;
|
||||||
|
}, ReferenceError);
|
||||||
|
|
||||||
var inputArray = [1, 2, 3];
|
var inputArray = [1, 2, 3];
|
||||||
var inputDeep = [1, inputArray];
|
var inputDeep = [1, inputArray];
|
||||||
|
@ -45,6 +51,11 @@ function testAll(fn) {
|
||||||
assertEqArray(fn('[, ...(o.prop)]', inputArray, 'o.prop'), expected);
|
assertEqArray(fn('[, ...(o.prop)]', inputArray, 'o.prop'), expected);
|
||||||
o.prop = null;
|
o.prop = null;
|
||||||
assertEqArray(fn('[, ...(o.call().prop)]', inputArray, 'o.prop'), expected);
|
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) {
|
function testDeclaration(fn) {
|
||||||
testStr(fn);
|
testStr(fn);
|
||||||
|
@ -53,10 +64,24 @@ function testDeclaration(fn) {
|
||||||
assertEqArray(fn('[, ...rest]', inputGenerator()), expected);
|
assertEqArray(fn('[, ...rest]', inputGenerator()), expected);
|
||||||
assertEqArray(fn('[, [, ...rest]]', inputDeep), expected);
|
assertEqArray(fn('[, [, ...rest]]', inputDeep), expected);
|
||||||
assertEqArray(fn('{a: [, ...rest]}', inputObject), 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) {
|
function testStr(fn) {
|
||||||
assertEqArray(fn('[, ...rest]', inputStr), expectedStr);
|
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) {
|
function testForIn(pattern, input, binding) {
|
||||||
|
@ -88,8 +113,9 @@ testAll(testGlobal);
|
||||||
|
|
||||||
function testClosure(pattern, input, binding) {
|
function testClosure(pattern, input, binding) {
|
||||||
binding = binding || 'rest';
|
binding = binding || 'rest';
|
||||||
|
const decl = binding.replace('[', '').replace(']', '');
|
||||||
return new Function('input',
|
return new Function('input',
|
||||||
'var ' + binding + '; (function () {' +
|
'var ' + decl + '; (function () {' +
|
||||||
'(' + pattern + ' = input);' +
|
'(' + pattern + ' = input);' +
|
||||||
'})();' +
|
'})();' +
|
||||||
'return ' + binding
|
'return ' + binding
|
||||||
|
|
|
@ -1824,6 +1824,12 @@ jit::ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph)
|
||||||
bool
|
bool
|
||||||
jit::MakeMRegExpHoistable(MIRGraph& graph)
|
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 (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||||
for (MDefinitionIterator iter(*block); iter; iter++) {
|
for (MDefinitionIterator iter(*block); iter; iter++) {
|
||||||
if (!iter->isRegExp())
|
if (!iter->isRegExp())
|
||||||
|
|
|
@ -1124,6 +1124,10 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge
|
||||||
|
|
||||||
RootedObject self(cx, this);
|
RootedObject self(cx, this);
|
||||||
|
|
||||||
|
Shape* existingShape = self->ensureShape(cx);
|
||||||
|
if (!existingShape)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (isNative() && as<NativeObject>().inDictionaryMode()) {
|
if (isNative() && as<NativeObject>().inDictionaryMode()) {
|
||||||
if (generateShape == GENERATE_SHAPE && !as<NativeObject>().generateOwnShape(cx))
|
if (generateShape == GENERATE_SHAPE && !as<NativeObject>().generateOwnShape(cx))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1137,10 +1141,6 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape* existingShape = self->ensureShape(cx);
|
|
||||||
if (!existingShape)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Shape* newShape = Shape::setObjectFlags(cx, flags, self->getTaggedProto(), existingShape);
|
Shape* newShape = Shape::setObjectFlags(cx, flags, self->getTaggedProto(), existingShape);
|
||||||
if (!newShape)
|
if (!newShape)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -110,6 +110,7 @@ struct BidiParagraphData {
|
||||||
nsTArray<nsLineBox*> mLinePerFrame;
|
nsTArray<nsLineBox*> mLinePerFrame;
|
||||||
nsDataHashtable<nsISupportsHashKey, int32_t> mContentToFrameIndex;
|
nsDataHashtable<nsISupportsHashKey, int32_t> mContentToFrameIndex;
|
||||||
bool mIsVisual;
|
bool mIsVisual;
|
||||||
|
bool mRequiresBidi;
|
||||||
bool mReset;
|
bool mReset;
|
||||||
nsBidiLevel mParaLevel;
|
nsBidiLevel mParaLevel;
|
||||||
nsIContent* mPrevContent;
|
nsIContent* mPrevContent;
|
||||||
|
@ -121,10 +122,14 @@ struct BidiParagraphData {
|
||||||
void Init(nsBlockFrame *aBlockFrame)
|
void Init(nsBlockFrame *aBlockFrame)
|
||||||
{
|
{
|
||||||
mBidiEngine = new nsBidi();
|
mBidiEngine = new nsBidi();
|
||||||
|
mRequiresBidi = false;
|
||||||
mPrevContent = nullptr;
|
mPrevContent = nullptr;
|
||||||
mParagraphDepth = 0;
|
mParagraphDepth = 0;
|
||||||
|
|
||||||
mParaLevel = nsBidiPresUtils::BidiLevelFromStyle(aBlockFrame->StyleContext());
|
mParaLevel = nsBidiPresUtils::BidiLevelFromStyle(aBlockFrame->StyleContext());
|
||||||
|
if (mParaLevel > 0) {
|
||||||
|
mRequiresBidi = true;
|
||||||
|
}
|
||||||
|
|
||||||
mIsVisual = aBlockFrame->PresContext()->IsVisualMode();
|
mIsVisual = aBlockFrame->PresContext()->IsVisualMode();
|
||||||
if (mIsVisual) {
|
if (mIsVisual) {
|
||||||
|
@ -664,14 +669,67 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||||
char16_t ch = GetBidiControl(aBlockFrame->StyleContext(), kOverride);
|
char16_t ch = GetBidiControl(aBlockFrame->StyleContext(), kOverride);
|
||||||
if (ch != 0) {
|
if (ch != 0) {
|
||||||
bpd.PushBidiControl(ch);
|
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;
|
for (nsBlockFrame* block = aBlockFrame; block;
|
||||||
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
|
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
|
||||||
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||||
nsBlockInFlowLineIterator lineIter(block, block->begin_lines());
|
nsBlockInFlowLineIterator lineIter(block, block->begin_lines());
|
||||||
bpd.ResetForNewBlock();
|
bpd.ResetForNewBlock();
|
||||||
TraverseFrames(aBlockFrame, &lineIter, block->GetFirstPrincipalChild(), &bpd);
|
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) {
|
if (ch != 0) {
|
||||||
|
@ -1241,6 +1299,56 @@ nsBidiPresUtils::TraverseFrames(nsBlockFrame* aBlockFrame,
|
||||||
MOZ_ASSERT(initialLineContainer == aLineIter->GetContainer());
|
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
|
void
|
||||||
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame,
|
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame,
|
||||||
BidiParagraphData* aBpd)
|
BidiParagraphData* aBpd)
|
||||||
|
|
|
@ -399,6 +399,23 @@ private:
|
||||||
nsIFrame* aCurrentFrame,
|
nsIFrame* aCurrentFrame,
|
||||||
BidiParagraphData* aBpd);
|
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).
|
* Position ruby content frames (ruby base/text frame).
|
||||||
* Called from RepositionRubyFrame.
|
* Called from RepositionRubyFrame.
|
||||||
|
|
|
@ -647,7 +647,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||||
mAsyncPanZoomEnabled(nsLayoutUtils::AsyncPanZoomEnabled(aReferenceFrame))
|
mAsyncPanZoomEnabled(nsLayoutUtils::AsyncPanZoomEnabled(aReferenceFrame))
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
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);
|
std::max(NS_ALIGNMENT_OF(void*),NS_ALIGNMENT_OF(double))-1);
|
||||||
|
|
||||||
nsPresContext* pc = aReferenceFrame->PresContext();
|
nsPresContext* pc = aReferenceFrame->PresContext();
|
||||||
|
|
|
@ -9345,9 +9345,13 @@ nsTextFrame::GetRenderedText(uint32_t aStartOffset,
|
||||||
startOffset = aStartOffset;
|
startOffset = aStartOffset;
|
||||||
endOffset = std::min<uint32_t>(INT32_MAX, aEndOffset);
|
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,
|
trimmedOffsets.mStart = std::max<uint32_t>(trimmedOffsets.mStart,
|
||||||
startOffset);
|
startOffset);
|
||||||
trimmedOffsets.mLength = std::min<uint32_t>(trimmedOffsets.GetEnd(),
|
trimmedOffsets.mLength = std::min<uint32_t>(origTrimmedOffsetsEnd,
|
||||||
endOffset) - trimmedOffsets.mStart;
|
endOffset) - trimmedOffsets.mStart;
|
||||||
if (trimmedOffsets.mLength <= 0) {
|
if (trimmedOffsets.mLength <= 0) {
|
||||||
offsetInRenderedString = nextOffsetInRenderedString;
|
offsetInRenderedString = nextOffsetInRenderedString;
|
||||||
|
|
|
@ -1176,10 +1176,13 @@ GetStatesForPseudoClass(const nsAString& aStatePseudo)
|
||||||
|
|
||||||
nsCOMPtr<nsIAtom> atom = do_GetAtom(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
|
// visited and unvisited style state
|
||||||
if (nsCSSPseudoClasses::GetPseudoType(atom) ==
|
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();
|
return EventStates();
|
||||||
}
|
}
|
||||||
// Our array above is long enough that indexing into it with
|
// Our array above is long enough that indexing into it with
|
||||||
|
|
|
@ -991,7 +991,6 @@ const KTableEntry nsCSSProps::kBoxShadowTypeKTable[] = {
|
||||||
const KTableEntry nsCSSProps::kBoxSizingKTable[] = {
|
const KTableEntry nsCSSProps::kBoxSizingKTable[] = {
|
||||||
{ eCSSKeyword_content_box, uint8_t(StyleBoxSizing::Content) },
|
{ eCSSKeyword_content_box, uint8_t(StyleBoxSizing::Content) },
|
||||||
{ eCSSKeyword_border_box, uint8_t(StyleBoxSizing::Border) },
|
{ eCSSKeyword_border_box, uint8_t(StyleBoxSizing::Border) },
|
||||||
{ eCSSKeyword_padding_box, uint8_t(StyleBoxSizing::Padding) },
|
|
||||||
{ eCSSKeyword_UNKNOWN, -1 }
|
{ eCSSKeyword_UNKNOWN, -1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,8 @@ CSS_STATE_PSEUDO_CLASS(link, ":link", 0, "", NS_EVENT_STATE_UNVISITED)
|
||||||
// what matches :link or :visited
|
// what matches :link or :visited
|
||||||
CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link", 0, "",
|
CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link", 0, "",
|
||||||
NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)
|
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(visited, ":visited", 0, "", NS_EVENT_STATE_VISITED)
|
||||||
|
|
||||||
CSS_STATE_PSEUDO_CLASS(active, ":active", 0, "", NS_EVENT_STATE_ACTIVE)
|
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;
|
t[i] = book->valuelist+entry[i]*book->dim;
|
||||||
}
|
}
|
||||||
for(i=0,o=0;i<book->dim;i++,o+=step)
|
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];
|
a[o+j]+=t[j][i];
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
@ -399,42 +399,13 @@ long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||||
int i,j,entry;
|
int i,j,entry;
|
||||||
float *t;
|
float *t;
|
||||||
|
|
||||||
if(book->dim>8){
|
|
||||||
for(i=0;i<n;){
|
for(i=0;i<n;){
|
||||||
entry = decode_packed_entry_number(book,b);
|
entry = decode_packed_entry_number(book,b);
|
||||||
if(entry==-1)return(-1);
|
if(entry==-1)return(-1);
|
||||||
t = book->valuelist+entry*book->dim;
|
t = book->valuelist+entry*book->dim;
|
||||||
for (j=0;j<book->dim;)
|
for(j=0;i<n && j<book->dim;)
|
||||||
a[i++]+=t[j++];
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@ -471,12 +442,13 @@ long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
|
||||||
long i,j,entry;
|
long i,j,entry;
|
||||||
int chptr=0;
|
int chptr=0;
|
||||||
if(book->used_entries>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);
|
entry = decode_packed_entry_number(book,b);
|
||||||
if(entry==-1)return(-1);
|
if(entry==-1)return(-1);
|
||||||
{
|
{
|
||||||
const float *t = book->valuelist+entry*book->dim;
|
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];
|
a[chptr++][i]+=t[j];
|
||||||
if(chptr==ch){
|
if(chptr==ch){
|
||||||
chptr=0;
|
chptr=0;
|
||||||
|
|
|
@ -186,7 +186,7 @@ cglobal quantize_%1, 0, %2, 15, coeff, ncoeff, skip, zbin, round, quant, \
|
||||||
pshuflw m7, m8, 0x1
|
pshuflw m7, m8, 0x1
|
||||||
pmaxsw m8, m7
|
pmaxsw m8, m7
|
||||||
pextrw r6, m8, 0
|
pextrw r6, m8, 0
|
||||||
mov [r2], r6
|
mov [r2], r6w
|
||||||
RET
|
RET
|
||||||
|
|
||||||
; skip-block, i.e. just write all zeroes
|
; 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
|
// Try and use SPDY when using SSL
|
||||||
pref("network.http.spdy.enabled", true);
|
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.http2", true);
|
||||||
pref("network.http.spdy.enabled.deps", true);
|
pref("network.http.spdy.enabled.deps", true);
|
||||||
pref("network.http.spdy.enforce-tls-profile", true);
|
pref("network.http.spdy.enforce-tls-profile", true);
|
||||||
|
@ -5137,4 +5137,4 @@ pref("toolkit.pageThumbs.minWidth", 0);
|
||||||
pref("toolkit.pageThumbs.minHeight", 0);
|
pref("toolkit.pageThumbs.minHeight", 0);
|
||||||
|
|
||||||
pref("tenfourfox.adblock.enabled", false);
|
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_rsa_aes_128_gcm_sha256", true);
|
||||||
pref("security.ssl3.ecdhe_ecdsa_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_sha", true);
|
||||||
|
pref("security.ssl3.ecdhe_rsa_aes_128_sha256", true);
|
||||||
pref("security.ssl3.ecdhe_ecdsa_aes_128_sha", true);
|
pref("security.ssl3.ecdhe_ecdsa_aes_128_sha", true);
|
||||||
pref("security.ssl3.ecdhe_rsa_aes_256_sha", true);
|
pref("security.ssl3.ecdhe_rsa_aes_256_sha", true);
|
||||||
pref("security.ssl3.ecdhe_ecdsa_aes_256_sha", true);
|
pref("security.ssl3.ecdhe_ecdsa_aes_256_sha", true);
|
||||||
|
|
|
@ -1014,6 +1014,15 @@ Http2Session::CleanupStream(Http2Stream *aStream, nsresult aResult,
|
||||||
return;
|
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)) {
|
if (aStream->DeferCleanup(aResult)) {
|
||||||
LOG3(("Http2Session::CleanupStream 0x%X deferred\n", aStream->StreamID()));
|
LOG3(("Http2Session::CleanupStream 0x%X deferred\n", aStream->StreamID()));
|
||||||
return;
|
return;
|
||||||
|
@ -1024,15 +1033,6 @@ Http2Session::CleanupStream(Http2Stream *aStream, nsresult aResult,
|
||||||
return;
|
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()) {
|
if (!aStream->RecvdFin() && !aStream->RecvdReset() && aStream->StreamID()) {
|
||||||
LOG3(("Stream had not processed recv FIN, sending RST code %X\n", aResetCode));
|
LOG3(("Stream had not processed recv FIN, sending RST code %X\n", aResetCode));
|
||||||
GenerateRstStream(aResetCode, aStream->StreamID());
|
GenerateRstStream(aResetCode, aStream->StreamID());
|
||||||
|
|
|
@ -101,10 +101,20 @@ Http2Stream::Http2Stream(nsAHttpTransaction *httpTransaction,
|
||||||
|
|
||||||
Http2Stream::~Http2Stream()
|
Http2Stream::~Http2Stream()
|
||||||
{
|
{
|
||||||
|
ClearPushSource();
|
||||||
ClearTransactionsBlockedOnTunnel();
|
ClearTransactionsBlockedOnTunnel();
|
||||||
mStreamID = Http2Session::kDeadStreamID;
|
mStreamID = Http2Session::kDeadStreamID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Http2Stream::ClearPushSource()
|
||||||
|
{
|
||||||
|
if (mPushSource) {
|
||||||
|
mPushSource->SetConsumerStream(nullptr);
|
||||||
|
mPushSource = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ReadSegments() is used to write data down the socket. Generally, HTTP
|
// ReadSegments() is used to write data down the socket. Generally, HTTP
|
||||||
// request data is pulled from the approriate transaction and
|
// request data is pulled from the approriate transaction and
|
||||||
// converted to HTTP/2 data. Sometimes control data like a window-update is
|
// converted to HTTP/2 data. Sometimes control data like a window-update is
|
||||||
|
@ -1091,6 +1101,10 @@ Http2Stream::ConvertPushHeaders(Http2Decompressor *decompressor,
|
||||||
void
|
void
|
||||||
Http2Stream::Close(nsresult reason)
|
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);
|
mTransaction->Close(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ public:
|
||||||
|
|
||||||
uint32_t StreamID() { return mStreamID; }
|
uint32_t StreamID() { return mStreamID; }
|
||||||
Http2PushedStream *PushSource() { return mPushSource; }
|
Http2PushedStream *PushSource() { return mPushSource; }
|
||||||
|
void ClearPushSource();
|
||||||
|
|
||||||
stateType HTTPState() { return mState; }
|
stateType HTTPState() { return mState; }
|
||||||
void SetHTTPState(stateType val) { mState = val; }
|
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 },
|
{ "goto.google.com", true, false, false, -1, &kPinset_google_root_pems },
|
||||||
{ "gr.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
|
{ "gr.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
|
||||||
{ "groups.google.com", true, false, false, -1, &kPinset_google_root_pems },
|
{ "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 },
|
{ "gstatic.com", true, false, false, -1, &kPinset_google_root_pems },
|
||||||
{ "gvt1.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 },
|
{ "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 },
|
{ "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 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;
|
extern PRLogModuleInfo* gPIPNSSLog;
|
||||||
|
|
||||||
|
#if (0) // TenFourFox issue 334
|
||||||
static void AccumulateCipherSuite(Telemetry::ID probe,
|
static void AccumulateCipherSuite(Telemetry::ID probe,
|
||||||
const SSLChannelInfo& channelInfo);
|
const SSLChannelInfo& channelInfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -1027,6 +1029,7 @@ CanFalseStartCallback(PRFileDesc* fd, void* client_data, PRBool *canFalseStart)
|
||||||
return SECSuccess;
|
return SECSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if(0) // TenFourFox issue 334
|
||||||
static void
|
static void
|
||||||
AccumulateNonECCKeySize(Telemetry::ID probe, uint32_t bits)
|
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_RSA_WITH_RC4_128_SHA: value = 8; break;
|
||||||
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: value = 9; 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_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
|
// DHE key exchange
|
||||||
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: value = 21; break;
|
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: value = 21; break;
|
||||||
case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: value = 22; 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);
|
MOZ_ASSERT(value != 0);
|
||||||
Telemetry::Accumulate(probe, value);
|
Telemetry::Accumulate(probe, value);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||||
nsNSSShutDownPreventionLock locker;
|
nsNSSShutDownPreventionLock locker;
|
||||||
|
@ -1146,6 +1151,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||||
rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo));
|
rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo));
|
||||||
MOZ_ASSERT(rv == SECSuccess);
|
MOZ_ASSERT(rv == SECSuccess);
|
||||||
if (rv == SECSuccess) {
|
if (rv == SECSuccess) {
|
||||||
|
#if(0) // TenFourFox issue 334
|
||||||
// Get the protocol version for telemetry
|
// Get the protocol version for telemetry
|
||||||
// 1=tls1, 2=tls1.1, 3=tls1.2
|
// 1=tls1, 2=tls1.1, 3=tls1.2
|
||||||
unsigned int versionEnum = channelInfo.protocolVersion & 0xFF;
|
unsigned int versionEnum = channelInfo.protocolVersion & 0xFF;
|
||||||
|
@ -1155,6 +1161,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||||
infoObject->IsFullHandshake() ? Telemetry::SSL_CIPHER_SUITE_FULL
|
infoObject->IsFullHandshake() ? Telemetry::SSL_CIPHER_SUITE_FULL
|
||||||
: Telemetry::SSL_CIPHER_SUITE_RESUMED,
|
: Telemetry::SSL_CIPHER_SUITE_RESUMED,
|
||||||
channelInfo);
|
channelInfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
SSLCipherSuiteInfo cipherInfo;
|
SSLCipherSuiteInfo cipherInfo;
|
||||||
rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
|
rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
|
||||||
|
@ -1163,17 +1170,20 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||||
if (rv == SECSuccess) {
|
if (rv == SECSuccess) {
|
||||||
usesWeakCipher = cipherInfo.symCipher == ssl_calg_rc4;
|
usesWeakCipher = cipherInfo.symCipher == ssl_calg_rc4;
|
||||||
|
|
||||||
|
#if(0)
|
||||||
// keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4
|
// keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4
|
||||||
Telemetry::Accumulate(
|
Telemetry::Accumulate(
|
||||||
infoObject->IsFullHandshake()
|
infoObject->IsFullHandshake()
|
||||||
? Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_FULL
|
? Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_FULL
|
||||||
: Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED,
|
: Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED,
|
||||||
cipherInfo.keaType);
|
cipherInfo.keaType);
|
||||||
|
#endif
|
||||||
|
|
||||||
DebugOnly<int16_t> KEAUsed;
|
DebugOnly<int16_t> KEAUsed;
|
||||||
MOZ_ASSERT(NS_SUCCEEDED(infoObject->GetKEAUsed(&KEAUsed)) &&
|
MOZ_ASSERT(NS_SUCCEEDED(infoObject->GetKEAUsed(&KEAUsed)) &&
|
||||||
(KEAUsed == cipherInfo.keaType));
|
(KEAUsed == cipherInfo.keaType));
|
||||||
|
|
||||||
|
#if(0)
|
||||||
if (infoObject->IsFullHandshake()) {
|
if (infoObject->IsFullHandshake()) {
|
||||||
switch (cipherInfo.keaType) {
|
switch (cipherInfo.keaType) {
|
||||||
case ssl_kea_rsa:
|
case ssl_kea_rsa:
|
||||||
|
@ -1223,6 +1233,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||||
? Telemetry::SSL_SYMMETRIC_CIPHER_FULL
|
? Telemetry::SSL_SYMMETRIC_CIPHER_FULL
|
||||||
: Telemetry::SSL_SYMMETRIC_CIPHER_RESUMED,
|
: Telemetry::SSL_SYMMETRIC_CIPHER_RESUMED,
|
||||||
cipherInfo.symCipher);
|
cipherInfo.symCipher);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -623,6 +623,9 @@ static const CipherPref sCipherPrefs[] = {
|
||||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, true },
|
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, true },
|
||||||
{ "security.ssl3.ecdhe_ecdsa_aes_128_sha",
|
{ "security.ssl3.ecdhe_ecdsa_aes_128_sha",
|
||||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, true },
|
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",
|
{ "security.ssl3.ecdhe_rsa_aes_256_sha",
|
||||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, true },
|
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
|
// FPR series
|
||||||
var vf = 0 + versionNum.substr(3);
|
var vf = 0 + versionNum.substr(3);
|
||||||
var pl = ""+ (vf - (vf|0));
|
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;
|
vf = vf|0; vf -= 9;
|
||||||
// XXX localize me
|
// XXX localize me
|
||||||
version.textContent = "Feature Parity Release "+vf+
|
version.textContent = "Feature Parity Release "+vf+
|
||||||
|
|
|
@ -59,6 +59,13 @@ interface nsIDatePicker : nsISupports
|
||||||
*/
|
*/
|
||||||
attribute AString maxDate;
|
attribute AString maxDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The selected date.
|
||||||
|
*
|
||||||
|
* @return Returns the date currently selected.
|
||||||
|
*/
|
||||||
|
readonly attribute AString selectedDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show date dialog. The dialog is displayed modally.
|
* Show date dialog. The dialog is displayed modally.
|
||||||
*
|
*
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "mozilla/HashFunctions.h"
|
#include "mozilla/HashFunctions.h"
|
||||||
#include "mozilla/MathAlgorithms.h"
|
#include "mozilla/MathAlgorithms.h"
|
||||||
#include "nsAlgorithm.h"
|
#include "nsAlgorithm.h"
|
||||||
|
#include "mozilla/HashFunctions.h"
|
||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/ChaosMode.h"
|
#include "mozilla/ChaosMode.h"
|
||||||
|
@ -71,7 +72,7 @@ PLDHashTable::HashStringKey(PLDHashTable* aTable, const void* aKey)
|
||||||
/* static */ PLDHashNumber
|
/* static */ PLDHashNumber
|
||||||
PLDHashTable::HashVoidPtrKeyStub(PLDHashTable* aTable, const void* aKey)
|
PLDHashTable::HashVoidPtrKeyStub(PLDHashTable* aTable, const void* aKey)
|
||||||
{
|
{
|
||||||
return (PLDHashNumber)(ptrdiff_t)aKey >> 2;
|
return mozilla::HashGeneric(aKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
|
@ -256,15 +257,38 @@ PLDHashTable::Hash1(PLDHashNumber aHash0)
|
||||||
return aHash0 >> mHashShift;
|
return aHash0 >> mHashShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double hashing needs the second hash code to be relatively prime to table
|
|
||||||
// size, so we simply make hash2 odd.
|
|
||||||
void
|
void
|
||||||
PLDHashTable::Hash2(PLDHashNumber aHash,
|
PLDHashTable::Hash2(PLDHashNumber aHash0,
|
||||||
uint32_t& aHash2Out, uint32_t& aSizeMaskOut)
|
uint32_t& aHash2Out, uint32_t& aSizeMaskOut)
|
||||||
{
|
{
|
||||||
uint32_t sizeLog2 = kHashBits - mHashShift;
|
uint32_t sizeLog2 = kHashBits - mHashShift;
|
||||||
aHash2Out = ((aHash << sizeLog2) >> mHashShift) | 1;
|
uint32_t sizeMask = (PLDHashNumber(1) << sizeLog2) - 1;
|
||||||
aSizeMaskOut = (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
|
// 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;
|
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
|
bool
|
||||||
StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
|
StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||||
const nsStringComparator& aComparator)
|
const nsStringComparator& aComparator)
|
||||||
|
@ -1038,6 +1049,17 @@ StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||||
return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
|
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
|
bool
|
||||||
StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
|
StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||||
const nsCStringComparator& aComparator)
|
const nsCStringComparator& aComparator)
|
||||||
|
@ -1050,6 +1072,17 @@ StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||||
return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
|
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
|
bool
|
||||||
StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
|
StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||||
const nsStringComparator& aComparator)
|
const nsStringComparator& aComparator)
|
||||||
|
@ -1063,6 +1096,17 @@ StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||||
aComparator);
|
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
|
bool
|
||||||
StringEndsWith(const nsACString& aSource, const nsACString& aSubstring,
|
StringEndsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||||
const nsCStringComparator& aComparator)
|
const nsCStringComparator& aComparator)
|
||||||
|
|
|
@ -386,18 +386,18 @@ uint32_t CountCharInReadable(const nsAString& aStr,
|
||||||
uint32_t CountCharInReadable(const nsACString& aStr,
|
uint32_t CountCharInReadable(const nsACString& aStr,
|
||||||
char aChar);
|
char aChar);
|
||||||
|
|
||||||
|
bool StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring);
|
||||||
bool StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
|
bool StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||||
const nsStringComparator& aComparator =
|
const nsStringComparator& aComparator);
|
||||||
nsDefaultStringComparator());
|
bool StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring);
|
||||||
bool StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
|
bool StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||||
const nsCStringComparator& aComparator =
|
const nsCStringComparator& aComparator);
|
||||||
nsDefaultCStringComparator());
|
bool StringEndsWith(const nsAString& aSource, const nsAString& aSubstring);
|
||||||
bool StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
|
bool StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
|
||||||
const nsStringComparator& aComparator =
|
const nsStringComparator& aComparator);
|
||||||
nsDefaultStringComparator());
|
bool StringEndsWith(const nsACString& aSource, const nsACString& aSubstring);
|
||||||
bool StringEndsWith(const nsACString& aSource, const nsACString& aSubstring,
|
bool StringEndsWith(const nsACString& aSource, const nsACString& aSubstring,
|
||||||
const nsCStringComparator& aComparator =
|
const nsCStringComparator& aComparator);
|
||||||
nsDefaultCStringComparator());
|
|
||||||
|
|
||||||
const nsAFlatString& EmptyString();
|
const nsAFlatString& EmptyString();
|
||||||
const nsAFlatCString& EmptyCString();
|
const nsAFlatCString& EmptyCString();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user