Merge pull request #8 from classilla/master

keep sync with master
This commit is contained in:
Riccardo 2018-03-23 09:22:51 +01:00 committed by GitHub
commit b61caed0c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
95 changed files with 2546 additions and 1364 deletions

View File

@ -18,6 +18,9 @@
<preference id="tenfourfox.ua.template"
name="tenfourfox.ua.template"
type="string"/>
<preference id="tenfourfox.adblock.enabled"
name="tenfourfox.adblock.enabled"
type="bool"/>
</preferences>
@ -69,3 +72,12 @@
</menulist>
</hbox>
</groupbox>
<groupbox id="adBlockGroup" data-category="paneTenFourFox" hidden="true">
<caption><label>&TFFadBlock.title;</label></caption>
<vbox>
<checkbox id="tenFourFoxAdBlockCheckbox"
label="&TFFadBlock.prompt;"
preference="tenfourfox.adblock.enabled"/>
</vbox>
</groupbox>

View File

@ -1 +1 @@
45.15.0
45.16.0

View File

@ -1 +1 @@
Feature Parity Release 6
Feature Parity Release 7

View File

@ -705,7 +705,17 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
// blocking zdbb.net seems to be problematic
// https://github.com/AdguardTeam/AdguardFilters/issues/1278
// this may also be true for adziff.com
// don't block kxcdn
// https://github.com/EFForg/privacybadger/issues/1381
// miners
BLOK("coinhive.com") ||
BLOK("www.freecontent.stream") ||
BLOK("www.freecontent.stream.") ||
// other obnoxious things
BLOK("c.amazon-adsystem.com") ||
BLOK("google-analytics.com") ||
@ -793,6 +803,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("cdn.segment.com") ||
BLOK("cdn-gl.imrworldwide.com") ||
BLOK("secure-us.imrworldwide.com") ||
BLOK("secure-dcr.imrworldwide.com") ||
BLOK("labs-cdn.revcontent.com") ||
@ -800,6 +811,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("cdn.revcontent.com") ||
BLOK("cas.criteo.com") ||
BLOK("rtax.criteo.com") ||
BLOK("static.criteo.net") ||
BLOK("jsc.idealmedia.com") ||
@ -848,6 +860,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("www.npttech.com") ||
BLOK("fw.adsafeprotected.com") ||
BLOK("cdn.adsafeprotected.com") ||
BLOK("pixel.adsafeprotected.com") ||
BLOK("static.adsafeprotected.com") ||
@ -902,6 +915,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("se.monetate.net") ||
BLOK("ad.crwdcntrl.net") ||
BLOK("bcp.crwdcntrl.net") ||
BLOK("tags.crwdcntrl.net") ||
BLOK("cdn.nsstatic.net") ||
@ -917,6 +931,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("stats.cloudwp.io") ||
BLOK("ap.lijit.com") ||
BLOK("ce.lijit.com") ||
BLOK("tlx.3lift.com") ||
@ -982,14 +997,12 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("cdata.carambo.la") ||
BLOK("route.carambo.la") ||
BLOK("us-u.openx.net") ||
BLOK("uk-ads.openx.net") ||
BLOK("us-ads.openx.net") ||
BLOK("s-static.innovid.com") ||
// This is controversial, but I'm pretty sure we
// don't want this.
BLOK("coinhive.com") ||
BLOK("ustatik.com") ||
BLOK("cdn.ustatik.com") ||
@ -997,6 +1010,43 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("s.spoutable.com") ||
BLOK("cdn.spoutable.com") ||
BLOK("ads.pubmatic.com") ||
BLOK("track.netshelter.net") ||
BLOK("t.neodatagroup.com") ||
BLOK("ads.servebom.com") ||
BLOK("a.mailmunch.co") ||
BLOK("ads.adthrive.com") ||
BLOK("js.agkn.com") ||
BLOK("htl.bid") ||
BLOK("rtb.districtm.io") ||
BLOK("prebid.districtm.ca") ||
BLOK("speednetwork14.adk2.co") ||
BLOK("speednetwork14.adk2x.com") ||
BLOK("deloton.com") ||
BLOK("clickiocdn.com") ||
BLOK("clickioadve.com") ||
BLOK("cti.w55c.net") ||
BLOK("cdn.w55c.net") ||
BLOK("mobpushup.com") ||
BLOK("sc.iasds01.com") ||
BLOK("cdn.optimizely.com") ||
BLOK("cdn3.optimizely.com") ||
0) {
#undef BLOK
// Yup.

View File

@ -10,4 +10,4 @@
# hardcoded milestones in the tree from these two files.
#--------------------------------------------------------
45.15.0
45.16.0

View File

@ -6630,9 +6630,17 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh, nsI
*/
loadInfo->SetReferrer(mCurrentURI);
/* Don't ever "guess" on which owner to use to avoid picking
* the current owner.
*/
// Set the triggering pricipal to aPrincipal if available, or current
// document's principal otherwise.
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
if (!principal) {
nsCOMPtr<nsIDocument> doc = GetDocument();
if (MOZ_UNLIKELY(!doc)) {
return NS_ERROR_FAILURE;
}
principal = doc->NodePrincipal();
}
loadInfo->SetOwner(principal); // equivalent for SetTriggeringPrincipal
loadInfo->SetOwnerIsExplicit(true);
/* Check if this META refresh causes a redirection
@ -6660,13 +6668,6 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh, nsI
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
}
// If the principal is null, the refresh will have a triggeringPrincipal
// derived from the referrer URI, or will be set to the system principal
// if there is no refererrer. See LoadURI()
if (aPrincipal) {
loadInfo->SetOwner(aPrincipal); // as called prior to bug 1286472
}
/*
* LoadURI(...) will cancel all refresh timers... This causes the
* Timer and its refreshData instance to be released...

View File

@ -19,9 +19,8 @@ interface nsIRefreshURI : nsISupports {
*
* @param aUri The uri to refresh.
* @param aPrincipal The triggeringPrincipal for the refresh load
* May be null, in which case a principal will be built based on the
* referrer URI of the previous docshell load, or will use the system
* principal when there is no referrer.
* May be null, in which case the principal of current document will be
* applied.
* @param aMillis The number of milliseconds to wait.
* @param aRepeat Flag to indicate if the uri is to be
* repeatedly refreshed every aMillis milliseconds.
@ -37,9 +36,8 @@ interface nsIRefreshURI : nsISupports {
*
* @param aURI The URI to refresh.
* @param aPrincipal The triggeringPrincipal for the refresh load
* May be null, in which case a principal will be built based on the
* referrer URI of the previous docshell load, or will use the system
* principal when there is no referrer.
* May be null, in which case the principal of current document will be
* applied.
* @param aMillis The number of milliseconds by which this refresh would
* be delayed if it were not being forced.
* @param aMetaRefresh Flag to indicate if this is a meta refresh.
@ -70,9 +68,8 @@ interface nsIRefreshURI : nsISupports {
*
* @param aBaseURI base URI to resolve refresh uri with.
* @param aPrincipal The triggeringPrincipal for the refresh load
* May be null, in which case a principal will be built based on the
* referrer URI of the previous docshell load, or will use the system
* principal when there is no referrer.
* May be null, in which case the principal of current document will be
* applied.
* @param aHeader The meta refresh header string.
*/
void setupRefreshURIFromHeader(in nsIURI aBaseURI,

View 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

View File

@ -44,7 +44,6 @@
#include "nsNameSpaceManager.h"
#include "nsContentList.h"
#include "nsVariant.h"
#include "nsDOMSettableTokenList.h"
#include "nsDOMTokenList.h"
#include "nsXBLPrototypeBinding.h"
#include "nsError.h"
@ -3086,11 +3085,11 @@ Element::GetLinkTarget(nsAString& aTarget)
}
static void
nsDOMSettableTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
void *aPropertyValue, void *aData)
nsDOMTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
void *aPropertyValue, void *aData)
{
nsDOMSettableTokenList* list =
static_cast<nsDOMSettableTokenList*>(aPropertyValue);
nsDOMTokenList* list =
static_cast<nsDOMTokenList*>(aPropertyValue);
NS_RELEASE(list);
}
@ -3113,8 +3112,9 @@ Element::HTMLSVGPropertiesToTraverseAndUnlink()
return sPropertiesToTraverseAndUnlink;
}
nsDOMSettableTokenList*
Element::GetTokenList(nsIAtom* aAtom)
nsDOMTokenList*
Element::GetTokenList(nsIAtom* aAtom,
const DOMTokenListSupportedTokenArray aSupportedTokens)
{
#ifdef DEBUG
nsIAtom*** props =
@ -3129,14 +3129,14 @@ Element::GetTokenList(nsIAtom* aAtom)
MOZ_ASSERT(found, "Trying to use an unknown tokenlist!");
#endif
nsDOMSettableTokenList* list = nullptr;
nsDOMTokenList* list = nullptr;
if (HasProperties()) {
list = static_cast<nsDOMSettableTokenList*>(GetProperty(aAtom));
list = static_cast<nsDOMTokenList*>(GetProperty(aAtom));
}
if (!list) {
list = new nsDOMSettableTokenList(this, aAtom);
list = new nsDOMTokenList(this, aAtom, aSupportedTokens);
NS_ADDREF(list);
SetProperty(aAtom, list, nsDOMSettableTokenListPropertyDestructor);
SetProperty(aAtom, list, nsDOMTokenListPropertyDestructor);
}
return list;
}
@ -3153,7 +3153,7 @@ Element::GetTokenList(nsIAtom* aAtom, nsIVariant** aResult)
nsresult
Element::SetTokenList(nsIAtom* aAtom, nsIVariant* aValue)
{
nsDOMSettableTokenList* itemType = GetTokenList(aAtom);
nsDOMTokenList* itemType = GetTokenList(aAtom);
nsAutoString string;
aValue->GetAsAString(string);
ErrorResult rv;

View File

@ -34,6 +34,7 @@
#include "nsAttrValue.h"
#include "mozilla/EventForwards.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/DOMTokenListSupportedTokens.h"
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/dom/ElementBinding.h"
#include "Units.h"
@ -44,7 +45,6 @@ class nsIURI;
class nsIScrollableFrame;
class nsAttrValueOrString;
class nsContentList;
class nsDOMSettableTokenList;
class nsDOMTokenList;
struct nsRect;
class nsFocusManager;
@ -1342,7 +1342,8 @@ protected:
*/
virtual void GetLinkTarget(nsAString& aTarget);
nsDOMSettableTokenList* GetTokenList(nsIAtom* aAtom);
nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
void GetTokenList(nsIAtom* aAtom, nsIVariant** aResult);
nsresult SetTokenList(nsIAtom* aAtom, nsIVariant* aValue);

View File

@ -25,11 +25,11 @@
class ContentUnbinder;
class nsContentList;
class nsDOMAttributeMap;
class nsDOMTokenList;
class nsIControllers;
class nsICSSDeclaration;
class nsIDocument;
class nsDOMStringMap;
class nsDOMTokenList;
class nsIURI;
namespace mozilla {

View 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)

View File

@ -45,6 +45,7 @@ EXPORTS += [
'AutocompleteFieldList.h',
'Crypto.h',
'HTMLSplitOnSpacesTokenizer.h',
'IframeSandboxKeywordList.h',
'mozAutoDocUpdate.h',
'mozFlushType.h',
'nsAtomListUtils.h',
@ -74,6 +75,7 @@ EXPORTS += [
'nsDOMJSUtils.h',
'nsDOMNavigationTiming.h',
'nsDOMString.h',
'nsDOMTokenList.h',
'nsFocusManager.h',
'nsFormData.h',
'nsFrameMessageManager.h',
@ -174,6 +176,7 @@ EXPORTS.mozilla.dom += [
'DOMRect.h',
'DOMRequest.h',
'DOMStringList.h',
'DOMTokenListSupportedTokens.h',
'Element.h',
'ElementInlines.h',
'EventSource.h',
@ -278,7 +281,6 @@ UNIFIED_SOURCES += [
'nsDOMNavigationTiming.cpp',
'nsDOMScriptObjectFactory.cpp',
'nsDOMSerializer.cpp',
'nsDOMSettableTokenList.cpp',
'nsDOMTokenList.cpp',
'nsDOMWindowList.cpp',
'nsFocusManager.cpp',

View File

@ -1362,19 +1362,13 @@ nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* sandboxAttr)
| SANDBOXED_DOMAIN;
// Macro for updating the flag according to the keywords
#define IF_KEYWORD(atom, flags) \
#define SANDBOX_KEYWORD(string, atom, flags) \
if (sandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { out &= ~(flags); }
IF_KEYWORD(allowsameorigin, SANDBOXED_ORIGIN)
IF_KEYWORD(allowforms, SANDBOXED_FORMS)
IF_KEYWORD(allowscripts, SANDBOXED_SCRIPTS | SANDBOXED_AUTOMATIC_FEATURES)
IF_KEYWORD(allowtopnavigation, SANDBOXED_TOPLEVEL_NAVIGATION)
IF_KEYWORD(allowpointerlock, SANDBOXED_POINTER_LOCK)
IF_KEYWORD(alloworientationlock, SANDBOXED_ORIENTATION_LOCK)
IF_KEYWORD(allowpopups, SANDBOXED_AUXILIARY_NAVIGATION)
#include "IframeSandboxKeywordList.h"
return out;
#undef IF_KEYWORD
#undef SANDBOX_KEYWORD
}
nsIBidiKeyboard*

View File

@ -9,20 +9,25 @@
*/
#include "nsDOMTokenList.h"
#include "nsAttrValueInlines.h"
#include "nsDataHashtable.h"
#include "nsAttrValue.h"
#include "nsContentUtils.h"
#include "nsError.h"
#include "nsHashKeys.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/DOMTokenListBinding.h"
#include "mozilla/BloomFilter.h"
#include "mozilla/ErrorResult.h"
using namespace mozilla;
using namespace mozilla::dom;
nsDOMTokenList::nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom)
nsDOMTokenList::nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom,
const DOMTokenListSupportedTokenArray aSupportedTokens)
: mElement(aElement),
mAttrAtom(aAttrAtom)
mAttrAtom(aAttrAtom),
mSupportedTokens(aSupportedTokens)
{
// We don't add a reference to our element. If it goes away,
// we'll be told to drop our reference
@ -50,6 +55,45 @@ nsDOMTokenList::GetParsedAttr()
return mElement->GetAttrInfo(kNameSpaceID_None, mAttrAtom).mValue;
}
void
nsDOMTokenList::RemoveDuplicates(const nsAttrValue* aAttr)
{
if (!aAttr || aAttr->Type() != nsAttrValue::eAtomArray) {
return;
}
BloomFilter<8, nsIAtom> filter;
nsAttrValue::AtomArray* array = aAttr->GetAtomArrayValue();
for (uint32_t i = 0; i < array->Length(); i++) {
nsIAtom* atom = array->ElementAt(i);
if (filter.mightContain(atom)) {
// Start again, with a hashtable
RemoveDuplicatesInternal(array, i);
return;
} else {
filter.add(atom);
}
}
}
void
nsDOMTokenList::RemoveDuplicatesInternal(nsAttrValue::AtomArray* aArray,
uint32_t aStart)
{
nsDataHashtable<nsPtrHashKey<nsIAtom>, bool> tokens;
for (uint32_t i = 0; i < aArray->Length(); i++) {
nsIAtom* atom = aArray->ElementAt(i);
// No need to check the hashtable below aStart
if (i >= aStart && tokens.Get(atom)) {
aArray->RemoveElementAt(i);
i--;
} else {
tokens.Put(atom, true);
}
}
}
uint32_t
nsDOMTokenList::Length()
{
@ -58,6 +102,7 @@ nsDOMTokenList::Length()
return 0;
}
RemoveDuplicates(attr);
return attr->GetAtomCount();
}
@ -66,6 +111,13 @@ nsDOMTokenList::IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aResult)
{
const nsAttrValue* attr = GetParsedAttr();
if (!attr || aIndex >= static_cast<uint32_t>(attr->GetAtomCount())) {
aFound = false;
return;
}
RemoveDuplicates(attr);
if (attr && aIndex < static_cast<uint32_t>(attr->GetAtomCount())) {
aFound = true;
attr->AtomAt(aIndex)->ToString(aResult);
@ -74,6 +126,16 @@ nsDOMTokenList::IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aResult)
}
}
void
nsDOMTokenList::SetValue(const nsAString& aValue, ErrorResult& rv)
{
if (!mElement) {
return;
}
rv = mElement->SetAttr(kNameSpaceID_None, mAttrAtom, aValue, true);
}
nsresult
nsDOMTokenList::CheckToken(const nsAString& aStr)
{
@ -130,10 +192,15 @@ nsDOMTokenList::AddInternal(const nsAttrValue* aAttr,
nsAutoString resultStr;
if (aAttr) {
aAttr->ToString(resultStr);
RemoveDuplicates(aAttr);
for (uint32_t i = 0; i < aAttr->GetAtomCount(); i++) {
if (i != 0) {
resultStr.AppendLiteral(" ");
}
resultStr.Append(nsDependentAtomString(aAttr->AtomAt(i)));
}
}
bool oneWasAdded = false;
nsAutoTArray<nsString, 10> addedClasses;
for (uint32_t i = 0, l = aTokens.Length(); i < l; ++i) {
@ -144,16 +211,11 @@ nsDOMTokenList::AddInternal(const nsAttrValue* aAttr,
continue;
}
if (oneWasAdded ||
(!resultStr.IsEmpty() &&
!nsContentUtils::IsHTMLWhitespace(resultStr.Last()))) {
if (!resultStr.IsEmpty()) {
resultStr.Append(' ');
resultStr.Append(aToken);
} else {
resultStr.Append(aToken);
}
resultStr.Append(aToken);
oneWasAdded = true;
addedClasses.AppendElement(aToken);
}
@ -186,60 +248,20 @@ nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
{
MOZ_ASSERT(aAttr, "Need an attribute");
nsAutoString input;
aAttr->ToString(input);
RemoveDuplicates(aAttr);
nsAString::const_iterator copyStart, tokenStart, iter, end;
input.BeginReading(iter);
input.EndReading(end);
copyStart = iter;
nsAutoString output;
bool lastTokenRemoved = false;
while (iter != end) {
// skip whitespace.
while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
++iter;
nsAutoString resultStr;
for (uint32_t i = 0; i < aAttr->GetAtomCount(); i++) {
if (aTokens.Contains(nsDependentAtomString(aAttr->AtomAt(i)))) {
continue;
}
if (iter == end) {
// At this point we're sure the last seen token (if any) wasn't to be
// removed. So the trailing spaces will need to be kept.
MOZ_ASSERT(!lastTokenRemoved, "How did this happen?");
output.Append(Substring(copyStart, end));
break;
}
tokenStart = iter;
do {
++iter;
} while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter));
if (aTokens.Contains(Substring(tokenStart, iter))) {
// Skip whitespace after the token, it will be collapsed.
while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
++iter;
}
copyStart = iter;
lastTokenRemoved = true;
} else {
if (lastTokenRemoved && !output.IsEmpty()) {
MOZ_ASSERT(!nsContentUtils::IsHTMLWhitespace(output.Last()),
"Invalid last output token");
output.Append(char16_t(' '));
}
lastTokenRemoved = false;
output.Append(Substring(copyStart, iter));
copyStart = iter;
if (!resultStr.IsEmpty()) {
resultStr.AppendLiteral(" ");
}
resultStr.Append(nsDependentAtomString(aAttr->AtomAt(i)));
}
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, output, true);
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, resultStr, true);
}
void
@ -299,6 +321,93 @@ nsDOMTokenList::Toggle(const nsAString& aToken,
return isPresent;
}
void
nsDOMTokenList::Replace(const nsAString& aToken,
const nsAString& aNewToken,
ErrorResult& aError)
{
// Doing this here instead of using `CheckToken` because if aToken had invalid
// characters, and aNewToken is empty, the returned error should be a
// SyntaxError, not an InvalidCharacterError.
if (aNewToken.IsEmpty()) {
aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
aError = CheckToken(aToken);
if (aError.Failed()) {
return;
}
aError = CheckToken(aNewToken);
if (aError.Failed()) {
return;
}
const nsAttrValue* attr = GetParsedAttr();
if (!attr) {
return;
}
ReplaceInternal(attr, aToken, aNewToken);
}
void
nsDOMTokenList::ReplaceInternal(const nsAttrValue* aAttr,
const nsAString& aToken,
const nsAString& aNewToken)
{
RemoveDuplicates(aAttr);
bool sawIt = false;
nsAutoString resultStr;
for (uint32_t i = 0; i < aAttr->GetAtomCount(); i++) {
if (aAttr->AtomAt(i)->Equals(aToken) ||
aAttr->AtomAt(i)->Equals(aNewToken)) {
if (sawIt) {
// We keep only the first
continue;
}
sawIt = true;
if (!resultStr.IsEmpty()) {
resultStr.AppendLiteral(" ");
}
resultStr.Append(aNewToken);
continue;
}
if (!resultStr.IsEmpty()) {
resultStr.AppendLiteral(" ");
}
resultStr.Append(nsDependentAtomString(aAttr->AtomAt(i)));
}
if (sawIt) {
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, resultStr, true);
}
}
bool
nsDOMTokenList::Supports(const nsAString& aToken,
ErrorResult& aError)
{
if (!mSupportedTokens) {
aError.ThrowTypeError<MSG_TOKENLIST_NO_SUPPORTED_TOKENS>(
mElement->LocalName(),
nsDependentAtomString(mAttrAtom));
return false;
}
for (DOMTokenListSupportedToken* supportedToken = mSupportedTokens;
*supportedToken;
++supportedToken) {
if (aToken.LowerCaseEqualsASCII(*supportedToken)) {
return true;
}
}
return false;
}
void
nsDOMTokenList::Stringify(nsAString& aResult)
{

View File

@ -13,9 +13,11 @@
#include "nsCOMPtr.h"
#include "nsDOMString.h"
#include "nsDOMString.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/DOMTokenListSupportedTokens.h"
namespace mozilla {
class ErrorResult;
@ -26,7 +28,7 @@ class nsAttrValue;
class nsIAtom;
// nsISupports must be on the primary inheritance chain
// because nsDOMSettableTokenList is traversed by Element.
class nsDOMTokenList : public nsISupports,
public nsWrapperCache
{
@ -37,7 +39,8 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMTokenList)
nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom);
nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom,
const mozilla::dom::DOMTokenListSupportedTokenArray = nullptr);
virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
@ -46,6 +49,7 @@ public:
return mElement;
}
void RemoveDuplicates(const nsAttrValue* aAttr);
uint32_t Length();
void Item(uint32_t aIndex, nsAString& aResult)
{
@ -63,9 +67,17 @@ public:
void Remove(const nsAString& aToken, mozilla::ErrorResult& aError);
void Remove(const nsTArray<nsString>& aTokens,
mozilla::ErrorResult& aError);
void Replace(const nsAString& aToken,
const nsAString& aNewToken,
mozilla::ErrorResult& aError);
bool Toggle(const nsAString& aToken,
const mozilla::dom::Optional<bool>& force,
mozilla::ErrorResult& aError);
bool Supports(const nsAString& aToken,
mozilla::ErrorResult& aError);
void GetValue(nsAString& aResult) { Stringify(aResult); }
void SetValue(const nsAString& aValue, mozilla::ErrorResult& rv);
void Stringify(nsAString& aResult);
protected:
@ -73,14 +85,20 @@ protected:
nsresult CheckToken(const nsAString& aStr);
nsresult CheckTokens(const nsTArray<nsString>& aStr);
void RemoveDuplicatesInternal(nsTArray<nsCOMPtr<nsIAtom>>* aArray,
uint32_t aStart);
void AddInternal(const nsAttrValue* aAttr,
const nsTArray<nsString>& aTokens);
void RemoveInternal(const nsAttrValue* aAttr,
const nsTArray<nsString>& aTokens);
void ReplaceInternal(const nsAttrValue* aAttr,
const nsAString& aToken,
const nsAString& aNewToken);
inline const nsAttrValue* GetParsedAttr();
nsCOMPtr<Element> mElement;
nsCOMPtr<nsIAtom> mAttrAtom;
const mozilla::dom::DOMTokenListSupportedTokenArray mSupportedTokens;
};
#endif // nsDOMTokenList_h___

