author | Phil Ringnalda <philringnalda@gmail.com> |
Sat, 02 May 2015 10:02:17 -0700 | |
changeset 242123 | 0f5eacc986e89338f40fc5478698850d756b496e |
parent 242062 | d3ae46508499306d36934437be685456d229944d (current diff) |
parent 242122 | f703c5483fa01bb6251c826cb2f7417d655ae611 (diff) |
child 242137 | dc5f85980a828aaa32b599b15b93ab8d1287ff5b |
push id | 28679 |
push user | philringnalda@gmail.com |
push date | Sat, 02 May 2015 17:02:29 +0000 |
treeherder | mozilla-central@0f5eacc986e8 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 40.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
browser/branding/aurora/Makefile.in | file | annotate | diff | comparison | revisions | |
browser/branding/nightly/Makefile.in | file | annotate | diff | comparison | revisions | |
browser/branding/official/Makefile.in | file | annotate | diff | comparison | revisions | |
browser/branding/unofficial/Makefile.in | file | annotate | diff | comparison | revisions | |
intl/uconv/tests/unit/test_bug365345.js | file | annotate | diff | comparison | revisions | |
intl/unicharutil/tables/htmlEntityVersions.properties | file | annotate | diff | comparison | revisions | |
intl/unicharutil/tables/transliterate.properties | file | annotate | diff | comparison | revisions | |
intl/unicharutil/tests/moz.build | file | annotate | diff | comparison | revisions | |
intl/unicharutil/tests/unit/test_bug_427350_1.js | file | annotate | diff | comparison | revisions | |
intl/unicharutil/tests/unit/xpcshell.ini | file | annotate | diff | comparison | revisions | |
media/libvpx/bug1137614.patch | file | annotate | diff | comparison | revisions |
--- a/Makefile.in +++ b/Makefile.in @@ -90,17 +90,17 @@ backend.RecursiveMakeBackend: Makefile: backend.RecursiveMakeBackend @$(TOUCH) $@ include backend.RecursiveMakeBackend.pp default:: backend.RecursiveMakeBackend install_manifests := \ - $(addprefix dist/,bin idl include public private sdk xpi-stage) \ + $(addprefix dist/,bin branding idl include public private sdk xpi-stage) \ _tests \ $(NULL) install_manifest_depends = \ CLOBBER \ $(configure_dir)/configure \ config.status \ backend.RecursiveMakeBackend \ $(NULL)
--- a/accessible/windows/ia2/ia2Accessible.cpp +++ b/accessible/windows/ia2/ia2Accessible.cpp @@ -349,17 +349,17 @@ ia2Accessible::get_states(AccessibleStat return E_INVALIDARG; *aStates = 0; // XXX: bug 344674 should come with better approach that we have here. AccessibleWrap* acc = static_cast<AccessibleWrap*>(this); if (acc->IsDefunct()) { *aStates = IA2_STATE_DEFUNCT; - return CO_E_OBJNOTCONNECTED; + return S_OK; } uint64_t state; if (acc->IsProxy()) state = acc->Proxy()->State(); else state = acc->State();
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -605,17 +605,17 @@ pref("mousewheel.with_shift.action", 2); pref("mousewheel.with_meta.action", 1); // win key on Win, Super/Hyper on Linux #endif pref("mousewheel.with_control.action",3); pref("mousewheel.with_win.action", 1); pref("browser.xul.error_pages.enabled", true); pref("browser.xul.error_pages.expert_bad_cert", false); -// Work Offline is best manually managed by the user. +// If true, network link events will change the value of navigator.onLine pref("network.manage-offline-status", false); // We want to make sure mail URLs are handled externally... pref("network.protocol-handler.external.mailto", true); // for mail pref("network.protocol-handler.external.news", true); // for news pref("network.protocol-handler.external.snews", true); // for secure news pref("network.protocol-handler.external.nntp", true); // also news #ifdef XP_WIN
deleted file mode 100644 --- a/browser/branding/aurora/Makefile.in +++ /dev/null @@ -1,48 +0,0 @@ -# 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/. - -include $(topsrcdir)/config/config.mk - -ifeq ($(MOZ_WIDGET_TOOLKIT),windows) -BRANDING_FILES := \ - firefox.ico \ - document.ico \ - branding.nsi \ - appname.bmp \ - bgintro.bmp \ - clock.bmp \ - particles.bmp \ - pencil.bmp \ - pencil-rtl.bmp \ - wizHeader.bmp \ - wizHeaderRTL.bmp \ - wizWatermark.bmp \ - newwindow.ico \ - newtab.ico \ - pbmode.ico \ - $(NULL) -endif - -ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) -BRANDING_FILES := \ - background.png \ - firefox.icns \ - disk.icns \ - document.icns \ - dsstore \ - $(NULL) -endif - -ifdef MOZ_WIDGET_GTK -BRANDING_FILES := \ - default16.png \ - default32.png \ - default48.png \ - mozicon128.png \ - $(NULL) -endif - -BRANDING_DEST := $(DIST)/branding -BRANDING_TARGET := export -INSTALL_TARGETS += BRANDING
--- a/browser/branding/aurora/moz.build +++ b/browser/branding/aurora/moz.build @@ -4,12 +4,9 @@ # 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/. DIRS += ['content', 'locales'] DIST_SUBDIR = 'browser' export('DIST_SUBDIR') -JS_PREFERENCE_FILES += [ - 'pref/firefox-branding.js', -] - +include('../branding-common.mozbuild')
new file mode 100644 --- /dev/null +++ b/browser/branding/branding-common.mozbuild @@ -0,0 +1,43 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +JS_PREFERENCE_FILES += [ + 'pref/firefox-branding.js', +] + +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': + BRANDING_FILES += [ + 'appname.bmp', + 'bgintro.bmp', + 'branding.nsi', + 'clock.bmp', + 'document.ico', + 'firefox.ico', + 'newtab.ico', + 'newwindow.ico', + 'particles.bmp', + 'pbmode.ico', + 'pencil-rtl.bmp', + 'pencil.bmp', + 'wizHeader.bmp', + 'wizHeaderRTL.bmp', + 'wizWatermark.bmp', + ] +elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': + BRANDING_FILES += [ + 'background.png', + 'disk.icns', + 'document.icns', + 'dsstore', + 'firefox.icns', + ] +elif CONFIG['MOZ_WIDGET_GTK']: + BRANDING_FILES += [ + 'default16.png', + 'default32.png', + 'default48.png', + 'mozicon128.png', + ]
deleted file mode 100644 --- a/browser/branding/nightly/Makefile.in +++ /dev/null @@ -1,48 +0,0 @@ -# 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/. - -include $(topsrcdir)/config/config.mk - -ifeq ($(MOZ_WIDGET_TOOLKIT),windows) -BRANDING_FILES := \ - firefox.ico \ - document.ico \ - branding.nsi \ - appname.bmp \ - bgintro.bmp \ - clock.bmp \ - particles.bmp \ - pencil.bmp \ - pencil-rtl.bmp \ - wizHeader.bmp \ - wizHeaderRTL.bmp \ - wizWatermark.bmp \ - newwindow.ico \ - newtab.ico \ - pbmode.ico \ - $(NULL) -endif - -ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) -BRANDING_FILES := \ - background.png \ - firefox.icns \ - disk.icns \ - document.icns \ - dsstore \ - $(NULL) -endif - -ifdef MOZ_WIDGET_GTK -BRANDING_FILES := \ - default16.png \ - default32.png \ - default48.png \ - mozicon128.png \ - $(NULL) -endif - -BRANDING_DEST := $(DIST)/branding -BRANDING_TARGET := export -INSTALL_TARGETS += BRANDING
--- a/browser/branding/nightly/moz.build +++ b/browser/branding/nightly/moz.build @@ -4,12 +4,9 @@ # 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/. DIRS += ['content', 'locales'] DIST_SUBDIR = 'browser' export('DIST_SUBDIR') -JS_PREFERENCE_FILES += [ - 'pref/firefox-branding.js', -] - +include('../branding-common.mozbuild')
deleted file mode 100644 --- a/browser/branding/official/Makefile.in +++ /dev/null @@ -1,48 +0,0 @@ -# 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/. - -include $(topsrcdir)/config/config.mk - -ifeq ($(MOZ_WIDGET_TOOLKIT),windows) -BRANDING_FILES := \ - firefox.ico \ - document.ico \ - branding.nsi \ - appname.bmp \ - bgintro.bmp \ - clock.bmp \ - particles.bmp \ - pencil.bmp \ - pencil-rtl.bmp \ - wizHeader.bmp \ - wizHeaderRTL.bmp \ - wizWatermark.bmp \ - newwindow.ico \ - newtab.ico \ - pbmode.ico \ - $(NULL) -endif - -ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) -BRANDING_FILES := \ - background.png \ - firefox.icns \ - disk.icns \ - document.icns \ - dsstore \ - $(NULL) -endif - -ifdef MOZ_WIDGET_GTK -BRANDING_FILES := \ - default16.png \ - default32.png \ - default48.png \ - mozicon128.png \ - $(NULL) -endif - -BRANDING_DEST := $(DIST)/branding -BRANDING_TARGET := export -INSTALL_TARGETS += BRANDING
--- a/browser/branding/official/moz.build +++ b/browser/branding/official/moz.build @@ -4,12 +4,9 @@ # 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/. DIRS += ['content', 'locales'] DIST_SUBDIR = 'browser' export('DIST_SUBDIR') -JS_PREFERENCE_FILES += [ - 'pref/firefox-branding.js', -] - +include('../branding-common.mozbuild')
deleted file mode 100644 --- a/browser/branding/unofficial/Makefile.in +++ /dev/null @@ -1,48 +0,0 @@ -# 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/. - -include $(topsrcdir)/config/config.mk - -ifeq ($(MOZ_WIDGET_TOOLKIT),windows) -BRANDING_FILES := \ - firefox.ico \ - document.ico \ - branding.nsi \ - appname.bmp \ - bgintro.bmp \ - clock.bmp \ - particles.bmp \ - pencil.bmp \ - pencil-rtl.bmp \ - wizHeader.bmp \ - wizHeaderRTL.bmp \ - wizWatermark.bmp \ - newwindow.ico \ - newtab.ico \ - pbmode.ico \ - $(NULL) -endif - -ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) -BRANDING_FILES := \ - background.png \ - firefox.icns \ - disk.icns \ - document.icns \ - dsstore \ - $(NULL) -endif - -ifdef MOZ_WIDGET_GTK -BRANDING_FILES := \ - default16.png \ - default32.png \ - default48.png \ - mozicon128.png \ - $(NULL) -endif - -BRANDING_DEST := $(DIST)/branding -BRANDING_TARGET := export -INSTALL_TARGETS += BRANDING
--- a/browser/branding/unofficial/moz.build +++ b/browser/branding/unofficial/moz.build @@ -4,12 +4,9 @@ # 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/. DIRS += ['content', 'locales'] DIST_SUBDIR = 'browser' export('DIST_SUBDIR') -JS_PREFERENCE_FILES += [ - 'pref/firefox-branding.js', -] - +include('../branding-common.mozbuild')
--- a/browser/locales/en-US/chrome/browser/devtools/netmonitor.properties +++ b/browser/locales/en-US/chrome/browser/devtools/netmonitor.properties @@ -31,18 +31,18 @@ netmonitor.tooltip=Network Monitor # LOCALIZATION NOTE (netmonitor.security.state.secure) # This string is used as an tooltip for request that was performed over secure # channel i.e. the connection was encrypted. netmonitor.security.state.secure=The connection used to fetch this resource was secure. # LOCALIZATION NOTE (netmonitor.security.state.insecure) # This string is used as an tooltip for request that was performed over insecure -# channel i.e. the connection was not encrypted. -netmonitor.security.state.insecure=The connection used to fetch this resource was not encrypted. +# channel i.e. the connection was not https +netmonitor.security.state.insecure=The connection used to fetch this resource was not secure. # LOCALIZATION NOTE (netmonitor.security.state.broken) # This string is used as an tooltip for request that failed due to security # issues. netmonitor.security.state.broken=A security error prevented the resource from being loaded. # LOCALIZATION NOTE (netmonitor.security.state.weak) # This string is used as an tooltip for request that had minor security issues
--- a/build/mobile/remoteautomation.py +++ b/build/mobile/remoteautomation.py @@ -75,16 +75,24 @@ class RemoteAutomation(Automation): env['MOZ_CRASHREPORTER_DISABLE'] = '1' # Crash on non-local network connections by default. # MOZ_DISABLE_NONLOCAL_CONNECTIONS can be set to "0" to temporarily # enable non-local connections for the purposes of local testing. # Don't override the user's choice here. See bug 1049688. env.setdefault('MOZ_DISABLE_NONLOCAL_CONNECTIONS', '1') + # Set WebRTC logging in case it is not set yet. + # On Android, environment variables cannot contain ',' so the + # standard WebRTC setting for NSPR_LOG_MODULES is not available. + # env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5') + env.setdefault('R_LOG_LEVEL', '6') + env.setdefault('R_LOG_DESTINATION', 'stderr') + env.setdefault('R_LOG_VERBOSE', '1') + return env def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath): """ Wait for tests to finish. If maxTime seconds elapse or no output is detected for timeout seconds, kill the process and fail the test. """ # maxTime is used to override the default timeout, we should honor that
--- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -634,43 +634,63 @@ nsContentUtils::InitializeModifierString sShiftText = new nsString(shiftModifier); sMetaText = new nsString(metaModifier); sOSText = new nsString(osModifier); sAltText = new nsString(altModifier); sControlText = new nsString(controlModifier); sModifierSeparator = new nsString(modifierSeparator); } +// Because of SVG/SMIL we have several atoms mapped to the same +// id, but we can rely on ID_TO_EVENT to map id to only one atom. +static bool +ShouldAddEventToStringEventTable(const EventNameMapping& aMapping) +{ + switch(aMapping.mId) { +#define ID_TO_EVENT(name_, id_, type_, struct_) \ + case id_: return nsGkAtoms::on##name_ == aMapping.mAtom; +#include "mozilla/EventNameList.h" +#undef ID_TO_EVENT + default: + break; + } + return false; +} + bool nsContentUtils::InitializeEventTable() { NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!"); NS_ASSERTION(!sStringEventTable, "EventTable already initialized!"); static const EventNameMapping eventArray[] = { #define EVENT(name_, _id, _type, _class) \ { nsGkAtoms::on##name_, _id, _type, _class }, #define WINDOW_ONLY_EVENT EVENT #define NON_IDL_EVENT EVENT #include "mozilla/EventNameList.h" #undef WINDOW_ONLY_EVENT +#undef NON_IDL_EVENT #undef EVENT { nullptr } }; sAtomEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>( ArrayLength(eventArray)); sStringEventTable = new nsDataHashtable<nsStringHashKey, EventNameMapping>( ArrayLength(eventArray)); sUserDefinedEvents = new nsCOMArray<nsIAtom>(64); // Subtract one from the length because of the trailing null for (uint32_t i = 0; i < ArrayLength(eventArray) - 1; ++i) { sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]); - sStringEventTable->Put(Substring(nsDependentAtomString(eventArray[i].mAtom), 2), - eventArray[i]); + if (ShouldAddEventToStringEventTable(eventArray[i])) { + sStringEventTable->Put( + Substring(nsDependentAtomString(eventArray[i].mAtom), 2), + eventArray[i]); + } } return true; } void nsContentUtils::InitializeTouchEventTable() {
--- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -1631,16 +1631,18 @@ ClearAllBoxObjects(nsIContent* aKey, nsP nsIDocument::~nsIDocument() { MOZ_ASSERT(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists), "must not have media query lists left"); if (mNodeInfoManager) { mNodeInfoManager->DropDocumentReference(); } + + UnlinkOriginalDocumentIfStatic(); } nsDocument::~nsDocument() { #ifdef PR_LOGGING if (gDocumentLeakPRLog) PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG, @@ -2088,23 +2090,24 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns // Unlink the mChildren nsAttrAndChildArray. for (int32_t indx = int32_t(tmp->mChildren.ChildCount()) - 1; indx >= 0; --indx) { tmp->mChildren.ChildAt(indx)->UnbindFromTree(); tmp->mChildren.RemoveChildAt(indx); } tmp->mFirstChild = nullptr; + tmp->UnlinkOriginalDocumentIfStatic(); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mXPathEvaluator) tmp->mCachedRootElement = nullptr; // Avoid a dangling pointer NS_IMPL_CYCLE_COLLECTION_UNLINK(mDisplayDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mFirstBaseNodeWithHref) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMImplementation) NS_IMPL_CYCLE_COLLECTION_UNLINK(mImageMaps) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginalDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder) NS_IMPL_CYCLE_COLLECTION_UNLINK(mUndoManager) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentTimeline) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingAnimationTracker) NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner) NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection) NS_IMPL_CYCLE_COLLECTION_UNLINK(mRegistry) NS_IMPL_CYCLE_COLLECTION_UNLINK(mMasterDocument) @@ -3920,16 +3923,21 @@ nsIDocument::TakeFrameRequestCallbacks(F { aCallbacks.AppendElements(mFrameRequestCallbacks); mFrameRequestCallbacks.Clear(); } bool nsIDocument::ShouldThrottleFrameRequests() { + if (mStaticCloneCount > 0) { + // Even if we're not visible, a static clone may be, so run at full speed. + return false; + } + if (!mIsShowing) { // We're not showing (probably in a background tab or the bf cache). return true; } if (!mPresShell) { return false; // Can't do anything smarter. } @@ -10275,16 +10283,19 @@ nsIDocument::CreateStaticClone(nsIDocShe nsCOMPtr<nsIDocument> tmp = do_QueryInterface(clonedNode); if (tmp) { clonedDoc = static_cast<nsDocument*>(tmp.get()); if (IsStaticDocument()) { clonedDoc->mOriginalDocument = mOriginalDocument; } else { clonedDoc->mOriginalDocument = this; } + + clonedDoc->mOriginalDocument->mStaticCloneCount++; + int32_t sheetsCount = GetNumberOfStyleSheets(); for (int32_t i = 0; i < sheetsCount; ++i) { nsRefPtr<CSSStyleSheet> sheet = do_QueryObject(GetStyleSheetAt(i)); if (sheet) { if (sheet->IsApplicable()) { nsRefPtr<CSSStyleSheet> clonedSheet = sheet->Clone(nullptr, nullptr, clonedDoc, nullptr); NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!"); @@ -10312,16 +10323,27 @@ nsIDocument::CreateStaticClone(nsIDocShe } } } } mCreatingStaticClone = false; return clonedDoc.forget(); } +void +nsIDocument::UnlinkOriginalDocumentIfStatic() +{ + if (IsStaticDocument() && mOriginalDocument) { + MOZ_ASSERT(mOriginalDocument->mStaticCloneCount > 0); + mOriginalDocument->mStaticCloneCount--; + mOriginalDocument = nullptr; + } + MOZ_ASSERT(!mOriginalDocument); +} + nsresult nsIDocument::ScheduleFrameRequestCallback(const FrameRequestCallbackHolder& aCallback, int32_t *aHandle) { if (mFrameRequestCallbackCounter == INT32_MAX) { // Can't increment without overflowing; bail out return NS_ERROR_NOT_AVAILABLE; }
--- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -1933,16 +1933,22 @@ public: */ nsIDocument* GetOriginalDocument() { MOZ_ASSERT(!mOriginalDocument || !mOriginalDocument->GetOriginalDocument()); return mOriginalDocument; } /** + * If this document is a static clone, let the original document know that + * we're going away and then release our reference to it. + */ + void UnlinkOriginalDocumentIfStatic(); + + /** * These are called by the parser as it encounters <picture> tags, the end of * said tags, and possible picture <source srcset> sources respectively. These * are used to inform ResolvePreLoadImage() calls. Unset attributes are * expected to be marked void. * * NOTE that the parser does not attempt to track the current picture nesting * level or whether the given <source> tag is within a picture -- it is only * guaranteed to order these calls properly with respect to @@ -2856,16 +2862,19 @@ protected: */ uint32_t mExternalScriptsBeingEvaluated; /** * The current frame request callback handle */ int32_t mFrameRequestCallbackCounter; + // Count of live static clones of this document. + uint32_t mStaticCloneCount; + // Array of nodes that have been blocked to prevent user tracking. // They most likely have had their nsIChannel canceled by the URL // classifier. (Safebrowsing) // // Weak nsINode pointers are used to allow nodes to disappear. nsTArray<nsWeakPtr> mBlockedTrackingNodes; // Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow,
--- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -17,17 +17,19 @@ #include "nsPIDOMWindow.h" #include "nsThreadUtils.h" #include "xpcpublic.h" class nsICycleCollectorListener; class nsScriptNameSpaceManager; namespace JS { -class AutoValueVector; +template <typename T> +class AutoVectorRooter; +typedef AutoVectorRooter<Value> AutoValueVector; } namespace mozilla { template <class> class Maybe; struct CycleCollectorResults; } // The amount of time we wait between a request to GC (due to leaving
--- a/dom/canvas/test/chrome/test_drawWindow_widget_layers.html +++ b/dom/canvas/test/chrome/test_drawWindow_widget_layers.html @@ -14,28 +14,32 @@ var sourceWindow; function openSourceWindow(event) { if (event.target != document) { return; } + // Add a little bottom padding to the window so that we don't capture the + // rounded corners at the bottom, which our GL drawing code on OS X draws + // for regular windows. + // (The reftest framework doesn't have this problem because it doesn't use + // a regular window with a titlebar, so there are no rounded corners.) + const WINDOW_INNER_WIDTH = CANVAS_WIDTH; + const WINDOW_INNER_HEIGHT = CANVAS_HEIGHT + 10; + // Need to open as a toplevel chrome window so that // DRAWWINDOW_USE_WIDGET_LAYERS is honored. sourceWindow = window.open("file_drawWindow_source.html", "", - "chrome,width=200,height=100"); - sourceWindow.addEventListener("load", runTests, false); + `chrome,width=${WINDOW_INNER_WIDTH},height=${WINDOW_INNER_HEIGHT}`); + SimpleTest.waitForFocus(runTests, sourceWindow); } - function runTests(event) { - if (event.target != sourceWindow.document) { - return; - } - + function runTests() { var cxInterfaceWrap = SpecialPowers.wrap(CanvasRenderingContext2D); var flags = cxInterfaceWrap.DRAWWINDOW_USE_WIDGET_LAYERS | cxInterfaceWrap.DRAWWINDOW_DRAW_CARET | cxInterfaceWrap.DRAWWINDOW_DRAW_VIEW; runDrawWindowTests(sourceWindow, flags, true); sourceWindow.close();
--- a/dom/canvas/test/file_drawWindow_common.js +++ b/dom/canvas/test/file_drawWindow_common.js @@ -1,11 +1,12 @@ +const CANVAS_WIDTH = 200; +const CANVAS_HEIGHT = 100; + function runDrawWindowTests(win, drawWindowFlags, transparentBackground) { - const CANVAS_WIDTH = 200; - const CANVAS_HEIGHT = 100; function make_canvas() { var canvas = document.createElement("canvas"); canvas.setAttribute("height", CANVAS_HEIGHT); canvas.setAttribute("width", CANVAS_WIDTH); document.body.appendChild(canvas); return canvas; }
--- a/dom/events/test/mochitest.ini +++ b/dom/events/test/mochitest.ini @@ -181,8 +181,10 @@ support-files = bug989198_embedded.html bug989198_helper.js skip-if = buildapp == 'b2g' || e10s [test_bug1096146.html] support-files = bug1096146_embedded.html [test_offsetxy.html] [test_eventhandler_scoping.html] +[test_bug1013412.html] +skip-if = buildapp == 'b2g' # no wheel events on b2g
new file mode 100644 --- /dev/null +++ b/dom/events/test/test_bug1013412.html @@ -0,0 +1,103 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1013412 +--> +<head> + <title>Test for Bug 1013412</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + #content { + height: 800px; + overflow: scroll; + } + + #scroller { + height: 2000px; + background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px); + } + + #scrollbox { + margin-top: 200px; + width: 500px; + height: 500px; + border-radius: 250px; + box-shadow: inset 0 0 0 60px #555; + background: #777; + } + + #circle { + position: relative; + left: 240px; + top: 20px; + border: 10px solid white; + border-radius: 10px; + width: 0px; + height: 0px; + transform-origin: 10px 230px; + will-change: transform; + } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1013412">Mozilla Bug 1013412</a> +<p id="display"></p> +<div id="content"> + <p>Scrolling the page should be async, but scrolling over the dark circle should not scroll the page and instead rotate the white ball.</p> + <div id="scroller"> + <div id="scrollbox"> + <div id="circle"></div> + </div> + </div> +</div> +<pre id="test"> +<script type="application/javascript;version=1.7"> + +/** Test for Bug 1013412 **/ + +var rotation = 0; +var rotationAdjusted = false; + +var incrementForMode = function (mode) { + switch (mode) { + case WheelEvent.DOM_DELTA_PIXEL: return 1; + case WheelEvent.DOM_DELTA_LINE: return 15; + case WheelEvent.DOM_DELTA_PAGE: return 400; + } + return 0; +}; + +document.getElementById("scrollbox").addEventListener("wheel", function (e) { + rotation += e.deltaY * incrementForMode(e.deltaMode) * 0.2; + document.getElementById("circle").style.transform = "rotate(" + rotation + "deg)"; + rotationAdjusted = true; + e.preventDefault(); +}); + +var iteration = 0; +function runTest() { + var content = document.getElementById('content'); + if (iteration < 300) { // enough iterations that we would scroll to the bottom of 'content' + iteration++; + synthesizeWheel(content, 100, 10, + { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaY: 1.0, lineOrPageDeltaY: 1 }); + setTimeout(runTest, 0); + return; + } + var scrollbox = document.getElementById('scrollbox'); + is(content.scrollTop < content.scrollTopMax, true, "We should not have scrolled to the bottom of the scrollframe"); + is(rotationAdjusted, true, "The rotation should have been adjusted"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTest, window); + +</script> +</pre> + +</body> +</html>
--- a/dom/interfaces/push/nsIPushObserverNotification.idl +++ b/dom/interfaces/push/nsIPushObserverNotification.idl @@ -4,17 +4,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" /** * A push message received by an `nsIPushNotificationService`, used as the * subject of a `push-notification` observer notification. */ -[scriptable, uuid(66a87970-6dc9-46e0-ac61-adb4a13791de)] +[scriptable, uuid(56f57607-28b6-44b0-aa56-3d4d3c88be15)] interface nsIPushObserverNotification : nsISupports { /* The URL that receives push messages from an application server. */ attribute string pushEndpoint; /** * The notification version sent by the application server. This is a * monotonically increasing number. @@ -22,9 +22,19 @@ interface nsIPushObserverNotification : attribute long long version; /** * The notification payload. Delivery is not guaranteed; if the browser is * offline when the application server sends the push message, the payload * may be discarded. */ attribute string data; + + /** + * How many times has a push event occured against this pushEndpoint + */ + attribute long long pushCount; + + /** + * The last time a push occured against this this pushEndpoint + */ + attribute long long lastPush; };
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -801,22 +801,25 @@ ContentChild::InitXPCOM() return; } mConsoleListener = new ConsoleListener(this); if (NS_FAILED(svc->RegisterListener(mConsoleListener))) NS_WARNING("Couldn't register console listener for child process"); bool isOffline, isLangRTL; + bool isConnected; ClipboardCapabilities clipboardCaps; DomainPolicyClone domainPolicy; - SendGetXPCOMProcessAttributes(&isOffline, &isLangRTL, &mAvailableDictionaries, + SendGetXPCOMProcessAttributes(&isOffline, &isConnected, + &isLangRTL, &mAvailableDictionaries, &clipboardCaps, &domainPolicy); RecvSetOffline(isOffline); + RecvSetConnectivity(isConnected); RecvBidiKeyboardNotify(isLangRTL); // Create the CPOW manager as soon as possible. SendPJavaScriptConstructor(); if (domainPolicy.active()) { nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); MOZ_ASSERT(ssm); @@ -1878,16 +1881,28 @@ ContentChild::RecvSetOffline(const bool& nsCOMPtr<nsIIOService> io (do_GetIOService()); NS_ASSERTION(io, "IO Service can not be null"); io->SetOffline(offline); return true; } +bool +ContentChild::RecvSetConnectivity(const bool& connectivity) +{ + nsCOMPtr<nsIIOService> io(do_GetIOService()); + nsCOMPtr<nsIIOServiceInternal> ioInternal(do_QueryInterface(io)); + NS_ASSERTION(ioInternal, "IO Service can not be null"); + + ioInternal->SetConnectivity(connectivity); + + return true; +} + void ContentChild::ActorDestroy(ActorDestroyReason why) { if (AbnormalShutdown == why) { NS_WARNING("shutting down early because of crash!"); QuickExit(); }
--- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -289,16 +289,17 @@ public: virtual bool RecvRegisterChromeItem(const ChromeRegistryItem& item) override; virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild() override; virtual bool DeallocPJavaScriptChild(mozilla::jsipc::PJavaScriptChild*) override; virtual PRemoteSpellcheckEngineChild* AllocPRemoteSpellcheckEngineChild() override; virtual bool DeallocPRemoteSpellcheckEngineChild(PRemoteSpellcheckEngineChild*) override; virtual bool RecvSetOffline(const bool& offline) override; + virtual bool RecvSetConnectivity(const bool& connectivity) override; virtual bool RecvSpeakerManagerNotify() override; virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL) override; virtual bool RecvUpdateServiceWorkerRegistrations() override; virtual bool RecvNotifyVisited(const URIParams& aURI) override;
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -400,16 +400,17 @@ namespace mozilla { namespace dom { #ifdef MOZ_NUWA_PROCESS int32_t ContentParent::sNuwaPid = 0; bool ContentParent::sNuwaReady = false; #endif #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline" +#define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity" class MemoryReportRequestParent : public PMemoryReportRequestParent { public: explicit MemoryReportRequestParent(uint32_t aGeneration); virtual ~MemoryReportRequestParent(); @@ -638,16 +639,17 @@ static uint64_t gContentChildID = 1; // actually for any app in particular. Use a magic manifest URL. // Can't be a static constant. #define MAGIC_PREALLOCATED_APP_MANIFEST_URL NS_LITERAL_STRING("{{template}}") static const char* sObserverTopics[] = { "xpcom-shutdown", "profile-before-change", NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC, + NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC, "child-memory-reporter-request", "memory-pressure", "child-gc-request", "child-cc-request", "child-mmu-request", "last-pb-context-exited", "file-watcher-update", #ifdef MOZ_WIDGET_GONK @@ -2930,23 +2932,26 @@ ContentParent::RecvAddNewProcess(const u sNuwaPrefUpdates->Length() : 0; // Resend pref updates to the forked child. for (size_t i = 0; i < numNuwaPrefUpdates; i++) { mozilla::unused << content->SendPreferenceUpdate(sNuwaPrefUpdates->ElementAt(i)); } // Update offline settings. bool isOffline, isLangRTL; + bool isConnected; InfallibleTArray<nsString> unusedDictionaries; ClipboardCapabilities clipboardCaps; DomainPolicyClone domainPolicy; - RecvGetXPCOMProcessAttributes(&isOffline, &isLangRTL, &unusedDictionaries, + RecvGetXPCOMProcessAttributes(&isOffline, &isConnected, + &isLangRTL, &unusedDictionaries, &clipboardCaps, &domainPolicy); mozilla::unused << content->SendSetOffline(isOffline); + mozilla::unused << content->SendSetConnectivity(isConnected); MOZ_ASSERT(!clipboardCaps.supportsSelectionClipboard() && !clipboardCaps.supportsFindClipboard(), "Unexpected values"); PreallocatedProcessManager::PublishSpareProcess(content); return true; #else NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!"); @@ -3029,16 +3034,27 @@ ContentParent::Observe(nsISupports* aSub #endif if (!SendSetOffline(!strcmp(offline, "true") ? true : false)) { return NS_ERROR_NOT_AVAILABLE; } #ifdef MOZ_NUWA_PROCESS } #endif } + else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC)) { +#ifdef MOZ_NUWA_PROCESS + if (!(IsNuwaReady() && IsNuwaProcess())) { +#endif + if (!SendSetConnectivity(NS_LITERAL_STRING("true").Equals(aData))) { + return NS_ERROR_NOT_AVAILABLE; + } +#ifdef MOZ_NUWA_PROCESS + } +#endif + } // listening for alert notifications else if (!strcmp(aTopic, "alertfinished") || !strcmp(aTopic, "alertclickcallback") || !strcmp(aTopic, "alertshow") ) { if (!SendNotifyAlertsObserver(nsDependentCString(aTopic), nsDependentString(aData))) return NS_ERROR_NOT_AVAILABLE; } @@ -3277,26 +3293,30 @@ ContentParent::RecvGetProcessAttributes( *aIsForApp = IsForApp(); *aIsForBrowser = mIsForBrowser; return true; } bool ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline, + bool* aIsConnected, bool* aIsLangRTL, InfallibleTArray<nsString>* dictionaries, ClipboardCapabilities* clipboardCaps, DomainPolicyClone* domainPolicy) { nsCOMPtr<nsIIOService> io(do_GetIOService()); MOZ_ASSERT(io, "No IO service?"); DebugOnly<nsresult> rv = io->GetOffline(aIsOffline); MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting offline?"); + rv = io->GetConnectivity(aIsConnected); + MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting connectivity?"); + nsIBidiKeyboard* bidi = nsContentUtils::GetBidiKeyboard(); *aIsLangRTL = false; if (bidi) { bidi->IsLangRTL(aIsLangRTL); } nsCOMPtr<nsISpellChecker> spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID));
--- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -541,16 +541,17 @@ private: PProcessHangMonitorParent* AllocPProcessHangMonitorParent(Transport* aTransport, ProcessId aOtherProcess) override; virtual bool RecvGetProcessAttributes(ContentParentId* aCpId, bool* aIsForApp, bool* aIsForBrowser) override; virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline, + bool* aIsConnected, bool* aIsLangRTL, InfallibleTArray<nsString>* dictionaries, ClipboardCapabilities* clipboardCaps, DomainPolicyClone* domainPolicy) override; virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override; virtual bool DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*) override;
--- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -520,16 +520,17 @@ child: PTestShell(); RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources, OverrideMapping[] overrides, nsCString locale, bool reset); RegisterChromeItem(ChromeRegistryItem item); async SetOffline(bool offline); + async SetConnectivity(bool connectivity); async NotifyVisited(URIParams uri); async SystemMemoryAvailable(uint64_t getterId, uint32_t memoryAvailable); PreferenceUpdate(PrefSetting pref); NotifyAlertsObserver(nsCString topic, nsString data); @@ -664,17 +665,17 @@ parent: * |isForBrowser|, we're loading <browser>. When |!isForApp && * !isForBrowser|, we're probably loading <xul:browser remote>. * * Keep the return values in sync with PBrowser()! */ sync GetProcessAttributes() returns (ContentParentId cpId, bool isForApp, bool isForBrowser); sync GetXPCOMProcessAttributes() - returns (bool isOffline, bool isLangRTL, nsString[] dictionaries, + returns (bool isOffline, bool isConnected, bool isLangRTL, nsString[] dictionaries, ClipboardCapabilities clipboardCaps, DomainPolicyClone domainPolicy); sync CreateChildProcess(IPCTabContext context, ProcessPriority priority, TabId openerTabId) returns (ContentParentId cpId, bool isForApp, bool isForBrowser, TabId tabId); sync BridgeToChildProcess(ContentParentId cpId);
--- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -477,42 +477,42 @@ void Promise::MaybeReject(const nsRefPtr<MediaStreamError>& aArg) { MaybeSomething(aArg, &Promise::MaybeReject); } bool Promise::PerformMicroTaskCheckpoint() { CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get(); - nsTArray<nsCOMPtr<nsIRunnable>>& microtaskQueue = + std::queue<nsCOMPtr<nsIRunnable>>& microtaskQueue = runtime->GetPromiseMicroTaskQueue(); - if (microtaskQueue.IsEmpty()) { + if (microtaskQueue.empty()) { return false; } Maybe<AutoSafeJSContext> cx; if (NS_IsMainThread()) { cx.emplace(); } do { - nsCOMPtr<nsIRunnable> runnable = microtaskQueue.ElementAt(0); + nsCOMPtr<nsIRunnable> runnable = microtaskQueue.front(); MOZ_ASSERT(runnable); // This function can re-enter, so we remove the element before calling. - microtaskQueue.RemoveElementAt(0); + microtaskQueue.pop(); nsresult rv = runnable->Run(); if (NS_WARN_IF(NS_FAILED(rv))) { return false; } if (cx.isSome()) { JS_CheckForInterrupt(cx.ref()); } - } while (!microtaskQueue.IsEmpty()); + } while (!microtaskQueue.empty()); return true; } /* static */ bool Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp) { JS::CallArgs args = CallArgsFromVp(aArgc, aVp); @@ -1163,20 +1163,20 @@ private: }; /* static */ void Promise::DispatchToMicroTask(nsIRunnable* aRunnable) { MOZ_ASSERT(aRunnable); CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get(); - nsTArray<nsCOMPtr<nsIRunnable>>& microtaskQueue = + std::queue<nsCOMPtr<nsIRunnable>>& microtaskQueue = runtime->GetPromiseMicroTaskQueue(); - microtaskQueue.AppendElement(aRunnable); + microtaskQueue.push(aRunnable); } #if defined(DOM_PROMISE_DEPRECATED_REPORTING) void Promise::MaybeReportRejected() { if (mState != Rejected || mHadRejectCallback || mResult.isUndefined()) { return;
--- a/dom/push/Push.js +++ b/dom/push/Push.js @@ -257,17 +257,17 @@ Push.prototype = { this._cpmm.sendAsyncMessage("Push:Register", { pageURL: this._pageURL.spec, scope: this._scope, requestID: resolverId }); }.bind(this), function() { - reject("denied"); + reject("PermissionDeniedError"); } ); }.bind(this)); return p; }, getSubscription: function() { debug("getSubscription()" + this._scope); @@ -281,17 +281,17 @@ Push.prototype = { this._cpmm.sendAsyncMessage("Push:Registration", { pageURL: this._pageURL.spec, scope: this._scope, requestID: resolverId }); }.bind(this), function() { - reject("denied"); + reject("PermissionDeniedError"); } ); }.bind(this)); return p; }, hasPermission: function() { debug("getSubscription()" + this._scope);
--- a/dom/push/PushService.jsm +++ b/dom/push/PushService.jsm @@ -42,19 +42,19 @@ XPCOMUtils.defineLazyServiceGetter(this, var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); this.EXPORTED_SYMBOLS = ["PushService"]; const prefs = new Preferences("dom.push."); // Set debug first so that all debugging actually works. gDebuggingEnabled = prefs.get("debug"); -const kPUSHDB_DB_NAME = "push"; +const kPUSHDB_DB_NAME = "pushapi"; const kPUSHDB_DB_VERSION = 1; // Change this if the IndexedDB format changes -const kPUSHDB_STORE_NAME = "push"; +const kPUSHDB_STORE_NAME = "pushapi"; const kUDP_WAKEUP_WS_STATUS_CODE = 4774; // WebSocket Close status code sent // by server to signal that it can // wake client up using UDP. const kCHILD_PROCESS_MESSAGES = ["Push:Register", "Push:Unregister", "Push:Registration"]; @@ -1329,16 +1329,18 @@ this.PushService = { debug("No record for channel ID " + aChannelID); return; } if (aPushRecord.version == null || aPushRecord.version < aLatestVersion) { debug("Version changed, notifying app and updating DB"); aPushRecord.version = aLatestVersion; + aPushRecord.pushCount = aPushRecord.pushCount + 1; + aPushRecord.lastPush = new Date().getTime(); this._notifyApp(aPushRecord); this._updatePushRecord(aPushRecord) .then( null, function(e) { debug("Error updating push record"); } ); @@ -1393,16 +1395,19 @@ this.PushService = { debug("notifyApp() " + aPushRecord.scope); let scopeURI = Services.io.newURI(aPushRecord.scope, null, null); // Notify XPCOM observers. let notification = Cc["@mozilla.org/push/ObserverNotification;1"] .createInstance(Ci.nsIPushObserverNotification); notification.pushEndpoint = aPushRecord.pushEndpoint; notification.version = aPushRecord.version; notification.data = ""; + notification.lastPush = aPushRecord.lastPush; + notification.pushCount = aPushRecord.pushCount; + Services.obs.notifyObservers( notification, "push-notification", aPushRecord.scope ); // If permission has been revoked, trash the message. if(Services.perms.testExactPermission(scopeURI, "push") != Ci.nsIPermissionManager.ALLOW_ACTION) { @@ -1533,16 +1538,18 @@ this.PushService = { throw "Invalid pushEndpoint " + data.pushEndpoint; } let record = { channelID: data.channelID, pushEndpoint: data.pushEndpoint, pageURL: aPageRecord.pageURL, scope: aPageRecord.scope, + pushCount: 0, + lastPush: 0, version: null }; debug("scope in _onRegisterSuccess: " + aPageRecord.scope) return this._updatePushRecord(record) .then( function() { @@ -1661,17 +1668,19 @@ this.PushService = { return; } this._db.getByScope(aPageRecord.scope, pushRecord => { let registration = null; if (pushRecord) { registration = { pushEndpoint: pushRecord.pushEndpoint, - version: pushRecord.version + version: pushRecord.version, + lastPush: pushRecord.lastPush, + pushCount: pushRecord.pushCount }; } resolve(registration); }, () => reject("Database error") ); }); },
--- a/dom/push/test/xpcshell/test_notification_incomplete.js +++ b/dom/push/test/xpcshell/test_notification_incomplete.js @@ -100,10 +100,24 @@ add_task(function* test_notification_inc }); yield waitForPromise(notificationDefer.promise, DEFAULT_TIMEOUT, 'Timed out waiting for incomplete notifications'); let storeRecords = yield promiseDB.getAllChannelIDs(); storeRecords.sort(({pushEndpoint: a}, {pushEndpoint: b}) => compareAscending(a, b)); - deepEqual(records, storeRecords, 'Should not update malformed records'); + recordsAreEqual(records, storeRecords); }); + +function recordIsEqual(a, b) { + strictEqual(a.channelID, b.channelID, 'Wrong channel ID in record'); + strictEqual(a.pushEndpoint, b.pushEndpoint, 'Wrong push endpoint in record'); + strictEqual(a.scope, b.scope, 'Wrong scope in record'); + strictEqual(a.version, b.version, 'Wrong version in record'); +} + +function recordsAreEqual(a, b) { + equal(a.length, b.length, 'Mismatched record count'); + for (let i = 0; i < a.length; i++) { + recordIsEqual(a[i], b[i]); + } +}
--- a/dom/push/test/xpcshell/test_registration_success.js +++ b/dom/push/test/xpcshell/test_registration_success.js @@ -55,13 +55,15 @@ add_task(function* test_registration_suc })); } }); } }); let registration = yield PushNotificationService.registration( 'https://example.net/a'); - deepEqual(registration, { - pushEndpoint: 'https://example.com/update/same-manifest/1', - version: 5 - }, 'Should include registrations for all pages with this manifest'); + equal( + registration.pushEndpoint, + 'https://example.com/update/same-manifest/1', + 'Wrong push endpoint for scope' + ); + equal(registration.version, 5, 'Wrong version for scope'); });
--- a/dom/smil/test/test_smilTimeEvents.xhtml +++ b/dom/smil/test/test_smilTimeEvents.xhtml @@ -282,13 +282,20 @@ window.addEventListener("load", continue // Register event handlers *in addition* to the handlers already added via the // "onbegin", "onend", "onrepeat" attributes on the <animate> and <circle> // elements. This is to test that both types of registration work. gAnim.addEventListener("beginEvent", handleOnBegin, false); gAnim.addEventListener("repeatEvent", handleOnRepeat, false); gAnim.addEventListener("endEvent", handleOnEnd, false); gCircle.addEventListener("beginEvent", parentHandler, false); + +var expectedEvents = + ["begin", "beginEvent", "repeat", "repeatEvent", "end", "endEvent", "SVGZoom", "zoom"]; + +for (var i = 0; i < expectedEvents.length; ++i) { + is((new Event(expectedEvents[i])).type, expectedEvents[i], "Unexpected event type!"); +} ]]> </script> </pre> </body> </html>
--- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -918,17 +918,17 @@ var interfaceNamesInGlobalScope = {name: "ServiceWorkerContainer", nightly: true, b2g: false}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "ServiceWorkerRegistration", nightly: true, b2g: false}, // IMPORTANT: Do not change this list without review from a DOM peer! "SettingsLock", // IMPORTANT: Do not change this list without review from a DOM peer! "SettingsManager", // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "ShadowRoot", pref: "dom.webcomponents.enabled"}, + "ShadowRoot", // Bogus, but the test harness forces it on. See bug 1159768. // IMPORTANT: Do not change this list without review from a DOM peer! "SharedWorker", // IMPORTANT: Do not change this list without review from a DOM peer! "SimpleGestureEvent", // IMPORTANT: Do not change this list without review from a DOM peer! {name: "SimpleTest", xbl: false}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "SourceBuffer", android: false, linux: false, release: false}, @@ -1376,17 +1376,16 @@ var interfaceNamesInGlobalScope = {name: "XULTemplateBuilder", xbl: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "XULTreeBuilder", xbl: true}, // IMPORTANT: Do not change this list without review from a DOM peer! ]; // IMPORTANT: Do not change the list above without review from a DOM peer! function createInterfaceMap(isXBLScope) { - var prefs = SpecialPowers.Services.prefs; var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version; var isNightly = version.endsWith("a1"); var isRelease = !version.includes("a"); var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent); var isB2G = !isDesktop && !navigator.userAgent.includes("Android"); var isMac = /Mac OS/.test(navigator.oscpu); var isWindows = /Windows/.test(navigator.oscpu); var isLinux = /Linux/.test(navigator.oscpu); @@ -1401,31 +1400,33 @@ function createInterfaceMap(isXBLScope) var interfaceMap = {}; function addInterfaces(interfaces) { for (var entry of interfaces) { if (typeof(entry) === "string") { interfaceMap[entry] = true; - } else if ((entry.nightly === !isNightly) || - (entry.xbl === !isXBLScope) || - (entry.desktop === !isDesktop) || - (entry.b2g === !isB2G) || - (entry.windows === !isWindows) || - (entry.mac === !isMac) || - (entry.linux === !isLinux) || - (entry.android === !isAndroid) || - (entry.release === !isRelease) || - (entry.pref && !prefs.getBoolPref(entry.pref)) || - (entry.permission && !hasPermission(entry.permission)) || - entry.disabled) { - interfaceMap[entry.name] = false; } else { - interfaceMap[entry.name] = true; + ok(!("pref" in entry), "Bogus pref annotation for " + entry.name); + if ((entry.nightly === !isNightly) || + (entry.xbl === !isXBLScope) || + (entry.desktop === !isDesktop) || + (entry.b2g === !isB2G) || + (entry.windows === !isWindows) || + (entry.mac === !isMac) || + (entry.linux === !isLinux) || + (entry.android === !isAndroid) || + (entry.release === !isRelease) || + (entry.permission && !hasPermission(entry.permission)) || + entry.disabled) { + interfaceMap[entry.name] = false; + } else { + interfaceMap[entry.name] = true; + } } } } addInterfaces(ecmaGlobals); addInterfaces(interfaceNamesInGlobalScope); if (isXBLScope) { // We expose QueryInterface to XBL scopes. It's not an interface but we
--- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -576,16 +576,17 @@ public: if (mJobType == REGISTER_JOB) { mRegistration = swm->GetRegistration(mScope); if (mRegistration) { nsRefPtr<ServiceWorkerInfo> newest = mRegistration->Newest(); if (newest && mScriptSpec.Equals(newest->ScriptSpec()) && mScriptSpec.Equals(mRegistration->mScriptSpec)) { mRegistration->mPendingUninstall = false; + swm->StoreRegistration(mPrincipal, mRegistration); Succeed(); Done(NS_OK); return; } } else { mRegistration = swm->CreateNewRegistration(mScope, mPrincipal); }
--- a/dom/workers/test/serviceworkers/serviceworker_wrapper.js +++ b/dom/workers/test/serviceworkers/serviceworker_wrapper.js @@ -26,31 +26,16 @@ function workerTestArrayEquals(a, b) { } return true; } function workerTestDone() { client.postMessage({ type: 'finish' }); } -function workerTestGetPrefs(prefs, cb) { - addEventListener('message', function workerTestGetPrefsCB(e) { - if (e.data.type != 'returnPrefs' || - !workerTestArrayEquals(prefs, e.data.prefs)) { - return; - } - removeEventListener('message', workerTestGetPrefsCB); - cb(e.data.result); - }); - client.postMessage({ - type: 'getPrefs', - prefs: prefs - }); -} - function workerTestGetPermissions(permissions, cb) { addEventListener('message', function workerTestGetPermissionsCB(e) { if (e.data.type != 'returnPermissions' || !workerTestArrayEquals(permissions, e.data.permissions)) { return; } removeEventListener('message', workerTestGetPermissionsCB); cb(e.data.result);
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js +++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js @@ -187,51 +187,53 @@ var interfaceNamesInGlobalScope = // IMPORTANT: Do not change this list without review from a DOM peer! "WorkerLocation", // IMPORTANT: Do not change this list without review from a DOM peer! "WorkerNavigator", // IMPORTANT: Do not change this list without review from a DOM peer! ]; // IMPORTANT: Do not change the list above without review from a DOM peer! -function createInterfaceMap(prefMap, permissionMap, version, userAgent, isB2G) { +function createInterfaceMap(permissionMap, version, userAgent, isB2G) { var isNightly = version.endsWith("a1"); var isRelease = !version.includes("a"); var isDesktop = !/Mobile|Tablet/.test(userAgent); var isAndroid = !!navigator.userAgent.includes("Android"); var interfaceMap = {}; function addInterfaces(interfaces) { for (var entry of interfaces) { if (typeof(entry) === "string") { interfaceMap[entry] = true; - } else if ((entry.nightly === !isNightly) || - (entry.desktop === !isDesktop) || - (entry.android === !isAndroid) || - (entry.b2g === !isB2G) || - (entry.release === !isRelease) || - (entry.pref && !prefMap[entry.pref]) || - (entry.permission && !permissionMap[entry.permission])) { - interfaceMap[entry.name] = false; } else { - interfaceMap[entry.name] = true; + ok(!("pref" in entry), "Bogus pref annotation for " + entry.name); + if ((entry.nightly === !isNightly) || + (entry.desktop === !isDesktop) || + (entry.android === !isAndroid) || + (entry.b2g === !isB2G) || + (entry.release === !isRelease) || + (entry.permission && !permissionMap[entry.permission])) { + interfaceMap[entry.name] = false; + } else { + interfaceMap[entry.name] = true; + } } } } addInterfaces(ecmaGlobals); addInterfaces(interfaceNamesInGlobalScope); return interfaceMap; } -function runTest(prefMap, permissionMap, version, userAgent, isB2G) { - var interfaceMap = createInterfaceMap(prefMap, permissionMap, version, userAgent, isB2G); +function runTest(permissionMap, version, userAgent, isB2G) { + var interfaceMap = createInterfaceMap(permissionMap, version, userAgent, isB2G); for (var name of Object.getOwnPropertyNames(self)) { // An interface name should start with an upper case character. if (!/^[A-Z]/.test(name)) { continue; } ok(interfaceMap[name], "If this is failing: DANGER, are you sure you want to expose the new interface " + name + " to all webpages as a property on the service worker? Do not make a change to this file without a " + @@ -244,45 +246,31 @@ function runTest(prefMap, permissionMap, if (!interfaceMap[name]) { delete interfaceMap[name]; } } is(Object.keys(interfaceMap).length, 0, "The following interface(s) are not enumerated: " + Object.keys(interfaceMap).join(", ")); } -function appendPrefs(prefs, interfaces) { - for (var entry of interfaces) { - if (entry.pref !== undefined && prefs.indexOf(entry.pref) === -1) { - prefs.push(entry.pref); - } - } -} - -var prefs = []; -appendPrefs(prefs, ecmaGlobals); -appendPrefs(prefs, interfaceNamesInGlobalScope); - function appendPermissions(permissions, interfaces) { for (var entry of interfaces) { if (entry.permission !== undefined && permissions.indexOf(entry.permission) === -1) { permissions.push(entry.permission); } } } var permissions = []; appendPermissions(permissions, ecmaGlobals); appendPermissions(permissions, interfaceNamesInGlobalScope); -workerTestGetPrefs(prefs, function(prefMap) { - workerTestGetPermissions(permissions, function(permissionMap) { - workerTestGetVersion(function(version) { - workerTestGetUserAgent(function(userAgent) { - workerTestGetIsB2G(function(isB2G) { - runTest(prefMap, permissionMap, version, userAgent, isB2G); - workerTestDone(); - }); +workerTestGetPermissions(permissions, function(permissionMap) { + workerTestGetVersion(function(version) { + workerTestGetUserAgent(function(userAgent) { + workerTestGetIsB2G(function(isB2G) { + runTest(permissionMap, version, userAgent, isB2G); + workerTestDone(); }); }); }); });
--- a/dom/workers/test/test_worker_interfaces.js +++ b/dom/workers/test/test_worker_interfaces.js @@ -175,52 +175,54 @@ var interfaceNamesInGlobalScope = // IMPORTANT: Do not change this list without review from a DOM peer! "WorkerLocation", // IMPORTANT: Do not change this list without review from a DOM peer! "WorkerNavigator", // IMPORTANT: Do not change this list without review from a DOM peer! ]; // IMPORTANT: Do not change the list above without review from a DOM peer! -function createInterfaceMap(prefMap, permissionMap, version, userAgent, isB2G) { +function createInterfaceMap(permissionMap, version, userAgent, isB2G) { var isNightly = version.endsWith("a1"); var isRelease = !version.includes("a"); var isDesktop = !/Mobile|Tablet/.test(userAgent); var isAndroid = !!navigator.userAgent.includes("Android"); var interfaceMap = {}; function addInterfaces(interfaces) { for (var entry of interfaces) { if (typeof(entry) === "string") { interfaceMap[entry] = true; - } else if ((entry.nightly === !isNightly) || - (entry.desktop === !isDesktop) || - (entry.android === !isAndroid) || - (entry.b2g === !isB2G) || - (entry.release === !isRelease) || - (entry.pref && !prefMap[entry.pref]) || - (entry.permission && !permissionMap[entry.permission]) || - entry.disabled) { - interfaceMap[entry.name] = false; } else { - interfaceMap[entry.name] = true; + ok(!("pref" in entry), "Bogus pref annotation for " + entry.name); + if ((entry.nightly === !isNightly) || + (entry.desktop === !isDesktop) || + (entry.android === !isAndroid) || + (entry.b2g === !isB2G) || + (entry.release === !isRelease) || + (entry.permission && !permissionMap[entry.permission]) || + entry.disabled) { + interfaceMap[entry.name] = false; + } else { + interfaceMap[entry.name] = true; + } } } } addInterfaces(ecmaGlobals); addInterfaces(interfaceNamesInGlobalScope); return interfaceMap; } -function runTest(prefMap, permissionMap, version, userAgent, isB2G) { - var interfaceMap = createInterfaceMap(prefMap, permissionMap, version, userAgent, isB2G); +function runTest(permissionMap, version, userAgent, isB2G) { + var interfaceMap = createInterfaceMap(permissionMap, version, userAgent, isB2G); for (var name of Object.getOwnPropertyNames(self)) { // An interface name should start with an upper case character. if (!/^[A-Z]/.test(name)) { continue; } ok(interfaceMap[name], "If this is failing: DANGER, are you sure you want to expose the new interface " + name + " to all webpages as a property on the worker? Do not make a change to this file without a " + @@ -233,45 +235,31 @@ function runTest(prefMap, permissionMap, if (!interfaceMap[name]) { delete interfaceMap[name]; } } is(Object.keys(interfaceMap).length, 0, "The following interface(s) are not enumerated: " + Object.keys(interfaceMap).join(", ")); } -function appendPrefs(prefs, interfaces) { - for (var entry of interfaces) { - if (entry.pref !== undefined && prefs.indexOf(entry.pref) === -1) { - prefs.push(entry.pref); - } - } -} - -var prefs = []; -appendPrefs(prefs, ecmaGlobals); -appendPrefs(prefs, interfaceNamesInGlobalScope); - function appendPermissions(permissions, interfaces) { for (var entry of interfaces) { if (entry.permission !== undefined && permissions.indexOf(entry.permission) === -1) { permissions.push(entry.permission); } } } var permissions = []; appendPermissions(permissions, ecmaGlobals); appendPermissions(permissions, interfaceNamesInGlobalScope); -workerTestGetPrefs(prefs, function(prefMap) { - workerTestGetPermissions(permissions, function(permissionMap) { - workerTestGetVersion(function(version) { - workerTestGetUserAgent(function(userAgent) { - workerTestGetIsB2G(function(isB2G) { - runTest(prefMap, permissionMap, version, userAgent, isB2G); - workerTestDone(); - }); +workerTestGetPermissions(permissions, function(permissionMap) { + workerTestGetVersion(function(version) { + workerTestGetUserAgent(function(userAgent) { + workerTestGetIsB2G(function(isB2G) { + runTest(permissionMap, version, userAgent, isB2G); + workerTestDone(); }); }); }); });
--- a/dom/workers/test/worker_driver.js +++ b/dom/workers/test/worker_driver.js @@ -14,17 +14,16 @@ // // ok() - like the SimpleTest assert // is() - like the SimpleTest assert // workerTestDone() - like SimpleTest.finish() indicating the test is complete // // There are also some functions for requesting information that requires // SpecialPowers or other main-thread-only resources: // -// workerTestGetPrefs() - request an array of prefs value from the main thread // workerTestGetPermissions() - request an array permissions from the MT // workerTestGetVersion() - request the current version string from the MT // workerTestGetUserAgent() - request the user agent string from the MT // workerTestGetOSCPU() - request the navigator.oscpu string from the MT // // For an example see test_worker_interfaces.html and test_worker_interfaces.js. function workerTestExec(script) { @@ -32,27 +31,16 @@ function workerTestExec(script) { var worker = new Worker('worker_wrapper.js'); worker.onmessage = function(event) { if (event.data.type == 'finish') { SimpleTest.finish(); } else if (event.data.type == 'status') { ok(event.data.status, event.data.msg); - } else if (event.data.type == 'getPrefs') { - var result = {}; - event.data.prefs.forEach(function(pref) { - result[pref] = SpecialPowers.Services.prefs.getBoolPref(pref); - }); - worker.postMessage({ - type: 'returnPrefs', - prefs: event.data.prefs, - result: result - }); - } else if (event.data.type == 'getPermissions') { var result = {}; event.data.permissions.forEach(function(permission) { result[permission] = SpecialPowers.hasPermission(permission, window.document); }); worker.postMessage({ type: 'returnPermissions', permissions: event.data.permissions,
--- a/dom/workers/test/worker_wrapper.js +++ b/dom/workers/test/worker_wrapper.js @@ -25,31 +25,16 @@ function workerTestArrayEquals(a, b) { } return true; } function workerTestDone() { postMessage({ type: 'finish' }); } -function workerTestGetPrefs(prefs, cb) { - addEventListener('message', function workerTestGetPrefsCB(e) { - if (e.data.type != 'returnPrefs' || - !workerTestArrayEquals(prefs, e.data.prefs)) { - return; - } - removeEventListener('message', workerTestGetPrefsCB); - cb(e.data.result); - }); - postMessage({ - type: 'getPrefs', - prefs: prefs - }); -} - function workerTestGetPermissions(permissions, cb) { addEventListener('message', function workerTestGetPermissionsCB(e) { if (e.data.type != 'returnPermissions' || !workerTestArrayEquals(permissions, e.data.permissions)) { return; } removeEventListener('message', workerTestGetPermissionsCB); cb(e.data.result);
--- a/editor/libeditor/nsHTMLEditRules.cpp +++ b/editor/libeditor/nsHTMLEditRules.cpp @@ -483,16 +483,18 @@ nsHTMLEditRules::AfterEditInner(EditActi (action == EditAction::htmlPaste || (action == EditAction::loadHTML))) { res = AdjustWhitespace(selection); NS_ENSURE_SUCCESS(res, res); // also do this for original selection endpoints. NS_ENSURE_STATE(mHTMLEditor); + NS_ENSURE_STATE(mRangeItem->startNode); + NS_ENSURE_STATE(mRangeItem->endNode); nsWSRunObject(mHTMLEditor, mRangeItem->startNode, mRangeItem->startOffset).AdjustWhitespace(); // we only need to handle old selection endpoint if it was different from start if (mRangeItem->startNode != mRangeItem->endNode || mRangeItem->startOffset != mRangeItem->endOffset) { NS_ENSURE_STATE(mHTMLEditor); nsWSRunObject(mHTMLEditor, mRangeItem->endNode, mRangeItem->endOffset).AdjustWhitespace();
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -642,18 +642,23 @@ private: }; class OverscrollAnimation: public AsyncPanZoomAnimation { public: explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ParentLayerPoint& aVelocity) : AsyncPanZoomAnimation(TimeDuration::Forever()) , mApzc(aApzc) { - mApzc.mX.SetVelocity(aVelocity.x); - mApzc.mY.SetVelocity(aVelocity.y); + mApzc.mX.StartOverscrollAnimation(aVelocity.x); + mApzc.mY.StartOverscrollAnimation(aVelocity.y); + } + ~OverscrollAnimation() + { + mApzc.mX.EndOverscrollAnimation(); + mApzc.mY.EndOverscrollAnimation(); } virtual bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) override { // Can't inline these variables due to short-circuit evaluation. bool continueX = mApzc.mX.SampleOverscrollAnimation(aDelta); bool continueY = mApzc.mY.SampleOverscrollAnimation(aDelta);
--- a/gfx/layers/apz/src/Axis.cpp +++ b/gfx/layers/apz/src/Axis.cpp @@ -135,17 +135,17 @@ bool Axis::AdjustDisplacement(ParentLaye return false; } if (forceOverscroll) { aOverscrollAmountOut = aDisplacement; aDisplacementOut = 0; return false; } - StopSamplingOverscrollAnimation(); + ClearOverscrollAnimationState(); ParentLayerCoord displacement = aDisplacement; // First consume any overscroll in the opposite direction along this axis. ParentLayerCoord consumedOverscroll = 0; if (mOverscroll > 0 && aDisplacement < 0) { consumedOverscroll = std::min(mOverscroll, -aDisplacement); } else if (mOverscroll < 0 && aDisplacement > 0) { @@ -177,17 +177,17 @@ ParentLayerCoord Axis::ApplyResistance(P // factor; this should prevent overscrolling by more than the composition // length. float resistanceFactor = 1 - fabsf(GetOverscroll()) / GetCompositionLength(); return resistanceFactor < 0 ? ParentLayerCoord(0) : aRequestedOverscroll * resistanceFactor; } void Axis::OverscrollBy(ParentLayerCoord aOverscroll) { MOZ_ASSERT(CanScroll()); - StopSamplingOverscrollAnimation(); + ClearOverscrollAnimationState(); aOverscroll = ApplyResistance(aOverscroll); if (aOverscroll > 0) { #ifdef DEBUG if (!FuzzyEqualsCoordinate(GetCompositionEnd().value, GetPageEnd().value)) { nsPrintfCString message("composition end (%f) is not equal (within error) to page end (%f)\n", GetCompositionEnd().value, GetPageEnd().value); NS_ASSERTION(false, message.get()); MOZ_CRASH(); @@ -219,20 +219,33 @@ ParentLayerCoord Axis::GetOverscroll() c NS_ASSERTION(false, message.get()); MOZ_CRASH(); } #endif return result; } -void Axis::StopSamplingOverscrollAnimation() { - ParentLayerCoord overscroll = GetOverscroll(); - ClearOverscroll(); - mOverscroll = overscroll; +void Axis::StartOverscrollAnimation(float aVelocity) { + // Make sure any state from a previous animation has been cleared. + MOZ_ASSERT(mFirstOverscrollAnimationSample == 0 && + mLastOverscrollPeak == 0 && + mOverscrollScale == 1); + + SetVelocity(aVelocity); +} + +void Axis::EndOverscrollAnimation() { + ClearOverscrollAnimationState(); +} + +void Axis::ClearOverscrollAnimationState() { + mFirstOverscrollAnimationSample = 0; + mLastOverscrollPeak = 0; + mOverscrollScale = 1.0f; } void Axis::StepOverscrollAnimation(double aStepDurationMilliseconds) { // Apply spring physics to the overscroll as time goes on. // Note: this method of sampling isn't perfectly smooth, as it assumes // a constant velocity over 'aDelta', instead of an accelerating velocity. // (The way we applying friction to flings has the same issue.) // Hooke's law with damping: @@ -342,20 +355,18 @@ bool Axis::SampleOverscrollAnimation(con return true; } bool Axis::IsOverscrolled() const { return mOverscroll != 0.f; } void Axis::ClearOverscroll() { + ClearOverscrollAnimationState(); mOverscroll = 0; - mFirstOverscrollAnimationSample = 0; - mLastOverscrollPeak = 0; - mOverscrollScale = 1.0f; } ParentLayerCoord Axis::PanStart() const { return mStartPos; } ParentLayerCoord Axis::PanDistance() const { return fabs(mPos - mStartPos);
--- a/gfx/layers/apz/src/Axis.h +++ b/gfx/layers/apz/src/Axis.h @@ -101,22 +101,32 @@ public: * mAsyncPanZoomController->mFrameMetrics.mScrollOffset must be at its * extreme allowed value in the relevant direction (that is, it must be at * its maximum value if we are overscrolled at our composition length, and * at its minimum value if we are overscrolled at the origin). */ ParentLayerCoord GetOverscroll() const; /** + * Start an overscroll animation with the given initial velocity. + */ + void StartOverscrollAnimation(float aVelocity); + + /** * Sample the snap-back animation to relieve overscroll. * |aDelta| is the time since the last sample. */ bool SampleOverscrollAnimation(const TimeDuration& aDelta); /** + * Stop an overscroll animation. + */ + void EndOverscrollAnimation(); + + /** * Return whether this axis is overscrolled in either direction. */ bool IsOverscrolled() const; /** * Clear any overscroll amount on this axis. */ void ClearOverscroll(); @@ -270,19 +280,18 @@ protected: nsTArray<std::pair<uint32_t, float> > mVelocityQueue; const FrameMetrics& GetFrameMetrics() const; // Adjust a requested overscroll amount for resistance, yielding a smaller // actual overscroll amount. ParentLayerCoord ApplyResistance(ParentLayerCoord aOverscroll) const; - // Helper function to disable overscroll transformations triggered by - // SampleOverscrollAnimation(). - void StopSamplingOverscrollAnimation(); + // Clear the state associated with an overscroll animation. + void ClearOverscrollAnimationState(); // Helper function for SampleOverscrollAnimation(). void StepOverscrollAnimation(double aStepDurationMilliseconds); // Convert a velocity from global inches/ms into ParentLayerCoords/ms. float ToLocalVelocity(float aVelocityInchesPerMs) const; };
--- a/gfx/layers/apz/src/InputBlockState.cpp +++ b/gfx/layers/apz/src/InputBlockState.cpp @@ -177,16 +177,25 @@ WheelBlockState::WheelBlockState(const n if (apzc != GetTargetApzc()) { UpdateTargetApzc(apzc); } } } bool +WheelBlockState::SetContentResponse(bool aPreventDefault) +{ + if (aPreventDefault) { + EndTransaction(); + } + return CancelableBlockState::SetContentResponse(aPreventDefault); +} + +bool WheelBlockState::SetConfirmedTargetApzc(const nsRefPtr<AsyncPanZoomController>& aTargetApzc) { // The APZC that we find via APZCCallbackHelpers may not be the same APZC // ESM or OverscrollHandoff would have computed. Make sure we get the right // one by looking for the first apzc the next pending event can scroll. nsRefPtr<AsyncPanZoomController> apzc = aTargetApzc; if (apzc && mEvents.Length() > 0) { const ScrollWheelInput& event = mEvents.ElementAt(0);
--- a/gfx/layers/apz/src/InputBlockState.h +++ b/gfx/layers/apz/src/InputBlockState.h @@ -87,17 +87,17 @@ public: } /** * Record whether or not content cancelled this block of events. * @param aPreventDefault true iff the block is cancelled. * @return false if this block has already received a response from * web content, true if not. */ - bool SetContentResponse(bool aPreventDefault); + virtual bool SetContentResponse(bool aPreventDefault); /** * Record that content didn't respond in time. * @return false if this block already timed out, true if not. */ bool TimeoutContentResponse(); /** @@ -156,16 +156,17 @@ private: */ class WheelBlockState : public CancelableBlockState { public: WheelBlockState(const nsRefPtr<AsyncPanZoomController>& aTargetApzc, bool aTargetConfirmed, const ScrollWheelInput& aEvent); + bool SetContentResponse(bool aPreventDefault) override; bool IsReadyForHandling() const override; bool HasEvents() const override; void DropEvents() override; void HandleEvents() override; bool MustStayActive() override; const char* Type() override; bool SetConfirmedTargetApzc(const nsRefPtr<AsyncPanZoomController>& aTargetApzc) override;
--- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -1008,17 +1008,17 @@ CompositorD3D11::BeginFrame(const nsIntR const Rect& aRenderBounds, Rect* aClipRectOut, Rect* aRenderBoundsOut) { // Don't composite if we are minimised. Other than for the sake of efficency, // this is important because resizing our buffers when mimised will fail and // cause a crash when we're restored. NS_ASSERTION(mHwnd, "Couldn't find an HWND when initialising?"); - if (::IsIconic(mHwnd) || gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { + if (::IsIconic(mHwnd) || mDevice->GetDeviceRemovedReason() != S_OK) { *aRenderBoundsOut = Rect(); return; } nsIntSize oldSize = mSize; UpdateRenderTarget(); // Failed to create a render target or the view. @@ -1081,16 +1081,20 @@ CompositorD3D11::BeginFrame(const nsIntR mutex->ReleaseSync(0); } } void CompositorD3D11::EndFrame() { + if (!mDefaultRT) { + return; + } + nsIntSize oldSize = mSize; EnsureSize(); UINT presentInterval = 0; if (gfxWindowsPlatform::GetPlatform()->IsWARP()) { // When we're using WARP we cannot present immediately as it causes us // to tear when rendering. When not using WARP it appears the DWM takes // care of tearing for us. @@ -1212,16 +1216,23 @@ CompositorD3D11::UpdateRenderTarget() return; } HRESULT hr; nsRefPtr<ID3D11Texture2D> backBuf; hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment()); + if (hr == DXGI_ERROR_INVALID_CALL) { + // This happens on some GPUs/drivers when there's a TDR. + if (mDevice->GetDeviceRemovedReason() != S_OK) { + gfxCriticalError() << "GetBuffer returned invalid call!"; + return; + } + } if (Failed(hr)) { return; } mDefaultRT = new CompositingRenderTargetD3D11(backBuf, IntPoint(0, 0)); mDefaultRT->SetSize(mSize); }
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -252,16 +252,27 @@ protected: AsyncPanZoomController::SetFrameTime(testStartTime); mcc = new NiceMock<MockContentControllerDelayed>(); tm = new TestAPZCTreeManager(); apzc = new TestAsyncPanZoomController(0, mcc, tm, mGestureBehavior); apzc->SetFrameMetrics(TestFrameMetrics()); } + /** + * Get the APZC's scroll range in CSS pixels. + */ + CSSRect GetScrollRange() const + { + const FrameMetrics& metrics = apzc->GetFrameMetrics(); + return CSSRect( + metrics.GetScrollableRect().TopLeft(), + metrics.GetScrollableRect().Size() - metrics.CalculateCompositedSizeInCssPixels()); + } + virtual void TearDown() { apzc->Destroy(); } void MakeApzcWaitForMainThread() { apzc->SetWaitForMainThread(); @@ -272,16 +283,59 @@ protected: apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToParentLayerScale(0.25f), CSSToParentLayerScale(4.0f))); } void MakeApzcUnzoomable() { apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToParentLayerScale(1.0f), CSSToParentLayerScale(1.0f))); } + void PanIntoOverscroll(int& aTime); + + /** + * Sample animations once, 1 ms later than the last sample. + */ + void SampleAnimationOnce() + { + const TimeDuration increment = TimeDuration::FromMilliseconds(1); + ParentLayerPoint pointOut; + ViewTransform viewTransformOut; + testStartTime += increment; + apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); + } + + /** + * Sample animations until we recover from overscroll. + * @param aExpectedScrollOffset the expected reported scroll offset + * throughout the animation + */ + void SampleAnimationUntilRecoveredFromOverscroll(const ParentLayerPoint& aExpectedScrollOffset) + { + const TimeDuration increment = TimeDuration::FromMilliseconds(1); + bool recoveredFromOverscroll = false; + ParentLayerPoint pointOut; + ViewTransform viewTransformOut; + while (apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut)) { + // The reported scroll offset should be the same throughout. + EXPECT_EQ(aExpectedScrollOffset, pointOut); + + // Trigger computation of the overscroll tranform, to make sure + // no assetions fire during the calculation. + apzc->GetOverscrollTransform(); + + if (!apzc->IsOverscrolled()) { + recoveredFromOverscroll = true; + } + + testStartTime += increment; + } + EXPECT_TRUE(recoveredFromOverscroll); + apzc->AssertStateIsReset(); + } + void TestOverscroll(); AsyncPanZoomController::GestureBehavior mGestureBehavior; TimeStamp testStartTime; nsRefPtr<MockContentControllerDelayed> mcc; nsRefPtr<TestAPZCTreeManager> tm; nsRefPtr<TestAsyncPanZoomController> apzc; }; @@ -1132,58 +1186,45 @@ TEST_F(APZCBasicTester, PanningTransform check.Call("Simple pan"); ApzcPanNoFling(apzc, time, 50, 25); check.Call("Complex pan"); Pan(apzc, time, 25, 45); apzc->AdvanceAnimationsUntilEnd(testStartTime); check.Call("Done"); } +void APZCBasicTester::PanIntoOverscroll(int& aTime) +{ + int touchStart = 500; + int touchEnd = 10; + Pan(apzc, aTime, touchStart, touchEnd); + EXPECT_TRUE(apzc->IsOverscrolled()); +} + void APZCBasicTester::TestOverscroll() { // Pan sufficiently to hit overscroll behavior int time = 0; - int touchStart = 500; - int touchEnd = 10; - Pan(apzc, time, touchStart, touchEnd); - EXPECT_TRUE(apzc->IsOverscrolled()); + PanIntoOverscroll(time); // Check that we recover from overscroll via an animation. - const TimeDuration increment = TimeDuration::FromMilliseconds(1); - bool recoveredFromOverscroll = false; - ParentLayerPoint pointOut; - ViewTransform viewTransformOut; - while (apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut)) { - // The reported scroll offset should be the same throughout. - EXPECT_EQ(ParentLayerPoint(0, 90), pointOut); - - // Trigger computation of the overscroll tranform, to make sure - // no assetions fire during the calculation. - apzc->GetOverscrollTransform(); - - if (!apzc->IsOverscrolled()) { - recoveredFromOverscroll = true; - } - - testStartTime += increment; - } - EXPECT_TRUE(recoveredFromOverscroll); - apzc->AssertStateIsReset(); + ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost()); + SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset); } TEST_F(APZCBasicTester, OverScrollPanning) { SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true); TestOverscroll(); } // Tests that an overscroll animation doesn't trigger an assertion failure // in the case where a sample has a velocity of zero. -TEST_F(APZCBasicTester, OverScroll_Bug1152051) { +TEST_F(APZCBasicTester, OverScroll_Bug1152051a) { SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true); // Doctor the prefs to make the velocity zero at the end of the first sample. // This ensures our incoming velocity to the overscroll animation is // a round(ish) number, 4.9 (that being the distance of the pan before // overscroll, which is 500 - 10 = 490 pixels, divided by the duration of // the pan, which is 100 ms). @@ -1192,16 +1233,54 @@ TEST_F(APZCBasicTester, OverScroll_Bug11 // To ensure the velocity after the first sample is 0, set the spring // stiffness to the incoming velocity (4.9) divided by the overscroll // (400 pixels) times the step duration (1 ms). SCOPED_GFX_PREF(APZOverscrollSpringStiffness, float, 0.01225f); TestOverscroll(); } +// Tests that ending an overscroll animation doesn't leave around state that +// confuses the next overscroll animation. +TEST_F(APZCBasicTester, OverScroll_Bug1152051b) { + SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true); + + SCOPED_GFX_PREF(APZOverscrollStopDistanceThreshold, float, 0.1f); + + // Pan sufficiently to hit overscroll behavior + int time = 0; + PanIntoOverscroll(time); + + // Sample animations once, to give the fling animation started on touch-up + // a chance to realize it's overscrolled, and schedule a call to + // HandleFlingOverscroll(). + SampleAnimationOnce(); + + // Give the call to HandleFlingOverscroll() a chance to occur, creating + // an overscroll animation. + mcc->RunThroughDelayedTasks(); + + // Sample the overscroll animation once, to get it to initialize + // the first overscroll sample. + SampleAnimationOnce(); + + // Do a touch-down to cancel the overscroll animation, and then a touch-up + // to schedule a new one since we're still overscrolled. We don't pan because + // panning can trigger functions that clear the overscroll animation state + // in other ways. + TouchDown(apzc, 10, 10, time, nullptr); + TouchUp(apzc, 10, 10, time); + + // Sample the second overscroll animation to its end. + // If the ending of the first overscroll animation fails to clear state + // properly, this will assert. + ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost()); + SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset); +} + TEST_F(APZCBasicTester, OverScrollAbort) { SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true); // Pan sufficiently to hit overscroll behavior int time = 0; int touchStart = 500; int touchEnd = 10; Pan(apzc, time, touchStart, touchEnd);
--- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -338,17 +338,17 @@ private: DECL_GFX_PREF(Live, "layout.css.scroll-behavior.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f); DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled", ScrollBehaviorEnabled, bool, false); DECL_GFX_PREF(Live, "layout.css.scroll-behavior.spring-constant", ScrollBehaviorSpringConstant, float, 250.0f); DECL_GFX_PREF(Live, "layout.css.scroll-snap.prediction-max-velocity", ScrollSnapPredictionMaxVelocity, int32_t, 2000); DECL_GFX_PREF(Live, "layout.css.scroll-snap.prediction-sensitivity", ScrollSnapPredictionSensitivity, float, 0.750f); DECL_GFX_PREF(Once, "layout.css.touch_action.enabled", TouchActionEnabled, bool, false); DECL_GFX_PREF(Live, "layout.display-list.dump", LayoutDumpDisplayList, bool, false); - DECL_GFX_PREF(Live, "layout.event-regions.enabled", LayoutEventRegionsEnabled, bool, false); + DECL_GFX_PREF(Live, "layout.event-regions.enabled", LayoutEventRegionsEnabledDoNotUseDirectly, bool, false); DECL_GFX_PREF(Once, "layout.frame_rate", LayoutFrameRate, int32_t, -1); DECL_GFX_PREF(Once, "layout.paint_rects_separately", LayoutPaintRectsSeparately, bool, true); // This and code dependent on it should be removed once containerless scrolling looks stable. DECL_GFX_PREF(Once, "layout.scroll.root-frame-containers", LayoutUseContainersForRootFrames, bool, true); // This affects whether events will be routed through APZ or not. DECL_GFX_PREF(Live, "mousewheel.system_scroll_override_on_root_content.enabled",
--- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -1720,18 +1720,18 @@ gfxWindowsPlatform::GetDXGIAdapter() // We leak this module everywhere, we might as well do so here as well. dxgiModule.disown(); return mAdapter; } bool DoesD3D11DeviceWork(ID3D11Device *device) { - static bool checked; - static bool result; + static bool checked = false; + static bool result = false; if (checked) return result; checked = true; if (gfxPrefs::Direct2DForceEnabled() || gfxPrefs::LayersAccelerationForceEnabled()) { @@ -1759,18 +1759,18 @@ bool DoesD3D11DeviceWork(ID3D11Device *d result = true; return true; } // See bug 1083071. On some drivers, Direct3D 11 CreateShaderResourceView fails // with E_OUTOFMEMORY. bool DoesD3D11TextureSharingWork(ID3D11Device *device) { - static bool checked; - static bool result; + static bool checked = false; + static bool result = false; if (checked) return result; checked = true; if (gfxPrefs::Direct2DForceEnabled() || gfxPrefs::LayersAccelerationForceEnabled()) {
--- a/image/src/imgLoader.cpp +++ b/image/src/imgLoader.cpp @@ -1434,19 +1434,18 @@ imgLoader::MinimizeCaches() bool imgLoader::PutIntoCache(const ImageCacheKey& aKey, imgCacheEntry* entry) { imgCacheTable& cache = GetCache(aKey); LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::PutIntoCache", "uri", aKey.Spec()); - // Check to see if this request already exists in the cache and is being - // loaded on a different thread. If so, don't allow this entry to be added to - // the cache. + // Check to see if this request already exists in the cache. If so, we'll + // replace the old version. nsRefPtr<imgCacheEntry> tmpCacheEntry; if (cache.Get(aKey, getter_AddRefs(tmpCacheEntry)) && tmpCacheEntry) { PR_LOG(GetImgLog(), PR_LOG_DEBUG, ("[this=%p] imgLoader::PutIntoCache -- Element already in the cache", nullptr)); nsRefPtr<imgRequest> tmpRequest = tmpCacheEntry->GetRequest(); // If it already exists, and we're putting the same key into the cache, we
--- a/intl/icu/source/common/uinvchar.c +++ b/intl/icu/source/common/uinvchar.c @@ -424,17 +424,17 @@ uprv_copyEbcdic(const UDataSwapper *ds, } /* setup and checking */ s=(const uint8_t *)inData; count=length; while(count>0) { c=*s++; if(c!=0 && ((c=asciiFromEbcdic[c])==0 || !UCHAR_IS_INVARIANT(c))) { - udata_printError(ds, "uprv_copyEbcdic() string[%] contains a variant character in position %d\n", + udata_printError(ds, "uprv_copyEbcdic() string[%d] contains a variant character in position %d\n", length, length-count); *pErrorCode=U_INVALID_CHAR_FOUND; return 0; } --count; } if(length>0 && inData!=outData) {
deleted file mode 100644 --- a/intl/uconv/tests/unit/test_bug365345.js +++ /dev/null @@ -1,52 +0,0 @@ -/* Tests conversion of unrepresented characters that should be transliterated - * to spaces (bug 365345), and some others from transliterate.properties while - * I'm here - */ - -const inSpace = "Hello Space"; -const inEnSpace = "Hello\u2002EnSpace"; -const inEmSpace = "Hello\u2003EmSpace"; -const inEuro = "Hello\u20ACEuro"; -const inTamil1000 = "Hello\u0BF2Tamil1000"; -const inMonospace9 = "Hello\ud835\udfffMonospace9"; - -const expectedSpace = "Hello Space"; -const expectedEnSpace = "Hello EnSpace"; -const expectedEmSpace = "Hello EmSpace"; -const expectedEuro = "HelloEUREuro"; -const expectedTamil1000 = "Hello[1000]Tamil1000"; -const expectedMonospace9 = "Hello9Monospace9"; - -const EntityAfterCharsetConv = 512; -const transliterate = 8; - -const charset = "ISO-8859-2"; - -function run_test() { - var SaveAsCharset = - Components.Constructor("@mozilla.org/intl/saveascharset;1", - "nsISaveAsCharset", - "Init"); - - var converter = new SaveAsCharset(charset, - EntityAfterCharsetConv, - transliterate); - - var outSpace = converter.Convert(inSpace); - do_check_eq(outSpace, expectedSpace); - - var outEnSpace = converter.Convert(inEnSpace); - do_check_eq(outEnSpace, expectedEnSpace); - - var outEmSpace = converter.Convert(inEmSpace); - do_check_eq(outEmSpace, expectedEmSpace); - - var outEuro = converter.Convert(inEuro); - do_check_eq(outEuro, expectedEuro); - - var outTamil1000 = converter.Convert(inTamil1000); - do_check_eq(outTamil1000, expectedTamil1000); - - var outMonospace9 = converter.Convert(inMonospace9); - do_check_eq(outMonospace9, expectedMonospace9); -}
--- a/intl/uconv/tests/unit/xpcshell.ini +++ b/intl/uconv/tests/unit/xpcshell.ini @@ -9,17 +9,16 @@ support-files = data/unicode-conversion.utf16be.txt data/unicode-conversion.utf16le.txt data/unicode-conversion.utf8.txt [test_bug116882.js] [test_bug317216.js] [test_bug321379.js] [test_bug340714.js] -[test_bug365345.js] [test_bug381412.Big5-HKSCS.js] [test_bug381412.Big5.js] [test_bug381412.euc-kr.js] [test_bug381412.euc_jp.js] [test_bug381412.gb2312.js] [test_bug381412.js] [test_bug396637.js] [test_bug399257.js]
--- a/intl/unicharutil/nsEntityConverter.cpp +++ b/intl/unicharutil/nsEntityConverter.cpp @@ -1,239 +1,173 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ #include "nsEntityConverter.h" #include "nsLiteralString.h" #include "nsString.h" #include "mozilla/Services.h" #include "nsServiceManagerUtils.h" #include "nsCRT.h" // // implementation methods // -nsEntityConverter::nsEntityConverter() : - mVersionList(nullptr), - mVersionListLength(0) -{ -} - -nsEntityConverter::~nsEntityConverter() -{ - if (mVersionList) - delete [] mVersionList; -} +nsEntityConverter::nsEntityConverter() { } -NS_IMETHODIMP -nsEntityConverter::LoadVersionPropertyFile() -{ - NS_NAMED_LITERAL_CSTRING(url, "resource://gre/res/entityTables/htmlEntityVersions.properties"); - - nsCOMPtr<nsIStringBundleService> bundleService = - mozilla::services::GetStringBundleService(); - if (!bundleService) - return NS_ERROR_FAILURE; - - nsCOMPtr<nsIStringBundle> entities; - nsresult rv = bundleService->CreateBundle(url.get(), getter_AddRefs(entities)); - if (NS_FAILED(rv)) return rv; - - nsresult result; +nsEntityConverter::~nsEntityConverter() { } - nsAutoString key; - nsXPIDLString value; - rv = entities->GetStringFromName(MOZ_UTF16("length"), - getter_Copies(value)); - NS_ASSERTION(NS_SUCCEEDED(rv),"nsEntityConverter: malformed entity table\n"); - if (NS_FAILED(rv)) return rv; - - mVersionListLength = nsAutoString(value).ToInteger(&result); - NS_ASSERTION(32 >= mVersionListLength,"nsEntityConverter: malformed entity table\n"); - if (32 < mVersionListLength) return NS_ERROR_FAILURE; - - mVersionList = new nsEntityVersionList[mVersionListLength]; - if (!mVersionList) return NS_ERROR_OUT_OF_MEMORY; - - for (uint32_t i = 0; i < mVersionListLength && NS_SUCCEEDED(rv); i++) { - key.SetLength(0); - key.AppendInt(i+1, 10); - rv = entities->GetStringFromName(key.get(), getter_Copies(value)); - uint32_t len = value.Length(); - if (kVERSION_STRING_LEN < len) return NS_ERROR_UNEXPECTED; - - memcpy(mVersionList[i].mEntityListName, value.get(), len*sizeof(char16_t)); - mVersionList[i].mEntityListName[len] = 0; - mVersionList[i].mVersion = (1 << i); +nsIStringBundle* +nsEntityConverter:: GetVersionBundleInstance(uint32_t versionNumber) +{ + switch(versionNumber){ + case nsIEntityConverter::html40Latin1: + if (!mHTML40Latin1Bundle) { + mHTML40Latin1Bundle = LoadEntityBundle(kHTML40LATIN1); + MOZ_ASSERT(mHTML40Latin1Bundle, "LoadEntityBundle failed"); + } + return mHTML40Latin1Bundle; + case nsIEntityConverter::html40Symbols: + if (!mHTML40SymbolsBundle) { + mHTML40SymbolsBundle = LoadEntityBundle(kHTML40SYMBOLS); + MOZ_ASSERT(mHTML40SymbolsBundle, "LoadEntityBundle failed"); } - - return NS_OK; + return mHTML40SymbolsBundle; + case nsIEntityConverter::html40Special: + if (!mHTML40SpecialBundle) { + mHTML40SpecialBundle = LoadEntityBundle(kHTML40SPECIAL); + MOZ_ASSERT(mHTML40SpecialBundle, "LoadEntityBundle failed"); + } + return mHTML40SpecialBundle; + case nsIEntityConverter::mathml20: + if (!mMathML20Bundle) { + mMathML20Bundle = LoadEntityBundle(kMATHML20); + MOZ_ASSERT(mMathML20Bundle, "LoadEntityBundle failed"); + } + return mMathML20Bundle; + default: + return nullptr; + } } already_AddRefed<nsIStringBundle> -nsEntityConverter::LoadEntityBundle(uint32_t version) +nsEntityConverter:: LoadEntityBundle(const char *fileName) { - nsAutoCString url(NS_LITERAL_CSTRING("resource://gre/res/entityTables/")); + NS_ENSURE_TRUE(fileName, nullptr); + + nsAutoCString url("resource://gre/res/entityTables/"); nsresult rv; nsCOMPtr<nsIStringBundleService> bundleService = - do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); + do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, nullptr); - - const char16_t *versionName = GetVersionName(version); - NS_ENSURE_TRUE(versionName, nullptr); - // all property file names are ASCII, like "html40Latin1" so this is safe - LossyAppendUTF16toASCII(versionName, url); - url.AppendLiteral(".properties"); + url.Append(fileName); nsCOMPtr<nsIStringBundle> bundle; rv = bundleService->CreateBundle(url.get(), getter_AddRefs(bundle)); NS_ENSURE_SUCCESS(rv, nullptr); - + return bundle.forget(); } -const char16_t* -nsEntityConverter:: GetVersionName(uint32_t versionNumber) -{ - for (uint32_t i = 0; i < mVersionListLength; i++) { - if (versionNumber == mVersionList[i].mVersion) - return mVersionList[i].mEntityListName; - } - - return nullptr; -} - -nsIStringBundle* -nsEntityConverter:: GetVersionBundleInstance(uint32_t versionNumber) -{ - if (!mVersionList) { - // load the property file which contains available version names - // and generate a list of version/name pair - if (NS_FAILED(LoadVersionPropertyFile())) - return nullptr; - } - - uint32_t i; - for (i = 0; i < mVersionListLength; i++) { - if (versionNumber == mVersionList[i].mVersion) { - if (!mVersionList[i].mEntities) - { // not loaded - // load the property file - mVersionList[i].mEntities = LoadEntityBundle(versionNumber); - NS_ASSERTION(mVersionList[i].mEntities, "LoadEntityBundle failed"); - } - return mVersionList[i].mEntities.get(); - } - } - - return nullptr; -} - - // // nsISupports methods // NS_IMPL_ISUPPORTS(nsEntityConverter,nsIEntityConverter) - // // nsIEntityConverter // NS_IMETHODIMP nsEntityConverter::ConvertToEntity(char16_t character, uint32_t entityVersion, char **_retval) -{ +{ return ConvertUTF32ToEntity((uint32_t)character, entityVersion, _retval); } NS_IMETHODIMP nsEntityConverter::ConvertUTF32ToEntity(uint32_t character, uint32_t entityVersion, char **_retval) { NS_ASSERTION(_retval, "null ptr- _retval"); - if(nullptr == _retval) + if (nullptr == _retval) { return NS_ERROR_NULL_POINTER; + } *_retval = nullptr; for (uint32_t mask = 1, mask2 = 0xFFFFFFFFL; (0!=(entityVersion & mask2)); mask<<=1, mask2<<=1) { - if (0 == (entityVersion & mask)) + if (0 == (entityVersion & mask)) { continue; + } + nsIStringBundle* entities = GetVersionBundleInstance(entityVersion & mask); - NS_ASSERTION(entities, "Cannot get the property file"); + NS_ASSERTION(entities, "Cannot get the entity"); - if (!entities) + if (!entities) { continue; + } nsAutoString key(NS_LITERAL_STRING("entity.")); key.AppendInt(character,10); nsXPIDLString value; nsresult rv = entities->GetStringFromName(key.get(), getter_Copies(value)); if (NS_SUCCEEDED(rv)) { *_retval = ToNewCString(value); - if(nullptr == *_retval) - return NS_ERROR_OUT_OF_MEMORY; - else - return NS_OK; + return NS_OK; } } - return NS_ERROR_ILLEGAL_VALUE; + return NS_ERROR_ILLEGAL_VALUE; } NS_IMETHODIMP nsEntityConverter::ConvertToEntities(const char16_t *inString, uint32_t entityVersion, char16_t **_retval) { NS_ENSURE_ARG_POINTER(inString); NS_ENSURE_ARG_POINTER(_retval); *_retval = nullptr; nsString outString; // per character look for the entity uint32_t len = NS_strlen(inString); for (uint32_t i = 0; i < len; i++) { nsAutoString key(NS_LITERAL_STRING("entity.")); - if (NS_IS_HIGH_SURROGATE(inString[i]) && - i + 2 < len && - NS_IS_LOW_SURROGATE(inString[i + 1])) { + if (NS_IS_HIGH_SURROGATE(inString[i]) && i + 2 < len && NS_IS_LOW_SURROGATE(inString[i + 1])) { key.AppendInt(SURROGATE_TO_UCS4(inString[i], inString[i+1]), 10); ++i; - } - else { + } else { key.AppendInt(inString[i],10); } - + nsXPIDLString value; const char16_t *entity = nullptr; for (uint32_t mask = 1, mask2 = 0xFFFFFFFFL; (0!=(entityVersion & mask2)); mask<<=1, mask2<<=1) { - if (0 == (entityVersion & mask)) - continue; + if (0 == (entityVersion & mask)) { + continue; + } nsIStringBundle* entities = GetVersionBundleInstance(entityVersion & mask); NS_ASSERTION(entities, "Cannot get the property file"); - if (!entities) - continue; + if (!entities) { + continue; + } - nsresult rv = entities->GetStringFromName(key.get(), - getter_Copies(value)); + nsresult rv = entities->GetStringFromName(key.get(), getter_Copies(value)); if (NS_SUCCEEDED(rv)) { entity = value.get(); break; } } if (entity) { outString.Append(entity); - } - else { + } else { outString.Append(&inString[i], 1); } } *_retval = ToNewUnicode(outString); - if (!*_retval) - return NS_ERROR_OUT_OF_MEMORY; return NS_OK; }
--- a/intl/unicharutil/nsEntityConverter.h +++ b/intl/unicharutil/nsEntityConverter.h @@ -5,64 +5,45 @@ #ifndef nsEntityConverter_h__ #define nsEntityConverter_h__ #include "nsIEntityConverter.h" #include "nsIStringBundle.h" #include "nsCOMPtr.h" -#define kVERSION_STRING_LEN 128 - -class nsEntityVersionList -{ -public: - nsEntityVersionList() {} - - uint32_t mVersion; - char16_t mEntityListName[kVERSION_STRING_LEN+1]; - nsCOMPtr<nsIStringBundle> mEntities; -}; - class nsEntityConverter: public nsIEntityConverter { public: - - // - // implementation methods - // - nsEntityConverter(); + // + // implementation methods + // + nsEntityConverter(); - // - // nsISupports - // - NS_DECL_ISUPPORTS + // + // nsISupports + // + NS_DECL_ISUPPORTS - // - // nsIEntityConverter - // - NS_IMETHOD ConvertUTF32ToEntity(uint32_t character, uint32_t entityVersion, char **_retval) override; - NS_IMETHOD ConvertToEntity(char16_t character, uint32_t entityVersion, char **_retval) override; - - NS_IMETHOD ConvertToEntities(const char16_t *inString, uint32_t entityVersion, char16_t **_retval) override; + NS_IMETHOD ConvertUTF32ToEntity(uint32_t character, uint32_t entityVersion, char **_retval) override; + NS_IMETHOD ConvertToEntity(char16_t character, uint32_t entityVersion, char **_retval) override; + NS_IMETHOD ConvertToEntities(const char16_t *inString, uint32_t entityVersion, char16_t **_retval) override; protected: + // map version number to a string bundle + nsIStringBundle* GetVersionBundleInstance(uint32_t versionNumber); - // load a version property file and generate a version list (number/name pair) - NS_IMETHOD LoadVersionPropertyFile(); - - // map version number to version string - const char16_t* GetVersionName(uint32_t versionNumber); + // load a string bundle file + already_AddRefed<nsIStringBundle> LoadEntityBundle(const char *fileName); - // map version number to a string bundle - nsIStringBundle* GetVersionBundleInstance(uint32_t versionNumber); - - // load a string bundle file - already_AddRefed<nsIStringBundle> LoadEntityBundle(uint32_t version); + const char* kHTML40LATIN1 = "html40Latin1.properties"; + const char* kHTML40SYMBOLS = "html40Symbols.properties"; + const char* kHTML40SPECIAL = "html40Special.properties"; + const char* kMATHML20 = "mathml20.properties"; + nsCOMPtr<nsIStringBundle> mHTML40Latin1Bundle; + nsCOMPtr<nsIStringBundle> mHTML40SymbolsBundle; + nsCOMPtr<nsIStringBundle> mHTML40SpecialBundle; + nsCOMPtr<nsIStringBundle> mMathML20Bundle; - - nsEntityVersionList *mVersionList; // array of version number/name pairs - uint32_t mVersionListLength; // number of supported versions - - virtual ~nsEntityConverter(); + virtual ~nsEntityConverter(); }; #endif
--- a/intl/unicharutil/nsIEntityConverter.idl +++ b/intl/unicharutil/nsIEntityConverter.idl @@ -13,17 +13,17 @@ [scriptable, uuid(D14C7111-55E0-11d3-91D9-00105AA3F7DC)] interface nsIEntityConverter : nsISupports { const unsigned long entityNone = 0; const unsigned long html40Latin1 = 1; const unsigned long html40Symbols = 2; const unsigned long html40Special = 4; // excludes ", &, <, > - const unsigned long transliterate = 8; + const unsigned long transliterate = 8; // Obsolete const unsigned long mathml20 = 16; const unsigned long html32 = html40Latin1; const unsigned long html40 = html40Latin1+html40Symbols+html40Special; const unsigned long entityW3C = html40+mathml20; string ConvertUTF32ToEntity(in unsigned long character, in unsigned long entityVersion); string ConvertToEntity(in wchar character, in unsigned long entityVersion);
deleted file mode 100644 --- a/intl/unicharutil/tables/htmlEntityVersions.properties +++ /dev/null @@ -1,18 +0,0 @@ - -# 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/. - - -# LOCALIZATION NOTE: FILE -# This file associates internal names of entity lists to integers. -# Do not translate anything in this file - -# list supported versions number/name pair -# length should not be greater than 32 -length=5 -1=html40Latin1 -2=html40Symbols -3=html40Special -4=transliterate -5=mathml20
--- a/intl/unicharutil/tables/moz.build +++ b/intl/unicharutil/tables/moz.build @@ -1,18 +1,16 @@ # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. RESOURCE_FILES.entityTables = [ - 'htmlEntityVersions.properties', 'html40Latin1.properties', 'html40Symbols.properties', 'html40Special.properties', 'mathml20.properties', - 'transliterate.properties', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt': CFLAGS += CONFIG['MOZ_QT_CFLAGS'] CXXFLAGS += CONFIG['MOZ_QT_CFLAGS']
deleted file mode 100644 --- a/intl/unicharutil/tables/transliterate.properties +++ /dev/null @@ -1,2893 +0,0 @@ -# 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/. - -# -# THIS FILE IS GENERATED BY mozilla/intl/unicharutil/tools/gentransliterate.pl -# PLEASE DO NOT MODIFY THIS FILE BY HAND -# -entity.list.name=transliterate -entity.169=(c) -# -# -# Here are the windows-1252 characters from the range 0x80 - 0x9F -# -entity.8364=EUR -entity.8218=, -entity.402=f -entity.8222=" -entity.8224=+ -entity.8225=++ -entity.710=^ -entity.8240=0/00 -entity.8249=< -entity.338=OE -entity.8216=' -entity.8217=' -entity.8220=" -entity.8221=" -entity.8226=. -entity.8211=-- -entity.8212=--- -entity.732=~ -entity.8250=> -entity.339=oe -entity.8192=\u0020 -entity.8193=\u0020 -entity.8208=- -entity.8209=- -entity.8210=- -entity.8213=-- -entity.8203= -entity.8289= -entity.8290= -entity.8518=d -entity.8722=- -entity.1470=- -entity.1472=| -entity.1475=: -entity.1523=' -entity.1524=" -## -## End of hand coded section -## Below are generated from the unicode character database -## -entity.160=\u0020 -entity.170=^(a) -entity.178=^(2) -entity.179=^(3) -entity.185=^(1) -entity.186=^(o) -entity.188=1/4 -entity.189=1/2 -entity.190=3/4 -entity.192=A` -entity.193=A' -entity.194=A^ -entity.195=A~ -entity.196=A" -entity.197=A* -entity.199=C, -entity.200=E` -entity.201=E' -entity.202=E^ -entity.203=E" -entity.204=I` -entity.205=I' -entity.206=I^ -entity.207=I" -entity.209=N~ -entity.210=O` -entity.211=O' -entity.212=O^ -entity.213=O~ -entity.214=O" -entity.217=U` -entity.218=U' -entity.219=U^ -entity.220=U" -entity.221=Y' -entity.224=a` -entity.225=a' -entity.226=a^ -entity.227=a~ -entity.228=a" -entity.229=a* -entity.231=c, -entity.232=e` -entity.233=e' -entity.234=e^ -entity.235=e" -entity.236=i` -entity.237=i' -entity.238=i^ -entity.239=i" -entity.241=n~ -entity.242=o` -entity.243=o' -entity.244=o^ -entity.245=o~ -entity.246=o" -entity.249=u` -entity.250=u' -entity.251=u^ -entity.252=u" -entity.253=y' -entity.255=y" -entity.256=A- -entity.257=a- -entity.258=A( -entity.259=a( -entity.260=A; -entity.261=a; -entity.262=C' -entity.263=c' -entity.264=C^ -entity.265=c^ -entity.266=C. -entity.267=c. -entity.268=C( -entity.269=c( -entity.270=D( -entity.271=d( -entity.274=E- -entity.275=e- -entity.276=E( -entity.277=e( -entity.278=E. -entity.279=e. -entity.280=E; -entity.281=e; -entity.282=E( -entity.283=e( -entity.284=G^ -entity.285=g^ -entity.286=G( -entity.287=g( -entity.288=G. -entity.289=g. -entity.290=G, -entity.291=g, -entity.292=H^ -entity.293=h^ -entity.296=I~ -entity.297=i~ -entity.298=I- -entity.299=i- -entity.300=I( -entity.301=i( -entity.302=I; -entity.303=i; -entity.304=I. -entity.306=IJ -entity.307=ij -entity.308=J^ -entity.309=j^ -entity.310=K, -entity.311=k, -entity.313=L' -entity.314=l' -entity.315=L, -entity.316=l, -entity.317=L( -entity.318=l( -entity.319=L. -entity.320=l. -entity.323=N' -entity.324=n' -entity.325=N, -entity.326=n, -entity.327=N( -entity.328=n( -entity.329='n -entity.332=O- -entity.333=o- -entity.334=O( -entity.335=o( -entity.336=O" -entity.337=o" -entity.340=R' -entity.341=r' -entity.342=R, -entity.343=r, -entity.344=R( -entity.345=r( -entity.346=S' -entity.347=s' -entity.348=S^ -entity.349=s^ -entity.350=S, -entity.351=s, -entity.352=S( -entity.353=s( -entity.354=T, -entity.355=t, -entity.356=T( -entity.357=t( -entity.360=U~ -entity.361=u~ -entity.362=U- -entity.363=u- -entity.364=U( -entity.365=u( -entity.366=U* -entity.367=u* -entity.368=U" -entity.369=u" -entity.370=U; -entity.371=u; -entity.372=W^ -entity.373=w^ -entity.374=Y^ -entity.375=y^ -entity.376=Y" -entity.377=Z' -entity.378=z' -entity.379=Z. -entity.380=z. -entity.381=Z( -entity.382=z( -entity.383=s -entity.416=O+ -entity.417=o+ -entity.431=U+ -entity.432=u+ -entity.452=DZ( -entity.453=Dz( -entity.454=dz( -entity.455=LJ -entity.456=Lj -entity.457=lj -entity.458=NJ -entity.459=Nj -entity.460=nj -entity.461=A( -entity.462=a( -entity.463=I( -entity.464=i( -entity.465=O( -entity.466=o( -entity.467=U( -entity.468=u( -entity.469=U"- -entity.470=u"- -entity.471=U"' -entity.472=u"' -entity.473=U"( -entity.474=u"( -entity.475=U"` -entity.476=u"` -entity.478=A"- -entity.479=a"- -entity.480=A.- -entity.481=a.- -entity.482=AE- -entity.483=ae- -entity.486=G( -entity.487=g( -entity.488=K( -entity.489=k( -entity.490=O; -entity.491=o; -entity.492=O;- -entity.493=o;- -entity.494=EZH( -entity.495=ezh( -entity.496=j( -entity.497=DZ -entity.498=Dz -entity.499=dz -entity.500=G' -entity.501=g' -entity.504=N` -entity.505=n` -entity.506=A*' -entity.507=a*' -entity.508=AE' -entity.509=ae' -entity.510=O/' -entity.511=o/' -entity.512=A`` -entity.513=a`` -entity.514=A( -entity.515=a( -entity.516=E`` -entity.517=e`` -entity.518=E( -entity.519=e( -entity.520=I`` -entity.521=i`` -entity.522=I( -entity.523=i( -entity.524=O`` -entity.525=o`` -entity.526=O( -entity.527=o( -entity.528=R`` -entity.529=r`` -entity.530=R( -entity.531=r( -entity.532=U`` -entity.533=u`` -entity.534=U( -entity.535=u( -entity.536=S, -entity.537=s, -entity.538=T, -entity.539=t, -entity.542=H( -entity.543=h( -entity.550=A. -entity.551=a. -entity.552=E, -entity.553=e, -entity.554=O"- -entity.555=o"- -entity.556=O~- -entity.557=o~- -entity.558=O. -entity.559=o. -entity.560=O.- -entity.561=o.- -entity.562=Y- -entity.563=y- -entity.688=^(h) -entity.690=^(j) -entity.691=^(r) -entity.695=^(w) -entity.696=^(y) -entity.737=^(l) -entity.738=^(s) -entity.739=^(x) -entity.1632=0 -entity.1633=1 -entity.1634=2 -entity.1635=3 -entity.1636=4 -entity.1637=5 -entity.1638=6 -entity.1639=7 -entity.1640=8 -entity.1641=9 -entity.1776=0 -entity.1777=1 -entity.1778=2 -entity.1779=3 -entity.1780=4 -entity.1781=5 -entity.1782=6 -entity.1783=7 -entity.1784=8 -entity.1785=9 -entity.1984=0 -entity.1985=1 -entity.1986=2 -entity.1987=3 -entity.1988=4 -entity.1989=5 -entity.1990=6 -entity.1991=7 -entity.1992=8 -entity.1993=9 -entity.2406=0 -entity.2407=1 -entity.2408=2 -entity.2409=3 -entity.2410=4 -entity.2411=5 -entity.2412=6 -entity.2413=7 -entity.2414=8 -entity.2415=9 -entity.2534=0 -entity.2535=1 -entity.2536=2 -entity.2537=3 -entity.2538=4 -entity.2539=5 -entity.2540=6 -entity.2541=7 -entity.2542=8 -entity.2543=9 -entity.2548=[1/16] -entity.2549=[1/8] -entity.2550=[3/16] -entity.2551=[1/4] -entity.2552=[3/4] -entity.2553=[16] -entity.2662=0 -entity.2663=1 -entity.2664=2 -entity.2665=3 -entity.2666=4 -entity.2667=5 -entity.2668=6 -entity.2669=7 -entity.2670=8 -entity.2671=9 -entity.2790=0 -entity.2791=1 -entity.2792=2 -entity.2793=3 -entity.2794=4 -entity.2795=5 -entity.2796=6 -entity.2797=7 -entity.2798=8 -entity.2799=9 -entity.2918=0 -entity.2919=1 -entity.2920=2 -entity.2921=3 -entity.2922=4 -entity.2923=5 -entity.2924=6 -entity.2925=7 -entity.2926=8 -entity.2927=9 -entity.2930=[1/4] -entity.2931=[1/2] -entity.2932=[3/4] -entity.2933=[1/16] -entity.2934=[1/8] -entity.2935=[3/16] -entity.3046=0 -entity.3047=1 -entity.3048=2 -entity.3049=3 -entity.3050=4 -entity.3051=5 -entity.3052=6 -entity.3053=7 -entity.3054=8 -entity.3055=9 -entity.3056=[10] -entity.3057=[100] -entity.3058=[1000] -entity.3174=0 -entity.3175=1 -entity.3176=2 -entity.3177=3 -entity.3178=4 -entity.3179=5 -entity.3180=6 -entity.3181=7 -entity.3182=8 -entity.3183=9 -entity.3192=[0] -entity.3193=[1] -entity.3194=[2] -entity.3195=[3] -entity.3196=[1] -entity.3197=[2] -entity.3198=[3] -entity.3302=0 -entity.3303=1 -entity.3304=2 -entity.3305=3 -entity.3306=4 -entity.3307=5 -entity.3308=6 -entity.3309=7 -entity.3310=8 -entity.3311=9 -entity.3430=0 -entity.3431=1 -entity.3432=2 -entity.3433=3 -entity.3434=4 -entity.3435=5 -entity.3436=6 -entity.3437=7 -entity.3438=8 -entity.3439=9 -entity.3440=[10] -entity.3441=[100] -entity.3442=[1000] -entity.3443=[1/4] -entity.3444=[1/2] -entity.3445=[3/4] -entity.3558=0 -entity.3559=1 -entity.3560=2 -entity.3561=3 -entity.3562=4 -entity.3563=5 -entity.3564=6 -entity.3565=7 -entity.3566=8 -entity.3567=9 -entity.3664=0 -entity.3665=1 -entity.3666=2 -entity.3667=3 -entity.3668=4 -entity.3669=5 -entity.3670=6 -entity.3671=7 -entity.3672=8 -entity.3673=9 -entity.3792=0 -entity.3793=1 -entity.3794=2 -entity.3795=3 -entity.3796=4 -entity.3797=5 -entity.3798=6 -entity.3799=7 -entity.3800=8 -entity.3801=9 -entity.3872=0 -entity.3873=1 -entity.3874=2 -entity.3875=3 -entity.3876=4 -entity.3877=5 -entity.3878=6 -entity.3879=7 -entity.3880=8 -entity.3881=9 -entity.3882=[1/2] -entity.3883=[3/2] -entity.3884=[5/2] -entity.3885=[7/2] -entity.3886=[9/2] -entity.3887=[11/2] -entity.3888=[13/2] -entity.3889=[15/2] -entity.3890=[17/2] -entity.3891=[-1/2] -entity.4160=0 -entity.4161=1 -entity.4162=2 -entity.4163=3 -entity.4164=4 -entity.4165=5 -entity.4166=6 -entity.4167=7 -entity.4168=8 -entity.4169=9 -entity.4240=0 -entity.4241=1 -entity.4242=2 -entity.4243=3 -entity.4244=4 -entity.4245=5 -entity.4246=6 -entity.4247=7 -entity.4248=8 -entity.4249=9 -entity.4969=[1] -entity.4970=[2] -entity.4971=[3] -entity.4972=[4] -entity.4973=[5] -entity.4974=[6] -entity.4975=[7] -entity.4976=[8] -entity.4977=[9] -entity.4978=[10] -entity.4979=[20] -entity.4980=[30] -entity.4981=[40] -entity.4982=[50] -entity.4983=[60] -entity.4984=[70] -entity.4985=[80] -entity.4986=[90] -entity.4987=[100] -entity.4988=[10000] -entity.5870=[17] -entity.5871=[18] -entity.5872=[19] -entity.6112=0 -entity.6113=1 -entity.6114=2 -entity.6115=3 -entity.6116=4 -entity.6117=5 -entity.6118=6 -entity.6119=7 -entity.6120=8 -entity.6121=9 -entity.6128=[0] -entity.6129=[1] -entity.6130=[2] -entity.6131=[3] -entity.6132=[4] -entity.6133=[5] -entity.6134=[6] -entity.6135=[7] -entity.6136=[8] -entity.6137=[9] -entity.6160=0 -entity.6161=1 -entity.6162=2 -entity.6163=3 -entity.6164=4 -entity.6165=5 -entity.6166=6 -entity.6167=7 -entity.6168=8 -entity.6169=9 -entity.6470=0 -entity.6471=1 -entity.6472=2 -entity.6473=3 -entity.6474=4 -entity.6475=5 -entity.6476=6 -entity.6477=7 -entity.6478=8 -entity.6479=9 -entity.6608=0 -entity.6609=1 -entity.6610=2 -entity.6611=3 -entity.6612=4 -entity.6613=5 -entity.6614=6 -entity.6615=7 -entity.6616=8 -entity.6617=9 -entity.6618=[1] -entity.6784=0 -entity.6785=1 -entity.6786=2 -entity.6787=3 -entity.6788=4 -entity.6789=5 -entity.6790=6 -entity.6791=7 -entity.6792=8 -entity.6793=9 -entity.6800=0 -entity.6801=1 -entity.6802=2 -entity.6803=3 -entity.6804=4 -entity.6805=5 -entity.6806=6 -entity.6807=7 -entity.6808=8 -entity.6809=9 -entity.6992=0 -entity.6993=1 -entity.6994=2 -entity.6995=3 -entity.6996=4 -entity.6997=5 -entity.6998=6 -entity.6999=7 -entity.7000=8 -entity.7001=9 -entity.7088=0 -entity.7089=1 -entity.7090=2 -entity.7091=3 -entity.7092=4 -entity.7093=5 -entity.7094=6 -entity.7095=7 -entity.7096=8 -entity.7097=9 -entity.7232=0 -entity.7233=1 -entity.7234=2 -entity.7235=3 -entity.7236=4 -entity.7237=5 -entity.7238=6 -entity.7239=7 -entity.7240=8 -entity.7241=9 -entity.7248=0 -entity.7249=1 -entity.7250=2 -entity.7251=3 -entity.7252=4 -entity.7253=5 -entity.7254=6 -entity.7255=7 -entity.7256=8 -entity.7257=9 -entity.7468=^(A) -entity.7470=^(B) -entity.7472=^(D) -entity.7473=^(E) -entity.7475=^(G) -entity.7476=^(H) -entity.7477=^(I) -entity.7478=^(J) -entity.7479=^(K) -entity.7480=^(L) -entity.7481=^(M) -entity.7482=^(N) -entity.7484=^(O) -entity.7486=^(P) -entity.7487=^(R) -entity.7488=^(T) -entity.7489=^(U) -entity.7490=^(W) -entity.7491=^(a) -entity.7495=^(b) -entity.7496=^(d) -entity.7497=^(e) -entity.7501=^(g) -entity.7503=^(k) -entity.7504=^(m) -entity.7506=^(o) -entity.7510=^(p) -entity.7511=^(t) -entity.7512=^(u) -entity.7515=^(v) -entity.7522=v(i) -entity.7523=v(r) -entity.7524=v(u) -entity.7525=v(v) -entity.7580=^(c) -entity.7584=^(f) -entity.7611=^(z) -entity.7680=A* -entity.7681=a* -entity.7682=B. -entity.7683=b. -entity.7684=B. -entity.7685=b. -entity.7686=B_ -entity.7687=b_ -entity.7688=C,' -entity.7689=c,' -entity.7690=D. -entity.7691=d. -entity.7692=D. -entity.7693=d. -entity.7694=D_ -entity.7695=d_ -entity.7696=D, -entity.7697=d, -entity.7698=D^ -entity.7699=d^ -entity.7700=E-` -entity.7701=e-` -entity.7702=E-' -entity.7703=e-' -entity.7704=E^ -entity.7705=e^ -entity.7706=E~ -entity.7707=e~ -entity.7708=E,( -entity.7709=e,( -entity.7710=F. -entity.7711=f. -entity.7712=G- -entity.7713=g- -entity.7714=H. -entity.7715=h. -entity.7716=H. -entity.7717=h. -entity.7718=H" -entity.7719=h" -entity.7720=H, -entity.7721=h, -entity.7722=H( -entity.7723=h( -entity.7724=I~ -entity.7725=i~ -entity.7726=I"' -entity.7727=i"' -entity.7728=K' -entity.7729=k' -entity.7730=K. -entity.7731=k. -entity.7732=K_ -entity.7733=k_ -entity.7734=L. -entity.7735=l. -entity.7736=L.- -entity.7737=l.- -entity.7738=L_ -entity.7739=l_ -entity.7740=L^ -entity.7741=l^ -entity.7742=M' -entity.7743=m' -entity.7744=M. -entity.7745=m. -entity.7746=M. -entity.7747=m. -entity.7748=N. -entity.7749=n. -entity.7750=N. -entity.7751=n. -entity.7752=N_ -entity.7753=n_ -entity.7754=N^ -entity.7755=n^ -entity.7756=O~' -entity.7757=o~' -entity.7758=O~" -entity.7759=o~" -entity.7760=O-` -entity.7761=o-` -entity.7762=O-' -entity.7763=o-' -entity.7764=P' -entity.7765=p' -entity.7766=P. -entity.7767=p. -entity.7768=R. -entity.7769=r. -entity.7770=R. -entity.7771=r. -entity.7772=R.- -entity.7773=r.- -entity.7774=R_ -entity.7775=r_ -entity.7776=S. -entity.7777=s. -entity.7778=S. -entity.7779=s. -entity.7780=S'. -entity.7781=s'. -entity.7782=S(. -entity.7783=s(. -entity.7784=S.. -entity.7785=s.. -entity.7786=T. -entity.7787=t. -entity.7788=T. -entity.7789=t. -entity.7790=T_ -entity.7791=t_ -entity.7792=T^ -entity.7793=t^ -entity.7794=U" -entity.7795=u" -entity.7796=U~ -entity.7797=u~ -entity.7798=U^ -entity.7799=u^ -entity.7800=U~' -entity.7801=u~' -entity.7802=U-" -entity.7803=u-" -entity.7804=V~ -entity.7805=v~ -entity.7806=V. -entity.7807=v. -entity.7808=W` -entity.7809=w` -entity.7810=W' -entity.7811=w' -entity.7812=W" -entity.7813=w" -entity.7814=W. -entity.7815=w. -entity.7816=W. -entity.7817=w. -entity.7818=X. -entity.7819=x. -entity.7820=X" -entity.7821=x" -entity.7822=Y. -entity.7823=y. -entity.7824=Z^ -entity.7825=z^ -entity.7826=Z. -entity.7827=z. -entity.7828=Z_ -entity.7829=z_ -entity.7830=h_ -entity.7831=t" -entity.7832=w* -entity.7833=y* -entity.7834=a* -entity.7840=A. -entity.7841=a. -entity.7842=A? -entity.7843=a? -entity.7844=A^' -entity.7845=a^' -entity.7846=A^` -entity.7847=a^` -entity.7848=A^? -entity.7849=a^? -entity.7850=A^~ -entity.7851=a^~ -entity.7852=A^. -entity.7853=a^. -entity.7854=A(' -entity.7855=a(' -entity.7856=A(` -entity.7857=a(` -entity.7858=A(? -entity.7859=a(? -entity.7860=A(~ -entity.7861=a(~ -entity.7862=A(. -entity.7863=a(. -entity.7864=E. -entity.7865=e. -entity.7866=E? -entity.7867=e? -entity.7868=E~ -entity.7869=e~ -entity.7870=E^' -entity.7871=e^' -entity.7872=E^` -entity.7873=e^` -entity.7874=E^? -entity.7875=e^? -entity.7876=E^~ -entity.7877=e^~ -entity.7878=E^. -entity.7879=e^. -entity.7880=I? -entity.7881=i? -entity.7882=I. -entity.7883=i. -entity.7884=O. -entity.7885=o. -entity.7886=O? -entity.7887=o? -entity.7888=O^' -entity.7889=o^' -entity.7890=O^` -entity.7891=o^` -entity.7892=O^? -entity.7893=o^? -entity.7894=O^~ -entity.7895=o^~ -entity.7896=O^. -entity.7897=o^. -entity.7898=O+' -entity.7899=o+' -entity.7900=O+` -entity.7901=o+` -entity.7902=O+? -entity.7903=o+? -entity.7904=O+~ -entity.7905=o+~ -entity.7906=O+. -entity.7907=o+. -entity.7908=U. -entity.7909=u. -entity.7910=U? -entity.7911=u? -entity.7912=U+' -entity.7913=u+' -entity.7914=U+` -entity.7915=u+` -entity.7916=U+? -entity.7917=u+? -entity.7918=U+~ -entity.7919=u+~ -entity.7920=U+. -entity.7921=u+. -entity.7922=Y` -entity.7923=y` -entity.7924=Y. -entity.7925=y. -entity.7926=Y? -entity.7927=y? -entity.7928=Y~ -entity.7929=y~ -entity.8194=\u0020 -entity.8195=\u0020 -entity.8196=\u0020 -entity.8197=\u0020 -entity.8198=\u0020 -entity.8199=\u0020 -entity.8200=\u0020 -entity.8201=\u0020 -entity.8202=\u0020 -entity.8228=. -entity.8229=.. -entity.8230=... -entity.8239=\u0020 -entity.8252=!! -entity.8263=?? -entity.8264=?! -entity.8265=!? -entity.8287=\u0020 -entity.8304=^(0) -entity.8305=^(i) -entity.8308=^(4) -entity.8309=^(5) -entity.8310=^(6) -entity.8311=^(7) -entity.8312=^(8) -entity.8313=^(9) -entity.8314=^(+) -entity.8316=^(=) -entity.8317=^(() -entity.8318=^()) -entity.8319=^(n) -entity.8320=v(0) -entity.8321=v(1) -entity.8322=v(2) -entity.8323=v(3) -entity.8324=v(4) -entity.8325=v(5) -entity.8326=v(6) -entity.8327=v(7) -entity.8328=v(8) -entity.8329=v(9) -entity.8330=v(+) -entity.8332=v(=) -entity.8333=v(() -entity.8334=v()) -entity.8336=v(a) -entity.8337=v(e) -entity.8338=v(o) -entity.8339=v(x) -entity.8340=schwa -entity.8341=v(h) -entity.8342=v(k) -entity.8343=v(l) -entity.8344=v(m) -entity.8345=v(n) -entity.8346=v(p) -entity.8347=v(s) -entity.8348=v(t) -entity.8360=Rs -entity.8448=a/c -entity.8449=a/s -entity.8450=C -entity.8453=c/o -entity.8454=c/u -entity.8458=g -entity.8459=H -entity.8460=H -entity.8461=H -entity.8462=h -entity.8464=I -entity.8465=I -entity.8466=L -entity.8467=l -entity.8469=N -entity.8470=No -entity.8473=P -entity.8474=Q -entity.8475=R -entity.8476=R -entity.8477=R -entity.8480=^(SM) -entity.8481=TEL -entity.8482=^(TM) -entity.8484=Z -entity.8488=Z -entity.8492=B -entity.8493=C -entity.8495=e -entity.8496=E -entity.8497=F -entity.8499=M -entity.8500=o -entity.8505=i -entity.8507=FAX -entity.8517=D -entity.8518=d -entity.8519=e -entity.8520=i -entity.8521=j -entity.8528=1/7 -entity.8529=1/9 -entity.8530=1/10 -entity.8531=1/3 -entity.8532=2/3 -entity.8533=1/5 -entity.8534=2/5 -entity.8535=3/5 -entity.8536=4/5 -entity.8537=1/6 -entity.8538=5/6 -entity.8539=1/8 -entity.8540=3/8 -entity.8541=5/8 -entity.8542=7/8 -entity.8543=1/ -entity.8544=I -entity.8545=II -entity.8546=III -entity.8547=IV -entity.8548=V -entity.8549=VI -entity.8550=VII -entity.8551=VIII -entity.8552=IX -entity.8553=X -entity.8554=XI -entity.8555=XII -entity.8556=L -entity.8557=C -entity.8558=D -entity.8559=M -entity.8560=i -entity.8561=ii -entity.8562=iii -entity.8563=iv -entity.8564=v -entity.8565=vi -entity.8566=vii -entity.8567=viii -entity.8568=ix -entity.8569=x -entity.8570=xi -entity.8571=xii -entity.8572=l -entity.8573=c -entity.8574=d -entity.8575=m -entity.8576=[1000] -entity.8577=[5000] -entity.8578=[10000] -entity.8581=[6] -entity.8582=[50] -entity.8583=[50000] -entity.8584=[100000] -entity.8585=0/3 -entity.9312=(1) -entity.9313=(2) -entity.9314=(3) -entity.9315=(4) -entity.9316=(5) -entity.9317=(6) -entity.9318=(7) -entity.9319=(8) -entity.9320=(9) -entity.9321=(10) -entity.9322=(11) -entity.9323=(12) -entity.9324=(13) -entity.9325=(14) -entity.9326=(15) -entity.9327=(16) -entity.9328=(17) -entity.9329=(18) -entity.9330=(19) -entity.9331=(20) -entity.9332=(1) -entity.9333=(2) -entity.9334=(3) -entity.9335=(4) -entity.9336=(5) -entity.9337=(6) -entity.9338=(7) -entity.9339=(8) -entity.9340=(9) -entity.9341=(10) -entity.9342=(11) -entity.9343=(12) -entity.9344=(13) -entity.9345=(14) -entity.9346=(15) -entity.9347=(16) -entity.9348=(17) -entity.9349=(18) -entity.9350=(19) -entity.9351=(20) -entity.9352=1. -entity.9353=2. -entity.9354=3. -entity.9355=4. -entity.9356=5. -entity.9357=6. -entity.9358=7. -entity.9359=8. -entity.9360=9. -entity.9361=10. -entity.9362=11. -entity.9363=12. -entity.9364=13. -entity.9365=14. -entity.9366=15. -entity.9367=16. -entity.9368=17. -entity.9369=18. -entity.9370=19. -entity.9371=20. -entity.9372=(a) -entity.9373=(b) -entity.9374=(c) -entity.9375=(d) -entity.9376=(e) -entity.9377=(f) -entity.9378=(g) -entity.9379=(h) -entity.9380=(i) -entity.9381=(j) -entity.9382=(k) -entity.9383=(l) -entity.9384=(m) -entity.9385=(n) -entity.9386=(o) -entity.9387=(p) -entity.9388=(q) -entity.9389=(r) -entity.9390=(s) -entity.9391=(t) -entity.9392=(u) -entity.9393=(v) -entity.9394=(w) -entity.9395=(x) -entity.9396=(y) -entity.9397=(z) -entity.9398=(A) -entity.9399=(B) -entity.9400=(C) -entity.9401=(D) -entity.9402=(E) -entity.9403=(F) -entity.9404=(G) -entity.9405=(H) -entity.9406=(I) -entity.9407=(J) -entity.9408=(K) -entity.9409=(L) -entity.9410=(M) -entity.9411=(N) -entity.9412=(O) -entity.9413=(P) -entity.9414=(Q) -entity.9415=(R) -entity.9416=(S) -entity.9417=(T) -entity.9418=(U) -entity.9419=(V) -entity.9420=(W) -entity.9421=(X) -entity.9422=(Y) -entity.9423=(Z) -entity.9424=(a) -entity.9425=(b) -entity.9426=(c) -entity.9427=(d) -entity.9428=(e) -entity.9429=(f) -entity.9430=(g) -entity.9431=(h) -entity.9432=(i) -entity.9433=(j) -entity.9434=(k) -entity.9435=(l) -entity.9436=(m) -entity.9437=(n) -entity.9438=(o) -entity.9439=(p) -entity.9440=(q) -entity.9441=(r) -entity.9442=(s) -entity.9443=(t) -entity.9444=(u) -entity.9445=(v) -entity.9446=(w) -entity.9447=(x) -entity.9448=(y) -entity.9449=(z) -entity.9450=(0) -entity.9451=(11) -entity.9452=(12) -entity.9453=(13) -entity.9454=(14) -entity.9455=(15) -entity.9456=(16) -entity.9457=(17) -entity.9458=(18) -entity.9459=(19) -entity.9460=(20) -entity.9461=(1) -entity.9462=(2) -entity.9463=(3) -entity.9464=(4) -entity.9465=(5) -entity.9466=(6) -entity.9467=(7) -entity.9468=(8) -entity.9469=(9) -entity.9470=(10) -entity.9471=(0) -entity.10102=(1) -entity.10103=(2) -entity.10104=(3) -entity.10105=(4) -entity.10106=(5) -entity.10107=(6) -entity.10108=(7) -entity.10109=(8) -entity.10110=(9) -entity.10111=(10) -entity.10112=(1) -entity.10113=(2) -entity.10114=(3) -entity.10115=(4) -entity.10116=(5) -entity.10117=(6) -entity.10118=(7) -entity.10119=(8) -entity.10120=(9) -entity.10121=(10) -entity.10122=(1) -entity.10123=(2) -entity.10124=(3) -entity.10125=(4) -entity.10126=(5) -entity.10127=(6) -entity.10128=(7) -entity.10129=(8) -entity.10130=(9) -entity.10131=(10) -entity.10868=::= -entity.10869=== -entity.10870==== -entity.11388=v(j) -entity.11389=^(V) -entity.11517=[1/2] -entity.12288=\u0020 -entity.12295=[0] -entity.12321=[1] -entity.12322=[2] -entity.12323=[3] -entity.12324=[4] -entity.12325=[5] -entity.12326=[6] -entity.12327=[7] -entity.12328=[8] -entity.12329=[9] -entity.12872=(10) -entity.12873=(20) -entity.12874=(30) -entity.12875=(40) -entity.12876=(50) -entity.12877=(60) -entity.12878=(70) -entity.12879=(80) -entity.12881=(21) -entity.12882=(22) -entity.12883=(23) -entity.12884=(24) -entity.12885=(25) -entity.12886=(26) -entity.12887=(27) -entity.12888=(28) -entity.12889=(29) -entity.12890=(30) -entity.12891=(31) -entity.12892=(32) -entity.12893=(33) -entity.12894=(34) -entity.12895=(35) -entity.12977=(36) -entity.12978=(37) -entity.12979=(38) -entity.12980=(39) -entity.12981=(40) -entity.12982=(41) -entity.12983=(42) -entity.12984=(43) -entity.12985=(44) -entity.12986=(45) -entity.12987=(46) -entity.12988=(47) -entity.12989=(48) -entity.12990=(49) -entity.12991=(50) -entity.42528=0 -entity.42529=1 -entity.42530=2 -entity.42531=3 -entity.42532=4 -entity.42533=5 -entity.42534=6 -entity.42535=7 -entity.42536=8 -entity.42537=9 -entity.42726=[1] -entity.42727=[2] -entity.42728=[3] -entity.42729=[4] -entity.42730=[5] -entity.42731=[6] -entity.42732=[7] -entity.42733=[8] -entity.42734=[9] -entity.42735=[0] -entity.43056=[1/4] -entity.43057=[1/2] -entity.43058=[3/4] -entity.43059=[1/16] -entity.43060=[1/8] -entity.43061=[3/16] -entity.43216=0 -entity.43217=1 -entity.43218=2 -entity.43219=3 -entity.43220=4 -entity.43221=5 -entity.43222=6 -entity.43223=7 -entity.43224=8 -entity.43225=9 -entity.43264=0 -entity.43265=1 -entity.43266=2 -entity.43267=3 -entity.43268=4 -entity.43269=5 -entity.43270=6 -entity.43271=7 -entity.43272=8 -entity.43273=9 -entity.43472=0 -entity.43473=1 -entity.43474=2 -entity.43475=3 -entity.43476=4 -entity.43477=5 -entity.43478=6 -entity.43479=7 -entity.43480=8 -entity.43481=9 -entity.43504=0 -entity.43505=1 -entity.43506=2 -entity.43507=3 -entity.43508=4 -entity.43509=5 -entity.43510=6 -entity.43511=7 -entity.43512=8 -entity.43513=9 -entity.43600=0 -entity.43601=1 -entity.43602=2 -entity.43603=3 -entity.43604=4 -entity.43605=5 -entity.43606=6 -entity.43607=7 -entity.43608=8 -entity.43609=9 -entity.44016=0 -entity.44017=1 -entity.44018=2 -entity.44019=3 -entity.44020=4 -entity.44021=5 -entity.44022=6 -entity.44023=7 -entity.44024=8 -entity.44025=9 -entity.64256=ff -entity.64257=fi -entity.64258=fl -entity.64259=ffi -entity.64260=ffl -entity.64262=st -entity.64297=+ -entity.65101=_ -entity.65102=_ -entity.65103=_ -entity.65104=, -entity.65106=. -entity.65108=; -entity.65109=: -entity.65110=? -entity.65111=! -entity.65113=( -entity.65114=) -entity.65115={ -entity.65116=} -entity.65119=# -entity.65120=& -entity.65121=* -entity.65122=+ -entity.65123=- -entity.65124=< -entity.65125=> -entity.65126== -entity.65128=\u005C -entity.65129=$ -entity.65130=% -entity.65131=@ -entity.65281=! -entity.65282=" -entity.65283=# -entity.65284=$ -entity.65285=% -entity.65286=& -entity.65287=' -entity.65288=( -entity.65289=) -entity.65290=* -entity.65291=+ -entity.65292=, -entity.65293=- -entity.65294=. -entity.65295=/ -entity.65296=0 -entity.65297=1 -entity.65298=2 -entity.65299=3 -entity.65300=4 -entity.65301=5 -entity.65302=6 -entity.65303=7 -entity.65304=8 -entity.65305=9 -entity.65306=: -entity.65307=; -entity.65308=< -entity.65309== -entity.65310=> -entity.65311=? -entity.65312=@ -entity.65313=A -entity.65314=B -entity.65315=C -entity.65316=D -entity.65317=E -entity.65318=F -entity.65319=G -entity.65320=H -entity.65321=I -entity.65322=J -entity.65323=K -entity.65324=L -entity.65325=M -entity.65326=N -entity.65327=O -entity.65328=P -entity.65329=Q -entity.65330=R -entity.65331=S -entity.65332=T -entity.65333=U -entity.65334=V -entity.65335=W -entity.65336=X -entity.65337=Y -entity.65338=Z -entity.65339=[ -entity.65340=\u005C -entity.65341=] -entity.65342=^ -entity.65343=_ -entity.65344=` -entity.65345=a -entity.65346=b -entity.65347=c -entity.65348=d -entity.65349=e -entity.65350=f -entity.65351=g -entity.65352=h -entity.65353=i -entity.65354=j -entity.65355=k -entity.65356=l -entity.65357=m -entity.65358=n -entity.65359=o -entity.65360=p -entity.65361=q -entity.65362=r -entity.65363=s -entity.65364=t -entity.65365=u -entity.65366=v -entity.65367=w -entity.65368=x -entity.65369=y -entity.65370=z -entity.65371={ -entity.65372=| -entity.65373=} -entity.65374=~ -entity.65799=[1] -entity.65800=[2] -entity.65801=[3] -entity.65802=[4] -entity.65803=[5] -entity.65804=[6] -entity.65805=[7] -entity.65806=[8] -entity.65807=[9] -entity.65808=[10] -entity.65809=[20] -entity.65810=[30] -entity.65811=[40] -entity.65812=[50] -entity.65813=[60] -entity.65814=[70] -entity.65815=[80] -entity.65816=[90] -entity.65817=[100] -entity.65818=[200] -entity.65819=[300] -entity.65820=[400] -entity.65821=[500] -entity.65822=[600] -entity.65823=[700] -entity.65824=[800] -entity.65825=[900] -entity.65826=[1000] -entity.65827=[2000] -entity.65828=[3000] -entity.65829=[4000] -entity.65830=[5000] -entity.65831=[6000] -entity.65832=[7000] -entity.65833=[8000] -entity.65834=[9000] -entity.65835=[10000] -entity.65836=[20000] -entity.65837=[30000] -entity.65838=[40000] -entity.65839=[50000] -entity.65840=[60000] -entity.65841=[70000] -entity.65842=[80000] -entity.65843=[90000] -entity.65856=[1/4] -entity.65857=[1/2] -entity.65858=[1] -entity.65859=[5] -entity.65860=[50] -entity.65861=[500] -entity.65862=[5000] -entity.65863=[50000] -entity.65864=[5] -entity.65865=[10] -entity.65866=[50] -entity.65867=[100] -entity.65868=[500] -entity.65869=[1000] -entity.65870=[5000] -entity.65871=[5] -entity.65872=[10] -entity.65873=[50] -entity.65874=[100] -entity.65875=[500] -entity.65876=[1000] -entity.65877=[10000] -entity.65878=[50000] -entity.65879=[10] -entity.65880=[1] -entity.65881=[1] -entity.65882=[1] -entity.65883=[2] -entity.65884=[2] -entity.65885=[2] -entity.65886=[2] -entity.65887=[5] -entity.65888=[10] -entity.65889=[10] -entity.65890=[10] -entity.65891=[10] -entity.65892=[10] -entity.65893=[30] -entity.65894=[50] -entity.65895=[50] -entity.65896=[50] -entity.65897=[50] -entity.65898=[100] -entity.65899=[300] -entity.65900=[500] -entity.65901=[500] -entity.65902=[500] -entity.65903=[500] -entity.65904=[500] -entity.65905=[1000] -entity.65906=[5000] -entity.65907=[5] -entity.65908=[50] -entity.65909=[1/2] -entity.65910=[1/2] -entity.65911=[2/3] -entity.65912=[3/4] -entity.65930=[0] -entity.65931=[1/4] -entity.66273=[1] -entity.66274=[2] -entity.66275=[3] -entity.66276=[4] -entity.66277=[5] -entity.66278=[6] -entity.66279=[7] -entity.66280=[8] -entity.66281=[9] -entity.66282=[10] -entity.66283=[20] -entity.66284=[30] -entity.66285=[40] -entity.66286=[50] -entity.66287=[60] -entity.66288=[70] -entity.66289=[80] -entity.66290=[90] -entity.66291=[100] -entity.66292=[200] -entity.66293=[300] -entity.66294=[400] -entity.66295=[500] -entity.66296=[600] -entity.66297=[700] -entity.66298=[800] -entity.66299=[900] -entity.66336=[1] -entity.66337=[5] -entity.66338=[10] -entity.66339=[50] -entity.66369=[90] -entity.66378=[900] -entity.66513=[1] -entity.66514=[2] -entity.66515=[10] -entity.66516=[20] -entity.66517=[100] -entity.66720=0 -entity.66721=1 -entity.66722=2 -entity.66723=3 -entity.66724=4 -entity.66725=5 -entity.66726=6 -entity.66727=7 -entity.66728=8 -entity.66729=9 -entity.67672=[1] -entity.67673=[2] -entity.67674=[3] -entity.67675=[10] -entity.67676=[20] -entity.67677=[100] -entity.67678=[1000] -entity.67679=[10000] -entity.67705=[1] -entity.67706=[2] -entity.67707=[3] -entity.67708=[4] -entity.67709=[5] -entity.67710=[10] -entity.67711=[20] -entity.67751=[1] -entity.67752=[2] -entity.67753=[3] -entity.67754=[4] -entity.67755=[4] -entity.67756=[5] -entity.67757=[10] -entity.67758=[20] -entity.67759=[100] -entity.67862=[1] -entity.67863=[10] -entity.67864=[20] -entity.67865=[100] -entity.67866=[2] -entity.67867=[3] -entity.68160=[1] -entity.68161=[2] -entity.68162=[3] -entity.68163=[4] -entity.68164=[10] -entity.68165=[20] -entity.68166=[100] -entity.68167=[1000] -entity.68221=[1] -entity.68222=[50] -entity.68253=[1] -entity.68254=[10] -entity.68255=[20] -entity.68331=[1] -entity.68332=[5] -entity.68333=[10] -entity.68334=[20] -entity.68335=[100] -entity.68440=[1] -entity.68441=[2] -entity.68442=[3] -entity.68443=[4] -entity.68444=[10] -entity.68445=[20] -entity.68446=[100] -entity.68447=[1000] -entity.68472=[1] -entity.68473=[2] -entity.68474=[3] -entity.68475=[4] -entity.68476=[10] -entity.68477=[20] -entity.68478=[100] -entity.68479=[1000] -entity.68521=[1] -entity.68522=[2] -entity.68523=[3] -entity.68524=[4] -entity.68525=[10] -entity.68526=[20] -entity.68527=[100] -entity.69216=[1] -entity.69217=[2] -entity.69218=[3] -entity.69219=[4] -entity.69220=[5] -entity.69221=[6] -entity.69222=[7] -entity.69223=[8] -entity.69224=[9] -entity.69225=[10] -entity.69226=[20] -entity.69227=[30] -entity.69228=[40] -entity.69229=[50] -entity.69230=[60] -entity.69231=[70] -entity.69232=[80] -entity.69233=[90] -entity.69234=[100] -entity.69235=[200] -entity.69236=[300] -entity.69237=[400] -entity.69238=[500] -entity.69239=[600] -entity.69240=[700] -entity.69241=[800] -entity.69242=[900] -entity.69243=[1/2] -entity.69244=[1/4] -entity.69245=[1/3] -entity.69246=[2/3] -entity.69714=[1] -entity.69715=[2] -entity.69716=[3] -entity.69717=[4] -entity.69718=[5] -entity.69719=[6] -entity.69720=[7] -entity.69721=[8] -entity.69722=[9] -entity.69723=[10] -entity.69724=[20] -entity.69725=[30] -entity.69726=[40] -entity.69727=[50] -entity.69728=[60] -entity.69729=[70] -entity.69730=[80] -entity.69731=[90] -entity.69732=[100] -entity.69733=[1000] -entity.69734=0 -entity.69735=1 -entity.69736=2 -entity.69737=3 -entity.69738=4 -entity.69739=5 -entity.69740=6 -entity.69741=7 -entity.69742=8 -entity.69743=9 -entity.69872=0 -entity.69873=1 -entity.69874=2 -entity.69875=3 -entity.69876=4 -entity.69877=5 -entity.69878=6 -entity.69879=7 -entity.69880=8 -entity.69881=9 -entity.69942=0 -entity.69943=1 -entity.69944=2 -entity.69945=3 -entity.69946=4 -entity.69947=5 -entity.69948=6 -entity.69949=7 -entity.69950=8 -entity.69951=9 -entity.70096=0 -entity.70097=1 -entity.70098=2 -entity.70099=3 -entity.70100=4 -entity.70101=5 -entity.70102=6 -entity.70103=7 -entity.70104=8 -entity.70105=9 -entity.70113=[1] -entity.70114=[2] -entity.70115=[3] -entity.70116=[4] -entity.70117=[5] -entity.70118=[6] -entity.70119=[7] -entity.70120=[8] -entity.70121=[9] -entity.70122=[10] -entity.70123=[20] -entity.70124=[30] -entity.70125=[40] -entity.70126=[50] -entity.70127=[60] -entity.70128=[70] -entity.70129=[80] -entity.70130=[90] -entity.70131=[100] -entity.70132=[1000] -entity.70384=0 -entity.70385=1 -entity.70386=2 -entity.70387=3 -entity.70388=4 -entity.70389=5 -entity.70390=6 -entity.70391=7 -entity.70392=8 -entity.70393=9 -entity.70864=0 -entity.70865=1 -entity.70866=2 -entity.70867=3 -entity.70868=4 -entity.70869=5 -entity.70870=6 -entity.70871=7 -entity.70872=8 -entity.70873=9 -entity.71248=0 -entity.71249=1 -entity.71250=2 -entity.71251=3 -entity.71252=4 -entity.71253=5 -entity.71254=6 -entity.71255=7 -entity.71256=8 -entity.71257=9 -entity.71360=0 -entity.71361=1 -entity.71362=2 -entity.71363=3 -entity.71364=4 -entity.71365=5 -entity.71366=6 -entity.71367=7 -entity.71368=8 -entity.71369=9 -entity.71904=0 -entity.71905=1 -entity.71906=2 -entity.71907=3 -entity.71908=4 -entity.71909=5 -entity.71910=6 -entity.71911=7 -entity.71912=8 -entity.71913=9 -entity.71914=[10] -entity.71915=[20] -entity.71916=[30] -entity.71917=[40] -entity.71918=[50] -entity.71919=[60] -entity.71920=[70] -entity.71921=[80] -entity.71922=[90] -entity.74752=[2] -entity.74753=[3] -entity.74754=[4] -entity.74755=[5] -entity.74756=[6] -entity.74757=[7] -entity.74758=[8] -entity.74759=[9] -entity.74760=[3] -entity.74761=[4] -entity.74762=[5] -entity.74763=[6] -entity.74764=[7] -entity.74765=[8] -entity.74766=[9] -entity.74767=[4] -entity.74768=[5] -entity.74769=[6] -entity.74770=[7] -entity.74771=[8] -entity.74772=[9] -entity.74773=[1] -entity.74774=[2] -entity.74775=[3] -entity.74776=[4] -entity.74777=[5] -entity.74778=[6] -entity.74779=[7] -entity.74780=[8] -entity.74781=[9] -entity.74782=[1] -entity.74783=[2] -entity.74784=[3] -entity.74785=[4] -entity.74786=[5] -entity.74787=[2] -entity.74788=[3] -entity.74789=[3] -entity.74790=[4] -entity.74791=[5] -entity.74792=[6] -entity.74793=[7] -entity.74794=[8] -entity.74795=[9] -entity.74796=[1] -entity.74797=[2] -entity.74798=[3] -entity.74799=[3] -entity.74800=[4] -entity.74801=[5] -entity.74802=[216000] -entity.74803=[432000] -entity.74804=[1] -entity.74805=[2] -entity.74806=[3] -entity.74807=[3] -entity.74808=[4] -entity.74809=[5] -entity.74810=[3] -entity.74811=[3] -entity.74812=[4] -entity.74813=[4] -entity.74814=[4] -entity.74815=[4] -entity.74816=[6] -entity.74817=[7] -entity.74818=[7] -entity.74819=[7] -entity.74820=[8] -entity.74821=[8] -entity.74822=[9] -entity.74823=[9] -entity.74824=[9] -entity.74825=[9] -entity.74826=[2] -entity.74827=[3] -entity.74828=[4] -entity.74829=[5] -entity.74830=[6] -entity.74831=[1] -entity.74832=[2] -entity.74833=[3] -entity.74834=[4] -entity.74835=[4] -entity.74836=[5] -entity.74837=[5] -entity.74838=[2] -entity.74839=[3] -entity.74840=[1] -entity.74841=[2] -entity.74842=[1/3] -entity.74843=[2/3] -entity.74844=[5/6] -entity.74845=[1/3] -entity.74846=[2/3] -entity.74847=[1/8] -entity.74848=[1/4] -entity.74849=[1/6] -entity.74850=[1/4] -entity.74851=[1/4] -entity.74852=[1/2] -entity.74853=[1/3] -entity.74854=[2/3] -entity.74855=[40] -entity.74856=[50] -entity.74857=[4] -entity.74858=[5] -entity.74859=[6] -entity.74860=[7] -entity.74861=[8] -entity.74862=[9] -entity.92768=0 -entity.92769=1 -entity.92770=2 -entity.92771=3 -entity.92772=4 -entity.92773=5 -entity.92774=6 -entity.92775=7 -entity.92776=8 -entity.92777=9 -entity.93008=0 -entity.93009=1 -entity.93010=2 -entity.93011=3 -entity.93012=4 -entity.93013=5 -entity.93014=6 -entity.93015=7 -entity.93016=8 -entity.93017=9 -entity.93019=[10] -entity.93020=[100] -entity.93021=[10000] -entity.93022=[1000000] -entity.93023=[100000000] -entity.93024=[10000000000] -entity.93025=[1000000000000] -entity.119648=[1] -entity.119649=[2] -entity.119650=[3] -entity.119651=[4] -entity.119652=[5] -entity.119653=[6] -entity.119654=[7] -entity.119655=[8] -entity.119656=[9] -entity.119657=[10] -entity.119658=[20] -entity.119659=[30] -entity.119660=[40] -entity.119661=[50] -entity.119662=[60] -entity.119663=[70] -entity.119664=[80] -entity.119665=[90] -entity.119808=A -entity.119809=B -entity.119810=C -entity.119811=D -entity.119812=E -entity.119813=F -entity.119814=G -entity.119815=H -entity.119816=I -entity.119817=J -entity.119818=K -entity.119819=L -entity.119820=M -entity.119821=N -entity.119822=O -entity.119823=P -entity.119824=Q -entity.119825=R -entity.119826=S -entity.119827=T -entity.119828=U -entity.119829=V -entity.119830=W -entity.119831=X -entity.119832=Y -entity.119833=Z -entity.119834=a -entity.119835=b -entity.119836=c -entity.119837=d -entity.119838=e -entity.119839=f -entity.119840=g -entity.119841=h -entity.119842=i -entity.119843=j -entity.119844=k -entity.119845=l -entity.119846=m -entity.119847=n -entity.119848=o -entity.119849=p -entity.119850=q -entity.119851=r -entity.119852=s -entity.119853=t -entity.119854=u -entity.119855=v -entity.119856=w -entity.119857=x -entity.119858=y -entity.119859=z -entity.119860=A -entity.119861=B -entity.119862=C -entity.119863=D -entity.119864=E -entity.119865=F -entity.119866=G -entity.119867=H -entity.119868=I -entity.119869=J -entity.119870=K -entity.119871=L -entity.119872=M -entity.119873=N -entity.119874=O -entity.119875=P -entity.119876=Q -entity.119877=R -entity.119878=S -entity.119879=T -entity.119880=U -entity.119881=V -entity.119882=W -entity.119883=X -entity.119884=Y -entity.119885=Z -entity.119886=a -entity.119887=b -entity.119888=c -entity.119889=d -entity.119890=e -entity.119891=f -entity.119892=g -entity.119894=i -entity.119895=j -entity.119896=k -entity.119897=l -entity.119898=m -entity.119899=n -entity.119900=o -entity.119901=p -entity.119902=q -entity.119903=r -entity.119904=s -entity.119905=t -entity.119906=u -entity.119907=v -entity.119908=w -entity.119909=x -entity.119910=y -entity.119911=z -entity.119912=A -entity.119913=B -entity.119914=C -entity.119915=D -entity.119916=E -entity.119917=F -entity.119918=G -entity.119919=H -entity.119920=I -entity.119921=J -entity.119922=K -entity.119923=L -entity.119924=M -entity.119925=N -entity.119926=O -entity.119927=P -entity.119928=Q -entity.119929=R -entity.119930=S -entity.119931=T -entity.119932=U -entity.119933=V -entity.119934=W -entity.119935=X -entity.119936=Y -entity.119937=Z -entity.119938=a -entity.119939=b -entity.119940=c -entity.119941=d -entity.119942=e -entity.119943=f -entity.119944=g -entity.119945=h -entity.119946=i -entity.119947=j -entity.119948=k -entity.119949=l -entity.119950=m -entity.119951=n -entity.119952=o -entity.119953=p -entity.119954=q -entity.119955=r -entity.119956=s -entity.119957=t -entity.119958=u -entity.119959=v -entity.119960=w -entity.119961=x -entity.119962=y -entity.119963=z -entity.119964=A -entity.119966=C -entity.119967=D -entity.119970=G -entity.119973=J -entity.119974=K -entity.119977=N -entity.119978=O -entity.119979=P -entity.119980=Q -entity.119982=S -entity.119983=T -entity.119984=U -entity.119985=V -entity.119986=W -entity.119987=X -entity.119988=Y -entity.119989=Z -entity.119990=a -entity.119991=b -entity.119992=c -entity.119993=d -entity.119995=f -entity.119997=h -entity.119998=i -entity.119999=j -entity.120000=k -entity.120001=l -entity.120002=m -entity.120003=n -entity.120005=p -entity.120006=q -entity.120007=r -entity.120008=s -entity.120009=t -entity.120010=u -entity.120011=v -entity.120012=w -entity.120013=x -entity.120014=y -entity.120015=z -entity.120016=A -entity.120017=B -entity.120018=C -entity.120019=D -entity.120020=E -entity.120021=F -entity.120022=G -entity.120023=H -entity.120024=I -entity.120025=J -entity.120026=K -entity.120027=L -entity.120028=M -entity.120029=N -entity.120030=O -entity.120031=P -entity.120032=Q -entity.120033=R -entity.120034=S -entity.120035=T -entity.120036=U -entity.120037=V -entity.120038=W -entity.120039=X -entity.120040=Y -entity.120041=Z -entity.120042=a -entity.120043=b -entity.120044=c -entity.120045=d -entity.120046=e -entity.120047=f -entity.120048=g -entity.120049=h -entity.120050=i -entity.120051=j -entity.120052=k -entity.120053=l -entity.120054=m -entity.120055=n -entity.120056=o -entity.120057=p -entity.120058=q -entity.120059=r -entity.120060=s -entity.120061=t -entity.120062=u -entity.120063=v -entity.120064=w -entity.120065=x -entity.120066=y -entity.120067=z -entity.120068=A -entity.120069=B -entity.120071=D -entity.120072=E -entity.120073=F -entity.120074=G -entity.120077=J -entity.120078=K -entity.120079=L -entity.120080=M -entity.120081=N -entity.120082=O -entity.120083=P -entity.120084=Q -entity.120086=S -entity.120087=T -entity.120088=U -entity.120089=V -entity.120090=W -entity.120091=X -entity.120092=Y -entity.120094=a -entity.120095=b -entity.120096=c -entity.120097=d -entity.120098=e -entity.120099=f -entity.120100=g -entity.120101=h -entity.120102=i -entity.120103=j -entity.120104=k -entity.120105=l -entity.120106=m -entity.120107=n -entity.120108=o -entity.120109=p -entity.120110=q -entity.120111=r -entity.120112=s -entity.120113=t -entity.120114=u -entity.120115=v -entity.120116=w -entity.120117=x -entity.120118=y -entity.120119=z -entity.120120=A -entity.120121=B -entity.120123=D -entity.120124=E -entity.120125=F -entity.120126=G -entity.120128=I -entity.120129=J -entity.120130=K -entity.120131=L -entity.120132=M -entity.120134=O -entity.120138=S -entity.120139=T -entity.120140=U -entity.120141=V -entity.120142=W -entity.120143=X -entity.120144=Y -entity.120146=a -entity.120147=b -entity.120148=c -entity.120149=d -entity.120150=e -entity.120151=f -entity.120152=g -entity.120153=h -entity.120154=i -entity.120155=j -entity.120156=k -entity.120157=l -entity.120158=m -entity.120159=n -entity.120160=o -entity.120161=p -entity.120162=q -entity.120163=r -entity.120164=s -entity.120165=t -entity.120166=u -entity.120167=v -entity.120168=w -entity.120169=x -entity.120170=y -entity.120171=z -entity.120172=A -entity.120173=B -entity.120174=C -entity.120175=D -entity.120176=E -entity.120177=F -entity.120178=G -entity.120179=H -entity.120180=I -entity.120181=J -entity.120182=K -entity.120183=L -entity.120184=M -entity.120185=N -entity.120186=O -entity.120187=P -entity.120188=Q -entity.120189=R -entity.120190=S -entity.120191=T -entity.120192=U -entity.120193=V -entity.120194=W -entity.120195=X -entity.120196=Y -entity.120197=Z -entity.120198=a -entity.120199=b -entity.120200=c -entity.120201=d -entity.120202=e -entity.120203=f -entity.120204=g -entity.120205=h -entity.120206=i -entity.120207=j -entity.120208=k -entity.120209=l -entity.120210=m -entity.120211=n -entity.120212=o -entity.120213=p -entity.120214=q -entity.120215=r -entity.120216=s -entity.120217=t -entity.120218=u -entity.120219=v -entity.120220=w -entity.120221=x -entity.120222=y -entity.120223=z -entity.120224=A -entity.120225=B -entity.120226=C -entity.120227=D -entity.120228=E -entity.120229=F -entity.120230=G -entity.120231=H -entity.120232=I -entity.120233=J -entity.120234=K -entity.120235=L -entity.120236=M -entity.120237=N -entity.120238=O -entity.120239=P -entity.120240=Q -entity.120241=R -entity.120242=S -entity.120243=T -entity.120244=U -entity.120245=V -entity.120246=W -entity.120247=X -entity.120248=Y -entity.120249=Z -entity.120250=a -entity.120251=b -entity.120252=c -entity.120253=d -entity.120254=e -entity.120255=f -entity.120256=g -entity.120257=h -entity.120258=i -entity.120259=j -entity.120260=k -entity.120261=l -entity.120262=m -entity.120263=n -entity.120264=o -entity.120265=p -entity.120266=q -entity.120267=r -entity.120268=s -entity.120269=t -entity.120270=u -entity.120271=v -entity.120272=w -entity.120273=x -entity.120274=y -entity.120275=z -entity.120276=A -entity.120277=B -entity.120278=C -entity.120279=D -entity.120280=E -entity.120281=F -entity.120282=G -entity.120283=H -entity.120284=I -entity.120285=J -entity.120286=K -entity.120287=L -entity.120288=M -entity.120289=N -entity.120290=O -entity.120291=P -entity.120292=Q -entity.120293=R -entity.120294=S -entity.120295=T -entity.120296=U -entity.120297=V -entity.120298=W -entity.120299=X -entity.120300=Y -entity.120301=Z -entity.120302=a -entity.120303=b -entity.120304=c -entity.120305=d -entity.120306=e -entity.120307=f -entity.120308=g -entity.120309=h -entity.120310=i -entity.120311=j -entity.120312=k -entity.120313=l -entity.120314=m -entity.120315=n -entity.120316=o -entity.120317=p -entity.120318=q -entity.120319=r -entity.120320=s -entity.120321=t -entity.120322=u -entity.120323=v -entity.120324=w -entity.120325=x -entity.120326=y -entity.120327=z -entity.120328=A -entity.120329=B -entity.120330=C -entity.120331=D -entity.120332=E -entity.120333=F -entity.120334=G -entity.120335=H -entity.120336=I -entity.120337=J -entity.120338=K -entity.120339=L -entity.120340=M -entity.120341=N -entity.120342=O -entity.120343=P -entity.120344=Q -entity.120345=R -entity.120346=S -entity.120347=T -entity.120348=U -entity.120349=V -entity.120350=W -entity.120351=X -entity.120352=Y -entity.120353=Z -entity.120354=a -entity.120355=b -entity.120356=c -entity.120357=d -entity.120358=e -entity.120359=f -entity.120360=g -entity.120361=h -entity.120362=i -entity.120363=j -entity.120364=k -entity.120365=l -entity.120366=m -entity.120367=n -entity.120368=o -entity.120369=p -entity.120370=q -entity.120371=r -entity.120372=s -entity.120373=t -entity.120374=u -entity.120375=v -entity.120376=w -entity.120377=x -entity.120378=y -entity.120379=z -entity.120380=A -entity.120381=B -entity.120382=C -entity.120383=D -entity.120384=E -entity.120385=F -entity.120386=G -entity.120387=H -entity.120388=I -entity.120389=J -entity.120390=K -entity.120391=L -entity.120392=M -entity.120393=N -entity.120394=O -entity.120395=P -entity.120396=Q -entity.120397=R -entity.120398=S -entity.120399=T -entity.120400=U -entity.120401=V -entity.120402=W -entity.120403=X -entity.120404=Y -entity.120405=Z -entity.120406=a -entity.120407=b -entity.120408=c -entity.120409=d -entity.120410=e -entity.120411=f -entity.120412=g -entity.120413=h -entity.120414=i -entity.120415=j -entity.120416=k -entity.120417=l -entity.120418=m -entity.120419=n -entity.120420=o -entity.120421=p -entity.120422=q -entity.120423=r -entity.120424=s -entity.120425=t -entity.120426=u -entity.120427=v -entity.120428=w -entity.120429=x -entity.120430=y -entity.120431=z -entity.120432=A -entity.120433=B -entity.120434=C -entity.120435=D -entity.120436=E -entity.120437=F -entity.120438=G -entity.120439=H -entity.120440=I -entity.120441=J -entity.120442=K -entity.120443=L -entity.120444=M -entity.120445=N -entity.120446=O -entity.120447=P -entity.120448=Q -entity.120449=R -entity.120450=S -entity.120451=T -entity.120452=U -entity.120453=V -entity.120454=W -entity.120455=X -entity.120456=Y -entity.120457=Z -entity.120458=a -entity.120459=b -entity.120460=c -entity.120461=d -entity.120462=e -entity.120463=f -entity.120464=g -entity.120465=h -entity.120466=i -entity.120467=j -entity.120468=k -entity.120469=l -entity.120470=m -entity.120471=n -entity.120472=o -entity.120473=p -entity.120474=q -entity.120475=r -entity.120476=s -entity.120477=t -entity.120478=u -entity.120479=v -entity.120480=w -entity.120481=x -entity.120482=y -entity.120483=z -entity.120782=0 -entity.120783=1 -entity.120784=2 -entity.120785=3 -entity.120786=4 -entity.120787=5 -entity.120788=6 -entity.120789=7 -entity.120790=8 -entity.120791=9 -entity.120792=0 -entity.120793=1 -entity.120794=2 -entity.120795=3 -entity.120796=4 -entity.120797=5 -entity.120798=6 -entity.120799=7 -entity.120800=8 -entity.120801=9 -entity.120802=0 -entity.120803=1 -entity.120804=2 -entity.120805=3 -entity.120806=4 -entity.120807=5 -entity.120808=6 -entity.120809=7 -entity.120810=8 -entity.120811=9 -entity.120812=0 -entity.120813=1 -entity.120814=2 -entity.120815=3 -entity.120816=4 -entity.120817=5 -entity.120818=6 -entity.120819=7 -entity.120820=8 -entity.120821=9 -entity.120822=0 -entity.120823=1 -entity.120824=2 -entity.120825=3 -entity.120826=4 -entity.120827=5 -entity.120828=6 -entity.120829=7 -entity.120830=8 -entity.120831=9 -entity.125127=[1] -entity.125128=[2] -entity.125129=[3] -entity.125130=[4] -entity.125131=[5] -entity.125132=[6] -entity.125133=[7] -entity.125134=[8] -entity.125135=[9] -entity.127232=0. -entity.127233=0, -entity.127234=1, -entity.127235=2, -entity.127236=3, -entity.127237=4, -entity.127238=5, -entity.127239=6, -entity.127240=7, -entity.127241=8, -entity.127242=9, -entity.127243=(0) -entity.127244=(0) -entity.127248=(A) -entity.127249=(B) -entity.127250=(C) -entity.127251=(D) -entity.127252=(E) -entity.127253=(F) -entity.127254=(G) -entity.127255=(H) -entity.127256=(I) -entity.127257=(J) -entity.127258=(K) -entity.127259=(L) -entity.127260=(M) -entity.127261=(N) -entity.127262=(O) -entity.127263=(P) -entity.127264=(Q) -entity.127265=(R) -entity.127266=(S) -entity.127267=(T) -entity.127268=(U) -entity.127269=(V) -entity.127270=(W) -entity.127271=(X) -entity.127272=(Y) -entity.127273=(Z) -entity.127274=S -entity.127275=(C) -entity.127276=(R) -entity.127277=(CD) -entity.127278=(WZ) -entity.127338=^(MC) -entity.127339=^(MD)
old mode 100644 new mode 100755 --- a/intl/unicharutil/tests/moz.build +++ b/intl/unicharutil/tests/moz.build @@ -1,16 +1,14 @@ # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. -XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini'] - GeckoSimplePrograms([ 'NormalizationTest', 'UnicharSelfTest', ], msvcrt='static') USE_LIBS += [ 'unicharutil_external_s', ]
deleted file mode 100644 --- a/intl/unicharutil/tests/unit/test_bug_427350_1.js +++ /dev/null @@ -1,56 +0,0 @@ -/* Tests transliteration of new characters in Unicode 5.1, 5.2, and 6.0 - */ - -const inTeluguFractions = "\u0C78\u0C79\u0C7A\u0C7B\u0C7C\u0C7D\u0C7E"; -const inMalayalamNumbers = "\u0D70\u0D71\u0D72\u0D73\u0D74\u0D75"; - -/* MYANMAR SHAN DIGIT ONE, - SUNDANESE DIGIT TWO, - LEPCHA DIGIT THREE, - OL CHIKI DIGIT FOUR, - VAI DIGIT FIVE, - SAURASHTRA DIGIT SIX - KAYAH LI DIGIT SEVEN - CHAM DIGIT EIGHT - JAVANESE DIGIT NINE - MEETEI MAYEK DIGIT ZERO */ -const inDigits = "\u1091\u1BB2\u1C43\u1C54\uA625\uA8D6\uA907\uAA58\uA9D9\uABF0"; -const inRomanNumerals = "\u2185\u2186\u2187\u2188"; -const inSuperSubscripts = "\u2C7C\u2C7D\u2095\u209C"; - -const expectedTeluguFractions = "[0][1][2][3][1][2][3]"; -const expectedMalayalamNumbers = "[10][100][1000][1/4][1/2][3/4]"; -const expectedDigits = "1234567890"; -const expectedRomanNumerals = "[6][50][50000][100000]"; -const expectedSuperSubscripts = "v(j)^(V)v(h)v(t)"; - -const EntityAfterCharsetConv = 512; -const transliterate = 8; - -const charset = "ISO-8859-1"; - -function run_test() { - var SaveAsCharset = - Components.Constructor("@mozilla.org/intl/saveascharset;1", - "nsISaveAsCharset", - "Init"); - - var converter = new SaveAsCharset(charset, - EntityAfterCharsetConv, - transliterate); - - var outTeluguFractions = converter.Convert(inTeluguFractions); - do_check_eq(outTeluguFractions, expectedTeluguFractions); - - var outMalayalamNumbers = converter.Convert(inMalayalamNumbers); - do_check_eq(outMalayalamNumbers, expectedMalayalamNumbers); - - var outDigits = converter.Convert(inDigits); - do_check_eq(outDigits, expectedDigits); - - var outRomanNumerals = converter.Convert(inRomanNumerals); - do_check_eq(outRomanNumerals, expectedRomanNumerals); - - var outSuperSubscripts = converter.Convert(inSuperSubscripts); - do_check_eq(outSuperSubscripts, expectedSuperSubscripts); -}
old mode 100644 new mode 100755 --- a/intl/unicharutil/tests/unit/xpcshell.ini +++ b/intl/unicharutil/tests/unit/xpcshell.ini @@ -1,6 +1,4 @@ [DEFAULT] head = tail = skip-if = toolkit == 'gonk' - -[test_bug_427350_1.js]
--- a/js/public/Class.h +++ b/js/public/Class.h @@ -37,17 +37,19 @@ class Shape; // This is equal to JSFunction::class_. Use it in places where you don't want // to #include jsfun.h. extern JS_FRIEND_DATA(const js::Class* const) FunctionClassPtr; } // namespace js namespace JS { -class AutoIdVector; +template <typename T> +class AutoVectorRooter; +typedef AutoVectorRooter<jsid> AutoIdVector; /* * Per ES6, the [[DefineOwnProperty]] internal method has three different * possible outcomes: * * - It can throw an exception (which we indicate by returning false). * * - It can return true, indicating unvarnished success.
--- a/js/src/NamespaceImports.h +++ b/js/src/NamespaceImports.h @@ -23,21 +23,23 @@ namespace JS { class Latin1Chars; class Latin1CharsZ; class ConstTwoByteChars; class TwoByteChars; class TwoByteCharsZ; class UTF8Chars; class UTF8CharsZ; -class AutoFunctionVector; -class AutoIdVector; -class AutoObjectVector; -class AutoScriptVector; -class AutoValueVector; +template <typename T> +class AutoVectorRooter; +typedef AutoVectorRooter<Value> AutoValueVector; +typedef AutoVectorRooter<jsid> AutoIdVector; +typedef AutoVectorRooter<JSObject*> AutoObjectVector; +typedef AutoVectorRooter<JSFunction*> AutoFunctionVector; +typedef AutoVectorRooter<JSScript*> AutoVector; class AutoIdArray; template <typename T> class AutoVectorRooter; template<typename K, typename V> class AutoHashMapRooter; template<typename T> class AutoHashSetRooter; template<typename T> class RootedGeneric; @@ -70,27 +72,27 @@ using JS::Latin1Char; using JS::Latin1Chars; using JS::Latin1CharsZ; using JS::ConstTwoByteChars; using JS::TwoByteChars; using JS::TwoByteCharsZ; using JS::UTF8Chars; using JS::UTF8CharsZ; -using JS::AutoFunctionVector; -using JS::AutoIdVector; -using JS::AutoObjectVector; -using JS::AutoScriptVector; -using JS::AutoValueVector; +using JS::AutoVectorRooter; +typedef AutoVectorRooter<Value> AutoValueVector; +typedef AutoVectorRooter<jsid> AutoIdVector; +typedef AutoVectorRooter<JSObject*> AutoObjectVector; +typedef AutoVectorRooter<JSFunction*> AutoFunctionVector; +typedef AutoVectorRooter<JSScript*> AutoScriptVector; using JS::AutoIdArray; using JS::AutoHashMapRooter; using JS::AutoHashSetRooter; -using JS::AutoVectorRooter; using JS::RootedGeneric; using JS::CallArgs; using JS::CallNonGenericMethod; using JS::CallReceiver; using JS::CompileOptions; using JS::IsAcceptableThis; using JS::NativeImpl;
--- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -1055,17 +1055,17 @@ static JSObject* InitClass(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp, JSProtoKey key, Native construct, const JSPropertySpec* properties, const JSFunctionSpec* methods) { RootedNativeObject proto(cx, global->createBlankPrototype(cx, clasp)); if (!proto) return nullptr; proto->setPrivate(nullptr); - Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 1)); + Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0)); if (!ctor || !LinkConstructorAndPrototype(cx, ctor, proto) || !DefinePropertiesAndFunctions(cx, proto, properties, methods) || !GlobalObject::initBuiltinConstructor(cx, global, key, ctor, proto)) { return nullptr; } return proto;
--- a/js/src/builtin/WeakSetObject.cpp +++ b/js/src/builtin/WeakSetObject.cpp @@ -46,17 +46,17 @@ WeakSetObject::initClass(JSContext* cx, { Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>()); // Todo: WeakSet.prototype should not be a WeakSet! Rooted<WeakSetObject*> proto(cx, global->createBlankPrototype<WeakSetObject>(cx)); if (!proto) return nullptr; proto->setReservedSlot(WEAKSET_MAP_SLOT, UndefinedValue()); - Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(JSProto_WeakSet, cx), 1)); + Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(JSProto_WeakSet, cx), 0)); if (!ctor || !LinkConstructorAndPrototype(cx, ctor, proto) || !DefinePropertiesAndFunctions(cx, proto, properties, methods) || !GlobalObject::initBuiltinConstructor(cx, global, JSProto_WeakSet, ctor, proto)) { return nullptr; } return proto;
--- a/js/src/ds/IdValuePair.h +++ b/js/src/ds/IdValuePair.h @@ -25,22 +25,22 @@ struct IdValuePair explicit IdValuePair(jsid idArg) : id(idArg), value(UndefinedValue()) {} IdValuePair(jsid idArg, Value valueArg) : id(idArg), value(valueArg) {} }; -class MOZ_STACK_CLASS AutoIdValueVector : public AutoVectorRooter<IdValuePair> +class MOZ_STACK_CLASS AutoIdValueVector : public JS::AutoVectorRooterBase<IdValuePair> { public: explicit AutoIdValueVector(ContextFriendFields* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<IdValuePair>(cx, IDVALVECTOR) + : AutoVectorRooterBase<IdValuePair>(cx, IDVALVECTOR) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; } MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; } /* namespace js */
--- a/js/src/gc/Allocator.cpp +++ b/js/src/gc/Allocator.cpp @@ -67,17 +67,20 @@ GCRuntime::checkAllocatorState(JSContext #endif // Crash if we perform a GC action when it is not safe. if (allowGC && !rt->mainThread.suppressGC) JS::AutoAssertOnGC::VerifyIsSafeToGC(rt); // For testing out of memory conditions if (js::oom::ShouldFailWithOOM()) { - ReportOutOfMemory(cx); + // If we are doing a fallible allocation, percolate up the OOM + // instead of reporting it. + if (allowGC) + ReportOutOfMemory(cx); return false; } return true; } template <typename T> /* static */ void
--- a/js/src/gc/Barrier.cpp +++ b/js/src/gc/Barrier.cpp @@ -8,65 +8,70 @@ #include "jscompartment.h" #include "jsobj.h" #include "gc/Zone.h" #include "js/Value.h" #include "vm/Symbol.h" -namespace js { - -struct ReadBarrierFunctor : public VoidDefaultAdaptor<Value> { - template <typename T> void operator()(T* t) { T::readBarrier(t); } -}; +#ifdef DEBUG -void -ValueReadBarrier(const Value& value) -{ - MOZ_ASSERT(!CurrentThreadIsIonCompiling()); - DispatchValueTyped(ReadBarrierFunctor(), value); -} - -#ifdef DEBUG bool -HeapSlot::preconditionForSet(NativeObject* owner, Kind kind, uint32_t slot) +js::HeapSlot::preconditionForSet(NativeObject* owner, Kind kind, uint32_t slot) { return kind == Slot ? &owner->getSlotRef(slot) == this : &owner->getDenseElement(slot) == (const Value*)this; } bool -HeapSlot::preconditionForWriteBarrierPost(NativeObject* obj, Kind kind, uint32_t slot, Value target) const +js::HeapSlot::preconditionForWriteBarrierPost(NativeObject* obj, Kind kind, uint32_t slot, + Value target) const { return kind == Slot ? obj->getSlotAddressUnchecked(slot)->get() == target : static_cast<HeapSlot*>(obj->getDenseElements() + slot)->get() == target; } bool -RuntimeFromMainThreadIsHeapMajorCollecting(JS::shadow::Zone* shadowZone) +js::RuntimeFromMainThreadIsHeapMajorCollecting(JS::shadow::Zone* shadowZone) { return shadowZone->runtimeFromMainThread()->isHeapMajorCollecting(); } bool -CurrentThreadIsIonCompiling() +js::CurrentThreadIsIonCompiling() { return TlsPerThreadData.get()->ionCompiling; } bool -CurrentThreadIsGCSweeping() +js::CurrentThreadIsGCSweeping() { return js::TlsPerThreadData.get()->gcSweeping; } #endif // DEBUG -bool -StringIsPermanentAtom(JSString* str) +template <typename S> +template <typename T> +void +js::ReadBarrierFunctor<S>::operator()(T* t) { - return str->isPermanentAtom(); + InternalGCMethods<T*>::readBarrier(t); } +template void js::ReadBarrierFunctor<JS::Value>::operator()<JS::Symbol>(JS::Symbol*); +template void js::ReadBarrierFunctor<JS::Value>::operator()<JSObject>(JSObject*); +template void js::ReadBarrierFunctor<JS::Value>::operator()<JSString>(JSString*); -} // namespace js +template <typename S> +template <typename T> +void +js::PreBarrierFunctor<S>::operator()(T* t) +{ + InternalGCMethods<T*>::preBarrier(t); +} +template void js::PreBarrierFunctor<JS::Value>::operator()<JS::Symbol>(JS::Symbol*); +template void js::PreBarrierFunctor<JS::Value>::operator()<JSObject>(JSObject*); +template void js::PreBarrierFunctor<JS::Value>::operator()<JSString>(JSString*); +template void js::PreBarrierFunctor<jsid>::operator()<JS::Symbol>(JS::Symbol*); +template void js::PreBarrierFunctor<jsid>::operator()<JSString>(JSString*);
--- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -6,16 +6,17 @@ #ifndef gc_Barrier_h #define gc_Barrier_h #include "NamespaceImports.h" #include "gc/Heap.h" #include "gc/StoreBuffer.h" +#include "js/HeapAPI.h" #include "js/Id.h" #include "js/RootingAPI.h" #include "js/Value.h" /* * A write barrier is a mechanism used by incremental or generation GCs to * ensure that every value that needs to be marked is marked. In general, the * write barrier should be invoked whenever a write can cause the set of things @@ -191,19 +192,16 @@ class JitCode; // a helper thread. bool CurrentThreadIsIonCompiling(); bool CurrentThreadIsGCSweeping(); #endif -bool -StringIsPermanentAtom(JSString* str); - namespace gc { template <typename T> struct MapTypeToTraceKind {}; template <> struct MapTypeToTraceKind<NativeObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; template <> struct MapTypeToTraceKind<ArrayObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; template <> struct MapTypeToTraceKind<ArgumentsObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; template <> struct MapTypeToTraceKind<ArrayBufferObject>{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; template <> struct MapTypeToTraceKind<ArrayBufferObjectMaybeShared>{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; @@ -235,65 +233,16 @@ template <> struct MapTypeToTraceKind<Ob // Marking.h depends on these barrier definitions, so we need a separate // entry point for marking to implement the pre-barrier. void MarkValueForBarrier(JSTracer* trc, Value* v, const char* name); void MarkIdForBarrier(JSTracer* trc, jsid* idp, const char* name); } // namespace gc -// This context is more basal than the GC things being implemented, so C++ does -// not know about the inheritance hierarchy yet. -static inline const gc::TenuredCell* AsTenuredCell(const JSString* str) { - return reinterpret_cast<const gc::TenuredCell*>(str); -} -static inline const gc::TenuredCell* AsTenuredCell(const JS::Symbol* sym) { - return reinterpret_cast<const gc::TenuredCell*>(sym); -} - -JS::Zone* -ZoneOfObjectFromAnyThread(const JSObject& obj); - -static inline JS::shadow::Zone* -ShadowZoneOfObjectFromAnyThread(JSObject* obj) -{ - return JS::shadow::Zone::asShadowZone(ZoneOfObjectFromAnyThread(*obj)); -} - -static inline JS::shadow::Zone* -ShadowZoneOfStringFromAnyThread(JSString* str) -{ - return JS::shadow::Zone::asShadowZone(AsTenuredCell(str)->zoneFromAnyThread()); -} - -static inline JS::shadow::Zone* -ShadowZoneOfSymbolFromAnyThread(JS::Symbol* sym) -{ - return JS::shadow::Zone::asShadowZone(AsTenuredCell(sym)->zoneFromAnyThread()); -} - -MOZ_ALWAYS_INLINE JS::Zone* -ZoneOfValueFromAnyThread(const JS::Value& value) -{ - MOZ_ASSERT(value.isMarkable()); - if (value.isObject()) - return ZoneOfObjectFromAnyThread(value.toObject()); - return js::gc::TenuredCell::fromPointer(value.toGCThing())->zoneFromAnyThread(); -} - -MOZ_ALWAYS_INLINE JS::Zone* -ZoneOfIdFromAnyThread(const jsid& id) -{ - MOZ_ASSERT(JSID_IS_GCTHING(id)); - return js::gc::TenuredCell::fromPointer(JSID_TO_GCTHING(id).asCell())->zoneFromAnyThread(); -} - -void -ValueReadBarrier(const Value& value); - template <typename T> struct InternalGCMethods {}; template <typename T> struct InternalGCMethods<T*> { static bool isMarkable(T* v) { return v != nullptr; } @@ -301,56 +250,33 @@ struct InternalGCMethods<T*> static void postBarrier(T** vp) { T::writeBarrierPost(*vp, vp); } static void postBarrierRelocate(T** vp) { T::writeBarrierPostRelocate(*vp, vp); } static void postBarrierRemove(T** vp) { T::writeBarrierPostRemove(*vp, vp); } static void readBarrier(T* v) { T::readBarrier(v); } }; +template <typename S> struct PreBarrierFunctor : VoidDefaultAdaptor<S> { + template <typename T> void operator()(T* t); +}; + +template <typename S> struct ReadBarrierFunctor : public VoidDefaultAdaptor<S> { + template <typename T> void operator()(T* t); +}; + template <> struct InternalGCMethods<Value> { - static JSRuntime* runtimeFromAnyThread(const Value& v) { - MOZ_ASSERT(v.isMarkable()); - return static_cast<js::gc::Cell*>(v.toGCThing())->runtimeFromAnyThread(); - } - static JS::shadow::Runtime* shadowRuntimeFromAnyThread(const Value& v) { - return reinterpret_cast<JS::shadow::Runtime*>(runtimeFromAnyThread(v)); - } - static JSRuntime* runtimeFromMainThread(const Value& v) { - MOZ_ASSERT(v.isMarkable()); - return static_cast<js::gc::Cell*>(v.toGCThing())->runtimeFromMainThread(); - } - static JS::shadow::Runtime* shadowRuntimeFromMainThread(const Value& v) { - return reinterpret_cast<JS::shadow::Runtime*>(runtimeFromMainThread(v)); - } - static bool isMarkable(Value v) { return v.isMarkable(); } static void preBarrier(Value v) { - MOZ_ASSERT(!CurrentThreadIsIonCompiling()); - if (v.isString() && StringIsPermanentAtom(v.toString())) - return; - if (v.isMarkable() && shadowRuntimeFromAnyThread(v)->needsIncrementalBarrier()) - preBarrierImpl(ZoneOfValueFromAnyThread(v), v); + DispatchValueTyped(PreBarrierFunctor<Value>(), v); } - private: - static void preBarrierImpl(Zone* zone, Value v) { - JS::shadow::Zone* shadowZone = JS::shadow::Zone::asShadowZone(zone); - if (shadowZone->needsIncrementalBarrier()) { - MOZ_ASSERT_IF(v.isMarkable(), shadowRuntimeFromMainThread(v)->needsIncrementalBarrier()); - Value tmp(v); - js::gc::MarkValueForBarrier(shadowZone->barrierTracer(), &tmp, "write barrier"); - MOZ_ASSERT(tmp == v); - } - } - - public: static void postBarrier(Value* vp) { MOZ_ASSERT(!CurrentThreadIsIonCompiling()); if (vp->isObject()) { gc::StoreBuffer* sb = reinterpret_cast<gc::Cell*>(&vp->toObject())->storeBuffer(); if (sb) sb->putValueFromAnyThread(vp); } } @@ -368,50 +294,27 @@ struct InternalGCMethods<Value> MOZ_ASSERT(vp); MOZ_ASSERT(vp->isMarkable()); MOZ_ASSERT(!CurrentThreadIsIonCompiling()); JSRuntime* rt = static_cast<js::gc::Cell*>(vp->toGCThing())->runtimeFromAnyThread(); JS::shadow::Runtime* shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt); shadowRuntime->gcStoreBufferPtr()->removeRelocatableValueFromAnyThread(vp); } - static void readBarrier(const Value& v) { ValueReadBarrier(v); } + static void readBarrier(const Value& v) { + DispatchValueTyped(ReadBarrierFunctor<Value>(), v); + } }; template <> struct InternalGCMethods<jsid> { static bool isMarkable(jsid id) { return JSID_IS_STRING(id) || JSID_IS_SYMBOL(id); } - static void preBarrier(jsid id) { - MOZ_ASSERT(!CurrentThreadIsIonCompiling()); - if (JSID_IS_STRING(id) && StringIsPermanentAtom(JSID_TO_STRING(id))) - return; - if (JSID_IS_GCTHING(id) && shadowRuntimeFromAnyThread(id)->needsIncrementalBarrier()) - preBarrierImpl(ZoneOfIdFromAnyThread(id), id); - } - - private: - static JSRuntime* runtimeFromAnyThread(jsid id) { - MOZ_ASSERT(JSID_IS_GCTHING(id)); - return JSID_TO_GCTHING(id).asCell()->runtimeFromAnyThread(); - } - static JS::shadow::Runtime* shadowRuntimeFromAnyThread(jsid id) { - return reinterpret_cast<JS::shadow::Runtime*>(runtimeFromAnyThread(id)); - } - static void preBarrierImpl(Zone* zone, jsid id) { - JS::shadow::Zone* shadowZone = JS::shadow::Zone::asShadowZone(zone); - if (shadowZone->needsIncrementalBarrier()) { - jsid tmp(id); - js::gc::MarkIdForBarrier(shadowZone->barrierTracer(), &tmp, "id write barrier"); - MOZ_ASSERT(tmp == id); - } - } - - public: + static void preBarrier(jsid id) { DispatchIdTyped(PreBarrierFunctor<jsid>(), id); } static void postBarrier(jsid* idp) {} static void postBarrierRelocate(jsid* idp) {} static void postBarrierRemove(jsid* idp) {} }; template <typename T> class BarrieredBaseMixins {};
--- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -521,29 +521,16 @@ js::TraceObjectSlots(JSTracer* trc, Nati for (uint32_t i = start; i < (start + nslots); ++i) { HeapSlot& slot = obj->getSlotRef(i); if (InternalGCMethods<Value>::isMarkable(slot)) DispatchToTracer(trc, slot.unsafeGet(), "object slot"); ++index; } } -void -gc::MarkValueForBarrier(JSTracer* trc, Value* valuep, const char* name) -{ - MOZ_ASSERT(!trc->runtime()->isHeapCollecting()); - TraceManuallyBarrieredEdge(trc, valuep, name); -} - -void -gc::MarkIdForBarrier(JSTracer* trc, jsid* idp, const char* name) -{ - TraceManuallyBarrieredEdge(trc, idp, name); -} - // A typed functor adaptor for TraceRoot. struct TraceRootFunctor { template <typename T> void operator()(JSTracer* trc, Cell** thingp, const char* name) { TraceRoot(trc, reinterpret_cast<T**>(thingp), name); } };
--- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -146,23 +146,23 @@ AutoGCRooter::trace(JSTracer* trc) static_cast<AutoPropertyDescriptorVector*>(this)->vector; for (size_t i = 0, len = descriptors.length(); i < len; i++) descriptors[i].trace(trc); return; } case VALVECTOR: { AutoValueVector::VectorImpl& vector = static_cast<AutoValueVector*>(this)->vector; - TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector"); + TraceRootRange(trc, vector.length(), vector.begin(), "JS::AutoValueVector.vector"); return; } case IDVECTOR: { AutoIdVector::VectorImpl& vector = static_cast<AutoIdVector*>(this)->vector; - TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector"); + TraceRootRange(trc, vector.length(), vector.begin(), "JS::AutoIdVector.vector"); return; } case IDVALVECTOR: { AutoIdValueVector::VectorImpl& vector = static_cast<AutoIdValueVector*>(this)->vector; for (size_t i = 0; i < vector.length(); i++) { TraceRoot(trc, &vector[i].id, "js::AutoIdValueVector id"); TraceRoot(trc, &vector[i].value, "js::AutoIdValueVector value"); @@ -174,23 +174,17 @@ AutoGCRooter::trace(JSTracer* trc) AutoShapeVector::VectorImpl& vector = static_cast<js::AutoShapeVector*>(this)->vector; TraceRootRange(trc, vector.length(), const_cast<Shape**>(vector.begin()), "js::AutoShapeVector.vector"); return; } case OBJVECTOR: { AutoObjectVector::VectorImpl& vector = static_cast<AutoObjectVector*>(this)->vector; - TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector"); - return; - } - - case FUNVECTOR: { - AutoFunctionVector::VectorImpl& vector = static_cast<AutoFunctionVector*>(this)->vector; - TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoFunctionVector.vector"); + TraceRootRange(trc, vector.length(), vector.begin(), "JS::AutoObjectVector.vector"); return; } case STRINGVECTOR: { AutoStringVector::VectorImpl& vector = static_cast<AutoStringVector*>(this)->vector; TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoStringVector.vector"); return; }
--- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -227,22 +227,16 @@ Zone::createJitZone(JSContext* cx) if (!cx->runtime()->getJitRuntime(cx)) return nullptr; jitZone_ = cx->new_<js::jit::JitZone>(); return jitZone_; } -JS::Zone* -js::ZoneOfObjectFromAnyThread(const JSObject& obj) -{ - return obj.zoneFromAnyThread(); -} - bool Zone::hasMarkedCompartments() { for (CompartmentsInZoneIter comp(this); !comp.done(); comp.next()) { if (comp->marked) return true; } return false;
--- a/js/src/gdb/moz.build +++ b/js/src/gdb/moz.build @@ -15,20 +15,17 @@ UNIFIED_SOURCES += [ 'tests/test-JSString.cpp', 'tests/test-JSSymbol.cpp', 'tests/test-jsval.cpp', 'tests/test-prettyprinters.cpp', 'tests/test-Root.cpp', 'tests/typedef-printers.cpp', ] -# Building against js_static requires that we declare mfbt sybols "exported" -# on its behalf. -for var in ('EXPORT_JS_API', 'IMPL_MFBT'): - DEFINES[var] = True +DEFINES['EXPORT_JS_API'] = True LOCAL_INCLUDES += ['..'] GENERATED_INCLUDES += ['..'] USE_LIBS += [ 'static:js', ]
--- a/js/src/jit-test/tests/arrays/sort-getter-only.js +++ b/js/src/jit-test/tests/arrays/sort-getter-only.js @@ -1,19 +1,19 @@ // The property assignments in Array.prototype.sort are strict assignments. load(libdir + "asserts.js"); var a = ["A", , "B", "C", "D"]; var normalArrayElementDesc = Object.getOwnPropertyDescriptor(a, 0); var getterDesc = { - configurable: false, + get: function () { return "F"; }, + set: undefined, enumerable: true, - get: function () { return "F"; }, - set: undefined + configurable: false }; Object.defineProperty(a, 1, getterDesc); // a.sort is permitted to try to delete a[1] or to try to assign a[1], but it // must try one or the other. Either one will fail, throwing a TypeError. assertThrowsInstanceOf(() => a.sort(), TypeError); // a.sort() is not permitted to delete the nonconfigurable property.
--- a/js/src/jit-test/tests/collections/Array-of-nonconfigurable-2.js +++ b/js/src/jit-test/tests/collections/Array-of-nonconfigurable-2.js @@ -4,13 +4,13 @@ load(libdir + "asserts.js"); var obj; function C() { obj = this; Object.defineProperty(this, 0, {value: "v", configurable: false}); } try { Array.of.call(C, 1); } catch (e) {} assertDeepEq(Object.getOwnPropertyDescriptor(obj, 0), { - configurable: false, + value: "v", + writable: false, enumerable: false, - value: "v", - writable: false + configurable: false });
--- a/js/src/jit-test/tests/collections/Map-surfaces-1.js +++ b/js/src/jit-test/tests/collections/Map-surfaces-1.js @@ -4,17 +4,17 @@ load(libdir + "iteration.js"); var desc = Object.getOwnPropertyDescriptor(this, "Map"); assertEq(desc.enumerable, false); assertEq(desc.configurable, true); assertEq(desc.writable, true); assertEq(typeof Map, 'function'); assertEq(Object.keys(Map).length, 0); -assertEq(Map.length, 1); +assertEq(Map.length, 0); assertEq(Map.name, "Map"); assertEq(Object.getPrototypeOf(Map.prototype), Object.prototype); assertEq(Object.prototype.toString.call(Map.prototype), "[object Map]"); assertEq(Object.prototype.toString.call(new Map()), "[object Map]"); assertEq(Object.keys(Map.prototype).join(), ""); assertEq(Map.prototype.constructor, Map);
--- a/js/src/jit-test/tests/collections/Set-surfaces-1.js +++ b/js/src/jit-test/tests/collections/Set-surfaces-1.js @@ -4,17 +4,17 @@ load(libdir + "iteration.js"); var desc = Object.getOwnPropertyDescriptor(this, "Set"); assertEq(desc.enumerable, false); assertEq(desc.configurable, true); assertEq(desc.writable, true); assertEq(typeof Set, 'function'); assertEq(Object.keys(Set).length, 0); -assertEq(Set.length, 1); +assertEq(Set.length, 0); assertEq(Set.name, "Set"); assertEq(Object.getPrototypeOf(Set.prototype), Object.prototype); assertEq(Object.prototype.toString.call(Set.prototype), "[object Set]"); assertEq(Object.prototype.toString.call(new Set()), "[object Set]"); assertEq(Object.keys(Set.prototype).join(), ""); assertEq(Set.prototype.constructor, Set);
--- a/js/src/jit-test/tests/collections/WeakMap-surfaces.js +++ b/js/src/jit-test/tests/collections/WeakMap-surfaces.js @@ -2,17 +2,17 @@ var desc = Object.getOwnPropertyDescriptor(this, "WeakMap"); assertEq(desc.enumerable, false); assertEq(desc.configurable, true); assertEq(desc.writable, true); assertEq(typeof WeakMap, 'function'); assertEq(Object.keys(WeakMap).length, 0); -assertEq(WeakMap.length, 1); +assertEq(WeakMap.length, 0); assertEq(WeakMap.name, "WeakMap"); assertEq(Object.getPrototypeOf(WeakMap.prototype), Object.prototype); assertEq(Object.prototype.toString.call(WeakMap.prototype), "[object WeakMap]"); assertEq(Object.prototype.toString.call(new WeakMap()), "[object WeakMap]"); assertEq(Object.keys(WeakMap.prototype).join(), ""); assertEq(WeakMap.prototype.constructor, WeakMap);
--- a/js/src/jit-test/tests/collections/WeakSet-surface.js +++ b/js/src/jit-test/tests/collections/WeakSet-surface.js @@ -2,17 +2,17 @@ var desc = Object.getOwnPropertyDescriptor(this, "WeakSet"); assertEq(desc.enumerable, false); assertEq(desc.configurable, true); assertEq(desc.writable, true); assertEq(typeof WeakSet, 'function'); assertEq(Object.keys(WeakSet).length, 0); -assertEq(WeakSet.length, 1); +assertEq(WeakSet.length, 0); assertEq(WeakSet.name, "WeakSet"); assertEq(Object.getPrototypeOf(WeakSet.prototype), Object.prototype); assertEq(Object.prototype.toString.call(WeakSet.prototype), "[object WeakSet]"); assertEq(Object.prototype.toString.call(new WeakSet), "[object WeakSet]"); assertEq(Object.keys(WeakSet.prototype).length, 0); assertEq(WeakSet.prototype.constructor, WeakSet);
--- a/js/src/jit-test/tests/proxy/testDirectProxyGetOwnPropertyDescriptor11.js +++ b/js/src/jit-test/tests/proxy/testDirectProxyGetOwnPropertyDescriptor11.js @@ -2,13 +2,13 @@ load(libdir + "asserts.js"); var p = new Proxy({}, { getOwnPropertyDescriptor() { return {configurable: true}; } }); var desc = Object.getOwnPropertyDescriptor(p, "x"); assertDeepEq(desc, { - configurable: true, + value: undefined, + writable: false, enumerable: false, - value: undefined, - writable: false + configurable: true });
--- a/js/src/jit-test/tests/proxy/testIndirectProxyGetOwnPropertyDescriptor.js +++ b/js/src/jit-test/tests/proxy/testIndirectProxyGetOwnPropertyDescriptor.js @@ -1,12 +1,12 @@ // Bug 1133294 - Object.getOwnPropertyDescriptor should never return an incomplete descriptor. load(libdir + "asserts.js"); var p = Proxy.create({ getOwnPropertyDescriptor() { return {}; } }); var desc = Object.getOwnPropertyDescriptor(p, "x"); assertDeepEq(desc, { - configurable: false, + value: undefined, + writable: false, enumerable: false, - value: undefined, - writable: false + configurable: false });
--- a/js/src/jsapi-tests/moz.build +++ b/js/src/jsapi-tests/moz.build @@ -95,19 +95,16 @@ if CONFIG['ENABLE_ION']: 'testJitMoveEmitterCycles-mips.cpp', 'testJitMoveEmitterCycles.cpp', 'testJitRangeAnalysis.cpp', 'testJitRegisterSet.cpp', 'testJitRValueAlloc.cpp', ] DEFINES['EXPORT_JS_API'] = True -# Building against js_static requires that we declare mfbt sybols "exported" -# on its behalf. -DEFINES['IMPL_MFBT'] = True LOCAL_INCLUDES += ['..'] GENERATED_INCLUDES += ['..'] USE_LIBS += [ 'static:js', ]
--- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -89,46 +89,46 @@ class AutoValueArray : public AutoGCRoot MOZ_ASSERT(i < N); return MutableHandleValue::fromMarkedLocation(&elements_[i]); } MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; template<class T> -class AutoVectorRooter : protected AutoGCRooter +class AutoVectorRooterBase : protected AutoGCRooter { typedef js::Vector<T, 8> VectorImpl; VectorImpl vector; public: - explicit AutoVectorRooter(JSContext* cx, ptrdiff_t tag + explicit AutoVectorRooterBase(JSContext* cx, ptrdiff_t tag MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : AutoGCRooter(cx, tag), vector(cx) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; } - explicit AutoVectorRooter(js::ContextFriendFields* cx, ptrdiff_t tag + explicit AutoVectorRooterBase(js::ContextFriendFields* cx, ptrdiff_t tag MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : AutoGCRooter(cx, tag), vector(cx) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; } typedef T ElementType; typedef typename VectorImpl::Range Range; size_t length() const { return vector.length(); } bool empty() const { return vector.empty(); } bool append(const T& v) { return vector.append(v); } bool appendN(const T& v, size_t len) { return vector.appendN(v, len); } bool append(const T* ptr, size_t len) { return vector.append(ptr, len); } - bool appendAll(const AutoVectorRooter<T>& other) { + bool appendAll(const AutoVectorRooterBase<T>& other) { return vector.appendAll(other.vector); } bool insert(T* p, const T& val) { return vector.insert(p, val); } /* For use when space has already been reserved. */ void infallibleAppend(const T& v) { vector.infallibleAppend(v); } @@ -185,16 +185,43 @@ class AutoVectorRooter : protected AutoG T* t = vector.begin() + oldLength; for (size_t i = oldLength; i < vector.length(); ++i, ++t) memset(t, 0, sizeof(T)); } MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; +template <typename T> +class MOZ_STACK_CLASS AutoVectorRooter : public AutoVectorRooterBase<T> +{ + public: + explicit AutoVectorRooter(JSContext* cx + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoVectorRooterBase<T>(cx, this->GetTag(T())) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + explicit AutoVectorRooter(js::ContextFriendFields* cx + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoVectorRooterBase<T>(cx, this->GetTag(T())) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +typedef AutoVectorRooter<Value> AutoValueVector; +typedef AutoVectorRooter<jsid> AutoIdVector; +typedef AutoVectorRooter<JSObject*> AutoObjectVector; +typedef AutoVectorRooter<JSFunction*> AutoFunctionVector; +typedef AutoVectorRooter<JSScript*> AutoScriptVector; + template<class Key, class Value> class AutoHashMapRooter : protected AutoGCRooter { private: typedef js::HashMap<Key, Value> HashMapImpl; public: explicit AutoHashMapRooter(JSContext* cx, ptrdiff_t tag @@ -418,88 +445,16 @@ class AutoHashSetRooter : protected Auto AutoHashSetRooter(const AutoHashSetRooter& hmr) = delete; AutoHashSetRooter& operator=(const AutoHashSetRooter& hmr) = delete; HashSetImpl set; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; -class MOZ_STACK_CLASS AutoValueVector : public AutoVectorRooter<Value> -{ - public: - explicit AutoValueVector(JSContext* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<Value>(cx, VALVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - -class AutoIdVector : public AutoVectorRooter<jsid> -{ - public: - explicit AutoIdVector(JSContext* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<jsid>(cx, IDVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - -class AutoObjectVector : public AutoVectorRooter<JSObject*> -{ - public: - explicit AutoObjectVector(JSContext* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<JSObject*>(cx, OBJVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - -class AutoFunctionVector : public AutoVectorRooter<JSFunction*> -{ - public: - explicit AutoFunctionVector(JSContext* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<JSFunction*>(cx, FUNVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - explicit AutoFunctionVector(js::ContextFriendFields* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<JSFunction*>(cx, FUNVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - -class AutoScriptVector : public AutoVectorRooter<JSScript*> -{ - public: - explicit AutoScriptVector(JSContext* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<JSScript*>(cx, SCRIPTVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - /* * Custom rooting behavior for internal and external clients. */ class JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter { public: template <typename CX> explicit CustomAutoRooter(CX* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
--- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -654,54 +654,19 @@ CheckForInterrupt(JSContext* cx) JSRuntime* rt = cx->runtime(); if (MOZ_UNLIKELY(rt->hasPendingInterrupt())) return rt->handleInterrupt(cx); return true; } /************************************************************************/ -class AutoStringVector : public AutoVectorRooter<JSString*> -{ - public: - explicit AutoStringVector(JSContext* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<JSString*>(cx, STRINGVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - -class AutoPropertyNameVector : public AutoVectorRooter<PropertyName*> -{ - public: - explicit AutoPropertyNameVector(JSContext* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<PropertyName*>(cx, STRINGVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - -class AutoShapeVector : public AutoVectorRooter<Shape*> -{ - public: - explicit AutoShapeVector(JSContext* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<Shape*>(cx, SHAPEVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; +typedef JS::AutoVectorRooter<JSString*> AutoStringVector; +typedef JS::AutoVectorRooter<PropertyName*> AutoPropertyNameVector; +typedef JS::AutoVectorRooter<Shape*> AutoShapeVector; class AutoObjectObjectHashMap : public AutoHashMapRooter<JSObject*, JSObject*> { public: explicit AutoObjectObjectHashMap(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : AutoHashMapRooter<JSObject*, JSObject*>(cx, OBJOBJHASHMAP) {
--- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -96,39 +96,48 @@ JSCompartment::~JSCompartment() js_delete(objectMetadataTable); js_delete(lazyArrayBuffers); js_free(enumerators); runtime_->numCompartments--; } bool -JSCompartment::init(JSContext* cx) +JSCompartment::init(JSContext* maybecx) { /* + * maybecx is null when called to create the atoms compartment from + * JSRuntime::init(). + * * As a hack, we clear our timezone cache every time we create a new * compartment. This ensures that the cache is always relatively fresh, but * shouldn't interfere with benchmarks which create tons of date objects * (unless they also create tons of iframes, which seems unlikely). */ - if (cx) - cx->runtime()->dateTimeInfo.updateTimeZoneAdjustment(); + if (maybecx) + maybecx->runtime()->dateTimeInfo.updateTimeZoneAdjustment(); - if (!crossCompartmentWrappers.init(0)) + if (!crossCompartmentWrappers.init(0)) { + if (maybecx) + ReportOutOfMemory(maybecx); + return false; + } + + if (!regExps.init(maybecx)) return false; - if (!regExps.init(cx)) - return false; - - enumerators = NativeIterator::allocateSentinel(cx); + enumerators = NativeIterator::allocateSentinel(maybecx); if (!enumerators) return false; - if (!savedStacks_.init()) + if (!savedStacks_.init()) { + if (maybecx) + ReportOutOfMemory(maybecx); return false; + } return true; } jit::JitRuntime* JSRuntime::createJitRuntime(JSContext* cx) { // The shared stubs are created in the atoms compartment, which may be
--- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -372,17 +372,17 @@ struct JSCompartment DebuggerObservesAsmJS; void updateDebuggerObservesFlag(unsigned flag); public: JSCompartment(JS::Zone* zone, const JS::CompartmentOptions& options); ~JSCompartment(); - bool init(JSContext* cx); + bool init(JSContext* maybecx); /* Mark cross-compartment wrappers. */ void markCrossCompartmentWrappers(JSTracer* trc); inline bool wrap(JSContext* cx, JS::MutableHandleValue vp, JS::HandleObject existing = js::NullPtr()); bool wrap(JSContext* cx, js::MutableHandleString strp); @@ -726,22 +726,22 @@ struct WrapperValue Value get() const { return value; } operator const Value&() const { return value; } JSObject& toObject() const { return value.toObject(); } private: Value value; }; -class AutoWrapperVector : public AutoVectorRooter<WrapperValue> +class AutoWrapperVector : public JS::AutoVectorRooterBase<WrapperValue> { public: explicit AutoWrapperVector(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<WrapperValue>(cx, WRAPVECTOR) + : AutoVectorRooterBase<WrapperValue>(cx, WRAPVECTOR) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; } MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; class AutoWrapperRooter : private JS::AutoGCRooter {
--- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -569,71 +569,87 @@ RegionMatches(const char* s1, int s1off, /* find UTC time from given date... no 1900 correction! */ static double date_msecFromDate(double year, double mon, double mday, double hour, double min, double sec, double msec) { return MakeDate(MakeDay(year, mon, mday), MakeTime(hour, min, sec, msec)); } -/* compute the time in msec (unclipped) from the given args */ -#define MAXARGS 7 - -static bool -date_msecFromArgs(JSContext* cx, CallArgs args, double* rval) -{ - unsigned loop; - double array[MAXARGS]; - double msec_time; - - for (loop = 0; loop < MAXARGS; loop++) { - if (loop < args.length()) { - double d; - if (!ToNumber(cx, args[loop], &d)) - return false; - /* return NaN if any arg is not finite */ - if (!IsFinite(d)) { - *rval = GenericNaN(); - return true; - } - array[loop] = ToInteger(d); - } else { - if (loop == 2) { - array[loop] = 1; /* Default the date argument to 1. */ - } else { - array[loop] = 0; - } - } - } - - /* adjust 2-digit years into the 20th century */ - if (array[0] >= 0 && array[0] <= 99) - array[0] += 1900; - - msec_time = date_msecFromDate(array[0], array[1], array[2], - array[3], array[4], array[5], array[6]); - *rval = msec_time; - return true; -} - -/* - * See ECMA 15.9.4.[3-10]; - */ +/* ES6 20.3.3.4. */ static bool date_UTC(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - double msec_time; - if (!date_msecFromArgs(cx, args, &msec_time)) + // Steps 1-2. + double y; + if (!ToNumber(cx, args.get(0), &y)) + return false; + + // Steps 3-4. + double m; + if (!ToNumber(cx, args.get(1), &m)) return false; - msec_time = TimeClip(msec_time); - - args.rval().setNumber(msec_time); + // Steps 5-6. + double dt; + if (args.length() >= 3) { + if (!ToNumber(cx, args[2], &dt)) + return false; + } else { + dt = 1; + } + + // Steps 7-8. + double h; + if (args.length() >= 4) { + if (!ToNumber(cx, args[3], &h)) + return false; + } else { + h = 0; + } + + // Steps 9-10. + double min; + if (args.length() >= 5) { + if (!ToNumber(cx, args[4], &min)) + return false; + } else { + min = 0; + } + + // Steps 11-12. + double s; + if (args.length() >= 6) { + if (!ToNumber(cx, args[5], &s)) + return false; + } else { + s = 0; + } + + // Steps 13-14. + double milli; + if (args.length() >= 7) { + if (!ToNumber(cx, args[6], &milli)) + return false; + } else { + milli = 0; + } + + // Step 15. + double yr = y; + if (!IsNaN(y)) { + double yint = ToInteger(y); + if (0 <= yint && yint <= 99) + yr = 1900 + yint; + } + + // Step 16. + args.rval().setDouble(TimeClip(MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)))); return true; } /* * Read and convert decimal digits from s[*i] into *result * while *i < limit. * * Succeed if any digits are converted. Advance *i only @@ -2886,17 +2902,17 @@ date_valueOf_impl(JSContext* cx, CallArg bool js::date_valueOf(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); return CallNonGenericMethod<IsDate, date_valueOf_impl>(cx, args); } static const JSFunctionSpec date_static_methods[] = { - JS_FN("UTC", date_UTC, MAXARGS,0), + JS_FN("UTC", date_UTC, 7,0), JS_FN("parse", date_parse, 1,0), JS_FN("now", date_now, 0,0), JS_FS_END }; static const JSFunctionSpec date_methods[] = { JS_FN("getTime", date_getTime, 0,0), JS_FN("getTimezoneOffset", date_getTimezoneOffset, 0,0), @@ -2951,75 +2967,170 @@ static const JSFunctionSpec date_methods #if JS_HAS_TOSOURCE JS_FN(js_toSource_str, date_toSource, 0,0), #endif JS_FN(js_toString_str, date_toString, 0,0), JS_FN(js_valueOf_str, date_valueOf, 0,0), JS_FS_END }; -bool -js::DateConstructor(JSContext* cx, unsigned argc, Value* vp) +static bool +NewDateObject(JSContext* cx, const CallArgs& args, double d) +{ + JSObject* obj = NewDateObjectMsec(cx, d); + if (!obj) + return false; + + args.rval().setObject(*obj); + return true; +} + +static bool +ToDateString(JSContext* cx, const CallArgs& args, double d) { - CallArgs args = CallArgsFromVp(argc, vp); - - /* Date called as function. */ - if (!args.isConstructing()) - return date_format(cx, NowAsMillis(), FORMATSPEC_FULL, args.rval()); - - /* Date called as constructor. */ - double d; - if (args.length() == 0) { - /* ES5 15.9.3.3. */ - d = NowAsMillis(); - } else if (args.length() == 1) { - /* ES5 15.9.3.2. */ - - /* Step 1. */ + return date_format(cx, d, FORMATSPEC_FULL, args.rval()); +} + +static bool +DateNoArguments(JSContext* cx, const CallArgs& args) +{ + MOZ_ASSERT(args.length() == 0); + + double now = NowAsMillis(); + + if (args.isConstructing()) + return NewDateObject(cx, args, now); + + return ToDateString(cx, args, now); +} + +static bool +DateOneArgument(JSContext* cx, const CallArgs& args) +{ + MOZ_ASSERT(args.length() == 1); + + if (args.isConstructing()) { + double d; + if (!ToPrimitive(cx, args[0])) return false; if (args[0].isString()) { - /* Step 2. */ - JSString* str = args[0].toString(); - if (!str) - return false; - - JSLinearString* linearStr = str->ensureLinear(cx); + JSLinearString* linearStr = args[0].toString()->ensureLinear(cx); if (!linearStr) return false; if (!ParseDate(linearStr, &d, &cx->runtime()->dateTimeInfo)) d = GenericNaN(); else d = TimeClip(d); } else { - /* Step 3. */ if (!ToNumber(cx, args[0], &d)) return false; d = TimeClip(d); } - } else { - double msec_time; - if (!date_msecFromArgs(cx, args, &msec_time)) + + return NewDateObject(cx, args, d); + } + + return ToDateString(cx, args, NowAsMillis()); +} + +static bool +DateMultipleArguments(JSContext* cx, const CallArgs& args) +{ + MOZ_ASSERT(args.length() >= 2); + + // Step 3. + if (args.isConstructing()) { + // Steps 3a-b. + double y; + if (!ToNumber(cx, args[0], &y)) + return false; + + // Steps 3c-d. + double m; + if (!ToNumber(cx, args[1], &m)) return false; - if (IsFinite(msec_time)) { - msec_time = UTC(msec_time, &cx->runtime()->dateTimeInfo); - msec_time = TimeClip(msec_time); + // Steps 3e-f. + double dt; + if (args.length() >= 3) { + if (!ToNumber(cx, args[2], &dt)) + return false; + } else { + dt = 1; + } + + // Steps 3g-h. + double h; + if (args.length() >= 4) { + if (!ToNumber(cx, args[3], &h)) + return false; + } else { + h = 0; + } + + // Steps 3i-j. + double min; + if (args.length() >= 5) { + if (!ToNumber(cx, args[4], &min)) + return false; + } else { + min = 0; } - d = msec_time; + + // Steps 3k-l. + double s; + if (args.length() >= 6) { + if (!ToNumber(cx, args[5], &s)) + return false; + } else { + s = 0; + } + + // Steps 3m-n. + double milli; + if (args.length() >= 7) { + if (!ToNumber(cx, args[6], &milli)) + return false; + } else { + milli = 0; + } + + // Step 3o. + double yr = y; + if (!IsNaN(y)) { + double yint = ToInteger(y); + if (0 <= yint && yint <= 99) + yr = 1900 + yint; + } + + // Step 3p. + double finalDate = MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)); + + // Steps 3q-t. + return NewDateObject(cx, args, TimeClip(UTC(finalDate, &cx->runtime()->dateTimeInfo))); } - JSObject* obj = NewDateObjectMsec(cx, d); - if (!obj) - return false; - - args.rval().setObject(*obj); - return true; + return ToDateString(cx, args, NowAsMillis()); +} + +bool +js::DateConstructor(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + if (args.length() == 0) + return DateNoArguments(cx, args); + + if (args.length() == 1) + return DateOneArgument(cx, args); + + return DateMultipleArguments(cx, args); } static bool FinishDateClassInit(JSContext* cx, HandleObject ctor, HandleObject proto) { proto->as<DateObject>().setUTCTime(GenericNaN()); /* @@ -3047,17 +3158,17 @@ const Class DateObject::class_ = { nullptr, /* mayResolve */ date_convert, nullptr, /* finalize */ nullptr, /* call */ nullptr, /* hasInstance */ nullptr, /* construct */ nullptr, /* trace */ { - GenericCreateConstructor<DateConstructor, MAXARGS, JSFunction::FinalizeKind>, + GenericCreateConstructor<DateConstructor, 7, JSFunction::FinalizeKind>, GenericCreatePrototype, date_static_methods, nullptr, date_methods, nullptr, FinishDateClassInit } };
--- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -6451,18 +6451,20 @@ js::NewCompartment(JSContext* cx, Zone* zone = cx->new_<Zone>(rt); if (!zone) return nullptr; zoneHolder.reset(zone); const JSPrincipals* trusted = rt->trustedPrincipals(); bool isSystem = principals && principals == trusted; - if (!zone->init(isSystem)) + if (!zone->init(isSystem)) { + ReportOutOfMemory(cx); return nullptr; + } } ScopedJSDeletePtr<JSCompartment> compartment(cx->new_<JSCompartment>(zone, options)); if (!compartment || !compartment->init(cx)) return nullptr; // Set up the principals. JS_SetCompartmentPrincipals(compartment, principals); @@ -7094,17 +7096,17 @@ JS::IsIncrementalBarrierNeeded(JSContext } JS_PUBLIC_API(void) JS::IncrementalReferenceBarrier(GCCellPtr thing) { if (!thing) return; - if (thing.isString() && StringIsPermanentAtom(thing.toString())) + if (thing.isString() && thing.toString()->isPermanentAtom()) return; #ifdef DEBUG Zone* zone = thing.isObject() ? thing.toObject()->zone() : thing.asCell()->asTenured().zone(); MOZ_ASSERT(!zone->runtimeFromMainThread()->isHeapMajorCollecting()); #endif
--- a/js/src/jshashutil.h +++ b/js/src/jshashutil.h @@ -26,21 +26,25 @@ struct DependentAddPtr template <class Lookup> DependentAddPtr(const ExclusiveContext* cx, const T& table, const Lookup& lookup) : addPtr(table.lookupForAdd(lookup)) , originalGcNumber(cx->zone()->gcNumber()) {} template <class KeyInput, class ValueInput> - bool add(const ExclusiveContext* cx, T& table, const KeyInput& key, const ValueInput& value) { + bool add(ExclusiveContext* cx, T& table, const KeyInput& key, const ValueInput& value) { bool gcHappened = originalGcNumber != cx->zone()->gcNumber(); if (gcHappened) addPtr = table.lookupForAdd(key); - return table.relookupOrAdd(addPtr, key, value); + if (!table.relookupOrAdd(addPtr, key, value)) { + ReportOutOfMemory(cx); + return false; + } + return true; } bool found() const { return addPtr.found(); } explicit operator bool() const { return found(); } const Entry& operator*() const { return *addPtr; } const Entry* operator->() const { return &*addPtr; }
--- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -538,21 +538,24 @@ NativeIterator::allocateIterator(JSConte } } ni->next_ = nullptr; ni->prev_ = nullptr; return ni; } NativeIterator* -NativeIterator::allocateSentinel(JSContext* cx) +NativeIterator::allocateSentinel(JSContext* maybecx) { NativeIterator* ni = js_pod_malloc<NativeIterator>(); - if (!ni) + if (!ni) { + if (maybecx) + ReportOutOfMemory(maybecx); return nullptr; + } PodZero(ni); ni->next_ = ni; ni->prev_ = ni; return ni; }
--- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -97,17 +97,17 @@ struct NativeIterator MOZ_ASSERT(flags & JSITER_ENUMERATE); next_->prev_ = prev_; prev_->next_ = next_; next_ = nullptr; prev_ = nullptr; } - static NativeIterator* allocateSentinel(JSContext* cx); + static NativeIterator* allocateSentinel(JSContext* maybecx); static NativeIterator* allocateIterator(JSContext* cx, uint32_t slength, const js::AutoIdVector& props); void init(JSObject* obj, JSObject* iterObj, unsigned flags, uint32_t slength, uint32_t key); void mark(JSTracer* trc); static void destroy(NativeIterator* iter) { js_free(iter);
--- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -122,72 +122,88 @@ js::InformalValueTypeName(const Value& v return "boolean"; if (v.isNull()) return "null"; if (v.isUndefined()) return "undefined"; return "value"; } +// ES6 draft rev37 6.2.4.4 FromPropertyDescriptor bool js::FromPropertyDescriptor(JSContext* cx, Handle<PropertyDescriptor> desc, MutableHandleValue vp) { + // Step 1. if (!desc.object()) { vp.setUndefined(); return true; } return FromPropertyDescriptorToObject(cx, desc, vp); } bool js::FromPropertyDescriptorToObject(JSContext* cx, Handle<PropertyDescriptor> desc, MutableHandleValue vp) { + // Step 2-3. RootedObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx)); if (!obj) return false; const JSAtomState& names = cx->names(); - RootedValue v(cx); - if (desc.hasConfigurable()) { - v.setBoolean(desc.configurable()); - if (!DefineProperty(cx, obj, names.configurable, v)) - return false; - } - if (desc.hasEnumerable()) { - v.setBoolean(desc.enumerable()); - if (!DefineProperty(cx, obj, names.enumerable, v)) - return false; - } + + // Step 4. if (desc.hasValue()) { if (!DefineProperty(cx, obj, names.value, desc.value())) return false; } + + // Step 5. + RootedValue v(cx); if (desc.hasWritable()) { v.setBoolean(desc.writable()); if (!DefineProperty(cx, obj, names.writable, v)) return false; } + + // Step 6. if (desc.hasGetterObject()) { if (JSObject* get = desc.getterObject()) v.setObject(*get); else v.setUndefined(); if (!DefineProperty(cx, obj, names.get, v)) return false; } + + // Step 7. if (desc.hasSetterObject()) { if (JSObject* set = desc.setterObject()) v.setObject(*set); else v.setUndefined(); if (!DefineProperty(cx, obj, names.set, v)) return false; } + + // Step 8. + if (desc.hasEnumerable()) { + v.setBoolean(desc.enumerable()); + if (!DefineProperty(cx, obj, names.enumerable, v)) + return false; + } + + // Step 9. + if (desc.hasConfigurable()) { + v.setBoolean(desc.configurable()); + if (!DefineProperty(cx, obj, names.configurable, v)) + return false; + } + vp.setObject(*obj); return true; } bool js::GetFirstArgumentAsObject(JSContext* cx, const CallArgs& args, const char* method, MutableHandleObject objp) {
--- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -28,17 +28,17 @@ #include "vm/Xdr.h" namespace JS { struct ClassInfo; } namespace js { -class AutoPropertyDescriptorVector; +typedef AutoVectorRooter<PropertyDescriptor> AutoPropertyDescriptorVector; class GCMarker; class Nursery; namespace gc { class RelocationOverlay; } inline JSObject*
--- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -566,28 +566,17 @@ inline bool IsInternalFunctionObject(JSObject* funobj) { JSFunction* fun = &funobj->as<JSFunction>(); MOZ_ASSERT_IF(fun->isLambda(), fun->isInterpreted() || fun->isAsmJSNative()); return fun->isLambda() && fun->isInterpreted() && !fun->environment(); } -class AutoPropertyDescriptorVector : public AutoVectorRooter<PropertyDescriptor> -{ - public: - explicit AutoPropertyDescriptorVector(JSContext* cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter(cx, DESCVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; +typedef AutoVectorRooter<PropertyDescriptor> AutoPropertyDescriptorVector; /* * Make an object with the specified prototype. If parent is null, it will * default to the prototype's global if the prototype is non-null. */ JSObject* NewObjectWithGivenTaggedProto(ExclusiveContext* cx, const Class* clasp, Handle<TaggedProto> proto, gc::AllocKind allocKind, NewObjectKind newKind);
--- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -21,33 +21,37 @@ #include "js/TypeDecls.h" #if defined(JS_GC_ZEAL) || defined(DEBUG) # define JSGC_HASH_TABLE_CHECKS #endif namespace JS { -class AutoIdVector; +template <typename T> +class AutoVectorRooter; +typedef AutoVectorRooter<jsid> AutoIdVector; class CallArgs; template <typename T> class Rooted; class JS_FRIEND_API(CompileOptions); class JS_FRIEND_API(ReadOnlyCompileOptions); class JS_FRIEND_API(OwningCompileOptions); class JS_PUBLIC_API(CompartmentOptions); +class Value; struct Zone; } /* namespace JS */ namespace js { struct ContextFriendFields; +class Shape; } // namespace js /* * Run-time version enumeration. For compile-time version checking, please use * the JS_HAS_* macros in jsversion.h, or use MOZJS_MAJOR_VERSION, * MOZJS_MINOR_VERSION, MOZJS_PATCH_VERSION, and MOZJS_ALPHA definitions. */ enum JSVersion { @@ -260,20 +264,27 @@ class JS_PUBLIC_API(AutoGCRooter) HASHABLEVALUE=-18, /* js::HashableValue */ IONMASM = -19, /* js::jit::MacroAssembler */ WRAPVECTOR = -20, /* js::AutoWrapperVector */ WRAPPER = -21, /* js::AutoWrapperRooter */ OBJOBJHASHMAP=-22, /* js::AutoObjectObjectHashMap */ OBJU32HASHMAP=-23, /* js::AutoObjectUnsigned32HashMap */ OBJHASHSET = -24, /* js::AutoObjectHashSet */ JSONPARSER = -25, /* js::JSONParser */ - CUSTOM = -26, /* js::CustomAutoRooter */ - FUNVECTOR = -27 /* js::AutoFunctionVector */ + CUSTOM = -26 /* js::CustomAutoRooter */ }; + static ptrdiff_t GetTag(const Value& value) { return VALVECTOR; } + static ptrdiff_t GetTag(const jsid& id) { return IDVECTOR; } + static ptrdiff_t GetTag(JSObject* obj) { return OBJVECTOR; } + static ptrdiff_t GetTag(JSScript* script) { return SCRIPTVECTOR; } + static ptrdiff_t GetTag(JSString* string) { return STRINGVECTOR; } + static ptrdiff_t GetTag(js::Shape* shape) { return SHAPEVECTOR; } + static ptrdiff_t GetTag(const JSPropertyDescriptor& pd) { return DESCVECTOR; } + private: AutoGCRooter ** const stackTop; /* No copy or assignment semantics. */ AutoGCRooter(AutoGCRooter& ida) = delete; void operator=(AutoGCRooter& ida) = delete; };
--- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -1587,18 +1587,20 @@ ScriptSource::chars(JSContext* cx, Uncom return uncompressedChars(); case DataCompressed: { if (const char16_t* decompressed = cx->runtime()->uncompressedSourceCache.lookup(this, holder)) return decompressed; const size_t nbytes = sizeof(char16_t) * (length_ + 1); char16_t* decompressed = static_cast<char16_t*>(js_malloc(nbytes)); - if (!decompressed) + if (!decompressed) { + JS_ReportOutOfMemory(cx); return nullptr; + } if (!DecompressString((const unsigned char*) compressedData(), compressedBytes(), reinterpret_cast<unsigned char*>(decompressed), nbytes)) { JS_ReportOutOfMemory(cx); js_free(decompressed); return nullptr; }
--- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -641,17 +641,17 @@ InitWeakMapClass(JSContext* cx, HandleOb Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>()); RootedObject weakMapProto(cx, global->createBlankPrototype(cx, &WeakMapObject::class_)); if (!weakMapProto) return nullptr; RootedFunction ctor(cx, global->createConstructor(cx, WeakMap_construct, - cx->names().WeakMap, 1)); + cx->names().WeakMap, 0)); if (!ctor) return nullptr; if (!LinkConstructorAndPrototype(cx, ctor, weakMapProto)) return nullptr; if (defineMembers) { if (!DefinePropertiesAndFunctions(cx, weakMapProto, nullptr, weak_map_methods))
--- a/js/src/shell/moz.build +++ b/js/src/shell/moz.build @@ -11,20 +11,17 @@ if CONFIG['JS_SHELL_NAME']: USE_LIBS += ['static:js'] UNIFIED_SOURCES += [ 'js.cpp', 'jsoptparse.cpp', 'OSObject.cpp' ] -# Building against js_static requires that we declare mfbt sybols "exported" -# on its behalf. -for var in ('EXPORT_JS_API', 'IMPL_MFBT'): - DEFINES[var] = True +DEFINES['EXPORT_JS_API'] = True if CONFIG['_MSC_VER']: # unnecessary PGO for js shell. But gcc cannot turn off pgo because it is # necessary to link PGO lib on gcc when a object/static lib are compiled # for PGO. NO_PGO = True LOCAL_INCLUDES += ['..']
new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_5/Date/UTC-convert-all-arguments.js @@ -0,0 +1,70 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1160356; +var summary = + "Date.UTC must convert *all* arguments to number, not return NaN early if " + + "a non-finite argument is encountered"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectThrowTypeError(f, i) +{ + try + { + f(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e, 42, "index " + i + ": expected 42, got " + e); + } +} + +var bad = + { toString: function() { throw 17; }, valueOf: function() { throw 42; } }; + +var args = + [ + [bad], + + [NaN, bad], + [Infinity, bad], + [1970, bad], + + [1970, NaN, bad], + [1970, Infinity, bad], + [1970, 4, bad], + + [1970, 4, NaN, bad], + [1970, 4, Infinity, bad], + [1970, 4, 17, bad], + + [1970, 4, 17, NaN, bad], + [1970, 4, 17, Infinity, bad], + [1970, 4, 17, 13, bad], + + [1970, 4, 17, 13, NaN, bad], + [1970, 4, 17, 13, Infinity, bad], + [1970, 4, 17, 13, 37, bad], + + [1970, 4, 17, 13, 37, NaN, bad], + [1970, 4, 17, 13, 37, Infinity, bad], + [1970, 4, 17, 13, 37, 23, bad], + ]; + +for (var i = 0, len = args.length; i < len; i++) + expectThrowTypeError(function() { Date.UTC.apply(null, args[i]); }, i); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete");
new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_5/Date/constructor-convert-all-arguments.js @@ -0,0 +1,70 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1160356; +var summary = + "new Date(...) must convert *all* arguments to number, not return NaN " + + "early if a non-finite argument is encountered"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectThrowTypeError(f, i) +{ + try + { + f(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e, 42, "index " + i + ": expected 42, got " + e); + } +} + +var bad = + { toString: function() { throw 17; }, valueOf: function() { throw 42; } }; + +var funcs = + [ + function() { new Date(bad); }, + + function() { new Date(NaN, bad); }, + function() { new Date(Infinity, bad); }, + function() { new Date(1970, bad); }, + + function() { new Date(1970, NaN, bad); }, + function() { new Date(1970, Infinity, bad); }, + function() { new Date(1970, 4, bad); }, + + function() { new Date(1970, 4, NaN, bad); }, + function() { new Date(1970, 4, Infinity, bad); }, + function() { new Date(1970, 4, 17, bad); }, + + function() { new Date(1970, 4, 17, NaN, bad); }, + function() { new Date(1970, 4, 17, Infinity, bad); }, + function() { new Date(1970, 4, 17, 13, bad); }, + + function() { new Date(1970, 4, 17, 13, NaN, bad); }, + function() { new Date(1970, 4, 17, 13, Infinity, bad); }, + function() { new Date(1970, 4, 17, 13, 37, bad); }, + + function() { new Date(1970, 4, 17, 13, 37, NaN, bad); }, + function() { new Date(1970, 4, 17, 13, 37, Infinity, bad); }, + function() { new Date(1970, 4, 17, 13, 37, 23, bad); }, + ]; + +for (var i = 0, len = funcs.length; i < len; i++) + expectThrowTypeError(funcs[i]); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete");
--- a/js/src/tests/ecma_6/Object/getOwnPropertyDescriptor.js +++ b/js/src/tests/ecma_6/Object/getOwnPropertyDescriptor.js @@ -13,23 +13,23 @@ assertThrowsInstanceOf(() => Object.getO Object.getOwnPropertyDescriptor(1); Object.getOwnPropertyDescriptor(true); if (typeof Symbol === "function") { Object.getOwnPropertyDescriptor(Symbol("foo")); } assertDeepEq(Object.getOwnPropertyDescriptor("foo", "length"), { - configurable: false, + value: 3, + writable: false, enumerable: false, - value: 3, - writable: false + configurable: false }); assertDeepEq(Object.getOwnPropertyDescriptor("foo", 0), { - configurable: false, + value: "f", + writable: false, enumerable: true, - value: "f", - writable: false + configurable: false }); if (typeof reportCompare === "function") reportCompare(true, true);
new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_6/Object/property-descriptor-order.js @@ -0,0 +1,17 @@ +var names = Object.getOwnPropertyNames(Object.getOwnPropertyDescriptor({foo: 0}, "foo")); +assertDeepEq(names, ["value", "writable", "enumerable", "configurable"]); + +names = Object.getOwnPropertyNames(Object.getOwnPropertyDescriptor({get foo(){}}, "foo")); +assertDeepEq(names, ["get", "set", "enumerable", "configurable"]); + +var proxy = new Proxy({}, { + defineProperty(target, key, desc) { + var names = Object.getOwnPropertyNames(desc); + assertDeepEq(names, ["set", "configurable"]); + return true; + } +}); + +Object.defineProperty(proxy, "foo", {configurable: true, set: function() {}}); + +reportCompare(true, true);
--- a/js/src/tests/ecma_6/Symbol/property-basics.js +++ b/js/src/tests/ecma_6/Symbol/property-basics.js @@ -20,20 +20,20 @@ for (var sym of symbols) { assertEq(Object.getOwnPropertyDescriptor(obj, sym), undefined); // assign, then try accessing again obj[sym] = "ok"; assertEq(sym in obj, true); assertEq(obj.hasOwnProperty(sym), true); assertEq(obj[sym], "ok"); assertDeepEq(Object.getOwnPropertyDescriptor(obj, sym), { - configurable: true, + value: "ok", + writable: true, enumerable: true, - value: "ok", - writable: true + configurable: true }); // assign again, observe value is overwritten obj[sym] = 12; assertEq(obj[sym], 12); // increment assertEq(obj[sym]++, 12);
--- a/js/src/tests/ecma_6/Symbol/property-reflection.js +++ b/js/src/tests/ecma_6/Symbol/property-reflection.js @@ -16,27 +16,27 @@ assertEq(Symbol.for("name") in f, true); assertEq(f[Symbol.for("name")], "eff"); // Object.defineProperties function D() {} var descs = new D; var s1 = Symbol("s1"); var hits = 0; descs[s1] = { - configurable: true, + get: () => hits++, + set: undefined, enumerable: true, - get: () => hits++, - set: undefined + configurable: true }; var s2 = Symbol("s2"); descs[s2] = { - configurable: true, + value: {}, + writable: true, enumerable: false, - value: {}, - writable: true + configurable: true }; var s3 = Symbol("s3"); D.prototype[s3] = {value: "FAIL"}; assertEq(Object.defineProperties(f, descs), f); assertEq(s1 in f, true); assertEq(f[s1], 0); assertEq(hits, 1); assertEq(s2 in f, true);
--- a/js/src/tests/ecma_6/TypedArray/of.js +++ b/js/src/tests/ecma_6/TypedArray/of.js @@ -9,20 +9,20 @@ const constructors = [ Float32Array, Float64Array ]; for (var constructor of constructors) { assertEq(constructor.of.length, 0); assertDeepEq(Object.getOwnPropertyDescriptor(constructor.__proto__, "of"), { - configurable: true, + value: constructor.of, + writable: true, enumerable: false, - value: constructor.of, - writable: true + configurable: true }); // Basic tests. assertEq(constructor.of().constructor, constructor); assertEq(constructor.of() instanceof constructor, true); assertDeepEq(constructor.of(10), new constructor([10])); assertDeepEq(constructor.of(1, 2, 3), new constructor([1, 2, 3])); assertDeepEq(constructor.of("1", "2", "3"), new constructor([1, 2, 3]));
--- a/js/src/tests/ecma_7/SIMD/float64x2-arithmetic.js +++ b/js/src/tests/ecma_7/SIMD/float64x2-arithmetic.js @@ -47,17 +47,18 @@ function testSqrt(v) { function test() { print(BUGNUMBER + ": " + summary); var v, w; for ([v, w] of [[float64x2(1, 2), float64x2(3, 4)], [float64x2(1.894, 2.8909), float64x2(100.764, 200.987)], [float64x2(-1, -2), float64x2(-14.54, 57)], - [float64x2(+Infinity, -Infinity), float64x2(NaN, -0)]]) + [float64x2(+Infinity, -Infinity), float64x2(NaN, -0)], + [float64x2(Math.pow(2, 31), Math.pow(2, -31)), float64x2(Math.pow(2, -1047), Math.pow(2, -149))]]) { testAdd(v, w); testSub(v, w); testMul(v, w); testDiv(v, w); testAbs(v); testNeg(v); testReciprocalApproximation(v);
--- a/js/src/tests/ecma_7/SIMD/unary-operations.js +++ b/js/src/tests/ecma_7/SIMD/unary-operations.js @@ -46,23 +46,26 @@ function testFloat32x4reciprocalApproxim for (var [v,w] of vals) { assertEqX4(float32x4.reciprocalApproximation(float32x4(...v)), w); } } function testFloat32x4reciprocalSqrtApproximation() { function reciprocalsqrtf(a) { - return Math.fround(1 / Math.sqrt(a)); + assertEq(Math.fround(a), a); + return Math.fround(1 / Math.fround(Math.sqrt(a))); } var vals = [ [[1, 1, 0.25, 0.25], [1, 1, 2, 2]], [[25, 16, 6.25, 1.5625], [25, 16, 6.25, 1.5625].map(reciprocalsqrtf)], - [[NaN, -0, Infinity, -Infinity], [NaN, -0, Infinity, -Infinity].map(reciprocalsqrtf)] + [[NaN, -0, Infinity, -Infinity], [NaN, -0, Infinity, -Infinity].map(reciprocalsqrtf)], + [[Math.pow(2, 32), Math.pow(2, -32), +0, Math.pow(2, -148)], + [Math.pow(2, -16), Math.pow(2, 16), Infinity, Math.pow(2, 74)]] ]; for (var [v,w] of vals) { assertEqX4(float32x4.reciprocalSqrtApproximation(float32x4(...v)), w); } } function testFloat32x4sqrt() {
--- a/js/src/vm/CharacterEncoding.cpp +++ b/js/src/vm/CharacterEncoding.cpp @@ -335,18 +335,20 @@ InflateUTF8StringHelper(JSContext* cx, c { *outlen = 0; bool isAscii; if (!countAction(cx, src, /* dst = */ nullptr, outlen, &isAscii)) return TwoByteCharsZ(); char16_t* dst = cx->pod_malloc<char16_t>(*outlen + 1); // +1 for NUL - if (!dst) + if (!dst) { + ReportOutOfMemory(cx); return TwoByteCharsZ(); + } if (isAscii) { size_t srclen = src.length(); MOZ_ASSERT(*outlen == srclen); for (uint32_t i = 0; i < srclen; i++) dst[i] = char16_t(src[i]); } else {
--- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -783,20 +783,18 @@ Debugger::wrapEnvironment(JSContext* cx, /* Create a new Debugger.Environment for env. */ RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_ENV_PROTO).toObject()); envobj = NewNativeObjectWithGivenProto(cx, &DebuggerEnv_class, proto, TenuredObject); if (!envobj) return false; envobj->setPrivateGCThing(env); envobj->setReservedSlot(JSSLOT_DEBUGENV_OWNER, ObjectValue(*object)); - if (!p.add(cx, environments, env, envobj)) { - ReportOutOfMemory(cx); + if (!p.add(cx, environments, env, envobj)) return false; - } CrossCompartmentKey key(CrossCompartmentKey::DebuggerEnvironment, object, env); if (!object->compartment()->putWrapper(cx, key, ObjectValue(*envobj))) { environments.remove(env); ReportOutOfMemory(cx); return false; } } @@ -827,20 +825,18 @@ Debugger::wrapDebuggeeValue(JSContext* c NativeObject* dobj = NewNativeObjectWithGivenProto(cx, &DebuggerObject_class, proto, TenuredObject); if (!dobj) return false; dobj->setPrivateGCThing(obj); dobj->setReservedSlot(JSSLOT_DEBUGOBJECT_OWNER, ObjectValue(*object)); - if (!p.add(cx, objects, obj, dobj)) { - ReportOutOfMemory(cx); + if (!p.add(cx, objects, obj, dobj)) return false; - } if (obj->compartment() != object->compartment()) { CrossCompartmentKey key(CrossCompartmentKey::DebuggerObject, object, obj); if (!object->compartment()->putWrapper(cx, key, ObjectValue(*dobj))) { objects.remove(obj); ReportOutOfMemory(cx); return false; } @@ -4344,20 +4340,18 @@ Debugger::wrapScript(JSContext* cx, Hand assertSameCompartment(cx, object.get()); MOZ_ASSERT(cx->compartment() != script->compartment()); DependentAddPtr<ScriptWeakMap> p(cx, scripts, script); if (!p) { JSObject* scriptobj = newDebuggerScript(cx, script); if (!scriptobj) return nullptr; - if (!p.add(cx, scripts, script, scriptobj)) { - ReportOutOfMemory(cx); + if (!p.add(cx, scripts, script, scriptobj)) return nullptr; - } CrossCompartmentKey key(CrossCompartmentKey::DebuggerScript, object, script); if (!object->compartment()->putWrapper(cx, key, ObjectValue(*scriptobj))) { scripts.remove(script); ReportOutOfMemory(cx); return nullptr; } } @@ -5365,20 +5359,18 @@ Debugger::wrapSource(JSContext* cx, Hand assertSameCompartment(cx, object.get()); MOZ_ASSERT(cx->compartment() != source->compartment()); DependentAddPtr<SourceWeakMap> p(cx, sources, source); if (!p) { JSObject* sourceobj = newDebuggerSource(cx, source); if (!sourceobj) return nullptr; - if (!p.add(cx, sources, source, sourceobj)) { - ReportOutOfMemory(cx); + if (!p.add(cx, sources, source, sourceobj)) return nullptr; - } CrossCompartmentKey key(CrossCompartmentKey::DebuggerSource, object, source); if (!object->compartment()->putWrapper(cx, key, ObjectValue(*sourceobj))) { sources.remove(source); ReportOutOfMemory(cx); return nullptr; } }
--- a/js/src/vm/ObjectGroup.cpp +++ b/js/src/vm/ObjectGroup.cpp @@ -468,16 +468,17 @@ ObjectGroup::defaultNewGroup(ExclusiveCo ObjectGroupCompartment::NewTable*& table = cx->compartment()->objectGroups.defaultNewTable; if (!table) { table = cx->new_<ObjectGroupCompartment::NewTable>(); if (!table || !table->init()) { js_delete(table); table = nullptr; + ReportOutOfMemory(cx); return nullptr; } } if (associated && associated->is<JSFunction>()) { MOZ_ASSERT(!clasp); // Canonicalize new functions to use the original one associated with its script. @@ -519,18 +520,20 @@ ObjectGroup::defaultNewGroup(ExclusiveCo initialFlags = OBJECT_FLAG_DYNAMIC_MASK; Rooted<TaggedProto> protoRoot(cx, proto); ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, clasp ? clasp : &PlainObject::class_, protoRoot, initialFlags); if (!group) return nullptr; - if (!table->add(p, ObjectGroupCompartment::NewEntry(group, associated))) + if (!table->add(p, ObjectGroupCompartment::NewEntry(group, associated))) { + ReportOutOfMemory(cx); return nullptr; + } ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, associated); if (proto.isObject()) { RootedObject obj(cx, proto.toObject()); if (associated) { if (associated->is<JSFunction>()) @@ -576,16 +579,17 @@ ObjectGroup::lazySingletonGroup(Exclusiv { MOZ_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment()); ObjectGroupCompartment::NewTable*& table = cx->compartment()->objectGroups.lazyTable; if (!table) { table = cx->new_<ObjectGroupCompartment::NewTable>(); if (!table || !table->init()) { + ReportOutOfMemory(cx); js_delete(table); table = nullptr; return nullptr; } } ObjectGroupCompartment::NewTable::AddPtr p = table->lookupForAdd(ObjectGroupCompartment::NewEntry::Lookup(clasp, proto, nullptr)); @@ -600,18 +604,20 @@ ObjectGroup::lazySingletonGroup(Exclusiv Rooted<TaggedProto> protoRoot(cx, proto); ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, clasp, protoRoot, OBJECT_FLAG_SINGLETON | OBJECT_FLAG_LAZY_SINGLETON); if (!group) return nullptr; - if (!table->add(p, ObjectGroupCompartment::NewEntry(group, nullptr))) + if (!table->add(p, ObjectGroupCompartment::NewEntry(group, nullptr))) { + ReportOutOfMemory(cx); return nullptr; + } ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, nullptr); return group; } /* static */ void ObjectGroup::setDefaultNewGroupUnknown(JSContext* cx, const Class* clasp, HandleObject obj) @@ -832,17 +838,18 @@ ObjectGroup::setGroupToHomogenousArray(E ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, &ArrayObject::class_, taggedProto); if (!group) return; obj->setGroup(group); AddTypePropertyId(cx, group, nullptr, JSID_VOID, elementType); key.proto = objProto; - (void) p.add(cx, *table, key, group); + if (!p.add(cx, *table, key, group)) + cx->recoverFromOutOfMemory(); } } ///////////////////////////////////////////////////////////////////// // ObjectGroupCompartment PlainObjectTable ///////////////////////////////////////////////////////////////////// struct ObjectGroupCompartment::PlainObjectKey
--- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -895,16 +895,19 @@ RegExpCompartment::init(JSContext* cx) } return true; } void RegExpCompartment::sweep(JSRuntime* rt) { + if (!set_.initialized()) + return; + for (Set::Enum e(set_); !e.empty(); e.popFront()) { RegExpShared* shared = e.front(); // Sometimes RegExpShared instances are marked without the // compartment being subsequently cleared. This can happen if a GC is // restarted while in progress (i.e. performing a full GC in the // middle of an incremental GC) or if a RegExpShared referenced via the // stack is traced but is not in a zone being collected.
--- a/js/src/vm/Runtime-inl.h +++ b/js/src/vm/Runtime-inl.h @@ -55,18 +55,21 @@ NewObjectCache::newObjectFromHit(JSConte if (group->shouldPreTenure()) heap = gc::TenuredHeap; if (cx->runtime()->gc.upcomingZealousGC()) return nullptr; NativeObject* obj = static_cast<NativeObject*>(Allocate<JSObject, NoGC>(cx, entry->kind, 0, heap, group->clasp())); - if (!obj) + if (!obj) { + // It's expected that this can return nullptr. + cx->recoverFromOutOfMemory(); return nullptr; + } copyCachedToObject(obj, templateObj, entry->kind); SetNewObjectMetadata(cx, obj); probes::CreateObject(cx, obj); gc::TraceCreateObject(obj); return obj;
--- a/js/src/vm/SavedStacks.cpp +++ b/js/src/vm/SavedStacks.cpp @@ -1032,20 +1032,18 @@ SavedStacks::getOrCreateSavedFrame(JSCon DependentAddPtr<SavedFrame::Set> p(cx, frames, lookupInstance); if (p) return *p; RootedSavedFrame frame(cx, createFrameFromLookup(cx, lookup)); if (!frame) return nullptr; - if (!p.add(cx, frames, lookupInstance, frame)) { - ReportOutOfMemory(cx); + if (!p.add(cx, frames, lookupInstance, frame)) return nullptr; - } return frame; } SavedFrame* SavedStacks::createFrameFromLookup(JSContext* cx, SavedFrame::HandleLookup lookup) { RootedGlobalObject global(cx, cx->global());
--- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1242,18 +1242,20 @@ BaseShape::adoptUnowned(UnownedBaseShape assertConsistency(); } /* static */ UnownedBaseShape* BaseShape::getUnowned(ExclusiveContext* cx, StackBaseShape& base) { BaseShapeSet& table = cx->compartment()->baseShapes; - if (!table.initialized() && !table.init()) + if (!table.initialized() && !table.init()) { + ReportOutOfMemory(cx); return nullptr; + } DependentAddPtr<BaseShapeSet> p(cx, table, base); if (p) return *p; BaseShape* nbase_ = Allocate<BaseShape>(cx); if (!nbase_) return nullptr; @@ -1475,18 +1477,20 @@ EmptyShape::new_(ExclusiveContext* cx, H /* static */ Shape* EmptyShape::getInitialShape(ExclusiveContext* cx, const Class* clasp, TaggedProto proto, size_t nfixed, uint32_t objectFlags) { MOZ_ASSERT_IF(proto.isObject(), cx->isInsideCurrentCompartment(proto.toObject())); InitialShapeSet& table = cx->compartment()->initialShapes; - if (!table.initialized() && !table.init()) + if (!table.initialized() && !table.init()) { + ReportOutOfMemory(cx); return nullptr; + } typedef InitialShapeEntry::Lookup Lookup; DependentAddPtr<InitialShapeSet> p(cx, table, Lookup(clasp, proto, nfixed, objectFlags)); if (p) return p->shape; Rooted<TaggedProto> protoRoot(cx, proto);
--- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -258,18 +258,20 @@ InterpreterStack::allocateFrame(JSContex maxFrames = MAX_FRAMES; if (MOZ_UNLIKELY(frameCount_ >= maxFrames)) { ReportOverRecursed(cx); return nullptr; } uint8_t* buffer = reinterpret_cast<uint8_t*>(allocator_.alloc(size)); - if (!buffer) + if (!buffer) { + ReportOutOfMemory(cx); return nullptr; + } frameCount_++; return buffer; } MOZ_ALWAYS_INLINE InterpreterFrame* InterpreterStack::getCallFrame(JSContext* cx, const CallArgs& args, HandleScript script, InterpreterFrame::Flags* flags, Value** pargv)
--- a/js/src/vm/String.h +++ b/js/src/vm/String.h @@ -1127,23 +1127,23 @@ static_assert(sizeof(PropertyName) == si "string subclasses must be binary-compatible with JSString"); static MOZ_ALWAYS_INLINE jsid NameToId(PropertyName* name) { return NON_INTEGER_ATOM_TO_JSID(name); } -class AutoNameVector : public AutoVectorRooter<PropertyName*> +class AutoNameVector : public JS::AutoVectorRooterBase<PropertyName*> { - typedef AutoVectorRooter<PropertyName*> BaseType; + typedef AutoVectorRooterBase<PropertyName*> BaseType; public: explicit AutoNameVector(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter<PropertyName*>(cx, NAMEVECTOR) + : AutoVectorRooterBase<PropertyName*>(cx, NAMEVECTOR) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; } HandlePropertyName operator[](size_t i) const { return HandlePropertyName::fromMarkedLocation(&begin()[i]); }
--- a/js/src/vm/TraceLogging.cpp +++ b/js/src/vm/TraceLogging.cpp @@ -180,20 +180,20 @@ TraceLoggerThread::initGraph() TraceLoggerThread::~TraceLoggerThread() { if (graph.get()) { if (!failed) graph->log(events); graph = nullptr; } - for (TextIdHashMap::Range r = extraTextId.all(); !r.empty(); r.popFront()) - js_delete(r.front().value()); - extraTextId.finish(); - pointerMap.finish(); + if (extraTextId.initialized()) { + for (TextIdHashMap::Range r = extraTextId.all(); !r.empty(); r.popFront()) + js_delete(r.front().value()); + } } bool TraceLoggerThread::enable() { if (enabled > 0) { enabled++; return true;
--- a/js/xpconnect/wrappers/FilteringWrapper.h +++ b/js/xpconnect/wrappers/FilteringWrapper.h @@ -10,17 +10,19 @@ #include "XrayWrapper.h" #include "mozilla/Attributes.h" #include "jswrapper.h" #include "js/CallNonGenericMethod.h" struct JSPropertyDescriptor; namespace JS { -class AutoIdVector; +template <typename T> +class AutoVectorRooter; +typedef AutoVectorRooter<jsid> AutoIdVector; } namespace xpc { template <typename Base, typename Policy> class FilteringWrapper : public Base { public: MOZ_CONSTEXPR explicit FilteringWrapper(unsigned flags) : Base(flags) {}
--- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -541,17 +541,16 @@ struct NewLayerEntry { // The following are only used for retained layers (for occlusion // culling of those layers). These regions are all relative to the // container reference frame. nsIntRegion mVisibleRegion; nsIntRegion mOpaqueRegion; // This rect is in the layer's own coordinate space. The computed visible // region for the layer cannot extend beyond this rect. nsIntRect mLayerContentsVisibleRect; - nsTArray<nsDisplayScrollInfoLayer*> mScrollInfoItems; bool mHideAllLayersBelow; // When mOpaqueForAnimatedGeometryRootParent is true, the opaque region of // this layer is opaque in the same position even subject to the animation of // geometry of mAnimatedGeometryRoot. For example when mAnimatedGeometryRoot // is a scrolled frame and the scrolled content is opaque everywhere in the // displayport, we can set this flag. // When this flag is set, we can treat this opaque region as covering // content whose animated geometry root is the animated geometry root for @@ -914,21 +913,16 @@ public: // When AllowResidualTranslation is false, display items will be drawn // scaled with a translation by integer pixels, so we know how the snapping // will work. mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() && !mParameters.AllowResidualTranslation(); CollectOldLayers(); } - ~ContainerState() - { - MOZ_ASSERT(mHoistedItems.IsEmpty()); - } - /** * This is the method that actually walks a display list and builds * the child layers. */ void ProcessDisplayItems(nsDisplayList* aList); /** * This finalizes all the open PaintedLayers by popping every element off * mPaintedLayerDataStack, then sets the children of the container layer @@ -996,26 +990,16 @@ public: * is in the coordinate space of the container reference frame. * aLayerContentsVisibleRect, if non-null, is in the layer's own * coordinate system. */ void SetOuterVisibleRegionForLayer(Layer* aLayer, const nsIntRegion& aOuterVisibleRegion, const nsIntRect* aLayerContentsVisibleRect = nullptr) const; - void AddHoistedItem(nsDisplayScrollInfoLayer* aItem) - { - mHoistedItems.AppendElement(aItem); - } - - void AddHoistedItems(const nsTArray<nsDisplayScrollInfoLayer*>& aItems) - { - mHoistedItems.AppendElements(aItems); - } - /** * Try to determine whether the PaintedLayer aData has a single opaque color * covering aRect. If successful, return that color, otherwise return * NS_RGBA(0,0,0,0). * If aRect turns out not to intersect any content in the layer, * *aOutIntersectsLayer will be set to false. */ nscolor FindOpaqueBackgroundColorInLayer(const PaintedLayerData* aData, @@ -1216,21 +1200,16 @@ protected: typedef nsAutoTArray<NewLayerEntry,1> AutoLayersArray; AutoLayersArray mNewChildLayers; nsTHashtable<nsRefPtrHashKey<PaintedLayer>> mPaintedLayersAvailableForRecycling; nsDataHashtable<nsPtrHashKey<Layer>, nsRefPtr<ImageLayer> > mRecycledMaskImageLayers; nscoord mAppUnitsPerDevPixel; bool mSnappingEnabled; bool mFlattenToSingleLayer; - /** - * In some cases we need to hoist nsDisplayScrollInfoLayer items out from a - * nested inactive container. This holds the items hoisted up from children. - */ - nsTArray<nsDisplayScrollInfoLayer*> mHoistedItems; }; class PaintedDisplayItemLayerUserData : public LayerUserData { public: PaintedDisplayItemLayerUserData() : mMaskClipCount(0), mForcedBackgroundColor(NS_RGBA(0,0,0,0)), @@ -1389,25 +1368,24 @@ FrameLayerBuilder::Shutdown() if (gMaskLayerImageCache) { delete gMaskLayerImageCache; gMaskLayerImageCache = nullptr; } } void FrameLayerBuilder::Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - PaintedLayerData* aLayerData, ContainerState* aContainingContainerState) + PaintedLayerData* aLayerData) { mDisplayListBuilder = aBuilder; mRootPresContext = aBuilder->RootReferenceFrame()->PresContext()->GetRootPresContext(); if (mRootPresContext) { mInitialDOMGeneration = mRootPresContext->GetDOMGeneration(); } mContainingPaintedLayer = aLayerData; - mContainingContainerState = aContainingContainerState; aManager->SetUserData(&gLayerManagerLayerBuilder, this); } void FrameLayerBuilder::FlashPaint(gfxContext *aContext) { float r = float(rand()) / RAND_MAX; float g = float(rand()) / RAND_MAX; @@ -2819,30 +2797,26 @@ void ContainerState::FinishPaintedLayerD nsRefPtr<PaintedLayer> paintedLayer = CreatePaintedLayer(data); data->mLayer = paintedLayer; NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, paintedLayer) < 0, "Layer already in list???"); mNewChildLayers[data->mNewChildLayersIndex].mLayer = paintedLayer.forget(); } - MOZ_ASSERT(mHoistedItems.IsEmpty()); - for (auto& item : data->mAssignedDisplayItems) { MOZ_ASSERT(item.mItem->GetType() != nsDisplayItem::TYPE_LAYER_EVENT_REGIONS); InvalidateForLayerChange(item.mItem, data->mLayer); mLayerBuilder->AddPaintedDisplayItem(data, item.mItem, item.mClip, *this, item.mLayerState, data->mAnimatedGeometryRootOffset); } NewLayerEntry* newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex]; - newLayerEntry->mScrollInfoItems.SwapElements(mHoistedItems); - nsRefPtr<Layer> layer; nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer(mBuilder); FLB_LOG_PAINTED_LAYER_DECISION(data, "Selecting layer for pld=%p\n", data); FLB_LOG_PAINTED_LAYER_DECISION(data, " Solid=%i, hasImage=%i, canOptimizeAwayPaintedLayer=%i\n", data->mIsSolidColorInVisibleRegion, !!imageContainer, CanOptimizeAwayPaintedLayer(data, mLayerBuilder)); @@ -3455,31 +3429,16 @@ ContainerState::ProcessDisplayItems(nsDi aList->RemoveBottom(); item->~nsDisplayItem(); item = aboveItem; } else { break; } } - nsDisplayItem::Type itemType = item->GetType(); - if (itemType == nsDisplayItem::TYPE_SCROLL_INFO_LAYER && - mLayerBuilder->GetContainingContainerState()) { - // We have encountered a scrollable area inside a nested (inactive) - // layer manager, so we need to hoist the item out into the parent; that - // way we will still generate a scrollinfo layer for it and the APZ can - // drive main-thread sync scrolling. - // Note: |item| is removed from aList and will be attached into the parent - // list, so we don't delete it here. - nsDisplayScrollInfoLayer* scrollInfoItem = static_cast<nsDisplayScrollInfoLayer*>(item); - scrollInfoItem->MarkHoisted(); - mLayerBuilder->GetContainingContainerState()->AddHoistedItem(scrollInfoItem); - continue; - } - nsDisplayList* itemSameCoordinateSystemChildren = item->GetSameCoordinateSystemChildren(); if (item->ShouldFlattenAway(mBuilder)) { aList->AppendToBottom(itemSameCoordinateSystemChildren); item->~nsDisplayItem(); continue; } @@ -3489,16 +3448,17 @@ ContainerState::ProcessDisplayItems(nsDi "items in a container layer should all have the same app units per dev pixel"); if (mBuilder->NeedToForceTransparentSurfaceForItem(item)) { aList->SetNeedsTransparentSurface(); } bool snap; nsRect itemContent = item->GetBounds(mBuilder, &snap); + nsDisplayItem::Type itemType = item->GetType(); if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) { nsDisplayLayerEventRegions* eventRegions = static_cast<nsDisplayLayerEventRegions*>(item); itemContent = eventRegions->GetHitRegionBounds(mBuilder, &snap); } nsIntRect itemDrawRect = ScaleToOutsidePixels(itemContent, snap); bool prerenderedTransform = itemType == nsDisplayItem::TYPE_TRANSFORM && static_cast<nsDisplayTransform*>(item)->ShouldPrerender(mBuilder); @@ -3981,17 +3941,17 @@ FrameLayerBuilder::AddPaintedDisplayItem if (entry) { entry->mContainerLayerFrame = aContainerState.GetContainerFrame(); if (entry->mContainerLayerGeneration == 0) { entry->mContainerLayerGeneration = mContainerLayerGeneration; } if (tempManager) { FLB_LOG_PAINTED_LAYER_DECISION(aLayerData, "Creating nested FLB for item %p\n", aItem); FrameLayerBuilder* layerBuilder = new FrameLayerBuilder(); - layerBuilder->Init(mDisplayListBuilder, tempManager, aLayerData, &aContainerState); + layerBuilder->Init(mDisplayListBuilder, tempManager, aLayerData); tempManager->BeginTransaction(); if (mRetainingManager) { layerBuilder->DidBeginRetainedLayerTransaction(tempManager); } UniquePtr<LayerProperties> props(LayerProperties::CloneFrom(tempManager->GetRoot())); nsRefPtr<Layer> tmpLayer = @@ -4407,68 +4367,16 @@ ContainerState::Finish(uint32_t* aTextCo mContainerLayer->InsertAfter(layer, prevChild); } else { NS_ASSERTION(layer->GetParent() == mContainerLayer, "Layer shouldn't be the child of some other container"); if (layer->GetPrevSibling() != prevChild) { mContainerLayer->RepositionChild(layer, prevChild); } } - - ContainerState* containingContainerState = mLayerBuilder->GetContainingContainerState(); - if (containingContainerState) { - containingContainerState->AddHoistedItems(mNewChildLayers[i].mScrollInfoItems); - } else { - // Build layers for all mNewChildLayers[i].mScrollInfoItems and insert - // them after layer. - for (nsDisplayScrollInfoLayer* item : mNewChildLayers[i].mScrollInfoItems) { - LayerState layerState = item->GetLayerState(mBuilder, mManager, mParameters); - MOZ_ASSERT(layerState == LAYER_ACTIVE_EMPTY); - nsRefPtr<Layer> scrollInfoLayer = item->BuildLayer(mBuilder, mManager, mParameters); - if (!scrollInfoLayer) { - item->~nsDisplayScrollInfoLayer(); - continue; - } - - mLayerBuilder->AddLayerDisplayItem(scrollInfoLayer, item, layerState, - nsPoint(), nullptr); - - const nsIFrame* animatedGeometryRoot = - nsLayoutUtils::GetAnimatedGeometryRootFor(item, mBuilder, mManager); - bool shouldFixToViewport = !animatedGeometryRoot->GetParent() && - item->ShouldFixToViewport(mManager); - const nsIFrame* fixedPosFrame = - FindFixedPosFrameForLayerData(animatedGeometryRoot, shouldFixToViewport); - - NewLayerEntry scrollInfoLayerEntry; - scrollInfoLayerEntry.mLayer = scrollInfoLayer; - scrollInfoLayerEntry.mAnimatedGeometryRoot = animatedGeometryRoot; - scrollInfoLayerEntry.mFixedPosFrameForLayerData = fixedPosFrame; - scrollInfoLayerEntry.mOpaqueForAnimatedGeometryRootParent = false; - scrollInfoLayerEntry.mBaseFrameMetrics = - item->ComputeFrameMetrics(scrollInfoLayer, mParameters); - SetupScrollingMetadata(&scrollInfoLayerEntry); - - if (!scrollInfoLayer->GetParent()) { - // This is not currently a child of the container, so just add it - // now. - mContainerLayer->InsertAfter(scrollInfoLayer, layer); - } else { - NS_ASSERTION(scrollInfoLayer->GetParent() == mContainerLayer, - "scrollInfoLayer shouldn't be the child of some other container"); - if (scrollInfoLayer->GetPrevSibling() != layer) { - mContainerLayer->RepositionChild(scrollInfoLayer, layer); - } - } - - layer = scrollInfoLayer; - item->~nsDisplayScrollInfoLayer(); - } - mNewChildLayers[i].mScrollInfoItems.Clear(); - } } // Remove old layers that have become unused. if (!layer) { layer = mContainerLayer->GetFirstChild(); } else { layer = layer->GetNextSibling(); }
--- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -185,18 +185,17 @@ public: ~FrameLayerBuilder() { MOZ_COUNT_DTOR(FrameLayerBuilder); } static void Shutdown(); void Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - PaintedLayerData* aLayerData = nullptr, - ContainerState* aContainingContainerState = nullptr); + PaintedLayerData* aLayerData = nullptr); /** * Call this to notify that we have just started a transaction on the * retained layer manager aManager. */ void DidBeginRetainedLayerTransaction(LayerManager* aManager); /** @@ -667,21 +666,16 @@ public: return mContainingPaintedLayer; } bool IsBuildingRetainedLayers() { return !mContainingPaintedLayer && mRetainingManager; } - ContainerState* GetContainingContainerState() - { - return mContainingContainerState; - } - /** * Attempt to build the most compressed layer tree possible, even if it means * throwing away existing retained buffers. */ void SetLayerTreeCompressionMode() { mInLayerTreeCompressionMode = true; } bool CheckInLayerTreeCompressionMode(); void ComputeGeometryChangeForItem(DisplayItemData* aData); @@ -723,18 +717,16 @@ protected: nsTHashtable<PaintedLayerItemsEntry> mPaintedLayerItems; /** * When building layers for an inactive layer, this is where the * inactive layer will be placed. */ PaintedLayerData* mContainingPaintedLayer; - ContainerState* mContainingContainerState; - /** * Saved generation counter so we can detect DOM changes. */ uint32_t mInitialDOMGeneration; /** * Set to true if we have detected and reported DOM modification during * the current paint. */
--- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -596,20 +596,22 @@ nsDisplayListBuilder::nsDisplayListBuild mLayerEventRegions(nullptr), mCurrentTableItem(nullptr), mCurrentFrame(aReferenceFrame), mCurrentReferenceFrame(aReferenceFrame), mCurrentAnimatedGeometryRoot(nullptr), mWillChangeBudgetCalculated(false), mDirtyRect(-1,-1,-1,-1), mGlassDisplayItem(nullptr), + mScrollInfoItemsForHoisting(nullptr), mMode(aMode), mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID), mCurrentScrollbarTarget(FrameMetrics::NULL_SCROLL_ID), mCurrentScrollbarFlags(0), + mSVGEffectsBuildingDepth(0), mBuildCaret(aBuildCaret), mIgnoreSuppression(false), mHadToIgnoreSuppression(false), mIsAtRootOfPseudoStackingContext(false), mIncludeAllOutOfFlows(false), mDescendIntoSubdocuments(true), mSelectedFramesOnly(false), mAccurateVisibleRegions(false), @@ -1212,16 +1214,47 @@ nsDisplayListBuilder::IsInWillChangeBudg const char16_t* params[] = { usageStr.get(), multiplierStr.get(), limitStr.get() }; key->Document()->WarnOnceAbout(nsIDocument::eWillChangeBudget, false, params, ArrayLength(params)); } return onBudget; } +void +nsDisplayListBuilder::EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage) +{ + MOZ_ASSERT(mSVGEffectsBuildingDepth >= 0); + MOZ_ASSERT(aHoistedItemsStorage); + if (mSVGEffectsBuildingDepth == 0) { + MOZ_ASSERT(!mScrollInfoItemsForHoisting); + mScrollInfoItemsForHoisting = aHoistedItemsStorage; + } + mSVGEffectsBuildingDepth++; +} + +void +nsDisplayListBuilder::ExitSVGEffectsContents() +{ + mSVGEffectsBuildingDepth--; + MOZ_ASSERT(mSVGEffectsBuildingDepth >= 0); + MOZ_ASSERT(mScrollInfoItemsForHoisting); + if (mSVGEffectsBuildingDepth == 0) { + mScrollInfoItemsForHoisting = nullptr; + } +} + +void +nsDisplayListBuilder::AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer* aScrollInfoItem) +{ + MOZ_ASSERT(ShouldBuildScrollInfoItemsForHoisting()); + MOZ_ASSERT(mScrollInfoItemsForHoisting); + mScrollInfoItemsForHoisting->AppendNewToTop(aScrollInfoItem); +} + void nsDisplayListSet::MoveTo(const nsDisplayListSet& aDestination) const { aDestination.BorderBackground()->AppendToTop(BorderBackground()); aDestination.BlockBorderBackgrounds()->AppendToTop(BlockBorderBackgrounds()); aDestination.Floats()->AppendToTop(Floats()); aDestination.Content()->AppendToTop(Content()); aDestination.PositionedDescendants()->AppendToTop(PositionedDescendants()); aDestination.Outlines()->AppendToTop(Outlines()); @@ -4298,17 +4331,16 @@ bool nsDisplayStickyPosition::TryMerge(n nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer( nsDisplayListBuilder* aBuilder, nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame) : nsDisplayWrapList(aBuilder, aScrollFrame) , mScrollFrame(aScrollFrame) , mScrolledFrame(aScrolledFrame) , mScrollParentId(aBuilder->GetCurrentScrollParentId()) - , mHoisted(false) { #ifdef NS_BUILD_REFCNT_LOGGING MOZ_COUNT_CTOR(nsDisplayScrollInfoLayer); #endif } #ifdef NS_BUILD_REFCNT_LOGGING nsDisplayScrollInfoLayer::~nsDisplayScrollInfoLayer() @@ -4320,21 +4352,17 @@ nsDisplayScrollInfoLayer::~nsDisplayScro already_AddRefed<Layer> nsDisplayScrollInfoLayer::BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aContainerParameters) { // In general for APZ with event-regions we no longer have a need for // scrollinfo layers. However, in some cases, there might be content that // cannot be layerized, and so needs to scroll synchronously. To handle those - // cases (which are indicated by setting mHoisted to true), we still want to - // generate scrollinfo layers. - if (!mHoisted) { - return nullptr; - } + // cases, we still want to generate scrollinfo layers. ContainerLayerParameters params = aContainerParameters; if (mScrolledFrame->GetContent() && nsLayoutUtils::GetCriticalDisplayPort(mScrolledFrame->GetContent(), nullptr)) { params.mInLowPrecisionDisplayPort = true; } return aManager->GetLayerBuilder()-> @@ -4343,27 +4371,17 @@ nsDisplayScrollInfoLayer::BuildLayer(nsD FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR); } LayerState nsDisplayScrollInfoLayer::GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aParameters) { - // See comment in BuildLayer - return mHoisted - ? LAYER_ACTIVE_EMPTY - : LAYER_NONE; -} - -bool -nsDisplayScrollInfoLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) -{ - // See comment in BuildLayer - return !mHoisted; + return LAYER_ACTIVE_EMPTY; } UniquePtr<FrameMetrics> nsDisplayScrollInfoLayer::ComputeFrameMetrics(Layer* aLayer, const ContainerLayerParameters& aContainerParameters) { ContainerLayerParameters params = aContainerParameters; if (mScrolledFrame->GetContent() && @@ -4714,26 +4732,30 @@ nsDisplayTransform::GetDeltaToPerspectiv } nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(const nsIFrame* aFrame, float aAppUnitsPerPixel, const nsRect* aBoundsOverride) : mFrame(aFrame) , mTransformList(aFrame->StyleDisplay()->mSpecifiedTransform) , mToTransformOrigin(GetDeltaToTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride)) - , mToPerspectiveOrigin(GetDeltaToPerspectiveOrigin(aFrame, aAppUnitsPerPixel)) , mChildPerspective(0) { const nsStyleDisplay* parentDisp = nullptr; nsStyleContext* parentStyleContext = aFrame->StyleContext()->GetParent(); if (parentStyleContext) { parentDisp = parentStyleContext->StyleDisplay(); } if (parentDisp && parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord) { mChildPerspective = parentDisp->mChildPerspective.GetCoordValue(); + // Calling GetDeltaToPerspectiveOrigin can be expensive, so we avoid + // calling it unnecessarily. + if (mChildPerspective > 0.0) { + mToPerspectiveOrigin = GetDeltaToPerspectiveOrigin(aFrame, aAppUnitsPerPixel); + } } } /* Wraps up the -moz-transform matrix in a change-of-basis matrix pair that * translates from local coordinate space to transform coordinate space, then * hands it back. */ gfx3DMatrix @@ -4821,17 +4843,17 @@ nsDisplayTransform::GetResultingTransfor if (aProperties.mChildPerspective > 0.0) { gfx3DMatrix perspective; perspective._34 = -1.0 / NSAppUnitsToFloatPixels(aProperties.mChildPerspective, aAppUnitsPerPixel); /* At the point when perspective is applied, we have been translated to the transform origin. * The translation to the perspective origin is the difference between these values. */ - perspective.ChangeBasis(aProperties.mToPerspectiveOrigin - aProperties.mToTransformOrigin); + perspective.ChangeBasis(aProperties.GetToPerspectiveOrigin() - aProperties.mToTransformOrigin); result = result * perspective; } /* Account for the -moz-transform-origin property by translating the * coordinate space to the new origin. */ Point3D newOrigin = Point3D(NSAppUnitsToFloatPixels(aOrigin.x, aAppUnitsPerPixel),
--- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -35,16 +35,17 @@ #include <stdlib.h> #include <algorithm> class nsIContent; class nsRenderingContext; class nsDisplayTableItem; class nsISelection; class nsDisplayLayerEventRegions; +class nsDisplayScrollInfoLayer; class nsCaret; namespace mozilla { class FrameLayerBuilder; namespace layers { class Layer; class ImageLayer; class ImageContainer; @@ -342,17 +343,19 @@ public: nsDisplayLayerEventRegions* GetLayerEventRegions() { return mLayerEventRegions; } void SetLayerEventRegions(nsDisplayLayerEventRegions* aItem) { mLayerEventRegions = aItem; } bool IsBuildingLayerEventRegions() { if (mMode == PAINTING) { - return (gfxPrefs::LayoutEventRegionsEnabled() || + // Note: this is the only place that gets to query LayoutEventRegionsEnabled + // 'directly' - other code should call this function. + return (gfxPrefs::LayoutEventRegionsEnabledDoNotUseDirectly() || gfxPrefs::AsyncPanZoomEnabled()); } return false; } bool IsInsidePointerEventsNoneDoc() { return CurrentPresShellState()->mInsidePointerEventsNoneDoc; } @@ -838,16 +841,24 @@ public: * Look up the cached animated geometry root for aFrame subject to * aStopAtAncestor. Store the nsIFrame* result into *aOutResult, and return * true if the cache was hit. Return false if the cache was not hit. */ bool GetCachedAnimatedGeometryRoot(const nsIFrame* aFrame, const nsIFrame* aStopAtAncestor, nsIFrame** aOutResult); + void EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage); + void ExitSVGEffectsContents(); + + bool ShouldBuildScrollInfoItemsForHoisting() const + { return mSVGEffectsBuildingDepth > 0; } + + void AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer* aScrollInfoItem); + private: void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame, const nsRect& aDirtyRect); struct PresShellState { nsIPresShell* mPresShell; nsIFrame* mCaretFrame; nsRect mCaretRect; @@ -921,22 +932,29 @@ private: mutable mozilla::DebugOnly<bool> mWillChangeBudgetCalculated; // Relative to mCurrentFrame. nsRect mDirtyRect; nsRegion mWindowExcludeGlassRegion; nsRegion mWindowOpaqueRegion; nsIntRegion mWindowDraggingRegion; // The display item for the Windows window glass background, if any nsDisplayItem* mGlassDisplayItem; + // A temporary list that we append scroll info items to while building + // display items for the contents of frames with SVG effects. + // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true. + // This is a pointer and not a real nsDisplayList value because the + // nsDisplayList class is defined below this class, so we can't use it here. + nsDisplayList* mScrollInfoItemsForHoisting; nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy; Mode mMode; ViewID mCurrentScrollParentId; ViewID mCurrentScrollbarTarget; uint32_t mCurrentScrollbarFlags; BlendModeSet mContainedBlendModes; + int32_t mSVGEffectsBuildingDepth; bool mBuildCaret; bool mIgnoreSuppression; bool mHadToIgnoreSuppression; bool mIsAtRootOfPseudoStackingContext; bool mIncludeAllOutOfFlows; bool mDescendIntoSubdocuments; bool mSelectedFramesOnly; bool mAccurateVisibleRegions; @@ -3201,30 +3219,28 @@ public: *aSnap = false; return nsRegion(); } virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aParameters) override; - virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override; + virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override + { return false; } virtual void WriteDebugInfo(std::stringstream& aStream) override; mozilla::UniquePtr<FrameMetrics> ComputeFrameMetrics(Layer* aLayer, const ContainerLayerParameters& aContainerParameters); - void MarkHoisted() { mHoisted = true; } - protected: nsIFrame* mScrollFrame; nsIFrame* mScrolledFrame; ViewID mScrollParentId; - bool mHoisted; }; /** * nsDisplayZoom is used for subdocuments that have a different full zoom than * their parent documents. This item creates a container layer. */ class nsDisplayZoom : public nsDisplaySubDocument { public: @@ -3493,25 +3509,34 @@ public: const nsRect* aBoundsOverride); FrameTransformProperties(nsCSSValueSharedList* aTransformList, const Point3D& aToTransformOrigin, const Point3D& aToPerspectiveOrigin, nscoord aChildPerspective) : mFrame(nullptr) , mTransformList(aTransformList) , mToTransformOrigin(aToTransformOrigin) + , mChildPerspective(aChildPerspective) , mToPerspectiveOrigin(aToPerspectiveOrigin) - , mChildPerspective(aChildPerspective) {} + const Point3D& GetToPerspectiveOrigin() const + { + MOZ_ASSERT(mChildPerspective > 0, "Only valid with mChildPerspective > 0"); + return mToPerspectiveOrigin; + } + const nsIFrame* mFrame; nsRefPtr<nsCSSValueSharedList> mTransformList; const Point3D mToTransformOrigin; - const Point3D mToPerspectiveOrigin; nscoord mChildPerspective; + + private: + // mToPerspectiveOrigin is only valid if mChildPerspective > 0. + Point3D mToPerspectiveOrigin; }; /** * Given a frame with the -moz-transform property or an SVG transform, * returns the transformation matrix for that frame. * * @param aFrame The frame to get the matrix from. * @param aOrigin Relative to which point this transform should be applied.
--- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1985,19 +1985,21 @@ nsIFrame::BuildDisplayListForStackingCon dirtyRect.SetEmpty(); } } inTransform = true; } bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this); nsRect dirtyRectOutsideSVGEffects = dirtyRect; + nsDisplayList hoistedScrollInfoItemsStorage; if (usingSVGEffects) { dirtyRect = nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect); + aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage); } bool useOpacity = HasVisualOpacity() && !nsSVGUtils::CanOptimizeOpacity(this); bool useBlendMode = disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL; bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY && IsScrollFrameActive(aBuilder, nsLayoutUtils::GetNearestScrollableFrame(GetParent(), nsLayoutUtils::SCROLLABLE_SAME_DOC | @@ -2121,16 +2123,20 @@ nsIFrame::BuildDisplayListForStackingCon * output even if the element being filtered wouldn't otherwise do so. */ if (usingSVGEffects) { // Revert to the post-filter dirty rect. buildingDisplayList.SetDirtyRect(dirtyRectOutsideSVGEffects); /* List now emptied, so add the new list to the top. */ resultList.AppendNewToTop( new (aBuilder) nsDisplaySVGEffects(aBuilder, this, &resultList)); + // Also add the hoisted scroll info items. We need those for APZ scrolling + // because nsDisplaySVGEffects items can't build active layers. + aBuilder->ExitSVGEffectsContents(); + resultList.AppendToTop(&hoistedScrollInfoItemsStorage); } /* Else, if the list is non-empty and there is CSS group opacity without SVG * effects, wrap it up in an opacity item. */ else if (useOpacity && !resultList.IsEmpty()) { // Don't clip nsDisplayOpacity items. We clip their descendants instead. // The clip we would set on an element with opacity would clip // all descendant content, but some should not be clipped.
--- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -3002,36 +3002,34 @@ ScrollFrameHelper::BuildDisplayList(nsDi !mShouldBuildScrollableLayer && shouldBuildLayer && aBuilder->IsBuildingLayerEventRegions()) { inactiveRegionItem = new (aBuilder) nsDisplayLayerEventRegions(aBuilder, mScrolledFrame); inactiveRegionItem->AddInactiveScrollPort(mScrollPort + aBuilder->ToReferenceFrame(mOuter)); } - // In case we are not using displayport or the nsDisplayScrollLayers are - // flattened during visibility computation, we still need to export the - // metadata about this scroll box to the compositor process. - nsDisplayScrollInfoLayer* layerItem = new (aBuilder) nsDisplayScrollInfoLayer( - aBuilder, mScrolledFrame, mOuter); - - nsDisplayList* positionedDescendants = scrolledContent.PositionedDescendants(); - nsDisplayList* destinationList = nullptr; - int32_t zindex = - MaxZIndexInListOfItemsContainedInFrame(positionedDescendants, mOuter); - if (zindex >= 0) { - layerItem->SetOverrideZIndex(zindex); - destinationList = positionedDescendants; - } else { - destinationList = scrolledContent.Outlines(); - } if (inactiveRegionItem) { + nsDisplayList* positionedDescendants = scrolledContent.PositionedDescendants(); + nsDisplayList* destinationList = nullptr; + int32_t zindex = + MaxZIndexInListOfItemsContainedInFrame(positionedDescendants, mOuter); + if (zindex >= 0) { + destinationList = positionedDescendants; + } else { + destinationList = scrolledContent.Outlines(); + } destinationList->AppendNewToTop(inactiveRegionItem); } - destinationList->AppendNewToTop(layerItem); + + if (aBuilder->ShouldBuildScrollInfoItemsForHoisting()) { + aBuilder->AppendNewScrollInfoItemForHoisting( + new (aBuilder) nsDisplayScrollInfoLayer(aBuilder, mScrolledFrame, + mOuter)); + } } // Now display overlay scrollbars and the resizer, if we have one. AppendScrollPartsTo(aBuilder, aDirtyRect, scrolledContent, usingDisplayport, createLayersForScrollbars, true); scrolledContent.MoveTo(aLists); } void
--- a/layout/generic/nsPluginFrame.cpp +++ b/layout/generic/nsPluginFrame.cpp @@ -1070,17 +1070,17 @@ nsPluginFrame::NotifyPluginReflowObserve { nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow"))); } void nsPluginFrame::DidSetWidgetGeometry() { #if defined(XP_MACOSX) - if (mInstanceOwner) { + if (mInstanceOwner && !IsHidden()) { mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable); } #else if (!mWidget && mInstanceOwner) { // UpdateWindowVisibility will notify the plugin of position changes // by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow. // We treat windowless plugins inside popups as always visible, since // plugins inside popups don't get valid mNextConfigurationBounds
--- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -501,25 +501,16 @@ AnimValuesStyleRule::List(FILE* out, int bool AnimationCollection::CanAnimatePropertyOnCompositor( const dom::Element *aElement, nsCSSProperty aProperty, CanAnimateFlags aFlags) { bool shouldLog = nsLayoutUtils::IsAnimationLoggingEnabled(); - if (!gfxPlatform::OffMainThreadCompositingEnabled()) { - if (shouldLog) { - nsCString message; - message.AppendLiteral("Performance warning: Compositor disabled"); - LogAsyncAnimationFailure(message); - } - return false; - } - nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement); if (IsGeometricProperty(aProperty)) { if (shouldLog) { nsCString message; message.AppendLiteral("Performance warning: Async animation of geometric property '"); message.Append(nsCSSProps::GetStringValue(aProperty)); message.AppendLiteral("' is disabled"); LogAsyncAnimationFailure(message, aElement); @@ -577,16 +568,29 @@ bool AnimationCollection::CanPerformOnCompositorThread( CanAnimateFlags aFlags) const { nsIFrame* frame = nsLayoutUtils::GetStyleFrame(mElement); if (!frame) { return false; } + nsIWidget* widget = frame->GetNearestWidget(); + if (!widget || + widget->GetLayerManager()->GetBackendType() != + layers::LayersBackend::LAYERS_CLIENT) { + // No widget (huh?), or a widget not using off-main-thread compositor. + if (nsLayoutUtils::IsAnimationLoggingEnabled()) { + nsCString message; + message.AppendLiteral("Performance warning: Compositor disabled"); + LogAsyncAnimationFailure(message); + } + return false; + } + if (mElementProperty != nsGkAtoms::transitionsProperty && mElementProperty != nsGkAtoms::animationsProperty) { if (nsLayoutUtils::IsAnimationLoggingEnabled()) { nsCString message; message.AppendLiteral("Gecko bug: Async animation of pseudoelements" " not supported. See bug 771367 ("); message.Append(nsAtomCString(mElementProperty)); message.Append(")");
deleted file mode 100644 --- a/media/libvpx/bug1137614.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/media/libvpx/vp8/encoder/block.h b/media/libvpx/vp8/encoder/block.h ---- a/media/libvpx/vp8/encoder/block.h -+++ b/media/libvpx/vp8/encoder/block.h -@@ -93,17 +93,18 @@ typedef struct macroblock - int rddiv; - int rdmult; - unsigned int * mb_activity_ptr; - int * mb_norm_activity_ptr; - signed int act_zbin_adj; - signed int last_act_zbin_adj; - - int *mvcost[2]; -- int *mvsadcost[2]; -+ /* MSVC generates code that thinks this is 16-byte aligned */ -+ DECLARE_ALIGNED(16, int*, mvsadcost[2]); - int (*mbmode_cost)[MB_MODE_COUNT]; - int (*intra_uv_mode_cost)[MB_MODE_COUNT]; - int (*bmode_costs)[10][10]; - int *inter_bmode_costs; - int (*token_costs)[COEF_BANDS][PREV_COEF_CONTEXTS] - [MAX_ENTROPY_TOKENS]; - - /* These define limits to motion vector components to prevent
--- a/media/libvpx/update.py +++ b/media/libvpx/update.py @@ -519,18 +519,16 @@ def update_and_remove_files(prefix, libv def apply_patches(): # Patch to permit vpx users to specify their own <stdint.h> types. os.system("patch -p0 < stdint.patch") # Patch for AVX intrinsic support with Apple's clang. os.system("patch -p3 < apple-clang.patch") # Patch to allow MSVC 2015 to compile libvpx os.system("patch -p3 < msvc2015.patch") - # Patch to fix a crash caused by MSVC 2013 - os.system("patch -p3 < bug1137614.patch") def update_readme(commit): with open('README_MOZILLA') as f: readme = f.read() if 'The git commit ID used was' in readme: new_readme = re.sub('The git commit ID used was [a-f0-9]+', 'The git commit ID used was %s' % commit, readme)
--- a/media/libvpx/vp8/encoder/block.h +++ b/media/libvpx/vp8/encoder/block.h @@ -93,18 +93,17 @@ typedef struct macroblock int rddiv; int rdmult; unsigned int * mb_activity_ptr; int * mb_norm_activity_ptr; signed int act_zbin_adj; signed int last_act_zbin_adj; int *mvcost[2]; - /* MSVC generates code that thinks this is 16-byte aligned */ - DECLARE_ALIGNED(16, int*, mvsadcost[2]); + int *mvsadcost[2]; int (*mbmode_cost)[MB_MODE_COUNT]; int (*intra_uv_mode_cost)[MB_MODE_COUNT]; int (*bmode_costs)[10][10]; int *inter_bmode_costs; int (*token_costs)[COEF_BANDS][PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]; /* These define limits to motion vector components to prevent
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1163,16 +1163,21 @@ pref("network.protocol-handler.external. pref("network.protocol-handler.expose-all", true); // Warning for about:networking page pref("network.warnOnAboutNetworking", true); // Example: make IMAP an exposed protocol // pref("network.protocol-handler.expose.imap", true); +// Whether IOService.connectivity and NS_IsOffline depends on connectivity status +pref("network.manage-offline-status", false); +// If set to true, IOService.offline depends on IOService.connectivity +pref("network.offline-mirrors-connectivity", true); + // <http> pref("network.http.version", "1.1"); // default // pref("network.http.version", "1.0"); // uncomment this out in case of problems // pref("network.http.version", "0.9"); // it'll work too if you're crazy // keep-alive option is effectively obsolete. Nevertheless it'll work with // some older 1.0 servers: pref("network.http.proxy.version", "1.1"); // default @@ -1330,18 +1335,18 @@ pref("network.http.spdy.ping-threshold", pref("network.http.spdy.ping-timeout", 8); pref("network.http.spdy.send-buffer-size", 131072); pref("network.http.spdy.allow-push", true); pref("network.http.spdy.push-allowance", 131072); pref("network.http.spdy.default-concurrent", 100); // alt-svc allows separation of transport routing from // the origin host without using a proxy. -pref("network.http.altsvc.enabled", false); -pref("network.http.altsvc.oe", false); +pref("network.http.altsvc.enabled", true); +pref("network.http.altsvc.oe", true); pref("network.http.diagnostics", false); pref("network.http.pacing.requests.enabled", true); pref("network.http.pacing.requests.min-parallelism", 6); pref("network.http.pacing.requests.hz", 100); pref("network.http.pacing.requests.burst", 32);
--- a/netwerk/base/nsIIOService.idl +++ b/netwerk/base/nsIIOService.idl @@ -17,17 +17,17 @@ interface nsILoadInfo; * nsIIOService provides a set of network utility functions. This interface * duplicates many of the nsIProtocolHandler methods in a protocol handler * independent way (e.g., NewURI inspects the scheme in order to delegate * creation of the new URI to the appropriate protocol handler). nsIIOService * also provides a set of URL parsing utility functions. These are provided * as a convenience to the programmer and in some cases to improve performance * by eliminating intermediate data structures and interfaces. */ -[scriptable, uuid(b1c3c61d-2df9-4240-ae16-0355b51a2770)] +[scriptable, uuid(4286de5a-b2ea-446f-8f70-e2a461f42694)] interface nsIIOService : nsISupports { /** * Returns a protocol handler for a given URI scheme. * * @param aScheme the URI scheme * @return reference to corresponding nsIProtocolHandler */ @@ -174,16 +174,21 @@ interface nsIIOService : nsISupports * available -- that's hard to detect without causing the dialer to * come up). * * Changing this fires observer notifications ... see below. */ attribute boolean offline; /** + * Returns false if there are no interfaces for a network request + */ + readonly attribute boolean connectivity; + + /** * Set whether network appears to be offline for network connections from * a given appID. * * Calling this function may fire the "network:app-offline-status-changed" * notification, which is also sent to child processes containing this appId. * 'state' must one of nsIAppOfflineInfo::{ONLINE|OFFLINE|WIFI_ONLY}. */ void setAppOffline(in uint32_t appId, in long state); @@ -264,8 +269,19 @@ interface nsIAppOfflineInfo : nsISupport #define NS_IOSERVICE_ONLINE "online" /** * When network:app-offline-status-changed is fired, * the 'Subject' argument is a nsIOfflineAppInfo. */ #define NS_IOSERVICE_APP_OFFLINE_STATUS_TOPIC "network:app-offline-status-changed" %} + +[builtinclass, uuid(cd66ffef-3bc3-40de-841a-e2dcbea213a2)] +interface nsIIOServiceInternal : nsISupports +{ + /** + * This is an internal method that should only be called from ContentChild + * in order to pass the connectivity state from the chrome process to the + * content process. It throws if called outside the content process. + */ + void SetConnectivity(in boolean connectivity); +};
--- a/netwerk/base/nsIOService.cpp +++ b/netwerk/base/nsIOService.cpp @@ -54,16 +54,17 @@ using namespace mozilla; using mozilla::net::IsNeckoChild; #define PORT_PREF_PREFIX "network.security.ports." #define PORT_PREF(x) PORT_PREF_PREFIX x #define AUTODIAL_PREF "network.autodial-helper.enabled" #define MANAGE_OFFLINE_STATUS_PREF "network.manage-offline-status" +#define OFFLINE_MIRRORS_CONNECTIVITY "network.offline-mirrors-connectivity" // Nb: these have been misnomers since bug 715770 removed the buffer cache. // "network.segment.count" and "network.segment.size" would be better names, // but the old names are still used to preserve backward compatibility. #define NECKO_BUFFER_CACHE_COUNT_PREF "network.buffer.cache.count" #define NECKO_BUFFER_CACHE_SIZE_PREF "network.buffer.cache.size" #define NETWORK_NOTIFY_CHANGED_PREF "network.notify.changed" @@ -153,17 +154,19 @@ bool nsIOService::sTelemetryEnabled = fa NS_IMPL_ISUPPORTS(nsAppOfflineInfo, nsIAppOfflineInfo) //////////////////////////////////////////////////////////////////////////////// nsIOService::nsIOService() : mOffline(true) , mOfflineForProfileChange(false) - , mManageOfflineStatus(false) + , mManageLinkStatus(false) + , mConnectivity(true) + , mOfflineMirrorsConnectivity(true) , mSettingOffline(false) , mSetOfflineValue(false) , mShutdown(false) , mNetworkLinkServiceInitialized(false) , mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY) , mAutoDialEnabled(false) , mNetworkNotifyChanged(true) , mPreviousWifiState(-1) @@ -221,20 +224,22 @@ nsIOService::Init() observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, true); observerService->AddObserver(this, NS_WIDGET_WAKE_OBSERVER_TOPIC, true); observerService->AddObserver(this, kNetworkActiveChanged, true); } else NS_WARNING("failed to get observer service"); Preferences::AddBoolVarCache(&sTelemetryEnabled, "toolkit.telemetry.enabled", false); + Preferences::AddBoolVarCache(&mOfflineMirrorsConnectivity, OFFLINE_MIRRORS_CONNECTIVITY, true); gIOService = this; InitializeNetworkLinkService(); + SetOffline(false); return NS_OK; } nsIOService::~nsIOService() { gIOService = nullptr; @@ -279,27 +284,20 @@ nsIOService::InitializeNetworkLinkServic if (XRE_GetProcessType() == GeckoProcessType_Default) { mNetworkLinkService = do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID, &rv); } if (mNetworkLinkService) { mNetworkLinkServiceInitialized = true; } - else { - // We can't really determine if the machine has a usable network connection, - // so let's cross our fingers! - mManageOfflineStatus = false; - } - if (mManageOfflineStatus) - OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN); - else - SetOffline(false); - + // After initializing the networkLinkService, query the connectivity state + OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN); + return rv; } nsIOService* nsIOService::GetInstance() { if (!gIOService) { gIOService = new nsIOService(); if (!gIOService) @@ -318,16 +316,17 @@ nsIOService::GetInstance() { } NS_IMPL_ISUPPORTS(nsIOService, nsIIOService, nsIIOService2, nsINetUtil, nsISpeculativeConnect, nsIObserver, + nsIIOServiceInternal, nsISupportsWeakReference) //////////////////////////////////////////////////////////////////////////////// nsresult nsIOService::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan, uint32_t flags, nsAsyncRedirectVerifyHelper *helper) @@ -872,17 +871,21 @@ nsIOService::IsLinkUp() } return isLinkUp; } NS_IMETHODIMP nsIOService::GetOffline(bool *offline) { - *offline = mOffline; + if (mOfflineMirrorsConnectivity) { + *offline = mOffline || !mConnectivity; + } else { + *offline = mOffline; + } return NS_OK; } NS_IMETHODIMP nsIOService::SetOffline(bool offline) { // When someone wants to go online (!offline) after we got XPCOM shutdown // throw ERROR_NOT_AVAILABLE to prevent return to online state. @@ -950,17 +953,18 @@ nsIOService::SetOffline(bool offline) mOffline = false; // indicate success only AFTER we've // brought up the services // trigger a PAC reload when we come back online if (mProxyService) mProxyService->ReloadPAC(); // don't care if notification fails - if (observerService) + // Only send the ONLINE notification if there is connectivity + if (observerService && mConnectivity) observerService->NotifyObservers(subject, NS_IOSERVICE_OFFLINE_STATUS_TOPIC, NS_LITERAL_STRING(NS_IOSERVICE_ONLINE).get()); } } // Don't notify here, as the above notifications (if used) suffice. if ((mShutdown || mOfflineForProfileChange) && mOffline) { @@ -976,16 +980,82 @@ nsIOService::SetOffline(bool offline) } } mSettingOffline = false; return NS_OK; } +NS_IMETHODIMP +nsIOService::GetConnectivity(bool *aConnectivity) +{ + *aConnectivity = mConnectivity; + return NS_OK; +} + +NS_IMETHODIMP +nsIOService::SetConnectivity(bool aConnectivity) +{ + // This should only be called from ContentChild to pass the connectivity + // value from the chrome process to the content process. + if (XRE_GetProcessType() == GeckoProcessType_Default) { + return NS_ERROR_NOT_AVAILABLE; + } + return SetConnectivityInternal(aConnectivity); +} + + +nsresult +nsIOService::SetConnectivityInternal(bool aConnectivity) +{ + if (mConnectivity == aConnectivity) { + // Nothing to do here. + return NS_OK; + } + mConnectivity = aConnectivity; + + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (!observerService) { + return NS_OK; + } + // This notification sends the connectivity to the child processes + if (XRE_GetProcessType() == GeckoProcessType_Default) { + observerService->NotifyObservers(nullptr, + NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC, aConnectivity ? + MOZ_UTF16("true") : + MOZ_UTF16("false")); + } + + if (mOffline) { + // We don't need to send any notifications if we're offline + return NS_OK; + } + + if (aConnectivity) { + // If we were previously offline due to connectivity=false, + // send the ONLINE notification + observerService->NotifyObservers( + static_cast<nsIIOService *>(this), + NS_IOSERVICE_OFFLINE_STATUS_TOPIC, + NS_LITERAL_STRING(NS_IOSERVICE_ONLINE).get()); + } else { + // If we were previously online and lost connectivity + // send the OFFLINE notification + const nsLiteralString offlineString(MOZ_UTF16(NS_IOSERVICE_OFFLINE)); + observerService->NotifyObservers(static_cast<nsIIOService *>(this), + NS_IOSERVICE_GOING_OFFLINE_TOPIC, + offlineString.get()); + observerService->NotifyObservers(static_cast<nsIIOService *>(this), + NS_IOSERVICE_OFFLINE_STATUS_TOPIC, + offlineString.get()); + } + return NS_OK; +} NS_IMETHODIMP nsIOService::AllowPort(int32_t inPort, const char *scheme, bool *_retval) { int16_t port = inPort; if (port == -1) { *_retval = true; return NS_OK; @@ -1204,47 +1274,46 @@ nsIOService::Observe(nsISupports *subjec } else if (!strcmp(topic, kProfileChangeNetTeardownTopic)) { if (!mOffline) { mOfflineForProfileChange = true; SetOffline(true); } } else if (!strcmp(topic, kProfileChangeNetRestoreTopic)) { if (mOfflineForProfileChange) { mOfflineForProfileChange = false; - if (!mManageOfflineStatus || - NS_FAILED(OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN))) { - SetOffline(false); - } - } + SetOffline(false); + } } else if (!strcmp(topic, kProfileDoChange)) { if (data && NS_LITERAL_STRING("startup").Equals(data)) { // Lazy initialization of network link service (see bug 620472) InitializeNetworkLinkService(); // Set up the initilization flag regardless the actuall result. // If we fail here, we will fail always on. mNetworkLinkServiceInitialized = true; + + // The browser starts off as offline. We go into online mode after this. + SetOffline(false); + // And now reflect the preference setting nsCOMPtr<nsIPrefBranch> prefBranch; GetPrefBranch(getter_AddRefs(prefBranch)); PrefsChanged(prefBranch, MANAGE_OFFLINE_STATUS_PREF); } } else if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { // Remember we passed XPCOM shutdown notification to prevent any // changes of the offline status from now. We must not allow going // online after this point. mShutdown = true; SetOffline(true); // Break circular reference. mProxyService = nullptr; } else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) { - if (!mOfflineForProfileChange && mManageOfflineStatus) { - OnNetworkLinkEvent(NS_ConvertUTF16toUTF8(data).get()); - } + OnNetworkLinkEvent(NS_ConvertUTF16toUTF8(data).get()); } else if (!strcmp(topic, NS_WIDGET_WAKE_OBSERVER_TOPIC)) { // coming back alive from sleep nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService(); NS_ASSERTION(observerService, "The observer service should not be null"); if (observerService && mNetworkNotifyChanged) { @@ -1378,99 +1447,91 @@ nsIOService::NewSimpleNestedURI(nsIURI* NS_IF_ADDREF(*aResult = new nsSimpleNestedURI(safeURI)); return *aResult ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } NS_IMETHODIMP nsIOService::SetManageOfflineStatus(bool aManage) { - nsresult rv = NS_OK; + mManageLinkStatus = aManage; - // SetManageOfflineStatus must throw when we fail to go from non-managed - // to managed. Usually because there is no link monitoring service - // available. Failure to do this switch is detected by a failure of - // OnNetworkLinkEvent(). When there is no network link available during - // call to InitializeNetworkLinkService(), application is put to offline - // mode. And when we change mMangeOfflineStatus to false on the next line - // we get stuck on being offline even though the link becomes later - // available. - bool wasManaged = mManageOfflineStatus; - mManageOfflineStatus = aManage; + // When detection is not activated, the default connectivity state is true. + if (!mManageLinkStatus) { + SetConnectivityInternal(true); + return NS_OK; + } InitializeNetworkLinkService(); - - if (mManageOfflineStatus && !wasManaged) { - rv = OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN); - if (NS_FAILED(rv)) - mManageOfflineStatus = false; - } - return rv; + // If the NetworkLinkService is already initialized, it does not call + // OnNetworkLinkEvent. This is needed, when mManageLinkStatus goes from + // false to true. + OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN); + return NS_OK; } NS_IMETHODIMP -nsIOService::GetManageOfflineStatus(bool* aManage) { - *aManage = mManageOfflineStatus; +nsIOService::GetManageOfflineStatus(bool* aManage) +{ + *aManage = mManageLinkStatus; return NS_OK; } // input argument 'data' is already UTF8'ed nsresult nsIOService::OnNetworkLinkEvent(const char *data) { if (!mNetworkLinkService) return NS_ERROR_FAILURE; if (mShutdown) return NS_ERROR_NOT_AVAILABLE; - if (!mManageOfflineStatus) { + if (!mManageLinkStatus) { return NS_OK; } if (!strcmp(data, NS_NETWORK_LINK_DATA_DOWN)) { // check to make sure this won't collide with Autodial if (mSocketTransportService) { bool autodialEnabled = false; mSocketTransportService->GetAutodialEnabled(&autodialEnabled); // If autodialing-on-link-down is enabled, check if the OS auto // dial option is set to always autodial. If so, then we are // always up for the purposes of offline management. if (autodialEnabled) { + bool isUp = true; #if defined(XP_WIN) // On Windows, we should first check with the OS to see if // autodial is enabled. If it is enabled then we are allowed // to manage the offline state. - if (nsNativeConnectionHelper::IsAutodialEnabled()) { - return SetOffline(false); - } -#else - return SetOffline(false); + isUp = nsNativeConnectionHelper::IsAutodialEnabled(); #endif + return SetConnectivityInternal(isUp); } } } - bool isUp; + bool isUp = true; if (!strcmp(data, NS_NETWORK_LINK_DATA_CHANGED)) { // CHANGED means UP/DOWN didn't change return NS_OK; } else if (!strcmp(data, NS_NETWORK_LINK_DATA_DOWN)) { isUp = false; } else if (!strcmp(data, NS_NETWORK_LINK_DATA_UP)) { isUp = true; } else if (!strcmp(data, NS_NETWORK_LINK_DATA_UNKNOWN)) { nsresult rv = mNetworkLinkService->GetIsLinkUp(&isUp); NS_ENSURE_SUCCESS(rv, rv); } else { NS_WARNING("Unhandled network event!"); return NS_OK; } - return SetOffline(!isUp); + return SetConnectivityInternal(isUp); } NS_IMETHODIMP nsIOService::EscapeString(const nsACString& aString, uint32_t aEscapeType, nsACString& aResult) { NS_ENSURE_ARG_MAX(aEscapeType, 4);
--- a/netwerk/base/nsIOService.h +++ b/netwerk/base/nsIOService.h @@ -21,16 +21,17 @@ #include "mozilla/Attributes.h" #define NS_N(x) (sizeof(x)/sizeof(*x)) // We don't want to expose this observer topic. // Intended internal use only for remoting offline/inline events. // See Bug 552829 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline" +#define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity" static const char gScheme[][sizeof("resource")] = {"chrome", "file", "http", "https", "jar", "data", "resource"}; class nsAsyncRedirectVerifyHelper; class nsINetworkLinkService; class nsIPrefBranch; class nsIProtocolProxyService2; @@ -44,24 +45,26 @@ namespace net { } // namespace net } // namespace mozilla class nsIOService final : public nsIIOService2 , public nsIObserver , public nsINetUtil , public nsISpeculativeConnect , public nsSupportsWeakReference + , public nsIIOServiceInternal { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIIOSERVICE NS_DECL_NSIIOSERVICE2 NS_DECL_NSIOBSERVER NS_DECL_NSINETUTIL NS_DECL_NSISPECULATIVECONNECT + NS_DECL_NSIIOSERVICEINTERNAL // Gets the singleton instance of the IO Service, creating it as needed // Returns nullptr on out of memory or failure to initialize. // Returns an addrefed pointer. static nsIOService* GetInstance(); nsresult Init(); nsresult NewURI(const char* aSpec, nsIURI* aBaseURI, @@ -81,16 +84,17 @@ public: void SetAppOfflineInternal(uint32_t appId, int32_t status); private: // These shouldn't be called directly: // - construct using GetInstance // - destroy using Release nsIOService(); ~nsIOService(); + nsresult SetConnectivityInternal(bool aConnectivity); nsresult OnNetworkLinkEvent(const char *data); nsresult GetCachedProtocolHandler(const char *scheme, nsIProtocolHandler* *hdlrResult, uint32_t start=0, uint32_t end=0); nsresult CacheProtocolHandler(const char *scheme, @@ -116,17 +120,21 @@ private: nsresult NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI, nsIURI* aProxyURI, uint32_t aProxyFlags, nsILoadInfo* aLoadInfo, nsIChannel** result); private: bool mOffline; bool mOfflineForProfileChange; - bool mManageOfflineStatus; + bool mManageLinkStatus; + bool mConnectivity; + // If true, the connectivity state will be mirrored by IOService.offline + // meaning if !mConnectivity, GetOffline() will return true + bool mOfflineMirrorsConnectivity; // Used to handle SetOffline() reentrancy. See the comment in // SetOffline() for more details. bool mSettingOffline; bool mSetOfflineValue; bool mShutdown;
--- a/netwerk/base/nsNetUtil.h +++ b/netwerk/base/nsNetUtil.h @@ -1958,20 +1958,23 @@ NS_NewNotificationCallbacksAggregation(n /** * Helper function for testing online/offline state of the browser. */ inline bool NS_IsOffline() { bool offline = true; + bool connectivity = true; nsCOMPtr<nsIIOService> ios = do_GetIOService(); - if (ios) + if (ios) { ios->GetOffline(&offline); - return offline; + ios->GetConnectivity(&connectivity); + } + return offline || !connectivity; } inline bool NS_IsAppOffline(uint32_t appId) { bool appOffline = false; nsCOMPtr<nsIIOService> io( do_GetService("@mozilla.org/network/io-service;1"));
--- a/netwerk/protocol/websocket/WebSocketChannel.cpp +++ b/netwerk/protocol/websocket/WebSocketChannel.cpp @@ -2698,17 +2698,17 @@ WebSocketChannel::OnProxyAvailable(nsICa nsAutoCString type; if (NS_SUCCEEDED(status) && pi && NS_SUCCEEDED(pi->GetType(type)) && !type.EqualsLiteral("direct")) { LOG(("WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n", this)); // call DNS callback directly without DNS resolver OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE); } else { - LOG(("WebSocketChannel::OnProxyAvailable[%] checking DNS resolution\n", this)); + LOG(("WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n", this)); nsresult rv = DoAdmissionDNS(); if (NS_FAILED(rv)) { LOG(("WebSocket OnProxyAvailable [%p] DNS lookup failed\n", this)); // call DNS callback directly without DNS resolver OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE); } }
--- a/netwerk/streamconv/converters/ParseFTPList.cpp +++ b/netwerk/streamconv/converters/ParseFTPList.cpp @@ -718,28 +718,35 @@ int ParseFTPList(const char *line, struc /* * "10-23-00 01:27PM <DIR> veronist" * "06-15-00 07:37AM <DIR> zoe" * "07-14-00 01:35PM 2094926 canprankdesk.tif" * "07-21-00 01:19PM 95077 Jon Kauffman Enjoys the Good Life.jpg" * "07-21-00 01:19PM 52275 Name Plate.jpg" * "07-14-00 01:38PM 2250540 Valentineoffprank-HiRes.jpg" */ - if ((numtoks >= 4) && (toklen[0] == 8 || toklen[0] == 10) && toklen[1] == 7 && + // Microsoft FTP server with FtpDirBrowseShowLongDate set returns year + // in 4-digit format: + // "10-10-2014 10:10AM <DIR> FTP" + // Windows CE FTP server returns time in 24-hour format: + // "05-03-13 22:01 <DIR> APPS" + if ((numtoks >= 4) && (toklen[0] == 8 || toklen[0] == 10) && + (toklen[1] == 5 || toklen[1] == 7) && (*tokens[2] == '<' || isdigit(*tokens[2])) ) { p = tokens[0]; if ( isdigit(p[0]) && isdigit(p[1]) && p[2]=='-' && isdigit(p[3]) && isdigit(p[4]) && p[5]=='-' && isdigit(p[6]) && isdigit(p[7]) ) { p = tokens[1]; if ( isdigit(p[0]) && isdigit(p[1]) && p[2]==':' && isdigit(p[3]) && isdigit(p[4]) && - (p[5]=='A' || p[5]=='P') && p[6]=='M') + (toklen[1] == 5 || (toklen[1] == 7 && + (p[5]=='A' || p[5]=='P') && p[6]=='M'))) { lstyle = 'W'; if (!state->lstyle) { p = tokens[2]; /* <DIR> or <JUNCTION> */ if (*p != '<' || p[toklen[2]-1] != '>') { @@ -826,20 +833,23 @@ int ParseFTPList(const char *line, struc if (result->fe_time.tm_year < 80) result->fe_time.tm_year += 2000; else if (result->fe_time.tm_year < 100) result->fe_time.tm_year += 1900; } result->fe_time.tm_hour = atoi(tokens[1]+0); result->fe_time.tm_min = atoi(tokens[1]+3); - if ((tokens[1][5]) == 'P' && result->fe_time.tm_hour < 12) - result->fe_time.tm_hour += 12; - else if ((tokens[1][5]) == 'A' && result->fe_time.tm_hour == 12) - result->fe_time.tm_hour = 0; + if (toklen[1] == 7) + { + if ((tokens[1][5]) == 'P' && result->fe_time.tm_hour < 12) + result->fe_time.tm_hour += 12; + else if ((tokens[1][5]) == 'A' && result->fe_time.tm_hour == 12) + result->fe_time.tm_hour = 0; + } /* the caller should do this (if dropping "." and ".." is desired) if (result->fe_type == 'd' && result->fe_fname[0] == '.' && (result->fe_fnlen == 1 || (result->fe_fnlen == 2 && result->fe_fname[1] == '.'))) return '?'; */
--- a/nsprpub/configure +++ b/nsprpub/configure @@ -2661,29 +2661,16 @@ esac # Check whether --with-gonk was given. if test "${with_gonk+set}" = set; then : withval=$with_gonk; gonkdir=$withval fi if test -n "$gonkdir" ; then - if test -z "$HOST_CPPFLAGS" ; then - HOST_CPPFLAGS=" " - fi - if test -z "$HOST_CFLAGS" ; then - HOST_CFLAGS=" " - fi - if test -z "$HOST_CXXFLAGS" ; then - HOST_CXXFLAGS=" " - fi - if test -z "$HOST_LDFLAGS" ; then - HOST_LDFLAGS=" " - fi - $as_echo "#define ANDROID 1" >>confdefs.h else case "$target" in *-android*|*-linuxandroid*) if test -z "$android_ndk" ; then as_fn_error $? "You must specify --with-android-ndk=/path/to/ndk when targeting Android." "$LINENO" 5 fi @@ -2758,29 +2745,16 @@ case "$target" in RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib STRIP="$android_toolchain"/bin/"$android_tool_prefix"-strip CPPFLAGS="-I$android_platform/usr/include $CPPFLAGS" CFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CFLAGS" CXXFLAGS="-mandroid -I$android_platform/usr/include -fpic -fno-short-enums -fno-exceptions $CXXFLAGS" LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform $LDFLAGS" - if test -z "$HOST_CPPFLAGS" ; then - HOST_CPPFLAGS=" " - fi - if test -z "$HOST_CFLAGS" ; then - HOST_CFLAGS=" " - fi - if test -z "$HOST_CXXFLAGS" ; then - HOST_CXXFLAGS=" " - fi - if test -z "$HOST_LDFLAGS" ; then - HOST_LDFLAGS=" " - fi - $as_echo "#define ANDROID 1" >>confdefs.h ;; esac fi dist_prefix='${MOD_DEPTH}/dist' dist_bindir='${dist_prefix}/bin' @@ -4616,22 +4590,16 @@ fi done test -n "$HOST_CC" || HOST_CC="""" if test -z "$HOST_CC"; then as_fn_error $? "no acceptable cc found in \$PATH" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HOST_CC" >&5 $as_echo "$HOST_CC" >&6; } - if test -z "$HOST_CFLAGS"; then - HOST_CFLAGS="$CFLAGS" - fi - if test -z "$HOST_LDFLAGS"; then - HOST_LDFLAGS="$LDFLAGS" - fi CC="$HOST_CC" CFLAGS="$HOST_CFLAGS" LDFLAGS="$HOST_LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works" >&5 $as_echo_n "checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works... " >&6; }
--- a/nsprpub/configure.in +++ b/nsprpub/configure.in @@ -155,30 +155,16 @@ dnl ==================================== AC_ARG_WITH(gonk, [ --with-gonk=DIR location of gonk dir], gonkdir=$withval) if test -n "$gonkdir" ; then dnl Most things are directly configured by env vars when building for gonk - dnl prevent cross compile section from using these flags as host flags - if test -z "$HOST_CPPFLAGS" ; then - HOST_CPPFLAGS=" " - fi - if test -z "$HOST_CFLAGS" ; then - HOST_CFLAGS=" " - fi - if test -z "$HOST_CXXFLAGS" ; then - HOST_CXXFLAGS=" " - fi - if test -z "$HOST_LDFLAGS" ; then - HOST_LDFLAGS=" " - fi - AC_DEFINE(ANDROID) else case "$target" in *-android*|*-linuxandroid*) if test -z "$android_ndk" ; then AC_MSG_ERROR([You must specify --with-android-ndk=/path/to/ndk when targeting Android.]) fi @@ -252,30 +238,16 @@ case "$target" in RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib STRIP="$android_toolchain"/bin/"$android_tool_prefix"-strip CPPFLAGS="-I$android_platform/usr/include $CPPFLAGS" CFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CFLAGS" CXXFLAGS="-mandroid -I$android_platform/usr/include -fpic -fno-short-enums -fno-exceptions $CXXFLAGS" LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform $LDFLAGS" - dnl prevent cross compile section from using these flags as host flags - if test -z "$HOST_CPPFLAGS" ; then - HOST_CPPFLAGS=" " - fi - if test -z "$HOST_CFLAGS" ; then - HOST_CFLAGS=" " - fi - if test -z "$HOST_CXXFLAGS" ; then - HOST_CXXFLAGS=" " - fi - if test -z "$HOST_LDFLAGS" ; then - HOST_LDFLAGS=" " - fi - AC_DEFINE(ANDROID) ;; esac fi dnl ======================================================== dnl = dnl = Check options that may affect the compiler @@ -648,22 +620,16 @@ if test "$target" != "$host"; then _SAVE_LDFLAGS="$LDFLAGS" AC_MSG_CHECKING([for $host compiler]) AC_CHECK_PROGS(HOST_CC, $HOST_CC gcc cc /usr/ucb/cc, "") if test -z "$HOST_CC"; then AC_MSG_ERROR([no acceptable cc found in \$PATH]) fi AC_MSG_RESULT([$HOST_CC]) - if test -z "$HOST_CFLAGS"; then - HOST_CFLAGS="$CFLAGS" - fi - if test -z "$HOST_LDFLAGS"; then - HOST_LDFLAGS="$LDFLAGS" - fi CC="$HOST_CC" CFLAGS="$HOST_CFLAGS" LDFLAGS="$HOST_LDFLAGS" AC_MSG_CHECKING([whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works]) AC_TRY_COMPILE([], [return 0;], [AC_MSG_RESULT([yes])],
--- a/python/mozbuild/mozbuild/backend/recursivemake.py +++ b/python/mozbuild/mozbuild/backend/recursivemake.py @@ -23,16 +23,17 @@ from mozpack.copier import FilePurger from mozpack.manifests import ( InstallManifest, ) import mozpack.path as mozpath from .common import CommonBackend from ..frontend.data import ( AndroidEclipseProjectData, + BrandingFiles, ConfigFileSubstitution, ContextDerived, ContextWrapped, Defines, DistFiles, DirectoryTraversal, Exports, ExternalLibrary, @@ -129,16 +130,17 @@ DEPRECATED_VARIABLES = [ 'MOCHITEST_A11Y_FILES', 'MOCHITEST_BROWSER_FILES', 'MOCHITEST_BROWSER_FILES_PARTS', 'MOCHITEST_CHROME_FILES', 'MOCHITEST_FILES', 'MOCHITEST_FILES_PARTS', 'MOCHITEST_METRO_FILES', 'MOCHITEST_ROBOCOP_FILES', + 'MOZ_CHROME_FILE_FORMAT', 'SHORT_LIBNAME', 'TESTING_JS_MODULES', 'TESTING_JS_MODULE_DIR', ] class BackendMakeFile(object): """Represents a generated backend.mk file. @@ -372,16 +374,17 @@ class RecursiveMakeBackend(CommonBackend self._test_manifests = {} self.backend_input_files.add(mozpath.join(self.environment.topobjdir, 'config', 'autoconf.mk')) self._install_manifests = { k: InstallManifest() for k in [ 'dist_bin', + 'dist_branding', 'dist_idl', 'dist_include', 'dist_public', 'dist_private', 'dist_sdk', 'dist_xpi-stage', 'tests', 'xpidl', @@ -488,16 +491,19 @@ class RecursiveMakeBackend(CommonBackend method=obj.method)) elif isinstance(obj, TestHarnessFiles): self._process_test_harness_files(obj, backend_file) elif isinstance(obj, Resources): self._process_resources(obj, obj.resources, backend_file) + elif isinstance(obj, BrandingFiles): + self._process_branding_files(obj, obj.files, backend_file) + elif isinstance(obj, JsPreferenceFile): if obj.path.startswith('/'): backend_file.write('PREF_JS_EXPORTS += $(topsrcdir)%s\n' % obj.path) else: backend_file.write('PREF_JS_EXPORTS += $(srcdir)/%s\n' % obj.path) elif isinstance(obj, JARManifest): backend_file.write('JAR_MANIFEST := %s\n' % obj.path) @@ -935,16 +941,32 @@ INSTALL_TARGETS += %(prefix)s dep_file = mozpath.join(dep_path, mozpath.basename(source) + '.pp') self._install_manifests['dist_bin'].add_preprocess(source, dest, dep_file, marker='%', defines=obj.defines) else: self._install_manifests['dist_bin'].add_symlink(source, dest) if not os.path.exists(source): raise Exception('File listed in RESOURCE_FILES does not exist: %s' % source) + def _process_branding_files(self, obj, files, backend_file): + for source, dest, flags in self._walk_hierarchy(obj, files): + if flags and flags.source: + source = mozpath.normpath(mozpath.join(obj.srcdir, flags.source)) + if not os.path.exists(source): + raise Exception('File listed in BRANDING_FILES does not exist: %s' % source) + + self._install_manifests['dist_branding'].add_symlink(source, dest) + + # Also emit the necessary rules to create $(DIST)/branding during partial + # tree builds. The locale makefiles rely on this working. + backend_file.write('NONRECURSIVE_TARGETS += export\n') + backend_file.write('NONRECURSIVE_TARGETS_export += branding\n') + backend_file.write('NONRECURSIVE_TARGETS_export_branding_DIRECTORY = $(DEPTH)\n') + backend_file.write('NONRECURSIVE_TARGETS_export_branding_TARGETS += install-dist/branding\n') + def _process_installation_target(self, obj, backend_file): # A few makefiles need to be able to override the following rules via # make XPI_NAME=blah commands, so we default to the lazy evaluation as # much as possible here to avoid breaking things. if obj.xpiname: backend_file.write('XPI_NAME = %s\n' % (obj.xpiname)) if obj.subdir: backend_file.write('DIST_SUBDIR = %s\n' % (obj.subdir))
--- a/python/mozbuild/mozbuild/frontend/context.py +++ b/python/mozbuild/mozbuild/frontend/context.py @@ -948,16 +948,37 @@ VARIABLES = { """, None), 'LD_VERSION_SCRIPT': (unicode, unicode, """The linker version script for shared libraries. This variable can only be used on Linux. """, None), + 'BRANDING_FILES': (HierarchicalStringListWithFlagsFactory({'source': unicode}), list, + """List of files to be installed into the branding directory. + + ``BRANDING_FILES`` will copy (or symlink, if the platform supports it) + the contents of its files to the ``dist/branding`` directory. Files that + are destined for a subdirectory can be specified by accessing a field. + For example, to export ``foo.png`` to the top-level directory and + ``bar.png`` to the directory ``images/subdir``, append to + ``BRANDING_FILES`` like so:: + + BRANDING_FILES += ['foo.png'] + BRANDING_FILES.images.subdir += ['bar.png'] + + If the source and destination have different file names, add the + destination name to the list and set the ``source`` property on the + entry, like so:: + + BRANDING_FILES.dir += ['baz.png'] + BRANDING_FILES.dir['baz.png'].source = 'quux.png' + """, None), + 'RESOURCE_FILES': (HierarchicalStringListWithFlagsFactory({'preprocess': bool}), list, """List of resources to be exported, and in which subdirectories. ``RESOURCE_FILES`` is used to list the resource files to be exported to ``dist/bin/res``, but it can be used for other files as well. This variable behaves as a list when appending filenames for resources in the top-level directory. Files can also be appended to a field to indicate which subdirectory they should be exported to. For example, to export
--- a/python/mozbuild/mozbuild/frontend/data.py +++ b/python/mozbuild/mozbuild/frontend/data.py @@ -243,16 +243,30 @@ class Resources(ContextDerived): ContextDerived.__init__(self, context) self.resources = resources defs = {} defs.update(context.config.defines) if defines: defs.update(defines) self.defines = defs +class BrandingFiles(ContextDerived): + """Sandbox container object for BRANDING_FILES, which is a + HierarchicalStringList. + + We need an object derived from ContextDerived for use in the backend, so + this object fills that role. It just has a reference to the underlying + HierarchicalStringList, which is created when parsing BRANDING_FILES. + """ + __slots__ = ('files') + + def __init__(self, sandbox, files): + ContextDerived.__init__(self, sandbox) + self.files = files + class JsPreferenceFile(ContextDerived): """Context derived container object for a Javascript preference file. Paths are assumed to be relative to the srcdir.""" __slots__ = ('path') def __init__(self, context, path): ContextDerived.__init__(self, context)
--- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -20,16 +20,17 @@ from mozbuild.util import ( ) import mozpack.path as mozpath import manifestparser import reftest import mozinfo from .data import ( + BrandingFiles, ConfigFileSubstitution, ContextWrapped, Defines, DistFiles, DirectoryTraversal, Exports, FinalTargetFiles, GeneratedEventWebIDLFile, @@ -659,16 +660,20 @@ class TreeMetadataEmitter(LoggingMixin): for f in dist_files: path = os.path.join(context.srcdir, f) if not os.path.exists(path): raise SandboxValidationError('File listed in DIST_FILES ' 'does not exist: %s' % f, context) yield DistFiles(context, dist_files, context['FINAL_TARGET']) + branding_files = context.get('BRANDING_FILES') + if branding_files: + yield BrandingFiles(context, branding_files) + self._handle_libraries(context) for obj in self._process_test_manifests(context): yield obj for obj in self._process_jar_manifests(context): yield obj
new file mode 100644 --- /dev/null +++ b/python/mozbuild/mozbuild/test/backend/data/branding-files/moz.build @@ -0,0 +1,14 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +BRANDING_FILES += [ + 'app.ico', + 'bar.ico', + 'sub/quux.png', +] +BRANDING_FILES['app.ico'].source = 'bar.ico' + +BRANDING_FILES.icons += [ + 'foo.ico', +] +
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py +++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py @@ -400,16 +400,29 @@ class TestRecursiveMakeBackend(BackendTe self.assertIn('res/foo.res', m) self.assertIn('res/fonts/font1.ttf', m) self.assertIn('res/fonts/desktop/desktop2.ttf', m) self.assertIn('res/bar.res', m) self.assertIn('res/tests/test.manifest', m) self.assertIn('res/tests/extra.manifest', m) + def test_branding_files(self): + """Ensure BRANDING_FILES is handled properly.""" + env = self._consume('branding-files', RecursiveMakeBackend) + + #BRANDING_FILES should appear in the dist_branding install manifest. + m = InstallManifest(path=os.path.join(env.topobjdir, + '_build_manifests', 'install', 'dist_branding')) + self.assertEqual(len(m), 4) + self.assertIn('app.ico', m) + self.assertIn('bar.ico', m) + self.assertIn('quux.png', m) + self.assertIn('icons/foo.ico', m) + def test_js_preference_files(self): """Ensure PREF_JS_EXPORTS is written out correctly.""" env = self._consume('js_preference_files', RecursiveMakeBackend) backend_path = os.path.join(env.topobjdir, 'backend.mk') lines = [l.strip() for l in open(backend_path, 'rt').readlines()] # Avoid positional parameter and async related breakage
new file mode 100644 --- /dev/null +++ b/python/mozbuild/mozbuild/test/frontend/data/branding-files/moz.build @@ -0,0 +1,15 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +BRANDING_FILES += [ + 'app.ico', + 'bar.ico', + 'baz.png', + 'foo.xpm', +] +BRANDING_FILES['app.ico'].source = 'test/bar.ico' + +BRANDING_FILES.icons += [ + 'quux.icns', +] +
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py +++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py @@ -5,16 +5,17 @@ from __future__ import unicode_literals import os import unittest from mozunit import main from mozbuild.frontend.data import ( + BrandingFiles, ConfigFileSubstitution, Defines, DistFiles, DirectoryTraversal, Exports, GeneratedFile, GeneratedInclude, GeneratedSources, @@ -340,16 +341,33 @@ class TestEmitterBasic(unittest.TestCase self.assertIn('private', nspr._children) private = nspr._children['private'] self.assertEqual(private._strings, ['pprio.res', 'pprthred.res']) self.assertIn('overwrite', resources._children) overwrite = resources._children['overwrite'] self.assertEqual(overwrite._strings, ['new.res']) + def test_branding_files(self): + reader = self.reader('branding-files') + objs = self.read_topsrcdir(reader) + + self.assertEqual(len(objs), 1) + self.assertIsInstance(objs[0], BrandingFiles) + + files = objs[0].files + + self.assertEqual(files._strings, ['app.ico', 'bar.ico', 'baz.png', 'foo.xpm']) + self.assertEqual(files['app.ico'].source, 'test/bar.ico') + + self.assertIn('icons', files._children) + icons = files._children['icons'] + + self.assertEqual(icons._strings, ['quux.icns']) + def test_preferences_js(self): reader = self.reader('js_preference_files') objs = self.read_topsrcdir(reader) prefs = [o.path for o in objs if isinstance(o, JsPreferenceFile)] prefsByDir = [ 'valid_val/prefs.js',
--- a/security/manager/ssl/src/nsNTLMAuthModule.cpp +++ b/security/manager/ssl/src/nsNTLMAuthModule.cpp @@ -997,16 +997,17 @@ nsNTLMAuthModule::Init(const char * const char16_t *password) { NS_ASSERTION((serviceFlags & ~nsIAuthModule::REQ_PROXY_AUTH) == nsIAuthModule::REQ_DEFAULT, "unexpected service flags"); mDomain = domain; mUsername = username; mPassword = password; + mNTLMNegotiateSent = false; static bool sTelemetrySent = false; if (!sTelemetrySent) { mozilla::Telemetry::Accumulate( mozilla::Telemetry::NTLM_MODULE_USED_2, serviceFlags & nsIAuthModule::REQ_PROXY_AUTH