Merge mozilla-central to autoland. r=merge a=merge on a CLOSED TREE

This commit is contained in:
Narcis Beleuzu 2017-12-15 03:46:15 +02:00
commit eda8e08e68
65 changed files with 1144 additions and 696 deletions

View File

@ -91,7 +91,7 @@
/* The fullscreen button doesnt show on Yosemite(10.10) or above so dont give it a
border there */
@media not all and (-moz-mac-yosemite-theme) {
@media (-moz-mac-yosemite-theme: 0) {
.titlebar-placeholder[type="fullscreen-button"] {
margin-right: 4px;
}

View File

@ -43,7 +43,7 @@
background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-expanded");
}
@media not all and (-moz-mac-yosemite-theme) {
@media (-moz-mac-yosemite-theme: 0) {
.item.client.selected .item-twisty-container {
background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-expanded-inverted");
}

View File

@ -7,7 +7,7 @@
%define glassInactiveBorderColor rgb(102, 102, 102)
@media (-moz-os-version: windows-win7) {
@media not all and (-moz-windows-classic) {
@media (-moz-windows-classic: 0) {
#main-window[sizemode="normal"] > #tab-view-deck > #browser-panel > #navigator-toolbox > #toolbar-menubar {
margin-top: 1px;
}

View File

@ -329,7 +329,7 @@
-moz-appearance: -moz-window-button-close;
}
@media not all and (-moz-windows-classic) {
@media (-moz-windows-classic: 0) {
#titlebar-min {
margin-inline-end: 2px;
}

View File

@ -138,7 +138,7 @@
padding-inline-end: 9px;
}
@media not all and (-moz-windows-classic) {
@media (-moz-windows-classic: 0) {
#placesToolbox {
-moz-appearance: none;
background-color: transparent;

View File

@ -5056,6 +5056,24 @@ NotifyActivityChanged(nsISupports *aSupports, void *aUnused)
}
}
bool
nsIDocument::IsTopLevelWindowInactive() const
{
nsCOMPtr<nsIDocShellTreeItem> treeItem = GetDocShell();
if (!treeItem) {
return false;
}
nsCOMPtr<nsIDocShellTreeItem> rootItem;
treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
if (!rootItem) {
return false;
}
nsCOMPtr<nsPIDOMWindowOuter> domWindow = rootItem->GetWindow();
return domWindow && !domWindow->IsActive();
}
void
nsIDocument::SetContainer(nsDocShell* aContainer)
{
@ -5751,10 +5769,7 @@ nsDocument::ContentStateChanged(nsIContent* aContent, EventStates aStateMask)
void
nsDocument::DocumentStatesChanged(EventStates aStateMask)
{
// Invalidate our cached state.
mGotDocumentState &= ~aStateMask;
mDocumentState &= ~aStateMask;
UpdateDocumentStates(aStateMask);
NS_DOCUMENT_NOTIFY_OBSERVERS(DocumentStatesChanged, (this, aStateMask));
}
@ -9875,21 +9890,22 @@ nsDocument::ForgetImagePreload(nsIURI* aURI)
}
void
nsIDocument::UpdatePossiblyStaleDocumentState()
nsIDocument::UpdateDocumentStates(EventStates aChangedStates)
{
if (!mGotDocumentState.HasState(NS_DOCUMENT_STATE_RTL_LOCALE)) {
if (aChangedStates.HasState(NS_DOCUMENT_STATE_RTL_LOCALE)) {
if (IsDocumentRightToLeft()) {
mDocumentState |= NS_DOCUMENT_STATE_RTL_LOCALE;
} else {
mDocumentState &= ~NS_DOCUMENT_STATE_RTL_LOCALE;
}
mGotDocumentState |= NS_DOCUMENT_STATE_RTL_LOCALE;
}
if (!mGotDocumentState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
nsIPresShell* shell = GetShell();
if (shell && shell->GetPresContext() &&
shell->GetPresContext()->IsTopLevelWindowInactive()) {
if (aChangedStates.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
if (IsTopLevelWindowInactive()) {
mDocumentState |= NS_DOCUMENT_STATE_WINDOW_INACTIVE;
} else {
mDocumentState &= ~NS_DOCUMENT_STATE_WINDOW_INACTIVE;
}
mGotDocumentState |= NS_DOCUMENT_STATE_WINDOW_INACTIVE;
}
}

View File

@ -1554,6 +1554,8 @@ public:
return window ? window->WindowID() : 0;
}
bool IsTopLevelWindowInactive() const;
/**
* Get the script loader for this document
*/
@ -2637,17 +2639,7 @@ public:
* Document state bits have the form NS_DOCUMENT_STATE_* and are declared in
* nsIDocument.h.
*/
mozilla::EventStates GetDocumentState()
{
UpdatePossiblyStaleDocumentState();
return ThreadSafeGetDocumentState();
}
// GetDocumentState() mutates the state due to lazy resolution;
// and can't be used during parallel traversal. Use this instead,
// and ensure GetDocumentState() has been called first.
// This will assert if the state is stale.
mozilla::EventStates ThreadSafeGetDocumentState() const
mozilla::EventStates GetDocumentState() const
{
return mDocumentState;
}
@ -3275,9 +3267,9 @@ protected:
return mChildDocumentUseCounters[aUseCounter];
}
private:
void UpdatePossiblyStaleDocumentState();
void UpdateDocumentStates(mozilla::EventStates);
private:
mutable std::bitset<eDeprecatedOperationCount> mDeprecationWarnedAbout;
mutable std::bitset<eDocumentWarningCount> mDocWarningWarnedAbout;
@ -3433,7 +3425,6 @@ protected:
mozilla::TimeStamp mLastFocusTime;
mozilla::EventStates mDocumentState;
mozilla::EventStates mGotDocumentState;
// True if BIDI is enabled.
bool mBidiEnabled : 1;

View File

@ -297,6 +297,8 @@ BodyMaybeUpdatePaddingSize(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
aQuotaInfo.mOrigin, bodyFile, &fileSize);
MOZ_DIAGNOSTIC_ASSERT(quotaObject);
MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0);
// XXXtt: bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1422815
if (!quotaObject) { return NS_ERROR_UNEXPECTED; }
if (*aPaddingSizeOut == InternalResponse::UNKNOWN_PADDING_SIZE) {
*aPaddingSizeOut = BodyGeneratePadding(fileSize, aPaddingInfo);

View File

@ -164,6 +164,12 @@ public:
return NS_SUCCEEDED(mNetworkResult);
}
const nsTArray<nsCString>&
URLList() const
{
return mURLList;
}
private:
~CompareNetwork()
{
@ -187,6 +193,7 @@ private:
ChannelInfo mChannelInfo;
RefPtr<InternalHeaders> mInternalHeaders;
UniquePtr<PrincipalInfo> mPrincipalInfo;
nsTArray<nsCString> mURLList;
nsCString mMaxScope;
nsLoadFlags mLoadFlags;
@ -468,6 +475,16 @@ private:
mState = WaitingForScriptOrComparisonResult;
// Always make sure to fetch the main script. If the old cache has
// no entries or the main script entry is missing, then the loop below
// may not trigger it. This should not really happen, but we handle it
// gracefully if it does occur. Its possible the bad cache state is due
// to a crash or shutdown during an update, etc.
rv = FetchScript(mURL, true /* aIsMainScript */, mOldCache);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
for (uint32_t i = 0; i < len; ++i) {
JS::Rooted<JS::Value> val(aCx);
if (NS_WARN_IF(!JS_GetElement(aCx, obj, i, &val)) ||
@ -484,7 +501,12 @@ private:
nsString URL;
request->GetUrl(URL);
rv = FetchScript(URL, mURL == URL /* aIsMainScript */, mOldCache);
// We explicitly start the fetch for the main script above.
if (mURL == URL) {
continue;
}
rv = FetchScript(URL, false /* aIsMainScript */, mOldCache);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
@ -587,6 +609,7 @@ private:
RefPtr<InternalResponse> ir =
new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
ir->SetBody(body, aCN->Buffer().Length());
ir->SetURLList(aCN->URLList());
ir->InitChannelInfo(aCN->GetChannelInfo());
UniquePtr<PrincipalInfo> principalInfo = aCN->TakePrincipalInfo();
@ -672,6 +695,7 @@ CompareNetwork::Initialize(nsIPrincipal* aPrincipal,
}
mURL = aURL;
mURLList.AppendElement(NS_ConvertUTF16toUTF8(mURL));
nsCOMPtr<nsILoadGroup> loadGroup;
rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), aPrincipal);
@ -765,7 +789,7 @@ CompareNetwork::Finish()
nsresult rv = NS_OK;
// mNetworkResult is prior to mCacheResult, since it's needed for reporting
// various errors to web contenet.
// various errors to web content.
if (NS_FAILED(mNetworkResult)) {
// An imported script could become offline, since it might no longer be
// needed by the new importing script. In that case, the importing script
@ -974,14 +998,14 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext
}
nsAutoCString mimeType;
nsresult rv2 = httpChannel->GetContentType(mimeType);
rv = httpChannel->GetContentType(mimeType);
if (NS_WARN_IF(NS_FAILED(rv))) {
// We should only end up here if !mResponseHead in the channel. If headers
// were received but no content type was specified, we'll be given
// UNKNOWN_CONTENT_TYPE "application/x-unknown-content-type" and so fall
// into the next case with its better error message.
rv = NS_ERROR_DOM_SECURITY_ERR;
return rv2;
return rv;
}
if (!mimeType.LowerCaseEqualsLiteral("text/javascript") &&
@ -992,7 +1016,24 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext
nsTArray<nsString> { NS_ConvertUTF8toUTF16(mRegistration->mScope),
NS_ConvertUTF8toUTF16(mimeType), mURL });
rv = NS_ERROR_DOM_SECURITY_ERR;
return rv2;
return rv;
}
nsCOMPtr<nsIURI> channelURL;
rv = httpChannel->GetURI(getter_AddRefs(channelURL));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCString channelURLSpec;
MOZ_ALWAYS_SUCCEEDS(channelURL->GetSpec(channelURLSpec));
// Append the final URL if its different from the original
// request URL. This lets us note that a redirect occurred
// even though we don't track every redirect URL here.
MOZ_DIAGNOSTIC_ASSERT(!mURLList.IsEmpty());
if (channelURLSpec != mURLList[0]) {
mURLList.AppendElement(channelURLSpec);
}
char16_t* buffer = nullptr;

View File

@ -231,6 +231,7 @@ support-files =
bug1290951_worker_main.sjs
bug1290951_worker_imported.sjs
sw_storage_not_allow.js
update_worker.sjs
[test_bug1151916.html]
[test_bug1240436.html]
@ -344,3 +345,4 @@ tags = openwindow
[test_async_waituntil.html]
[test_worker_reference_gc_timeout.html]
[test_nofetch_handler.html]
[test_bad_script_cache.html]

View File

@ -0,0 +1,96 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test updating a service worker with a bad script cache.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script src='utils.js'></script>
<script class="testbody" type="text/javascript">
async function deleteCaches(cacheStorage) {
let keyList = await cacheStorage.keys();
let promiseList = [];
keyList.forEach(key => {
promiseList.push(cacheStorage.delete(key));
});
return await Promise.all(keyList);
}
function waitForUpdate(reg) {
return new Promise(resolve => {
reg.addEventListener('updatefound', resolve, { once: true });
});
}
async function runTest() {
let reg;
try {
const script = 'update_worker.sjs';
const scope = 'bad-script-cache';
reg = await navigator.serviceWorker.register(script, { scope: scope });
await waitForState(reg.installing, 'activated');
// Verify the service worker script cache has the worker script stored.
let chromeCaches = SpecialPowers.createChromeCache('chrome', window.origin);
let scriptURL = new URL(script, window.location.href);
let response = await chromeCaches.match(scriptURL.href);
is(response.url, scriptURL.href, 'worker script should be stored');
// Force delete the service worker script out from under the service worker.
// Note: Prefs are set to kill the SW thread immediately on idle.
await deleteCaches(chromeCaches);
// Verify the service script cache no longer knows about the worker script.
response = await chromeCaches.match(scriptURL.href);
is(response, undefined, 'worker script should not be stored');
// Force an update and wait for it to fire an update event.
reg.update();
await waitForUpdate(reg);
await waitForState(reg.installing, 'activated');
// Verify that the script cache knows about the worker script again.
response = await chromeCaches.match(scriptURL.href);
is(response.url, scriptURL.href, 'worker script should be stored');
} catch (e) {
ok(false, e);
}
if (reg) {
await reg.unregister();
}
// If this test is run on windows and the process shuts down immediately after, then
// we may fail to remove some of the Cache API body files. This is because the GC
// runs late causing Cache API to cleanup after shutdown begins. It seems something
// during shutdown scans these files and conflicts with removing the file on windows.
//
// To avoid this we perform an explict GC here to ensure that Cache API can cleanup
// earlier.
await new Promise(resolve => SpecialPowers.exactGC(resolve));
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
// standard prefs
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.caches.enabled", true],
// immediately kill the service worker thread when idle
["dom.serviceWorkers.idle_timeout", 0],
]}, runTest);
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,13 @@
/* 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/. */
"use strict";
function handleRequest(request, response) {
// This header is necessary for making this script able to be loaded.
response.setHeader("Content-Type", "application/javascript");
var body = '/* ' + Date.now() + ' */';
response.write(body);
}

View File

@ -1668,6 +1668,10 @@ XULDocument::AddElementToDocumentPre(Element* aElement)
nsresult
XULDocument::AddElementToDocumentPost(Element* aElement)
{
if (aElement == GetRootElement()) {
ResetDocumentDirection();
}
// We need to pay special attention to the keyset tag to set up a listener
if (aElement->NodeInfo()->Equals(nsGkAtoms::keyset, kNameSpaceID_XUL)) {
// Create our XUL key listener and hook it up.

View File

@ -609,13 +609,6 @@ GeneralParser<ParseHandler, CharT>::asFinalParser() const
return static_cast<const FinalParser*>(this);
}
template<class ParseHandler, typename CharT>
inline bool
GeneralParser<ParseHandler, CharT>::abortIfSyntaxParser()
{
return asFinalParser()->abortIfSyntaxParser();
}
template <class ParseHandler, typename CharT>
void
GeneralParser<ParseHandler, CharT>::error(unsigned errorNumber, ...)
@ -805,7 +798,8 @@ ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
const char16_t* chars, size_t length,
bool foldConstants,
UsedNameTracker& usedNames)
: context(cx),
: AutoGCRooter(cx, PARSER),
context(cx),
alloc(alloc),
anyChars(cx, options, thisForCtor()),
traceListHead(nullptr),
@ -824,8 +818,20 @@ ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
tempPoolMark = alloc.mark();
}
bool
ParserBase::checkOptions()
{
#ifdef DEBUG
checkOptionsCalled = true;
#endif
return anyChars.checkOptions();
}
ParserBase::~ParserBase()
{
MOZ_ASSERT(checkOptionsCalled);
alloc.release(tempPoolMark);
/*
@ -838,6 +844,18 @@ ParserBase::~ParserBase()
context->frontendCollectionPool().removeActiveCompilation();
}
template <class ParseHandler>
PerHandlerParser<ParseHandler>::PerHandlerParser(JSContext* cx, LifoAlloc& alloc,
const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length,
bool foldConstants, UsedNameTracker& usedNames,
LazyScript* lazyOuterFunction)
: ParserBase(cx, alloc, options, chars, length, foldConstants, usedNames),
handler(cx, alloc, lazyOuterFunction)
{
}
template <class ParseHandler, typename CharT>
GeneralParser<ParseHandler, CharT>::GeneralParser(JSContext* cx, LifoAlloc& alloc,
const ReadOnlyCompileOptions& options,
@ -846,28 +864,16 @@ GeneralParser<ParseHandler, CharT>::GeneralParser(JSContext* cx, LifoAlloc& allo
UsedNameTracker& usedNames,
SyntaxParser* syntaxParser,
LazyScript* lazyOuterFunction)
: ParserBase(cx, alloc, options, chars, length, foldConstants, usedNames),
AutoGCRooter(cx, PARSER),
syntaxParser_(syntaxParser),
tokenStream(cx, options, chars, length),
handler(cx, alloc, lazyOuterFunction)
{}
template<class ParseHandler, typename CharT>
bool
GeneralParser<ParseHandler, CharT>::checkOptions()
: Base(cx, alloc, options, chars, length, foldConstants, usedNames, lazyOuterFunction),
tokenStream(cx, options, chars, length)
{
#ifdef DEBUG
checkOptionsCalled = true;
#endif
return anyChars.checkOptions();
}
template <class ParseHandler, typename CharT>
GeneralParser<ParseHandler, CharT>::~GeneralParser()
{
MOZ_ASSERT(checkOptionsCalled);
// The Mozilla specific JSOPTION_EXTRA_WARNINGS option adds extra warnings
// which are not generated if functions are parsed lazily. Note that the
// standard "use strict" does not inhibit lazy parsing.
if (options.extraWarningsOption)
disableSyntaxParser();
else
setSyntaxParser(syntaxParser);
}
template <typename CharT>
@ -882,8 +888,8 @@ void
Parser<FullParseHandler, CharT>::setAwaitHandling(AwaitHandling awaitHandling)
{
this->awaitHandling_ = awaitHandling;
if (syntaxParser_)
syntaxParser_->setAwaitHandling(awaitHandling);
if (SyntaxParser* syntaxParser = getSyntaxParser())
syntaxParser->setAwaitHandling(awaitHandling);
}
template <class ParseHandler, typename CharT>
@ -906,7 +912,7 @@ ParserBase::newObjectBox(JSObject* obj)
* function.
*/
ObjectBox* objbox = alloc.new_<ObjectBox>(obj, traceListHead);
ObjectBox* objbox = alloc.template new_<ObjectBox>(obj, traceListHead);
if (!objbox) {
ReportOutOfMemory(context);
return nullptr;
@ -917,13 +923,12 @@ ParserBase::newObjectBox(JSObject* obj)
return objbox;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
FunctionBox*
GeneralParser<ParseHandler, CharT>::newFunctionBox(Node fn, JSFunction* fun,
uint32_t toStringStart,
Directives inheritedDirectives,
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind)
PerHandlerParser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun, uint32_t toStringStart,
Directives inheritedDirectives,
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind)
{
MOZ_ASSERT(fun);
@ -935,9 +940,8 @@ GeneralParser<ParseHandler, CharT>::newFunctionBox(Node fn, JSFunction* fun,
* function.
*/
FunctionBox* funbox =
alloc.new_<FunctionBox>(context, traceListHead, fun, toStringStart,
inheritedDirectives, options().extraWarningsOption,
generatorKind, asyncKind);
alloc.new_<FunctionBox>(context, traceListHead, fun, toStringStart, inheritedDirectives,
options().extraWarningsOption, generatorKind, asyncKind);
if (!funbox) {
ReportOutOfMemory(context);
return nullptr;
@ -961,9 +965,8 @@ ModuleSharedContext::ModuleSharedContext(JSContext* cx, ModuleObject* module,
thisBinding_ = ThisBinding::Module;
}
template <class ParseHandler, typename CharT>
void
GeneralParser<ParseHandler, CharT>::trace(JSTracer* trc)
ParserBase::trace(JSTracer* trc)
{
ObjectBox::TraceList(trc, traceListHead);
}
@ -971,7 +974,7 @@ GeneralParser<ParseHandler, CharT>::trace(JSTracer* trc)
void
TraceParser(JSTracer* trc, AutoGCRooter* parser)
{
static_cast<GeneralParser<FullParseHandler, char16_t>*>(parser)->trace(trc);
static_cast<ParserBase*>(parser)->trace(trc);
}
/*
@ -1179,10 +1182,9 @@ GeneralParser<ParseHandler, CharT>::notePositionalFormalParameter(Node fn, Handl
return true;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
bool
GeneralParser<ParseHandler, CharT>::noteDestructuredPositionalFormalParameter(Node fn,
Node destruct)
PerHandlerParser<ParseHandler>::noteDestructuredPositionalFormalParameter(Node fn, Node destruct)
{
// Append an empty name to the positional formals vector to keep track of
// argument slots when making FunctionScope::Data.
@ -1621,15 +1623,9 @@ GeneralParser<ParseHandler, CharT>::noteDeclaredName(HandlePropertyName name, De
return true;
}
template <class ParseHandler, typename CharT>
bool
GeneralParser<ParseHandler, CharT>::noteUsedName(HandlePropertyName name)
ParserBase::noteUsedNameInternal(HandlePropertyName name)
{
// If the we are delazifying, the LazyScript already has all the
// closed-over info for bindings and there's no need to track used names.
if (handler.canSkipLazyClosedOverBindings())
return true;
// The asm.js validator does all its own symbol-table management so, as an
// optimization, avoid doing any work here.
if (pc->useAsmOrInsideUseAsm())
@ -1646,18 +1642,17 @@ GeneralParser<ParseHandler, CharT>::noteUsedName(HandlePropertyName name)
return usedNames.noteUse(context, name, pc->scriptId(), scope->id());
}
template <class ParseHandler, typename CharT>
bool
GeneralParser<ParseHandler, CharT>::hasUsedName(HandlePropertyName name)
ParserBase::hasUsedName(HandlePropertyName name)
{
if (UsedNamePtr p = usedNames.lookup(name))
return p->value().isUsedInScript(pc->scriptId());
return false;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
bool
GeneralParser<ParseHandler, CharT>::propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope)
PerHandlerParser<ParseHandler>::propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope)
{
// Now that we have all the declared names in the scope, check which
// functions should exhibit Annex B semantics.
@ -2084,9 +2079,9 @@ ParserBase::newLexicalScopeData(ParseContext::Scope& scope)
return Some(bindings);
}
template <typename CharT>
template <>
SyntaxParseHandler::Node
Parser<SyntaxParseHandler, CharT>::finishLexicalScope(ParseContext::Scope& scope, Node body)
PerHandlerParser<SyntaxParseHandler>::finishLexicalScope(ParseContext::Scope& scope, Node body)
{
if (!propagateFreeNamesAndMarkClosedOverBindings(scope))
return null();
@ -2094,9 +2089,9 @@ Parser<SyntaxParseHandler, CharT>::finishLexicalScope(ParseContext::Scope& scope
return body;
}
template <typename CharT>
template <>
ParseNode*
Parser<FullParseHandler, CharT>::finishLexicalScope(ParseContext::Scope& scope, ParseNode* body)
PerHandlerParser<FullParseHandler>::finishLexicalScope(ParseContext::Scope& scope, ParseNode* body)
{
if (!propagateFreeNamesAndMarkClosedOverBindings(scope))
return nullptr;
@ -2108,13 +2103,6 @@ Parser<FullParseHandler, CharT>::finishLexicalScope(ParseContext::Scope& scope,
return handler.newLexicalScope(*bindings, body);
}
template <class ParseHandler, typename CharT>
inline typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::finishLexicalScope(ParseContext::Scope& scope, Node body)
{
return asFinalParser()->finishLexicalScope(scope, body);
}
template <typename CharT>
ParseNode*
Parser<FullParseHandler, CharT>::evalBody(EvalSharedContext* evalsc)
@ -2298,17 +2286,16 @@ Parser<SyntaxParseHandler, CharT>::moduleBody(ModuleSharedContext* modulesc)
return SyntaxParseHandler::NodeFailure;
}
template <class ParseHandler, typename CharT>
bool
GeneralParser<ParseHandler, CharT>::hasUsedFunctionSpecialName(HandlePropertyName name)
ParserBase::hasUsedFunctionSpecialName(HandlePropertyName name)
{
MOZ_ASSERT(name == context->names().arguments || name == context->names().dotThis);
return hasUsedName(name) || pc->functionBox()->bindingsAccessedDynamically();
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
bool
GeneralParser<ParseHandler, CharT>::declareFunctionThis()
PerHandlerParser<ParseHandler>::declareFunctionThis()
{
// The asm.js validator does all its own symbol-table management so, as an
// optimization, avoid doing any work here.
@ -2341,9 +2328,9 @@ GeneralParser<ParseHandler, CharT>::declareFunctionThis()
return true;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::newInternalDotName(HandlePropertyName name)
PerHandlerParser<ParseHandler>::newInternalDotName(HandlePropertyName name)
{
Node nameNode = newName(name);
if (!nameNode)
@ -2353,23 +2340,22 @@ GeneralParser<ParseHandler, CharT>::newInternalDotName(HandlePropertyName name)
return nameNode;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::newThisName()
PerHandlerParser<ParseHandler>::newThisName()
{
return newInternalDotName(context->names().dotThis);
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::newDotGeneratorName()
PerHandlerParser<ParseHandler>::newDotGeneratorName()
{
return newInternalDotName(context->names().dotGenerator);
}
template <class ParseHandler, typename CharT>
bool
GeneralParser<ParseHandler, CharT>::declareDotGeneratorName()
ParserBase::declareDotGeneratorName()
{
// The special '.generator' binding must be on the function scope, as
// generators expect to find it on the CallObject.
@ -2384,9 +2370,9 @@ GeneralParser<ParseHandler, CharT>::declareDotGeneratorName()
return true;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
bool
GeneralParser<ParseHandler, CharT>::finishFunctionScopes(bool isStandaloneFunction)
PerHandlerParser<ParseHandler>::finishFunctionScopes(bool isStandaloneFunction)
{
FunctionBox* funbox = pc->functionBox();
@ -2403,9 +2389,9 @@ GeneralParser<ParseHandler, CharT>::finishFunctionScopes(bool isStandaloneFuncti
return true;
}
template <typename CharT>
template <>
bool
Parser<FullParseHandler, CharT>::finishFunction(bool isStandaloneFunction /* = false */)
PerHandlerParser<FullParseHandler>::finishFunction(bool isStandaloneFunction /* = false */)
{
if (!finishFunctionScopes(isStandaloneFunction))
return false;
@ -2438,9 +2424,9 @@ Parser<FullParseHandler, CharT>::finishFunction(bool isStandaloneFunction /* = f
return true;
}
template <typename CharT>
template <>
bool
Parser<SyntaxParseHandler, CharT>::finishFunction(bool isStandaloneFunction /* = false */)
PerHandlerParser<SyntaxParseHandler>::finishFunction(bool isStandaloneFunction /* = false */)
{
// The LazyScript for a lazily parsed function needs to know its set of
// free variables and inner functions so that when it is fully parsed, we
@ -2498,13 +2484,6 @@ Parser<SyntaxParseHandler, CharT>::finishFunction(bool isStandaloneFunction /* =
return true;
}
template <class ParseHandler, typename CharT>
inline bool
GeneralParser<ParseHandler, CharT>::finishFunction(bool isStandaloneFunction /* = false */)
{
return asFinalParser()->finishFunction(isStandaloneFunction);
}
static YieldHandling
GetYieldHandling(GeneratorKind generatorKind)
{
@ -2602,9 +2581,9 @@ Parser<FullParseHandler, CharT>::standaloneFunction(HandleFunction fun,
return fn;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
bool
GeneralParser<ParseHandler, CharT>::declareFunctionArgumentsObject()
PerHandlerParser<ParseHandler>::declareFunctionArgumentsObject()
{
FunctionBox* funbox = pc->functionBox();
ParseContext::Scope& funScope = pc->functionScope();
@ -2882,9 +2861,8 @@ GeneralParser<ParseHandler, CharT>::matchOrInsertSemicolon()
return tokenStream.matchToken(&matched, TOK_SEMI, TokenStream::Operand);
}
template <class ParseHandler, typename CharT>
bool
GeneralParser<ParseHandler, CharT>::leaveInnerFunction(ParseContext* outerpc)
ParserBase::leaveInnerFunction(ParseContext* outerpc)
{
MOZ_ASSERT(pc != outerpc);
@ -2913,9 +2891,8 @@ GeneralParser<ParseHandler, CharT>::leaveInnerFunction(ParseContext* outerpc)
return true;
}
template <class ParseHandler, typename CharT>
JSAtom*
GeneralParser<ParseHandler, CharT>::prefixAccessorName(PropertyType propType, HandleAtom propAtom)
ParserBase::prefixAccessorName(PropertyType propType, HandleAtom propAtom)
{
RootedAtom prefix(context);
if (propType == PropertyType::Setter || propType == PropertyType::SetterNoExpressionClosure) {
@ -3450,7 +3427,8 @@ Parser<FullParseHandler, CharT>::trySyntaxParseInnerFunction(ParseNode* funcNode
break;
}
if (!syntaxParser_)
SyntaxParser* syntaxParser = getSyntaxParser();
if (!syntaxParser)
break;
UsedNameTracker::RewindToken token = usedNames.getRewindToken();
@ -3458,7 +3436,7 @@ Parser<FullParseHandler, CharT>::trySyntaxParseInnerFunction(ParseNode* funcNode
// Move the syntax parser to the current position in the stream.
typename TokenStream::Position position(keepAtoms);
tokenStream.tell(&position);
if (!syntaxParser_->tokenStream.seek(position, anyChars))
if (!syntaxParser->tokenStream.seek(position, anyChars))
return false;
// Make a FunctionBox before we enter the syntax parser, because |pn|
@ -3470,26 +3448,26 @@ Parser<FullParseHandler, CharT>::trySyntaxParseInnerFunction(ParseNode* funcNode
return false;
funbox->initWithEnclosingParseContext(pc, kind);
if (!syntaxParser_->innerFunctionForFunctionBox(SyntaxParseHandler::NodeGeneric,
pc, funbox, inHandling, yieldHandling,
kind, newDirectives))
if (!syntaxParser->innerFunctionForFunctionBox(SyntaxParseHandler::NodeGeneric,
pc, funbox, inHandling, yieldHandling,
kind, newDirectives))
{
if (syntaxParser_->hadAbortedSyntaxParse()) {
if (syntaxParser->hadAbortedSyntaxParse()) {
// Try again with a full parse. UsedNameTracker needs to be
// rewound to just before we tried the syntax parse for
// correctness.
syntaxParser_->clearAbortedSyntaxParse();
syntaxParser->clearAbortedSyntaxParse();
usedNames.rewind(token);
MOZ_ASSERT_IF(!syntaxParser_->context->helperThread(),
!syntaxParser_->context->isExceptionPending());
MOZ_ASSERT_IF(!syntaxParser->context->helperThread(),
!syntaxParser->context->isExceptionPending());
break;
}
return false;
}
// Advance this parser over tokens processed by the syntax parser.
syntaxParser_->tokenStream.tell(&position);
if (!tokenStream.seek(position, syntaxParser_->anyChars))
syntaxParser->tokenStream.tell(&position);
if (!tokenStream.seek(position, syntaxParser->anyChars))
return false;
// Update the end position of the parse node.
@ -5405,50 +5383,37 @@ GeneralParser<ParseHandler, CharT>::checkExportedNameForClass(Node node)
{
return asFinalParser()->checkExportedNameForClass(node);
}
template<typename CharT>
bool
Parser<FullParseHandler, CharT>::processExport(ParseNode* node)
template<>
inline bool
PerHandlerParser<FullParseHandler>::processExport(ParseNode* node)
{
return pc->sc()->asModuleContext()->builder.processExport(node);
}
template<typename CharT>
template<>
inline bool
Parser<SyntaxParseHandler, CharT>::processExport(Node node)
PerHandlerParser<SyntaxParseHandler>::processExport(Node node)
{
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
return false;
}
template<class ParseHandler, typename CharT>
template<>
inline bool
GeneralParser<ParseHandler, CharT>::processExport(Node node)
{
return asFinalParser()->processExport(node);
}
template<typename CharT>
bool
Parser<FullParseHandler, CharT>::processExportFrom(ParseNode* node)
PerHandlerParser<FullParseHandler>::processExportFrom(ParseNode* node)
{
return pc->sc()->asModuleContext()->builder.processExportFrom(node);
}
template<typename CharT>
template<>
inline bool
Parser<SyntaxParseHandler, CharT>::processExportFrom(Node node)
PerHandlerParser<SyntaxParseHandler>::processExportFrom(Node node)
{
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
return false;
}
template<class ParseHandler, typename CharT>
inline bool
GeneralParser<ParseHandler, CharT>::processExportFrom(Node node)
{
return asFinalParser()->processExportFrom(node);
}
template <class ParseHandler, typename CharT>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::exportFrom(uint32_t begin, Node specList)
@ -6614,7 +6579,7 @@ GeneralParser<ParseHandler, CharT>::breakStatement(YieldHandling yieldHandling)
return stmt->label() == label;
};
if (!pc->findInnermostStatement<ParseContext::LabelStatement>(hasSameLabel)) {
if (!pc->template findInnermostStatement<ParseContext::LabelStatement>(hasSameLabel)) {
error(JSMSG_LABEL_NOT_FOUND);
return null();
}
@ -6810,7 +6775,7 @@ GeneralParser<ParseHandler, CharT>::labeledStatement(YieldHandling yieldHandling
uint32_t begin = pos().begin;
if (pc->findInnermostStatement<ParseContext::LabelStatement>(hasSameLabel)) {
if (pc->template findInnermostStatement<ParseContext::LabelStatement>(hasSameLabel)) {
errorAt(begin, JSMSG_DUPLICATE_LABEL);
return null();
}
@ -7318,17 +7283,13 @@ GeneralParser<ParseHandler, CharT>::classDefinition(YieldHandling yieldHandling,
TokenPos(classStartOffset, classEndOffset));
}
template <class ParseHandler, typename CharT>
bool
GeneralParser<ParseHandler, CharT>::nextTokenContinuesLetDeclaration(TokenKind next)
ParserBase::nextTokenContinuesLetDeclaration(TokenKind next)
{
MOZ_ASSERT(anyChars.isCurrentTokenType(TOK_LET));
MOZ_ASSERT(anyChars.nextToken().type == next);
#ifdef DEBUG
TokenKind verify;
MOZ_ALWAYS_TRUE(tokenStream.peekToken(&verify));
MOZ_ASSERT(next == verify);
#endif
TokenStreamShared::verifyConsistentModifier(TokenStreamShared::None, anyChars.nextToken());
// Destructuring continues a let declaration.
if (next == TOK_LB || next == TOK_LC)
@ -8247,10 +8208,10 @@ GeneralParser<ParseHandler, CharT>::assignExpr(InHandling inHandling, YieldHandl
return handler.newAssignment(kind, lhs, rhs);
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
bool
GeneralParser<ParseHandler, CharT>::isValidSimpleAssignmentTarget(Node node,
FunctionCallBehavior behavior /* = ForbidAssignmentToFunctionCalls */)
PerHandlerParser<ParseHandler>::isValidSimpleAssignmentTarget(Node node,
FunctionCallBehavior behavior /* = ForbidAssignmentToFunctionCalls */)
{
// Note that this method implements *only* a boolean test. Reporting an
// error for the various syntaxes that fail this, and warning for the
@ -8274,9 +8235,9 @@ GeneralParser<ParseHandler, CharT>::isValidSimpleAssignmentTarget(Node node,
return false;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
const char*
GeneralParser<ParseHandler, CharT>::nameIsArgumentsOrEval(Node node)
PerHandlerParser<ParseHandler>::nameIsArgumentsOrEval(Node node)
{
MOZ_ASSERT(handler.isName(node), "must only call this function on known names");
@ -8524,12 +8485,12 @@ GeneralParser<ParseHandler, CharT>::argumentList(YieldHandling yieldHandling, No
return true;
}
template <class ParseHandler, typename CharT>
bool
GeneralParser<ParseHandler, CharT>::checkAndMarkSuperScope()
ParserBase::checkAndMarkSuperScope()
{
if (!pc->sc()->allowSuperProperty())
return false;
pc->setSuperScopeNeedsHomeObject();
return true;
}
@ -8770,16 +8731,16 @@ GeneralParser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
return lhs;
}
template <class ParseHandler, typename CharT>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::newName(PropertyName* name)
template <class ParseHandler>
inline typename ParseHandler::Node
PerHandlerParser<ParseHandler>::newName(PropertyName* name)
{
return newName(name, pos());
}
template <class ParseHandler, typename CharT>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::newName(PropertyName* name, TokenPos pos)
template <class ParseHandler>
inline typename ParseHandler::Node
PerHandlerParser<ParseHandler>::newName(PropertyName* name, TokenPos pos)
{
return handler.newName(name, pos, context);
}
@ -8911,9 +8872,9 @@ GeneralParser<ParseHandler, CharT>::bindingIdentifier(YieldHandling yieldHandlin
return ident;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::identifierReference(Handle<PropertyName*> name)
PerHandlerParser<ParseHandler>::identifierReference(Handle<PropertyName*> name)
{
Node pn = newName(name);
if (!pn)
@ -8925,16 +8886,16 @@ GeneralParser<ParseHandler, CharT>::identifierReference(Handle<PropertyName*> na
return pn;
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::stringLiteral()
PerHandlerParser<ParseHandler>::stringLiteral()
{
return handler.newStringLiteral(anyChars.currentToken().atom(), pos());
}
template <class ParseHandler, typename CharT>
template <class ParseHandler>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::noSubstitutionTaggedTemplate()
PerHandlerParser<ParseHandler>::noSubstitutionTaggedTemplate()
{
if (anyChars.hasInvalidTemplateEscape()) {
anyChars.clearInvalidTemplateEscape();
@ -9990,6 +9951,8 @@ GeneralParser<ParseHandler, CharT>::warnOnceAboutExprClosure()
return true;
}
template class PerHandlerParser<FullParseHandler>;
template class PerHandlerParser<SyntaxParseHandler>;
template class GeneralParser<FullParseHandler, char16_t>;
template class GeneralParser<SyntaxParseHandler, char16_t>;
template class Parser<FullParseHandler, char16_t>;

View File

@ -9,6 +9,161 @@
#ifndef frontend_Parser_h
#define frontend_Parser_h
/*
* JS parsers capable of generating ASTs from source text.
*
* A parser embeds token stream information, then gets and matches tokens to
* generate a syntax tree that, if desired, BytecodeEmitter will use to compile
* bytecode.
*
* Like token streams (see the comment near the top of TokenStream.h), parser
* classes are heavily templatized -- along the token stream's character-type
* axis, and also along a full-parse/syntax-parse axis. Certain limitations of
* C++ (primarily the inability to partially specialize function templates),
* plus the desire to minimize compiled code size in duplicate function
* template instantiations wherever possible, mean that Parser exhibits much of
* the same unholy template/inheritance complexity as token streams.
*
* == ParserBase JS::AutoGCRooter, StrictModeGetter ==
*
* ParserBase is the base parser class, shared by all parsers of all character
* types and parse-handling behavior. It stores everything character- and
* handler-agnostic.
*
* ParserBase's most important field is the parser's token stream's
* |TokenStreamAnyChars| component, for all tokenizing aspects that are
* character-type-agnostic. The character-type-sensitive components residing
* in |TokenStreamSpecific| (see the comment near the top of TokenStream.h)
* live elsewhere in this hierarchy. These separate locations are the reason
* for the |AnyCharsAccess| template parameter to |TokenStreamChars| and
* |TokenStreamSpecific|.
*
* Of particular note: making ParserBase inherit JS::AutoGCRooter (rather than
* placing it under one of the more-derived parser classes) means that all
* parsers can be traced using the same AutoGCRooter mechanism: it's not
* necessary to have separate tracing functionality for syntax/full parsers or
* parsers of different character types.
*
* == PerHandlerParser<ParseHandler> ParserBase ==
*
* Certain parsing behavior varies between full parsing and syntax-only parsing
* but does not vary across source-text character types. For example, the work
* to "create an arguments object for a function" obviously varies between
* syntax and full parsing but (because no source characters are examined) does
* not vary by source text character type. Such functionality is implemented
* through functions in PerHandlerParser.
*
* Functionality only used by syntax parsing or full parsing doesn't live here:
* it should be implemented in the appropriate Parser<ParseHandler> (described
* further below).
*
* == GeneralParser<ParseHandler, CharT> PerHandlerParser<ParseHandler> ==
*
* Most parsing behavior varies across the character-type axis (and possibly
* along the full/syntax axis). For example:
*
* * Parsing ECMAScript's Expression production, implemented by
* GeneralParser::expr, varies in this manner: different types are used to
* represent nodes in full and syntax parsing (ParseNode* versus an enum),
* and reading the tokens comprising the expression requires inspecting
* individual characters (necessarily dependent upon character type).
* * Reporting an error or warning does not depend on the full/syntax parsing
* distinction. But error reports and warnings include a line of context
* (or a slice of one), for pointing out where a mistake was made.
* Computing such line of context requires inspecting the source text to
* make that line/slice of context, which requires knowing the source text
* character type.
*
* Such functionality, implemented using identical function code across these
* axes, should live in GeneralParser.
*
* GeneralParser's most important field is the parser's token stream's
* |TokenStreamSpecific| component, for all aspects of tokenizing that (contra
* |TokenStreamAnyChars| in ParserBase above) are character-type-sensitive. As
* noted above, this field's existence separate from that in ParserBase
* motivates the |AnyCharsAccess| template parameters on various token stream
* classes.
*
* Everything in PerHandlerParser *could* be folded into GeneralParser (below)
* if desired. We don't fold in this manner because all such functions would
* be instantiated once per CharT -- but if exactly equivalent code would be
* generated (because PerHandlerParser functions have no awareness of CharT),
* it's risky to *depend* upon the compiler coalescing the instantiations into
* one in the final binary. PerHandlerParser guarantees no duplication.
*
* == Parser<ParseHandler, CharT> final GeneralParser<ParseHandler, CharT> ==
*
* The final (pun intended) axis of complexity lies in Parser.
*
* Some functionality depends on character type, yet also is defined in
* significantly different form in full and syntax parsing. For example,
* attempting to parse the source text of a module will do so in full parsing
* but immediately fail in syntax parsing -- so the former is a mess'o'code
* while the latter is effectively |return null();|. Such functionality is
* defined in Parser<SyntaxParseHandler or FullParseHandler, CharT> as
* appropriate.
*
* There's a crucial distinction between GeneralParser and Parser, that
* explains why both must exist (despite taking exactly the same template
* parameters, and despite GeneralParser and Parser existing in a one-to-one
* relationship). GeneralParser is one unspecialized template class:
*
* template<class ParseHandler, typename CharT>
* class GeneralParser : ...
* {
* ...parsing functions...
* };
*
* but Parser is one undefined template class with two separate
* specializations:
*
* // Declare, but do not define.
* template<class ParseHandler, typename CharT> class Parser;
*
* // Define a syntax-parsing specialization.
* template<typename CharT>
* class Parser<SyntaxParseHandler, CharT> final
* : public GeneralParser<SyntaxParseHandler, CharT>
* {
* ...parsing functions...
* };
*
* // Define a full-parsing specialization.
* template<typename CharT>
* class Parser<SyntaxParseHandler, CharT> final
* : public GeneralParser<SyntaxParseHandler, CharT>
* {
* ...parsing functions...
* };
*
* This odd distinction is necessary because C++ unfortunately doesn't allow
* partial function specialization:
*
* // BAD: You can only specialize a template function if you specify *every*
* // template parameter, i.e. ParseHandler *and* CharT.
* template<typename CharT>
* void
* GeneralParser<SyntaxParseHandler, CharT>::foo() {}
*
* But if you specialize Parser *as a class*, then this is allowed:
*
* template<typename CharT>
* void
* Parser<SyntaxParseHandler, CharT>::foo() {}
*
* template<typename CharT>
* void
* Parser<FullParseHandler, CharT>::foo() {}
*
* because the only template parameter on the function is CharT -- and so all
* template parameters *are* varying, not a strict subset of them.
*
* So -- any parsing functionality that is differently defined for different
* ParseHandlers, *but* is defined textually identically for different CharT
* (even if different code ends up generated for them by the compiler), should
* reside in Parser.
*/
#include "mozilla/Array.h"
#include "mozilla/Maybe.h"
#include "mozilla/TypeTraits.h"
@ -104,29 +259,21 @@ enum class PropertyType {
DerivedConstructor
};
// Specify a value for an ES6 grammar parametrization. We have no enum for
// [Return] because its behavior is exactly equivalent to checking whether
// we're in a function box -- easier and simpler than passing an extra
// parameter everywhere.
enum YieldHandling { YieldIsName, YieldIsKeyword };
enum AwaitHandling : uint8_t { AwaitIsName, AwaitIsKeyword, AwaitIsModuleKeyword };
enum InHandling { InAllowed, InProhibited };
enum DefaultHandling { NameRequired, AllowDefaultName };
enum TripledotHandling { TripledotAllowed, TripledotProhibited };
enum FunctionCallBehavior {
PermitAssignmentToFunctionCalls,
ForbidAssignmentToFunctionCalls
};
template <class ParseHandler, typename CharT>
class AutoAwaitIsKeyword;
class ParserBase : public StrictModeGetter
class ParserBase
: public StrictModeGetter,
private JS::AutoGCRooter
{
private:
ParserBase* thisForCtor() { return this; }
// This is needed to cast a parser to JS::AutoGCRooter.
friend void js::frontend::TraceParser(JSTracer* trc, JS::AutoGCRooter* parser);
public:
JSContext* const context;
@ -175,6 +322,10 @@ class ParserBase : public StrictModeGetter
UsedNameTracker& usedNames);
~ParserBase();
bool checkOptions();
void trace(JSTracer* trc);
const char* getFilename() const { return anyChars.getFilename(); }
TokenPos pos() const { return anyChars.currentToken().pos; }
@ -246,6 +397,23 @@ class ParserBase : public StrictModeGetter
protected:
enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true };
enum ForInitLocation { InForInit, NotInForInit };
// While on a |let| TOK_NAME token, examine |next| (which must already be
// gotten). Indicate whether |next|, the next token already gotten with
// modifier TokenStream::None, continues a LexicalDeclaration.
bool nextTokenContinuesLetDeclaration(TokenKind next);
bool noteUsedNameInternal(HandlePropertyName name);
bool hasUsedName(HandlePropertyName name);
bool hasUsedFunctionSpecialName(HandlePropertyName name);
bool checkAndMarkSuperScope();
bool declareDotGeneratorName();
bool leaveInnerFunction(ParseContext* outerpc);
JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);
};
inline
@ -271,6 +439,187 @@ ParseContext::VarScope::VarScope(ParserBase* parser)
useAsVarScope(parser->pc);
}
enum FunctionCallBehavior {
PermitAssignmentToFunctionCalls,
ForbidAssignmentToFunctionCalls
};
template <class ParseHandler>
class PerHandlerParser
: public ParserBase
{
private:
using Node = typename ParseHandler::Node;
protected:
/* State specific to the kind of parse being performed. */
ParseHandler handler;
// When ParseHandler is FullParseHandler:
//
// If non-null, this field holds the syntax parser used to attempt lazy
// parsing of inner functions. If null, then lazy parsing is disabled.
//
// When ParseHandler is SyntaxParseHandler:
//
// If non-null, this field must be a sentinel value signaling that the
// syntax parse was aborted. If null, then lazy parsing was aborted due
// to encountering unsupported language constructs.
//
// |internalSyntaxParser_| is really a |Parser<SyntaxParseHandler, CharT>*|
// where |CharT| varies per |Parser<ParseHandler, CharT>|. But this
// template class doesn't have access to |CharT|, so we store a |void*|
// here, then intermediate all access to this field through accessors in
// |GeneralParser<ParseHandler, CharT>| that impose the real type on this
// field.
void* internalSyntaxParser_;
protected:
PerHandlerParser(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length, bool foldConstants,
UsedNameTracker& usedNames, LazyScript* lazyOuterFunction);
static Node null() { return ParseHandler::null(); }
Node stringLiteral();
const char* nameIsArgumentsOrEval(Node node);
bool noteDestructuredPositionalFormalParameter(Node fn, Node destruct);
bool noteUsedName(HandlePropertyName name) {
// If the we are delazifying, the LazyScript already has all the
// closed-over info for bindings and there's no need to track used
// names.
if (handler.canSkipLazyClosedOverBindings())
return true;
return ParserBase::noteUsedNameInternal(name);
}
// Required on Scope exit.
bool propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope);
bool finishFunctionScopes(bool isStandaloneFunction);
Node finishLexicalScope(ParseContext::Scope& scope, Node body);
bool finishFunction(bool isStandaloneFunction = false);
bool declareFunctionThis();
bool declareFunctionArgumentsObject();
inline Node newName(PropertyName* name);
inline Node newName(PropertyName* name, TokenPos pos);
Node newInternalDotName(HandlePropertyName name);
Node newThisName();
Node newDotGeneratorName();
Node identifierReference(Handle<PropertyName*> name);
Node noSubstitutionTaggedTemplate();
inline bool processExport(Node node);
inline bool processExportFrom(Node node);
// If ParseHandler is SyntaxParseHandler:
// Do nothing.
// If ParseHandler is FullParseHandler:
// Disable syntax parsing of all future inner functions during this
// full-parse.
inline void disableSyntaxParser();
// If ParseHandler is SyntaxParseHandler:
// Flag the current syntax parse as aborted due to unsupported language
// constructs and return false. Aborting the current syntax parse does
// not disable attempts to syntax-parse future inner functions.
// If ParseHandler is FullParseHandler:
// Disable syntax parsing of all future inner functions and return true.
inline bool abortIfSyntaxParser();
// If ParseHandler is SyntaxParseHandler:
// Return whether the last syntax parse was aborted due to unsupported
// language constructs.
// If ParseHandler is FullParseHandler:
// Return false.
inline bool hadAbortedSyntaxParse();
// If ParseHandler is SyntaxParseHandler:
// Clear whether the last syntax parse was aborted.
// If ParseHandler is FullParseHandler:
// Do nothing.
inline void clearAbortedSyntaxParse();
public:
bool isValidSimpleAssignmentTarget(Node node,
FunctionCallBehavior behavior = ForbidAssignmentToFunctionCalls);
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, uint32_t toStringStart,
Directives directives, GeneratorKind generatorKind,
FunctionAsyncKind asyncKind);
};
#define ABORTED_SYNTAX_PARSE_SENTINEL reinterpret_cast<void*>(0x1)
template<>
inline void
PerHandlerParser<SyntaxParseHandler>::disableSyntaxParser()
{
}
template<>
inline bool
PerHandlerParser<SyntaxParseHandler>::abortIfSyntaxParser()
{
internalSyntaxParser_ = ABORTED_SYNTAX_PARSE_SENTINEL;
return false;
}
template<>
inline bool
PerHandlerParser<SyntaxParseHandler>::hadAbortedSyntaxParse()
{
return internalSyntaxParser_ == ABORTED_SYNTAX_PARSE_SENTINEL;
}
template<>
inline void
PerHandlerParser<SyntaxParseHandler>::clearAbortedSyntaxParse()
{
internalSyntaxParser_ = nullptr;
}
#undef ABORTED_SYNTAX_PARSE_SENTINEL
// Disable syntax parsing of all future inner functions during this
// full-parse.
template<>
inline void
PerHandlerParser<FullParseHandler>::disableSyntaxParser()
{
internalSyntaxParser_ = nullptr;
}
template<>
inline bool
PerHandlerParser<FullParseHandler>::abortIfSyntaxParser()
{
disableSyntaxParser();
return true;
}
template<>
inline bool
PerHandlerParser<FullParseHandler>::hadAbortedSyntaxParse()
{
return false;
}
template<>
inline void
PerHandlerParser<FullParseHandler>::clearAbortedSyntaxParse()
{
}
enum class ExpressionClosure { Allowed, Forbidden };
template<class Parser>
@ -284,21 +633,95 @@ class ParserAnyCharsAccess
static inline const TokenStreamAnyChars& anyChars(const TokenStreamChars* ts);
};
// Specify a value for an ES6 grammar parametrization. We have no enum for
// [Return] because its behavior is exactly equivalent to checking whether
// we're in a function box -- easier and simpler than passing an extra
// parameter everywhere.
enum YieldHandling { YieldIsName, YieldIsKeyword };
enum InHandling { InAllowed, InProhibited };
enum DefaultHandling { NameRequired, AllowDefaultName };
enum TripledotHandling { TripledotAllowed, TripledotProhibited };
template <class ParseHandler, typename CharT>
class Parser;
template <class ParseHandler, typename CharT>
class GeneralParser
: public ParserBase,
private JS::AutoGCRooter
: public PerHandlerParser<ParseHandler>
{
private:
using Base = PerHandlerParser<ParseHandler>;
using FinalParser = Parser<ParseHandler, CharT>;
using Node = typename ParseHandler::Node;
using typename Base::InvokedPrediction;
using SyntaxParser = Parser<SyntaxParseHandler, CharT>;
protected:
using Modifier = TokenStreamShared::Modifier;
private:
using FinalParser = Parser<ParseHandler, CharT>;
using Node = typename ParseHandler::Node;
using Base::PredictUninvoked;
using Base::PredictInvoked;
using Base::alloc;
using Base::awaitIsKeyword;
#if DEBUG
using Base::checkOptionsCalled;
#endif
using Base::finishFunctionScopes;
using Base::finishLexicalScope;
using Base::foldConstants;
using Base::getFilename;
using Base::hasUsedFunctionSpecialName;
using Base::hasValidSimpleStrictParameterNames;
using Base::isUnexpectedEOF_;
using Base::keepAtoms;
using Base::nameIsArgumentsOrEval;
using Base::newFunction;
using Base::newFunctionBox;
using Base::newName;
using Base::null;
using Base::options;
using Base::pos;
using Base::propagateFreeNamesAndMarkClosedOverBindings;
using Base::setLocalStrictMode;
using Base::stringLiteral;
using Base::traceListHead;
using Base::yieldExpressionsSupported;
using Base::disableSyntaxParser;
using Base::abortIfSyntaxParser;
using Base::hadAbortedSyntaxParse;
using Base::clearAbortedSyntaxParse;
public:
using Base::anyChars;
using Base::context;
using Base::handler;
using Base::isValidSimpleAssignmentTarget;
using Base::pc;
using Base::usedNames;
private:
using Base::checkAndMarkSuperScope;
using Base::declareDotGeneratorName;
using Base::declareFunctionArgumentsObject;
using Base::declareFunctionThis;
using Base::finishFunction;
using Base::hasUsedName;
using Base::identifierReference;
using Base::leaveInnerFunction;
using Base::newDotGeneratorName;
using Base::newInternalDotName;
using Base::newThisName;
using Base::nextTokenContinuesLetDeclaration;
using Base::noSubstitutionTaggedTemplate;
using Base::noteDestructuredPositionalFormalParameter;
using Base::noteUsedName;
using Base::prefixAccessorName;
using Base::processExport;
using Base::processExportFrom;
private:
inline FinalParser* asFinalParser();
inline const FinalParser* asFinalParser() const;
@ -429,30 +852,24 @@ class GeneralParser
void transferErrorsTo(PossibleError* other);
};
protected:
// When ParseHandler is FullParseHandler:
//
// If non-null, this field holds the syntax parser used to attempt lazy
// parsing of inner functions. If null, then lazy parsing is disabled.
//
// When ParseHandler is SyntaxParseHandler:
//
// If non-null, this field must be a sentinel value signaling that the
// syntax parse was aborted. If null, then lazy parsing was aborted due
// to encountering unsupported language constructs.
using SyntaxParser = Parser<SyntaxParseHandler, CharT>;
SyntaxParser* syntaxParser_;
private:
inline bool abortIfSyntaxParser();
// DO NOT USE THE syntaxParser_ FIELD DIRECTLY. Use the accessors defined
// below to access this field per its actual type.
using Base::internalSyntaxParser_;
protected:
SyntaxParser* getSyntaxParser() const {
return reinterpret_cast<SyntaxParser*>(internalSyntaxParser_);
}
void setSyntaxParser(SyntaxParser* syntaxParser) {
internalSyntaxParser_ = syntaxParser;
}
public:
using TokenStream = TokenStreamSpecific<CharT, ParserAnyCharsAccess<GeneralParser>>;
TokenStream tokenStream;
/* State specific to the kind of parse being performed. */
ParseHandler handler;
void prepareNodeForMutation(Node node) { handler.prepareNodeForMutation(node); }
void freeTree(Node node) { handler.freeTree(node); }
@ -461,25 +878,14 @@ class GeneralParser
const CharT* chars, size_t length, bool foldConstants,
UsedNameTracker& usedNames, SyntaxParser* syntaxParser,
LazyScript* lazyOuterFunction);
~GeneralParser();
inline void setAwaitHandling(AwaitHandling awaitHandling);
bool checkOptions();
friend void js::frontend::TraceParser(JSTracer* trc, JS::AutoGCRooter* parser);
/*
* Parse a top-level JS script.
*/
Node parse();
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, uint32_t toStringStart,
Directives directives,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind);
void trace(JSTracer* trc);
/* Report the given error at the current offset. */
void error(unsigned errorNumber, ...);
void errorWithNotes(UniquePtr<JSErrorNotes> notes, unsigned errorNumber, ...);
@ -526,7 +932,6 @@ class GeneralParser
private:
GeneralParser* thisForCtor() { return this; }
Node noSubstitutionTaggedTemplate();
Node noSubstitutionUntaggedTemplate();
Node templateLiteral(YieldHandling yieldHandling);
bool taggedTemplate(YieldHandling yieldHandling, Node nodeList, TokenKind tt);
@ -611,16 +1016,9 @@ class GeneralParser
Node ifStatement(YieldHandling yieldHandling);
Node consequentOrAlternative(YieldHandling yieldHandling);
// While on a |let| TOK_NAME token, examine |next|. Indicate whether
// |next|, the next token already gotten with modifier TokenStream::None,
// continues a LexicalDeclaration.
bool nextTokenContinuesLetDeclaration(TokenKind next);
Node lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind);
inline Node importDeclaration();
inline bool processExport(Node node);
inline bool processExportFrom(Node node);
Node exportFrom(uint32_t begin, Node specList);
Node exportBatch(uint32_t begin);
@ -723,7 +1121,6 @@ class GeneralParser
TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr);
bool tryNewTarget(Node& newTarget);
bool checkAndMarkSuperScope();
Node methodDefinition(uint32_t toStringStart, PropertyType propType, HandleAtom funName);
@ -780,32 +1177,13 @@ class GeneralParser
return labelOrIdentifierReference(yieldHandling);
}
Node identifierReference(Handle<PropertyName*> name);
bool matchLabel(YieldHandling yieldHandling, MutableHandle<PropertyName*> label);
// Indicate if the next token (tokenized as Operand) is |in| or |of|. If
// so, consume it.
bool matchInOrOf(bool* isForInp, bool* isForOfp);
bool hasUsedFunctionSpecialName(HandlePropertyName name);
bool declareFunctionArgumentsObject();
bool declareFunctionThis();
Node newInternalDotName(HandlePropertyName name);
Node newThisName();
Node newDotGeneratorName();
bool declareDotGeneratorName();
inline bool finishFunction(bool isStandaloneFunction = false);
bool leaveInnerFunction(ParseContext* outerpc);
public:
bool isValidSimpleAssignmentTarget(Node node,
FunctionCallBehavior behavior = ForbidAssignmentToFunctionCalls);
private:
const char* nameIsArgumentsOrEval(Node node);
bool checkIncDecOperand(Node operand, uint32_t operandOffset);
bool checkStrictAssignment(Node lhs);
@ -815,14 +1193,9 @@ class GeneralParser
uint32_t prevPos);
bool notePositionalFormalParameter(Node fn, HandlePropertyName name, uint32_t beginPos,
bool disallowDuplicateParams, bool* duplicatedParam);
bool noteDestructuredPositionalFormalParameter(Node fn, Node destruct);
bool checkLexicalDeclarationDirectlyWithinBlock(ParseContext::Statement& stmt,
DeclarationKind kind, TokenPos pos);
bool noteUsedName(HandlePropertyName name);
bool hasUsedName(HandlePropertyName name);
inline Node finishLexicalScope(ParseContext::Scope& scope, Node body);
Node propertyName(YieldHandling yieldHandling,
const mozilla::Maybe<DeclarationKind>& maybeDecl, Node propList,
@ -860,13 +1233,6 @@ class GeneralParser
}
protected:
static Node null() { return ParseHandler::null(); }
Node stringLiteral();
inline Node newName(PropertyName* name);
inline Node newName(PropertyName* name, TokenPos pos);
// Match the current token against the BindingIdentifier production with
// the given Yield parameter. If there is no match, report a syntax
// error.
@ -883,18 +1249,11 @@ class GeneralParser
FunctionAsyncKind asyncKind, bool tryAnnexB, Directives inheritedDirectives,
Directives* newDirectives);
bool finishFunctionScopes(bool isStandaloneFunction);
bool matchOrInsertSemicolon();
bool noteDeclaredName(HandlePropertyName name, DeclarationKind kind, TokenPos pos);
// Required on Scope exit.
bool propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope);
private:
JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);
inline bool asmJS(Node list);
};
@ -925,7 +1284,9 @@ class Parser<SyntaxParseHandler, CharT> final
public:
using Base::anyChars;
using Base::clearAbortedSyntaxParse;
using Base::context;
using Base::hadAbortedSyntaxParse;
using Base::innerFunctionForFunctionBox;
using Base::tokenStream;
@ -955,9 +1316,12 @@ class Parser<SyntaxParseHandler, CharT> final
using Base::ss;
using Base::statementList;
using Base::stringLiteral;
using Base::syntaxParser_;
using Base::usedNames;
private:
using Base::abortIfSyntaxParser;
using Base::disableSyntaxParser;
public:
// Functions with multiple overloads of different visibility. We can't
// |using| the whole thing into existence because of the visibility
@ -977,8 +1341,6 @@ class Parser<SyntaxParseHandler, CharT> final
Node moduleBody(ModuleSharedContext* modulesc);
inline Node importDeclaration();
inline bool processExport(Node node);
inline bool processExportFrom(Node node);
inline bool checkLocalExportNames(Node node);
inline bool checkExportedName(JSAtom* exportName);
inline bool checkExportedNamesForDeclaration(Node node);
@ -995,37 +1357,6 @@ class Parser<SyntaxParseHandler, CharT> final
bool skipLazyInnerFunction(Node funcNode, uint32_t toStringStart, FunctionSyntaxKind kind,
bool tryAnnexB);
Node finishLexicalScope(ParseContext::Scope& scope, Node body);
bool finishFunction(bool isStandaloneFunction = false);
#define ABORTED_SYNTAX_PARSE_SENTINEL reinterpret_cast<SyntaxParser*>(0x1)
// Flag the current syntax parse as aborted due to unsupported language
// constructs and return false. Aborting the current syntax parse does not
// disable attempts to syntax parse future inner functions.
bool abortIfSyntaxParser() {
syntaxParser_ = ABORTED_SYNTAX_PARSE_SENTINEL;
return false;
}
// Return whether the last syntax parse was aborted due to unsupported
// language constructs.
bool hadAbortedSyntaxParse() {
return syntaxParser_ == ABORTED_SYNTAX_PARSE_SENTINEL;
}
// Clear whether the last syntax parse was aborted.
void clearAbortedSyntaxParse() {
syntaxParser_ = nullptr;
}
// Disable syntax parsing of all future inner functions during this
// full-parse.
void disableSyntaxParser() {}
#undef ABORTED_SYNTAX_PARSE_SENTINEL
bool asmJS(Node list);
// Functions present only in Parser<SyntaxParseHandler, CharT>.
@ -1049,19 +1380,6 @@ class Parser<FullParseHandler, CharT> final
friend class GeneralParser<FullParseHandler, CharT>;
public:
Parser(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
const CharT* chars, size_t length, bool foldConstants, UsedNameTracker& usedNames,
SyntaxParser* syntaxParser, LazyScript* lazyOuterFunction)
: Base(cx, alloc, options, chars, length, foldConstants, usedNames, syntaxParser,
lazyOuterFunction)
{
// The Mozilla specific JSOPTION_EXTRA_WARNINGS option adds extra warnings
// which are not generated if functions are parsed lazily. Note that the
// standard "use strict" does not inhibit lazy parsing.
if (options.extraWarningsOption)
disableSyntaxParser();
}
using Base::Base;
// Inherited types, listed here to have non-dependent names.
@ -1071,7 +1389,9 @@ class Parser<FullParseHandler, CharT> final
public:
using Base::anyChars;
using Base::clearAbortedSyntaxParse;
using Base::functionFormalParametersAndBody;
using Base::hadAbortedSyntaxParse;
using Base::handler;
using Base::newFunctionBox;
using Base::options;
@ -1090,6 +1410,7 @@ class Parser<FullParseHandler, CharT> final
using Base::error;
using Base::errorAt;
using Base::finishFunctionScopes;
using Base::finishLexicalScope;
using Base::innerFunction;
using Base::innerFunctionForFunctionBox;
using Base::keepAtoms;
@ -1106,9 +1427,13 @@ class Parser<FullParseHandler, CharT> final
using Base::propagateFreeNamesAndMarkClosedOverBindings;
using Base::statementList;
using Base::stringLiteral;
using Base::syntaxParser_;
using Base::usedNames;
using Base::abortIfSyntaxParser;
using Base::disableSyntaxParser;
using Base::getSyntaxParser;
using Base::setSyntaxParser;
public:
// Functions with multiple overloads of different visibility. We can't
// |using| the whole thing into existence because of the visibility
@ -1129,8 +1454,6 @@ class Parser<FullParseHandler, CharT> final
Node moduleBody(ModuleSharedContext* modulesc);
Node importDeclaration();
bool processExport(Node node);
bool processExportFrom(Node node);
bool checkLocalExportNames(Node node);
bool checkExportedName(JSAtom* exportName);
bool checkExportedNamesForDeclaration(Node node);
@ -1147,10 +1470,6 @@ class Parser<FullParseHandler, CharT> final
bool skipLazyInnerFunction(Node funcNode, uint32_t toStringStart, FunctionSyntaxKind kind,
bool tryAnnexB);
Node finishLexicalScope(ParseContext::Scope& scope, Node body);
bool finishFunction(bool isStandaloneFunction = false);
// Functions present only in Parser<FullParseHandler, CharT>.
// Parse the body of an eval.
@ -1172,26 +1491,6 @@ class Parser<FullParseHandler, CharT> final
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
Directives inheritedDirectives, Directives* newDirectives);
bool abortIfSyntaxParser() {
disableSyntaxParser();
return true;
}
// Return whether the last syntax parse was aborted due to unsupported
// language constructs.
bool hadAbortedSyntaxParse() {
return false;
}
// Clear whether the last syntax parse was aborted.
void clearAbortedSyntaxParse() {}
// Disable syntax parsing of all future inner functions during this
// full-parse.
void disableSyntaxParser() {
syntaxParser_ = nullptr;
}
bool checkStatementsEOF();
// Parse the body of a global script.

View File

@ -15,6 +15,7 @@
#include "jscntxt.h"
#include "frontend/ParseNode.h"
#include "js/GCAnnotations.h"
namespace js {
@ -36,6 +37,18 @@ class SyntaxParseHandler
JSAtom* lastAtom;
TokenPos lastStringPos;
// WARNING: Be careful about adding fields to this function, that might be
// GC things (like JSAtom*). The JS_HAZ_ROOTED causes the GC
// analysis to *ignore* anything that might be a rooting hazard in
// this class. The |lastAtom| field above is safe because
// SyntaxParseHandler only appears as a field in
// PerHandlerParser<SyntaxParseHandler>, and that class inherits
// from ParserBase which contains an AutoKeepAtoms field that
// prevents atoms from being moved around while the AutoKeepAtoms
// lives -- which is as long as ParserBase lives, which is longer
// than the PerHandlerParser<SyntaxParseHandler> that inherits
// from it will live.
public:
enum Node {
NodeFailure = 0,
@ -536,7 +549,7 @@ class SyntaxParseHandler
}
void adjustGetToSet(Node node) {}
};
} JS_HAZ_ROOTED; // See the top of SyntaxParseHandler for why this is safe.
} // namespace frontend
} // namespace js

View File

@ -329,11 +329,20 @@ NewFunctionForwarder(JSContext* cx, HandleId idArg, HandleObject callable,
if (id == JSID_VOIDHANDLE)
id = GetJSIDByIndex(cx, XPCJSContext::IDX_EMPTYSTRING);
// If our callable is a (possibly wrapped) function, we can give
// the exported thing the right number of args.
unsigned nargs = 0;
RootedObject unwrapped(cx, js::UncheckedUnwrap(callable));
if (unwrapped) {
if (JSFunction* fun = JS_GetObjectFunction(unwrapped))
nargs = JS_GetFunctionArity(fun);
}
// We have no way of knowing whether the underlying function wants to be a
// constructor or not, so we just mark all forwarders as constructors, and
// let the underlying function throw for construct calls if it wants.
JSFunction* fun = js::NewFunctionByIdWithReserved(cx, FunctionForwarder,
0, JSFUN_CONSTRUCTOR, id);
nargs, JSFUN_CONSTRUCTOR, id);
if (!fun)
return false;

View File

@ -10,12 +10,14 @@ function run_test() {
epsb.do_check_true = do_check_true;
epsb.do_check_eq = do_check_eq;
subsb.do_check_true = do_check_true;
subsb.do_check_eq = do_check_eq;
// Exporting should work if prinicipal of the source sandbox
// subsumes the principal of the target sandbox.
Cu.evalInSandbox("(" + function() {
var wasCalled = false;
this.funToExport = function(expectedThis, a, obj, native, mixed, callback) {
do_check_eq(arguments.callee.length, 6);
do_check_eq(a, 42);
do_check_eq(obj, subsb.tobecloned);
do_check_eq(obj.cloned, "cloned");
@ -53,6 +55,7 @@ function run_test() {
invokedCallback = false;
callback = function() { invokedCallback = true; };
imported(this, 42, tobecloned, native, mixed, callback);
do_check_eq(imported.length, 6);
do_check_true(invokedCallback);
}.toSource() + ")()", subsb);

View File

@ -9010,7 +9010,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
target->GetView(), rcx,
nsContainerFrame::SET_ASYNC);
target->DidReflow(mPresContext, nullptr, nsDidReflowStatus::FINISHED);
target->DidReflow(mPresContext, nullptr);
if (target == rootFrame && size.BSize(wm) == NS_UNCONSTRAINEDSIZE) {
mPresContext->SetVisibleArea(boundsRelativeToTarget);
}

View File

@ -10028,12 +10028,7 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
FrameConstructionItemList& aItems,
nsIFrame* aParentFrame)
{
if (aItems.IsEmpty()) {
return;
}
const LayoutFrameType parentType = aParentFrame->Type();
if (parentType != LayoutFrameType::FlexContainer &&
parentType != LayoutFrameType::GridContainer) {
if (aItems.IsEmpty() || !::IsFlexOrGridContainer(aParentFrame)) {
return;
}
@ -10717,9 +10712,7 @@ static bool
FrameWantsToBeInAnonymousItem(const nsIFrame* aContainerFrame,
const nsIFrame* aFrame)
{
LayoutFrameType containerType = aContainerFrame->Type();
MOZ_ASSERT(containerType == LayoutFrameType::FlexContainer ||
containerType == LayoutFrameType::GridContainer);
MOZ_ASSERT(::IsFlexOrGridContainer(aContainerFrame));
// Any line-participant frames (e.g. text) definitely want to be wrapped in
// an anonymous flex/grid item.
@ -10729,8 +10722,7 @@ FrameWantsToBeInAnonymousItem(const nsIFrame* aContainerFrame,
// If the container is a -webkit-box/-webkit-inline-box, then placeholders
// also need to be wrapped, for compatibility.
if (containerType == LayoutFrameType::FlexContainer &&
aContainerFrame->HasAnyStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX) &&
if (IsFlexContainerForLegacyBox(aContainerFrame) &&
aFrame->IsPlaceholderFrame()) {
return true;
}
@ -10744,9 +10736,7 @@ VerifyGridFlexContainerChildren(nsIFrame* aParentFrame,
const nsFrameList& aChildren)
{
#ifdef DEBUG
auto parentType = aParentFrame->Type();
if (parentType != LayoutFrameType::FlexContainer &&
parentType != LayoutFrameType::GridContainer) {
if (!::IsFlexOrGridContainer(aParentFrame)) {
return;
}

View File

@ -1689,19 +1689,7 @@ nsPresContext::GetBidi() const
bool
nsPresContext::IsTopLevelWindowInactive()
{
nsCOMPtr<nsIDocShellTreeItem> treeItem(mContainer);
if (!treeItem)
return false;
nsCOMPtr<nsIDocShellTreeItem> rootItem;
treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
if (!rootItem) {
return false;
}
nsCOMPtr<nsPIDOMWindowOuter> domWindow = rootItem->GetWindow();
return domWindow && !domWindow->IsActive();
return Document()->IsTopLevelWindowInactive();
}
void

View File

@ -475,8 +475,7 @@ nsListControlFrame::Reflow(nsPresContext* aPresContext,
// of the reflow protocol, but things seem to work fine without it...
// Is that just an implementation detail of nsHTMLScrollFrame that
// we're depending on?
nsHTMLScrollFrame::DidReflow(aPresContext, &state,
nsDidReflowStatus::FINISHED);
nsHTMLScrollFrame::DidReflow(aPresContext, &state);
// Now compute the block size we want to have
nscoord computedBSize = CalcIntrinsicBSize(BSizeOfARow(), length);
@ -558,8 +557,7 @@ nsListControlFrame::ReflowAsDropdown(nsPresContext* aPresContext,
// of the reflow protocol, but things seem to work fine without it...
// Is that just an implementation detail of nsHTMLScrollFrame that
// we're depending on?
nsHTMLScrollFrame::DidReflow(aPresContext, &state,
nsDidReflowStatus::FINISHED);
nsHTMLScrollFrame::DidReflow(aPresContext, &state);
// Now compute the block size we want to have.
// Note: no need to apply min/max constraints, since we have no such
@ -1506,13 +1504,12 @@ nsListControlFrame::AboutToRollup()
void
nsListControlFrame::DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus)
const ReflowInput* aReflowInput)
{
bool wasInterrupted = !mHasPendingInterruptAtStartOfReflow &&
aPresContext->HasPendingInterrupt();
nsHTMLScrollFrame::DidReflow(aPresContext, aReflowInput, aStatus);
nsHTMLScrollFrame::DidReflow(aPresContext, aReflowInput);
if (mNeedToReset && !wasInterrupted) {
mNeedToReset = false;

View File

@ -79,8 +79,7 @@ public:
nsIFrame* aPrevInFlow) override;
virtual void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus) override;
const ReflowInput* aReflowInput) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,

View File

@ -775,8 +775,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
nsContainerFrame::PositionChildViews(aKidFrame);
}
aKidFrame->DidReflow(aPresContext, &kidReflowInput,
nsDidReflowStatus::FINISHED);
aKidFrame->DidReflow(aPresContext, &kidReflowInput);
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {

View File

@ -6397,8 +6397,7 @@ nsBlockFrame::ReflowFloat(BlockReflowInput& aState,
NS_FRAME_NO_MOVE_VIEW);
}
// Pass floatRS so the frame hierarchy can be used (redoFloatRS has the same hierarchy)
aFloat->DidReflow(aState.mPresContext, &floatRS,
nsDidReflowStatus::FINISHED);
aFloat->DidReflow(aState.mPresContext, &floatRS);
#ifdef NOISY_FLOAT
printf("end ReflowFloat %p, sized to %d,%d\n",
@ -7248,8 +7247,7 @@ nsBlockFrame::ReflowBullet(nsIFrame* aBulletFrame,
aMetrics.ISize(wm),
aMetrics.BSize(wm)),
aState.ContainerSize());
aBulletFrame->DidReflow(aState.mPresContext, &aState.mReflowInput,
nsDidReflowStatus::FINISHED);
aBulletFrame->DidReflow(aState.mPresContext, &aState.mReflowInput);
}
// This is used to scan frames for any float placeholders, add their

View File

@ -428,8 +428,7 @@ nsBlockReflowContext::PlaceBlock(const ReflowInput& aReflowInput,
backupContainingBlockAdvance + mMetrics.BSize(mWritingMode);
if (bEnd > mSpace.BEnd(mWritingMode)) {
// didn't fit, we must acquit.
mFrame->DidReflow(mPresContext, &aReflowInput,
nsDidReflowStatus::FINISHED);
mFrame->DidReflow(mPresContext, &aReflowInput);
return false;
}
}

View File

@ -1089,7 +1089,7 @@ nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame,
}
}
aKidFrame->DidReflow(aPresContext, aReflowInput, nsDidReflowStatus::FINISHED);
aKidFrame->DidReflow(aPresContext, aReflowInput);
}
//XXX temporary: hold on to a copy of the old physical version of
@ -1128,7 +1128,7 @@ nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame,
}
}
aKidFrame->DidReflow(aPresContext, aReflowInput, nsDidReflowStatus::FINISHED);
aKidFrame->DidReflow(aPresContext, aReflowInput);
}
void