View File

@ -562,7 +562,7 @@ nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
}
if (!aDontSerializeRoot) {
rv = SerializeNodeEnd(node, aStr);
rv = SerializeNodeEnd(maybeFixedNode, aStr);
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -347,17 +347,32 @@ public:
}
/**
* Return the base URI for relative URIs in the document (the document uri
* unless it's overridden by SetBaseURI, HTML <base> tags, etc.). The
* returned URI could be null if there is no document URI. If the document
* is a srcdoc document, return the parent document's base URL.
* Return the fallback base URL for this document, as defined in the HTML
* specification. Note that this can return null if there is no document URI.
*
* XXXbz: This doesn't implement the bits for about:blank yet.
*/
nsIURI* GetDocBaseURI() const
nsIURI* GetFallbackBaseURI() const
{
if (mIsSrcdocDocument && mParentDocument) {
return mParentDocument->GetDocBaseURI();
}
return mDocumentBaseURI ? mDocumentBaseURI : mDocumentURI;
return mDocumentURI;
}
/**
* Return the base URI for relative URIs in the document (the document uri
* unless it's overridden by SetBaseURI, HTML <base> tags, etc.). The
* returned URI could be null if there is no document URI. If the document is
* a srcdoc document and has no explicit base URL, return the parent
* document's base URL.
*/
nsIURI* GetDocBaseURI() const
{
if (mDocumentBaseURI) {
return mDocumentBaseURI;
}
return GetFallbackBaseURI();
}
virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;

View File

@ -93,16 +93,16 @@ const size_t gStackSize = 8192;
// The amount of time we wait from the first request to GC to actually
// doing the first GC.
#define NS_FIRST_GC_DELAY 10000 // ms
#define NS_FIRST_GC_DELAY 30000 // ms
#define NS_FULL_GC_DELAY 60000 // ms
#define NS_FULL_GC_DELAY 100000 // ms
// The default amount of time to wait from the user being idle to starting a
// shrinking GC.
#define NS_DEAULT_INACTIVE_GC_DELAY 300000 // ms
// Maximum amount of time that should elapse between incremental GC slices
#define NS_INTERSLICE_GC_DELAY 100 // ms
#define NS_INTERSLICE_GC_DELAY 1000 // ms
// If we haven't painted in 100ms, we allow for a longer GC budget
#define NS_INTERSLICE_GC_BUDGET 40 // ms
@ -111,13 +111,13 @@ const size_t gStackSize = 8192;
// and doing the actual CC.
#define NS_CC_DELAY 6000 // ms
#define NS_CC_SKIPPABLE_DELAY 250 // ms
#define NS_CC_SKIPPABLE_DELAY 2500 // ms
// Maximum amount of time that should elapse between incremental CC slices
static const int64_t kICCIntersliceDelay = 32; // ms
static const int64_t kICCIntersliceDelay = 1000; // ms
// Time budget for an incremental CC slice
static const int64_t kICCSliceBudget = 5; // ms
static const int64_t kICCSliceBudget = 100; // ms
// Maximum total duration for an ICC
static const uint32_t kMaxICCDuration = 2000; // ms
@ -125,7 +125,7 @@ static const uint32_t kMaxICCDuration = 2000; // ms
// Force a CC after this long if there's more than NS_CC_FORCED_PURPLE_LIMIT
// objects in the purple buffer.
#define NS_CC_FORCED (2 * 60 * PR_USEC_PER_SEC) // 2 min
#define NS_CC_FORCED_PURPLE_LIMIT 10
#define NS_CC_FORCED_PURPLE_LIMIT 9
// Don't allow an incremental GC to lock out the CC for too long.
#define NS_MAX_CC_LOCKEDOUT_TIME (30 * PR_USEC_PER_SEC) // 30 seconds

View File

@ -149,7 +149,9 @@ nsStyleLinkElement::IsImportEnabled()
}
static uint32_t ToLinkMask(const nsAString& aLink, nsIPrincipal* aPrincipal)
{
{
// Keep this in sync with sRelValues in HTMLLinkElement.cpp
// XXX: "icon" and "search" are supported, but not listed here.
if (aLink.EqualsLiteral("prefetch"))
return nsStyleLinkElement::ePREFETCH;
else if (aLink.EqualsLiteral("dns-prefetch"))

View File

@ -345,22 +345,22 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
// Should we optimize for aData.Length() == 0?
CheckedUint32 length = mState.mLength;
length += aLength;
if (!length.isValid()) {
return false;
// FYI: Don't use CheckedInt in this method since here is very hot path
// in some performance tests.
if (MOZ_UNLIKELY(NS_MAX_TEXT_FRAGMENT_LENGTH - mState.mLength < aLength)) {
return false; // Would be overflown if we'd keep handling.
}
if (mState.mIs2b) {
length *= sizeof(char16_t);
if (!length.isValid()) {
return false;
size_t size = mState.mLength + aLength;
if (MOZ_UNLIKELY(SIZE_MAX / sizeof(char16_t) < size)) {
return false; // Would be overflown if we'd keep handling.
}
size *= sizeof(char16_t);
// Already a 2-byte string so the result will be too
char16_t* buff = static_cast<char16_t*>(realloc(m2b, length.value()));
if (!buff) {
char16_t* buff = static_cast<char16_t*>(realloc(m2b, size));
if (MOZ_UNLIKELY(!buff)) {
return false;
}
@ -379,15 +379,16 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
int32_t first16bit = FirstNon8Bit(aBuffer, aBuffer + aLength);
if (first16bit != -1) { // aBuffer contains no non-8bit character
length *= sizeof(char16_t);
if (!length.isValid()) {
return false;
size_t size = mState.mLength + aLength;
if (MOZ_UNLIKELY((SIZE_MAX / sizeof(char16_t)) < size)) {
return false; // Would be overflown if we'd keep handling.
}
size *= sizeof(char16_t);
// The old data was 1-byte, but the new is not so we have to expand it
// all to 2-byte
char16_t* buff = static_cast<char16_t*>(malloc(length.value()));
if (!buff) {
char16_t* buff = static_cast<char16_t*>(malloc(size));
if (MOZ_UNLIKELY(!buff)) {
return false;
}
@ -414,16 +415,18 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
}
// The new and the old data is all 1-byte
size_t size = mState.mLength + aLength;
MOZ_ASSERT(sizeof(char) == 1);
char* buff;
if (mState.mInHeap) {
buff = static_cast<char*>(realloc(const_cast<char*>(m1b), length.value()));
if (!buff) {
buff = static_cast<char*>(realloc(const_cast<char*>(m1b), size));
if (MOZ_UNLIKELY(!buff)) {
return false;
}
}
else {
buff = static_cast<char*>(malloc(length.value()));
if (!buff) {
buff = static_cast<char*>(malloc(size));
if (MOZ_UNLIKELY(!buff)) {
return false;
}
@ -461,21 +464,8 @@ void
nsTextFragment::UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength)
{
if (mState.mIs2b && !mState.mIsBidi) {
const char16_t* cp = aBuffer;
const char16_t* end = cp + aLength;
while (cp < end) {
char16_t ch1 = *cp++;
uint32_t utf32Char = ch1;
if (NS_IS_HIGH_SURROGATE(ch1) &&
cp < end &&
NS_IS_LOW_SURROGATE(*cp)) {
char16_t ch2 = *cp++;
utf32Char = SURROGATE_TO_UCS4(ch1, ch2);
}
if (UTF32_CHAR_IS_BIDI(utf32Char) || IsBidiControl(utf32Char)) {
mState.mIsBidi = true;
break;
}
if (HasRTLChars(aBuffer, aLength)) {
mState.mIsBidi = true;
}
}
}

View File

@ -213,9 +213,13 @@ public:
uint32_t mInHeap : 1;
uint32_t mIs2b : 1;
uint32_t mIsBidi : 1;
// Note that when you change the bits of mLength, you also need to change
// NS_MAX_TEXT_FRAGMENT_LENGTH.
uint32_t mLength : 29;
};
#define NS_MAX_TEXT_FRAGMENT_LENGTH (static_cast<uint32_t>(0x1FFFFFFF))
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
private:

View File

@ -441,10 +441,6 @@ DOMInterfaces = {
'implicitJSContext': [ 'then' ],
},
'DOMSettableTokenList': {
'nativeType': 'nsDOMSettableTokenList',
},
'DOMStringMap': {
'nativeType': 'nsDOMStringMap'
},

View File

@ -1136,11 +1136,13 @@ class CGHeaders(CGWrapper):
if desc.interface.maplikeOrSetlikeOrIterable:
# We need ToJSValue.h for maplike/setlike type conversions
bindingHeaders.add("mozilla/dom/ToJSValue.h")
# Add headers for the key and value types of the maplike, since
# they'll be needed for convenience functions
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.keyType,
desc, None))
if desc.interface.maplikeOrSetlikeOrIterable.valueType:
# Add headers for the key and value types of the
# maplike/setlike/iterable, since they'll be needed for
# convenience functions
if desc.interface.maplikeOrSetlikeOrIterable.hasKeyType():
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.keyType,
desc, None))
if desc.interface.maplikeOrSetlikeOrIterable.hasValueType():
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.valueType,
desc, None))
@ -2269,34 +2271,50 @@ class MethodDefiner(PropertyDefiner):
"condition": MemberCondition()
})
# Generate the maplike/setlike iterator, if one wasn't already
# generated by a method. If we already have an @@iterator symbol, fail.
if descriptor.interface.maplikeOrSetlikeOrIterable:
if hasIterator(methods, self.regular):
raise TypeError("Cannot have maplike/setlike/iterable interface with "
"other members that generate @@iterator "
"on interface %s, such as indexed getters "
"or aliased functions." %
self.descriptor.interface.identifier.name)
for m in methods:
if (m.isMaplikeOrSetlikeOrIterableMethod() and
(((m.maplikeOrSetlikeOrIterable.isMaplike() or
(m.maplikeOrSetlikeOrIterable.isIterable() and
m.maplikeOrSetlikeOrIterable.hasValueType())) and
m.identifier.name == "entries") or
(((m.maplikeOrSetlikeOrIterable.isSetlike() or
(m.maplikeOrSetlikeOrIterable.isIterable() and
not m.maplikeOrSetlikeOrIterable.hasValueType()))) and
m.identifier.name == "values"))):
self.regular.append({
"name": "@@iterator",
"methodName": m.identifier.name,
"length": methodLength(m),
"flags": "0",
"condition": PropertyDefiner.getControllingCondition(m,
descriptor),
})
break
# Generate the keys/values/entries aliases for value iterables.
maplikeOrSetlikeOrIterable = descriptor.interface.maplikeOrSetlikeOrIterable
if (not static and
not unforgeable and
maplikeOrSetlikeOrIterable and
maplikeOrSetlikeOrIterable.isIterable() and
maplikeOrSetlikeOrIterable.isValueIterator()):
# Add our keys/values/entries/forEach
self.regular.append({
"name": "keys",
"methodInfo": False,
"selfHostedName": "ArrayKeys",
"length": 0,
"flags": "JSPROP_ENUMERATE",
"condition": PropertyDefiner.getControllingCondition(m,
descriptor)
})
self.regular.append({
"name": "values",
"methodInfo": False,
"selfHostedName": "ArrayValues",
"length": 0,
"flags": "JSPROP_ENUMERATE",
"condition": PropertyDefiner.getControllingCondition(m,
descriptor)
})
self.regular.append({
"name": "entries",
"methodInfo": False,
"selfHostedName": "ArrayEntries",
"length": 0,
"flags": "JSPROP_ENUMERATE",
"condition": PropertyDefiner.getControllingCondition(m,
descriptor)
})
self.regular.append({
"name": "forEach",
"methodInfo": False,
"selfHostedName": "ArrayForEach",
"length": 1,
"flags": "JSPROP_ENUMERATE",
"condition": PropertyDefiner.getControllingCondition(m,
descriptor)
})
if not static:
stringifier = descriptor.operations['Stringifier']
@ -13008,8 +13026,9 @@ class CGForwardDeclarations(CGWrapper):
# arguments to helper functions, and they'll need to be forward
# declared in the header.
if d.interface.maplikeOrSetlikeOrIterable:
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.keyType,
config)
if d.interface.maplikeOrSetlikeOrIterable.hasKeyType():
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.keyType,
config)
if d.interface.maplikeOrSetlikeOrIterable.hasValueType():
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.valueType,
config)
@ -15735,6 +15754,31 @@ class CGIterableMethodGenerator(CGGeneric):
using CGCallGenerator.
"""
def __init__(self, descriptor, iterable, methodName):
if methodName == "forEach":
CGGeneric.__init__(self, fill(
"""
if (!JS::IsCallable(arg0)) {
ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 1 of ${ifaceName}.forEach");
return false;
}
JS::AutoValueArray<3> callArgs(cx);
callArgs[2].setObject(*obj);
JS::Rooted<JS::Value> ignoredReturnVal(cx);
for (size_t i = 0; i < self->GetIterableLength(); ++i) {
if (!ToJSValue(cx, self->GetValueAtIndex(i), callArgs[0])) {
return false;
}
if (!ToJSValue(cx, self->GetKeyAtIndex(i), callArgs[1])) {
return false;
}
if (!JS::Call(cx, arg1, arg0, JS::HandleValueArray(callArgs),
&ignoredReturnVal)) {
return false;
}
}
""",
ifaceName=descriptor.interface.identifier.name))
return
CGGeneric.__init__(self, fill(
"""
typedef ${iterClass} itrType;

View File

@ -893,8 +893,5 @@ def getAllTypes(descriptors, dictionaries, callbacks):
def iteratorNativeType(descriptor):
assert descriptor.interface.isIterable()
iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
if iterableDecl.valueType is None:
iterClass = "OneTypeIterableIterator"
else:
iterClass = "TwoTypeIterableIterator"
return "mozilla::dom::%s<%s>" % (iterClass, descriptor.nativeType)
assert iterableDecl.isPairIterator()
return "mozilla::dom::IterableIterator<%s>" % descriptor.nativeType

View File

@ -92,3 +92,4 @@ MSG_DEF(MSG_IS_NOT_PROMISE, 1, JSEXN_TYPEERR, "{0} is not a Promise")
MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} encountered an error during installation.")
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a typed array on SharedArrayBuffer")
MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")

View File