View File

@ -218,7 +218,7 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
kid->SetRect(nsRect(bp.IStart(wm), bp.BStart(wm),
convertedSize.ISize(wm), convertedSize.BSize(wm)));
kid->FinishAndStoreOverflow(&kidMetrics, rs.mStyleDisplay);
kid->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
kid->DidReflow(aPresContext, nullptr);
convertedSize.ISize(wm) += bp.IStartEnd(wm);
convertedSize.BSize(wm) += bp.BStartEnd(wm);

View File

@ -6396,20 +6396,16 @@ nsIFrame::ComputeISizeValue(gfxContext* aRenderingContext,
}
void
nsFrame::DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus)
nsFrame::DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput)
{
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
("nsFrame::DidReflow: aStatus=%d", static_cast<uint32_t>(aStatus)));
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, ("nsFrame::DidReflow"));
SVGObserverUtils::InvalidateDirectRenderingObservers(this,
SVGObserverUtils::INVALIDATE_REFLOW);
if (nsDidReflowStatus::FINISHED == aStatus) {
RemoveStateBits(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW |
NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
}
RemoveStateBits(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW |
NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
// Notify the percent bsize observer if there is a percent bsize.
// The observer may be able to initiate another reflow with a computed

View File

@ -368,8 +368,7 @@ public:
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus) override;
const ReflowInput* aReflowInput) override;
/**
* NOTE: aStatus is assumed to be already-initialized. The reflow statuses of

View File

@ -2293,6 +2293,11 @@ ScrollFrameHelper::ScrollToWithOrigin(nsPoint aScrollPosition,
const nsRect* aRange,
nsIScrollbarMediator::ScrollSnapMode aSnap)
{
if (aOrigin != nsGkAtoms::restore) {
// If we're doing a non-restore scroll, we don't want to later
// override it by restoring our saved scroll position.
mRestorePos.x = mRestorePos.y = -1;
}
if (aSnap == nsIScrollableFrame::ENABLE_SNAP) {
GetSnapPointForDestination(nsIScrollableFrame::DEVICE_PIXELS,
@ -4367,6 +4372,8 @@ ScrollFrameHelper::ScrollToRestoredPosition()
(mScrollPort.XMost() - scrollToPos.x - mScrolledFrame->GetRect().width);
}
AutoWeakFrame weakFrame(mOuter);
// It's very important to pass nsGkAtoms::restore here, so
// ScrollToWithOrigin won't clear out mRestorePos.
ScrollToWithOrigin(scrollToPos, nsIScrollableFrame::INSTANT,
nsGkAtoms::restore, nullptr);
if (!weakFrame.IsAlive()) {

View File

@ -390,14 +390,6 @@ operator<<(std::ostream& aStream, const nsReflowStatus& aStatus);
//----------------------------------------------------------------------
/**
* DidReflow status values.
*/
enum class nsDidReflowStatus : uint32_t {
NOT_FINISHED,
FINISHED
};
/**
* When there is no scrollable overflow rect, the visual overflow rect
* may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for
@ -2578,8 +2570,7 @@ public:
* a given reflow?
*/
virtual void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus) = 0;
const ReflowInput* aReflowInput) = 0;
/**
* Updates the overflow areas of the frame. This can be called if an

View File

@ -1042,8 +1042,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
// Tell the frame that we're done reflowing it
aFrame->DidReflow(mPresContext,
isText ? nullptr : reflowInputHolder.ptr(),
nsDidReflowStatus::FINISHED);
isText ? nullptr : reflowInputHolder.ptr());
if (aMetrics) {
*aMetrics = reflowOutput;

View File

@ -833,25 +833,18 @@ nsPluginFrame::GetWindowOriginInPixels(bool aWindowless)
}
void
nsPluginFrame::DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus)
nsPluginFrame::DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput)
{
// Do this check before calling the superclass, as that clears
// NS_FRAME_FIRST_REFLOW
if (aStatus == nsDidReflowStatus::FINISHED &&
(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
NS_ASSERTION(objContent, "Why not an object loading content?");
objContent->HasNewFrame(this);
}
nsFrame::DidReflow(aPresContext, aReflowInput, aStatus);
// The view is created hidden; once we have reflowed it and it has been
// positioned then we show it.
if (aStatus != nsDidReflowStatus::FINISHED)
return;
nsFrame::DidReflow(aPresContext, aReflowInput);
if (HasView()) {
nsView* view = GetView();
@ -1314,9 +1307,7 @@ nsPluginFrame::PrintPlugin(gfxContext& aRenderingContext,
// XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
// XXX Calling DidReflow here makes no sense!!!
nsDidReflowStatus status = nsDidReflowStatus::FINISHED; // should we use a special status?
frame->DidReflow(presContext,
nullptr, status); // DidReflow will take care of it
frame->DidReflow(presContext, nullptr); // DidReflow will take care of it
}
nsRect

View File

@ -83,8 +83,7 @@ public:
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus) override;
const ReflowInput* aReflowInput) override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;

View File

@ -1416,8 +1416,7 @@ nsMathMLContainerFrame::DidReflowChildren(nsIFrame* aFirst, nsIFrame* aStop)
if (grandchild)
DidReflowChildren(grandchild, nullptr);
frame->DidReflow(frame->PresContext(), nullptr,
nsDidReflowStatus::FINISHED);
frame->DidReflow(frame->PresContext(), nullptr);
}
}
}

View File

@ -107,12 +107,11 @@ public:
nsReflowStatus& aStatus) override;
virtual void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus) override
const ReflowInput* aReflowInput) override
{
mPresentationData.flags &= ~NS_MATHML_STRETCH_DONE;
return nsContainerFrame::DidReflow(aPresContext, aReflowInput, aStatus);
return nsContainerFrame::DidReflow(aPresContext, aReflowInput);
}
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,

View File

@ -641,7 +641,7 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
dx += bmBase.width;
} else if (prescriptsFrame == childFrame) {
// Clear reflow flags of prescripts frame.
prescriptsFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
prescriptsFrame->DidReflow(aPresContext, nullptr);
} else {
// process each sup/sub pair
if (0 == count) {

View File

@ -4309,7 +4309,6 @@ public:
nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayEventReceiver);
MOZ_ASSERT(aBuilder->IsForEventDelivery());
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayEventReceiver() {

View File

@ -373,10 +373,6 @@ ServoStyleSet::PreTraverseSync()
LookAndFeel::NativeInit();
// This is lazily computed and pseudo matching needs to access
// it so force computation early.
mPresContext->Document()->GetDocumentState();
if (gfxUserFontSet* userFontSet = mPresContext->Document()->GetUserFontSet()) {
// Ensure that the @font-face data is not stale
uint64_t generation = userFontSet->GetGeneration();

View File

@ -196,16 +196,8 @@ nsCSSPseudoClasses::StringPseudoMatches(const mozilla::dom::Element* aElement,
switch (aPseudo) {
case CSSPseudoClassType::mozLocaleDir:
{
bool docIsRTL;
if (ServoStyleSet::IsInServoTraversal()) {
docIsRTL = aDocument->ThreadSafeGetDocumentState()
.HasState(NS_DOCUMENT_STATE_RTL_LOCALE);
} else {
auto doc = const_cast<nsIDocument*>(aDocument);
docIsRTL = doc->GetDocumentState()
.HasState(NS_DOCUMENT_STATE_RTL_LOCALE);
}
const bool docIsRTL =
aDocument->GetDocumentState().HasState(NS_DOCUMENT_STATE_RTL_LOCALE);
nsDependentString dirString(aString);
if (dirString.EqualsLiteral("rtl")) {

View File

@ -5537,7 +5537,7 @@ SVGTextFrame::DoReflow()
"does not get styled");
kid->Reflow(presContext, desiredSize, reflowInput, status);
kid->DidReflow(presContext, &reflowInput, nsDidReflowStatus::FINISHED);
kid->DidReflow(presContext, &reflowInput);
kid->SetSize(wm, desiredSize.Size(wm));
RemoveStateBits(NS_STATE_SVG_TEXT_IN_REFLOW);

View File

@ -507,10 +507,9 @@ nsSVGOuterSVGFrame::Reflow(nsPresContext* aPresContext,
void
nsSVGOuterSVGFrame::DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus)
const ReflowInput* aReflowInput)
{
nsSVGDisplayContainerFrame::DidReflow(aPresContext,aReflowInput,aStatus);
nsSVGDisplayContainerFrame::DidReflow(aPresContext,aReflowInput);
// Make sure elements styled by :hover get updated if script/animation moves
// them under or out from under the pointer:

View File

@ -63,8 +63,7 @@ public:
nsReflowStatus& aStatus) override;
virtual void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus) override;
const ReflowInput* aReflowInput) override;
virtual void UnionChildOverflow(nsOverflowAreas& aOverflowAreas) override;

View File

@ -786,7 +786,7 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
ReflowOutput desiredSize(aReflowInput);
nsReflowStatus status;
ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowInput, 0, 0, 0, status);
kidFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
kidFrame->DidReflow(aPresContext, nullptr);
continue;
}
@ -1151,7 +1151,7 @@ nsTableRowFrame::ReflowCellFrame(nsPresContext* aPresContext,
aCellFrame->
HasAnyStateBits(NS_FRAME_FIRST_REFLOW));
aCellFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
aCellFrame->DidReflow(aPresContext, nullptr);
return desiredSize.BSize(wm);
}

View File

@ -1163,7 +1163,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsPresContext* aPresContext,
ReflowChild(rowFrame, aPresContext, rowMetrics, rowReflowInput,
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
rowFrame->SetSize(nsSize(rowMetrics.Width(), rowMetrics.Height()));
rowFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
rowFrame->DidReflow(aPresContext, nullptr);
rowFrame->DidResize();
if (!aRowForcedPageBreak && !aStatus.IsFullyComplete() &&

View File

@ -559,12 +559,11 @@ nsBoxFrame::GetInitialAutoStretch(bool& aStretch)
void
nsBoxFrame::DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus)
const ReflowInput* aReflowInput)
{
nsFrameState preserveBits =
mState & (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
nsFrame::DidReflow(aPresContext, aReflowInput, aStatus);
nsFrame::DidReflow(aPresContext, aReflowInput);
AddStateBits(preserveBits);
}

View File

@ -134,8 +134,7 @@ public:
#endif
virtual void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus) override;
const ReflowInput* aReflowInput) override;
virtual bool HonorPrintBackgroundSettings() override;

View File

@ -3250,7 +3250,9 @@ Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter *writer,
"stream->writeSegments returning code %" PRIx32 "\n",
this, streamID, mNeedsCleanup, static_cast<uint32_t>(rv)));
MOZ_ASSERT(!mNeedsCleanup || mNeedsCleanup->StreamID() == streamID);
CleanupStream(streamID, NS_OK, CANCEL_ERROR);
CleanupStream(streamID,
(rv == NS_BINDING_RETARGETED) ? NS_BINDING_RETARGETED : NS_OK,
CANCEL_ERROR);
mNeedsCleanup = nullptr;
*again = false;
rv = ResumeRecv();

View File

@ -1159,4 +1159,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1521662270609000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1521746183319000);

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
/*****************************************************************************/
#include <stdint.h>
const PRTime gPreloadListExpirationTime = INT64_C(1524081455613000);
const PRTime gPreloadListExpirationTime = INT64_C(1524165372062000);
%%
0-1.party, 1
0.me.uk, 1
@ -532,6 +532,7 @@ aaronmcguire.me, 1
aaronroyle.com, 1
aaronsilber.me, 1
aatf.us, 1
aati.info, 0
abaapplianceservice.com, 1
abacus-events.co.uk, 1
abacusbouncycastle.co.uk, 1
@ -2578,6 +2579,7 @@ avid.blue, 1
avidcruiser.com, 1
aviv.nyc, 1
avmemo.com, 1
avmo.pw, 1
avmoo.com, 1
avnet.ws, 1
avocode.com, 1
@ -2585,6 +2587,7 @@ avonlearningcampus.com, 1
avotoma.com, 1
avova.de, 1
avpres.net, 1
avso.pw, 1
avsox.com, 1
avspot.net, 1
avticket.ru, 0
@ -2593,6 +2596,7 @@ avtogara-isperih.com, 1
avtosept.by, 1
avtovokzaly.ru, 1
avvcorda.com, 1
avxo.pw, 1
awan.tech, 1
awaremi-tai.com, 1
awaro.net, 1
@ -3602,7 +3606,6 @@ bitmessage.ch, 1
bitmex.com, 1
bitminter.com, 1
bitmoe.com, 1
bitmon.net, 1
bitok.com, 1
bitplay.space, 1
bitpod.de, 1
@ -3774,6 +3777,7 @@ blockchain.info, 1
blockchaindaigakko.jp, 1
blockified.io, 1
blockmetry.com, 1
blockstream.com, 1
blockxit.de, 1
bloemendal.me, 1
blog-grupom2.es, 1
@ -4227,7 +4231,6 @@ brainserve.com, 1
brainserve.swiss, 1
brainster.co, 1
braintensive.com, 1
braintreebouncycastles.com, 1
brainvoyagermusic.com, 1
brainwork.space, 1
brakemanpro.com, 1
@ -4457,6 +4460,7 @@ btcontract.com, 1
btcpop.co, 1
btcpot.ltd, 1
btcycle.org, 1
btio.pw, 1
btku.org, 1
btnissanparts.com, 1
btorrent.xyz, 1
@ -4474,6 +4478,7 @@ bubblespetspa.com, 1
bubblinghottubs.co.uk, 1
bubblybouncers.co.uk, 1
bubhub.io, 1
buch-angucken.de, 1
buck.com, 1
buckmulligans.com, 1
buckypaper.com, 1
@ -4751,6 +4756,7 @@ caipai.fm, 1
cairnterrier.com.br, 1
cais.de, 1
caitcs.com, 1
caizx.com, 0
caja-pdf.es, 1
cajio.ru, 1
cajunuk.co.uk, 1
@ -5723,7 +5729,7 @@ cirugiasplasticas.com.mx, 1
cirujanooral.com, 1
cirurgicagervasio.com.br, 1
cirurgicalucena.com.br, 1
ciscodude.net, 0
ciscodude.net, 1
cisoaid.com, 1
ciss.ltd, 1
cisy.me, 1
@ -6259,6 +6265,7 @@ compliancedictionary.com, 1
compliancerisksoftware.co.uk, 1
complt.xyz, 1
compostatebien.com.ar, 1
compraneta.com, 0
compreautomacao.com.br, 1
compredietlight.com.br, 1
comprefitasadere.com.br, 1
@ -7505,6 +7512,7 @@ defont.nl, 1
defrax.com, 1
defrax.de, 1
deftek.com, 1
deftnerd.com, 1
defuse.ca, 1
defxing.net, 1
degata.com, 1
@ -7848,6 +7856,7 @@ dicionarioetimologico.com.br, 1
dick.red, 1
dickieslife.com, 1
dickpics.ru, 1
dicoding.com, 1
didacte.com, 1
didche.net, 1
diddens.de, 1
@ -7922,6 +7931,7 @@ digitalcloud.ovh, 1
digitalcraftmarketing.co.uk, 1
digitalcreationclass.com, 1
digitalcuko.com, 1
digitaldashboard.gov, 1
digitaldatacenter.net, 1
digitaldeli.com, 1
digitaldeli.org, 1
@ -8026,7 +8036,7 @@ disconformity.net, 1
discord-chan.net, 1
discordapp.com, 1
discordghost.space, 1
discotek.club, 1
discotek.club, 0
discount24.de, 1
discountmania.eu, 1
discountmetaux.fr, 1
@ -8245,7 +8255,6 @@ domadillo.com, 1
domain-ermittlung.de, 1
domain001.info, 1
domainedemiolan.ch, 1
domainelaremejeanne.com, 1
domainexpress.de, 0
domainkauf.de, 1
domains.google.com, 1
@ -9453,7 +9462,6 @@ epicsecure.de, 1
epicsoft.de, 1
epicvistas.com, 1
epicvistas.de, 1
epicwalnutcreek.com, 1
epilis.gr, 1
epiphyte.network, 1
epistas.com, 1
@ -10255,7 +10263,6 @@ fcapartsdb.com, 1
fcburk.de, 1
fcforum.net, 1
fcitasc.com, 1
fckd.net, 1
fcprovadia.com, 1
fdevs.ch, 1
fdlibre.eu, 1
@ -10369,6 +10376,7 @@ feuerwehr-illmensee.de, 1
feuerwehr-oberkotzau.de, 1
feuerwerksmanufaktur.de, 1
feuetgloire.com, 1
fewo-thueringer-wald.de, 1
fexco.com, 1
feyermedia.de, 1
ff-bad-hoehenstadt.de, 1
@ -10690,7 +10698,6 @@ flowcom.de, 1
flowerandplant.org, 1
flowersbylegacy.com, 1
flowreader.com, 1
flox.io, 1
floydm.com, 1
flra.gov, 1
flucky.xyz, 1
@ -10941,7 +10948,6 @@ fraho.eu, 1
framapiaf.org, 1
framedpaws.com, 1
fran.cr, 1
francesca-and-lucas.com, 1
francescopalazzo.com, 1
franchini.email, 1
franchini.engineer, 1
@ -12681,6 +12687,7 @@ hapivm.com, 1
happist.com, 0
happyagain.de, 1
happyagain.se, 1
happyandrelaxeddogs.eu, 0
happybounce.co.uk, 1
happycarb.de, 1
happydoq.ch, 1
@ -13251,7 +13258,6 @@ hms-waldmann.de, 1
hmsseahawk.com, 1
hn.search.yahoo.com, 0
hoahau.org, 1
hobaugh.social, 1
hobby-drechselei.de, 1
hobby-gamerz-community.de, 1
hobbyspeed.com, 1
@ -13391,7 +13397,6 @@ hord.ca, 1
horeizai.net, 1
horisonttimedia.fi, 1
horizonhomes-samui.com, 1
horizonshypnosis.ca, 1
horkel.cf, 1
hornyforhanzo.com, 1
horodance.dk, 1
@ -14871,7 +14876,6 @@ jackpothappy.com, 1
jackrusselterrier.com.br, 1
jackyliao123.tk, 1
jackyyf.com, 0
jaco.by, 1
jacobdevans.com, 1
jacobhaug.com, 1
jacobi-server.de, 1
@ -15226,7 +15230,6 @@ jiyusu.com, 1
jiyuu-ni.com, 1
jiyuu-ni.net, 1
jjf.org.au, 1
jjj.blog, 1
jjspartyhire.co.uk, 1
jjspartytime.co.uk, 1
jjvanoorschot.nl, 1
@ -15611,7 +15614,7 @@ justbouncecastles.co.uk, 1
justchunks.net, 1
justgalak.com, 1
justgalak.org, 1
justice.gov, 1
justice.gov, 0
justice4assange.com, 1
justinellingwood.com, 1
justinharrison.ca, 1
@ -15981,7 +15984,6 @@ kepler-seminar.de, 1
kerebro.com, 1
kerem.xyz, 1
kerforhome.com, 1
kerijacoby.com, 1
kermadec.com, 1
kernel-error.de, 1
kernelpanics.nl, 1
@ -16647,6 +16649,7 @@ kwidz.fr, 1
kwikmed.eu, 0
kwipi.com, 1
kwmr.me, 1
kwok.cc, 1
kwyxz.org, 1
kxah35.com, 1
kxnrl.com, 1
@ -17007,7 +17010,6 @@ leakreporter.net, 1
leaks.directory, 1
leanclub.org, 1
leandre.cn, 1
leanplando.com, 1
leaodarodesia.com.br, 1
leap-it.be, 1
leapandjump.co.uk, 1
@ -17082,7 +17084,7 @@ legaltip.eu, 1
legatofmrc.fr, 1
legendary.camera, 1
legendesdechine.ch, 1
legendofkrystal.com, 0
legendofkrystal.com, 1
legends-game.ru, 0
legible.es, 1
legioniv.org, 1
@ -17546,6 +17548,7 @@ liul.in, 1
liushuyu.tk, 1
liv3ly.com, 1
livebetterwith.com, 1
livecards.co.uk, 1
livecards.es, 1
livecards.eu, 1
livecards.it, 1
@ -17586,7 +17589,6 @@ liyin.date, 1
liyinjia.com, 1
lizardsystems.com, 1
lizhi.io, 1
lizzythepooch.com, 1
ljason.cn, 1
ljs.io, 1
lknw.de, 1
@ -17880,7 +17882,6 @@ luc-oberson.ch, 1
luca.swiss, 1
lucakrebs.de, 1
lucasantarella.com, 1
lucascantor.com, 1
lucascodes.com, 1
lucasem.com, 1
lucasgaland.com, 1
@ -18187,6 +18188,7 @@ mail-settings.google.com, 1
mail.com, 1
mail.de, 1
mail.google.com, 1
mail.yahoo.com, 0
mail4geek.com, 1
mail4you.in, 1
mailbox.mg, 1
@ -18284,7 +18286,6 @@ mamiecouscous.com, 1
mammals.net, 1
mammaw.com, 1
mammeitalianeavienna.com, 1
mammooc.org, 1
mamochka.org.ua, 1
mamospienas.lt, 1
mamot.fr, 0
@ -18619,6 +18620,7 @@ mattcarr.net, 0
mattcoles.io, 1
matteomarescotti.it, 1
mattferderer.com, 1
mattfin.ch, 1
mattforster.ca, 1
matthecat.com, 1
matthew-carson.info, 1
@ -19726,7 +19728,6 @@ morepay.cn, 1
moreserviceleads.com, 1
morespacestorage.com.au, 1
moresw.com, 1
morethandigital.info, 1
morfitronik.pl, 1
morganino.eu, 1
morganino.it, 1
@ -19835,7 +19836,7 @@ mplusm.eu, 1
mpn.poker, 1
mpnpokertour.com, 1
mpodraza.pl, 1
mpreserver.com, 0
mpreserver.com, 1
mpserver12.org, 1
mpsgarage.com.au, 1
mpsoundcraft.com, 1
@ -20939,6 +20940,7 @@ nielshoogenhout.be, 1
nielshoogenhout.eu, 1
nielshoogenhout.nl, 1
nien.cf, 1
nien.co, 1
nien.com, 1
nien.com.tw, 1
nien.eu.org, 1
@ -21130,7 +21132,6 @@ noop.ch, 1
noordsee.de, 1
noorsolidarity.com, 1
nootropic.com, 1
nootropicsource.com, 1
noovell.com, 1
nopaste.xyz, 1
nopaynocure.com, 1
@ -21877,6 +21878,7 @@ oreto.de, 1
orf-digitalsatkarte.at, 0
orf-kartentausch.at, 0
orfeo-engineering.ch, 1
organica.co.za, 1
organicae.com, 1
organisatieteam.nl, 1
organisationsberatung-jacobi.de, 1
@ -22776,6 +22778,7 @@ phuket-idc.com, 1
phuket-idc.de, 1
phunehehe.net, 1
phuong.faith, 1
phurl.de, 1
phurl.io, 1
phus.lu, 1
physicalism.com, 1
@ -23074,7 +23077,6 @@ plugcubed.net, 0
pluggedhead.com, 1
plugin-planet.com, 1
pluginfactory.io, 1
pluginsloaded.com, 1
plumber-in-sandton.co.za, 1
plumbingbenoni.co.za, 1
plumlocosoft.com, 1
@ -23108,6 +23110,7 @@ pmbc.org, 1
pmbremer.de, 1
pmconference.ch, 1
pmctire.com, 1
pmemanager.fr, 1
pmessage.ch, 1
pmg-offshore-company.com, 1
pmg-purchase.com, 1
@ -23304,6 +23307,7 @@ postdarwinism.com, 1
postdeck.de, 1
posteo.de, 0
posters.win, 1
posterspy.com, 1
postfalls-naturopathic.com, 1
postfinance.ch, 1
postmatescode.com, 1
@ -23619,7 +23623,6 @@ projectunity.io, 1
projectvault.ovh, 1
projectx.top, 1
projekt-umbriel.de, 1
projektik.cz, 1
projektzentrisch.de, 1
projest.ch, 1
prok.pw, 1
@ -23923,6 +23926,7 @@ qifu.me, 1
qifu.org.cn, 1
qikan.net, 1
qimiao.io, 1
qingpat.com, 1
qingpei.me, 0
qionouu.cn, 1
qitarabutrans.com, 1
@ -24220,7 +24224,6 @@ ravhaaglanden.org, 1
ravindran.me, 1
ravis.org, 1
ravse.dk, 1
raw-diets.com, 1
rawsec.net, 1
raxion.cf, 1
raxion.tk, 1
@ -24754,7 +24757,6 @@ rico-brase.de, 0
rico.ovh, 1
ricochet.im, 1
ricozienke.de, 1
riddims.co, 1
ride-up.com, 1
rideaudiscount.com, 1
ridingboutique.de, 1
@ -24995,7 +24997,6 @@ romanticschemermovie.com, 1
romanticvillas.com.au, 1
rome.dating, 1
rommelwood.de, 1
ronanrbr.com, 1
rondommen.nl, 1
rondouin.fr, 1
rondreis-planner.nl, 1
@ -26069,6 +26070,7 @@ selfici.com, 1
selfici.cz, 1
selfishness.com, 1
selfloath.in, 1
selfmade4u.de, 1
selfserverx.com, 0
selkiemckatrick.com, 1
sellajoch.com, 1
@ -26079,7 +26081,7 @@ seltendoof.de, 1
semacode.com, 1
semaflex.it, 1
semaphore-studios.com, 1
semenov.su, 1
semenov.su, 0
semianalog.com, 1
seminariruum.ee, 1
semiocast.com, 1
@ -26858,7 +26860,6 @@ sktsolution.com, 0
skuldwyrm.no, 1
skwile-cafe.com, 1
sky-aroma.com, 1
skyanchor.com, 1
skybound.link, 1
skydragoness.com, 1
skydrive.live.com, 0
@ -27579,6 +27580,7 @@ ssa.gov, 0
ssbkk.ru, 1
ssbrm.ch, 1
sscd.no, 1
ssdax.com, 0
ssenberg.nl, 1
ssh-keys.online, 1
ssh-vault.com, 1
@ -27699,7 +27701,7 @@ starttraffic.uk, 1
startup.melbourne, 1
startuplevel.com, 1
startuppeople.co.uk, 1
startupsort.com, 1
startupsort.com, 0
startupum.ru, 1
starwatches.eu, 1
starwins.co.uk, 1
@ -27834,7 +27836,6 @@ stevensheffey.me, 1
stevenski.com, 0
steventress.com, 1
stevenwooding.com, 1
stevenz.net, 1
stevenz.science, 1
stevenz.xyz, 1
stevesdrivingschooltyneside.com, 1
@ -28417,7 +28418,7 @@ ta65.com, 1
taabe.net, 1
taartenfeesies.nl, 1
tab.watch, 1
tabelfirme.ro, 1
tabelfirme.ro, 0
tabernadovinho.com.br, 1
tabino.top, 1
tabithawebb.co.uk, 1
@ -28679,6 +28680,7 @@ techday.com, 1
techday.com.au, 1
techday.eu, 1
techdirt.com, 1
techendeavors.com, 1
techhappy.ca, 1
techiehall.com, 1
techinet.pl, 1
@ -29001,6 +29003,7 @@ thecondobuyers.com, 1
thecozycastle.com, 1
thecrazytravel.com, 1
thecrew-exchange.com, 1
thecrochetcottage.net, 1
thecskr.in, 1
thecsw.com, 1
thecuppacakery.co.uk, 1
@ -29486,7 +29489,6 @@ tkn.tokyo, 1
tkts.cl, 1
tkusano.jp, 1
tkw01536.de, 1
tlach.cz, 1
tlca.org, 1
tlcnet.info, 1
tlehseasyads.com, 1
@ -29567,7 +29569,6 @@ todocracy.com, 1
todoescine.com, 1
todoist.com, 1
todon.fr, 1
todoscomciro.com, 1
todosrv.com, 1
toeglhofer.at, 1
toeightycountries.com, 1
@ -30199,7 +30200,6 @@ turtleduckstudios.com, 1
turtlepwr.com, 1
turtles.ga, 1
tutanota.com, 1
tuthowto.com, 1
tutiendaroja.com, 1
tutiendarosa.com, 1
tuto-craft.com, 1
@ -30349,7 +30349,6 @@ ubineering.de, 1
ublaboo.org, 1
uborcare.com, 1
ubtce.com, 1
ubuntuhot.com, 1
ucac.nz, 0
ucangiller.com, 1
ucch.be, 1
@ -30613,6 +30612,7 @@ urbanietz-immobilien.de, 1
urbanmelbourne.info, 1
urbannewsservice.com, 1
urbansparrow.in, 1
urbanstylestaging.com, 1
urbanwildlifealliance.org, 1
urbexdk.nl, 1
urcentral.com, 1
@ -30626,7 +30626,6 @@ url.cab, 1
url.fi, 1
url.fm, 1
url.rw, 1
url0.eu, 1
urlachershop.com.br, 1
urlaub-leitner.at, 1
urlscan.io, 1
@ -31255,7 +31254,7 @@ vocalviews.com, 1
vodpay.com, 1
vodpay.net, 1
vodpay.org, 1
voeux.io, 1
voeux.io, 0
vogler.name, 1
vogt.tech, 1
voice-of-design.com, 1
@ -31533,7 +31532,6 @@ waterschaplimburg.nl, 1
watertrails.io, 1
waterworkscondos.com, 1
watsonwork.me, 1
wattechweb.com, 1
wave-ola.es, 1
wavesboardshop.com, 1
wavesoftime.com, 1
@ -31615,7 +31613,6 @@ webbhuset.se, 0
webbiz.co.uk, 1
webbson.net, 1
webbuzz.com.au, 1
webbx.se, 1
webcamtoy.com, 1
webcatchers.nl, 1
webcatechism.com, 1
@ -32260,7 +32257,6 @@ woodlandsvale.uk, 1
woodlandwindows.com, 1
woodomat.com, 1
woodsidepottery.ca, 1
woodworkertip.com, 1
woof.gq, 1
woohooyeah.nl, 1
woomu.me, 1
@ -32517,6 +32513,7 @@ www.theguardian.com, 1
www.therapynotes.com, 1
www.tinfoilsecurity.com, 0
www.torproject.org, 0
www.tumblr.com, 0
www.twitter.com, 0
www.united.com, 1
www.usaa.com, 0
@ -33046,6 +33043,7 @@ yotilab.com, 1
yotilabs.com, 1
yotta-zetta.com, 1
yotubaiotona.net, 1
youcaitian.com, 1
youcancraft.de, 1
youcanfuckoff.xyz, 1
youcanmakeit.at, 1
@ -33053,7 +33051,6 @@ youcruit.com, 1
youdamom.com, 0
youdowell.com, 1
youdungoofd.com, 1
youftp.tk, 1
yougee.ml, 1
youhacked.me, 1
youhavewords.com, 1
@ -33243,7 +33240,6 @@ zaratan.fr, 1
zargaripour.com, 1
zarmarket.org, 1
zarpo.com.br, 1
zary.me, 1
zaufanatrzeciastrona.pl, 1
zavec.com.ec, 1
zavetaji.lv, 1