@ -6,19 +6,17 @@
/**
* The IterableIterator class is used for WebIDL interfaces that have a
* iterable<> member defined. It handles the ES6 Iterator-like functions that
* are generated for the iterable interface.
* iterable<> member defined with two types (so a pair iterator). It handles
* the ES6 Iterator-like functions that are generated for the iterable
* interface.
*
* For iterable interfaces, the implementation class will need to
* implement these two functions:
* For iterable interfaces with a pair iterator, the implementation class will
* need to implement these two functions:
*
* - size_t GetIterableLength()
* - Returns the number of elements available to iterate over
* - [type] GetValueAtIndex(size_t index)
* - Returns the value at the requested index.
*
* If this is a two-type iterator, then the implementation class will also need to implement:
*
* - [type] GetKeyAtIndex(size_t index)
* - Returns the key at the requested index
*
@ -60,13 +58,77 @@ protected:
};
template <typename T>
class IterableIterator : public IterableIteratorBase
class IterableIterator final : public IterableIteratorBase
{
public:
explicit IterableIterator(T* aIterableObj)
typedef bool (*WrapFunc)(JSContext* aCx,
IterableIterator<T>* aObject,
JS::Handle<JSObject*> aGivenProto,
JS::MutableHandle<JSObject*> aReflector);
explicit IterableIterator(T* aIterableObj,
IterableIteratorType aIteratorType,
WrapFunc aWrapFunc)
: mIterableObj(aIterableObj)
, mIteratorType(aIteratorType)
, mWrapFunc(aWrapFunc)
, mIndex(0)
{
MOZ_ASSERT(mIterableObj);
MOZ_ASSERT(mWrapFunc);
}
void
Next(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv)
{
JS::Rooted<JS::Value> value(aCx, JS::UndefinedValue());
if (mIndex >= this->mIterableObj->GetIterableLength()) {
DictReturn(aCx, aResult, true, value, aRv);
return;
}
switch (mIteratorType) {
case IterableIteratorType::Keys:
{
if (!ToJSValue(aCx, this->mIterableObj->GetKeyAtIndex(mIndex), &value)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
DictReturn(aCx, aResult, false, value, aRv);
break;
}
case IterableIteratorType::Values:
{
if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
DictReturn(aCx, aResult, false, value, aRv);
break;
}
case IterableIteratorType::Entries:
{
JS::Rooted<JS::Value> key(aCx);
if (!ToJSValue(aCx, this->mIterableObj->GetKeyAtIndex(mIndex), &key)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
KeyAndValueReturn(aCx, key, value, aResult, aRv);
break;
}
default:
MOZ_CRASH("Invalid iterator type!");
}
++mIndex;
}
bool
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aObj)
{
return (*mWrapFunc)(aCx, this, aGivenProto, aObj);
}
protected:
@ -128,161 +190,6 @@ protected:
// Binding Implementation object that we're iterating over.
RefPtr<T> mIterableObj;
};
template<typename T>
class OneTypeIterableIterator final : public IterableIterator<T>
{
public:
typedef typename IterableIterator<T>::IterableIteratorType IterableIteratorType;
using IterableIterator<T>::DictReturn;
using IterableIterator<T>::KeyAndValueReturn;
typedef bool (*WrapFunc)(JSContext* aCx,
OneTypeIterableIterator<T>* aObject,
JS::Handle<JSObject*> aGivenProto,
JS::MutableHandle<JSObject*> aReflector);
OneTypeIterableIterator(T* aIterableObj,
IterableIteratorType aIteratorType,
WrapFunc aWrapFunc)
: IterableIterator<T>(aIterableObj)
, mIteratorType(aIteratorType)
, mWrapFunc(aWrapFunc)
, mIndex(0)
{
MOZ_ASSERT(mWrapFunc);
}
void
Next(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv)
{
JS::Rooted<JS::Value> value(aCx, JS::UndefinedValue());
if (mIndex >= this->mIterableObj->GetIterableLength()) {
DictReturn(aCx, aResult, true, value, aRv);
return;
}
switch (mIteratorType) {
case IterableIteratorType::Keys:
case IterableIteratorType::Values:
{
if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
DictReturn(aCx, aResult, false, value, aRv);
break;
}
case IterableIteratorType::Entries:
{
if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
KeyAndValueReturn(aCx, value, value, aResult, aRv);
break;
}
default:
MOZ_CRASH("Invalid iterator type!");
}
++mIndex;
}
bool
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aObj)
{
return (*mWrapFunc)(aCx, this, aGivenProto, aObj);
}
protected:
virtual ~OneTypeIterableIterator() {}
// Tells whether this is a key, value, or entries iterator.
IterableIteratorType mIteratorType;
// Function pointer to binding-type-specific Wrap() call for this iterator.
WrapFunc mWrapFunc;
// Current index of iteration.
uint32_t mIndex;
};
template<typename T>
class TwoTypeIterableIterator final : public IterableIterator<T>
{
public:
typedef typename IterableIterator<T>::IterableIteratorType IterableIteratorType;
using IterableIterator<T>::DictReturn;
using IterableIterator<T>::KeyAndValueReturn;
typedef bool (*WrapFunc)(JSContext* aCx,
TwoTypeIterableIterator<T>* aObject,
JS::Handle<JSObject*> aGivenProto,
JS::MutableHandle<JSObject*> aReflector);
TwoTypeIterableIterator(T* aIterableObj, IterableIteratorType aIteratorType,
WrapFunc aWrapFunc)
: IterableIterator<T>(aIterableObj)
, mIteratorType(aIteratorType)
, mWrapFunc(aWrapFunc)
, mIndex(0)
{
MOZ_ASSERT(mWrapFunc);
}
void
Next(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv)
{
JS::Rooted<JS::Value> value(aCx, JS::UndefinedValue());
if (mIndex >= this->mIterableObj->GetIterableLength()) {
DictReturn(aCx, aResult, true, value, aRv);
return;
}
switch (mIteratorType) {
case IterableIteratorType::Keys:
{
if (!ToJSValue(aCx, this->mIterableObj->GetKeyAtIndex(mIndex), &value)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
DictReturn(aCx, aResult, false, value, aRv);
break;
}
case IterableIteratorType::Values:
{
if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
DictReturn(aCx, aResult, false, value, aRv);
break;
}
case IterableIteratorType::Entries:
{
JS::Rooted<JS::Value> key(aCx);
if (!ToJSValue(aCx, this->mIterableObj->GetKeyAtIndex(mIndex), &key)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
KeyAndValueReturn(aCx, key, value, aResult, aRv);
break;
}
default:
MOZ_CRASH("Invalid iterator type!");
}
++mIndex;
}
bool
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aObj)
{
return (*mWrapFunc)(aCx, this, aGivenProto, aObj);
}
protected:
virtual ~TwoTypeIterableIterator() {}
// Tells whether this is a key, value, or entries iterator.
IterableIteratorType mIteratorType;
// Function pointer to binding-type-specific Wrap() call for this iterator.

View File

@ -1089,7 +1089,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
def validate(self):
# We don't support consequential unforgeable interfaces. Need to check
# this here, becaue in finish() an interface might not know yet that
# this here, because in finish() an interface might not know yet that
# it's consequential.
if self.getExtendedAttribute("Unforgeable") and self.isConsequential():
raise WebIDLError(
@ -1108,6 +1108,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
self.identifier.name,
locations)
indexedGetter = None
hasLengthAttribute = False
for member in self.members:
member.validate()
@ -1118,8 +1120,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
[self.location, member.location])
# Check that PutForwards refers to another attribute and that no
# cycles exist in forwarded assignments.
# cycles exist in forwarded assignments. Also check for a
# integer-typed "length" attribute.
if member.isAttr():
if (member.identifier.name == "length" and
member.type.isInteger()):
hasLengthAttribute = True
iface = self
attr = member
putForwards = attr.getExtendedAttribute("PutForwards")
@ -1157,8 +1164,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
putForwards = attr.getExtendedAttribute("PutForwards")
# Check that the name of an [Alias] doesn't conflict with an
# interface member.
# interface member and whether we support indexed properties.
if member.isMethod():
if member.isGetter() and member.isIndexed():
indexedGetter = member
for alias in member.aliases:
if self.isOnGlobalProtoChain():
raise WebIDLError("[Alias] must not be used on a "
@ -1219,6 +1229,35 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
"exposed conditionally",
[self.location])
# Value iterators are only allowed on interfaces with indexed getters,
# and pair iterators are only allowed on interfaces without indexed
# getters.
if self.isIterable():
iterableDecl = self.maplikeOrSetlikeOrIterable
if iterableDecl.isValueIterator():
if not indexedGetter:
raise WebIDLError("Interface with value iterator does not "
"support indexed properties",
[self.location])
if iterableDecl.valueType != indexedGetter.signatures()[0][0]:
raise WebIDLError("Iterable type does not match indexed "
"getter type",
[iterableDecl.location,
indexedGetter.location])
if not hasLengthAttribute:
raise WebIDLError('Interface with value iterator does not '
'have an integer-typed "length" attribute',
[self.location])
else:
assert iterableDecl.isPairIterator()
if indexedGetter:
raise WebIDLError("Interface with pair iterator supports "
"indexed properties",
[self.location, iterableDecl.location,
indexedGetter.location])
def isInterface(self):
return True
@ -3408,7 +3447,10 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
assert isinstance(keyType, IDLType)
if keyType is not None:
assert isinstance(keyType, IDLType)
else:
assert valueType is not None
assert ifaceType in ['maplike', 'setlike', 'iterable']
if valueType is not None:
assert isinstance(valueType, IDLType)
@ -3427,6 +3469,9 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
def isIterable(self):
return self.maplikeOrSetlikeOrIterableType == "iterable"
def hasKeyType(self):
return self.keyType is not None
def hasValueType(self):
return self.valueType is not None
@ -3451,7 +3496,8 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
[self.location, member.location])
def addMethod(self, name, members, allowExistingOperations, returnType, args=[],
chromeOnly=False, isPure=False, affectsNothing=False, newObject=False):
chromeOnly=False, isPure=False, affectsNothing=False, newObject=False,
isIteratorAlias=False):
"""
Create an IDLMethod based on the parameters passed in.
@ -3511,16 +3557,20 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
if newObject:
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("NewObject",))])
if isIteratorAlias:
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("Alias", "@@iterator"))])
members.append(method)
def resolve(self, parentScope):
self.keyType.resolveType(parentScope)
if self.keyType:
self.keyType.resolveType(parentScope)
if self.valueType:
self.valueType.resolveType(parentScope)
def finish(self, scope):
IDLInterfaceMember.finish(self, scope)
if not self.keyType.isComplete():
if self.keyType and not self.keyType.isComplete():
t = self.keyType.complete(scope)
assert not isinstance(t, IDLUnresolvedType)
@ -3542,9 +3592,23 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
IDLInterfaceMember.handleExtendedAttribute(self, attr)
def _getDependentObjects(self):
deps = set()
if self.keyType:
deps.add(self.keyType)
if self.valueType:
return set([self.keyType, self.valueType])
return set([self.keyType])
deps.add(self.valueType)
return deps
def getForEachArguments(self):
return [IDLArgument(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
"callback"),
BuiltinTypes[IDLBuiltinType.Types.object]),
IDLArgument(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
"thisArg"),
BuiltinTypes[IDLBuiltinType.Types.any],
optional=True)]
# Iterable adds ES6 iterator style functions and traits
# (keys/values/entries/@@iterator) to an interface.
@ -3565,9 +3629,15 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
we generate our functions as if they were part of the interface
specification during parsing.
"""
# We only need to add entries/keys/values here if we're a pair iterator.
# Value iterators just copy these from %ArrayPrototype% instead.
if not self.isPairIterator():
return
# object entries()
self.addMethod("entries", members, False, self.iteratorType,
affectsNothing=True, newObject=True)
affectsNothing=True, newObject=True,
isIteratorAlias=True)
# object keys()
self.addMethod("keys", members, False, self.iteratorType,
affectsNothing=True, newObject=True)
@ -3575,6 +3645,17 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
self.addMethod("values", members, False, self.iteratorType,
affectsNothing=True, newObject=True)
# void forEach(callback(valueType, keyType), optional any thisArg)
self.addMethod("forEach", members, False,
BuiltinTypes[IDLBuiltinType.Types.void],
self.getForEachArguments())
def isValueIterator(self):
return not self.isPairIterator()
def isPairIterator(self):
return self.hasKeyType()
# MaplikeOrSetlike adds ES6 map-or-set-like traits to an interface.
class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
@ -3611,26 +3692,17 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
# object entries()
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
affectsNothing=True, isIteratorAlias=self.isMaplike())
# object keys()
self.addMethod("keys", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
# object values()
self.addMethod("values", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
affectsNothing=True, isIteratorAlias=self.isSetlike())
# void forEach(callback(valueType, keyType), thisVal)
foreachArguments = [IDLArgument(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
"callback"),
BuiltinTypes[IDLBuiltinType.Types.object]),
IDLArgument(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
"thisArg"),
BuiltinTypes[IDLBuiltinType.Types.any],
optional=True)]
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
foreachArguments)
self.getForEachArguments())
def getKeyArg():
return IDLArgument(self.location,
@ -5436,10 +5508,13 @@ class Parser(Tokenizer):
location = self.getLocation(p, 2)
identifier = IDLUnresolvedIdentifier(location, "__iterable",
allowDoubleUnderscore=True)
keyType = p[3]
valueType = None
if (len(p) > 6):
keyType = p[3]
valueType = p[5]
else:
keyType = None
valueType = p[3]
p[0] = IDLIterable(location, identifier, keyType, valueType, self.globalScope())
def p_Setlike(self, p):
@ -6509,7 +6584,7 @@ class Parser(Tokenizer):
if isinstance(m, IDLIterable):
iterable = m
break
if iterable:
if iterable and iterable.isPairIterator():
def simpleExtendedAttr(str):
return IDLExtendedAttribute(iface.location, (str, ))
nextMethod = IDLMethod(

View File

@ -55,17 +55,22 @@ TestInterfaceIterableSingle::GetParentObject() const
return mParent;
}
size_t
TestInterfaceIterableSingle::GetIterableLength() const
uint32_t
TestInterfaceIterableSingle::Length() const
{
return mValues.Length();
}
uint32_t
TestInterfaceIterableSingle::GetValueAtIndex(uint32_t index) const
int32_t
TestInterfaceIterableSingle::IndexedGetter(uint32_t aIndex, bool& aFound) const
{
MOZ_ASSERT(index < mValues.Length());
return mValues.ElementAt(index);
if (aIndex >= mValues.Length()) {
aFound = false;
return 0;
}
aFound = true;
return mValues[aIndex];
}
} // namespace dom

View File

@ -36,12 +36,13 @@ public:
static already_AddRefed<TestInterfaceIterableSingle>
Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
size_t GetIterableLength() const;
uint32_t GetValueAtIndex(uint32_t aIndex) const;
uint32_t Length() const;
int32_t IndexedGetter(uint32_t aIndex, bool& aFound) const;
private:
virtual ~TestInterfaceIterableSingle() {}
nsCOMPtr<nsPIDOMWindow> mParent;
nsTArray<uint32_t> mValues;
nsTArray<int32_t> mValues;
};
} // namespace dom

View File

@ -39,6 +39,12 @@ ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
#undef ANCHOR_ELEMENT_FLAG_BIT
// static
const DOMTokenListSupportedToken HTMLAnchorElement::sSupportedRelValues[] = {
"noreferrer",
nullptr
};
HTMLAnchorElement::~HTMLAnchorElement()
{
}
@ -302,7 +308,7 @@ nsDOMTokenList*
HTMLAnchorElement::RelList()
{
if (!mRelList) {
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel);
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues);
}
return mRelList;
}

View File

@ -227,6 +227,8 @@ public:
GetHref(aResult);
}
static DOMTokenListSupportedToken sSupportedRelValues[];
protected:
virtual ~HTMLAnchorElement();

View File

@ -7,6 +7,7 @@
#include "mozilla/dom/HTMLAreaElement.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/HTMLAnchorElement.h"
#include "mozilla/dom/HTMLAreaElementBinding.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventStates.h"
@ -122,7 +123,8 @@ nsDOMTokenList*
HTMLAreaElement::RelList()
{
if (!mRelList) {
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel);
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel,
HTMLAnchorElement::sSupportedRelValues);
}
return mRelList;
}

View File

@ -18,6 +18,15 @@ NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame)
namespace mozilla {
namespace dom {
// static
const DOMTokenListSupportedToken HTMLIFrameElement::sSupportedSandboxTokens[] =
{
#define SANDBOX_KEYWORD(string, atom, flags) string,
#include "IframeSandboxKeywordList.h"
#undef SANDBOX_KEYWORD
nullptr
};
HTMLIFrameElement::HTMLIFrameElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
FromParser aFromParser)
: nsGenericHTMLFrameElement(aNodeInfo, aFromParser)

View File

@ -10,7 +10,7 @@
#include "mozilla/Attributes.h"
#include "nsGenericHTMLFrameElement.h"
#include "nsIDOMHTMLIFrameElement.h"
#include "nsDOMSettableTokenList.h"
#include "nsDOMTokenList.h"
namespace mozilla {
namespace dom {
@ -84,9 +84,9 @@ public:
{
SetHTMLAttr(nsGkAtoms::name, aName, aError);
}
nsDOMSettableTokenList* Sandbox()
nsDOMTokenList* Sandbox()
{
return GetTokenList(nsGkAtoms::sandbox);
return GetTokenList(nsGkAtoms::sandbox, sSupportedSandboxTokens);
}
bool AllowFullscreen() const
{
@ -202,6 +202,8 @@ protected:
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsRuleData* aData);
static const DOMTokenListSupportedToken sSupportedSandboxTokens[];
};
} // namespace dom

View File

@ -26,6 +26,7 @@
#include "nsPIDOMWindow.h"
#include "nsReadableUtils.h"
#include "nsStyleConsts.h"
#include "nsStyleLinkElement.h"
#include "nsUnicharUtils.h"
#define LINK_ELEMENT_FLAG_BIT(n_) \
@ -499,11 +500,30 @@ HTMLLinkElement::GetLinkTarget(nsAString& aTarget)
}
}
static const DOMTokenListSupportedToken sSupportedRelValues[] = {
// Keep this in sync with ToLinkMask in nsStyleLinkElement.cpp.
// "import" must come first because it's conditional.
"import"
"prefetch",
"dns-prefetch",
"stylesheet",
"next",
"alternate",
"preconnect",
"icon",
"search",
nullptr
};
nsDOMTokenList*
HTMLLinkElement::RelList()
{
if (!mRelList) {
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel);
const DOMTokenListSupportedTokenArray relValues =
nsStyleLinkElement::IsImportEnabled() ?
sSupportedRelValues : &sSupportedRelValues[1];
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, relValues);
}
return mRelList;
}

View File

@ -119,7 +119,7 @@ public:
{
SetHTMLAttr(nsGkAtoms::hreflang, aHreflang, aRv);
}
nsDOMSettableTokenList* Sizes()
nsDOMTokenList* Sizes()
{
return GetTokenList(nsGkAtoms::sizes);
}

View File

@ -11,6 +11,7 @@
#include "mozilla/dom/HTMLMenuItemElementBinding.h"
#include "nsAttrValueInlines.h"
#include "nsContentUtils.h"
#include "nsDOMTokenList.h"
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(MenuItem)

View File

@ -11,7 +11,6 @@
#include "mozilla/dom/HTMLFormElement.h"
#include "mozilla/dom/HTMLOutputElementBinding.h"
#include "nsContentUtils.h"
#include "nsDOMSettableTokenList.h"
#include "nsFormSubmission.h"
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output)
@ -166,11 +165,11 @@ HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult&
}
}
nsDOMSettableTokenList*
nsDOMTokenList*
HTMLOutputElement::HtmlFor()
{
if (!mTokenList) {
mTokenList = new nsDOMSettableTokenList(this, nsGkAtoms::_for);
mTokenList = new nsDOMTokenList(this, nsGkAtoms::_for);
}
return mTokenList;
}

View File

@ -64,7 +64,7 @@ public:
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
// WebIDL
nsDOMSettableTokenList* HtmlFor();
nsDOMTokenList* HtmlFor();
// nsGenericHTMLFormElement::GetForm is fine.
void GetName(nsAString& aName)
{
@ -108,7 +108,7 @@ protected:
ValueModeFlag mValueModeFlag;
bool mIsDoneAddingChildren;
nsString mDefaultValue;
RefPtr<nsDOMSettableTokenList> mTokenList;
RefPtr<nsDOMTokenList> mTokenList;
};
} // namespace dom

View File

@ -9,7 +9,7 @@
#include "nsContentUtils.h"
#include "nsGenericHTMLElement.h"
#include "nsVariant.h"
#include "nsDOMSettableTokenList.h"
#include "nsDOMTokenList.h"
#include "nsAttrValue.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/dom/HTMLPropertiesCollectionBinding.h"

View File

@ -164,14 +164,15 @@ SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch)
return;
}
// Resolve the <base> element's href relative to our document URI
// Resolve the <base> element's href relative to our document's
// fallback base URI.
nsAutoString href;
child->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
nsCOMPtr<nsIURI> newBaseURI;
nsContentUtils::NewURIWithDocumentCharset(
getter_AddRefs(newBaseURI), href, aDocument,
aDocument->GetDocumentURI());
aDocument->GetFallbackBaseURI());
// Try to set our base URI. If that fails, try to set base URI to null
nsresult rv = aDocument->SetBaseURI(newBaseURI);

View File

@ -47,7 +47,7 @@ public:
{
SetUnsignedIntAttr(nsGkAtoms::rowspan, aRowSpan, aError);
}
//already_AddRefed<nsDOMSettableTokenList> Headers() const;
//already_AddRefed<nsDOMTokenList> Headers() const;
void GetHeaders(DOMString& aHeaders)
{
GetHTMLAttr(nsGkAtoms::headers, aHeaders);

View File

@ -96,7 +96,7 @@
#include "HTMLPropertiesCollection.h"
#include "nsVariant.h"
#include "nsDOMSettableTokenList.h"
#include "nsDOMTokenList.h"
#include "nsThreadUtils.h"
#include "nsTextFragment.h"
#include "mozilla/dom/BindingUtils.h"

View File

@ -20,7 +20,7 @@
#include "mozilla/dom/ValidityState.h"
#include "mozilla/dom/ElementInlines.h"
class nsDOMSettableTokenList;
class nsDOMTokenList;
class nsIDOMHTMLMenuElement;
class nsIEditor;
class nsIFormControlFrame;
@ -104,7 +104,7 @@ public:
{
SetHTMLBoolAttr(nsGkAtoms::itemscope, aItemScope, aError);
}
nsDOMSettableTokenList* ItemType()
nsDOMTokenList* ItemType()
{
return GetTokenList(nsGkAtoms::itemtype);
}
@ -116,11 +116,11 @@ public:
{
SetHTMLAttr(nsGkAtoms::itemid, aItemID, aError);
}
nsDOMSettableTokenList* ItemRef()
nsDOMTokenList* ItemRef()
{
return GetTokenList(nsGkAtoms::itemref);
}
nsDOMSettableTokenList* ItemProp()
nsDOMTokenList* ItemProp()
{
return GetTokenList(nsGkAtoms::itemprop);
}

View File

@ -32,7 +32,7 @@ interface nsIDOMHTMLElement : nsIDOMElement
attribute nsIVariant itemType;
attribute DOMString itemId;
readonly attribute nsISupports properties;
// The following attributes are really nsDOMSettableTokenList, which has
// The following attributes are really nsDOMTokenList, which has
// PutForwards, so we express them as nsIVariants to deal with this.
attribute nsIVariant itemValue;
attribute nsIVariant itemProp;

View File

@ -79,7 +79,7 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
return aPlane.mWidth <= PlanarYCbCrImage::MAX_DIMENSION &&
aPlane.mHeight <= PlanarYCbCrImage::MAX_DIMENSION &&
aPlane.mWidth * aPlane.mHeight < MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
aPlane.mStride > 0;
aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride;
}
#ifdef MOZ_WIDGET_GONK

View File

@ -460,6 +460,18 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem,
float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS];
domItem->ToSVGPathSegEncodedData(segAsRaw);
if (AnimListMirrorsBaseList()) {
// The anim val list is in sync with the base val list - remove mirroring
// animVal item if necessary. We do this *before* touching InternalList()
// so the removed item can correctly store its internal value.
DOMSVGPathSegList* animVal =
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
if (animVal->ItemAt(aIndex)) {
animVal->ItemAt(aIndex)->RemovingFromList();
animVal->ItemAt(aIndex) = nullptr;
}
}
if (!InternalList().mData.ReplaceElementsAt(internalIndex, 1 + oldArgCount,
segAsRaw, 1 + newArgCount,
fallible)) {
@ -474,8 +486,13 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem,
int32_t delta = newArgCount - oldArgCount;
if (delta != 0) {
for (uint32_t i = aIndex + 1; i < LengthNoFlush(); ++i) {
mItems[i].mInternalDataIndex += delta;
// Sync up the internal indexes of all ItemProxys that come after aIndex:
UpdateListIndicesFromIndex(aIndex + 1, delta);
if (AnimListMirrorsBaseList()) {
// The anim val list is in sync with the base val list
DOMSVGPathSegList* animVal =
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
animVal->UpdateListIndicesFromIndex(aIndex + 1, delta);
}
}

View File

@ -20,6 +20,13 @@ interface DOMTokenList {
[Throws]
void remove(DOMString... tokens);
[Throws]
void replace(DOMString token, DOMString newToken);
[Throws]
boolean toggle(DOMString token, optional boolean force);
[Throws]
boolean supports(DOMString token);
[SetterThrows]
attribute DOMString value;
stringifier DOMString ();
iterable<DOMString?>;
};

View File

@ -30,7 +30,7 @@ interface Element : Node {
attribute DOMString id;
[Pure]
attribute DOMString className;
[Constant]
[Constant, PutForwards=value]
readonly attribute DOMTokenList classList;
[SameObject]

View File

@ -23,6 +23,7 @@ interface HTMLAnchorElement : HTMLElement {
attribute DOMString rel;
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
attribute DOMString referrerPolicy;
[PutForwards=value]
readonly attribute DOMTokenList relList;
[SetterThrows]
attribute DOMString hreflang;

View File

@ -30,6 +30,7 @@ interface HTMLAreaElement : HTMLElement {
attribute DOMString rel;
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
attribute DOMString referrerPolicy;
[PutForwards=value]
readonly attribute DOMTokenList relList;
};

View File

@ -28,11 +28,11 @@ interface HTMLElement : Element {
// microdata
[SetterThrows, Pure]
attribute boolean itemScope;
[PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemType;
[PutForwards=value,Constant] readonly attribute DOMTokenList itemType;
[SetterThrows, Pure]
attribute DOMString itemId;
[PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemRef;
[PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemProp;
[PutForwards=value,Constant] readonly attribute DOMTokenList itemRef;
[PutForwards=value,Constant] readonly attribute DOMTokenList itemProp;
[Constant]
readonly attribute HTMLPropertiesCollection properties;
[Throws]
@ -54,7 +54,7 @@ interface HTMLElement : Element {
readonly attribute DOMString accessKeyLabel;
[SetterThrows, Pure]
attribute boolean draggable;
//[PutForwards=value] readonly attribute DOMSettableTokenList dropzone;
//[PutForwards=value] readonly attribute DOMTokenList dropzone;
[SetterThrows, Pure]
attribute DOMString contentEditable;
[Pure]

View File

@ -18,7 +18,7 @@ interface HTMLIFrameElement : HTMLElement {
attribute DOMString srcdoc;
[SetterThrows, Pure]
attribute DOMString name;
[PutForwards=value] readonly attribute DOMSettableTokenList sandbox;
[PutForwards=value] readonly attribute DOMTokenList sandbox;
// attribute boolean seamless;
[SetterThrows, Pure]
attribute boolean allowFullscreen;

View File

@ -21,6 +21,7 @@ interface HTMLLinkElement : HTMLElement {
attribute DOMString? crossOrigin;
[SetterThrows, Pure]
attribute DOMString rel;
[PutForwards=value]
readonly attribute DOMTokenList relList;
[SetterThrows, Pure]
attribute DOMString media;
@ -28,7 +29,7 @@ interface HTMLLinkElement : HTMLElement {
attribute DOMString hreflang;
[SetterThrows, Pure]
attribute DOMString type;
[PutForwards=value] readonly attribute DOMSettableTokenList sizes;
[PutForwards=value] readonly attribute DOMTokenList sizes;
};
HTMLLinkElement implements LinkStyle;

View File

@ -14,7 +14,7 @@
// http://www.whatwg.org/specs/web-apps/current-work/#the-output-element
interface HTMLOutputElement : HTMLElement {
[PutForwards=value, Constant]
readonly attribute DOMSettableTokenList htmlFor;
readonly attribute DOMTokenList htmlFor;
readonly attribute HTMLFormElement? form;
[SetterThrows, Pure]
attribute DOMString name;

View File

@ -16,7 +16,7 @@ interface HTMLTableCellElement : HTMLElement {
attribute unsigned long colSpan;
[SetterThrows]
attribute unsigned long rowSpan;
//[PutForwards=value] readonly attribute DOMSettableTokenList headers;
//[PutForwards=value] readonly attribute DOMTokenList headers;
[SetterThrows]
attribute DOMString headers;
readonly attribute long cellIndex;

View File

@ -13,4 +13,5 @@
interface NodeList {
getter Node? item(unsigned long index);
readonly attribute unsigned long length;
iterable<Node?>;
};

View File

@ -50,6 +50,8 @@ interface TestInterfaceSetlikeNode {
Pref="dom.expose_test_interfaces"]
interface TestInterfaceIterableSingle {
iterable<long>;
getter long(unsigned long index);
readonly attribute unsigned long length;
};
[Constructor(),

View File

@ -132,7 +132,6 @@ WEBIDL_FILES = [
'DOMRect.webidl',
'DOMRectList.webidl',
'DOMRequest.webidl',
'DOMSettableTokenList.webidl',
'DOMStringList.webidl',
'DOMStringMap.webidl',
'DOMTokenList.webidl',

View File

@ -176,7 +176,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsEditor)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventListener)
if (tmp->mEventListener) {
nsEditorEventListener* listener =
reinterpret_cast<nsEditorEventListener*>(tmp->mEventListener.get());
listener->Disconnect();
tmp->mEventListener = nullptr;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEditor)

View File

@ -430,12 +430,15 @@ static void
CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
const gfx::IntSize &aSize, int32_t aStride, int32_t aSkip)
{
int32_t height = aSize.height;
int32_t width = aSize.width;
MOZ_RELEASE_ASSERT(width <= aStride);
if (!aSkip) {
// Fast path: planar input.
memcpy(aDst, aSrc, aSize.height * aStride);
memcpy(aDst, aSrc, height * aStride);
} else {
int32_t height = aSize.height;
int32_t width = aSize.width;
for (int y = 0; y < height; ++y) {
const uint8_t *src = aSrc;
uint8_t *dst = aDst;
@ -453,13 +456,11 @@ CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
bool
RecyclingPlanarYCbCrImage::CopyData(const Data& aData)
{
mData = aData;
// update buffer size
// Use uint32_t throughout to match AllocateBuffer's param and mBufferSize
const auto checkedSize =
CheckedInt<uint32_t>(mData.mCbCrStride) * mData.mCbCrSize.height * 2 +
CheckedInt<uint32_t>(mData.mYStride) * mData.mYSize.height;
CheckedInt<uint32_t>(aData.mCbCrStride) * aData.mCbCrSize.height * 2 +
CheckedInt<uint32_t>(aData.mYStride) * aData.mYSize.height;
if (!checkedSize.isValid())
return false;
@ -468,22 +469,24 @@ RecyclingPlanarYCbCrImage::CopyData(const Data& aData)
// get new buffer
mBuffer = AllocateBuffer(size);
if (!mBuffer)
if (MOZ_UNLIKELY(!mBuffer))
return false;
// update buffer size
mBufferSize = size;
mData = aData;
mData.mYChannel = mBuffer.get();
mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
mData.mYSkip = mData.mCbSkip = mData.mCrSkip = 0;
CopyPlane(mData.mYChannel, aData.mYChannel,
mData.mYSize, mData.mYStride, mData.mYSkip);
aData.mYSize, aData.mYStride, aData.mYSkip);
CopyPlane(mData.mCbChannel, aData.mCbChannel,
mData.mCbCrSize, mData.mCbCrStride, mData.mCbSkip);
aData.mCbCrSize, aData.mCbCrStride, aData.mCbSkip);
CopyPlane(mData.mCrChannel, aData.mCrChannel,
mData.mCbCrSize, mData.mCbCrStride, mData.mCrSkip);
aData.mCbCrSize, aData.mCbCrStride, aData.mCrSkip);
mSize = aData.mPicSize;
return true;

View File

@ -152,7 +152,17 @@ nsBIG5ToUnicode::GetMaxLength(const char* aSrc,
{
// The length of the output in UTF-16 code units never exceeds the length
// of the input in bytes.
*aDestLength = aSrcLength + (mPendingTrail ? 1 : 0) + (mBig5Lead ? 1 : 0);
mozilla::CheckedInt32 length = aSrcLength;
if (mPendingTrail) {
length += 1;
}
if (mBig5Lead) {
length += 1;
}
if (!length.isValid()) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aDestLength = length.value();
return NS_OK;
}

View File

@ -211,12 +211,21 @@ nsUnicodeToBIG5::GetMaxLength(const char16_t* aSrc,
int32_t aSrcLength,
int32_t* aDestLength)
{
*aDestLength = (aSrcLength * 2) +
(mPendingTrail ? 1 : 0) +
// If the lead ends up being paired, the bytes produced
// are already included above.
// If not, it produces a single '?'.
(mUtf16Lead ? 1 : 0);
mozilla::CheckedInt32 length = aSrcLength;
length *= 2;
if (mPendingTrail) {
length += 1;
}
// If the lead ends up being paired, the bytes produced
// are already included above.
// If not, it produces a single '?'.
if (mUtf16Lead) {
length += 1;
}
if (!length.isValid()) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aDestLength = length.value();
return NS_OK;
}

View File

@ -5,6 +5,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsBidiUtils.h"
namespace mozilla {
static const uint32_t kMinRTLChar = 0x0590;
} // namespace mozilla;
#define ARABIC_TO_HINDI_DIGIT_INCREMENT (START_HINDI_DIGITS - START_ARABIC_DIGITS)
#define PERSIAN_TO_HINDI_DIGIT_INCREMENT (START_HINDI_DIGITS - START_FARSI_DIGITS)
#define ARABIC_TO_PERSIAN_DIGIT_INCREMENT (START_FARSI_DIGITS - START_ARABIC_DIGITS)
@ -82,16 +86,18 @@ nsresult HandleNumbers(char16_t* aBuffer, uint32_t aSize, uint32_t aNumFlag)
return NS_OK;
}
bool HasRTLChars(const nsAString& aString)
bool HasRTLChars(const char16_t* aText, uint32_t aLength)
{
// This is used to determine whether to enable bidi if a string has
// right-to-left characters. To simplify things, anything that could be a
// surrogate or RTL presentation form is covered just by testing >= 0xD800).
// It's fine to enable bidi in rare cases where it actually isn't needed.
int32_t length = aString.Length();
for (int32_t i = 0; i < length; i++) {
char16_t ch = aString.CharAt(i);
if (ch >= 0xD800 || IS_IN_BMP_RTL_BLOCK(ch)) {
// This is used to determine whether a string has right-to-left characters
// that mean it will require bidi processing.
const char16_t* cp = aText;
const char16_t* end = cp + aLength;
while (cp < end) {
char16_t ch = *cp++;
if (ch < mozilla::kMinRTLChar) {
continue;
}
if (UTF16_CODE_UNIT_IS_BIDI(ch) || IsBidiControlRTL(ch)) {
return true;
}
}

View File

@ -110,10 +110,19 @@ typedef enum nsCharType nsCharType;
* Return false, otherwise
*/
#define LRM_CHAR 0x200e
#define RLM_CHAR 0x200f
#define LRE_CHAR 0x202a
#define RLE_CHAR 0x202b
#define PDF_CHAR 0x202c
#define LRO_CHAR 0x202d
#define RLO_CHAR 0x202e
#define LRI_CHAR 0x2066
#define RLI_CHAR 0x2067
#define FSI_CHAR 0x2068
#define PDI_CHAR 0x2069
#define ALM_CHAR 0x061C
inline bool IsBidiControl(uint32_t aChar) {
return ((LRE_CHAR <= aChar && aChar <= RLO_CHAR) ||
@ -123,10 +132,32 @@ typedef enum nsCharType nsCharType;
}
/**
* Give an nsString.
* Give a UTF-16 codepoint (changed for TenFourFox; we don't use this for
* UTF-32 characters, so the conversion is unnecessary).
* Return true if the codepoint is a Bidi control character that may result
* in RTL directionality and therefore needs to trigger bidi resolution;
* return false otherwise.
*/
inline bool IsBidiControlRTL(char16_t aChar) {
return aChar == RLM_CHAR ||
aChar == RLE_CHAR ||
aChar == RLO_CHAR ||
aChar == RLI_CHAR ||
aChar == ALM_CHAR;
}
/**
* Give a 16-bit (UTF-16) text buffer and length
* @return true if the string contains right-to-left characters
*/
bool HasRTLChars(const nsAString& aString);
bool HasRTLChars(const char16_t* aText, uint32_t aLength);
/**
* Convenience function to call the above on an nsAString.
*/
inline bool HasRTLChars(const nsAString& aString) {
return HasRTLChars(aString.BeginReading(), aString.Length());
}
// These values are shared with Preferences dialog
// ------------------
@ -248,6 +279,17 @@ typedef enum nsCharType nsCharType;
((0xfe70 <= (c)) && ((c) <= 0xfefc)))
#define IS_IN_SMP_RTL_BLOCK(c) (((0x10800 <= (c)) && ((c) <= 0x10fff)) || \
((0x1e800 <= (c)) && ((c) <= 0x1eFFF)))
// Due to the supplementary-plane RTL blocks being identifiable from the
// high surrogate without examining the low surrogate, it is correct to
// use this by-code-unit check on potentially astral text without doing
// the math to decode surrogate pairs into code points. However, unpaired
// high surrogates that are RTL high surrogates then count as RTL even
// though, if replaced by the REPLACEMENT CHARACTER, it would not be
// RTL.
#define UTF16_CODE_UNIT_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \
(IS_RTL_PRESENTATION_FORM(c)) || \
(c) == 0xD802 || (c) == 0xD803 || \
(c) == 0xD83A || (c) == 0xD83B)
#define UCS2_CHAR_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \
(IS_RTL_PRESENTATION_FORM(c)))
#define UTF32_CHAR_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \

View File

@ -3761,7 +3761,6 @@ BytecodeEmitter::emitDestructuringDeclsWithEmitter(JSOp prologueOp, ParseNode* p
continue;
ParseNode* target = element;
if (element->isKind(PNK_SPREAD)) {
MOZ_ASSERT(element->pn_kid->isKind(PNK_NAME));
target = element->pn_kid;
}
if (target->isKind(PNK_ASSIGN))

View File

@ -4276,11 +4276,6 @@ Parser<FullParseHandler>::checkDestructuringArray(BindData<FullParseHandler>* da
return false;
}
target = element->pn_kid;
if (handler.isUnparenthesizedDestructuringPattern(target)) {
report(ParseError, false, target, JSMSG_BAD_DESTRUCT_TARGET);
return false;
}
} else if (handler.isUnparenthesizedAssignment(element)) {
target = element->pn_left;
} else {

View File

@ -49,6 +49,23 @@ assertIterable([5,5,4,4],
it => { var [,,...rest] = it; return rest; },
[3,4]);
// the iterator should be exhausted before any error is thrown
if(0) {
// XXX: this doesn't throw right now. just test syntax below.
// plan to reenable this for issue 485
assertIterable([5,5,4,4],
it => {
assertThrowsInstanceOf(function () {
"use strict";
[...{0: "".x}] = it;
}, TypeError);
return [];
},
[]);
} else {
assertIterable([5,5,4,4], it => { [...{0: "".x}] = it; return []; }, []);
}
var arraycalls = 0;
var ArrayIterator = Array.prototype[Symbol.iterator];
Array.prototype[Symbol.iterator] = function () {
@ -58,7 +75,11 @@ Array.prototype[Symbol.iterator] = function () {
// [...rest] should not call Array#@@iterator for the LHS
var [...rest] = iterable;
assertEq(arraycalls, 0, 'calls to Array#@@iterator');
// [...[...rest]] should do so, since it creates an implicit array for the
// first rest pattern, then destructures that again using @@iterator() for the
// second rest pattern.
var [...[...rest]] = iterable;
assertEq(arraycalls, 1, 'calls to Array#@@iterator');
// loop `fn` a few times, to get it JIT-compiled
function loop(fn) {
@ -67,7 +88,7 @@ function loop(fn) {
}
loop(() => { doneafter = 4; var [a] = iterable; return a; });
loop(() => { doneafter = 4; var [a,b,...rest] = iterable; return rest; });
loop(() => { doneafter = 4; var [a,b,...[...rest]] = iterable; return rest; });
// destructuring assignment should always use iterators and not optimize

View File

@ -4,8 +4,6 @@ load(libdir + 'eqArrayHelper.js');
assertThrowsInstanceOf(() => new Function('[...a, ,] = []'), SyntaxError, 'trailing elision');
assertThrowsInstanceOf(() => new Function('[a, ...b, c] = []'), SyntaxError, 'trailing param');
assertThrowsInstanceOf(() => new Function('[...[a]] = []'), SyntaxError, 'nested arraypattern');
assertThrowsInstanceOf(() => new Function('[...{a}] = []'), SyntaxError, 'nested objectpattern');
assertThrowsInstanceOf(() => new Function('[...a=b] = []'), SyntaxError, 'assignment expression');
assertThrowsInstanceOf(() => new Function('[...a()] = []'), SyntaxError, 'call expression');
assertThrowsInstanceOf(() => new Function('[...(a,b)] = []'), SyntaxError, 'comma expression');
@ -22,6 +20,14 @@ assertThrowsInstanceOf(() =>
assertThrowsInstanceOf(() => new Function('[...b,] = []'), SyntaxError)
, Error);
assertThrowsInstanceOf(() => {
try {
eval('let [...[...x]] = (() => { throw "foo"; } )();');
} catch(e) {
assertEq(e, "foo");
}
x;
}, ReferenceError);
var inputArray = [1, 2, 3];
var inputDeep = [1, inputArray];
@ -45,6 +51,11 @@ function testAll(fn) {
assertEqArray(fn('[, ...(o.prop)]', inputArray, 'o.prop'), expected);
o.prop = null;
assertEqArray(fn('[, ...(o.call().prop)]', inputArray, 'o.prop'), expected);
o.prop = null;
assertEqArray(fn('[, ...[...(o.prop)]]', inputArray, 'o.prop'), expected);
o.prop = null;
assertEqArray(fn('[, ...[...(o.call().prop)]]', inputArray, 'o.prop'), expected);
}
function testDeclaration(fn) {
testStr(fn);
@ -53,10 +64,24 @@ function testDeclaration(fn) {
assertEqArray(fn('[, ...rest]', inputGenerator()), expected);
assertEqArray(fn('[, [, ...rest]]', inputDeep), expected);
assertEqArray(fn('{a: [, ...rest]}', inputObject), expected);
assertEqArray(fn('[, ...[...rest]]', inputArray), expected);
assertEqArray(fn('[, ...[...rest]]', inputGenerator()), expected);
assertEqArray(fn('[, [, ...[...rest]]]', inputDeep), expected);
assertEqArray(fn('{a: [, ...[...rest]]}', inputObject), expected);
assertEqArray(fn('[, ...{0: a, 1: b}]', inputArray, '[a, b]'), expected);
assertEqArray(fn('[, ...{0: a, 1: b}]', inputGenerator(), '[a, b]'), expected);
assertEqArray(fn('[, [, ...{0: a, 1: b}]]', inputDeep, '[a, b]'), expected);
assertEqArray(fn('{a: [, ...{0: a, 1: b}]}', inputObject, '[a, b]'), expected);
}
function testStr(fn) {
assertEqArray(fn('[, ...rest]', inputStr), expectedStr);
assertEqArray(fn('[, ...[...rest]]', inputStr), expectedStr);
assertEqArray(fn('[, ...{0: a, 1: b}]', inputStr, '[a, b]'), expectedStr);
}
function testForIn(pattern, input, binding) {
@ -88,8 +113,9 @@ testAll(testGlobal);
function testClosure(pattern, input, binding) {
binding = binding || 'rest';
const decl = binding.replace('[', '').replace(']', '');
return new Function('input',
'var ' + binding + '; (function () {' +
'var ' + decl + '; (function () {' +
'(' + pattern + ' = input);' +
'})();' +
'return ' + binding

View File

@ -1824,6 +1824,12 @@ jit::ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph)
bool
jit::MakeMRegExpHoistable(MIRGraph& graph)
{
// If we are compiling try blocks, regular expressions may be observable
// from catch blocks (which Ion does not compile). For now just disable the
// pass in this case.
if (graph.hasTryBlock())
return true;
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
for (MDefinitionIterator iter(*block); iter; iter++) {
if (!iter->isRegExp())

View File

@ -1124,6 +1124,10 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge
RootedObject self(cx, this);
Shape* existingShape = self->ensureShape(cx);
if (!existingShape)
return false;
if (isNative() && as<NativeObject>().inDictionaryMode()) {
if (generateShape == GENERATE_SHAPE && !as<NativeObject>().generateOwnShape(cx))
return false;
@ -1137,10 +1141,6 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge
return true;
}
Shape* existingShape = self->ensureShape(cx);
if (!existingShape)
return false;
Shape* newShape = Shape::setObjectFlags(cx, flags, self->getTaggedProto(), existingShape);
if (!newShape)
return false;

View File

@ -110,6 +110,7 @@ struct BidiParagraphData {
nsTArray<nsLineBox*> mLinePerFrame;
nsDataHashtable<nsISupportsHashKey, int32_t> mContentToFrameIndex;
bool mIsVisual;
bool mRequiresBidi;
bool mReset;
nsBidiLevel mParaLevel;
nsIContent* mPrevContent;
@ -121,10 +122,14 @@ struct BidiParagraphData {
void Init(nsBlockFrame *aBlockFrame)
{
mBidiEngine = new nsBidi();
mRequiresBidi = false;
mPrevContent = nullptr;
mParagraphDepth = 0;
mParaLevel = nsBidiPresUtils::BidiLevelFromStyle(aBlockFrame->StyleContext());
if (mParaLevel > 0) {
mRequiresBidi = true;
}
mIsVisual = aBlockFrame->PresContext()->IsVisualMode();
if (mIsVisual) {
@ -664,14 +669,67 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
char16_t ch = GetBidiControl(aBlockFrame->StyleContext(), kOverride);
if (ch != 0) {
bpd.PushBidiControl(ch);
bpd.mRequiresBidi = true;
} else if (!bpd.mRequiresBidi) {
// If there are no unicode-bidi properties and no RTL characters in the
// block's content, then it is pure LTR and we can skip the rest of bidi
// resolution.
nsIContent* currContent = nullptr;
for (nsBlockFrame* block = aBlockFrame; block;
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
if (/* !bpd.mRequiresBidi && */
ChildListMayRequireBidi(block->PrincipalChildList().FirstChild(),
&currContent)) {
bpd.mRequiresBidi = true;
// Optimization for TenFourFox issue 482:
// It's safe to break here if mRequiresBidi is true because we'll
// pull the state bits off in the loop below (if we didn't, we would
// essentially cause bug 1362423). This also allows us to reduce
// checking mRequiresBidi all the time.
break;
}
#if(0)
// XXX: Unnecessary work given that the below isn't executed.
// If we need bidi support for overflow, we need to enable this too.
/* if (!bpd.mRequiresBidi) { */
nsBlockFrame::FrameLines* overflowLines = block->GetOverflowLines();
if (overflowLines) { // XXX: see below
if (ChildListMayRequireBidi(overflowLines->mFrames.FirstChild(),
&currContent)) {
bpd.mRequiresBidi = true;
break; // as above
}
}
/* } */
#endif
}
// Moving the below here so that we can keep partial work causes RTL
// to get munged. It seems we really do have to iterate through all the
// frames again from the beginning if any are RTL.
if (!bpd.mRequiresBidi) {
return NS_OK;
}
}
for (nsBlockFrame* block = aBlockFrame; block;
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
nsBlockInFlowLineIterator lineIter(block, block->begin_lines());
bpd.ResetForNewBlock();
TraverseFrames(aBlockFrame, &lineIter, block->GetFirstPrincipalChild(), &bpd);
// XXX what about overflow lines?
#if(0)
nsBlockFrame::FrameLines* overflowLines = block->GetOverflowLines();
// XXX: Not sure if this is going to break anything.
// It's safe to do above (from bug 1358275) because that doesn't actually
// bidi-process the overflow lines; it just checks if we need to.
if (overflowLines) {
nsBlockInFlowLineIterator it(block, overflowLines->mLines.begin(), true);
bpd.ResetForNewBlock();
TraverseFrames(aBlockFrame, &it, overflowLines->mFrames.FirstChild(), &bpd);
}
#endif
}
if (ch != 0) {
@ -1241,6 +1299,56 @@ nsBidiPresUtils::TraverseFrames(nsBlockFrame* aBlockFrame,
MOZ_ASSERT(initialLineContainer == aLineIter->GetContainer());
}
bool
nsBidiPresUtils::ChildListMayRequireBidi(nsIFrame* aFirstChild,
nsIContent** aCurrContent)
{
MOZ_ASSERT(!aFirstChild || !aFirstChild->GetPrevSibling(),
"Expecting to traverse from the start of a child list");
for (nsIFrame* childFrame = aFirstChild; childFrame;
childFrame = childFrame->GetNextSibling()) {
nsIFrame* frame = childFrame;
// If the real frame for a placeholder is a first-letter frame, we need to
// consider its contents for potential Bidi resolution.
if (childFrame->GetType() == nsGkAtoms::placeholderFrame) {
nsIFrame* realFrame =
nsPlaceholderFrame::GetRealFrameForPlaceholder(childFrame);
if (realFrame->GetType() == nsGkAtoms::letterFrame) {
frame = realFrame;
}
}
// If unicode-bidi properties are present, we should do bidi resolution.
nsStyleContext* sc = frame->StyleContext();
if (GetBidiControl(sc, kOverrideOrEmbed)) {
return true;
}
if (IsBidiLeaf(frame)) {
if (frame->GetType() == nsGkAtoms::textFrame) {
// Check whether the text frame has any RTL characters; if so, bidi
// resolution will be needed.
nsIContent* content = frame->GetContent();
if (content != *aCurrContent) {
*aCurrContent = content;
const nsTextFragment* txt = content->GetText();
if (txt->Is2b() && HasRTLChars(txt->Get2b(), txt->GetLength())) {
return true;
}
}
}
} else if (ChildListMayRequireBidi(frame->PrincipalChildList().FirstChild(),
aCurrContent)) {
return true;
}
}
return false;
}
void
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame,
BidiParagraphData* aBpd)

View File

@ -399,6 +399,23 @@ private:
nsIFrame* aCurrentFrame,
BidiParagraphData* aBpd);
/**
* Perform a recursive "pre-traversal" of the child frames of a block or
* inline container frame, to determine whether full bidi resolution is
* actually needed.
* This explores the same frames as TraverseFrames (above), but is less
* expensive and may allow us to avoid performing the full TraverseFrames
* operation.
* @param aFirstChild frame to start traversal from
* @param[in/out] aCurrContent the content node that we've most recently
* scanned for RTL characters (so that when descendant frames refer
* to the same content, we can avoid repeatedly scanning it).
* @return true if it finds that bidi is (or may be) required,
* false if no potentially-bidi content is present.
*/
static bool ChildListMayRequireBidi(nsIFrame* aFirstChild,
nsIContent** aCurrContent);
/**
* Position ruby content frames (ruby base/text frame).
* Called from RepositionRubyFrame.

View File

@ -647,7 +647,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mAsyncPanZoomEnabled(nsLayoutUtils::AsyncPanZoomEnabled(aReferenceFrame))
{
MOZ_COUNT_CTOR(nsDisplayListBuilder);
PL_InitArenaPool(&mPool, "displayListArena", 1024,
PL_InitArenaPool(&mPool, "displayListArena", 4096,
std::max(NS_ALIGNMENT_OF(void*),NS_ALIGNMENT_OF(double))-1);
nsPresContext* pc = aReferenceFrame->PresContext();

View File

@ -9345,9 +9345,13 @@ nsTextFrame::GetRenderedText(uint32_t aStartOffset,
startOffset = aStartOffset;
endOffset = std::min<uint32_t>(INT32_MAX, aEndOffset);
}
// If startOffset and/or endOffset are inside of trimmedOffsets' range,
// then clamp the edges of trimmedOffsets accordingly.
int32_t origTrimmedOffsetsEnd = trimmedOffsets.GetEnd();
trimmedOffsets.mStart = std::max<uint32_t>(trimmedOffsets.mStart,
startOffset);
trimmedOffsets.mLength = std::min<uint32_t>(trimmedOffsets.GetEnd(),
trimmedOffsets.mLength = std::min<uint32_t>(origTrimmedOffsetsEnd,
endOffset) - trimmedOffsets.mStart;
if (trimmedOffsets.mLength <= 0) {
offsetInRenderedString = nextOffsetInRenderedString;

View File

@ -1176,10 +1176,13 @@ GetStatesForPseudoClass(const nsAString& aStatePseudo)
nsCOMPtr<nsIAtom> atom = do_GetAtom(aStatePseudo);
// Ignore :moz-any-link so we don't give the element simultaneous
// Ignore :any-link so we don't give the element simultaneous
// visited and unvisited style state
if (nsCSSPseudoClasses::GetPseudoType(atom) ==
nsCSSPseudoClasses::ePseudoClass_mozAnyLink) {
nsCSSPseudoClasses::ePseudoClass_mozAnyLink ||
// XXX: this could be cleaned up. do it once it's building
nsCSSPseudoClasses::GetPseudoType(atom) ==
nsCSSPseudoClasses::ePseudoClass_anyLink) {
return EventStates();
}
// Our array above is long enough that indexing into it with

View File

@ -991,7 +991,6 @@ const KTableEntry nsCSSProps::kBoxShadowTypeKTable[] = {
const KTableEntry nsCSSProps::kBoxSizingKTable[] = {
{ eCSSKeyword_content_box, uint8_t(StyleBoxSizing::Content) },
{ eCSSKeyword_border_box, uint8_t(StyleBoxSizing::Border) },
{ eCSSKeyword_padding_box, uint8_t(StyleBoxSizing::Padding) },
{ eCSSKeyword_UNKNOWN, -1 }
};

View File

@ -142,6 +142,8 @@ CSS_STATE_PSEUDO_CLASS(link, ":link", 0, "", NS_EVENT_STATE_UNVISITED)
// what matches :link or :visited
CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link", 0, "",
NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)
CSS_STATE_PSEUDO_CLASS(anyLink, ":any-link", 0, "",
NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)
CSS_STATE_PSEUDO_CLASS(visited, ":visited", 0, "", NS_EVENT_STATE_VISITED)
CSS_STATE_PSEUDO_CLASS(active, ":active", 0, "", NS_EVENT_STATE_ACTIVE)

View File

@ -387,7 +387,7 @@ long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
t[i] = book->valuelist+entry[i]*book->dim;
}
for(i=0,o=0;i<book->dim;i++,o+=step)
for (j=0;j<step;j++)
for (j=0;o+j<n && j<step;j++)
a[o+j]+=t[j][i];
}
return(0);
@ -399,41 +399,12 @@ long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
int i,j,entry;
float *t;
if(book->dim>8){
for(i=0;i<n;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;)
a[i++]+=t[j++];
}
}else{
for(i=0;i<n;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim;
j=0;
switch((int)book->dim){
case 8:
a[i++]+=t[j++];
case 7:
a[i++]+=t[j++];
case 6:
a[i++]+=t[j++];
case 5:
a[i++]+=t[j++];
case 4:
a[i++]+=t[j++];
case 3:
a[i++]+=t[j++];
case 2:
a[i++]+=t[j++];
case 1:
a[i++]+=t[j++];
case 0:
break;
}
}
for(i=0;i<n;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim;
for(j=0;i<n && j<book->dim;)
a[i++]+=t[j++];
}
}
return(0);
@ -471,12 +442,13 @@ long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
long i,j,entry;
int chptr=0;
if(book->used_entries>0){
for(i=offset/ch;i<(offset+n)/ch;){
int m=(offset+n)/ch;
for(i=offset/ch;i<m;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
{
const float *t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;j++){
for (j=0;i<m && j<book->dim;j++){
a[chptr++][i]+=t[j];
if(chptr==ch){
chptr=0;

View File

@ -186,7 +186,7 @@ cglobal quantize_%1, 0, %2, 15, coeff, ncoeff, skip, zbin, round, quant, \
pshuflw m7, m8, 0x1
pmaxsw m8, m7
pextrw r6, m8, 0
mov [r2], r6
mov [r2], r6w
RET
; skip-block, i.e. just write all zeroes

View File

@ -1412,7 +1412,7 @@ pref("network.http.bypass-cachelock-threshold", 250);
// Try and use SPDY when using SSL
pref("network.http.spdy.enabled", true);
pref("network.http.spdy.enabled.v3-1", true);
pref("network.http.spdy.enabled.v3-1", false);
pref("network.http.spdy.enabled.http2", true);
pref("network.http.spdy.enabled.deps", true);
pref("network.http.spdy.enforce-tls-profile", true);
@ -5137,4 +5137,4 @@ pref("toolkit.pageThumbs.minWidth", 0);
pref("toolkit.pageThumbs.minHeight", 0);
pref("tenfourfox.adblock.enabled", false);
pref("tenfourfox.adblock.logging.enabled", true);
pref("tenfourfox.adblock.logging.enabled", false);

View File

@ -19,6 +19,7 @@ pref("security.ssl.enable_alpn", true);
pref("security.ssl3.ecdhe_rsa_aes_128_gcm_sha256", true);
pref("security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256", true);
pref("security.ssl3.ecdhe_rsa_aes_128_sha", true);
pref("security.ssl3.ecdhe_rsa_aes_128_sha256", true);
pref("security.ssl3.ecdhe_ecdsa_aes_128_sha", true);
pref("security.ssl3.ecdhe_rsa_aes_256_sha", true);
pref("security.ssl3.ecdhe_ecdsa_aes_256_sha", true);

View File

@ -1014,6 +1014,15 @@ Http2Session::CleanupStream(Http2Stream *aStream, nsresult aResult,
return;
}
Http2PushedStream *pushSource = aStream->PushSource();
if (pushSource) {
// aStream is a synthetic attached to an even push
MOZ_ASSERT(pushSource->GetConsumerStream() == aStream);
MOZ_ASSERT(!aStream->StreamID());
MOZ_ASSERT(!(pushSource->StreamID() & 0x1));
aStream->ClearPushSource();
}
if (aStream->DeferCleanup(aResult)) {
LOG3(("Http2Session::CleanupStream 0x%X deferred\n", aStream->StreamID()));
return;
@ -1024,15 +1033,6 @@ Http2Session::CleanupStream(Http2Stream *aStream, nsresult aResult,
return;
}
Http2PushedStream *pushSource = aStream->PushSource();
if (pushSource) {
// aStream is a synthetic attached to an even push
MOZ_ASSERT(pushSource->GetConsumerStream() == aStream);
MOZ_ASSERT(!aStream->StreamID());
MOZ_ASSERT(!(pushSource->StreamID() & 0x1));
pushSource->SetConsumerStream(nullptr);
}
if (!aStream->RecvdFin() && !aStream->RecvdReset() && aStream->StreamID()) {
LOG3(("Stream had not processed recv FIN, sending RST code %X\n", aResetCode));
GenerateRstStream(aResetCode, aStream->StreamID());

View File

@ -101,10 +101,20 @@ Http2Stream::Http2Stream(nsAHttpTransaction *httpTransaction,
Http2Stream::~Http2Stream()
{
ClearPushSource();
ClearTransactionsBlockedOnTunnel();
mStreamID = Http2Session::kDeadStreamID;
}
void
Http2Stream::ClearPushSource()
{
if (mPushSource) {
mPushSource->SetConsumerStream(nullptr);
mPushSource = nullptr;
}
}
// ReadSegments() is used to write data down the socket. Generally, HTTP
// request data is pulled from the approriate transaction and
// converted to HTTP/2 data. Sometimes control data like a window-update is
@ -1091,6 +1101,10 @@ Http2Stream::ConvertPushHeaders(Http2Decompressor *decompressor,
void
Http2Stream::Close(nsresult reason)
{
// In case we are connected to a push, make sure the push knows we are closed,
// so it doesn't try to give us any more DATA that comes on it after our close.
ClearPushSource();
mTransaction->Close(reason);
}

View File

@ -47,6 +47,7 @@ public:
uint32_t StreamID() { return mStreamID; }
Http2PushedStream *PushSource() { return mPushSource; }
void ClearPushSource();
stateType HTTPState() { return mState; }
void SetHTTPState(stateType val) { mState = val; }

View File

@ -1032,6 +1032,7 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
{ "goto.google.com", true, false, false, -1, &kPinset_google_root_pems },
{ "gr.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
{ "groups.google.com", true, false, false, -1, &kPinset_google_root_pems },
{ "gstatic.cn", true, false, false, -1, &kPinset_google_root_pems },
{ "gstatic.com", true, false, false, -1, &kPinset_google_root_pems },
{ "gvt1.com", true, false, false, -1, &kPinset_google_root_pems },
{ "gvt2.com", true, false, false, -1, &kPinset_google_root_pems },
@ -1179,8 +1180,8 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
{ "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
};
// Pinning Preload List Length = 477;
// Pinning Preload List Length = 478;
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1527453921095000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1528837162062000);

View File

@ -30,8 +30,10 @@ using namespace mozilla::psm;
extern PRLogModuleInfo* gPIPNSSLog;
#if (0) // TenFourFox issue 334
static void AccumulateCipherSuite(Telemetry::ID probe,
const SSLChannelInfo& channelInfo);
#endif
namespace {
@ -1027,6 +1029,7 @@ CanFalseStartCallback(PRFileDesc* fd, void* client_data, PRBool *canFalseStart)
return SECSuccess;
}
#if(0) // TenFourFox issue 334
static void
AccumulateNonECCKeySize(Telemetry::ID probe, uint32_t bits)
{
@ -1076,6 +1079,7 @@ AccumulateCipherSuite(Telemetry::ID probe, const SSLChannelInfo& channelInfo)
case TLS_ECDHE_RSA_WITH_RC4_128_SHA: value = 8; break;
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: value = 9; break;
case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: value = 10; break;
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: value = 11; break; // just in case, issue 489
// DHE key exchange
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: value = 21; break;
case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: value = 22; break;
@ -1114,6 +1118,7 @@ AccumulateCipherSuite(Telemetry::ID probe, const SSLChannelInfo& channelInfo)
MOZ_ASSERT(value != 0);
Telemetry::Accumulate(probe, value);
}
#endif
void HandshakeCallback(PRFileDesc* fd, void* client_data) {
nsNSSShutDownPreventionLock locker;
@ -1146,6 +1151,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo));
MOZ_ASSERT(rv == SECSuccess);
if (rv == SECSuccess) {
#if(0) // TenFourFox issue 334
// Get the protocol version for telemetry
// 1=tls1, 2=tls1.1, 3=tls1.2
unsigned int versionEnum = channelInfo.protocolVersion & 0xFF;
@ -1155,6 +1161,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
infoObject->IsFullHandshake() ? Telemetry::SSL_CIPHER_SUITE_FULL
: Telemetry::SSL_CIPHER_SUITE_RESUMED,
channelInfo);
#endif
SSLCipherSuiteInfo cipherInfo;
rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
@ -1163,17 +1170,20 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
if (rv == SECSuccess) {
usesWeakCipher = cipherInfo.symCipher == ssl_calg_rc4;
#if(0)
// keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4
Telemetry::Accumulate(
infoObject->IsFullHandshake()
? Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_FULL
: Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED,
cipherInfo.keaType);
#endif
DebugOnly<int16_t> KEAUsed;
MOZ_ASSERT(NS_SUCCEEDED(infoObject->GetKEAUsed(&KEAUsed)) &&
(KEAUsed == cipherInfo.keaType));
#if(0)
if (infoObject->IsFullHandshake()) {
switch (cipherInfo.keaType) {
case ssl_kea_rsa:
@ -1223,6 +1233,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
? Telemetry::SSL_SYMMETRIC_CIPHER_FULL
: Telemetry::SSL_SYMMETRIC_CIPHER_RESUMED,
cipherInfo.symCipher);
#endif
}
}

View File

@ -623,6 +623,9 @@ static const CipherPref sCipherPrefs[] = {
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, true },
{ "security.ssl3.ecdhe_ecdsa_aes_128_sha",
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, true },
// stopgap for TenFourFox issue 489 pending ChaCha20/Poly1305 implementation
{ "security.ssl3.ecdhe_rsa_aes_128_sha256",
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, true },
{ "security.ssl3.ecdhe_rsa_aes_256_sha",
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, true },

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@ if (versionNum.substr(0,3) == "45.") {
// FPR series
var vf = 0 + versionNum.substr(3);
var pl = ""+ (vf - (vf|0));
pl = 0 + pl.substr(1);
pl = ((0 + pl.substr(1) * 10)+0.001)|0; // damn float rounding
vf = vf|0; vf -= 9;
// XXX localize me
version.textContent = "Feature Parity Release "+vf+

View File

@ -59,6 +59,13 @@ interface nsIDatePicker : nsISupports
*/
attribute AString maxDate;
/**
* The selected date.
*
* @return Returns the date currently selected.
*/
readonly attribute AString selectedDate;
/**
* Show date dialog. The dialog is displayed modally.
*

View File

@ -12,6 +12,7 @@
#include "mozilla/HashFunctions.h"
#include "mozilla/MathAlgorithms.h"
#include "nsAlgorithm.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/Likely.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/ChaosMode.h"
@ -71,7 +72,7 @@ PLDHashTable::HashStringKey(PLDHashTable* aTable, const void* aKey)
/* static */ PLDHashNumber
PLDHashTable::HashVoidPtrKeyStub(PLDHashTable* aTable, const void* aKey)
{
return (PLDHashNumber)(ptrdiff_t)aKey >> 2;
return mozilla::HashGeneric(aKey);
}
/* static */ bool
@ -256,15 +257,38 @@ PLDHashTable::Hash1(PLDHashNumber aHash0)
return aHash0 >> mHashShift;
}
// Double hashing needs the second hash code to be relatively prime to table
// size, so we simply make hash2 odd.
void
PLDHashTable::Hash2(PLDHashNumber aHash,
PLDHashTable::Hash2(PLDHashNumber aHash0,
uint32_t& aHash2Out, uint32_t& aSizeMaskOut)
{
uint32_t sizeLog2 = kHashBits - mHashShift;
aHash2Out = ((aHash << sizeLog2) >> mHashShift) | 1;
aSizeMaskOut = (PLDHashNumber(1) << sizeLog2) - 1;
uint32_t sizeMask = (PLDHashNumber(1) << sizeLog2) - 1;
aSizeMaskOut = sizeMask;
// The incoming aHash0 always has the low bit unset (since we leave it
// free for the collision flag), and should have reasonably random
// data in the other 31 bits. We used the high bits of aHash0 for
// Hash1, so we use the low bits here. If the table size is large,
// the bits we use may overlap, but that's still more random than
// filling with 0s.
//
// Since the result of Hash2 controls how far we jump around the table
// to build a chain after starting at a location determined by Hash1,
// we'd like to keep it small, to improve cache behavior.
// Keep the jumps from the second hash small, to improve cache behavior.
const uint32_t kHash2MaskMaxBits = 6;
uint32_t hash2Mask;
if (sizeLog2 >= kHash2MaskMaxBits) {
hash2Mask = (PLDHashNumber(1) << kHash2MaskMaxBits) - 1;
} else {
hash2Mask = sizeMask;
}
// Double hashing needs the second hash code to be relatively prime to table
// size, so we simply make hash2 odd.
//
// This also conveniently covers up the fact that we have the low bit
// unset since aHash0 has the low bit unset.
aHash2Out = (aHash0 & hash2Mask) | 1;
}
// Reserve mKeyHash 0 for free entries and 1 for removed-entry sentinels. Note

View File

@ -1026,6 +1026,17 @@ CountCharInReadable(const nsACString& aStr, char aChar)
return count;
}
bool
StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring)
{
nsAString::size_type src_len = aSource.Length(),
sub_len = aSubstring.Length();
if (sub_len > src_len) {
return false;
}
return Substring(aSource, 0, sub_len).Equals(aSubstring);
}
bool
StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
const nsStringComparator& aComparator)
@ -1038,6 +1049,17 @@ StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
}
bool
StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring)
{
nsACString::size_type src_len = aSource.Length(),
sub_len = aSubstring.Length();
if (sub_len > src_len) {
return false;
}
return Substring(aSource, 0, sub_len).Equals(aSubstring);
}
bool
StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
const nsCStringComparator& aComparator)
@ -1050,6 +1072,17 @@ StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
}
bool
StringEndsWith(const nsAString& aSource, const nsAString& aSubstring)
{
nsAString::size_type src_len = aSource.Length(),
sub_len = aSubstring.Length();
if (sub_len > src_len) {
return false;
}
return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring);
}
bool
StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
const nsStringComparator& aComparator)
@ -1063,6 +1096,17 @@ StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
aComparator);
}
bool
StringEndsWith(const nsACString& aSource, const nsACString& aSubstring)
{
nsACString::size_type src_len = aSource.Length(),
sub_len = aSubstring.Length();
if (sub_len > src_len) {
return false;
}
return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring);
}
bool
StringEndsWith(const nsACString& aSource, const nsACString& aSubstring,
const nsCStringComparator& aComparator)

View File

@ -386,18 +386,18 @@ uint32_t CountCharInReadable(const nsAString& aStr,
uint32_t CountCharInReadable(const nsACString& aStr,
char aChar);
bool StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring);
bool StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring,
const nsStringComparator& aComparator =
nsDefaultStringComparator());
const nsStringComparator& aComparator);
bool StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring);
bool StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring,
const nsCStringComparator& aComparator =
nsDefaultCStringComparator());
const nsCStringComparator& aComparator);
bool StringEndsWith(const nsAString& aSource, const nsAString& aSubstring);
bool StringEndsWith(const nsAString& aSource, const nsAString& aSubstring,
const nsStringComparator& aComparator =
nsDefaultStringComparator());
const nsStringComparator& aComparator);
bool StringEndsWith(const nsACString& aSource, const nsACString& aSubstring);
bool StringEndsWith(const nsACString& aSource, const nsACString& aSubstring,
const nsCStringComparator& aComparator =
nsDefaultCStringComparator());
const nsCStringComparator& aComparator);
const nsAFlatString& EmptyString();
const nsAFlatCString& EmptyCString();