View File

@ -28,11 +28,6 @@ jobs:
- /bin/bash
- -c
- echo "Dummy task"
treeherder:
symbol: Rel(BD)
platform: linux/opt
kind: test
tier: 1
devedition:
name: post-balrog-dummy
@ -50,8 +45,3 @@ jobs:
- /bin/bash
- -c
- echo "Dummy task"
treeherder:
symbol: Rel(BD)
platform: linux-devedition/opt
kind: test
tier: 1

View File

@ -46,11 +46,6 @@ jobs:
- /bin/bash
- -c
- echo "Dummy task"
treeherder:
symbol: Rel(BMD)
platform: linux/opt
kind: test
tier: 1
devedition-ship:
name: post-beetmover-dummy
@ -85,8 +80,3 @@ jobs:
- /bin/bash
- -c
- echo "Dummy task"
treeherder:
symbol: Rel(BMD)
platform: linux-devedition/opt
kind: test
tier: 1

View File

@ -144,11 +144,11 @@ browser-screenshots:
loopback-video: true
run-on-projects:
by-test-platform:
windows.*/opt: ['mozilla-central']
linux64/opt: ['mozilla-central']
macosx.*/opt: ['mozilla-central']
windows7-32-devedition/opt: []
windows10-64-devedition/opt: []
# We don't want debug, pgo, devedition or nightly builds
windows7-32/opt: ['mozilla-central', 'integration']
windows10-64/opt: ['mozilla-central', 'integration']
linux64/opt: ['mozilla-central', 'integration']
macosx64/opt: ['mozilla-central', 'integration']
default: []
max-run-time: 3600
mozharness:

View File

@ -151,6 +151,8 @@ def verify_dependency_tiers(task, taskgraph, scratch_pad):
for d in task.dependencies.itervalues():
if taskgraph[d].task.get("workerType") == "buildbot-bridge":
continue
if "dummy" in taskgraph[d].kind:
continue
if tier < tiers[d]:
raise Exception(
'{} (tier {}) cannot depend on {} (tier {})'

View File

@ -4,7 +4,9 @@
RUST_PROGRAMS += ["geckodriver"]
RustTest("geckodriver")
# https://bugzil.la/1425365
if CONFIG["OS_ARCH"] != "WINNT":
RustTest("geckodriver")
with Files("**"):
BUG_COMPONENT = ("Testing", "Marionette")

View File

@ -643,11 +643,13 @@ class DeviceManagerADB(DeviceManager):
if directive == "systime" or directive == "all":
ret["systime"] = self.shellCheckOutput(["date"], timeout=self.short_timeout)
if directive == "memtotal" or directive == "all":
meminfo = {}
for line in self.pullFile("/proc/meminfo").splitlines():
key, value = line.split(":")
meminfo[key] = value.strip()
ret["memtotal"] = meminfo["MemTotal"]
out = self.shellCheckOutput(["cat", "/proc/meminfo"], timeout=self.short_timeout)
out = out.replace('\r\n', '\n').splitlines(True)
for line in out:
parts = line.split(":")
if len(parts) == 2 and parts[0] == "MemTotal":
ret["memtotal"] = parts[1].strip()
break
if directive == "disk" or directive == "all":
data = self.shellCheckOutput(
["df", "/data", "/system", "/sdcard"], timeout=self.short_timeout)

View File

@ -155029,6 +155029,18 @@
{}
]
],
"css/cssom-view/scrollTop-display-change.html": [
[
"/css/cssom-view/scrollTop-display-change.html",
[
[
"/css/cssom-view/scrollTop-display-change-ref.html",
"=="
]
],
{}
]
],
"css/cssom-view/scrollingElement-quirks-dynamic-001.html": [
[
"/css/cssom-view/scrollingElement-quirks-dynamic-001.html",
@ -253096,6 +253108,11 @@
{}
]
],
"css/cssom-view/scrollTop-display-change-ref.html": [
[
{}
]
],
"css/cssom-view/scrollingElement-quirks-dynamic-001-ref.html": [
[
{}
@ -511612,6 +511629,14 @@
"0561564f185dcaf2ad3a8e14e081efb3c2c273e3",
"testharness"
],
"css/cssom-view/scrollTop-display-change-ref.html": [
"bb9079ba597cbcc27604cf8cc5556b4e6e0cda93",
"support"
],
"css/cssom-view/scrollTop-display-change.html": [
"68d33e9669be4db95ea9016a8893212e588189fd",
"reftest"
],
"css/cssom-view/scrollWidthHeight.xht": [
"06ec592720f3db3c04cdd792177179b11a097a23",
"testharness"

View File

@ -0,0 +1,8 @@
<!doctype html>
<meta charset=utf-8>
<div id="scroller" style="height: 100px; overflow: scroll">
<div style="height: 1000px">
I should be visible.
</div>
I should not be visible.
</div>

View File

@ -0,0 +1,17 @@
<!doctype html>
<meta charset=utf-8>
<title>Setting scrollTop to 0 immediately after toggling display from "none" on an element that had nonzero scrollTop before should work.</title>
<link rel=match href="scrollTop-display-change-ref.html">
<div id="scroller" style="height: 100px; overflow: scroll">
<div style="height: 1000px">
I should be visible.
</div>
I should not be visible.
</div>
<script>
scroller.scrollTop = 1000;
scroller.style.display = "none";
var win = scroller.scrollTop; // Force layout flush
scroller.style.display = "";
scroller.scrollTop = 0;
</script>

View File

@ -108,10 +108,10 @@ Readability.prototype = {
// All of the regular expressions in use within readability.
// Defined up here so we don't instantiate them repeatedly in loops.
REGEXPS: {
unlikelyCandidates: /banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|foot|header|legends|menu|modal|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
unlikelyCandidates: /banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|foot|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
okMaybeItsACandidate: /and|article|body|column|main|shadow/i,
positive: /article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i,
negative: /hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|modal|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,
negative: /hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,
extraneous: /print|archive|comment|discuss|e[\-]?mail|share|reply|all|login|sign|single|utility/i,
byline: /byline|author|dateline|writtenby|p-author/i,
replaceFonts: /<(\/?)font[^>]*>/gi,
@ -249,7 +249,7 @@ Readability.prototype = {
*/
_cleanClasses: function(node) {
var classesToPreserve = this._classesToPreserve;
var className = node.className
var className = (node.getAttribute("class") || "")
.split(/\s+/)
.filter(function(cls) {
return classesToPreserve.indexOf(cls) != -1;
@ -257,7 +257,7 @@ Readability.prototype = {
.join(" ");
if (className) {
node.className = className;
node.setAttribute("class", className);
} else {
node.removeAttribute("class");
}

View File

@ -90,7 +90,7 @@ html|a {
text-decoration: underline;
}
@media not all and (-moz-touch-enabled) {
@media (-moz-touch-enabled: 0) {
:-moz-handler-clicktoplay .msgTapToPlay {
display: none;
}

View File

@ -55,7 +55,7 @@ tab[visuallyselected="true"]:not(:-moz-window-inactive) {
color: #FFF;
}
@media not all and (-moz-mac-yosemite-theme) {
@media (-moz-mac-yosemite-theme: 0) {
tab[visuallyselected="true"] {
color: #FFF;
text-shadow: rgba(0, 0, 0, 0.4) 0 1px;