Merge m-c into larch
authorZibi Braniecki <gandalf@mozilla.com>
Tue, 11 Oct 2016 12:43:40 -0700
changeset 428985 15a5f3920481be2c6cacf4938eedc28c77d37077
parent 428984 9bffb12773c3a7afb8f29019cc164a9b70f003ee (current diff)
parent 423604 7ae377917236b7e6111146aa9fb4c073c0efc7f4 (diff)
child 428986 22a929d86e4db43d828efe54430a34c182b2dbc2
push id33449
push userzbraniecki@mozilla.com
push dateMon, 24 Oct 2016 21:39:41 +0000
milestone52.0a1
Merge m-c into larch
accessible/windows/msaa/ChildIDThunk.cpp
accessible/windows/msaa/ChildIDThunk.h
browser/base/content/browser.xul
browser/base/content/test/general/browser_bug880101.js
browser/installer/package-manifest.in
browser/locales/en-US/searchplugins/list.txt
browser/locales/jar.mn
build/moz.configure/ffi.configure
devtools/client/inspector/markup/html-editor.js
devtools/client/netmonitor/netmonitor.css
devtools/client/shared/widgets/HTMLTooltip.js
devtools/client/shared/widgets/Tooltip.js
devtools/client/webconsole/new-console-output/test/actions/filters.test.js
devtools/client/webconsole/new-console-output/test/actions/messages.test.js
devtools/client/webconsole/new-console-output/test/actions/ui.test.js
devtools/client/webconsole/new-console-output/test/components/repeat.test.js
dom/browser-element/BrowserElementPanning.js
dom/browser-element/BrowserElementPanningAPZDisabled.js
dom/canvas/test/test_mozDashOffset.html
dom/canvas/test/test_setlinedash.html
dom/cellbroadcast/CellBroadcast.cpp
dom/cellbroadcast/CellBroadcast.h
dom/cellbroadcast/CellBroadcastMessage.cpp
dom/cellbroadcast/CellBroadcastMessage.h
dom/cellbroadcast/gonk/CellBroadcastService.js
dom/cellbroadcast/gonk/CellBroadcastService.manifest
dom/cellbroadcast/interfaces/moz.build
dom/cellbroadcast/interfaces/nsICellBroadcastService.idl
dom/cellbroadcast/interfaces/nsICellbroadcastMessenger.idl
dom/cellbroadcast/interfaces/nsIGonkCellBroadcastService.idl
dom/cellbroadcast/ipc/CellBroadcastIPCService.cpp
dom/cellbroadcast/ipc/CellBroadcastIPCService.h
dom/cellbroadcast/ipc/CellBroadcastParent.cpp
dom/cellbroadcast/ipc/CellBroadcastParent.h
dom/cellbroadcast/ipc/PCellBroadcast.ipdl
dom/cellbroadcast/moz.build
dom/cellbroadcast/tests/marionette/head.js
dom/cellbroadcast/tests/marionette/manifest.ini
dom/cellbroadcast/tests/marionette/test_cellbroadcast_etws.js
dom/cellbroadcast/tests/marionette/test_cellbroadcast_gsm.js
dom/cellbroadcast/tests/marionette/test_cellbroadcast_gsm_language_and_body.js
dom/cellbroadcast/tests/marionette/test_cellbroadcast_multi_sim.js
dom/cellbroadcast/tests/marionette/test_cellbroadcast_umts.js
dom/cellbroadcast/tests/marionette/test_cellbroadcast_umts_language_and_body.js
dom/fmradio/FMRadio.cpp
dom/fmradio/FMRadio.h
dom/fmradio/FMRadioCommon.h
dom/fmradio/FMRadioService.cpp
dom/fmradio/FMRadioService.h
dom/fmradio/ipc/FMRadioChild.cpp
dom/fmradio/ipc/FMRadioChild.h
dom/fmradio/ipc/FMRadioParent.cpp
dom/fmradio/ipc/FMRadioParent.h
dom/fmradio/ipc/FMRadioRequestChild.cpp
dom/fmradio/ipc/FMRadioRequestChild.h
dom/fmradio/ipc/FMRadioRequestParent.cpp
dom/fmradio/ipc/FMRadioRequestParent.h
dom/fmradio/ipc/PFMRadio.ipdl
dom/fmradio/ipc/PFMRadioRequest.ipdl
dom/fmradio/ipc/moz.build
dom/fmradio/moz.build
dom/fmradio/test/marionette/manifest.ini
dom/fmradio/test/marionette/test_bug862672.js
dom/fmradio/test/marionette/test_bug876597.js
dom/fmradio/test/marionette/test_cancel_seek.js
dom/fmradio/test/marionette/test_enable_disable.js
dom/fmradio/test/marionette/test_one_seek_at_once.js
dom/fmradio/test/marionette/test_seek_up_and_down.js
dom/fmradio/test/marionette/test_set_frequency.js
dom/permission/tests/mochitest-fm.ini
dom/permission/tests/test_cellbroadcast.html
dom/permission/tests/test_fmradio.html
dom/tests/mochitest/general/test_interfaces.html
dom/u2f/tests/test_frame.html
dom/u2f/tests/test_frame_appid_facet.html
dom/u2f/tests/test_frame_appid_facet_insecure.html
dom/u2f/tests/test_frame_appid_facet_subdomain.html
dom/u2f/tests/test_frame_register.html
dom/u2f/tests/test_frame_register_sign.html
dom/webidl/FMRadio.webidl
dom/webidl/MozCellBroadcast.webidl
dom/webidl/MozCellBroadcastEvent.webidl
dom/webidl/MozCellBroadcastMessage.webidl
dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
dom/workers/test/test_worker_interfaces.js
gfx/layers/apz/test/mochitest/test_bug1285070.html
layout/base/nsBidi.cpp
layout/base/tests/chrome/passpointerevents_dynamically_window.html
layout/base/tests/chrome/passpointerevents_window.html
layout/base/tests/chrome/test_passpointerevents.html
layout/base/tests/chrome/test_passpointerevents_dynamic.html
layout/base/tests/test_remote_passpointerevents.html
layout/style/StyleSheetInfo.cpp
mobile/android/base/java/org/mozilla/gecko/TextSelectionHandle.java
mobile/android/base/java/org/mozilla/gecko/notifications/AppNotificationClient.java
mobile/android/base/java/org/mozilla/gecko/notifications/NotificationHandler.java
mobile/android/base/java/org/mozilla/gecko/notifications/ServiceNotificationClient.java
mobile/android/base/resources/drawable/handle_anchor_level.xml
mobile/android/base/resources/drawable/handle_focus_level.xml
mobile/android/base/resources/layout/activity_stream_card_highlights_item.xml
mobile/android/base/resources/layout/text_selection_handles.xml
mobile/android/chrome/content/SelectionHandler.js
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/Axis.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/DisplayPortMetrics.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/DrawTimingQueue.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SubdocumentScrollHelper.java
mobile/android/installer/package-manifest.in
mobile/android/locales/jar.mn
netwerk/protocol/about/nsAboutBloat.cpp
netwerk/protocol/about/nsAboutBloat.h
old-configure.in
security/manager/pki/resources/content/certpicker.js
security/manager/pki/resources/content/certpicker.xul
security/manager/ssl/nsCertPicker.cpp
security/manager/ssl/nsCertPicker.h
security/manager/ssl/nsICertPickDialogs.idl
security/manager/ssl/nsIUserCertPicker.idl
services/sync/tests/unit/test_errorhandler.js
testing/mochitest/cc-analyzer.js
testing/mochitest/runtestsb2g.py
testing/mochitest/start_b2g.js
testing/profiles/prefs_b2g_unittest.js
testing/web-platform/meta/encrypted-media/Google/encrypted-media-keystatuses.html.ini
toolkit/components/search/tests/xpcshell/data/list.txt
toolkit/content/jar.mn
toolkit/modules/moz.build
--- a/.eslintignore
+++ b/.eslintignore
@@ -97,17 +97,17 @@ devtools/client/shared/webgl-utils.js
 devtools/client/shared/developer-toolbar.js
 devtools/client/shared/components/test/**
 devtools/client/shared/redux/middleware/test/**
 devtools/client/shared/test/**
 !devtools/client/shared/test/test-actor-registry.js
 devtools/client/shared/widgets/*.jsm
 devtools/client/sourceeditor/test/*.js
 devtools/client/webaudioeditor/**
-#devtools/client/webconsole/**
+devtools/client/webconsole/**
 !devtools/client/webconsole/panel.js
 !devtools/client/webconsole/jsterm.js
 !devtools/client/webconsole/console-commands.js
 devtools/client/webide/**
 !devtools/client/webide/components/webideCli.js
 devtools/server/*.js
 devtools/server/*.jsm
 !devtools/server/child.js
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1302855 changed build system to fold browsercomps into xul
+Bug 1267884 - Updated Android support library to 23.4
--- a/accessible/aom/moz.build
+++ b/accessible/aom/moz.build
@@ -30,9 +30,11 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
     LOCAL_INCLUDES += [
         '/accessible/mac',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
--- a/accessible/base/EventTree.cpp
+++ b/accessible/base/EventTree.cpp
@@ -253,17 +253,17 @@ EventTree::Process(const RefPtr<DocAcces
 
   mDependentEvents.Clear();
 }
 
 EventTree*
 EventTree::FindOrInsert(Accessible* aContainer)
 {
   if (!mFirst) {
-    mFirst.reset(new EventTree(aContainer, true));
+    mFirst.reset(new EventTree(aContainer, mDependentEvents.IsEmpty()));
     return mFirst.get();
   }
 
   EventTree* prevNode = nullptr;
   EventTree* node = mFirst.get();
   do {
     MOZ_ASSERT(!node->mContainer->IsApplication(),
                "No event for application accessible is expected here");
@@ -389,16 +389,17 @@ void
 EventTree::Clear()
 {
   mFirst = nullptr;
   mNext = nullptr;
   mContainer = nullptr;
 
   uint32_t eventsCount = mDependentEvents.Length();
   for (uint32_t jdx = 0; jdx < eventsCount; jdx++) {
+    mDependentEvents[jdx]->mEventType = AccEvent::eDoNotEmit;
     AccHideEvent* ev = downcast_accEvent(mDependentEvents[jdx]);
     if (ev && ev->NeedsShutdown()) {
       ev->Document()->ShutdownChildrenInSubtree(ev->mAccessible);
     }
   }
   mDependentEvents.Clear();
 }
 
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -420,18 +420,18 @@ NotificationController::WillRefresh(mozi
       ipcDoc = new DocAccessibleChild(childDoc);
       childDoc->SetIPCDoc(ipcDoc);
       nsCOMPtr<nsITabChild> tabChild =
         do_GetInterface(mDocument->DocumentNode()->GetDocShell());
       if (tabChild) {
         static_cast<TabChild*>(tabChild.get())->
           SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id);
 #if defined(XP_WIN)
-        IAccessibleHolder holder(CreateHolderFromAccessible(childDoc));
-        ipcDoc->SendCOMProxy(holder);
+        MOZ_ASSERT(parentIPCDoc);
+        ipcDoc->SendMsaaID(AccessibleWrap::GetChildIDFor(childDoc));
 #endif
       }
     }
   }
 
   mObservingState = eRefreshObserving;
   if (!mDocument)
     return;
--- a/accessible/html/moz.build
+++ b/accessible/html/moz.build
@@ -37,12 +37,14 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
     LOCAL_INCLUDES += [
         '/accessible/mac',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wno-error=shadow']
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/msaa/AccessibleMarshal.rc
@@ -0,0 +1,5 @@
+/* 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/. */
+
+1 typelib ISimpleDOMNode.tlb
--- a/accessible/interfaces/msaa/moz.build
+++ b/accessible/interfaces/msaa/moz.build
@@ -21,15 +21,21 @@ DEFINES['REGISTER_PROXY_DLL'] = True
 DEFFILE = SRCDIR + '/AccessibleMarshal.def'
 
 OS_LIBS += [
     'kernel32',
     'rpcrt4',
     'oleaut32',
 ]
 
+GENERATED_FILES += [
+    'ISimpleDOMNode.tlb',
+]
+
+RCINCLUDE = 'AccessibleMarshal.rc'
+
 # The Windows MIDL code generator creates things like:
 #
 #   #endif !_MIDL_USE_GUIDDEF_
 #
 # which clang-cl complains about.  MSVC doesn't, so turn this warning off.
 if CONFIG['CLANG_CL']:
     CFLAGS += ['-Wno-extra-tokens']
--- a/accessible/ipc/DocAccessibleChildBase.cpp
+++ b/accessible/ipc/DocAccessibleChildBase.cpp
@@ -49,89 +49,49 @@ DocAccessibleChildBase::InterfacesFor(Ac
   return interfaces;
 }
 
 /* static */ void
 DocAccessibleChildBase::SerializeTree(Accessible* aRoot,
                                       nsTArray<AccessibleData>& aTree)
 {
   uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
+#if defined(XP_WIN)
+  int32_t msaaId = AccessibleWrap::GetChildIDFor(aRoot);
+#endif
   uint32_t role = aRoot->Role();
   uint32_t childCount = aRoot->ChildCount();
   uint32_t interfaces = InterfacesFor(aRoot);
 
-#if defined(XP_WIN)
-  IAccessibleHolder holder(CreateHolderFromAccessible(aRoot));
-#endif
-
   // OuterDocAccessibles are special because we don't want to serialize the
   // child doc here, we'll call PDocAccessibleConstructor in
   // NotificationController.
   MOZ_ASSERT(!aRoot->IsDoc(), "documents shouldn't be serialized");
   if (aRoot->IsOuterDoc()) {
     childCount = 0;
   }
 
 #if defined(XP_WIN)
-  aTree.AppendElement(AccessibleData(id, role, childCount, interfaces,
-                                     holder));
+  aTree.AppendElement(AccessibleData(id, msaaId, role, childCount, interfaces));
 #else
   aTree.AppendElement(AccessibleData(id, role, childCount, interfaces));
 #endif
 
   for (uint32_t i = 0; i < childCount; i++) {
     SerializeTree(aRoot->GetChildAt(i), aTree);
   }
 }
 
-#if defined(XP_WIN)
-/* static */ void
-DocAccessibleChildBase::SetMsaaIds(Accessible* aRoot,
-                                   uint32_t& aMsaaIdIndex,
-                                   const nsTArray<MsaaMapping>& aNewMsaaIds)
-{
-  const MsaaMapping& mapping = aNewMsaaIds[aMsaaIdIndex];
-#if defined(DEBUG)
-  uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
-  MOZ_ASSERT(mapping.ID() == id);
-#endif // defined(DEBUG)
-  static_cast<AccessibleWrap*>(aRoot)->SetID(mapping.MsaaID());
-  ++aMsaaIdIndex;
-  if (aRoot->IsOuterDoc()) {
-    // This needs to match the tree traversal in SerializeTree
-    return;
-  }
-  for (uint32_t i = 0, n = aRoot->ChildCount(); i < n; ++i) {
-    SetMsaaIds(aRoot->GetChildAt(i), aMsaaIdIndex, aNewMsaaIds);
-  }
-}
-#endif // defined(XP_WIN)
-
 void
 DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent)
 {
   Accessible* parent = aShowEvent->Parent();
   uint64_t parentID = parent->IsDoc() ? 0 : reinterpret_cast<uint64_t>(parent->UniqueID());
   uint32_t idxInParent = aShowEvent->InsertionIndex();
   nsTArray<AccessibleData> shownTree;
   ShowEventData data(parentID, idxInParent, shownTree);
   SerializeTree(aShowEvent->GetAccessible(), data.NewTree());
-#if defined(XP_WIN)
-  nsTArray<MsaaMapping> newMsaaIds;
-  SendShowEventInfo(data, &newMsaaIds);
-  // newMsaaIds could be empty if something went wrong in SendShowEvent()
-  if (!newMsaaIds.IsEmpty()) {
-    uint32_t index = 0;
-    SetMsaaIds(aShowEvent->GetAccessible(), index, newMsaaIds);
-  }
-  // NB: On Windows, SendShowEvent attaches the subtree and generates new IDs,
-  //     but does *NOT* fire the native event. We need to do that after
-  //     we've called SetMsaaIds.
-  SendEvent(reinterpret_cast<uint64_t>(aShowEvent->GetAccessible()->UniqueID()),
-            nsIAccessibleEvent::EVENT_SHOW);
-#else
   SendShowEvent(data, aShowEvent->IsFromUserInput());
-#endif // defined(XP_WIN)
 }
 
 } // namespace a11y
 } // namespace mozilla
 
--- a/accessible/ipc/DocAccessibleChildBase.h
+++ b/accessible/ipc/DocAccessibleChildBase.h
@@ -55,20 +55,16 @@ public:
 
     mDoc->SetIPCDoc(nullptr);
     mDoc = nullptr;
   }
 
 protected:
   static uint32_t InterfacesFor(Accessible* aAcc);
   static void SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree);
-#if defined(XP_WIN)
-  static void SetMsaaIds(Accessible* aRoot, uint32_t& aMsaaIdIndex,
-                         const nsTArray<MsaaMapping>& aNewMsaaIds);
-#endif
 
   DocAccessible*  mDoc;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_DocAccessibleChildBase_h
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -11,23 +11,18 @@
 #include "xpcAccEvents.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 
 namespace mozilla {
 namespace a11y {
 
 bool
-#if defined(XP_WIN)
-DocAccessibleParent::RecvShowEventInfo(const ShowEventData& aData,
-                                       nsTArray<MsaaMapping>* aNewMsaaIds)
-#else
 DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
                                    const bool& aFromUser)
-#endif // defined(XP_WIN)
 {
   if (mShutdown)
     return true;
 
   MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
 
   if (aData.NewTree().IsEmpty()) {
     NS_ERROR("no children being added");
@@ -44,23 +39,17 @@ DocAccessibleParent::RecvShowEvent(const
   }
 
   uint32_t newChildIdx = aData.Idx();
   if (newChildIdx > parent->ChildrenCount()) {
     NS_ERROR("invalid index to add child at");
     return true;
   }
 
-#if defined(XP_WIN)
-  aNewMsaaIds->SetCapacity(aData.NewTree().Length());
-  uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx,
-                                 aNewMsaaIds);
-#else
   uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx);
-#endif
   MOZ_ASSERT(consumed == aData.NewTree().Length());
 
   // XXX This shouldn't happen, but if we failed to add children then the below
   // is pointless and can crash.
   if (!consumed) {
     return true;
   }
 
@@ -68,46 +57,38 @@ DocAccessibleParent::RecvShowEvent(const
   for (uint32_t i = 0; i < consumed; i++) {
     uint64_t id = aData.NewTree()[i].ID();
     MOZ_ASSERT(mAccessibles.GetEntry(id));
   }
 #endif
 
   MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
 
-  // NB: On Windows we dispatch the native event via a subsequent call to
-  // RecvEvent().
-#if !defined(XP_WIN)
   ProxyAccessible* target = parent->ChildAt(newChildIdx);
   ProxyShowHideEvent(target, parent, true, aFromUser);
 
   if (!nsCoreUtils::AccEventObserversExist()) {
     return true;
   }
 
   uint32_t type = nsIAccessibleEvent::EVENT_SHOW;
   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target);
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
   nsIDOMNode* node = nullptr;
   RefPtr<xpcAccEvent> event = new xpcAccEvent(type, xpcAcc, doc, node,
                                               aFromUser);
   nsCoreUtils::DispatchAccEvent(Move(event));
-#endif
 
   return true;
 }
 
 uint32_t
 DocAccessibleParent::AddSubtree(ProxyAccessible* aParent,
                                 const nsTArray<a11y::AccessibleData>& aNewTree,
-                                uint32_t aIdx, uint32_t aIdxInParent
-#if defined(XP_WIN)
-                                , nsTArray<MsaaMapping>* aNewMsaaIds
-#endif
-                                )
+                                uint32_t aIdx, uint32_t aIdxInParent)
 {
   if (aNewTree.Length() <= aIdx) {
     NS_ERROR("bad index in serialized tree!");
     return 0;
   }
 
   const AccessibleData& newChild = aNewTree[aIdx];
   if (newChild.Role() > roles::LAST_ROLE) {
@@ -117,53 +98,32 @@ DocAccessibleParent::AddSubtree(ProxyAcc
 
   if (mAccessibles.Contains(newChild.ID())) {
     NS_ERROR("ID already in use");
     return 0;
   }
 
   auto role = static_cast<a11y::role>(newChild.Role());
 
-#if defined(XP_WIN)
-  const IAccessibleHolder& proxyStream = newChild.COMProxy();
-  RefPtr<IAccessible> comPtr(proxyStream.Get());
-  if (!comPtr) {
-    NS_ERROR("Could not obtain remote IAccessible interface");
-    return 0;
-  }
-
-  ProxyAccessible* newProxy =
-    new ProxyAccessible(newChild.ID(), aParent, this, role,
-                        newChild.Interfaces(), comPtr);
-#else
   ProxyAccessible* newProxy =
     new ProxyAccessible(newChild.ID(), aParent, this, role,
                         newChild.Interfaces());
-#endif
 
   aParent->AddChildAt(aIdxInParent, newProxy);
   mAccessibles.PutEntry(newChild.ID())->mProxy = newProxy;
   ProxyCreated(newProxy, newChild.Interfaces());
 
 #if defined(XP_WIN)
-  Accessible* idForAcc = WrapperFor(newProxy);
-  MOZ_ASSERT(idForAcc);
-  uint32_t newMsaaId = AccessibleWrap::GetChildIDFor(idForAcc);
-  MOZ_ASSERT(newMsaaId);
-  aNewMsaaIds->AppendElement(MsaaMapping(newChild.ID(), newMsaaId));
-#endif // defined(XP_WIN)
+  WrapperFor(newProxy)->SetID(newChild.MsaaID());
+#endif
 
   uint32_t accessibles = 1;
   uint32_t kids = newChild.ChildrenCount();
   for (uint32_t i = 0; i < kids; i++) {
-    uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i
-#if defined(XP_WIN)
-                                   , aNewMsaaIds
-#endif
-                                  );
+    uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i);
     if (!consumed)
       return 0;
 
     accessibles += consumed;
   }
 
   MOZ_ASSERT(newProxy->ChildrenCount() == kids);
 
@@ -495,36 +455,45 @@ DocAccessibleParent::GetXPCAccessible(Pr
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
   MOZ_ASSERT(doc);
 
   return doc->GetXPCAccessible(aProxy);
 }
 
 #if defined(XP_WIN)
 /**
+ * @param aMsaaID The MSAA ID that was generated by content that the chrome
+ *        process should assign to this DocAccessibleParent.
  * @param aCOMProxy COM Proxy to the document in the content process.
  * @param aParentCOMProxy COM Proxy to the OuterDocAccessible that is
  *        the parent of the document. The content process will use this
  *        proxy when traversing up across the content/chrome boundary.
  */
 bool
-DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
-                                  IAccessibleHolder* aParentCOMProxy,
-                                  uint32_t* aMsaaID)
+DocAccessibleParent::RecvCOMProxy(const int32_t& aMsaaID,
+                                  const IAccessibleHolder& aCOMProxy,
+                                  IAccessibleHolder* aParentCOMProxy)
 {
+  WrapperFor(this)->SetID(aMsaaID);
+
   RefPtr<IAccessible> ptr(aCOMProxy.Get());
   SetCOMInterface(ptr);
 
   Accessible* outerDoc = OuterDocOfRemoteBrowser();
   IAccessible* rawNative = nullptr;
   if (outerDoc) {
     outerDoc->GetNativeInterface((void**) &rawNative);
   }
 
   aParentCOMProxy->Set(IAccessibleHolder::COMPtrType(rawNative));
-  Accessible* wrapper = WrapperFor(this);
-  *aMsaaID = AccessibleWrap::GetChildIDFor(wrapper);
+  return true;
+}
+
+bool
+DocAccessibleParent::RecvMsaaID(const int32_t& aMsaaID)
+{
+  WrapperFor(this)->SetID(aMsaaID);
   return true;
 }
 #endif // defined(XP_WIN)
 
 } // a11y
 } // mozilla
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -45,23 +45,18 @@ public:
 
   /*
    * Called when a message from a document in a child process notifies the main
    * process it is firing an event.
    */
   virtual bool RecvEvent(const uint64_t& aID, const uint32_t& aType)
     override;
 
-#if defined(XP_WIN)
-  virtual bool RecvShowEventInfo(const ShowEventData& aData,
-                                 nsTArray<MsaaMapping>* aNewMsaaIds) override;
-#else
   virtual bool RecvShowEvent(const ShowEventData& aData, const bool& aFromUser)
     override;
-#endif // defined(XP_WIN)
   virtual bool RecvHideEvent(const uint64_t& aRootID, const bool& aFromUser)
     override;
   virtual bool RecvStateChangeEvent(const uint64_t& aID,
                                     const uint64_t& aState,
                                     const bool& aEnabled) override final;
 
   virtual bool RecvCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset)
     override final;
@@ -73,16 +68,17 @@ public:
 
   virtual bool RecvSelectionEvent(const uint64_t& aID,
                                   const uint64_t& aWidgetID,
                                   const uint32_t& aType) override;
 
   virtual bool RecvRoleChangedEvent(const uint32_t& aRole) override final;
 
   virtual bool RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) override;
+
   void Unbind()
   {
     mParent = nullptr;
     if (DocAccessibleParent* parent = ParentDoc()) {
       parent->mChildDocs.RemoveElement(this);
     }
 
     mParentDoc = nullptr;
@@ -143,19 +139,21 @@ public:
   const ProxyAccessible* GetAccessible(uintptr_t aID) const
     { return const_cast<DocAccessibleParent*>(this)->GetAccessible(aID); }
 
   size_t ChildDocCount() const { return mChildDocs.Length(); }
   const DocAccessibleParent* ChildDocAt(size_t aIdx) const
     { return mChildDocs[aIdx]; }
 
 #if defined(XP_WIN)
-  virtual bool RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
-                            IAccessibleHolder* aParentCOMProxy,
-                            uint32_t* aMsaaID) override;
+  virtual bool RecvCOMProxy(const int32_t& aMsaaID,
+                            const IAccessibleHolder& aCOMProxy,
+                            IAccessibleHolder* aParentCOMProxy) override;
+
+  virtual bool RecvMsaaID(const int32_t& aMsaaID) override;
 #endif
 
 private:
 
   class ProxyEntry : public PLDHashEntryHdr
   {
   public:
     explicit ProxyEntry(const void*) : mProxy(nullptr) {}
@@ -175,21 +173,17 @@ private:
 
     enum { ALLOW_MEMMOVE = true };
 
     ProxyAccessible* mProxy;
   };
 
   uint32_t AddSubtree(ProxyAccessible* aParent,
                       const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx,
-                      uint32_t aIdxInParent
-#if defined(XP_WIN)
-                      , nsTArray<MsaaMapping>* aNewMsaaIds
-#endif // defined(XP_WIN)
-                      );
+                      uint32_t aIdxInParent);
   MOZ_MUST_USE bool CheckDocTree() const;
   xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);
 
   nsTArray<DocAccessibleParent*> mChildDocs;
   DocAccessibleParent* mParentDoc;
 
   /*
    * Conceptually this is a map from IDs to proxies, but we store the ID in the
--- a/accessible/ipc/other/PDocAccessible.ipdl
+++ b/accessible/ipc/other/PDocAccessible.ipdl
@@ -38,17 +38,17 @@ struct Attribute
 };
 
 struct RelationTargets
 {
   uint32_t Type;
   uint64_t[] Targets;
 };
 
-prio(normal upto high) sync protocol PDocAccessible
+nested(upto inside_sync) sync protocol PDocAccessible
 {
   manager PBrowser;
 
 parent:
   async Shutdown();
 
   /*
    * Notify the parent process the document in the child process is firing an
@@ -69,193 +69,193 @@ parent:
    * document.
    */
   async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
 
 child:
   async __delete__();
 
   // Accessible
-  prio(high) sync State(uint64_t aID) returns(uint64_t states);
-  prio(high) sync NativeState(uint64_t aID) returns(uint64_t states);
-  prio(high) sync Name(uint64_t aID) returns(nsString name);
-  prio(high) sync Value(uint64_t aID) returns(nsString value);
-  prio(high) sync Help(uint64_t aID) returns(nsString help);
-  prio(high) sync Description(uint64_t aID) returns(nsString desc);
-  prio(high) sync Attributes(uint64_t aID) returns(Attribute[] attributes);
-  prio(high) sync RelationByType(uint64_t aID, uint32_t aRelationType)
+  nested(inside_sync) sync State(uint64_t aID) returns(uint64_t states);
+  nested(inside_sync) sync NativeState(uint64_t aID) returns(uint64_t states);
+  nested(inside_sync) sync Name(uint64_t aID) returns(nsString name);
+  nested(inside_sync) sync Value(uint64_t aID) returns(nsString value);
+  nested(inside_sync) sync Help(uint64_t aID) returns(nsString help);
+  nested(inside_sync) sync Description(uint64_t aID) returns(nsString desc);
+  nested(inside_sync) sync Attributes(uint64_t aID) returns(Attribute[] attributes);
+  nested(inside_sync) sync RelationByType(uint64_t aID, uint32_t aRelationType)
     returns(uint64_t[] targets);
-  prio(high) sync Relations(uint64_t aID) returns(RelationTargets[] relations);
-  prio(high) sync IsSearchbox(uint64_t aID) returns(bool retval);
-  prio(high) sync LandmarkRole(uint64_t aID) returns(nsString landmark);
-  prio(high) sync ARIARoleAtom(uint64_t aID) returns(nsString role);
-  prio(high) sync GetLevelInternal(uint64_t aID) returns(int32_t aLevel);
+  nested(inside_sync) sync Relations(uint64_t aID) returns(RelationTargets[] relations);
+  nested(inside_sync) sync IsSearchbox(uint64_t aID) returns(bool retval);
+  nested(inside_sync) sync LandmarkRole(uint64_t aID) returns(nsString landmark);
+  nested(inside_sync) sync ARIARoleAtom(uint64_t aID) returns(nsString role);
+  nested(inside_sync) sync GetLevelInternal(uint64_t aID) returns(int32_t aLevel);
   async ScrollTo(uint64_t aID, uint32_t aScrollType);
   async ScrollToPoint(uint64_t aID, uint32_t aScrollType, int32_t aX,
                       int32_t aY);
 
   // AccessibleText
 
   // TextSubstring is getText in IDL.
-  prio(high) sync CaretLineNumber(uint64_t aID) returns(int32_t aLineNumber);
-  prio(high) sync CaretOffset(uint64_t aID) returns(int32_t aOffset);
+  nested(inside_sync) sync CaretLineNumber(uint64_t aID) returns(int32_t aLineNumber);
+  nested(inside_sync) sync CaretOffset(uint64_t aID) returns(int32_t aOffset);
    async SetCaretOffset(uint64_t aID, int32_t aOffset);
-  prio(high) sync CharacterCount(uint64_t aID) returns(int32_t aCount);
-  prio(high) sync SelectionCount(uint64_t aID) returns(int32_t aCount);
-  prio(high) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t
-                                aEndOffset) returns(nsString aText, bool aValid);
-  prio(high) sync GetTextAfterOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
+  nested(inside_sync) sync CharacterCount(uint64_t aID) returns(int32_t aCount);
+  nested(inside_sync) sync SelectionCount(uint64_t aID) returns(int32_t aCount);
+  nested(inside_sync) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t
+                                         aEndOffset) returns(nsString aText, bool aValid);
+  nested(inside_sync) sync GetTextAfterOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
     returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
-  prio(high) sync GetTextAtOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
+  nested(inside_sync) sync GetTextAtOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
     returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
 
-  prio(high) sync GetTextBeforeOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
+  nested(inside_sync) sync GetTextBeforeOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
     returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
-  prio(high) sync CharAt(uint64_t aID, int32_t aOffset) returns(uint16_t aChar);
+  nested(inside_sync) sync CharAt(uint64_t aID, int32_t aOffset) returns(uint16_t aChar);
 
-  prio(high) sync TextAttributes(uint64_t aID, bool aIncludeDefAttrs, int32_t aOffset)
+  nested(inside_sync) sync TextAttributes(uint64_t aID, bool aIncludeDefAttrs, int32_t aOffset)
     returns(Attribute[] aAttributes, int32_t aStartOffset, int32_t aEndOffset);
-  prio(high) sync DefaultTextAttributes(uint64_t aID) returns(Attribute[] aAttributes);
+  nested(inside_sync) sync DefaultTextAttributes(uint64_t aID) returns(Attribute[] aAttributes);
 
-  prio(high) sync TextBounds(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset,
+  nested(inside_sync) sync TextBounds(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset,
                              uint32_t aCoordType)
     returns(nsIntRect aRetVal);
-  prio(high) sync CharBounds(uint64_t aID, int32_t aOffset, uint32_t aCoordType)
+  nested(inside_sync) sync CharBounds(uint64_t aID, int32_t aOffset, uint32_t aCoordType)
     returns(nsIntRect aRetVal);
 
-  prio(high) sync OffsetAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aCoordType)
+  nested(inside_sync) sync OffsetAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aCoordType)
     returns(int32_t aRetVal);
 
-  prio(high) sync SelectionBoundsAt(uint64_t aID, int32_t aSelectionNum)
+  nested(inside_sync) sync SelectionBoundsAt(uint64_t aID, int32_t aSelectionNum)
     returns(bool aSucceeded, nsString aData, int32_t aStartOffset, int32_t aEndOffset);
-  prio(high) sync SetSelectionBoundsAt(uint64_t aID, int32_t aSelectionNum,
+  nested(inside_sync) sync SetSelectionBoundsAt(uint64_t aID, int32_t aSelectionNum,
                                        int32_t aStartOffset, int32_t aEndOffset)
     returns(bool aSucceeded);
-  prio(high) sync AddToSelection(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset)
+  nested(inside_sync) sync AddToSelection(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset)
     returns(bool aSucceeded);
-  prio(high) sync RemoveFromSelection(uint64_t aID, int32_t aSelectionNum)
+  nested(inside_sync) sync RemoveFromSelection(uint64_t aID, int32_t aSelectionNum)
     returns(bool aSucceeded);
 
   async ScrollSubstringTo(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset,
                           uint32_t aScrollType);
   async ScrollSubstringToPoint(uint64_t aID,
                                int32_t aStartOffset,
                                int32_t aEndOffset,
                                uint32_t aCoordinateType,
                                int32_t aX, int32_t aY);
 
-  prio(high) sync Text(uint64_t aID) returns(nsString aText);
-  prio(high) sync ReplaceText(uint64_t aID, nsString aText);
-  prio(high) sync InsertText(uint64_t aID, nsString aText, int32_t aPosition)
+  nested(inside_sync) sync Text(uint64_t aID) returns(nsString aText);
+  nested(inside_sync) sync ReplaceText(uint64_t aID, nsString aText);
+  nested(inside_sync) sync InsertText(uint64_t aID, nsString aText, int32_t aPosition)
     returns(bool aValid);
-  prio(high) sync CopyText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
+  nested(inside_sync) sync CopyText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
     returns(bool aValid);
-  prio(high) sync CutText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
+  nested(inside_sync) sync CutText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
     returns(bool aValid);
-  prio(high) sync DeleteText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
+  nested(inside_sync) sync DeleteText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
     returns(bool aValid);
-  prio(high) sync PasteText(uint64_t aID, int32_t aPosition)
+  nested(inside_sync) sync PasteText(uint64_t aID, int32_t aPosition)
     returns(bool aValid);
 
-  prio(high) sync ImagePosition(uint64_t aID, uint32_t aCoordType) returns(IntPoint aRetVal);
-  prio(high) sync ImageSize(uint64_t aID) returns(IntSize aRetVal);
+  nested(inside_sync) sync ImagePosition(uint64_t aID, uint32_t aCoordType) returns(IntPoint aRetVal);
+  nested(inside_sync) sync ImageSize(uint64_t aID) returns(IntSize aRetVal);
 
-  prio(high) sync StartOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
-  prio(high) sync EndOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
-  prio(high) sync IsLinkValid(uint64_t aID) returns(bool aRetVal);
-  prio(high) sync AnchorCount(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
-  prio(high) sync AnchorURIAt(uint64_t aID, uint32_t aIndex) returns(nsCString aURI, bool aOk);
-  prio(high) sync AnchorAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfAnchor, bool aOk);
+  nested(inside_sync) sync StartOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
+  nested(inside_sync) sync EndOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
+  nested(inside_sync) sync IsLinkValid(uint64_t aID) returns(bool aRetVal);
+  nested(inside_sync) sync AnchorCount(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
+  nested(inside_sync) sync AnchorURIAt(uint64_t aID, uint32_t aIndex) returns(nsCString aURI, bool aOk);
+  nested(inside_sync) sync AnchorAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfAnchor, bool aOk);
 
-  prio(high) sync LinkCount(uint64_t aID) returns(uint32_t aCount);
-  prio(high) sync LinkAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfLink, bool aOk);
-  prio(high) sync LinkIndexOf(uint64_t aID, uint64_t aLinkID) returns(int32_t aIndex);
-  prio(high) sync LinkIndexAtOffset(uint64_t aID, uint32_t aOffset) returns(int32_t aIndex);
+  nested(inside_sync) sync LinkCount(uint64_t aID) returns(uint32_t aCount);
+  nested(inside_sync) sync LinkAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfLink, bool aOk);
+  nested(inside_sync) sync LinkIndexOf(uint64_t aID, uint64_t aLinkID) returns(int32_t aIndex);
+  nested(inside_sync) sync LinkIndexAtOffset(uint64_t aID, uint32_t aOffset) returns(int32_t aIndex);
 
-  prio(high) sync TableOfACell(uint64_t aID) returns(uint64_t aTableID, bool aOk);
-  prio(high) sync ColIdx(uint64_t aID) returns(uint32_t aIndex);
-  prio(high) sync RowIdx(uint64_t aID) returns(uint32_t aIndex);
-  prio(high) sync ColExtent(uint64_t aID) returns(uint32_t aExtent);
-  prio(high) sync RowExtent(uint64_t aID) returns(uint32_t aExtent);
-  prio(high) sync ColHeaderCells(uint64_t aID) returns(uint64_t[] aCells);
-  prio(high) sync RowHeaderCells(uint64_t aID) returns(uint64_t[] aCells);
-  prio(high) sync IsCellSelected(uint64_t aID) returns(bool aSelected);
+  nested(inside_sync) sync TableOfACell(uint64_t aID) returns(uint64_t aTableID, bool aOk);
+  nested(inside_sync) sync ColIdx(uint64_t aID) returns(uint32_t aIndex);
+  nested(inside_sync) sync RowIdx(uint64_t aID) returns(uint32_t aIndex);
+  nested(inside_sync) sync ColExtent(uint64_t aID) returns(uint32_t aExtent);
+  nested(inside_sync) sync RowExtent(uint64_t aID) returns(uint32_t aExtent);
+  nested(inside_sync) sync ColHeaderCells(uint64_t aID) returns(uint64_t[] aCells);
+  nested(inside_sync) sync RowHeaderCells(uint64_t aID) returns(uint64_t[] aCells);
+  nested(inside_sync) sync IsCellSelected(uint64_t aID) returns(bool aSelected);
 
-  prio(high) sync TableCaption(uint64_t aID) returns(uint64_t aCaptionID, bool aOk);
-  prio(high) sync TableSummary(uint64_t aID) returns(nsString aSummary);
-  prio(high) sync TableColumnCount(uint64_t aID) returns(uint32_t aColCount);
-  prio(high) sync TableRowCount(uint64_t aID) returns(uint32_t aRowCount);
-  prio(high) sync TableCellAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint64_t aCellID, bool aOk);
-  prio(high) sync TableCellIndexAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(int32_t aIndex);
-  prio(high) sync TableColumnIndexAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aCol);
-  prio(high) sync TableRowIndexAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aRow);
-  prio(high) sync TableRowAndColumnIndicesAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aRow, int32_t aCol);
-  prio(high) sync TableColumnExtentAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint32_t aExtent);
-  prio(high) sync TableRowExtentAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint32_t aExtent);
-  prio(high) sync TableColumnDescription(uint64_t aID, uint32_t aCol) returns(nsString aDescription);
-  prio(high) sync TableRowDescription(uint64_t aID, uint32_t aRow) returns(nsString aDescription);
-  prio(high) sync TableColumnSelected(uint64_t aID, uint32_t aCol) returns(bool aSelected);
-  prio(high) sync TableRowSelected(uint64_t aID, uint32_t aRow) returns(bool aSelected);
-  prio(high) sync TableCellSelected(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(bool aSelected);
-  prio(high) sync TableSelectedCellCount(uint64_t aID) returns(uint32_t aSelectedCells);
-  prio(high) sync TableSelectedColumnCount(uint64_t aID) returns(uint32_t aSelectedColumns);
-  prio(high) sync TableSelectedRowCount(uint64_t aID) returns(uint32_t aSelectedRows);
-  prio(high) sync TableSelectedCells(uint64_t aID) returns(uint64_t[] aCellIDs);
-  prio(high) sync TableSelectedCellIndices(uint64_t aID) returns(uint32_t[] aCellIndeces);
-  prio(high) sync TableSelectedColumnIndices(uint64_t aID) returns(uint32_t[] aColumnIndeces);
-  prio(high) sync TableSelectedRowIndices(uint64_t aID) returns(uint32_t[] aRowIndeces);
-  prio(high) sync TableSelectColumn(uint64_t aID, uint32_t aCol);
-  prio(high) sync TableSelectRow(uint64_t aID, uint32_t aRow);
-  prio(high) sync TableUnselectColumn(uint64_t aID, uint32_t aCol);
-  prio(high) sync TableUnselectRow(uint64_t aID, uint32_t aRow);
-  prio(high) sync TableIsProbablyForLayout(uint64_t aID) returns(bool aForLayout);
-  prio(high) sync AtkTableColumnHeader(uint64_t aID, int32_t aCol)
+  nested(inside_sync) sync TableCaption(uint64_t aID) returns(uint64_t aCaptionID, bool aOk);
+  nested(inside_sync) sync TableSummary(uint64_t aID) returns(nsString aSummary);
+  nested(inside_sync) sync TableColumnCount(uint64_t aID) returns(uint32_t aColCount);
+  nested(inside_sync) sync TableRowCount(uint64_t aID) returns(uint32_t aRowCount);
+  nested(inside_sync) sync TableCellAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint64_t aCellID, bool aOk);
+  nested(inside_sync) sync TableCellIndexAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(int32_t aIndex);
+  nested(inside_sync) sync TableColumnIndexAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aCol);
+  nested(inside_sync) sync TableRowIndexAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aRow);
+  nested(inside_sync) sync TableRowAndColumnIndicesAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aRow, int32_t aCol);
+  nested(inside_sync) sync TableColumnExtentAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint32_t aExtent);
+  nested(inside_sync) sync TableRowExtentAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint32_t aExtent);
+  nested(inside_sync) sync TableColumnDescription(uint64_t aID, uint32_t aCol) returns(nsString aDescription);
+  nested(inside_sync) sync TableRowDescription(uint64_t aID, uint32_t aRow) returns(nsString aDescription);
+  nested(inside_sync) sync TableColumnSelected(uint64_t aID, uint32_t aCol) returns(bool aSelected);
+  nested(inside_sync) sync TableRowSelected(uint64_t aID, uint32_t aRow) returns(bool aSelected);
+  nested(inside_sync) sync TableCellSelected(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(bool aSelected);
+  nested(inside_sync) sync TableSelectedCellCount(uint64_t aID) returns(uint32_t aSelectedCells);
+  nested(inside_sync) sync TableSelectedColumnCount(uint64_t aID) returns(uint32_t aSelectedColumns);
+  nested(inside_sync) sync TableSelectedRowCount(uint64_t aID) returns(uint32_t aSelectedRows);
+  nested(inside_sync) sync TableSelectedCells(uint64_t aID) returns(uint64_t[] aCellIDs);
+  nested(inside_sync) sync TableSelectedCellIndices(uint64_t aID) returns(uint32_t[] aCellIndeces);
+  nested(inside_sync) sync TableSelectedColumnIndices(uint64_t aID) returns(uint32_t[] aColumnIndeces);
+  nested(inside_sync) sync TableSelectedRowIndices(uint64_t aID) returns(uint32_t[] aRowIndeces);
+  nested(inside_sync) sync TableSelectColumn(uint64_t aID, uint32_t aCol);
+  nested(inside_sync) sync TableSelectRow(uint64_t aID, uint32_t aRow);
+  nested(inside_sync) sync TableUnselectColumn(uint64_t aID, uint32_t aCol);
+  nested(inside_sync) sync TableUnselectRow(uint64_t aID, uint32_t aRow);
+  nested(inside_sync) sync TableIsProbablyForLayout(uint64_t aID) returns(bool aForLayout);
+  nested(inside_sync) sync AtkTableColumnHeader(uint64_t aID, int32_t aCol)
     returns(uint64_t aHeaderID, bool aOk);
-  prio(high) sync AtkTableRowHeader(uint64_t aID, int32_t aRow)
+  nested(inside_sync) sync AtkTableRowHeader(uint64_t aID, int32_t aRow)
     returns(uint64_t aHeaderID, bool aOk);
 
-  prio(high) sync SelectedItems(uint64_t aID) returns(uint64_t[] aSelectedItemIDs);
-  prio(high) sync SelectedItemCount(uint64_t aID) returns(uint32_t aCount);
-  prio(high) sync GetSelectedItem(uint64_t aID, uint32_t aIndex) returns(uint64_t aSelected, bool aOk);
-  prio(high) sync IsItemSelected(uint64_t aID, uint32_t aIndex) returns(bool aSelected);
-  prio(high) sync AddItemToSelection(uint64_t aID, uint32_t aIndex) returns(bool aSuccess);
-  prio(high) sync RemoveItemFromSelection(uint64_t aID, uint32_t aIndex) returns(bool aSuccess);
-  prio(high) sync SelectAll(uint64_t aID) returns(bool aSuccess);
-  prio(high) sync UnselectAll(uint64_t aID) returns(bool aSuccess);
+  nested(inside_sync) sync SelectedItems(uint64_t aID) returns(uint64_t[] aSelectedItemIDs);
+  nested(inside_sync) sync SelectedItemCount(uint64_t aID) returns(uint32_t aCount);
+  nested(inside_sync) sync GetSelectedItem(uint64_t aID, uint32_t aIndex) returns(uint64_t aSelected, bool aOk);
+  nested(inside_sync) sync IsItemSelected(uint64_t aID, uint32_t aIndex) returns(bool aSelected);
+  nested(inside_sync) sync AddItemToSelection(uint64_t aID, uint32_t aIndex) returns(bool aSuccess);
+  nested(inside_sync) sync RemoveItemFromSelection(uint64_t aID, uint32_t aIndex) returns(bool aSuccess);
+  nested(inside_sync) sync SelectAll(uint64_t aID) returns(bool aSuccess);
+  nested(inside_sync) sync UnselectAll(uint64_t aID) returns(bool aSuccess);
 
   async TakeSelection(uint64_t aID);
   async SetSelected(uint64_t aID, bool aSelected);
 
-  prio(high) sync DoAction(uint64_t aID, uint8_t aIndex) returns(bool aSuccess);
-  prio(high) sync ActionCount(uint64_t aID) returns(uint8_t aCount);
-  prio(high) sync ActionDescriptionAt(uint64_t aID, uint8_t aIndex) returns(nsString aDescription);
-  prio(high) sync ActionNameAt(uint64_t aID, uint8_t aIndex) returns(nsString aName);
-  prio(high) sync AccessKey(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask);
-  prio(high) sync KeyboardShortcut(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask);
-  prio(high) sync AtkKeyBinding(uint64_t aID) returns(nsString aResult);
+  nested(inside_sync) sync DoAction(uint64_t aID, uint8_t aIndex) returns(bool aSuccess);
+  nested(inside_sync) sync ActionCount(uint64_t aID) returns(uint8_t aCount);
+  nested(inside_sync) sync ActionDescriptionAt(uint64_t aID, uint8_t aIndex) returns(nsString aDescription);
+  nested(inside_sync) sync ActionNameAt(uint64_t aID, uint8_t aIndex) returns(nsString aName);
+  nested(inside_sync) sync AccessKey(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask);
+  nested(inside_sync) sync KeyboardShortcut(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask);
+  nested(inside_sync) sync AtkKeyBinding(uint64_t aID) returns(nsString aResult);
 
-  prio(high) sync CurValue(uint64_t aID) returns(double aValue);
-  prio(high) sync SetCurValue(uint64_t aID, double aValue) returns(bool aRetVal);
-  prio(high) sync MinValue(uint64_t aID) returns(double aValue);
-  prio(high) sync MaxValue(uint64_t aID) returns(double aValue);
-  prio(high) sync Step(uint64_t aID) returns(double aStep);
+  nested(inside_sync) sync CurValue(uint64_t aID) returns(double aValue);
+  nested(inside_sync) sync SetCurValue(uint64_t aID, double aValue) returns(bool aRetVal);
+  nested(inside_sync) sync MinValue(uint64_t aID) returns(double aValue);
+  nested(inside_sync) sync MaxValue(uint64_t aID) returns(double aValue);
+  nested(inside_sync) sync Step(uint64_t aID) returns(double aStep);
 
   async TakeFocus(uint64_t aID);
-  prio(high) sync FocusedChild(uint64_t aID)
+  nested(inside_sync) sync FocusedChild(uint64_t aID)
     returns(uint64_t aChild, bool aOk);
 
-  prio(high) sync Language(uint64_t aID) returns(nsString aLocale);
-  prio(high) sync DocType(uint64_t aID) returns(nsString aType);
-  prio(high) sync Title(uint64_t aID) returns(nsString aTitle);
-  prio(high) sync URL(uint64_t aID) returns(nsString aURL);
-  prio(high) sync MimeType(uint64_t aID) returns(nsString aMime);
-  prio(high) sync URLDocTypeMimeType(uint64_t aID) returns(nsString aURL, nsString aDocType, nsString aMimeType);
+  nested(inside_sync) sync Language(uint64_t aID) returns(nsString aLocale);
+  nested(inside_sync) sync DocType(uint64_t aID) returns(nsString aType);
+  nested(inside_sync) sync Title(uint64_t aID) returns(nsString aTitle);
+  nested(inside_sync) sync URL(uint64_t aID) returns(nsString aURL);
+  nested(inside_sync) sync MimeType(uint64_t aID) returns(nsString aMime);
+  nested(inside_sync) sync URLDocTypeMimeType(uint64_t aID) returns(nsString aURL, nsString aDocType, nsString aMimeType);
 
-  prio(high) sync AccessibleAtPoint(uint64_t aID, int32_t aX, int32_t aY, bool aNeedsScreenCoords, uint32_t aWhich)
+  nested(inside_sync) sync AccessibleAtPoint(uint64_t aID, int32_t aX, int32_t aY, bool aNeedsScreenCoords, uint32_t aWhich)
     returns(uint64_t aResult, bool aOk);
 
-  prio(high) sync Extents(uint64_t aID, bool aNeedsScreenCoords)
+  nested(inside_sync) sync Extents(uint64_t aID, bool aNeedsScreenCoords)
     returns(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight);
-  prio(high) sync DOMNodeID(uint64_t aID) returns(nsString aDOMNodeID);
+  nested(inside_sync) sync DOMNodeID(uint64_t aID) returns(nsString aDOMNodeID);
 };
 
 }
 }
--- a/accessible/ipc/win/DocAccessibleChild.cpp
+++ b/accessible/ipc/win/DocAccessibleChild.cpp
@@ -28,18 +28,17 @@ DocAccessibleChild::DocAccessibleChild(D
 DocAccessibleChild::~DocAccessibleChild()
 {
   MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
 }
 
 void
 DocAccessibleChild::SendCOMProxy(const IAccessibleHolder& aProxy)
 {
+  int32_t msaaID = AccessibleWrap::GetChildIDFor(mDoc);
   IAccessibleHolder parentProxy;
-  uint32_t msaaID = AccessibleWrap::kNoID;
-  PDocAccessibleChild::SendCOMProxy(aProxy, &parentProxy, &msaaID);
+  PDocAccessibleChild::SendCOMProxy(msaaID, aProxy, &parentProxy);
   mParentProxy.reset(parentProxy.Release());
-  mDoc->SetID(msaaID);
 }
 
 } // namespace a11y
 } // namespace mozilla
 
--- a/accessible/ipc/win/PDocAccessible.ipdl
+++ b/accessible/ipc/win/PDocAccessible.ipdl
@@ -10,35 +10,29 @@ include protocol PBrowser;
 using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/COMPtrTypes.h";
 
 namespace mozilla {
 namespace a11y {
 
 struct AccessibleData
 {
   uint64_t ID;
+  int32_t MsaaID;
   uint32_t Role;
   uint32_t ChildrenCount;
   uint32_t Interfaces;
-  IAccessibleHolder COMProxy;
 };
 
 struct ShowEventData
 {
   uint64_t ID;
   uint32_t Idx;
   AccessibleData[] NewTree;
 };
 
-struct MsaaMapping
-{
-  uint64_t ID;
-  uint32_t MsaaID;
-};
-
 struct Attribute
 {
   nsCString Name;
   nsString Value;
 };
 
 sync protocol PDocAccessible
 {
@@ -47,34 +41,36 @@ sync protocol PDocAccessible
 parent:
   async Shutdown();
 
   /*
    * Notify the parent process the document in the child process is firing an
    * event.
    */
   async Event(uint64_t aID, uint32_t type);
-  sync ShowEventInfo(ShowEventData data) returns (MsaaMapping[] aNewMsaaIds);
+  async ShowEvent(ShowEventData data, bool aFromUser);
   async HideEvent(uint64_t aRootID, bool aFromUser);
   async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
   async CaretMoveEvent(uint64_t aID, int32_t aOffset);
   async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
                         bool aIsInsert, bool aFromUser);
   async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType);
   async RoleChangedEvent(uint32_t aRole);
 
   /*
    * Tell the parent document to bind the existing document as a new child
    * document.
    */
   async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
 
   // For now we'll add the command to send the proxy here. This might move to
   // PDocAccessible constructor in PBrowser.
-  sync COMProxy(IAccessibleHolder aDocCOMProxy)
-    returns(IAccessibleHolder aParentCOMProxy, uint32_t aMsaaID);
+  sync COMProxy(int32_t aMsaaID, IAccessibleHolder aDocCOMProxy)
+    returns(IAccessibleHolder aParentCOMProxy);
+
+  async MsaaID(int32_t aMsaaID);
 
 child:
   async __delete__();
 };
 
 }
 }
--- a/accessible/ipc/win/ProxyAccessible.cpp
+++ b/accessible/ipc/win/ProxyAccessible.cpp
@@ -14,107 +14,106 @@
 #include "mozilla/Unused.h"
 #include "mozilla/a11y/Platform.h"
 #include "RelationType.h"
 #include "mozilla/a11y/Role.h"
 #include "xpcAccessibleDocument.h"
 
 #include <comutil.h>
 
+static const VARIANT kChildIdSelf = {VT_I4};
+
 namespace mozilla {
 namespace a11y {
 
 bool
 ProxyAccessible::GetCOMInterface(void** aOutAccessible) const
 {
   if (!aOutAccessible) {
     return false;
   }
+
+  if (!mCOMProxy) {
+    // See if we can lazily obtain a COM proxy
+    AccessibleWrap* wrap = WrapperFor(this);
+    bool isDefunct = false;
+    ProxyAccessible* thisPtr = const_cast<ProxyAccessible*>(this);
+    thisPtr->mCOMProxy = wrap->GetIAccessibleFor(kChildIdSelf, &isDefunct);
+  }
+
   RefPtr<IAccessible> addRefed = mCOMProxy;
   addRefed.forget(aOutAccessible);
   return !!mCOMProxy;
 }
 
 void
 ProxyAccessible::Name(nsString& aName) const
 {
   aName.Truncate();
   RefPtr<IAccessible> acc;
   if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
     return;
   }
 
-  VARIANT id;
-  id.vt = VT_I4;
-  id.lVal = CHILDID_SELF;
   BSTR result;
-  HRESULT hr = acc->get_accName(id, &result);
+  HRESULT hr = acc->get_accName(kChildIdSelf, &result);
   _bstr_t resultWrap(result, false);
   if (FAILED(hr)) {
     return;
   }
   aName = (wchar_t*)resultWrap;
 }
 
 void
 ProxyAccessible::Value(nsString& aValue) const
 {
   aValue.Truncate();
   RefPtr<IAccessible> acc;
   if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
     return;
   }
 
-  VARIANT id;
-  id.vt = VT_I4;
-  id.lVal = CHILDID_SELF;
   BSTR result;
-  HRESULT hr = acc->get_accValue(id, &result);
+  HRESULT hr = acc->get_accValue(kChildIdSelf, &result);
   _bstr_t resultWrap(result, false);
   if (FAILED(hr)) {
     return;
   }
   aValue = (wchar_t*)resultWrap;
 }
 
 void
 ProxyAccessible::Description(nsString& aDesc) const
 {
   aDesc.Truncate();
   RefPtr<IAccessible> acc;
   if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
     return;
   }
 
-  VARIANT id;
-  id.vt = VT_I4;
-  id.lVal = CHILDID_SELF;
   BSTR result;
-  HRESULT hr = acc->get_accDescription(id, &result);
+  HRESULT hr = acc->get_accDescription(kChildIdSelf, &result);
   _bstr_t resultWrap(result, false);
   if (FAILED(hr)) {
     return;
   }
   aDesc = (wchar_t*)resultWrap;
 }
 
 uint64_t
 ProxyAccessible::State() const
 {
   uint64_t state = 0;
   RefPtr<IAccessible> acc;
   if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
     return state;
   }
 
-  VARIANT id;
-  id.vt = VT_I4;
-  id.lVal = CHILDID_SELF;
   VARIANT varState;
-  HRESULT hr = acc->get_accState(id, &varState);
+  HRESULT hr = acc->get_accState(kChildIdSelf, &varState);
   if (FAILED(hr)) {
     return state;
   }
   return uint64_t(varState.lVal);
 }
 
 nsIntRect
 ProxyAccessible::Bounds()
@@ -125,20 +124,17 @@ ProxyAccessible::Bounds()
   if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
     return rect;
   }
 
   long left;
   long top;
   long width;
   long height;
-  VARIANT id;
-  id.vt = VT_I4;
-  id.lVal = CHILDID_SELF;
-  HRESULT hr = acc->accLocation(&left, &top, &width, &height, id);
+  HRESULT hr = acc->accLocation(&left, &top, &width, &height, kChildIdSelf);
   if (FAILED(hr)) {
     return rect;
   }
   rect.x = left;
   rect.y = top;
   rect.width = width;
   rect.height = height;
   return rect;
--- a/accessible/ipc/win/ProxyAccessible.h
+++ b/accessible/ipc/win/ProxyAccessible.h
@@ -20,21 +20,18 @@
 
 namespace mozilla {
 namespace a11y {
 
 class ProxyAccessible : public ProxyAccessibleBase<ProxyAccessible>
 {
 public:
   ProxyAccessible(uint64_t aID, ProxyAccessible* aParent,
-                  DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces,
-                  const RefPtr<IAccessible>& aIAccessible)
+                  DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces)
     : ProxyAccessibleBase(aID, aParent, aDoc, aRole, aInterfaces)
-    , mCOMProxy(aIAccessible)
-
   {
     MOZ_COUNT_CTOR(ProxyAccessible);
   }
 
   ~ProxyAccessible()
   {
     MOZ_COUNT_DTOR(ProxyAccessible);
   }
--- a/accessible/tests/mochitest/events/test_coalescence.html
+++ b/accessible/tests/mochitest/events/test_coalescence.html
@@ -645,16 +645,52 @@
         getNode('t10_c2_moved').setAttribute('aria-owns', 't10_c3_moved');
       };
 
       this.getID = function test10_getID() {
         return "Move a node by aria-owns into a node moved by aria-owns to left within the tree";
       };
     }
 
+    /**
+     * Move a node by aria-owns from right to left in the tree, and then
+     * move its parent too by aria-owns. No hide event should be fired for
+     * original node.
+     */
+    function test11()
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode('t11_c1_child')),
+        new invokerChecker(EVENT_SHOW, 't11_c2_child'),
+        new invokerChecker(EVENT_HIDE, getNode('t11_c2')),
+        new invokerChecker(EVENT_SHOW, 't11_c2'),
+        new invokerChecker(EVENT_REORDER, 't11'),
+        new unexpectedInvokerChecker(EVENT_HIDE, 't11_c2_child'),
+        new unexpectedInvokerChecker(EVENT_REORDER, 't11_c1'),
+        new unexpectedInvokerChecker(EVENT_REORDER, 't11_c2'),
+        new unexpectedInvokerChecker(EVENT_REORDER, 't11_c3')
+      ];
+
+      this.invoke = function test11_invoke()
+      {
+        // Remove a node from 't11_c1' container to give the event tree a
+        // desired structure (the 't11_c1' container node goes first in
+        // the event tree),
+        getNode('t11_c1_child').remove();
+        // then move 't11_c2_moved' from 't11_c2' to 't11_c1', and then move
+        // 't11_c2' to 't11_c3'.
+        getNode('t11_c1').setAttribute('aria-owns', 't11_c2_child');
+        getNode('t11_c3').setAttribute('aria-owns', 't11_c2');
+      };
+
+      this.getID = function test11_getID() {
+        return "Move a node by aria-owns to left within the tree";
+      };
+    }
+
     ////////////////////////////////////////////////////////////////////////////
     // Do tests.
 
     //gA11yEventDumpToConsole = true; // debug stuff
     //enableLogging("eventTree");
 
     var gQueue = null;
     function doTests()
@@ -681,16 +717,17 @@
       gQueue.push(new test3());
       gQueue.push(new test4());
       gQueue.push(new test5());
       gQueue.push(new test6());
       gQueue.push(new test7());
       gQueue.push(new test8());
       gQueue.push(new test9());
       gQueue.push(new test10());
+      gQueue.push(new test11());
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
@@ -810,10 +847,16 @@
     <div id="t10_c2">
       <div id="t10_c2_child"></div>
       <div id="t10_c2_moved"></div>
     </div>
     <div id="t10_c3">
       <div id="t10_c3_moved"></div>
     </div>
   </div>
+
+  <div id="t11">
+    <div id="t11_c1"><div id="t11_c1_child"></div></div>
+    <div id="t11_c2"><div id="t11_c2_child"></div></div>
+    <div id="t11_c3"></div>
+  </div>
 </body>
 </html>
--- a/accessible/tests/mochitest/treeupdate/test_ariaowns.html
+++ b/accessible/tests/mochitest/treeupdate/test_ariaowns.html
@@ -72,17 +72,18 @@
 
     function removeARIAOwns()
     {
       this.eventSeq = [
         new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
         new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
         new invokerChecker(EVENT_HIDE, getNode("t1_button")),
         new invokerChecker(EVENT_SHOW, getNode("t1_button")),
-        new invokerChecker(EVENT_REORDER, getNode("t1_container"))
+        new invokerChecker(EVENT_REORDER, getNode("t1_container")),
+        new unexpectedInvokerChecker(EVENT_REORDER, getNode("t1_checkbox"))
       ];
 
       this.invoke = function removeARIAOwns_invoke()
       {
         getNode("t1_container").removeAttribute("aria-owns");
       }
 
       this.finalCheck = function removeARIAOwns_finalCheck()
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -37,16 +37,17 @@
 #include "nsIServiceManager.h"
 #include "nsNameSpaceManager.h"
 #include "nsTextFormatter.h"
 #include "nsView.h"
 #include "nsViewManager.h"
 #include "nsEventMap.h"
 #include "nsArrayUtils.h"
 #include "mozilla/Preferences.h"
+#include "nsIXULRuntime.h"
 
 #include "oleacc.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 const uint32_t USE_ROLE_STRING = 0;
 
@@ -55,37 +56,36 @@ const uint32_t USE_ROLE_STRING = 0;
  */
 
 //#define DEBUG_LEAKS
 
 #ifdef DEBUG_LEAKS
 static gAccessibles = 0;
 #endif
 
-#ifdef _WIN64
-IDSet AccessibleWrap::sIDGen;
-#endif
+MsaaIdGenerator AccessibleWrap::sIDGen;
+
+static const VARIANT kVarChildIdSelf = {VT_I4};
 
 static const int32_t kIEnumVariantDisconnected = -1;
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccessibleWrap
 ////////////////////////////////////////////////////////////////////////////////
 AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
   Accessible(aContent, aDoc)
   , mID(kNoID)
 {
 }
 
 AccessibleWrap::~AccessibleWrap()
 {
-#ifdef _WIN64
-  if (mID != kNoID && XRE_IsParentProcess())
-    sIDGen.ReleaseID(mID);
-#endif
+  if (mID != kNoID) {
+    sIDGen.ReleaseID(this);
+  }
 }
 
 ITypeInfo* AccessibleWrap::gTypeInfo = nullptr;
 
 NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, Accessible)
 
 void
 AccessibleWrap::Shutdown()
@@ -244,56 +244,116 @@ AccessibleWrap::get_accChild(
     return E_INVALIDARG;
 
   *ppdispChild = nullptr;
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   // IAccessible::accChild is used to return this accessible or child accessible
   // at the given index or to get an accessible by child ID in the case of
-  // document accessible (it's handled by overriden GetXPAccessibleFor method
-  // on the document accessible). The getting an accessible by child ID is used
-  // by AccessibleObjectFromEvent() called by AT when AT handles our MSAA event.
-  Accessible* child = GetXPAccessibleFor(varChild);
-  if (!child)
+  // document accessible.
+  // The getting an accessible by child ID is used by AccessibleObjectFromEvent()
+  // called by AT when AT handles our MSAA event.
+  bool isDefunct = false;
+  RefPtr<IAccessible> child = GetIAccessibleFor(varChild, &isDefunct);
+  if (!child) {
     return E_INVALIDARG;
+  }
 
-  if (child->IsDefunct())
+  if (isDefunct) {
     return CO_E_OBJNOTCONNECTED;
+  }
 
-  *ppdispChild = NativeAccessible(child);
+  child.forget(ppdispChild);
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
+/**
+ * This function is a helper for implementing IAccessible methods that accept
+ * a Child ID as a parameter. If the child ID is CHILDID_SELF, the function
+ * returns S_OK but a null *aOutInterface. Otherwise, *aOutInterface points
+ * to the resolved IAccessible.
+ *
+ * The CHILDID_SELF case is special because in that case we actually execute
+ * the implementation of the IAccessible method, whereas in the non-self case,
+ * we delegate the method call to that object for execution.
+ *
+ * A sample invocation of this would look like:
+ *
+ *  RefPtr<IAccessible> accessible;
+ *  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+ *  if (FAILED(hr)) {
+ *    return hr;
+ *  }
+ *
+ *  if (accessible) {
+ *    return accessible->get_accFoo(kVarChildIdSelf, pszName);
+ *  }
+ *
+ *  // Implementation for CHILDID_SELF case goes here
+ */
+HRESULT
+AccessibleWrap::ResolveChild(const VARIANT& aVarChild,
+                             IAccessible** aOutInterface)
+{
+  MOZ_ASSERT(aOutInterface);
+  *aOutInterface = nullptr;
+
+  if (aVarChild.vt != VT_I4) {
+    return E_INVALIDARG;
+  }
+
+  if (IsDefunct()) {
+    return CO_E_OBJNOTCONNECTED;
+  }
+
+  if (aVarChild.lVal == CHILDID_SELF) {
+    return S_OK;
+  }
+
+  bool isDefunct = false;
+  RefPtr<IAccessible> accessible = GetIAccessibleFor(aVarChild, &isDefunct);
+  if (!accessible) {
+    return E_INVALIDARG;
+  }
+
+  if (isDefunct) {
+    return CO_E_OBJNOTCONNECTED;
+  }
+
+  accessible.forget(aOutInterface);
+  return S_OK;
+}
+
 STDMETHODIMP
 AccessibleWrap::get_accName(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszName)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  if (!pszName)
+  if (!pszName || varChild.vt != VT_I4)
     return E_INVALIDARG;
 
   *pszName = nullptr;
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  Accessible* xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible)
-    return E_INVALIDARG;
-
-  if (xpAccessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (accessible) {
+    return accessible->get_accName(kVarChildIdSelf, pszName);
+  }
 
   nsAutoString name;
-  xpAccessible->Name(name);
+  Name(name);
 
   // The name was not provided, e.g. no alt attribute for an image. A screen
   // reader may choose to invent its own accessible name, e.g. from an image src
   // attribute. Refer to eNoNameOnPurpose return value.
   if (name.IsVoid())
     return S_FALSE;
 
   *pszName = ::SysAllocStringLen(name.get(), name.Length());
@@ -312,28 +372,28 @@ AccessibleWrap::get_accValue(
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!pszValue)
     return E_INVALIDARG;
 
   *pszValue = nullptr;
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  Accessible* xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible)
-    return E_INVALIDARG;
-
-  if (xpAccessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (accessible) {
+    return accessible->get_accValue(kVarChildIdSelf, pszValue);
+  }
 
   nsAutoString value;
-  xpAccessible->Value(value);
+  Value(value);
 
   // See bug 438784: need to expose URL on doc's value attribute. For this,
   // reverting part of fix for bug 425693 to make this MSAA method behave
   // IAccessible2-style.
   if (value.IsEmpty())
     return S_FALSE;
 
   *pszValue = ::SysAllocStringLen(value.get(), value.Length());
@@ -350,28 +410,28 @@ AccessibleWrap::get_accDescription(VARIA
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!pszDescription)
     return E_INVALIDARG;
 
   *pszDescription = nullptr;
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  Accessible* xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible)
-    return E_INVALIDARG;
-
-  if (xpAccessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (accessible) {
+    return accessible->get_accDescription(kVarChildIdSelf, pszDescription);
+  }
 
   nsAutoString description;
-  xpAccessible->Description(description);
+  Description(description);
 
   *pszDescription = ::SysAllocStringLen(description.get(),
                                         description.Length());
   return *pszDescription ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
 
@@ -382,33 +442,33 @@ AccessibleWrap::get_accRole(
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!pvarRole)
     return E_INVALIDARG;
 
   VariantInit(pvarRole);
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  Accessible* xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible)
-    return E_INVALIDARG;
-
-  if (xpAccessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (accessible) {
+    return accessible->get_accRole(kVarChildIdSelf, pvarRole);
+  }
 
   a11y::role geckoRole;
 #ifdef DEBUG
-  NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(xpAccessible),
+  NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(this),
                "Does not support Text when it should");
 #endif
 
-  geckoRole = xpAccessible->Role();
+  geckoRole = Role();
 
   uint32_t msaaRole = 0;
 
 #define ROLE(_geckoRole, stringRole, atkRole, macRole, \
              _msaaRole, ia2Role, nameRule) \
   case roles::_geckoRole: \
     msaaRole = _msaaRole; \
     break;
@@ -435,17 +495,17 @@ AccessibleWrap::get_accRole(
     pvarRole->vt = VT_I4;
     pvarRole->lVal = msaaRole;  // Normal enumerated role
     return S_OK;
   }
 
   // -- Try BSTR role
   // Could not map to known enumerated MSAA role like ROLE_BUTTON
   // Use BSTR role to expose role attribute or tag name + namespace
-  nsIContent *content = xpAccessible->GetContent();
+  nsIContent *content = GetContent();
   if (!content)
     return E_FAIL;
 
   if (content->IsElement()) {
     nsAutoString roleString;
     if (msaaRole != ROLE_SYSTEM_CLIENT &&
         !content->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roleString)) {
       nsIDocument * document = content->GetUncomposedDoc();
@@ -484,25 +544,25 @@ AccessibleWrap::get_accState(
 
   if (!pvarState)
     return E_INVALIDARG;
 
   VariantInit(pvarState);
   pvarState->vt = VT_I4;
   pvarState->lVal = 0;
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  Accessible* xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible)
-    return E_INVALIDARG;
-
-  if (xpAccessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (accessible) {
+    return accessible->get_accState(kVarChildIdSelf, pvarState);
+  }
 
   // MSAA only has 31 states and the lowest 31 bits of our state bit mask
   // are the same states as MSAA.
   // Note: we map the following Gecko states to different MSAA states:
   //   REQUIRED -> ALERT_LOW
   //   ALERT -> ALERT_MEDIUM
   //   INVALID -> ALERT_HIGH
   //   CHECKABLE -> MARQUEED
@@ -558,29 +618,30 @@ AccessibleWrap::get_accKeyboardShortcut(
       /* [retval][out] */ BSTR __RPC_FAR *pszKeyboardShortcut)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!pszKeyboardShortcut)
     return E_INVALIDARG;
   *pszKeyboardShortcut = nullptr;
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
-
-  Accessible* acc = GetXPAccessibleFor(varChild);
-  if (!acc)
-    return E_INVALIDARG;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  if (acc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (accessible) {
+    return accessible->get_accKeyboardShortcut(kVarChildIdSelf,
+                                               pszKeyboardShortcut);
+  }
 
-  KeyBinding keyBinding = acc->AccessKey();
+  KeyBinding keyBinding = AccessKey();
   if (keyBinding.IsEmpty())
-    keyBinding = acc->KeyboardShortcut();
+    keyBinding = KeyboardShortcut();
 
   nsAutoString shortcut;
   keyBinding.ToString(shortcut);
 
   *pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
                                              shortcut.Length());
   return *pszKeyboardShortcut ? S_OK : E_OUTOFMEMORY;
 
@@ -791,81 +852,80 @@ AccessibleWrap::get_accDefaultAction(
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!pszDefaultAction)
     return E_INVALIDARG;
 
   *pszDefaultAction = nullptr;
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  Accessible* xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible)
-    return E_INVALIDARG;
-
-  if (xpAccessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (accessible) {
+    return accessible->get_accDefaultAction(kVarChildIdSelf, pszDefaultAction);
+  }
 
   nsAutoString defaultAction;
-  xpAccessible->ActionNameAt(0, defaultAction);
+  ActionNameAt(0, defaultAction);
 
   *pszDefaultAction = ::SysAllocStringLen(defaultAction.get(),
                                           defaultAction.Length());
   return *pszDefaultAction ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::accSelect(
       /* [in] */ long flagsSelect,
       /* [optional][in] */ VARIANT varChild)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  // currently only handle focus and selection
-  Accessible* xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible)
-    return E_INVALIDARG;
-
-  if (xpAccessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (accessible) {
+    return accessible->accSelect(flagsSelect, kVarChildIdSelf);
+  }
 
   if (flagsSelect & SELFLAG_TAKEFOCUS) {
     if (XRE_IsContentProcess()) {
       // In this case we might have been invoked while the IPC MessageChannel is
       // waiting on a sync reply. We cannot dispatch additional IPC while that
       // is happening, so we dispatch TakeFocus from the main thread to
       // guarantee that we are outside any IPC.
       nsCOMPtr<nsIRunnable> runnable =
-        mozilla::NewRunnableMethod(xpAccessible, &Accessible::TakeFocus);
+        mozilla::NewRunnableMethod(this, &Accessible::TakeFocus);
       NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
       return S_OK;
     }
-    xpAccessible->TakeFocus();
+    TakeFocus();
     return S_OK;
   }
 
   if (flagsSelect & SELFLAG_TAKESELECTION) {
-    xpAccessible->TakeSelection();
+    TakeSelection();
     return S_OK;
   }
 
   if (flagsSelect & SELFLAG_ADDSELECTION) {
-    xpAccessible->SetSelected(true);
+    SetSelected(true);
     return S_OK;
   }
 
   if (flagsSelect & SELFLAG_REMOVESELECTION) {
-    xpAccessible->SetSelected(false);
+    SetSelected(false);
     return S_OK;
   }
 
   return E_FAIL;
 
   A11Y_TRYBLOCK_END
 }
 
@@ -882,27 +942,28 @@ AccessibleWrap::accLocation(
   if (!pxLeft || !pyTop || !pcxWidth || !pcyHeight)
     return E_INVALIDARG;
 
   *pxLeft = 0;
   *pyTop = 0;
   *pcxWidth = 0;
   *pcyHeight = 0;
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  Accessible* xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible)
-    return E_INVALIDARG;
+  if (accessible) {
+    return accessible->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight,
+                                   kVarChildIdSelf);
+  }
 
-  if (xpAccessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
-
-  nsIntRect rect = xpAccessible->Bounds();
+  nsIntRect rect = Bounds();
 
   *pxLeft = rect.x;
   *pyTop = rect.y;
   *pcxWidth = rect.width;
   *pcyHeight = rect.height;
   return S_OK;
 
   A11Y_TRYBLOCK_END
@@ -916,64 +977,64 @@ AccessibleWrap::accNavigate(
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!pvarEndUpAt)
     return E_INVALIDARG;
 
   VariantInit(pvarEndUpAt);
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varStart, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  Accessible* accessible = GetXPAccessibleFor(varStart);
-  if (!accessible)
-    return E_INVALIDARG;
-
-  if (accessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (accessible) {
+    return accessible->accNavigate(navDir, kVarChildIdSelf, pvarEndUpAt);
+  }
 
   Accessible* navAccessible = nullptr;
   Maybe<RelationType> xpRelation;
 
 #define RELATIONTYPE(geckoType, stringType, atkType, msaaType, ia2Type) \
   case msaaType: \
     xpRelation.emplace(RelationType::geckoType); \
     break;
 
   switch(navDir) {
     case NAVDIR_FIRSTCHILD:
-      if (accessible->IsProxy()) {
-        if (!accessible->Proxy()->MustPruneChildren()) {
-          navAccessible = WrapperFor(accessible->Proxy()->FirstChild());
+      if (IsProxy()) {
+        if (!Proxy()->MustPruneChildren()) {
+          navAccessible = WrapperFor(Proxy()->FirstChild());
         }
       } else {
-        if (!nsAccUtils::MustPrune(accessible))
-          navAccessible = accessible->FirstChild();
+        if (!nsAccUtils::MustPrune(this))
+          navAccessible = FirstChild();
       }
       break;
     case NAVDIR_LASTCHILD:
-      if (accessible->IsProxy()) {
-        if (!accessible->Proxy()->MustPruneChildren()) {
-          navAccessible = WrapperFor(accessible->Proxy()->LastChild());
+      if (IsProxy()) {
+        if (!Proxy()->MustPruneChildren()) {
+          navAccessible = WrapperFor(Proxy()->LastChild());
         }
       } else {
-        if (!nsAccUtils::MustPrune(accessible))
-          navAccessible = accessible->LastChild();
+        if (!nsAccUtils::MustPrune(this))
+          navAccessible = LastChild();
       }
       break;
     case NAVDIR_NEXT:
-      navAccessible = accessible->IsProxy()
-        ? WrapperFor(accessible->Proxy()->NextSibling())
-        : accessible->NextSibling();
+      navAccessible = IsProxy()
+        ? WrapperFor(Proxy()->NextSibling())
+        : NextSibling();
       break;
     case NAVDIR_PREVIOUS:
-      navAccessible = accessible->IsProxy()
-        ? WrapperFor(accessible->Proxy()->PrevSibling())
-        : accessible->PrevSibling();
+      navAccessible = IsProxy()
+        ? WrapperFor(Proxy()->PrevSibling())
+        : PrevSibling();
       break;
     case NAVDIR_DOWN:
     case NAVDIR_LEFT:
     case NAVDIR_RIGHT:
     case NAVDIR_UP:
       return E_NOTIMPL;
 
     // MSAA relationship extensions to accNavigate
@@ -1041,27 +1102,27 @@ AccessibleWrap::accHitTest(
 }
 
 STDMETHODIMP
 AccessibleWrap::accDoDefaultAction(
       /* [optional][in] */ VARIANT varChild)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  if (IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  RefPtr<IAccessible> accessible;
+  HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
+  if (FAILED(hr)) {
+    return hr;
+  }
 
-  Accessible* xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible)
-    return E_INVALIDARG;
+  if (accessible) {
+    return accessible->accDoDefaultAction(kVarChildIdSelf);
+  }
 
-  if (xpAccessible->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
-
-  return xpAccessible->DoAction(0) ? S_OK : E_INVALIDARG;
+  return DoAction(0) ? S_OK : E_INVALIDARG;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::put_accName(
       /* [optional][in] */ VARIANT varChild,
       /* [in] */ BSTR szName)
@@ -1143,23 +1204,18 @@ AccessibleWrap::GetNativeInterface(void*
 {
   *aOutAccessible = static_cast<IAccessible*>(this);
   NS_ADDREF_THIS();
 }
 
 void
 AccessibleWrap::SetID(uint32_t aID)
 {
-  MOZ_ASSERT(XRE_IsContentProcess());
+  MOZ_ASSERT(XRE_IsParentProcess() && IsProxy());
   mID = aID;
-  DocAccessibleWrap* doc = static_cast<DocAccessibleWrap*>(Document());
-  DebugOnly<AccessibleWrap*> checkAcc = nullptr;
-  MOZ_ASSERT(!(checkAcc = doc->GetAccessibleByID(aID)) ||
-             checkAcc->GetExistingID() == aID);
-  doc->AddID(aID, this);
 }
 
 void
 AccessibleWrap::FireWinEvent(Accessible* aTarget, uint32_t aEventType)
 {
   MOZ_ASSERT(XRE_IsParentProcess());
   static_assert(sizeof(gWinEventMap)/sizeof(gWinEventMap[0]) == nsIAccessibleEvent::EVENT_LAST_ENTRY,
                 "MSAA event map skewed");
@@ -1252,54 +1308,38 @@ AccessibleWrap::GetChildIDFor(Accessible
   // A child ID of the window is required, when we use NotifyWinEvent,
   // so that the 3rd party application can call back and get the IAccessible
   // the event occurred on.
 
   if (!aAccessible) {
     return 0;
   }
 
-  // Content should use mID which has been generated by the chrome process.
-  if (XRE_IsContentProcess() && !aAccessible->IsApplication()) {
+  // Chrome should use mID which has been generated by the content process.
+  if (aAccessible->IsProxy()) {
     const uint32_t id = static_cast<AccessibleWrap*>(aAccessible)->mID;
     MOZ_ASSERT(id != kNoID);
     return id;
   }
 
-#ifdef _WIN64
-  if (!aAccessible->Document() && !aAccessible->IsProxy())
+  if (!aAccessible->Document())
     return 0;
 
   uint32_t* id = & static_cast<AccessibleWrap*>(aAccessible)->mID;
   if (*id != kNoID)
     return *id;
 
   *id = sIDGen.GetID();
 
-  if (aAccessible->IsProxy()) {
-    DocProxyAccessibleWrap* doc =
-      static_cast<AccessibleWrap*>(aAccessible)->DocProxyWrapper();
-    doc->AddID(*id, static_cast<AccessibleWrap*>(aAccessible));
-  } else {
-    DocAccessibleWrap* doc =
-      static_cast<DocAccessibleWrap*>(aAccessible->Document());
-    doc->AddID(*id, static_cast<AccessibleWrap*>(aAccessible));
-  }
+  MOZ_ASSERT(!aAccessible->IsProxy());
+  DocAccessibleWrap* doc =
+    static_cast<DocAccessibleWrap*>(aAccessible->Document());
+  doc->AddID(*id, static_cast<AccessibleWrap*>(aAccessible));
 
   return *id;
-#else
-  int32_t id = - reinterpret_cast<intptr_t>(aAccessible);
-  if (aAccessible->IsProxy()) {
-    DocProxyAccessibleWrap* doc =
-      static_cast<AccessibleWrap*>(aAccessible)->DocProxyWrapper();
-    doc->AddID(id, static_cast<AccessibleWrap*>(aAccessible));
-  }
-
-  return id;
-#endif
 }
 
 HWND
 AccessibleWrap::GetHWNDFor(Accessible* aAccessible)
 {
   if (!aAccessible) {
     return nullptr;
   }
@@ -1391,169 +1431,191 @@ GetAccessibleInSubtree(DocAccessible* aD
     child = GetAccessibleInSubtree(aDoc->GetChildDocumentAt(i), aID);
     if (child)
       return child;
   }
 
     return nullptr;
   }
 
-static AccessibleWrap*
-GetProxiedAccessibleInSubtree(const DocAccessibleParent* aDoc, uint32_t aID)
+static already_AddRefed<IDispatch>
+GetProxiedAccessibleInSubtree(const DocAccessibleParent* aDoc,
+                              const VARIANT& aVarChild)
 {
   auto wrapper = static_cast<DocProxyAccessibleWrap*>(WrapperFor(aDoc));
-  AccessibleWrap* child = wrapper->GetAccessibleByID(aID);
-  if (child) {
-    return child;
+  RefPtr<IAccessible> comProxy;
+  int32_t wrapperChildId = AccessibleWrap::GetChildIDFor(wrapper);
+  if (wrapperChildId == aVarChild.lVal) {
+    wrapper->GetNativeInterface(getter_AddRefs(comProxy));
+    return comProxy.forget();
   }
 
-  size_t childDocs = aDoc->ChildDocCount();
-  for (size_t i = 0; i < childDocs; i++) {
-    const DocAccessibleParent* childDoc = aDoc->ChildDocAt(i);
-    child = GetProxiedAccessibleInSubtree(childDoc, aID);
-    if (child) {
-      return child;
-    }
+  MOZ_ASSERT(aDoc->IsTopLevel());
+  if (!aDoc->IsTopLevel()) {
+    return nullptr;
   }
 
-  return nullptr;
+  wrapper->GetNativeInterface(getter_AddRefs(comProxy));
+
+  RefPtr<IDispatch> disp;
+  if (FAILED(comProxy->get_accChild(aVarChild, getter_AddRefs(disp)))) {
+    return nullptr;
+  }
+
+  return disp.forget();
 }
 
-Accessible*
-AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
+already_AddRefed<IAccessible>
+AccessibleWrap::GetIAccessibleFor(const VARIANT& aVarChild, bool* aIsDefunct)
 {
   if (aVarChild.vt != VT_I4)
     return nullptr;
 
-  // if its us real easy - this seems to always be the case
-  if (aVarChild.lVal == CHILDID_SELF)
-    return this;
+  VARIANT varChild = aVarChild;
+
+  MOZ_ASSERT(aIsDefunct);
+  *aIsDefunct = false;
+
+  RefPtr<IAccessible> result;
+
+  if (varChild.lVal == CHILDID_SELF) {
+    *aIsDefunct = IsDefunct();
+    if (*aIsDefunct) {
+      return nullptr;
+    }
+    GetNativeInterface(getter_AddRefs(result));
+    if (result) {
+      return result.forget();
+    }
+    // If we're not a proxy, there's nothing more we can do to attempt to
+    // resolve the IAccessible, so we just fail.
+    if (!IsProxy()) {
+      return nullptr;
+    }
+    // Otherwise, since we're a proxy and we have a null native interface, this
+    // indicates that we need to obtain a COM proxy. To do this, we'll replace
+    // CHILDID_SELF with our real MSAA ID and continue the search from there.
+    varChild.lVal = GetExistingID();
+  }
 
   if (IsProxy() ? Proxy()->MustPruneChildren() : nsAccUtils::MustPrune(this)) {
     return nullptr;
   }
 
-  if (aVarChild.lVal > 0) {
+  // If the MSAA ID is not a chrome id then we already know that we won't
+  // find it here and should look remotely instead.
+  if (XRE_IsParentProcess() && !sIDGen.IsChromeID(varChild.lVal)) {
+    return GetRemoteIAccessibleFor(varChild);
+  }
+  MOZ_ASSERT(XRE_IsParentProcess() ||
+             sIDGen.IsIDForThisContentProcess(varChild.lVal));
+
+  if (varChild.lVal > 0) {
     // Gecko child indices are 0-based in contrast to indices used in MSAA.
-    if (IsProxy()) {
-      if (static_cast<uint32_t>(aVarChild.lVal) > Proxy()->ChildrenCount()) {
-        return nullptr;
-      }
-
-      return WrapperFor(Proxy()->ChildAt(aVarChild.lVal - 1));
-    } else {
-      return GetChildAt(aVarChild.lVal - 1);
+    MOZ_ASSERT(!IsProxy());
+    Accessible* xpAcc = GetChildAt(varChild.lVal - 1);
+    if (!xpAcc) {
+      return nullptr;
     }
+    *aIsDefunct = xpAcc->IsDefunct();
+    static_cast<AccessibleWrap*>(xpAcc)->GetNativeInterface(getter_AddRefs(result));
+    return result.forget();
   }
 
   // If lVal negative then it is treated as child ID and we should look for
   // accessible through whole accessible subtree including subdocuments.
   // Otherwise we treat lVal as index in parent.
-  // Convert child ID to unique ID.
   // First handle the case that both this accessible and the id'd one are in
   // this process.
   if (!IsProxy()) {
-    void* uniqueID = reinterpret_cast<void*>(intptr_t(-aVarChild.lVal));
-
     DocAccessible* document = Document();
     Accessible* child =
-#ifdef _WIN64
-      GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal));
-#else
-      XRE_IsContentProcess() ?
-        GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal)) :
-        document->GetAccessibleByUniqueIDInSubtree(uniqueID);
-#endif
+      GetAccessibleInSubtree(document, static_cast<uint32_t>(varChild.lVal));
 
     // If it is a document then just return an accessible.
-    if (child && IsDoc())
-      return child;
+    if (child && IsDoc()) {
+      *aIsDefunct = child->IsDefunct();
+      static_cast<AccessibleWrap*>(child)->GetNativeInterface(getter_AddRefs(result));
+      return result.forget();
+    }
 
     // Otherwise check whether the accessible is a child (this path works for
     // ARIA documents and popups).
     Accessible* parent = child;
     while (parent && parent != document) {
-      if (parent == this)
-        return child;
+      if (parent == this) {
+        *aIsDefunct = child->IsDefunct();
+        static_cast<AccessibleWrap*>(child)->GetNativeInterface(getter_AddRefs(result));
+        return result.forget();
+      }
 
       parent = parent->Parent();
     }
   }
 
   // Now see about the case that both this accessible and the target one are
   // proxied.
-  uint32_t id = aVarChild.lVal;
   if (IsProxy()) {
     DocAccessibleParent* proxyDoc = Proxy()->Document();
-    AccessibleWrap* wrapper = GetProxiedAccessibleInSubtree(proxyDoc, id);
-    if (!wrapper)
+    RefPtr<IDispatch> disp = GetProxiedAccessibleInSubtree(proxyDoc, varChild);
+    if (!disp) {
       return nullptr;
-
-    MOZ_ASSERT(wrapper->IsProxy());
-
-    if (proxyDoc == this->Proxy()) {
-      return wrapper;
     }
 
-    ProxyAccessible* parent = wrapper->Proxy();
-    while (parent && parent != proxyDoc) {
-      if (parent == this->Proxy()) {
-        return wrapper;
-      }
-
-      parent = parent->Parent();
-    }
-
-    return nullptr;
+    MOZ_ASSERT(mscom::IsProxy(disp));
+    DebugOnly<HRESULT> hr = disp->QueryInterface(IID_IAccessible,
+                                                 getter_AddRefs(result));
+    MOZ_ASSERT(SUCCEEDED(hr));
+    return result.forget();
   }
 
-  // Finally we need to handle the case that this accessible is in the main
-  // process, but the target is proxied.  This is the case when the target
-  // accessible is in a child document of this one.
+  return nullptr;
+}
+
+already_AddRefed<IAccessible>
+AccessibleWrap::GetRemoteIAccessibleFor(const VARIANT& aVarChild)
+{
   DocAccessibleParent* proxyDoc = nullptr;
   DocAccessible* doc = Document();
   const nsTArray<DocAccessibleParent*>* remoteDocs =
     DocManager::TopLevelRemoteDocs();
   if (!remoteDocs) {
     return nullptr;
   }
 
+  RefPtr<IAccessible> result;
+
   size_t docCount = remoteDocs->Length();
   for (size_t i = 0; i < docCount; i++) {
-    Accessible* outerDoc = remoteDocs->ElementAt(i)->OuterDocOfRemoteBrowser();
+    DocAccessibleParent* remoteDoc = remoteDocs->ElementAt(i);
+
+    uint32_t remoteDocMsaaId = WrapperFor(remoteDoc)->GetExistingID();
+    if (!sIDGen.IsSameContentProcessFor(aVarChild.lVal, remoteDocMsaaId)) {
+      continue;
+    }
+
+    Accessible* outerDoc = remoteDoc->OuterDocOfRemoteBrowser();
     if (!outerDoc) {
       continue;
     }
 
     if (outerDoc->Document() != doc) {
       continue;
     }
 
-    if (doc == this) {
-      AccessibleWrap* proxyWrapper =
-        GetProxiedAccessibleInSubtree(remoteDocs->ElementAt(i), id);
-      if (proxyWrapper) {
-        return proxyWrapper;
-      }
-
+    RefPtr<IDispatch> disp =
+      GetProxiedAccessibleInSubtree(remoteDoc, aVarChild);
+    if (!disp) {
       continue;
     }
 
-    Accessible* parent = outerDoc;
-    while (parent && parent != doc) {
-      if (parent == this) {
-        AccessibleWrap* proxyWrapper =
-          GetProxiedAccessibleInSubtree(remoteDocs->ElementAt(i), id);
-        if (proxyWrapper) {
-          return proxyWrapper;
-        }
-      }
-
-      parent = parent->Parent();
-    }
+    DebugOnly<HRESULT> hr = disp->QueryInterface(IID_IAccessible,
+                                                 getter_AddRefs(result));
+    MOZ_ASSERT(SUCCEEDED(hr));
+    return result.forget();
   }
 
   return nullptr;
 }
 
 void
 AccessibleWrap::UpdateSystemCaretFor(Accessible* aAccessible)
 {
@@ -1598,8 +1660,22 @@ AccessibleWrap::GetTI(LCID lcid)
   hr = typeLib->GetTypeInfoOfGuid(IID_IAccessible, &gTypeInfo);
   typeLib->Release();
 
   if (FAILED(hr))
     return nullptr;
 
   return gTypeInfo;
 }
+
+/* static */
+uint32_t
+AccessibleWrap::GetContentProcessIdFor(dom::ContentParentId aIPCContentId)
+{
+  return sIDGen.GetContentProcessIDFor(aIPCContentId);
+}
+
+/* static */
+void
+AccessibleWrap::ReleaseContentProcessIdFor(dom::ContentParentId aIPCContentId)
+{
+  sIDGen.ReleaseContentProcessIDFor(aIPCContentId);
+}
--- a/accessible/windows/msaa/AccessibleWrap.h
+++ b/accessible/windows/msaa/AccessibleWrap.h
@@ -9,18 +9,19 @@
 
 #include "nsCOMPtr.h"
 #include "Accessible.h"
 #include "Accessible2.h"
 #include "ia2Accessible.h"
 #include "ia2AccessibleComponent.h"
 #include "ia2AccessibleHyperlink.h"
 #include "ia2AccessibleValue.h"
+#include "mozilla/a11y/MsaaIdGenerator.h"
 #include "mozilla/a11y/ProxyAccessible.h"
-#include "mozilla/a11y/IDSet.h"
+#include "mozilla/Attributes.h"
 
 #ifdef __GNUC__
 // Inheriting from both XPCOM and MSCOM interfaces causes a lot of warnings
 // about virtual functions being hidden by each other. This is done by
 // design, so silence the warning.
 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
 #endif
 
@@ -168,47 +169,57 @@ public: // construction, destruction
    * We will use an invisible system caret.
    * Gecko is still responsible for drawing its own caret
    */
   void UpdateSystemCaretFor(Accessible* aAccessible);
 
   /**
    * Find an accessible by the given child ID in cached documents.
    */
-  Accessible* GetXPAccessibleFor(const VARIANT& aVarChild);
+  MOZ_MUST_USE already_AddRefed<IAccessible>
+  GetIAccessibleFor(const VARIANT& aVarChild, bool* aIsDefunct);
 
   virtual void GetNativeInterface(void **aOutAccessible) override;
 
   static IDispatch* NativeAccessible(Accessible* aAccessible);
 
   uint32_t GetExistingID() const { return mID; }
   static const uint32_t kNoID = 0;
-  // This is only valid to call in content
   void SetID(uint32_t aID);
 
+  static uint32_t GetContentProcessIdFor(dom::ContentParentId aIPCContentId);
+  static void ReleaseContentProcessIdFor(dom::ContentParentId aIPCContentId);
+
 protected:
   virtual ~AccessibleWrap();
 
   uint32_t mID;
 
+  HRESULT
+  ResolveChild(const VARIANT& aVarChild, IAccessible** aOutInterface);
+
+  /**
+   * Find a remote accessible by the given child ID.
+   */
+  MOZ_MUST_USE already_AddRefed<IAccessible>
+  GetRemoteIAccessibleFor(const VARIANT& aVarChild);
+
   /**
    * Return the wrapper for the document's proxy.
    */
   DocProxyAccessibleWrap* DocProxyWrapper() const;
 
   /**
    * Creates ITypeInfo for LIBID_Accessibility if it's needed and returns it.
    */
   static ITypeInfo* GetTI(LCID lcid);
 
   static ITypeInfo* gTypeInfo;
 
-#ifdef _WIN64
-  static IDSet sIDGen;
-#endif
+  static MsaaIdGenerator sIDGen;
 
   enum navRelations {
     NAVRELATION_CONTROLLED_BY = 0x1000,
     NAVRELATION_CONTROLLER_FOR = 0x1001,
     NAVRELATION_LABEL_FOR = 0x1002,
     NAVRELATION_LABELLED_BY = 0x1003,
     NAVRELATION_MEMBER_OF = 0x1004,
     NAVRELATION_NODE_CHILD_OF = 0x1005,
deleted file mode 100644
--- a/accessible/windows/msaa/ChildIDThunk.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ChildIDThunk.h"
-#include "MainThreadUtils.h"
-#include "mozilla/mscom/InterceptorLog.h"
-
-using namespace mozilla::mscom;
-
-namespace mozilla {
-namespace a11y {
-
-ChildIDThunk::ChildIDThunk()
-  : mRefCnt(0)
-{
-}
-
-HRESULT
-ChildIDThunk::QueryInterface(REFIID riid, void** ppv)
-{
-  if (!ppv) {
-    return E_INVALIDARG;
-  }
-
-  if (riid == IID_IUnknown || riid == IID_ICallFrameEvents ||
-      riid == IID_IInterceptorSink) {
-    *ppv = static_cast<IInterceptorSink*>(this);
-    AddRef();
-    return S_OK;
-  }
-
-  *ppv = nullptr;
-  return E_NOINTERFACE;
-}
-
-ULONG
-ChildIDThunk::AddRef()
-{
-  return (ULONG) InterlockedIncrement((LONG*)&mRefCnt);
-}
-
-ULONG
-ChildIDThunk::Release()
-{
-  ULONG newRefCnt = (ULONG) InterlockedDecrement((LONG*)&mRefCnt);
-  if (newRefCnt == 0) {
-    MOZ_ASSERT(NS_IsMainThread());
-    delete this;
-  }
-  return newRefCnt;
-}
-
-enum IAccessibleVTableIndex
-{
-  eget_accName = 10,
-  eget_accValue = 11,
-  eget_accDescription = 12,
-  eget_accRole = 13,
-  eget_accState = 14,
-  eget_accHelp = 15,
-  eget_accHelpTopic = 16,
-  eget_accKeyboardShortcut = 17,
-  eget_accDefaultAction = 20,
-  eaccSelect = 21,
-  eaccLocation = 22,
-  eaccNavigate = 23,
-  eaccDoDefaultAction = 25,
-  eput_accName = 26,
-  eput_accValue = 27
-};
-
-Maybe<ULONG>
-ChildIDThunk::IsMethodInteresting(const ULONG aMethodIdx)
-{
-  switch (aMethodIdx) {
-    case eget_accName:
-    case eget_accValue:
-    case eget_accDescription:
-    case eget_accRole:
-    case eget_accState:
-    case eget_accHelp:
-    case eget_accKeyboardShortcut:
-    case eget_accDefaultAction:
-    case eaccDoDefaultAction:
-    case eput_accName:
-    case eput_accValue:
-      return Some(0UL);
-    case eget_accHelpTopic:
-    case eaccNavigate:
-      return Some(1UL);
-    case eaccSelect:
-      return Some(2UL);
-    case eaccLocation:
-      return Some(4UL);
-    default:
-      return Nothing();
-  }
-}
-
-bool
-ChildIDThunk::IsChildIDSelf(ICallFrame* aFrame, const ULONG aChildIDIdx,
-                            LONG& aOutChildID)
-{
-  VARIANT paramValue;
-  HRESULT hr = aFrame->GetParam(aChildIDIdx, &paramValue);
-  MOZ_ASSERT(SUCCEEDED(hr));
-  if (FAILED(hr)) {
-    return false;
-  }
-
-  const bool isVariant = paramValue.vt & VT_VARIANT;
-  MOZ_ASSERT(isVariant);
-  if (!isVariant) {
-    return false;
-  }
-
-  VARIANT& childID = *(paramValue.pvarVal);
-  if (childID.vt != VT_I4) {
-    return false;
-  }
-
-  aOutChildID = childID.lVal;
-  return childID.lVal == CHILDID_SELF;
-}
-
-/**
- * ICallFrame::SetParam always returns E_NOTIMPL, so we'll just have to work
- * around this by manually poking at the parameter's location on the stack.
- */
-/* static */ HRESULT
-ChildIDThunk::SetChildIDParam(ICallFrame* aFrame, const ULONG aParamIdx,
-                              const LONG aChildID)
-{
-  void* stackBase = aFrame->GetStackLocation();
-  MOZ_ASSERT(stackBase);
-  if (!stackBase) {
-    return E_UNEXPECTED;
-  }
-
-  CALLFRAMEPARAMINFO paramInfo;
-  HRESULT hr = aFrame->GetParamInfo(aParamIdx, &paramInfo);
-  MOZ_ASSERT(SUCCEEDED(hr));
-  if (FAILED(hr)) {
-    return hr;
-  }
-
-  // We expect this childID to be a VARIANT in-parameter
-  MOZ_ASSERT(paramInfo.fIn);
-  MOZ_ASSERT(paramInfo.cbParam == sizeof(VARIANT));
-  if (!paramInfo.fIn || paramInfo.cbParam != sizeof(VARIANT)) {
-    return E_UNEXPECTED;
-  }
-
-  // Given the stack base and param offset, calculate the address of the param
-  // and replace its value
-  VARIANT* pInParam = reinterpret_cast<VARIANT*>(
-      reinterpret_cast<PBYTE>(stackBase) + paramInfo.stackOffset);
-  MOZ_ASSERT(pInParam->vt == VT_I4);
-  if (pInParam->vt != VT_I4) {
-    return E_UNEXPECTED;
-  }
-  pInParam->lVal = aChildID;
-  return S_OK;
-}
-
-HRESULT
-ChildIDThunk::ResolveTargetInterface(REFIID aIid, IUnknown** aOut)
-{
-  MOZ_ASSERT(aOut);
-  *aOut = nullptr;
-
-  RefPtr<IInterceptor> interceptor;
-  HRESULT hr = mInterceptor->Resolve(IID_IInterceptor,
-                                     (void**)getter_AddRefs(interceptor));
-  if (FAILED(hr)) {
-    return hr;
-  }
-
-  InterceptorTargetPtr target;
-  hr = interceptor->GetTargetForIID(aIid, target);
-  if (FAILED(hr)) {
-    return hr;
-  }
-
-  RefPtr<IUnknown> refTarget = target.get();
-  refTarget.forget(aOut);
-  return S_OK;
-}
-
-HRESULT
-ChildIDThunk::OnCall(ICallFrame* aFrame)
-{
-#if defined(MOZILLA_INTERNAL_API)
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(XRE_IsParentProcess());
-#endif
-
-  IID iid;
-  ULONG method;
-  HRESULT hr = aFrame->GetIIDAndMethod(&iid, &method);
-  MOZ_ASSERT(SUCCEEDED(hr));
-  if (FAILED(hr)) {
-    return hr;
-  }
-
-  RefPtr<IUnknown> target;
-  hr = ResolveTargetInterface(iid, getter_AddRefs(target));
-  if (FAILED(hr)) {
-    return hr;
-  }
-
-  Maybe<ULONG> childIDIdx;
-  LONG childID;
-  if (iid != IID_IAccessible ||
-      (childIDIdx = IsMethodInteresting(method)).isNothing() ||
-      IsChildIDSelf(aFrame, childIDIdx.value(), childID)) {
-    // We're only interested in methods which accept a child ID parameter which
-    // is not equal to CHILDID_SELF. Otherwise we just invoke against the
-    // original target interface.
-    hr = aFrame->Invoke(target);
-    if (SUCCEEDED(hr)) {
-      InterceptorLog::Event(aFrame, target);
-    }
-    return hr;
-  }
-
-  // Otherwise we need to resolve the child node...
-  RefPtr<IAccessible> acc;
-  hr = target->QueryInterface(iid, (void**)getter_AddRefs(acc));
-  if (FAILED(hr)) {
-    return hr;
-  }
-
-  VARIANT vChildID;
-  VariantInit(&vChildID);
-  vChildID.vt = VT_I4;
-  vChildID.lVal = childID;
-
-  RefPtr<IDispatch> disp;
-  hr = acc->get_accChild(vChildID, getter_AddRefs(disp));
-  if (FAILED(hr)) {
-    aFrame->SetReturnValue(hr);
-    return S_OK;
-  }
-
-  RefPtr<IAccessible> directAccessible;
-  // Yes, given our implementation we could just downcast, but that's not very COMy
-  hr = disp->QueryInterface(IID_IAccessible,
-                            (void**)getter_AddRefs(directAccessible));
-  if (FAILED(hr)) {
-    aFrame->SetReturnValue(hr);
-    return S_OK;
-  }
-
-  // Now that we have the IAccessible for the child ID we need to replace it
-  // in the activation record with a self-referant child ID
-  hr = SetChildIDParam(aFrame, childIDIdx.value(), CHILDID_SELF);
-  MOZ_ASSERT(SUCCEEDED(hr));
-  if (FAILED(hr)) {
-    return hr;
-  }
-
-  hr = aFrame->Invoke(directAccessible);
-  if (SUCCEEDED(hr)) {
-    InterceptorLog::Event(aFrame, directAccessible);
-  }
-  return hr;
-}
-
-HRESULT
-ChildIDThunk::SetInterceptor(IWeakReference* aInterceptor)
-{
-  mInterceptor = aInterceptor;
-  return S_OK;
-}
-
-} // namespace a11y
-} // namespace mozilla
-
deleted file mode 100644
--- a/accessible/windows/msaa/ChildIDThunk.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_a11y_ChildIDThunk_h
-#define mozilla_a11y_ChildIDThunk_h
-
-#include "mozilla/mscom/Interceptor.h"
-#include "mozilla/Maybe.h"
-#include "mozilla/RefPtr.h"
-
-#include <oleacc.h>
-#include <callobj.h>
-
-namespace mozilla {
-namespace a11y {
-
-class ChildIDThunk : public mozilla::mscom::IInterceptorSink
-{
-public:
-  ChildIDThunk();
-
-  // IUnknown
-  STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
-  STDMETHODIMP_(ULONG) AddRef() override;
-  STDMETHODIMP_(ULONG) Release() override;
-
-  // ICallFrameEvents
-  STDMETHODIMP OnCall(ICallFrame* aFrame) override;
-
-  // IInterceptorSink
-  STDMETHODIMP SetInterceptor(mozilla::mscom::IWeakReference* aInterceptor) override;
-
-private:
-  HRESULT ResolveTargetInterface(REFIID aIid, IUnknown** aOut);
-
-  static mozilla::Maybe<ULONG> IsMethodInteresting(const ULONG aMethodIdx);
-  static bool IsChildIDSelf(ICallFrame* aFrame, const ULONG aChildIdIdx,
-                            LONG& aOutChildID);
-  static HRESULT SetChildIDParam(ICallFrame* aFrame, const ULONG aParamIdx,
-                                 const LONG aChildID);
-
-private:
-  ULONG mRefCnt;
-  RefPtr<mozilla::mscom::IWeakReference> mInterceptor;
-};
-
-} // namespace a11y
-} // namespace mozilla
-
-#endif // mozilla_a11y_ChildIDThunk_h
-
--- a/accessible/windows/msaa/IDSet.h
+++ b/accessible/windows/msaa/IDSet.h
@@ -14,72 +14,81 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/SplayTree.h"
 
 namespace mozilla {
 namespace a11y {
 
 /**
- * On windows an accessible's id must be a negative 32 bit integer.  It is
+ * On windows an accessible's id must be a negative 32 bit integer. It is
  * important to support recycling arbitrary IDs because accessibles can be
  * created and destroyed at any time in the life of a page.  IDSet provides 2
- * operations: generate an ID in the range [ - 2^31, 0 ), and release an ID so
+ * operations: generate an ID in the range (0, mMaxId], and release an ID so
  * it can be allocated again.  Allocated ID are tracked by a sparse bitmap
  * implemented with a splay tree.  Nodes in the tree are keyed by the upper N
- * bits of the bitwise negation of the ID, and the node contains a bitmap
- * tracking the allocation of 2^(32 - N) IDs.
+ * bits of the ID, and the node contains a bitmap tracking the allocation of
+ * 2^(ceil(log2(mMaxId)) - N) IDs.
+ *
+ * Note that negation is handled by MsaaIdGenerator as it performs additional
+ * decoration on the ID generated by IDSet.
+ * @see mozilla::a11y::MsaaIdGenerator
  */
 class IDSet
 {
 public:
-  constexpr IDSet() : mBitSet(), mIdx(0) {}
+  constexpr explicit IDSet(const uint32_t aMaxIdBits)
+    : mBitSet()
+    , mIdx(0)
+    , mMaxId((1UL << aMaxIdBits) - 1UL)
+    , mMaxIdx(mMaxId / bitsPerElt)
+  {
+  }
 
   /**
    * Return a new unique id.
    */
   uint32_t GetID()
   {
     uint32_t idx = mIdx;
     while (true) {
       BitSetElt* elt = mBitSet.findOrInsert(BitSetElt(idx));
       if (elt->mBitvec[0] != UINT64_MAX) {
         uint32_t i = CountTrailingZeroes64(~elt->mBitvec[0]);
 
         elt->mBitvec[0] |= (1ull << i);
         mIdx = idx;
-        return ~(elt->mIdx * bitsPerElt + i);
+        return (elt->mIdx * bitsPerElt + i);
       }
 
       if (elt->mBitvec[1] != UINT64_MAX) {
         uint32_t i = CountTrailingZeroes64(~elt->mBitvec[1]);
 
         elt->mBitvec[1] |= (1ull << i);
         mIdx = idx;
-        return ~(elt->mIdx * bitsPerElt + bitsPerWord + i);
+        return (elt->mIdx * bitsPerElt + bitsPerWord + i);
       }
 
       idx++;
-      if (idx > sMaxIdx) {
+      if (idx > mMaxIdx) {
         idx = 0;
       }
 
       if (idx == mIdx) {
         MOZ_CRASH("used up all the available ids");
       }
     }
   }
 
   /**
    * Free a no longer required id so it may be allocated again.
    */
   void ReleaseID(uint32_t aID)
   {
-    aID = ~aID;
-    MOZ_ASSERT(aID < static_cast<uint32_t>(INT32_MAX));
+    MOZ_ASSERT(aID < mMaxId);
 
     uint32_t idx = aID / bitsPerElt;
     mIdx = idx;
     BitSetElt* elt = mBitSet.find(BitSetElt(idx));
     MOZ_ASSERT(elt);
 
     uint32_t vecIdx = (aID % bitsPerElt) / bitsPerWord;
     elt->mBitvec[vecIdx] &= ~(1ull << (aID % bitsPerWord));
@@ -87,17 +96,16 @@ public:
       delete mBitSet.remove(*elt);
     }
   }
 
 private:
   static const unsigned int wordsPerElt = 2;
   static const unsigned int bitsPerWord = 64;
   static const unsigned int bitsPerElt = wordsPerElt * bitsPerWord;
-  static const uint32_t sMaxIdx = INT32_MAX / bitsPerElt;
 
   struct BitSetElt : mozilla::SplayTreeNode<BitSetElt>
   {
     explicit BitSetElt(uint32_t aIdx) :
       mIdx(aIdx)
     { mBitvec[0] = mBitvec[1] = 0; }
 
     uint64_t mBitvec[wordsPerElt];
@@ -113,14 +121,16 @@ private:
         return -1;
       }
       return 1;
     }
   };
 
   SplayTree<BitSetElt, BitSetElt> mBitSet;
   uint32_t mIdx;
+  const uint32_t mMaxId;
+  const uint32_t mMaxIdx;
 };
 
 }
 }
 
 #endif
new file mode 100644
--- /dev/null
+++ b/accessible/windows/msaa/MsaaIdGenerator.cpp
@@ -0,0 +1,246 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MsaaIdGenerator.h"
+
+#include "mozilla/a11y/AccessibleWrap.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/Unused.h"
+#include "nsDataHashtable.h"
+#include "nsIXULRuntime.h"
+
+// These constants may be adjusted to modify the proportion of the Child ID
+// allocated to the content ID vs proportion allocated to the unique ID. They
+// must always sum to 31, ie. the width of a 32-bit integer less the sign bit.
+
+// NB: kNumContentProcessIDBits must be large enough to successfully hold the
+// maximum permitted number of e10s content processes. If the e10s maximum
+// number of content processes changes, then kNumContentProcessIDBits must also
+// be updated if necessary to accommodate that new value!
+static const uint32_t kNumContentProcessIDBits = 7UL;
+static const uint32_t kNumUniqueIDBits = (31UL - kNumContentProcessIDBits);
+
+static_assert(kNumContentProcessIDBits + kNumUniqueIDBits == 31,
+              "Allocation of Content ID bits and Unique ID bits must sum to 31");
+
+namespace mozilla {
+namespace a11y {
+namespace detail {
+
+typedef nsDataHashtable<nsUint64HashKey, uint32_t> ContentParentIdMap;
+
+#pragma pack(push, 1)
+union MsaaID
+{
+  int32_t mInt32;
+  uint32_t mUInt32;
+  struct
+  {
+    uint32_t mUniqueID:kNumUniqueIDBits;
+    uint32_t mContentProcessID:kNumContentProcessIDBits;
+    uint32_t mSignBit:1;
+  }
+  mCracked;
+};
+#pragma pack(pop)
+
+static uint32_t
+BuildMsaaID(const uint32_t aID, const uint32_t aContentProcessID)
+{
+  MsaaID id;
+  id.mCracked.mSignBit = 0;
+  id.mCracked.mUniqueID = aID;
+  id.mCracked.mContentProcessID = aContentProcessID;
+  return ~id.mUInt32;
+}
+
+class MsaaIDCracker
+{
+public:
+  explicit MsaaIDCracker(const uint32_t aMsaaID)
+  {
+    mID.mUInt32 = ~aMsaaID;
+  }
+
+  uint32_t GetContentProcessId()
+  {
+    return mID.mCracked.mContentProcessID;
+  }
+
+  uint32_t GetUniqueId()
+  {
+    return mID.mCracked.mUniqueID;
+  }
+
+private:
+  MsaaID  mID;
+};
+
+} // namespace detail
+
+constexpr MsaaIdGenerator::MsaaIdGenerator()
+  : mIDSet(kNumUniqueIDBits)
+  , mContentProcessID(0)
+{}
+
+uint32_t
+MsaaIdGenerator::GetID()
+{
+  static const uint32_t kContentProcessId = ResolveContentProcessID();
+  uint32_t id = mIDSet.GetID();
+  MOZ_ASSERT(id <= ((1UL << kNumUniqueIDBits) - 1UL));
+  return detail::BuildMsaaID(id, kContentProcessId);
+}
+
+void
+MsaaIdGenerator::ReleaseID(AccessibleWrap* aAccWrap)
+{
+  MOZ_ASSERT(aAccWrap);
+  uint32_t id = aAccWrap->GetExistingID();
+  MOZ_ASSERT(id != AccessibleWrap::kNoID);
+  detail::MsaaIDCracker cracked(id);
+  if (cracked.GetContentProcessId() != mContentProcessID) {
+    // This may happen if chrome holds a proxy whose ID was originally generated
+    // by a content process. Since ReleaseID only has meaning in the process
+    // that originally generated that ID, we ignore ReleaseID calls for any ID
+    // that did not come from the current process.
+    MOZ_ASSERT(aAccWrap->IsProxy());
+    return;
+  }
+  mIDSet.ReleaseID(cracked.GetUniqueId());
+}
+
+bool
+MsaaIdGenerator::IsChromeID(uint32_t aID)
+{
+  detail::MsaaIDCracker cracked(aID);
+  return cracked.GetContentProcessId() == 0;
+}
+
+bool
+MsaaIdGenerator::IsIDForThisContentProcess(uint32_t aID)
+{
+  MOZ_ASSERT(XRE_IsContentProcess());
+  static const uint32_t kContentProcessId = ResolveContentProcessID();
+  detail::MsaaIDCracker cracked(aID);
+  return cracked.GetContentProcessId() == kContentProcessId;
+}
+
+bool
+MsaaIdGenerator::IsIDForContentProcess(uint32_t aID,
+                                       dom::ContentParentId aIPCContentProcessId)
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+  detail::MsaaIDCracker cracked(aID);
+  return cracked.GetContentProcessId() ==
+           GetContentProcessIDFor(aIPCContentProcessId);
+}
+
+bool
+MsaaIdGenerator::IsSameContentProcessFor(uint32_t aFirstID, uint32_t aSecondID)
+{
+  detail::MsaaIDCracker firstCracked(aFirstID);
+  detail::MsaaIDCracker secondCracked(aSecondID);
+  return firstCracked.GetContentProcessId() ==
+           secondCracked.GetContentProcessId();
+}
+
+uint32_t
+MsaaIdGenerator::ResolveContentProcessID()
+{
+  if (XRE_IsParentProcess()) {
+    return 0;
+  }
+
+  dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
+  Unused << contentChild->SendGetA11yContentId(&mContentProcessID);
+
+  MOZ_ASSERT(mContentProcessID);
+  return mContentProcessID;
+}
+
+/**
+ * Each dom::ContentParent has a 64-bit ID. This ID is monotonically increasing
+ * with each new content process, so those IDs are effectively single-use. OTOH,
+ * MSAA requires 32-bit IDs. Since we only allocate kNumContentProcessIDBits for
+ * the content process ID component, the MSAA content process ID value must be
+ * reusable. sContentParentIdMap holds the current associations between
+ * dom::ContentParent IDs and the MSAA content parent IDs that have been
+ * allocated to them.
+ */
+static StaticAutoPtr<detail::ContentParentIdMap> sContentParentIdMap;
+
+static const uint32_t kBitsPerByte = 8UL;
+// Set sContentProcessIdBitmap[0] to 1 to reserve the Chrome process's id
+static uint64_t sContentProcessIdBitmap[(1UL << kNumContentProcessIDBits) /
+                                        (sizeof(uint64_t) * kBitsPerByte)] = {1ULL};
+static const uint32_t kBitsPerElement = sizeof(sContentProcessIdBitmap[0]) *
+                                        kBitsPerByte;
+
+uint32_t
+MsaaIdGenerator::GetContentProcessIDFor(dom::ContentParentId aIPCContentProcessID)
+{
+  MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
+  if (!sContentParentIdMap) {
+    sContentParentIdMap = new detail::ContentParentIdMap();
+    ClearOnShutdown(&sContentParentIdMap);
+  }
+
+  uint32_t value = 0;
+  if (sContentParentIdMap->Get(aIPCContentProcessID, &value)) {
+    return value;
+  }
+
+  uint32_t index = 0;
+  for (; index < ArrayLength(sContentProcessIdBitmap); ++index) {
+    if (sContentProcessIdBitmap[index] == UINT64_MAX) {
+      continue;
+    }
+    uint32_t bitIndex = CountTrailingZeroes64(~sContentProcessIdBitmap[index]);
+    MOZ_ASSERT(!(sContentProcessIdBitmap[index] & (1ULL << bitIndex)));
+    MOZ_ASSERT(bitIndex != 0 || index != 0);
+    sContentProcessIdBitmap[index] |= (1ULL << bitIndex);
+    value = index * kBitsPerElement + bitIndex;
+    break;
+  }
+
+  // If we run out of content process IDs, we're in trouble
+  MOZ_RELEASE_ASSERT(index < ArrayLength(sContentProcessIdBitmap));
+
+  sContentParentIdMap->Put(aIPCContentProcessID, value);
+  return value;
+}
+
+void
+MsaaIdGenerator::ReleaseContentProcessIDFor(dom::ContentParentId aIPCContentProcessID)
+{
+  MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
+  if (!sContentParentIdMap) {
+    // Since Content IDs are generated lazily, ContentParent might attempt
+    // to release an ID that was never allocated to begin with.
+    return;
+  }
+
+  Maybe<uint32_t> mapping = sContentParentIdMap->GetAndRemove(aIPCContentProcessID);
+  if (!mapping) {
+    // Since Content IDs are generated lazily, ContentParent might attempt
+    // to release an ID that was never allocated to begin with.
+    return;
+  }
+
+  uint32_t index = mapping.ref() / kBitsPerElement;
+  MOZ_ASSERT(index < ArrayLength(sContentProcessIdBitmap));
+
+  uint64_t mask = 1ULL << (mapping.ref() % kBitsPerElement);
+  MOZ_ASSERT(sContentProcessIdBitmap[index] & mask);
+
+  sContentProcessIdBitmap[index] &= ~mask;
+}
+
+} // namespace a11y
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/accessible/windows/msaa/MsaaIdGenerator.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_MsaaIdGenerator_h
+#define mozilla_a11y_MsaaIdGenerator_h
+
+#include "mozilla/a11y/IDSet.h"
+
+#include "mozilla/dom/ipc/IdType.h"
+
+namespace mozilla {
+namespace a11y {
+
+class AccessibleWrap;
+
+/**
+ * This class is responsible for generating child IDs used by our MSAA
+ * implementation. Since e10s requires us to differentiate IDs based on the
+ * originating process of the accessible, a portion of the ID's bits are
+ * allocated to storing that information. The remaining bits represent the
+ * unique ID of the accessible, within that content process.
+ *
+ * The constants kNumContentProcessIDBits and kNumUniqueIDBits in the
+ * implementation are responsible for determining the proportion of bits that
+ * are allocated for each purpose.
+ */
+class MsaaIdGenerator
+{
+public:
+  constexpr MsaaIdGenerator();
+
+  uint32_t GetID();
+  void ReleaseID(AccessibleWrap* aAccWrap);
+  bool IsChromeID(uint32_t aID);
+  bool IsIDForThisContentProcess(uint32_t aID);
+  bool IsIDForContentProcess(uint32_t aID,
+                             dom::ContentParentId aIPCContentProcessId);
+  bool IsSameContentProcessFor(uint32_t aFirstID, uint32_t aSecondID);
+
+  uint32_t GetContentProcessIDFor(dom::ContentParentId aIPCContentProcessID);
+  void ReleaseContentProcessIDFor(dom::ContentParentId aIPCContentProcessID);
+
+private:
+  uint32_t ResolveContentProcessID();
+
+private:
+  IDSet     mIDSet;
+  uint32_t  mContentProcessID;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // mozilla_a11y_MsaaIdGenerator_h
--- a/accessible/windows/msaa/Platform.cpp
+++ b/accessible/windows/msaa/Platform.cpp
@@ -80,30 +80,16 @@ void
 a11y::ProxyDestroyed(ProxyAccessible* aProxy)
 {
   AccessibleWrap* wrapper =
     reinterpret_cast<AccessibleWrap*>(aProxy->GetWrapper());
   MOZ_ASSERT(wrapper);
   if (!wrapper)
     return;
 
-  auto doc =
-    static_cast<DocProxyAccessibleWrap*>(WrapperFor(aProxy->Document()));
-  MOZ_ASSERT(doc);
-  if (doc) {
-#ifdef _WIN64
-    uint32_t id = wrapper->GetExistingID();
-    if (id != AccessibleWrap::kNoID) {
-      doc->RemoveID(id);
-    }
-#else
-    doc->RemoveID(-reinterpret_cast<int32_t>(wrapper));
-#endif
-  }
-
   wrapper->Shutdown();
   aProxy->SetWrapper(0);
   wrapper->Release();
 }
 
 void
 a11y::ProxyEvent(ProxyAccessible* aTarget, uint32_t aEventType)
 {
--- a/accessible/windows/msaa/RootAccessibleWrap.cpp
+++ b/accessible/windows/msaa/RootAccessibleWrap.cpp
@@ -1,92 +1,35 @@
 /* -*- 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 "RootAccessibleWrap.h"
 
-#include "ChildIDThunk.h"
 #include "Compatibility.h"
-#include "mozilla/mscom/interceptor.h"
 #include "nsCoreUtils.h"
-#include "nsIXULRuntime.h"
 #include "nsWinUtils.h"
 
 using namespace mozilla::a11y;
-using namespace mozilla::mscom;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/destructor
 
 RootAccessibleWrap::
   RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
   RootAccessible(aDocument, aPresShell)
 {
 }
 
 RootAccessibleWrap::~RootAccessibleWrap()
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Accessible
-
-void
-RootAccessibleWrap::GetNativeInterface(void** aOutAccessible)
-{
-  MOZ_ASSERT(aOutAccessible);
-  if (!aOutAccessible) {
-    return;
-  }
-
-  if (mInterceptor &&
-      SUCCEEDED(mInterceptor->Resolve(IID_IAccessible, aOutAccessible))) {
-    return;
-  }
-
-  *aOutAccessible = nullptr;
-
-  RefPtr<IAccessible> rootAccessible;
-  RootAccessible::GetNativeInterface((void**)getter_AddRefs(rootAccessible));
-
-  if (!mozilla::BrowserTabsRemoteAutostart() || XRE_IsContentProcess()) {
-    // We only need to wrap this interface if our process is non-content e10s
-    rootAccessible.forget(aOutAccessible);
-    return;
-  }
-
-  // Otherwise, we need to wrap that IAccessible with an interceptor
-  RefPtr<IInterceptorSink> eventSink(MakeAndAddRef<ChildIDThunk>());
-
-  RefPtr<IAccessible> interceptor;
-  HRESULT hr = CreateInterceptor<IAccessible>(
-      STAUniquePtr<IAccessible>(rootAccessible.forget().take()), eventSink,
-      getter_AddRefs(interceptor));
-  if (FAILED(hr)) {
-    return;
-  }
-
-  RefPtr<IWeakReferenceSource> weakRefSrc;
-  hr = interceptor->QueryInterface(IID_IWeakReferenceSource,
-                                   (void**)getter_AddRefs(weakRefSrc));
-  if (FAILED(hr)) {
-    return;
-  }
-
-  hr = weakRefSrc->GetWeakReference(getter_AddRefs(mInterceptor));
-  if (FAILED(hr)) {
-    return;
-  }
-
-  interceptor.forget(aOutAccessible);
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // RootAccessible
 
 void
 RootAccessibleWrap::DocumentActivated(DocAccessible* aDocument)
 {
   if (Compatibility::IsDolphin() &&
       nsCoreUtils::IsTabDocument(aDocument->DocumentNode())) {
     uint32_t count = mChildDocuments.Length();
--- a/accessible/windows/msaa/RootAccessibleWrap.h
+++ b/accessible/windows/msaa/RootAccessibleWrap.h
@@ -4,36 +4,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_RootAccessibleWrap_h__
 #define mozilla_a11y_RootAccessibleWrap_h__
 
 #include "RootAccessible.h"
 
 namespace mozilla {
-namespace mscom {
-
-struct IWeakReference;
-
-} // namespace mscom
-
 namespace a11y {
 
 class RootAccessibleWrap : public RootAccessible
 {
 public:
   RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
   virtual ~RootAccessibleWrap();
 
-  // Accessible
-  virtual void GetNativeInterface(void** aOutAccessible) override;
-
   // RootAccessible
   virtual void DocumentActivated(DocAccessible* aDocument);
-
-private:
-  RefPtr<mscom::IWeakReference> mInterceptor;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -8,31 +8,32 @@ EXPORTS += [
     'IUnknownImpl.h',
 ]
 
 EXPORTS.mozilla.a11y += [
     'AccessibleWrap.h',
     'Compatibility.h',
     'HyperTextAccessibleWrap.h',
     'IDSet.h',
+    'MsaaIdGenerator.h',
 ]
 
 UNIFIED_SOURCES += [
     'AccessibleWrap.cpp',
     'ApplicationAccessibleWrap.cpp',
     'ARIAGridAccessibleWrap.cpp',
-    'ChildIDThunk.cpp',
     'Compatibility.cpp',
     'DocAccessibleWrap.cpp',
     'EnumVariant.cpp',
     'HTMLTableAccessibleWrap.cpp',
     'HTMLWin32ObjectAccessible.cpp',
     'HyperTextAccessibleWrap.cpp',
     'ImageAccessibleWrap.cpp',
     'IUnknownImpl.cpp',
+    'MsaaIdGenerator.cpp',
     'nsWinUtils.cpp',
     'Platform.cpp',
     'RootAccessibleWrap.cpp',
     'TextLeafAccessibleWrap.cpp',
 ]
 
 # This file cannot be built in unified mode because it includes ISimpleDOMNode_i.c.
 SOURCES += [
--- a/accessible/windows/sdn/moz.build
+++ b/accessible/windows/sdn/moz.build
@@ -14,9 +14,11 @@ LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
     '/accessible/html',
     '/accessible/windows/msaa',
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
--- a/accessible/windows/uia/moz.build
+++ b/accessible/windows/uia/moz.build
@@ -12,9 +12,11 @@ LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
     '/accessible/html',
     '/accessible/windows/msaa',
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
--- a/accessible/xul/moz.build
+++ b/accessible/xul/moz.build
@@ -42,12 +42,14 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
     LOCAL_INCLUDES += [
         '/accessible/mac',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wno-error=shadow']
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -954,21 +954,16 @@ pref("layout.accessiblecaret.enabled", t
 
 // Show the selection bars at the two ends of the selection highlight. Required
 // by the spec in bug 921965.
 pref("layout.accessiblecaret.bar.enabled", true);
 
 // Hide the caret in cursor mode after 3 seconds.
 pref("layout.accessiblecaret.timeout_ms", 3000);
 
-// APZ on real devices supports long tap events.
-#ifdef MOZ_WIDGET_GONK
-pref("layout.accessiblecaret.use_long_tap_injector", false);
-#endif
-
 // Hide carets and text selection dialog during scrolling.
 pref("layout.accessiblecaret.always_show_when_scrolling", false);
 
 // Enable sync and mozId with Firefox Accounts.
 pref("services.sync.fxaccounts.enabled", true);
 pref("identity.fxaccounts.enabled", true);
 
 pref("identity.fxaccounts.remote.oauth.uri", "https://oauth.accounts.firefox.com/v1");
@@ -1011,17 +1006,17 @@ pref("dom.mozSettings.allowForceReadOnly
 // the system app in dev mode.
 pref("dom.activities.developer_mode_only", "import-app");
 
 // mulet apparently loads firefox.js as well as b2g.js, so we have to explicitly
 // disable serviceworkers and push here to get them disabled in mulet.
 pref("dom.serviceWorkers.enabled", false);
 pref("dom.push.enabled", false);
 
-#if defined(RELEASE_BUILD)
+#if defined(RELEASE_OR_BETA)
 // Bug 1278848: Enable service worker notifications on release B2G once
 // they're ready.
 pref("dom.webnotifications.serviceworker.enabled", false);
 #else
 pref("dom.webnotifications.serviceworker.enabled", true);
 #endif
 
 // Retain at most 10 processes' layers buffers
--- a/b2g/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -36,16 +36,17 @@
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
 #ifdef MOZ_WIDGET_GONK
 # include <binder/ProcessState.h>
 #endif
 
+#include "mozilla/Sprintf.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
@@ -118,17 +119,17 @@ static int do_main(int argc, char* argv[
 
     rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
     if (NS_FAILED(rv)) {
       Output("application.ini path not recognized: '%s'", argv[2]);
       return 255;
     }
 
     char appEnv[MAXPATHLEN];
-    snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
+    SprintfLiteral(appEnv, "XUL_APP_FILE=%s", argv[2]);
     if (putenv(strdup(appEnv))) {
       Output("Couldn't set %s.\n", appEnv);
       return 255;
     }
     argv[2] = argv[0];
     argv += 2;
     argc -= 2;
   }
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -34,16 +34,17 @@
 #ifdef MOZ_SANDBOX
 #include "mozilla/sandboxing/SandboxInitialization.h"
 #endif
 #endif
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
+#include "mozilla/Sprintf.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
 #if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) \
   && !(defined(XP_LINUX) && defined(MOZ_SANDBOX))
 #define MOZ_BROWSER_CAN_BE_CONTENTPROC
 #include "../../ipc/contentproc/plugin-container.cpp"
 #endif
@@ -187,17 +188,17 @@ static int do_main(int argc, char* argv[
 
     rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
     if (NS_FAILED(rv)) {
       Output("application.ini path not recognized: '%s'", argv[2]);
       return 255;
     }
 
     char appEnv[MAXPATHLEN];
-    snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
+    SprintfLiteral(appEnv, "XUL_APP_FILE=%s", argv[2]);
     if (putenv(strdup(appEnv))) {
       Output("Couldn't set %s.\n", appEnv);
       return 255;
     }
     argv[2] = argv[0];
     argv += 2;
     argc -= 2;
   } else if (argc > 1 && IsArg(argv[1], "xpcshell")) {
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -117,17 +117,17 @@ pref("app.update.enabled", true);
 // app updates are enabled per the app.update.enabled preference and if the user
 // can apply updates.
 pref("app.update.auto", true);
 
 // If set to true, the Update Service will present no UI for any event.
 pref("app.update.silent", false);
 
 // If set to true, the hamburger button will show badges for update events.
-#ifndef RELEASE_BUILD
+#ifndef RELEASE_OR_BETA
 pref("app.update.badge", true);
 #else
 pref("app.update.badge", false);
 #endif
 // app.update.badgeWaitTime is in branding section
 
 // If set to true, the Update Service will apply updates in the background
 // when it finishes downloading them.
@@ -323,17 +323,17 @@ pref("browser.download.loglevel", "Error
 // feedback from their action.
 pref("browser.download.saveLinkAsFilenameTimeout", 4000);
 
 pref("browser.download.useDownloadDir", true);
 pref("browser.download.folderList", 1);
 pref("browser.download.manager.addToRecentDocs", true);
 pref("browser.download.manager.resumeOnWakeDelay", 10000);
 
-#ifdef RELEASE_BUILD
+#ifdef RELEASE_OR_BETA
 pref("browser.download.showPanelDropmarker", false);
 #else
 pref("browser.download.showPanelDropmarker", true);
 #endif
 
 // This allows disabling the animated notifications shown by
 // the Downloads Indicator when a download starts or completes.
 pref("browser.download.animateNotifications", true);
@@ -1003,17 +1003,17 @@ pref("security.sandbox.content.level", 1
 // to whitelist more system calls.
 //
 // So the purpose of this setting is to allow nightly users to disable the
 // sandbox while we fix their problems. This way, they won't have to wait for
 // another nightly release which disables seccomp-bpf again.
 //
 // This setting may not be required anymore once we decide to permanently
 // enable the content sandbox.
-pref("security.sandbox.content.level", 1);
+pref("security.sandbox.content.level", 2);
 #endif
 
 #if defined(XP_MACOSX) || defined(XP_WIN)
 #if defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
 // ID (a UUID when set by gecko) that is used to form the name of a
 // sandbox-writable temporary directory to be used by content processes
 // when a temporary writable file is required in a level 1 sandbox.
 pref("security.sandbox.content.tempDirSuffix", "");
@@ -1239,37 +1239,37 @@ pref("security.cert_pinning.enforcement_
 // Override the Gecko-default value of false for Firefox.
 pref("plain_text.wrap_long_lines", true);
 
 // If this turns true, Moz*Gesture events are not called stopPropagation()
 // before content.
 pref("dom.debug.propagate_gesture_events_through_content", false);
 
 // The request URL of the GeoLocation backend.
-#ifdef RELEASE_BUILD
+#ifdef RELEASE_OR_BETA
 pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%");
 #else
 pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
 #endif
 
 #ifdef XP_MACOSX
-#ifdef RELEASE_BUILD
+#ifdef RELEASE_OR_BETA
 pref("geo.provider.use_corelocation", false);
 #else
 pref("geo.provider.use_corelocation", true);
 #endif
 #endif
 
 #ifdef XP_WIN
 pref("geo.provider.ms-windows-location", false);
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #ifdef MOZ_GPSD
-#ifdef RELEASE_BUILD
+#ifdef RELEASE_OR_BETA
 pref("geo.provider.use_gpsd", false);
 #else
 pref("geo.provider.use_gpsd", true);
 #endif
 #endif
 #endif
 
 // Necko IPC security checks only needed for app isolation for cookies/cache/etc:
@@ -1423,17 +1423,17 @@ pref("privacy.trackingprotection.introUR
 #ifdef NIGHTLY_BUILD
 pref("privacy.userContext.enabled", true);
 pref("privacy.userContext.ui.enabled", true);
 #else
 pref("privacy.userContext.enabled", false);
 pref("privacy.userContext.ui.enabled", false);
 #endif
 
-#ifndef RELEASE_BUILD
+#ifndef RELEASE_OR_BETA
 // At the moment, autostart.2 is used, while autostart.1 is unused.
 // We leave it here set to false to reset users' defaults and allow
 // us to change everybody to true in the future, when desired.
 pref("browser.tabs.remote.autostart.1", false);
 pref("browser.tabs.remote.autostart.2", true);
 #endif
 
 // For the about:tabcrashed page
@@ -1442,17 +1442,17 @@ pref("browser.tabs.crashReporting.includ
 pref("browser.tabs.crashReporting.emailMe", false);
 pref("browser.tabs.crashReporting.email", "");
 
 // Enable e10s add-on interposition by default.
 pref("extensions.interposition.enabled", true);
 pref("extensions.interposition.prefetching", true);
 
 // Enable blocking of e10s for add-on users on beta/release.
-#ifdef RELEASE_BUILD
+#ifdef RELEASE_OR_BETA
 pref("extensions.e10sBlocksEnabling", true);
 #endif
 
 pref("browser.defaultbrowser.notificationbar", false);
 
 // How often to check for CPOW timeouts. CPOWs are only timed out by
 // the hang monitor.
 pref("dom.ipc.cpow.timeout", 500);
@@ -1525,17 +1525,17 @@ pref("print.use_simplify_page", true);
 
 // Space separated list of URLS that are allowed to send objects (instead of
 // only strings) through webchannels. This list is duplicated in mobile/android/app/mobile.js
 pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
 
 // Whether or not the browser should scan for unsubmitted
 // crash reports, and then show a notification for submitting
 // those reports.
-#ifdef RELEASE_BUILD
+#ifdef RELEASE_OR_BETA
 pref("browser.crashReports.unsubmittedCheck.enabled", false);
 #else
 pref("browser.crashReports.unsubmittedCheck.enabled", true);
 #endif
 
 // chancesUntilSuppress is how many times we'll show the unsubmitted
 // crash report notification across different days and shutdown
 // without a user choice before we suppress the notification for
--- a/browser/base/content/browser-devedition.js
+++ b/browser/base/content/browser-devedition.js
@@ -118,12 +118,12 @@ var DevEdition = {
     }
     this.styleSheet = null;
   }
 };
 
 // If the DevEdition theme is going to be applied in gBrowserInit.onLoad,
 // then preload it now.  This prevents a flash of unstyled content where the
 // normal theme is applied while the DevEdition stylesheet is loading.
-if (!AppConstants.RELEASE_BUILD &&
+if (!AppConstants.RELEASE_OR_BETA &&
     this != Services.appShell.hiddenDOMWindow && DevEdition.isThemeCurrentlyApplied) {
   DevEdition.createStyleSheet();
 }
--- a/browser/base/content/browser-fullScreenAndPointerLock.js
+++ b/browser/base/content/browser-fullScreenAndPointerLock.js
@@ -380,17 +380,20 @@ var FullScreen = {
   receiveMessage: function(aMessage) {
     let browser = aMessage.target;
     switch (aMessage.name) {
       case "DOMFullscreen:Request": {
         this._windowUtils.remoteFrameFullscreenChanged(browser);
         break;
       }
       case "DOMFullscreen:NewOrigin": {
-        PointerlockFsWarning.showFullScreen(aMessage.data.originNoSuffix);
+        // Don't show the warning if we've already exited fullscreen.
+        if (document.fullscreen) {
+          PointerlockFsWarning.showFullScreen(aMessage.data.originNoSuffix);
+        }
         break;
       }
       case "DOMFullscreen:Exit": {
         this._windowUtils.remoteFrameFullscreenReverted();
         break;
       }
       case "DOMFullscreen:Painted": {
         Services.obs.notifyObservers(window, "fullscreen-painted", "");
@@ -405,38 +408,42 @@ var FullScreen = {
     if (!document.fullscreenElement) {
       return;
     }
 
     // If we have a current pointerlock warning shown then hide it
     // before transition.
     PointerlockFsWarning.close();
 
+    // If it is a remote browser, send a message to ask the content
+    // to enter fullscreen state. We don't need to do so if it is an
+    // in-process browser, since all related document should have
+    // entered fullscreen state at this point.
+    // This should be done before the active tab check below to ensure
+    // that the content document handles the pending request. Doing so
+    // before the check is fine since we also check the activeness of
+    // the requesting document in content-side handling code.
+    if (this._isRemoteBrowser(aBrowser)) {
+      aBrowser.messageManager.sendAsyncMessage("DOMFullscreen:Entered");
+    }
+
     // If we've received a fullscreen notification, we have to ensure that the
     // element that's requesting fullscreen belongs to the browser that's currently
     // active. If not, we exit fullscreen since the "full-screen document" isn't
     // actually visible now.
     if (!aBrowser || gBrowser.selectedBrowser != aBrowser ||
         // The top-level window has lost focus since the request to enter
         // full-screen was made. Cancel full-screen.
         Services.focus.activeWindow != window) {
       // This function is called synchronously in fullscreen change, so
       // we have to avoid calling exitFullscreen synchronously here.
       setTimeout(() => document.exitFullscreen(), 0);
       return;
     }
 
-    // If it is a remote browser, send a message to ask the content
-    // to enter fullscreen state. We don't need to do so if it is an
-    // in-process browser, since all related document should have
-    // entered fullscreen state at this point.
-    if (this._isRemoteBrowser(aBrowser)) {
-      aBrowser.messageManager.sendAsyncMessage("DOMFullscreen:Entered");
-    }
-
     document.documentElement.setAttribute("inDOMFullscreen", true);
 
     if (gFindBarInitialized) {
       gFindBar.close(true);
     }
 
     // Exit DOM full-screen mode upon open, close, or change tab.
     gBrowser.tabContainer.addEventListener("TabOpen", this.exitDomFullScreen);
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -756,17 +756,17 @@ html|*#fullscreen-exit-button {
 .notification-anchor-icon:not([showing]) {
   display: none;
 }
 
 #invalid-form-popup > description {
   max-width: 280px;
 }
 
-.form-validation-anchor {
+.popup-anchor {
   /* should occupy space but not be visible */
   opacity: 0;
   visibility: hidden;
   pointer-events: none;
   -moz-stack-sizing: ignore;
 }
 
 #addon-progress-notification {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -12,16 +12,17 @@ Cu.import("resource://gre/modules/Contex
 Cu.import("resource://gre/modules/NotificationDB.jsm");
 
 // lazy module getters
 [
   ["AboutHome", "resource:///modules/AboutHome.jsm"],
   ["AddonWatcher", "resource://gre/modules/AddonWatcher.jsm"],
   ["AppConstants", "resource://gre/modules/AppConstants.jsm"],
   ["BrowserUITelemetry", "resource:///modules/BrowserUITelemetry.jsm"],
+  ["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
   ["BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"],
   ["CastingApps", "resource:///modules/CastingApps.jsm"],
   ["CharsetMenu", "resource://gre/modules/CharsetMenu.jsm"],
   ["Color", "resource://gre/modules/Color.jsm"],
   ["ContentSearch", "resource:///modules/ContentSearch.jsm"],
   ["Deprecated", "resource://gre/modules/Deprecated.jsm"],
   ["E10SUtils", "resource:///modules/E10SUtils.jsm"],
   ["FormValidationHandler", "resource:///modules/FormValidationHandler.jsm"],
@@ -704,17 +705,17 @@ function gKeywordURIFixup({ target: brow
   // decimal representations of IPs are normalized to a 'regular'
   // dot-separated IP address by network code, but that only happens for
   // numbers that don't overflow. Longer numbers do not get normalized,
   // but still work to access IP addresses. So for instance,
   // 1097347366913 (ff7f000001) gets resolved by using the final bytes,
   // making it the same as 7f000001, which is 127.0.0.1 aka localhost.
   // While 2130706433 would get normalized by network, 1097347366913
   // does not, and we have to deal with both cases here:
-  if (isIPv4Address(asciiHost) || /^\d+$/.test(asciiHost))
+  if (isIPv4Address(asciiHost) || /^(?:\d+|0x[a-f0-9]+)$/i.test(asciiHost))
     return;
 
   let onLookupComplete = (request, record, status) => {
     let browser = weakBrowser.get();
     if (!Components.isSuccessCode(status) || !browser)
       return;
 
     let currentURI = browser.currentURI;
@@ -3768,26 +3769,23 @@ const BrowserSearch = {
   },
 
   loadAddEngines: function BrowserSearch_loadAddEngines() {
     var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
     var where = newWindowPref == 3 ? "tab" : "window";
     openUILinkIn(this.searchEnginesURL, where);
   },
 
-  get _isExtendedTelemetryEnabled() {
-    return Services.prefs.getBoolPref("toolkit.telemetry.enabled");
-  },
-
   _getSearchEngineId: function (engine) {
     if (engine && engine.identifier) {
       return engine.identifier;
     }
 
-    if (!engine || (engine.name === undefined) || !this._isExtendedTelemetryEnabled)
+    if (!engine || (engine.name === undefined) ||
+        !Services.prefs.getBoolPref("toolkit.telemetry.enabled"))
       return "other";
 
     return "other-" + engine.name;
   },
 
   /**
    * Helper to record a search with Telemetry.
    *
@@ -3799,35 +3797,22 @@ const BrowserSearch = {
    *        (string) Where the search originated from. See the FHR
    *        SearchesProvider for allowed values.
    * @param selection [optional]
    *        ({index: The selected index, kind: "key" or "mouse"}) If
    *        the search was a suggested search, this indicates where the
    *        item was in the suggestion list and how the user selected it.
    */
   recordSearchInTelemetry: function (engine, source, selection) {
-    const SOURCES = [
-      "abouthome",
-      "contextmenu",
-      "newtab",
-      "searchbar",
-      "urlbar",
-    ];
-
     BrowserUITelemetry.countSearchEvent(source, null, selection);
-
-    if (SOURCES.indexOf(source) == -1) {
-      Cu.reportError("Unknown source for search: " + source);
-      return;
-    }
-
-    let countId = this._getSearchEngineId(engine) + "." + source;
-
-    let count = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS");
-    count.add(countId);
+    try {
+      BrowserUsageTelemetry.recordSearch(engine, source);
+    } catch (ex) {
+      Cu.reportError(ex);
+    }
   },
 
   recordOneoffSearchInTelemetry: function (engine, source, type, where) {
     let id = this._getSearchEngineId(engine) + "." + source;
     BrowserUITelemetry.countOneoffSearchEvent(id, type, where);
   }
 };
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -155,16 +155,22 @@
     <!-- for url bar autocomplete -->
     <panel type="autocomplete-richlistbox"
            id="PopupAutoCompleteRichResult"
            noautofocus="true"
            hidden="true"
            flip="none"
            level="parent"/>
 
+    <panel id="DateTimePickerPanel"
+           hidden="true"
+           noautofocus="true"
+           consumeoutsideclicks="false"
+           level="parent"/>
+
     <!-- for select dropdowns. The menupopup is what shows the list of options,
          and the popuponly menulist makes things like the menuactive attributes
          work correctly on the menupopup. ContentSelectDropdown expects the
          popuponly menulist to be its immediate parent. -->
     <menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
       <menupopup rolluponmousewheel="true"
                  activateontab="true" position="after_start"
 #ifdef XP_WIN
@@ -1057,17 +1063,18 @@
       <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
       <vbox id="appcontent" flex="1">
         <notificationbox id="high-priority-global-notificationbox" notificationside="top"/>
         <tabbrowser id="content"
                     flex="1" contenttooltip="aHTMLTooltip"
                     tabcontainer="tabbrowser-tabs"
                     contentcontextmenu="contentAreaContextMenu"
                     autocompletepopup="PopupAutoComplete"
-                    selectmenulist="ContentSelectDropdown"/>
+                    selectmenulist="ContentSelectDropdown"
+                    datetimepicker="DateTimePickerPanel"/>
       </vbox>
       <vbox id="browser-border-end" hidden="true" layer="true"/>
     </hbox>
 #include ../../components/customizableui/content/customizeMode.inc.xul
   </deck>
 
   <html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="true">
     <html:div class="pointerlockfswarning-domain-text">
--- a/browser/base/content/newtab/dragDataHelper.js
+++ b/browser/base/content/newtab/dragDataHelper.js
@@ -6,17 +6,17 @@
 
 var gDragDataHelper = {
   get mimeType() {
     return "text/x-moz-url";
   },
 
   getLinkFromDragEvent: function DragDataHelper_getLinkFromDragEvent(aEvent) {
     let dt = aEvent.dataTransfer;
-    if (!dt || !dt.types.contains(this.mimeType)) {
+    if (!dt || !dt.types.includes(this.mimeType)) {
       return null;
     }
 
     let data = dt.getData(this.mimeType) || "";
     let [url, title] = data.split(/[\r\n]+/);
     return {url: url, title: title};
   }
 };
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -925,12 +925,18 @@ var UserContextIdNotifier = {
 UserContextIdNotifier.init();
 
 ExtensionContent.init(this);
 addEventListener("unload", () => {
   ExtensionContent.uninit(this);
   RefreshBlocker.uninit();
 });
 
+addMessageListener("AllowScriptsToClose", () => {
+  content.QueryInterface(Ci.nsIInterfaceRequestor)
+         .getInterface(Ci.nsIDOMWindowUtils)
+         .allowScriptsToClose();
+});
+
 addEventListener("MozAfterPaint", function onFirstPaint() {
   removeEventListener("MozAfterPaint", onFirstPaint);
   sendAsyncMessage("Browser:FirstPaint");
 });
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -20,17 +20,17 @@
                   flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown"
                   onselect="if (event.target.localName == 'tabpanels') this.parentNode.updateCurrentBrowser();">
         <xul:tabpanels flex="1" class="plain" selectedIndex="0" anonid="panelcontainer">
           <xul:notificationbox flex="1" notificationside="top">
             <xul:hbox flex="1" class="browserSidebarContainer">
               <xul:vbox flex="1" class="browserContainer">
                 <xul:stack flex="1" class="browserStack" anonid="browserStack">
                   <xul:browser anonid="initialBrowser" type="content-primary" message="true" messagemanagergroup="browsers"
-                               xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup,selectmenulist"/>
+                               xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup,selectmenulist,datetimepicker"/>
                 </xul:stack>
               </xul:vbox>
             </xul:hbox>
           </xul:notificationbox>
         </xul:tabpanels>
       </xul:tabbox>
       <children/>
     </content>
@@ -134,29 +134,29 @@
           for (var i = 0; i < this.tabs.length; i++) {
             if (!this.tabs[i].pinned)
               break;
           }
           return i;
         ]]></getter>
       </property>
 
-      <property name="formValidationAnchor" readonly="true">
+      <property name="popupAnchor" readonly="true">
         <getter><![CDATA[
-        if (this.mCurrentTab._formValidationAnchor) {
-          return this.mCurrentTab._formValidationAnchor;
+        if (this.mCurrentTab._popupAnchor) {
+          return this.mCurrentTab._popupAnchor;
         }
         let stack = this.mCurrentBrowser.parentNode;
-        // Create an anchor for the form validation popup
+        // Create an anchor for the popup
         const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-        let formValidationAnchor = document.createElementNS(NS_XUL, "hbox");
-        formValidationAnchor.className = "form-validation-anchor";
-        formValidationAnchor.hidden = true;
-        stack.appendChild(formValidationAnchor);
-        return this.mCurrentTab._formValidationAnchor = formValidationAnchor;
+        let popupAnchor = document.createElementNS(NS_XUL, "hbox");
+        popupAnchor.className = "popup-anchor";
+        popupAnchor.hidden = true;
+        stack.appendChild(popupAnchor);
+        return this.mCurrentTab._popupAnchor = popupAnchor;
         ]]></getter>
       </property>
 
       <method name="isFindBarInitialized">
         <parameter name="aTab"/>
         <body><![CDATA[
           return (aTab || this.selectedTab)._findBar != undefined;
         ]]></body>
@@ -1881,16 +1881,20 @@
 
             if (!aParams.isPreloadBrowser && this.hasAttribute("autocompletepopup")) {
               b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
             }
 
             if (this.hasAttribute("selectmenulist"))
               b.setAttribute("selectmenulist", this.getAttribute("selectmenulist"));
 
+            if (this.hasAttribute("datetimepicker")) {
+              b.setAttribute("datetimepicker", this.getAttribute("datetimepicker"));
+            }
+
             b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
 
             if (aParams.relatedBrowser) {
               b.relatedBrowser = aParams.relatedBrowser;
             }
 
             // Create the browserStack container
             var stack = document.createElementNS(NS_XUL, "stack");
@@ -4964,28 +4968,21 @@
         ]]>
       </handler>
       <handler event="oop-browser-crashed">
         <![CDATA[
           if (!event.isTrusted)
             return;
 
           let browser = event.originalTarget;
-          let title = browser.contentTitle;
-          let uri = browser.currentURI;
           let icon = browser.mIconURL;
-
           let tab = this.getTabForBrowser(browser);
 
           if (this.selectedBrowser == browser) {
-            this.updateBrowserRemotenessByURL(browser, "about:tabcrashed");
-            browser.setAttribute("crashedPageTitle", title);
-            browser.docShell.displayLoadError(Cr.NS_ERROR_CONTENT_CRASHED, uri, null);
-            browser.removeAttribute("crashedPageTitle");
-            tab.setAttribute("crashed", true);
+            TabCrashHandler.onSelectedBrowserCrash(browser);
           } else {
             this.updateBrowserRemoteness(browser, false);
             SessionStore.reviveCrashedTab(tab);
           }
 
           tab.removeAttribute("soundplaying");
           this.setIcon(tab, icon, browser.contentPrincipal);
         ]]>
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -253,27 +253,25 @@ skip-if = buildapp == 'mulet'
 [browser_bug676619.js]
 skip-if = buildapp == 'mulet' || os == "mac" # mac: Intermittent failures, bug 925225
 [browser_bug678392.js]
 skip-if = os == "mac" # Bug 1102331 - does focus things on the content window which break in e10s mode (still causes orange on Mac 10.10)
 [browser_bug710878.js]
 [browser_bug719271.js]
 [browser_bug724239.js]
 [browser_bug734076.js]
-skip-if = (os == 'linux' && e10s) # bug 1277750
 [browser_bug735471.js]
 [browser_bug749738.js]
 [browser_bug763468_perwindowpb.js]
 [browser_bug767836_perwindowpb.js]
 [browser_bug817947.js]
 [browser_bug822367.js]
 tags = mcb
 [browser_bug832435.js]
 [browser_bug839103.js]
-[browser_bug880101.js]
 [browser_bug882977.js]
 [browser_bug902156.js]
 tags = mcb
 [browser_bug906190.js]
 tags = mcb
 skip-if = buildapp == "mulet" # Bug 1093642 - test manipulates content and relies on content focus
 [browser_mixedContentFromOnunload.js]
 tags = mcb
--- a/browser/base/content/test/general/browser_aboutHome.js
+++ b/browser/base/content/test/general/browser_aboutHome.js
@@ -161,30 +161,38 @@ add_task(function* () {
          args.expectedVersion,
          "cached-version is correct");
       ok(snippetsMap.has("snippets-last-update"), "last-update still exists");
     }, { expectedVersion: AboutHomeUtils.snippetsVersion });
 });
 
 add_task(function* () {
   info("Check if the 'Know Your Rights' default snippet is shown when " +
-    "'browser.rights.override' pref is set");
+    "'browser.rights.override' pref is set and that its link works");
 
   Services.prefs.setBoolPref("browser.rights.override", false);
 
   ok(AboutHomeUtils.showKnowYourRights, "AboutHomeUtils.showKnowYourRights should be TRUE");
 
   yield withSnippetsMap(null, function* () {
     let doc = content.document;
     let snippetsElt = doc.getElementById("snippets");
     ok(snippetsElt, "Found snippets element");
-    is(snippetsElt.getElementsByTagName("a")[0].href, "about:rights",
-      "Snippet link is present.");
+    let linkEl = snippetsElt.querySelector("a");
+    is(linkEl.href, "about:rights", "Snippet link is present.");
+  }, null, function* () {
+    let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, "about:rights");
+    yield BrowserTestUtils.synthesizeMouseAtCenter("a[href='about:rights']", {
+      button: 0
+    }, gBrowser.selectedBrowser);
+    yield loadPromise;
+    is(gBrowser.currentURI.spec, "about:rights", "about:rights should have opened.");
   });
 
+
   Services.prefs.clearUserPref("browser.rights.override");
 });
 
 add_task(function* () {
   info("Check if the 'Know Your Rights' default snippet is NOT shown when " +
     "'browser.rights.override' pref is NOT set");
 
   Services.prefs.setBoolPref("browser.rights.override", true);
@@ -559,19 +567,25 @@ add_task(function* () {
 });
 
 /**
  * Cleans up snippets and ensures that by default we don't try to check for
  * remote snippets since that may cause network bustage or slowness.
  *
  * @param aSetupFn
  *        The setup function to be run.
+ * @param testFn
+ *        the content task to run
+ * @param testArgs (optional)
+ *        the parameters to pass to the content task
+ * @param parentFn (optional)
+ *        the function to run in the parent after the content task has completed.
  * @return {Promise} resolved when the snippets are ready.  Gets the snippets map.
  */
-function* withSnippetsMap(setupFn, testFn, testArgs = null) {
+function* withSnippetsMap(setupFn, testFn, testArgs = null, parentFn = null) {
   let setupFnSource;
   if (setupFn) {
     setupFnSource = setupFn.toSource();
   }
 
   yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (browser) {
     let promiseAfterLocationChange = () => {
       return ContentTask.spawn(browser, {
@@ -634,16 +648,19 @@ function* withSnippetsMap(setupFn, testF
 
     // Set the URL to 'about:home' here to allow capturing the 'AboutHomeLoadSnippets'
     // event.
     browser.loadURI("about:home");
     // Wait for LocationChange.
     yield promise;
 
     yield ContentTask.spawn(browser, testArgs, testFn);
+    if (parentFn) {
+      yield parentFn();
+    }
   });
 }
 
 function promiseContentSearchChange(browser, newEngineName) {
   return ContentTask.spawn(browser, { newEngineName }, function* (args) {
     return new Promise(resolve => {
       content.addEventListener("ContentSearchService", function listener(aEvent) {
         if (aEvent.detail.type == "CurrentState" &&
--- a/browser/base/content/test/general/browser_bug734076.js
+++ b/browser/base/content/test/general/browser_bug734076.js
@@ -33,16 +33,18 @@ add_task(function* ()
     {
       name: "view image",
       url: "http://mochi.test:8888/",
       element: "img",
       go: function () {
         return ContentTask.spawn(gBrowser.selectedBrowser, { writeDomainURL: writeDomainURL }, function* (arg) {
           let doc = content.document;
           let img = doc.createElement("img");
+          img.height = 100;
+          img.width = 100;
           img.setAttribute("src", arg.writeDomainURL);
           doc.body.insertBefore(img, doc.body.firstChild);
 
           return "context-viewimage";
         });
       },
       verify: function () {
         return ContentTask.spawn(gBrowser.selectedBrowser, null, function* (arg) {
@@ -89,16 +91,18 @@ add_task(function* ()
 
     info("Run subtest " + test.name);
     let commandToRun = yield test.go();
 
     let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
     yield BrowserTestUtils.synthesizeMouse(test.element, 3, 3,
           { type: "contextmenu", button: 2 }, gBrowser.selectedBrowser);
     yield popupShownPromise;
+    info("onImage: " + gContextMenu.onImage);
+    info("target: " + gContextMenu.target.tagName);
 
     let loadedAfterCommandPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
     document.getElementById(commandToRun).click();
     yield loadedAfterCommandPromise;
 
     yield test.verify();
 
     let popupHiddenPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popuphidden");
deleted file mode 100644
--- a/browser/base/content/test/general/browser_bug880101.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const URL = "http://example.com/browser/browser/base/content/test/general/dummy_page.html";
-
-function test() {
-  let win;
-
-  let listener = {
-    onLocationChange: (webProgress, request, uri, flags) => {
-      ok(webProgress.isTopLevel, "Received onLocationChange from top frame");
-      is(uri.spec, URL, "Received onLocationChange for correct URL");
-      finish();
-    }
-  };
-
-  waitForExplicitFinish();
-
-  // Remove the listener and window when we're done.
-  registerCleanupFunction(() => {
-    win.gBrowser.removeProgressListener(listener);
-    win.close();
-  });
-
-  // Wait for the newly opened window.
-  whenNewWindowOpened(w => win = w);
-
-  // Open a link in a new window.
-  openLinkIn(URL, "window", {});
-
-  // On the next tick, but before the window has finished loading, access the
-  // window's gBrowser property to force the tabbrowser constructor early.
-  (function tryAddProgressListener() {
-    executeSoon(() => {
-      try {
-        win.gBrowser.addProgressListener(listener);
-      } catch (e) {
-        // win.gBrowser wasn't ready, yet. Try again in a tick.
-        tryAddProgressListener();
-      }
-    });
-  })();
-}
-
-function whenNewWindowOpened(cb) {
-  Services.obs.addObserver(function obs(win) {
-    Services.obs.removeObserver(obs, "domwindowopened");
-    cb(win);
-  }, "domwindowopened", false);
-}
--- a/browser/base/content/test/general/browser_clipboard_pastefile.js
+++ b/browser/base/content/test/general/browser_clipboard_pastefile.js
@@ -39,17 +39,17 @@ add_task(function*() {
   searchbar.focus();
 
   yield new Promise((resolve, reject) => {
     searchbar.addEventListener("paste", function copyEvent(event) {
       searchbar.removeEventListener("paste", copyEvent, true);
 
       let dt = event.clipboardData;
       is(dt.types.length, 3, "number of types");
-      ok(dt.types.contains("text/plain"), "text/plain exists in types");
+      ok(dt.types.includes("text/plain"), "text/plain exists in types");
       ok(dt.mozTypesAt(0).contains("text/plain"), "text/plain exists in mozTypesAt");
       is(dt.getData("text/plain"), "Alternate", "text/plain returned in getData");
       is(dt.mozGetDataAt("text/plain", 0), "Alternate", "text/plain returned in mozGetDataAt");
 
       resolve();
     }, true);
 
     EventUtils.synthesizeKey("v", { accelKey: true });
--- a/browser/base/content/test/general/browser_parsable_css.js
+++ b/browser/base/content/test/general/browser_parsable_css.js
@@ -42,22 +42,16 @@ let allowedImageReferences = [
   {file: "chrome://devtools/skin/images/dock-bottom-maximize@2x.png",
    from: "chrome://devtools/skin/toolbox.css",
    isFromDevTools: true},
 
   // Bug 1302708
   {file: "chrome/devtools/modules/devtools/client/themes/images/filter.svg",
    from: "chrome/devtools/modules/devtools/client/themes/common.css",
    isFromDevTools: true},
-
-  // Bug 1302890
-  {file: "chrome://global/skin/icons/warning-32.png",
-   from: "chrome://devtools/skin/tooltips.css",
-   platforms: ["linux", "win"],
-   isFromDevTools: true},
 ];
 
 var moduleLocation = gTestPath.replace(/\/[^\/]*$/i, "/parsingTestHelpers.jsm");
 var {generateURIsFromDirTree} = Cu.import(moduleLocation, {});
 
 // Add suffix to stylesheets' URI so that we always load them here and
 // have them parsed. Add a random number so that even if we run this
 // test multiple times, it would be unlikely to affect each other.
--- a/browser/base/content/test/general/browser_trackingUI_4.js
+++ b/browser/base/content/test/general/browser_trackingUI_4.js
@@ -25,17 +25,17 @@ registerCleanupFunction(function() {
 });
 
 function waitForSecurityChange(numChanges = 1) {
   return new Promise(resolve => {
     let n = 0;
     let listener = {
       onSecurityChange: function() {
         n = n + 1;
-        info ("Recieved onSecurityChange event " + n + " of " + numChanges);
+        info ("Received onSecurityChange event " + n + " of " + numChanges);
         if (n >= numChanges) {
           tabbrowser.removeProgressListener(listener);
           resolve();
         }
       }
     };
     tabbrowser.addProgressListener(listener);
   });
--- a/browser/base/content/test/plugins/browser_private_clicktoplay.js
+++ b/browser/base/content/test/plugins/browser_private_clicktoplay.js
@@ -6,233 +6,214 @@ var gTestBrowser = null;
 var gNextTest = null;
 var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 var gPrivateWindow = null;
 var gPrivateBrowser = null;
 
-function pageLoad(aEvent) {
-  // The plugin events are async dispatched and can come after the load event
-  // This just allows the events to fire before we then go on to test the states
-  executeSoon(gNextTest);
-  gNextTest = null;
-}
-
-function prepareTest(nextTest, url, browser) {
-  gNextTest = nextTest;
-  if (!browser)
-    browser = gTestBrowser;
-
-  ContentTask.spawn(browser, url, function(url) {
-    content.location = url;
-  });
-}
-
 function finishTest() {
   clearAllPluginPermissions();
-  gTestBrowser.removeEventListener("load", pageLoad, true);
   gBrowser.removeCurrentTab();
   if (gPrivateWindow) {
     gPrivateWindow.close();
   }
   window.focus();
-  finish();
 }
 
-function createPrivateWindow(nextTest, url) {
-  gPrivateWindow = OpenBrowserWindow({private: true});
+let createPrivateWindow = Task.async(function* createPrivateWindow(url) {
+  gPrivateWindow = yield BrowserTestUtils.openNewBrowserWindow({private: true});
   ok(!!gPrivateWindow, "should have created a private window.");
-  whenDelayedStartupFinished(gPrivateWindow, function() {
-    gPrivateBrowser = gPrivateWindow.getBrowser().selectedBrowser;
-    gPrivateBrowser.addEventListener("load", pageLoad, true);
-    gNextTest = function() {
-      prepareTest(nextTest, url, gPrivateBrowser);
-    };
-  });
-}
+  gPrivateBrowser = gPrivateWindow.getBrowser().selectedBrowser;
 
-function whenDelayedStartupFinished(aWindow, aCallback) {
-  Services.obs.addObserver(function observer(aSubject, aTopic) {
-    if (aWindow == aSubject) {
-      Services.obs.removeObserver(observer, aTopic);
-      executeSoon(aCallback);
-    }
-  }, "browser-delayed-startup-finished", false);
-}
+  BrowserTestUtils.loadURI(gPrivateBrowser, url);
+  yield BrowserTestUtils.browserLoaded(gPrivateBrowser);
+});
 
-function test() {
-  waitForExplicitFinish();
+add_task(function* test() {
   registerCleanupFunction(function() {
     clearAllPluginPermissions();
     getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_ENABLED;
     getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_ENABLED;
   });
 
   let newTab = gBrowser.addTab();
   gBrowser.selectedTab = newTab;
   gTestBrowser = gBrowser.selectedBrowser;
-  gTestBrowser.addEventListener("load", pageLoad, true);
+  let promise = BrowserTestUtils.browserLoaded(gTestBrowser);
 
   Services.prefs.setBoolPref("plugins.click_to_play", true);
   getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
   getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
-  gNextTest = test1a;
-}
+  yield promise;
+});
 
-function test1a() {
-  createPrivateWindow(test1b, gHttpTestRoot + "plugin_test.html");
-}
+add_task(function* test1a() {
+  yield createPrivateWindow(gHttpTestRoot + "plugin_test.html");
+});
 
-function test1b() {
+add_task(function* test1b() {
   let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser);
   ok(popupNotification, "Test 1b, Should have a click-to-play notification");
 
-  let plugin = gPrivateBrowser.contentDocument.getElementById("test");
-  let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(!objLoadingContent.activated, "Test 1b, Plugin should not be activated");
+  yield ContentTask.spawn(gPrivateBrowser, null, function() {
+    let plugin = content.document.getElementById("test");
+    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    ok(!objLoadingContent.activated, "Test 1b, Plugin should not be activated");
+  });
 
   // Check the button status
   let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel,
                                                    "Shown");
   popupNotification.reshow();
-  promiseShown.then(() => {
-    let button1 = gPrivateWindow.PopupNotifications.panel.firstChild._primaryButton;
-    let button2 = gPrivateWindow.PopupNotifications.panel.firstChild._secondaryButton;
-    is(button1.getAttribute("action"), "_singleActivateNow", "Test 1b, Blocked plugin in private window should have a activate now button");
-    ok(button2.hidden, "Test 1b, Blocked plugin in a private window should not have a secondary button")
+
+  yield promiseShown;
+  let button1 = gPrivateWindow.PopupNotifications.panel.firstChild._primaryButton;
+  let button2 = gPrivateWindow.PopupNotifications.panel.firstChild._secondaryButton;
+  is(button1.getAttribute("action"), "_singleActivateNow", "Test 1b, Blocked plugin in private window should have a activate now button");
+  ok(button2.hidden, "Test 1b, Blocked plugin in a private window should not have a secondary button")
 
-    gPrivateWindow.close();
-    prepareTest(test2a, gHttpTestRoot + "plugin_test.html");
-  });
-}
+  gPrivateWindow.close();
+  BrowserTestUtils.loadURI(gTestBrowser, gHttpTestRoot + "plugin_test.html");
+  yield BrowserTestUtils.browserLoaded(gTestBrowser);
+});
 
-function test2a() {
+add_task(function* test2a() {
   // enable test plugin on this site
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 2a, Should have a click-to-play notification");
 
-  let plugin = gTestBrowser.contentDocument.getElementById("test");
-  let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(!objLoadingContent.activated, "Test 2a, Plugin should not be activated");
+  yield ContentTask.spawn(gTestBrowser, null, function() {
+    let plugin = content.document.getElementById("test");
+    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    ok(!objLoadingContent.activated, "Test 2a, Plugin should not be activated");
+  });
 
   // Simulate clicking the "Allow Now" button.
   let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
                                                    "Shown");
   popupNotification.reshow();
-  promiseShown.then(() => {
-    PopupNotifications.panel.firstChild._secondaryButton.click();
+  yield promiseShown;
+
+  PopupNotifications.panel.firstChild._secondaryButton.click();
 
+  yield ContentTask.spawn(gTestBrowser, null, function* () {
+    let plugin = content.document.getElementById("test");
+    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     let condition = () => objLoadingContent.activated;
-    waitForCondition(condition, test2b, "Test 2a, Waited too long for plugin to activate");
+    yield ContentTaskUtils.waitForCondition(condition, "Test 2a, Waited too long for plugin to activate");
   });
-}
+});
 
-function test2b() {
-  createPrivateWindow(test2c, gHttpTestRoot + "plugin_test.html");
-}
+add_task(function* test2b() {
+  yield createPrivateWindow(gHttpTestRoot + "plugin_test.html");
+});
 
-function test2c() {
-  let promise = TestUtils.topicObserved("PopupNotifications-updateNotShowing");
-  promise.then(() => {
-    let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser);
-    ok(popupNotification, "Test 2c, Should have a click-to-play notification");
+add_task(function* test2c() {
+  yield TestUtils.topicObserved("PopupNotifications-updateNotShowing");
 
-    let plugin = gPrivateBrowser.contentDocument.getElementById("test");
+  let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser);
+  ok(popupNotification, "Test 2c, Should have a click-to-play notification");
+
+  yield ContentTask.spawn(gPrivateBrowser, null, function() {
+    let plugin = content.document.getElementById("test");
     let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     ok(objLoadingContent.activated, "Test 2c, Plugin should be activated");
-
-    // Check the button status
-    let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel,
-                                                     "Shown");
-    popupNotification.reshow();
-    promiseShown.then(() => {
-      let buttonContainer = gPrivateWindow.PopupNotifications.panel.firstChild._buttonContainer;
-      ok(buttonContainer.hidden, "Test 2c, Activated plugin in a private window should not have visible buttons");
+  });
 
-      clearAllPluginPermissions();
-      gPrivateWindow.close();
-      prepareTest(test3a, gHttpTestRoot + "plugin_test.html");
-    });
-  });
-}
+  // Check the button status
+  let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel,
+                                                   "Shown");
+  popupNotification.reshow();
+  yield promiseShown;
+  let buttonContainer = gPrivateWindow.PopupNotifications.panel.firstChild._buttonContainer;
+  ok(buttonContainer.hidden, "Test 2c, Activated plugin in a private window should not have visible buttons");
 
-function test3a() {
+  clearAllPluginPermissions();
+  gPrivateWindow.close();
+
+  BrowserTestUtils.loadURI(gTestBrowser, gHttpTestRoot + "plugin_test.html");
+  yield BrowserTestUtils.browserLoaded(gTestBrowser);
+});
+
+add_task(function* test3a() {
   // enable test plugin on this site
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 3a, Should have a click-to-play notification");
 
-  let plugin = gTestBrowser.contentDocument.getElementById("test");
-  let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-  ok(!objLoadingContent.activated, "Test 3a, Plugin should not be activated");
+  yield ContentTask.spawn(gTestBrowser, null, function() {
+    let plugin = content.document.getElementById("test");
+    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    ok(!objLoadingContent.activated, "Test 3a, Plugin should not be activated");
+  });
 
   // Simulate clicking the "Allow Always" button.
   let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
                                                    "Shown");
   popupNotification.reshow();
-  promiseShown.then(() => {
-    PopupNotifications.panel.firstChild._secondaryButton.click();
+  yield promiseShown;
+  PopupNotifications.panel.firstChild._secondaryButton.click();
 
+  yield ContentTask.spawn(gTestBrowser, null, function* () {
+    let plugin = content.document.getElementById("test");
+    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     let condition = () => objLoadingContent.activated;
-    waitForCondition(condition, test3b, "Test 3a, Waited too long for plugin to activate");
+    yield ContentTaskUtils.waitForCondition(condition, "Test 3a, Waited too long for plugin to activate");
   });
-}
+});
 
-function test3b() {
-  createPrivateWindow(test3c, gHttpTestRoot + "plugin_test.html");
-}
+add_task(function* test3b() {
+  yield createPrivateWindow(gHttpTestRoot + "plugin_test.html");
+});
 
-function test3c() {
-  let promise = TestUtils.topicObserved("PopupNotifications-updateNotShowing");
-  promise.then(() => {
-    let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser);
-    ok(popupNotification, "Test 3c, Should have a click-to-play notification");
+add_task(function* test3c() {
+  yield TestUtils.topicObserved("PopupNotifications-updateNotShowing");
+  let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser);
+  ok(popupNotification, "Test 3c, Should have a click-to-play notification");
 
-    // Check the button status
-    let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel,
-                                                     "Shown");
-    popupNotification.reshow();
-    promiseShown.then(() => {
-      let buttonContainer = gPrivateWindow.PopupNotifications.panel.firstChild._buttonContainer;
-      ok(buttonContainer.hidden, "Test 3c, Activated plugin in a private window should not have visible buttons");
+  // Check the button status
+  let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel,
+                                                   "Shown");
+  popupNotification.reshow();
+  yield promiseShown;
+  let buttonContainer = gPrivateWindow.PopupNotifications.panel.firstChild._buttonContainer;
+  ok(buttonContainer.hidden, "Test 3c, Activated plugin in a private window should not have visible buttons");
 
-      prepareTest(test3d, gHttpTestRoot + "plugin_two_types.html", gPrivateBrowser);
-    });
-  });
-}
+  BrowserTestUtils.loadURI(gPrivateBrowser, gHttpTestRoot + "plugin_two_types.html");
+  yield BrowserTestUtils.browserLoaded(gPrivateBrowser);
+});
 
-function test3d() {
+add_task(function* test3d() {
   let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser);
   ok(popupNotification, "Test 3d, Should have a click-to-play notification");
 
   // Check the list item status
   let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel,
                                                    "Shown");
   popupNotification.reshow();
-  promiseShown.then(() => {
-    let doc = gPrivateWindow.document;
-    for (let item of gPrivateWindow.PopupNotifications.panel.firstChild.childNodes) {
-      let allowalways = doc.getAnonymousElementByAttribute(item, "anonid", "allowalways");
-      ok(allowalways, "Test 3d, should have list item for allow always");
-      let allownow = doc.getAnonymousElementByAttribute(item, "anonid", "allownow");
-      ok(allownow, "Test 3d, should have list item for allow now");
-      let block = doc.getAnonymousElementByAttribute(item, "anonid", "block");
-      ok(block, "Test 3d, should have list item for block");
+  yield promiseShown;
+  let doc = gPrivateWindow.document;
+  for (let item of gPrivateWindow.PopupNotifications.panel.firstChild.childNodes) {
+    let allowalways = doc.getAnonymousElementByAttribute(item, "anonid", "allowalways");
+    ok(allowalways, "Test 3d, should have list item for allow always");
+    let allownow = doc.getAnonymousElementByAttribute(item, "anonid", "allownow");
+    ok(allownow, "Test 3d, should have list item for allow now");
+    let block = doc.getAnonymousElementByAttribute(item, "anonid", "block");
+    ok(block, "Test 3d, should have list item for block");
 
-      if (item.action.pluginName === "Test") {
-        is(item.value, "allowalways", "Test 3d, Plugin should bet set to 'allow always'");
-        ok(!allowalways.hidden, "Test 3d, Plugin set to 'always allow' should have a visible 'always allow' action.");
-        ok(allownow.hidden, "Test 3d, Plugin set to 'always allow' should have an invisible 'allow now' action.");
-        ok(block.hidden, "Test 3d, Plugin set to 'always allow' should have an invisible 'block' action.");
-      } else if (item.action.pluginName === "Second Test") {
-        is(item.value, "block", "Test 3d, Second plugin should bet set to 'block'");
-        ok(allowalways.hidden, "Test 3d, Plugin set to 'block' should have a visible 'always allow' action.");
-        ok(!allownow.hidden, "Test 3d, Plugin set to 'block' should have a visible 'allow now' action.");
-        ok(!block.hidden, "Test 3d, Plugin set to 'block' should have a visible 'block' action.");
-      } else {
-        ok(false, "Test 3d, Unexpected plugin '"+item.action.pluginName+"'");
-      }
+    if (item.action.pluginName === "Test") {
+      is(item.value, "allowalways", "Test 3d, Plugin should bet set to 'allow always'");
+      ok(!allowalways.hidden, "Test 3d, Plugin set to 'always allow' should have a visible 'always allow' action.");
+      ok(allownow.hidden, "Test 3d, Plugin set to 'always allow' should have an invisible 'allow now' action.");
+      ok(block.hidden, "Test 3d, Plugin set to 'always allow' should have an invisible 'block' action.");
+    } else if (item.action.pluginName === "Second Test") {
+      is(item.value, "block", "Test 3d, Second plugin should bet set to 'block'");
+      ok(allowalways.hidden, "Test 3d, Plugin set to 'block' should have a visible 'always allow' action.");
+      ok(!allownow.hidden, "Test 3d, Plugin set to 'block' should have a visible 'allow now' action.");
+      ok(!block.hidden, "Test 3d, Plugin set to 'block' should have a visible 'block' action.");
+    } else {
+      ok(false, "Test 3d, Unexpected plugin '"+item.action.pluginName+"'");
     }
+  }
 
-    finishTest();
-  });
-}
+  finishTest();
+});
--- a/browser/base/content/test/tabs/browser.ini
+++ b/browser/base/content/test/tabs/browser.ini
@@ -1,2 +1,4 @@
 [browser_tabSpinnerProbe.js]
 skip-if = !e10s # Tab spinner is e10s only.
+[browser_tabSwitchPrintPreview.js]
+skip-if = os == 'mac'
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabs/browser_tabSwitchPrintPreview.js
@@ -0,0 +1,23 @@
+const kURL1 = "data:text/html,Should I stay or should I go?";
+const kURL2 = "data:text/html,I shouldn't be here!";
+
+/**
+ * Verify that if we open a new tab and try to make it the selected tab while
+ * print preview is up, that doesn't happen.
+ */
+add_task(function* () {
+  yield BrowserTestUtils.withNewTab(kURL1, function* (browser) {
+    let tab = gBrowser.addTab(kURL2);
+    document.getElementById("cmd_printPreview").doCommand();
+    gBrowser.selectedTab = tab;
+    yield BrowserTestUtils.waitForCondition(() => gInPrintPreviewMode, "should be in print preview mode");
+    isnot(gBrowser.selectedTab, tab, "Selected tab should not be the tab we added");
+    is(gBrowser.selectedTab, PrintPreviewListener._printPreviewTab, "Selected tab should be the print preview tab");
+    gBrowser.selectedTab = tab;
+    isnot(gBrowser.selectedTab, tab, "Selected tab should still not be the tab we added");
+    is(gBrowser.selectedTab, PrintPreviewListener._printPreviewTab, "Selected tab should still be the print preview tab");
+    PrintUtils.exitPrintPreview();
+    yield BrowserTestUtils.waitForCondition(() => !gInPrintPreviewMode, "should be in print preview mode");
+    yield BrowserTestUtils.removeTab(tab);
+  });
+});
--- a/browser/base/content/test/urlbar/browser_urlbarSearchSingleWordNotification.js
+++ b/browser/base/content/test/urlbar/browser_urlbarSearchSingleWordNotification.js
@@ -98,16 +98,39 @@ add_task(function* test_navigate_large_n
   yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   yield* runURLBarSearchTest({
     valueToOpen: "123456789012345",
     expectSearch: true,
     expectNotification: false
   });
   gBrowser.removeTab(tab);
 });
+
+add_task(function* test_navigate_small_hex_number() {
+  let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
+  yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  yield* runURLBarSearchTest({
+    valueToOpen: "0x1f00ffff",
+    expectSearch: true,
+    expectNotification: false
+  });
+  gBrowser.removeTab(tab);
+});
+
+add_task(function* test_navigate_large_hex_number() {
+  let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
+  yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  yield* runURLBarSearchTest({
+    valueToOpen: "0x7f0000017f000001",
+    expectSearch: true,
+    expectNotification: false
+  });
+  gBrowser.removeTab(tab);
+});
+
 function get_test_function_for_localhost_with_hostname(hostName, isPrivate) {
   return function* test_navigate_single_host() {
     const pref = "browser.fixup.domainwhitelist.localhost";
     let win;
     if (isPrivate) {
       win = yield promiseOpenAndLoadWindow({private: true}, true);
       let deferredOpenFocus = Promise.defer();
       waitForFocus(deferredOpenFocus.resolve, win);
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -651,20 +651,20 @@ file, You can obtain one at http://mozil
           this.inputField.removeAttribute("tooltiptext");
         ]]></body>
       </method>
 
       <method name="onDragOver">
         <parameter name="aEvent"/>
         <body>
           var types = aEvent.dataTransfer.types;
-          if (types.contains("application/x-moz-file") ||
-              types.contains("text/x-moz-url") ||
-              types.contains("text/uri-list") ||
-              types.contains("text/unicode"))
+          if (types.includes("application/x-moz-file") ||
+              types.includes("text/x-moz-url") ||
+              types.includes("text/uri-list") ||
+              types.includes("text/unicode"))
             aEvent.preventDefault();
         </body>
       </method>
 
       <method name="onDrop">
         <parameter name="aEvent"/>
         <body><![CDATA[
           let links = browserDragAndDrop.dropLinks(aEvent);
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -60,16 +60,17 @@ static RedirEntry kRedirMap[] = {
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml",
     nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
     nsIAboutModule::ALLOW_SCRIPT },
   { "rights",
     "chrome://global/content/aboutRights.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
+    nsIAboutModule::MAKE_LINKABLE |
     nsIAboutModule::ALLOW_SCRIPT },
   { "robots", "chrome://browser/content/aboutRobots.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::ALLOW_SCRIPT },
   { "searchreset", "chrome://browser/content/search/searchReset.xhtml",
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml",
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -144,22 +144,22 @@ CustomizeMode.prototype = {
     }
     if (this._customizing) {
       this.exit();
     } else {
       this.enter();
     }
   },
 
-  swatchForTheme: function(aDocument) {
-   let lwthemeButton = aDocument.getElementById("customization-lwtheme-button");
-   let lwthemeIcon = aDocument.getAnonymousElementByAttribute(lwthemeButton,
-          "class", "button-icon");
-   lwthemeIcon.style.backgroundImage = LightweightThemeManager.currentTheme ?
-     "url(" + LightweightThemeManager.currentTheme.iconURL + ")" : "";
+  _updateLWThemeButtonIcon: function() {
+    let lwthemeButton = this.document.getElementById("customization-lwtheme-button");
+    let lwthemeIcon = this.document.getAnonymousElementByAttribute(lwthemeButton,
+                        "class", "button-icon");
+    lwthemeIcon.style.backgroundImage = LightweightThemeManager.currentTheme ?
+      "url(" + LightweightThemeManager.currentTheme.iconURL + ")" : "";
   },
 
   setTab: function(aTab) {
     if (gTab == aTab) {
       return;
     }
 
     if (gTab) {
@@ -351,17 +351,17 @@ CustomizeMode.prototype = {
       window.setTimeout(() => {
         // Force layout reflow to ensure the animation runs,
         // and make it async so it doesn't affect the timing.
         this.visiblePalette.clientTop;
         this.visiblePalette.setAttribute("showing", "true");
       }, 0);
       this._updateEmptyPaletteNotice();
 
-      this.swatchForTheme(document);
+      this._updateLWThemeButtonIcon();
       this.maybeShowTip(panelHolder);
 
       this._handler.isEnteringCustomizeMode = false;
       panelContents.removeAttribute("customize-transitioning");
 
       CustomizableUI.dispatchToolboxEvent("customizationready", {}, window);
       this._enableOutlinesTimeout = window.setTimeout(() => {
         this.document.getElementById("nav-bar").setAttribute("showoutline", "true");
@@ -1170,17 +1170,17 @@ CustomizeMode.prototype = {
     btn.disabled = true;
     return Task.spawn(function*() {
       this._removePanelCustomizationPlaceholders();
       yield this.depopulatePalette();
       yield this._unwrapToolbarItems();
 
       CustomizableUI.reset();
 
-      this.swatchForTheme(this.document);
+      this._updateLWThemeButtonIcon();
 
       yield this._wrapToolbarItems();
       this.populatePalette();
 
       this.persistCurrentSets(true);
 
       this._updateResetButton();
       this._updateUndoResetButton();
@@ -1198,17 +1198,17 @@ CustomizeMode.prototype = {
 
     return Task.spawn(function*() {
       this._removePanelCustomizationPlaceholders();
       yield this.depopulatePalette();
       yield this._unwrapToolbarItems();
 
       CustomizableUI.undoReset();
 
-      this.swatchForTheme(this.document);
+      this._updateLWThemeButtonIcon();
 
       yield this._wrapToolbarItems();
       this.populatePalette();
 
       this.persistCurrentSets(true);
 
       this._updateResetButton();
       this._updateUndoResetButton();
@@ -1340,27 +1340,33 @@ CustomizeMode.prototype = {
     let getMoreURL = Services.urlFormatter.formatURLPref("lightweightThemes.getMoreURL");
     this.window.openUILinkIn(getMoreURL, "tab");
   },
 
   onLWThemesMenuShowing: function(aEvent) {
     const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
     const RECENT_LWT_COUNT = 5;
 
-    this.resetLWThemesMenu(aEvent.target);
+    this._clearLWThemesMenu(aEvent.target);
 
     function previewTheme(aEvent) {
       LightweightThemeManager.previewTheme(aEvent.target.theme.id != DEFAULT_THEME_ID ?
                                            aEvent.target.theme : null);
     }
 
     function resetPreview() {
       LightweightThemeManager.resetPreview();
     }
 
+    let onThemeSelected = panel => {
+      this._updateLWThemeButtonIcon();
+      this._onUIChange();
+      panel.hidePopup();
+    };
+
     AddonManager.getAddonByID(DEFAULT_THEME_ID, function(aDefaultTheme) {
       let doc = this.window.document;
 
       function buildToolbarButton(aTheme) {
         let tbb = doc.createElement("toolbarbutton");
         tbb.theme = aTheme;
         tbb.setAttribute("label", aTheme.name);
         if (aDefaultTheme == aTheme) {
@@ -1398,70 +1404,66 @@ CustomizeMode.prototype = {
         themes.push(lwt);
       }
 
       let footer = doc.getElementById("customization-lwtheme-menu-footer");
       let panel = footer.parentNode;
       let themesInMyThemesSection = 0;
       let recommendedLabel = doc.getElementById("customization-lwtheme-menu-recommended");
       for (let theme of themes) {
-        let tbb = buildToolbarButton(theme);
-        tbb.addEventListener("command", function() {
-          if ("userDisabled" in this.theme)
-            this.theme.userDisabled = false;
+        let button = buildToolbarButton(theme);
+        button.addEventListener("command", () => {
+          if ("userDisabled" in button.theme)
+            button.theme.userDisabled = false;
           else
-            LightweightThemeManager.currentTheme = this.theme;
-          this.parentNode.hidePopup();
+            LightweightThemeManager.currentTheme = button.theme;
+          onThemeSelected(panel);
         });
-        panel.insertBefore(tbb, recommendedLabel);
+        panel.insertBefore(button, recommendedLabel);
         themesInMyThemesSection++;
       }
 
       let lwthemePrefs = Services.prefs.getBranch("lightweightThemes.");
       let recommendedThemes = lwthemePrefs.getComplexValue("recommendedThemes",
                                                            Ci.nsISupportsString).data;
       recommendedThemes = JSON.parse(recommendedThemes);
       let sb = Services.strings.createBundle("chrome://browser/locale/lightweightThemes.properties");
       for (let theme of recommendedThemes) {
         theme.name = sb.GetStringFromName("lightweightThemes." + theme.id + ".name");
         theme.description = sb.GetStringFromName("lightweightThemes." + theme.id + ".description");
-        let tbb = buildToolbarButton(theme);
-        tbb.addEventListener("command", function() {
-          LightweightThemeManager.setLocalTheme(this.theme);
-          recommendedThemes = recommendedThemes.filter((aTheme) => { return aTheme.id != this.theme.id; });
+        let button = buildToolbarButton(theme);
+        button.addEventListener("command", () => {
+          LightweightThemeManager.setLocalTheme(button.theme);
+          recommendedThemes = recommendedThemes.filter((aTheme) => { return aTheme.id != button.theme.id; });
           let string = Cc["@mozilla.org/supports-string;1"]
                          .createInstance(Ci.nsISupportsString);
           string.data = JSON.stringify(recommendedThemes);
           lwthemePrefs.setComplexValue("recommendedThemes",
                                        Ci.nsISupportsString, string);
-          this.parentNode.hidePopup();
+          onThemeSelected(panel);
         });
-        panel.insertBefore(tbb, footer);
+        panel.insertBefore(button, footer);
       }
       let hideRecommendedLabel = (footer.previousSibling == recommendedLabel);
       recommendedLabel.hidden = hideRecommendedLabel;
     }.bind(this));
   },
 
-  resetLWThemesMenu: function(target) {
-    let doc = target.ownerDocument;
-    let footer = doc.getElementById("customization-lwtheme-menu-footer");
-    let recommendedLabel = doc.getElementById("customization-lwtheme-menu-recommended");
-    this.swatchForTheme(doc);
+  _clearLWThemesMenu: function(panel) {
+    let footer = this.document.getElementById("customization-lwtheme-menu-footer");
+    let recommendedLabel = this.document.getElementById("customization-lwtheme-menu-recommended");
     for (let element of [footer, recommendedLabel]) {
       while (element.previousSibling &&
              element.previousSibling.localName == "toolbarbutton") {
         element.previousSibling.remove();
       }
     }
-    target.removeAttribute("height");
 
-    if (LightweightThemeManager.currentTheme) {
-      this._onUIChange();
-    }
+    // Workaround for bug 1059934
+    panel.removeAttribute("height");
   },
 
   _onUIChange: function() {
     this._changed = true;
     if (!this.resetting) {
       this._updateResetButton();
       this._updateUndoResetButton();
       this._updateEmptyPaletteNotice();
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -1386,19 +1386,19 @@ DownloadsPlacesView.prototype = {
     dt.setData("text/uri-list", url);
     dt.setData("text/plain", url);
     dt.effectAllowed = "copyMove";
     dt.addElement(selectedItem);
   },
 
   onDragOver(aEvent) {
     let types = aEvent.dataTransfer.types;
-    if (types.contains("text/uri-list") ||
-        types.contains("text/x-moz-url") ||
-        types.contains("text/plain")) {
+    if (types.includes("text/uri-list") ||
+        types.includes("text/x-moz-url") ||
+        types.includes("text/plain")) {
       aEvent.preventDefault();
     }
   },
 
   onDrop(aEvent) {
     let dt = aEvent.dataTransfer;
     // If dragged item is from our source, do not try to
     // redownload already downloaded file.
--- a/browser/components/downloads/test/browser/browser.ini
+++ b/browser/components/downloads/test/browser/browser.ini
@@ -8,8 +8,9 @@ skip-if = os == "linux" # Bug 949434
 [browser_overflow_anchor.js]
 skip-if = os == "linux" # Bug 952422
 [browser_confirm_unblock_download.js]
 [browser_iframe_gone_mid_download.js]
 [browser_indicatorDrop.js]
 [browser_libraryDrop.js]
 [browser_downloads_panel_block.js]
 [browser_downloads_panel_footer.js]
+[browser_downloads_panel_height.js]
--- a/browser/components/downloads/test/browser/browser_downloads_panel_footer.js
+++ b/browser/components/downloads/test/browser/browser_downloads_panel_footer.js
@@ -6,16 +6,17 @@ function *task_openDownloadsSubPanel() {
 
   let downloadsDropmarker = document.getElementById("downloadsFooterDropmarker");
   EventUtils.synthesizeMouseAtCenter(downloadsDropmarker, {}, window);
 
   yield popupShownPromise;
 }
 
 add_task(function* test_openDownloadsFolder() {
+  yield SpecialPowers.pushPrefEnv({"set": [["browser.download.showPanelDropmarker", true]]});
   yield task_openPanel();
 
   yield task_openDownloadsSubPanel();
 
   yield new Promise(resolve => {
     sinon.stub(DownloadsCommon, "showDirectory", file => {
       resolve(Downloads.getPreferredDownloadsDirectory().then(downloadsPath => {
         is(file.path, downloadsPath, "Check the download folder path.");
new file mode 100644
--- /dev/null
+++ b/browser/components/downloads/test/browser/browser_downloads_panel_height.js
@@ -0,0 +1,29 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * This test exists because we use a <panelmultiview> element and it handles
+ * some of the height changes for us. We need to verify that the height is
+ * updated correctly if downloads are removed while the panel is hidden.
+ */
+add_task(function* test_height_reduced_after_removal() {
+  yield task_addDownloads([
+    { state: nsIDM.DOWNLOAD_FINISHED },
+  ]);
+
+  yield task_openPanel();
+  let panel = document.getElementById("downloadsPanel");
+  let heightBeforeRemoval = panel.getBoundingClientRect().height;
+
+  // We want to close the panel before we remove the download from the list.
+  DownloadsPanel.hidePanel();
+  yield task_resetState();
+
+  yield task_openPanel();
+  let heightAfterRemoval = panel.getBoundingClientRect().height;
+  Assert.greater(heightBeforeRemoval, heightAfterRemoval);
+
+  yield task_resetState();
+});
--- a/browser/components/extensions/.eslintrc
+++ b/browser/components/extensions/.eslintrc
@@ -1,19 +1,22 @@
 {
   "extends": "../../../toolkit/components/extensions/.eslintrc",
 
   "globals": {
     "AllWindowEvents": true,
+    "browserActionFor": true,
     "currentWindow": true,
     "EventEmitter": true,
     "getCookieStoreIdForTab": true,
     "IconDetails": true,
     "makeWidgetId": true,
     "pageActionFor": true,
     "PanelPopup": true,
     "TabContext": true,
     "ViewPopup": true,
     "WindowEventManager": true,
     "WindowListManager": true,
     "WindowManager": true,
   },
 }
+
+
--- a/browser/components/extensions/ext-browserAction.js
+++ b/browser/components/extensions/ext-browserAction.js
@@ -9,18 +9,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
                                   "resource://gre/modules/Timer.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "colorUtils", () => {
   return require("devtools/shared/css/color").colorUtils;
 });
 
 Cu.import("resource://devtools/shared/event-emitter.js");
+Cu.import("resource://gre/modules/ExtensionUtils.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
 
-Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 var {
   EventManager,
   IconDetails,
 } = ExtensionUtils;
 
 const POPUP_PRELOAD_TIMEOUT_MS = 200;
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@@ -103,20 +104,19 @@ BrowserAction.prototype = {
       onViewShowing: event => {
         let document = event.target.ownerDocument;
         let tabbrowser = document.defaultView.gBrowser;
 
         let tab = tabbrowser.selectedTab;
         let popupURL = this.getProperty(tab, "popup");
         this.tabManager.addActiveTabPermission(tab);
 
-        // If the widget has a popup URL defined, we open a popup, but do not
-        // dispatch a click event to the extension.
-        // If it has no popup URL defined, we dispatch a click event, but do not
-        // open a popup.
+        // Popups are shown only if a popup URL is defined; otherwise
+        // a "click" event is dispatched. This is done for compatibility with the
+        // Google Chrome onClicked extension API.
         if (popupURL) {
           try {
             let popup = this.getPopup(document.defaultView, popupURL);
             event.detail.addBlocker(popup.attach(event.target));
           } catch (e) {
             Cu.reportError(e);
             event.preventDefault();
           }
@@ -130,16 +130,52 @@ BrowserAction.prototype = {
     });
 
     this.tabContext.on("tab-select", // eslint-disable-line mozilla/balanced-listeners
                        (evt, tab) => { this.updateWindow(tab.ownerGlobal); });
 
     this.widget = widget;
   },
 
+  /**
+   * Triggers this browser action for the given window, with the same effects as
+   * if it were clicked by a user.
+   *
+   * This has no effect if the browser action is disabled for, or not
+   * present in, the given window.
+   */
+  triggerAction: Task.async(function* (window) {
+    let popup = ViewPopup.for(this.extension, window);
+    if (popup) {
+      popup.closePopup();
+      return;
+    }
+
+    let widget = this.widget.forWindow(window);
+    let tab = window.gBrowser.selectedTab;
+
+    if (!widget || !this.getProperty(tab, "enabled")) {
+      return;
+    }
+
+    // Popups are shown only if a popup URL is defined; otherwise
+    // a "click" event is dispatched. This is done for compatibility with the
+    // Google Chrome onClicked extension API.
+    if (this.getProperty(tab, "popup")) {
+      if (this.widget.areaType == CustomizableUI.TYPE_MENU_PANEL) {
+        yield window.PanelUI.show();
+      }
+
+      let event = new window.CustomEvent("command", {bubbles: true, cancelable: true});
+      widget.node.dispatchEvent(event);
+    } else {
+      this.emit("click");
+    }
+  }),
+
   handleEvent(event) {
     let button = event.target;
     let window = button.ownerDocument.defaultView;
 
     switch (event.type) {
       case "mousedown":
         if (event.button == 0) {
           // Begin pre-loading the browser for the popup, so it's more likely to
--- a/browser/components/extensions/ext-commands.js
+++ b/browser/components/extensions/ext-commands.js
@@ -123,16 +123,19 @@ CommandList.prototype = {
 
     /* eslint-disable mozilla/balanced-listeners */
     // We remove all references to the key elements when the extension is shutdown,
     // therefore the listeners for these elements will be garbage collected.
     keyElement.addEventListener("command", (event) => {
       if (name == "_execute_page_action") {
         let win = event.target.ownerDocument.defaultView;
         pageActionFor(this.extension).triggerAction(win);
+      } else if (name == "_execute_browser_action") {
+        let win = event.target.ownerDocument.defaultView;
+        browserActionFor(this.extension).triggerAction(win);
       } else {
         TabManager.for(this.extension)
                   .addActiveTabPermission(TabManager.activeTab);
         this.emit("command", name);
       }
     });
     /* eslint-enable mozilla/balanced-listeners */
 
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -27,16 +27,17 @@ Cu.import("resource://gre/modules/AppCon
 const POPUP_LOAD_TIMEOUT_MS = 200;
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 // Minimum time between two resizes.
 const RESIZE_TIMEOUT = 100;
 
 var {
+  DefaultWeakMap,
   EventManager,
 } = ExtensionUtils;
 
 // This file provides some useful code for the |tabs| and |windows|
 // modules. All of the code is installed on |global|, which is a scope
 // shared among the different ext-*.js scripts.
 
 global.makeWidgetId = id => {
@@ -120,16 +121,22 @@ class BasePopup {
     let arrowContent = doc.getAnonymousElementByAttribute(this.panel, "class", "panel-arrowcontent");
     this.borderColor = doc.defaultView.getComputedStyle(arrowContent).borderTopColor;
 
     this.browser = null;
     this.browserLoaded = new Promise((resolve, reject) => {
       this.browserLoadedDeferred = {resolve, reject};
     });
     this.browserReady = this.createBrowser(viewNode, popupURL);
+
+    BasePopup.instances.get(this.window).set(extension, this);
+  }
+
+  static for(extension, window) {
+    return BasePopup.instances.get(window).get(extension);
   }
 
   destroy() {
     this.destroyed = true;
     this.browserLoadedDeferred.reject(new Error("Popup destroyed"));
     return this.browserReady.then(() => {
       this.destroyBrowser(this.browser);
       this.browser.remove();
@@ -137,16 +144,18 @@ class BasePopup {
       this.viewNode.removeEventListener(this.DESTROY_EVENT, this);
       this.viewNode.style.maxHeight = "";
 
       if (this.panel) {
         this.panel.style.removeProperty("--arrowpanel-background");
         this.panel.style.removeProperty("--panel-arrow-image-vertical");
       }
 
+      BasePopup.instances.get(this.window).delete(this.extension);
+
       this.browser = null;
       this.viewNode = null;
     });
   }
 
   destroyBrowser(browser) {
     browser.removeEventListener("DOMWindowCreated", this, true);
     browser.removeEventListener("load", this, true);
@@ -417,23 +426,31 @@ class BasePopup {
 
     let event = new this.window.CustomEvent("WebExtPopupResized");
     this.browser.dispatchEvent(event);
 
     this._resolveContentReady();
   }
 }
 
+/**
+ * A map of active popups for a given browser window.
+ *
+ * WeakMap[window -> WeakMap[Extension -> BasePopup]]
+ */
+BasePopup.instances = new DefaultWeakMap(() => new WeakMap());
+
 global.PanelPopup = class PanelPopup extends BasePopup {
   constructor(extension, imageNode, popupURL, browserStyle) {
     let document = imageNode.ownerDocument;
 
     let panel = document.createElement("panel");
     panel.setAttribute("id", makeWidgetId(extension.id) + "-panel");
     panel.setAttribute("class", "browser-extension-panel");
+    panel.setAttribute("tabspecific", "true");
     panel.setAttribute("type", "arrow");
     panel.setAttribute("role", "group");
 
     document.getElementById("mainPopupSet").appendChild(panel);
 
     super(extension, panel, popupURL, browserStyle);
 
     this.ignoreResizes = false;
--- a/browser/components/extensions/ext-windows.js
+++ b/browser/components/extensions/ext-windows.js
@@ -8,18 +8,23 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
                                   "resource://gre/modules/AppConstants.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 var {
   EventManager,
+  promiseObserved,
 } = ExtensionUtils;
 
+function onXULFrameLoaderCreated({target}) {
+  target.messageManager.sendAsyncMessage("AllowScriptsToClose", {});
+}
+
 extensions.registerSchemaAPI("windows", "addon_parent", context => {
   let {extension} = context;
   return {
     windows: {
       onCreated:
       new WindowEventManager(context, "windows.onCreated", "domwindowopened", (fire, window) => {
         fire(WindowManager.convert(extension, window));
       }).api(),
@@ -89,16 +94,20 @@ extensions.registerSchemaAPI("windows", 
 
         let args = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
 
         if (createData.tabId !== null) {
           if (createData.url !== null) {
             return Promise.reject({message: "`tabId` may not be used in conjunction with `url`"});
           }
 
+          if (createData.allowScriptsToClose) {
+            return Promise.reject({message: "`tabId` may not be used in conjunction with `allowScriptsToClose`"});
+          }
+
           let tab = TabManager.getTab(createData.tabId, context);
 
           // Private browsing tabs can only be moved to private browsing
           // windows.
           let incognito = PrivateBrowsingUtils.isBrowserPrivate(tab.linkedBrowser);
           if (createData.incognito !== null && createData.incognito != incognito) {
             return Promise.reject({message: "`incognito` property must match the incognito state of tab"});
           }
@@ -131,48 +140,52 @@ extensions.registerSchemaAPI("windows", 
         if (createData.incognito !== null) {
           if (createData.incognito) {
             features.push("private");
           } else {
             features.push("non-private");
           }
         }
 
+        let {allowScriptsToClose, url} = createData;
+        if (allowScriptsToClose === null) {
+          allowScriptsToClose = typeof url === "string" && url.startsWith("moz-extension://");
+        }
+
         let window = Services.ww.openWindow(null, "chrome://browser/content/browser.xul", "_blank",
                                             features.join(","), args);
 
         WindowManager.updateGeometry(window, createData);
 
         // TODO: focused, type
 
         return new Promise(resolve => {
           window.addEventListener("load", function listener() {
             window.removeEventListener("load", listener);
 
             if (createData.state == "maximized" || createData.state == "normal" ||
                 (createData.state == "fullscreen" && AppConstants.platform != "macosx")) {
               window.document.documentElement.setAttribute("sizemode", createData.state);
             } else if (createData.state !== null) {
-              // window.minimize() has no useful effect until the window has
-              // been shown.
-
-              let obs = doc => {
-                if (doc === window.document) {
-                  Services.obs.removeObserver(obs, "document-shown");
-                  WindowManager.setState(window, createData.state);
-                  resolve();
-                }
-              };
-              Services.obs.addObserver(obs, "document-shown", false);
-              return;
+              // window.minimize() has no effect until the window has been shown.
+              return promiseObserved("document-shown", doc => doc == window.document).then(() => {
+                WindowManager.setState(window, createData.state);
+                resolve();
+              });
             }
-
             resolve();
           });
         }).then(() => {
+          if (allowScriptsToClose) {
+            for (let {linkedBrowser} of window.gBrowser.tabs) {
+              onXULFrameLoaderCreated({target: linkedBrowser});
+              linkedBrowser.addEventListener( // eslint-disable-line mozilla/balanced-listeners
+                                             "XULFrameLoaderCreated", onXULFrameLoaderCreated);
+            }
+          }
           return WindowManager.convert(extension, window);
         });
       },
 
       update: function(windowId, updateInfo) {
         if (updateInfo.state !== null && updateInfo.state != "normal") {
           if (updateInfo.left !== null || updateInfo.top !== null ||
               updateInfo.width !== null || updateInfo.height !== null) {
--- a/browser/components/extensions/schemas/windows.json
+++ b/browser/components/extensions/schemas/windows.json
@@ -268,20 +268,20 @@
           {
             "type": "object",
             "name": "createData",
             "properties": {
               "url": {
                 "description": "A URL or array of URLs to open as tabs in the window. Fully-qualified URLs must include a scheme (i.e. 'http://www.google.com', not 'www.google.com'). Relative URLs will be relative to the current page within the extension. Defaults to the New Tab Page.",
                 "optional": true,
                 "choices": [
-                  { "type": "string" },
+                  { "type": "string", "format": "relativeUrl" },
                   {
                     "type": "array",
-                    "items": { "type": "string" }
+                    "items": { "type": "string", "format": "relativeUrl" }
                   }
                 ]
               },
               "tabId": {
                 "type": "integer",
                 "minimum": 0,
                 "optional": true,
                 "description": "The id of the tab for which you want to adopt to the new window."
@@ -323,16 +323,21 @@
                 "$ref": "CreateType",
                 "optional": true,
                 "description": "Specifies what type of browser window to create. The 'panel' and 'detached_panel' types create a popup unless the '--enable-panels' flag is set."
               },
               "state": {
                 "$ref": "WindowState",
                 "optional": true,
                 "description": "The initial state of the window. The 'minimized', 'maximized' and 'fullscreen' states cannot be combined with 'left', 'top', 'width' or 'height'."
+              },
+              "allowScriptsToClose": {
+                "type": "boolean",
+                "optional": true,
+                "description": "Allow scripts to close the window."
               }
             },
             "optional": true
           },
           {
             "type": "function",
             "name": "callback",
             "optional": true,
--- a/browser/components/extensions/test/browser/browser.ini
+++ b/browser/components/extensions/test/browser/browser.ini
@@ -22,16 +22,17 @@ tags = webextensions
 
 [browser_ext_browserAction_context.js]
 [browser_ext_browserAction_disabled.js]
 [browser_ext_browserAction_pageAction_icon.js]
 [browser_ext_browserAction_pageAction_icon_permissions.js]
 [browser_ext_browserAction_popup.js]
 [browser_ext_browserAction_popup_resize.js]
 [browser_ext_browserAction_simple.js]
+[browser_ext_commands_execute_browser_action.js]
 [browser_ext_commands_execute_page_action.js]
 [browser_ext_commands_getAll.js]
 [browser_ext_commands_onCommand.js]
 [browser_ext_contentscript_connect.js]
 [browser_ext_contextMenus.js]
 [browser_ext_contextMenus_checkboxes.js]
 [browser_ext_contextMenus_icons.js]
 [browser_ext_contextMenus_radioGroups.js]
@@ -87,13 +88,14 @@ tags = webextensions
 [browser_ext_topwindowid.js]
 [browser_ext_webNavigation_frameId0.js]
 [browser_ext_webNavigation_getFrames.js]
 [browser_ext_webNavigation_urlbar_transitions.js]
 [browser_ext_windows.js]
 [browser_ext_windows_create.js]
 tags = fullscreen
 [browser_ext_windows_create_tabId.js]
+[browser_ext_windows_create_url.js]
 [browser_ext_windows_events.js]
 [browser_ext_windows_size.js]
 skip-if = os == 'mac' # Fails when windows are randomly opened in fullscreen mode
 [browser_ext_windows_update.js]
 tags = fullscreen
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
@@ -1,12 +1,19 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
+function getBrowserAction(extension) {
+  const {GlobalManager, Management: {global: {browserActionFor}}} = Cu.import("resource://gre/modules/Extension.jsm", {});
+
+  let ext = GlobalManager.extensionMap.get(extension.id);
+  return browserActionFor(ext);
+}
+
 function* testInArea(area) {
   let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "background": {
         "page": "data/background.html",
       },
@@ -20,17 +27,17 @@ function* testInArea(area) {
       "popup-a.html": scriptPage("popup-a.js"),
       "popup-a.js": function() {
         window.onload = () => {
           let color = window.getComputedStyle(document.body).color;
           browser.test.assertEq("rgb(34, 36, 38)", color);
           browser.runtime.sendMessage("from-popup-a");
         };
         browser.runtime.onMessage.addListener(msg => {
-          if (msg == "close-popup") {
+          if (msg == "close-popup-using-window.close") {
             window.close();
           }
         });
       },
 
       "data/popup-b.html": scriptPage("popup-b.js"),
       "data/popup-b.js": function() {
         window.onload = () => {
@@ -47,96 +54,112 @@ function* testInArea(area) {
       },
 
       "data/background.html": scriptPage("background.js"),
 
       "data/background.js": function() {
         let sendClick;
         let tests = [
           () => {
-            browser.test.log("Open popup a");
+            browser.test.log(`Click browser action, expect popup "a".`);
+            sendClick({expectEvent: false, expectPopup: "a"});
+          },
+          () => {
+            browser.test.log(`Click browser action again, expect popup "a".`);
             sendClick({expectEvent: false, expectPopup: "a"});
           },
           () => {
-            browser.test.log("Open popup a again");
-            sendClick({expectEvent: false, expectPopup: "a"});
+            browser.test.log(`Call triggerAction, expect popup "a" again. Leave popup open.`);
+            sendClick({expectEvent: false, expectPopup: "a", closePopup: false}, "trigger-action");
           },
           () => {
-            browser.test.log("Open popup c");
+            browser.test.log(`Call triggerAction again. Expect remaining popup closed.`);
+            sendClick({expectEvent: false, expectPopup: null}, "trigger-action");
+            browser.test.sendMessage("next-test", {waitUntilClosed: true});
+          },
+          () => {
+            browser.test.log(`Call triggerAction again. Expect popup "a" again.`);
+            sendClick({expectEvent: false, expectPopup: "a"}, "trigger-action");
+          },
+          () => {
+            browser.test.log(`Set popup to "c" and click browser action. Expect popup "c".`);
             browser.browserAction.setPopup({popup: "popup-c.html"});
             sendClick({expectEvent: false, expectPopup: "c", closePopup: false});
           },
           () => {
-            browser.test.log("Open popup b");
+            browser.test.log(`Set popup to "b" and click browser action. Expect popup "b".`);
             browser.browserAction.setPopup({popup: "popup-b.html"});
             sendClick({expectEvent: false, expectPopup: "b"});
           },
           () => {
-            browser.test.log("Open popup b again");
+            browser.test.log(`Click browser action again, expect popup "b".`);
             sendClick({expectEvent: false, expectPopup: "b"});
           },
           () => {
+            browser.test.log(`Clear popup URL. Click browser action. Expect click event.`);
             browser.browserAction.setPopup({popup: ""});
             sendClick({expectEvent: true, expectPopup: null});
           },
           () => {
+            browser.test.log(`Click browser action again. Expect another click event.`);
             sendClick({expectEvent: true, expectPopup: null});
           },
           () => {
-            browser.browserAction.setPopup({popup: "/popup-a.html"});
-            sendClick({expectEvent: false, expectPopup: "a", runNextTest: true});
+            browser.test.log(`Call triggerAction. Expect click event.`);
+            sendClick({expectEvent: true, expectPopup: null}, "trigger-action");
           },
           () => {
-            browser.test.sendMessage("next-test", {expectClosed: true});
+            browser.test.log(`Set popup to "a" and click browser action. Expect popup "a", and leave open.`);
+            browser.browserAction.setPopup({popup: "/popup-a.html"});
+            sendClick({expectEvent: false, expectPopup: "a", closePopup: false});
+          },
+          () => {
+            browser.test.log(`Tell popup "a" to call window.close(). Expect popup closed.`);
+            browser.test.sendMessage("next-test", {closePopupUsingWindow: true});
           },
         ];
 
         let expect = {};
-        sendClick = ({expectEvent, expectPopup, runNextTest, closePopup}) => {
+        sendClick = ({expectEvent, expectPopup, runNextTest, waitUntilClosed, closePopup}, message = "send-click") => {
           if (closePopup == undefined) {
             closePopup = true;
           }
 
-          expect = {event: expectEvent, popup: expectPopup, runNextTest, closePopup};
-          browser.test.sendMessage("send-click");
+          expect = {event: expectEvent, popup: expectPopup, runNextTest, waitUntilClosed, closePopup};
+          browser.test.sendMessage(message);
         };
 
         browser.runtime.onMessage.addListener(msg => {
-          if (msg == "close-popup") {
+          if (msg == "close-popup-using-window.close") {
             return;
           } else if (expect.popup) {
             browser.test.assertEq(msg, `from-popup-${expect.popup}`,
                                   "expected popup opened");
           } else {
             browser.test.fail(`unexpected popup: ${msg}`);
           }
 
           expect.popup = null;
-          if (expect.runNextTest) {
-            expect.runNextTest = false;
-            tests.shift()();
-          } else {
-            browser.test.sendMessage("next-test", {closePopup: expect.closePopup});
-          }
+          browser.test.sendMessage("next-test", expect);
         });
 
         browser.browserAction.onClicked.addListener(() => {
           if (expect.event) {
             browser.test.succeed("expected click event received");
           } else {
             browser.test.fail("unexpected click event");
           }
 
           expect.event = false;
-          browser.test.sendMessage("next-test");
+          browser.test.sendMessage("next-test", expect);
         });
 
         browser.test.onMessage.addListener((msg) => {
-          if (msg == "close-popup") {
-            browser.runtime.sendMessage("close-popup");
+          if (msg == "close-popup-using-window.close") {
+            browser.runtime.sendMessage("close-popup-using-window.close");
             return;
           }
 
           if (msg != "next-test") {
             browser.test.fail("Expecting 'next-test' message");
           }
 
           if (tests.length) {
@@ -151,28 +174,37 @@ function* testInArea(area) {
       },
     },
   });
 
   extension.onMessage("send-click", () => {
     clickBrowserAction(extension);
   });
 
+  extension.onMessage("trigger-action", () => {
+    getBrowserAction(extension).triggerAction(window);
+  });
+
   let widget;
   extension.onMessage("next-test", Task.async(function* (expecting = {}) {
     if (!widget) {
       widget = getBrowserActionWidget(extension);
       CustomizableUI.addWidgetToArea(widget.id, area);
     }
-    if (expecting.expectClosed) {
+    if (expecting.waitUntilClosed) {
+      let panel = getBrowserActionPopup(extension);
+      if (panel && panel.state != "closed") {
+        yield promisePopupHidden(panel);
+      }
+    } else if (expecting.closePopupUsingWindow) {
       let panel = getBrowserActionPopup(extension);
       ok(panel, "Expect panel to exist");
       yield promisePopupShown(panel);
 
-      extension.sendMessage("close-popup");
+      extension.sendMessage("close-popup-using-window.close");
 
       yield promisePopupHidden(panel);
       ok(true, "Panel is closed");
     } else if (expecting.closePopup) {
       yield closeBrowserAction(extension);
     }
 
     extension.sendMessage("next-test");
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_commands_execute_browser_action.js
@@ -0,0 +1,113 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+function* testExecuteBrowserActionWithOptions(options = {}) {
+  let extensionOptions = {};
+
+  extensionOptions.manifest = {
+    "commands": {
+      "_execute_browser_action": {
+        "suggested_key": {
+          "default": "Alt+Shift+J",
+        },
+      },
+    },
+    "browser_action": {
+      "browser_style": true,
+    },
+  };
+
+  if (options.withPopup) {
+    extensionOptions.manifest.browser_action.default_popup = "popup.html";
+
+    extensionOptions.files = {
+      "popup.html": `
+        <!DOCTYPE html>
+        <html>
+          <head>
+            <meta charset="utf-8">
+            <script src="popup.js"></script>
+          </head>
+        </html>
+      `,
+
+      "popup.js": function() {
+        browser.runtime.sendMessage("from-browser-action-popup");
+      },
+    };
+  }
+
+  extensionOptions.background = () => {
+    browser.test.onMessage.addListener((message, withPopup) => {
+      browser.commands.onCommand.addListener((commandName) => {
+        if (commandName == "_execute_browser_action") {
+          browser.test.fail("The onCommand listener should never fire for _execute_browser_action.");
+        }
+      });
+
+      browser.browserAction.onClicked.addListener(() => {
+        if (withPopup) {
+          browser.test.fail("The onClick listener should never fire if the browserAction has a popup.");
+          browser.test.notifyFail("execute-browser-action-on-clicked-fired");
+        } else {
+          browser.test.notifyPass("execute-browser-action-on-clicked-fired");
+        }
+      });
+
+      browser.runtime.onMessage.addListener(msg => {
+        if (msg == "from-browser-action-popup") {
+          browser.test.notifyPass("execute-browser-action-popup-opened");
+        }
+      });
+
+      browser.test.sendMessage("send-keys");
+    });
+  };
+
+  let extension = ExtensionTestUtils.loadExtension(extensionOptions);
+
+  extension.onMessage("send-keys", () => {
+    EventUtils.synthesizeKey("j", {altKey: true, shiftKey: true});
+  });
+
+  yield extension.startup();
+
+  if (options.inArea) {
+    let widget = getBrowserActionWidget(extension);
+    CustomizableUI.addWidgetToArea(widget.id, options.inArea);
+  }
+
+  extension.sendMessage("withPopup", options.withPopup);
+
+  if (options.withPopup) {
+    yield extension.awaitFinish("execute-browser-action-popup-opened");
+    yield closeBrowserAction(extension);
+  } else {
+    yield extension.awaitFinish("execute-browser-action-on-clicked-fired");
+  }
+  yield extension.unload();
+}
+
+add_task(function* test_execute_browser_action_with_popup() {
+  yield testExecuteBrowserActionWithOptions({
+    withPopup: true,
+  });
+});
+
+add_task(function* test_execute_browser_action_without_popup() {
+  yield testExecuteBrowserActionWithOptions();
+});
+
+add_task(function* test_execute_browser_action_in_hamburger_menu_with_popup() {
+  yield testExecuteBrowserActionWithOptions({
+    withPopup: true,
+    inArea: CustomizableUI.AREA_PANEL,
+  });
+});
+
+add_task(function* test_execute_browser_action_in_hamburger_menu_without_popup() {
+  yield testExecuteBrowserActionWithOptions({
+    inArea: CustomizableUI.AREA_PANEL,
+  });
+});
--- a/browser/components/extensions/test/browser/browser_ext_contextMenus.js
+++ b/browser/components/extensions/test/browser/browser_ext_contextMenus.js
@@ -1,16 +1,16 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
+const PAGE = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html";
 
 add_task(function* () {
-  let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
-    "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
+  let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
 
   gBrowser.selectedTab = tab1;
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["contextMenus"],
     },
 
@@ -37,21 +37,18 @@ add_task(function* () {
   is(item.length, 0, "no contextMenu item for image was found");
   yield closeContextMenu();
 
   yield extension.unload();
 
   yield BrowserTestUtils.removeTab(tab1);
 });
 
-/* globals content */
-/* eslint-disable mozilla/no-cpows-in-tests */
 add_task(function* () {
-  let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
-    "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
+  let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
 
   gBrowser.selectedTab = tab1;
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["contextMenus"],
     },
 
@@ -138,26 +135,26 @@ add_task(function* () {
 
   yield extension.startup();
   yield extension.awaitFinish("contextmenus");
 
   let expectedClickInfo = {
     menuItemId: "ext-image",
     mediaType: "image",
     srcUrl: "http://mochi.test:8888/browser/browser/components/extensions/test/browser/ctxmenu-image.png",
-    pageUrl: "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html",
+    pageUrl: PAGE,
     editable: false,
   };
 
   function checkClickInfo(result) {
     for (let i of Object.keys(expectedClickInfo)) {
       is(result.info[i], expectedClickInfo[i],
          "click info " + i + " expected to be: " + expectedClickInfo[i] + " but was: " + result.info[i]);
     }
-    is(expectedClickInfo.pageSrc, result.tab.url);
+    is(expectedClickInfo.pageSrc, result.tab.url, "click info page source is the right tab");
   }
 
   let extensionMenuRoot = yield openExtensionContextMenu();
 
   // Check some menu items
   let items = extensionMenuRoot.getElementsByAttribute("label", "image");
   is(items.length, 1, "contextMenu item for image was found (context=image)");
   let image = items[0];
@@ -190,17 +187,17 @@ add_task(function* () {
   is(items.length, 1, "contextMenu item for text input element was found (context=editable)");
   let editable = items[0];
 
   // Click on ext-editable item and check the click results.
   yield closeExtensionContextMenu(editable);
 
   expectedClickInfo = {
     menuItemId: "ext-editable",
-    pageUrl: "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html",
+    pageUrl: PAGE,
     editable: true,
   };
 
   result = yield extension.awaitMessage("onclick");
   checkClickInfo(result);
   result = yield extension.awaitMessage("browser.contextMenus.onClicked");
   checkClickInfo(result);
 
@@ -223,17 +220,17 @@ add_task(function* () {
   // Check some menu items
   items = extensionMenuRoot.getElementsByAttribute("label", "Without onclick property");
   is(items.length, 1, "contextMenu item was found (context=page)");
 
   yield closeExtensionContextMenu(items[0]);
 
   expectedClickInfo = {
     menuItemId: "ext-without-onclick",
-    pageUrl: "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html",
+    pageUrl: PAGE,
   };
 
   result = yield extension.awaitMessage("browser.contextMenus.onClicked");
   checkClickInfo(result);
 
   // Bring up context menu again
   extensionMenuRoot = yield openExtensionContextMenu();
 
@@ -244,25 +241,84 @@ add_task(function* () {
 
   items = extensionMenuRoot.getElementsByAttribute("label", "selection");
   is(items.length, 0, "contextMenu item label update worked (context=selection)");
 
   yield closeExtensionContextMenu(selectionItem);
 
   expectedClickInfo = {
     menuItemId: "ext-selection",
-    pageUrl: "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html",
+    pageUrl: PAGE,
     selectionText: "just some text 1234567890123456789012345678901234567890123456789012345678901234567890123456789012",
   };
 
   result = yield extension.awaitMessage("onclick");
   checkClickInfo(result);
   result = yield extension.awaitMessage("browser.contextMenus.onClicked");
   checkClickInfo(result);
 
   let contentAreaContextMenu = yield openContextMenu("#img1");
   items = contentAreaContextMenu.getElementsByAttribute("ext-type", "top-level-menu");
   is(items.length, 0, "top level item was not found (after removeAll()");
   yield closeContextMenu();
 
   yield extension.unload();
   yield BrowserTestUtils.removeTab(tab1);
 });
+
+add_task(function* testRemoveAllWithTwoExtensions() {
+  const tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
+  const manifest = {permissions: ["contextMenus"]};
+
+  const first = ExtensionTestUtils.loadExtension({manifest, background() {
+    browser.contextMenus.create({title: "alpha", contexts: ["all"]});
+
+    browser.contextMenus.onClicked.addListener(() => {
+      browser.contextMenus.removeAll();
+    });
+    browser.test.onMessage.addListener(() => {
+      browser.contextMenus.create({title: "gamma", contexts: ["all"]});
+    });
+  }});
+
+  const second = ExtensionTestUtils.loadExtension({manifest, background() {
+    browser.contextMenus.create({title: "beta", contexts: ["all"]});
+
+    browser.contextMenus.onClicked.addListener(() => {
+      browser.contextMenus.removeAll();
+    });
+  }});
+
+  yield first.startup();
+  yield second.startup();
+
+  function* confirmMenuItems(...items) {
+    const menu = yield openContextMenu();
+    for (const id of ["alpha", "beta", "gamma"]) {
+      const expected = items.includes(id);
+      const found = menu.getElementsByAttribute("label", id);
+      is(found.length, expected, `menu item ${id} ${expected ? "" : "not "}found`);
+    }
+    // Return the first menu item, we need to click it.
+    return menu.getElementsByAttribute("label", items[0])[0];
+  }
+
+  // Confirm alpha, beta exist; click alpha to remove it.
+  const alpha = yield confirmMenuItems("alpha", "beta");
+  yield closeExtensionContextMenu(alpha);
+
+  // Confirm only beta exists.
+  yield confirmMenuItems("beta");
+  yield closeContextMenu();
+
+  // Create gamma, confirm, click.
+  first.sendMessage("create");
+  const beta = yield confirmMenuItems("beta", "gamma");
+  yield closeExtensionContextMenu(beta);
+
+  // Confirm only gamma is left.
+  yield confirmMenuItems("gamma");
+  yield closeContextMenu();
+
+  yield first.unload();
+  yield second.unload();
+  yield BrowserTestUtils.removeTab(tab);
+});
--- a/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
@@ -1,13 +1,15 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 add_task(function* testPageActionPopup() {
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
+
   let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head></html>`;
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "background": {
         "page": "data/background.html",
       },
       "page_action": {
@@ -64,16 +66,22 @@ add_task(function* testPageActionPopup()
           },
           () => {
             browser.pageAction.setPopup({tabId, popup: "/popup-a.html"});
             sendClick({expectEvent: false, expectPopup: "a", runNextTest: true});
           },
           () => {
             browser.test.sendMessage("next-test", {expectClosed: true});
           },
+          () => {
+            sendClick({expectEvent: false, expectPopup: "a", runNextTest: true});
+          },
+          () => {
+            browser.test.sendMessage("next-test", {closeOnTabSwitch: true});
+          },
         ];
 
         let expect = {};
         sendClick = ({expectEvent, expectPopup, runNextTest}) => {
           expect = {event: expectEvent, popup: expectPopup, runNextTest};
           browser.test.sendMessage("send-click");
         };
 
@@ -148,16 +156,30 @@ add_task(function* testPageActionPopup()
     if (expecting.expectClosed) {
       ok(panel, "Expect panel to exist");
       yield promisePopupShown(panel);
 
       extension.sendMessage("close-popup");
 
       yield promisePopupHidden(panel);
       ok(true, `Panel is closed`);
+    } else if (expecting.closeOnTabSwitch) {
+      ok(panel, "Expect panel to exist");
+      yield promisePopupShown(panel);
+
+      let oldTab = gBrowser.selectedTab;
+      ok(oldTab != gBrowser.tabs[0], "Should have an inactive tab to switch to");
+
+      let hiddenPromise = promisePopupHidden(panel);
+
+      gBrowser.selectedTab = gBrowser.tabs[0];
+      yield hiddenPromise;
+      info("Panel closed");
+
+      gBrowser.selectedTab = oldTab;
     } else if (panel) {
       yield promisePopupShown(panel);
       panel.hidePopup();
     }
 
     if (panel) {
       panel = document.getElementById(panelId);
       is(panel, null, "panel successfully removed from document after hiding");
@@ -172,16 +194,18 @@ add_task(function* testPageActionPopup()
 
   yield extension.unload();
 
   let node = document.getElementById(pageActionId);
   is(node, null, "pageAction image removed from document");
 
   let panel = document.getElementById(panelId);
   is(panel, null, "pageAction panel removed from document");
+
+  yield BrowserTestUtils.removeTab(tab);
 });
 
 
 add_task(function* testPageActionSecurity() {
   const URL = "chrome://browser/content/browser.xul";
 
   let apis = ["browser_action", "page_action"];
 
--- a/browser/components/extensions/test/browser/browser_ext_windows_create.js
+++ b/browser/components/extensions/test/browser/browser_ext_windows_create.js
@@ -160,8 +160,65 @@ add_task(function* testWindowCreateParam
     },
   });
 
   yield extension.startup();
   yield extension.awaitFinish("window-create-params");
   yield extension.unload();
 });
 
+// Tests allowScriptsToClose option
+add_task(function* test_allowScriptsToClose() {
+  const files = {
+    "dummy.html": "<meta charset=utf-8><script src=close.js></script>",
+    "close.js": function() {
+      window.close();
+      if (!window.closed) {
+        browser.test.sendMessage("close-failed");
+      }
+    },
+  };
+
+  function background() {
+    browser.test.onMessage.addListener((msg, options) => {
+      function listener(_, {status}, {url}) {
+        if (status == "complete" && url == options.url) {
+          browser.tabs.onUpdated.removeListener(listener);
+          browser.tabs.executeScript({file: "close.js"});
+        }
+      }
+      options.url = browser.runtime.getURL(options.url);
+      browser.windows.create(options);
+      if (msg === "create+execute") {
+        browser.tabs.onUpdated.addListener(listener);
+      }
+    });
+    browser.test.notifyPass();
+  }
+
+  const example = "http://example.com/";
+  const manifest = {permissions: ["tabs", example]};
+
+  const extension = ExtensionTestUtils.loadExtension({files, background, manifest});
+  yield SpecialPowers.pushPrefEnv({set: [["dom.allow_scripts_to_close_windows", false]]});
+
+  yield extension.startup();
+  yield extension.awaitFinish();
+
+  extension.sendMessage("create", {url: "dummy.html"});
+  let win = yield BrowserTestUtils.waitForNewWindow();
+  yield BrowserTestUtils.windowClosed(win);
+  info("script allowed to close the window");
+
+  extension.sendMessage("create+execute", {url: example});
+  win = yield BrowserTestUtils.waitForNewWindow();
+  yield extension.awaitMessage("close-failed");
+  info("script prevented from closing the window");
+  win.close();
+
+  extension.sendMessage("create+execute", {url: example, allowScriptsToClose: true});
+  win = yield BrowserTestUtils.waitForNewWindow();
+  yield BrowserTestUtils.windowClosed(win);
+  info("script allowed to close the window");
+
+  yield SpecialPowers.popPrefEnv();
+  yield extension.unload();
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_windows_create_url.js
@@ -0,0 +1,84 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+add_task(function* testWindowCreate() {
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      permissions: ["tabs"],
+    },
+
+    background() {
+      const EXTENSION_URL = browser.runtime.getURL("test.html");
+      const REMOTE_URL = browser.runtime.getURL("test.html");
+
+      let windows = new class extends Map { // eslint-disable-line new-parens
+        get(id) {
+          if (!this.has(id)) {
+            let window = {
+              tabs: new Map(),
+            };
+            window.promise = new Promise(resolve => {
+              window.resolvePromise = resolve;
+            });
+
+            this.set(id, window);
+          }
+
+          return super.get(id);
+        }
+      };
+
+      browser.tabs.onUpdated.addListener((tabId, changed, tab) => {
+        if (changed.status == "complete" && tab.url !== "about:blank") {
+          let window = windows.get(tab.windowId);
+          window.tabs.set(tab.index, tab);
+
+          if (window.tabs.size === window.expectedTabs) {
+            window.resolvePromise(window);
+          }
+        }
+      });
+
+      function create(options) {
+        return browser.windows.create(options).then(window => {
+          let win = windows.get(window.id);
+
+          win.expectedTabs = Array.isArray(options.url) ? options.url.length : 1;
+
+          return win.promise;
+        });
+      }
+
+      Promise.all([
+        create({url: REMOTE_URL}),
+        create({url: "test.html"}),
+        create({url: EXTENSION_URL}),
+        create({url: [REMOTE_URL, "test.html", EXTENSION_URL]}),
+      ]).then(windows => {
+        browser.test.assertEq(REMOTE_URL, windows[0].tabs.get(0).url, "Single, absolute, remote URL");
+
+        browser.test.assertEq(REMOTE_URL, windows[1].tabs.get(0).url, "Single, relative URL");
+
+        browser.test.assertEq(REMOTE_URL, windows[2].tabs.get(0).url, "Single, absolute, extension URL");
+
+        browser.test.assertEq(REMOTE_URL, windows[3].tabs.get(0).url, "url[0]: Absolute, remote URL");
+        browser.test.assertEq(EXTENSION_URL, windows[3].tabs.get(1).url, "url[1]: Relative URL");
+        browser.test.assertEq(EXTENSION_URL, windows[3].tabs.get(2).url, "url[2]: Absolute, extension URL");
+      }).then(() => {
+        browser.test.notifyPass("window-create-url");
+      }).catch(e => {
+        browser.test.fail(`${e} :: ${e.stack}`);
+        browser.test.notifyFail("window-create-url");
+      });
+    },
+
+    files: {
+      "test.html": `<DOCTYPE html><html><head><meta charset="utf-8"></head></html>`,
+    },
+  });
+
+  yield extension.startup();
+  yield extension.awaitFinish("window-create-url");
+  yield extension.unload();
+});
--- a/browser/components/extensions/test/browser/context.html
+++ b/browser/components/extensions/test/browser/context.html
@@ -1,10 +1,11 @@
 <html>
   <head>
+    <meta charset="utf-8">
   </head>
   <body>
   just some text 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
   <img src="ctxmenu-image.png" id="img1">
 
   <p>
     <a href="some-link" id="link1">Some link</a>
   </p>
--- a/browser/components/migration/AutoMigrate.jsm
+++ b/browser/components/migration/AutoMigrate.jsm
@@ -82,17 +82,21 @@ const AutoMigrate = {
   },
 
   observe(subject, topic, data) {
     if (topic == kPasswordManagerTopic) {
       // As soon as any login gets added or modified, disable undo:
       // (Note that this ignores logins being removed as that doesn't
       //  impair the 'undo' functionality of the import.)
       if (kPasswordManagerTopicTypes.has(data)) {
-        this.removeUndoOption(this.UNDO_REMOVED_REASON_PASSWORD_CHANGE);
+        // Ignore chrome:// things like sync credentials:
+        let loginInfo = subject.QueryInterface(Ci.nsILoginInfo);
+        if (!loginInfo.hostname || !loginInfo.hostname.startsWith("chrome://")) {
+          this.removeUndoOption(this.UNDO_REMOVED_REASON_PASSWORD_CHANGE);
+        }
       }
     } else if (topic == kSyncTopic) {
       this.removeUndoOption(this.UNDO_REMOVED_REASON_SYNC_SIGNIN);
     }
   },
 
   /**
    * Automatically pick a migrator and resources to migrate,
--- a/browser/components/migration/ChromeProfileMigrator.js
+++ b/browser/components/migration/ChromeProfileMigrator.js
@@ -28,18 +28,16 @@ Cu.import("resource://gre/modules/osfile
 Cu.import("resource://gre/modules/Console.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource:///modules/MigrationUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OSCrypto",
                                   "resource://gre/modules/OSCrypto.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Sqlite",
-                                  "resource://gre/modules/Sqlite.jsm");
 /**
  * Get an nsIFile instance representing the expected location of user data
  * for this copy of Chrome/Chromium/Canary on different OSes.
  * @param subfoldersWin {Array} an array of subfolders to use for Windows
  * @param subfoldersOSX {Array} an array of subfolders to use for OS X
  * @param subfoldersUnix {Array} an array of subfolders to use for *nix systems
  * @returns {nsIFile} the place we expect data to live. Might not actually exist!
  */
@@ -103,17 +101,16 @@ function* insertBookmarkItems(parentGuid
       }
     } catch (e) {
       Cu.reportError(e);
       errorAccumulator(e);
     }
   }
 }
 
-
 function ChromeProfileMigrator() {
   let chromeUserDataFolder =
     getDataFolder(["Google", "Chrome"], ["Google", "Chrome"], ["google-chrome"]);
   this._chromeUserDataFolder = chromeUserDataFolder.exists() ?
     chromeUserDataFolder : null;
 }
 
 ChromeProfileMigrator.prototype = Object.create(MigratorPrototype);
@@ -306,69 +303,29 @@ function GetBookmarksResource(aProfileFo
 }
 
 function GetHistoryResource(aProfileFolder) {
   let historyFile = aProfileFolder.clone();
   historyFile.append("History");
   if (!historyFile.exists())
     return null;
 
-  function getRows(dbOptions) {
-    const RETRYLIMIT = 10;
-    const RETRYINTERVAL = 100;
-    return Task.spawn(function* innerGetRows() {
-      let rows = null;
-      for (let retryCount = RETRYLIMIT; retryCount && !rows; retryCount--) {
-        // Attempt to get the rows. If this succeeds, we will bail out of the loop,
-        // close the database in a failsafe way, and pass the rows back.
-        // If fetching the rows throws, we will wait RETRYINTERVAL ms
-        // and try again. This will repeat a maximum of RETRYLIMIT times.
-        let db;
-        let didOpen = false;
-        let exceptionSeen;
-        try {
-          db = yield Sqlite.openConnection(dbOptions);
-          didOpen = true;
-          rows = yield db.execute(`SELECT url, title, last_visit_time, typed_count
-                                   FROM urls WHERE hidden = 0`);
-        } catch (ex) {
-          if (!exceptionSeen) {
-            Cu.reportError(ex);
-          }
-          exceptionSeen = ex;
-        } finally {
-          try {
-            if (didOpen) {
-              yield db.close();
-            }
-          } catch (ex) {}
-        }
-        if (exceptionSeen) {
-          yield new Promise(resolve => setTimeout(resolve, RETRYINTERVAL));
-        }
-      }
-      if (!rows) {
-        throw new Error("Couldn't get rows from the Chrome history database.");
-      }
-      return rows;
-    });
-  }
-
   return {
     type: MigrationUtils.resourceTypes.HISTORY,
 
     migrate(aCallback) {
       Task.spawn(function* () {
         let dbOptions = {
           readOnly: true,
           ignoreLockingMode: true,
           path: historyFile.path
         };
 
-        let rows = yield getRows(dbOptions);
+        let rows = yield MigrationUtils.getRowsFromDBWithoutLocks(historyFile.path, "Chrome history",
+          `SELECT url, title, last_visit_time, typed_count FROM urls WHERE hidden = 0`);
         let places = [];
         for (let row of rows) {
           try {
             // if having typed_count, we changes transition type to typed.
             let transType = PlacesUtils.history.TRANSITION_LINK;
             if (row.getResultByName("typed_count") > 0)
               transType = PlacesUtils.history.TRANSITION_TYPED;
 
@@ -419,160 +376,140 @@ function GetCookiesResource(aProfileFold
   let cookiesFile = aProfileFolder.clone();
   cookiesFile.append("Cookies");
   if (!cookiesFile.exists())
     return null;
 
   return {
     type: MigrationUtils.resourceTypes.COOKIES,
 
-    migrate: function(aCallback) {
-      let dbConn = Services.storage.openUnsharedDatabase(cookiesFile);
+    migrate: Task.async(function* (aCallback) {
       // We don't support decrypting cookies yet so only import plaintext ones.
-      let stmt = dbConn.createAsyncStatement(`
-        SELECT host_key, name, value, path, expires_utc, secure, httponly, encrypted_value
+      let rows = yield MigrationUtils.getRowsFromDBWithoutLocks(cookiesFile.path, "Chrome cookies",
+       `SELECT host_key, name, value, path, expires_utc, secure, httponly, encrypted_value
         FROM cookies
-        WHERE length(encrypted_value) = 0`);
-
-      stmt.executeAsync({
-        handleResult : function(aResults) {
-          for (let row = aResults.getNextRow(); row; row = aResults.getNextRow()) {
-            let host_key = row.getResultByName("host_key");
-            if (host_key.match(/^\./)) {
-              // 1st character of host_key may be ".", so we have to remove it
-              host_key = host_key.substr(1);
-            }
+        WHERE length(encrypted_value) = 0`).catch(ex => {
+        Cu.reportError(ex);
+        aCallback(false);
+      });
+      // If the promise was rejected we will have already called aCallback,
+      // so we can just return here.
+      if (!rows) {
+        return;
+      }
 
-            try {
-              let expiresUtc =
-                chromeTimeToDate(row.getResultByName("expires_utc")) / 1000;
-              Services.cookies.add(host_key,
-                                   row.getResultByName("path"),
-                                   row.getResultByName("name"),
-                                   row.getResultByName("value"),
-                                   row.getResultByName("secure"),
-                                   row.getResultByName("httponly"),
-                                   false,
-                                   parseInt(expiresUtc),
-                                   {});
-            } catch (e) {
-              Cu.reportError(e);
-            }
-          }
-        },
+      for (let row of rows) {
+        let host_key = row.getResultByName("host_key");
+        if (host_key.match(/^\./)) {
+          // 1st character of host_key may be ".", so we have to remove it
+          host_key = host_key.substr(1);
+        }
 
-        handleError : function(aError) {
-          Cu.reportError("Async statement execution returned with '" +
-                         aError.result + "', '" + aError.message + "'");
-        },
-
-        handleCompletion : function(aReason) {
-          dbConn.asyncClose();
-          aCallback(aReason == Ci.mozIStorageStatementCallback.REASON_FINISHED);
-        },
-      });
-      stmt.finalize();
-    }
-  }
+        try {
+          let expiresUtc =
+            chromeTimeToDate(row.getResultByName("expires_utc")) / 1000;
+          Services.cookies.add(host_key,
+                               row.getResultByName("path"),
+                               row.getResultByName("name"),
+                               row.getResultByName("value"),
+                               row.getResultByName("secure"),
+                               row.getResultByName("httponly"),
+                               false,
+                               parseInt(expiresUtc),
+                               {});
+        } catch (e) {
+          Cu.reportError(e);
+        }
+      }
+      aCallback(true);
+    }),
+  };
 }
 
 function GetWindowsPasswordsResource(aProfileFolder) {
   let loginFile = aProfileFolder.clone();
   loginFile.append("Login Data");
   if (!loginFile.exists())
     return null;
 
   return {
     type: MigrationUtils.resourceTypes.PASSWORDS,
 
-    migrate(aCallback) {
-      let dbConn = Services.storage.openUnsharedDatabase(loginFile);
-      let stmt = dbConn.createAsyncStatement(`
-        SELECT origin_url, action_url, username_element, username_value,
+    migrate: Task.async(function* (aCallback) {
+      let rows = yield MigrationUtils.getRowsFromDBWithoutLocks(loginFile.path, "Chrome passwords",
+       `SELECT origin_url, action_url, username_element, username_value,
         password_element, password_value, signon_realm, scheme, date_created,
-        times_used FROM logins WHERE blacklisted_by_user = 0`);
+        times_used FROM logins WHERE blacklisted_by_user = 0`).catch(ex => {
+        Cu.reportError(ex);
+        aCallback(false);
+      });
+      // If the promise was rejected we will have already called aCallback,
+      // so we can just return here.
+      if (!rows) {
+        return;
+      }
       let crypto = new OSCrypto();
 
-      stmt.executeAsync({
-        _rowToLoginInfo(row) {
-          let loginInfo = {
-            username: row.getResultByName("username_value"),
-            password: crypto.
-                      decryptData(crypto.arrayToString(row.getResultByName("password_value")),
-                                                       null),
-            hostName: NetUtil.newURI(row.getResultByName("origin_url")).prePath,
-            submitURL: null,
-            httpRealm: null,
-            usernameElement: row.getResultByName("username_element"),
-            passwordElement: row.getResultByName("password_element"),
-            timeCreated: chromeTimeToDate(row.getResultByName("date_created") + 0).getTime(),
-            timesUsed: row.getResultByName("times_used") + 0,
-          };
+      for (let row of rows) {
+        let loginInfo = {
+          username: row.getResultByName("username_value"),
+          password: crypto.
+                    decryptData(crypto.arrayToString(row.getResultByName("password_value")),
+                                                     null),
+          hostName: NetUtil.newURI(row.getResultByName("origin_url")).prePath,
+          submitURL: null,
+          httpRealm: null,
+          usernameElement: row.getResultByName("username_element"),
+          passwordElement: row.getResultByName("password_element"),
+          timeCreated: chromeTimeToDate(row.getResultByName("date_created") + 0).getTime(),
+          timesUsed: row.getResultByName("times_used") + 0,
+        };
 
+        try {
           switch (row.getResultByName("scheme")) {
             case AUTH_TYPE.SCHEME_HTML:
               loginInfo.submitURL = NetUtil.newURI(row.getResultByName("action_url")).prePath;
               break;
             case AUTH_TYPE.SCHEME_BASIC:
             case AUTH_TYPE.SCHEME_DIGEST:
               // signon_realm format is URIrealm, so we need remove URI
               loginInfo.httpRealm = row.getResultByName("signon_realm")
                                     .substring(loginInfo.hostName.length + 1);
               break;
             default:
               throw new Error("Login data scheme type not supported: " +
                               row.getResultByName("scheme"));
           }
-
-          return loginInfo;
-        },
-
-        handleResult(aResults) {
-          for (let row = aResults.getNextRow(); row; row = aResults.getNextRow()) {
-            try {
-              let loginInfo = this._rowToLoginInfo(row);
-              let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
+          let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
 
-              login.init(loginInfo.hostName, loginInfo.submitURL, loginInfo.httpRealm,
-                         loginInfo.username, loginInfo.password, loginInfo.usernameElement,
-                         loginInfo.passwordElement);
-              login.QueryInterface(Ci.nsILoginMetaInfo);
-              login.timeCreated = loginInfo.timeCreated;
-              login.timeLastUsed = loginInfo.timeCreated;
-              login.timePasswordChanged = loginInfo.timeCreated;
-              login.timesUsed = loginInfo.timesUsed;
-
-              // Add the login only if there's not an existing entry
-              let logins = Services.logins.findLogins({}, login.hostname,
-                                                      login.formSubmitURL,
-                                                      login.httpRealm);
+          login.init(loginInfo.hostName, loginInfo.submitURL, loginInfo.httpRealm,
+                     loginInfo.username, loginInfo.password, loginInfo.usernameElement,
+                     loginInfo.passwordElement);
+          login.QueryInterface(Ci.nsILoginMetaInfo);
+          login.timeCreated = loginInfo.timeCreated;
+          login.timeLastUsed = loginInfo.timeCreated;
+          login.timePasswordChanged = loginInfo.timeCreated;
+          login.timesUsed = loginInfo.timesUsed;
 
-              // Bug 1187190: Password changes should be propagated depending on timestamps.
-              if (!logins.some(l => login.matches(l, true))) {
-                Services.logins.addLogin(login);
-              }
-            } catch (e) {
-              Cu.reportError(e);
-            }
-          }
-        },
+          // Add the login only if there's not an existing entry
+          let logins = Services.logins.findLogins({}, login.hostname,
+                                                  login.formSubmitURL,
+                                                  login.httpRealm);
 
-        handleError(aError) {
-          Cu.reportError("Async statement execution returned with '" +
-                         aError.result + "', '" + aError.message + "'");
-        },
-
-        handleCompletion(aReason) {
-          dbConn.asyncClose();
-          aCallback(aReason == Ci.mozIStorageStatementCallback.REASON_FINISHED);
-          crypto.finalize();
-        },
-      });
-      stmt.finalize();
-    }
+          // Bug 1187190: Password changes should be propagated depending on timestamps.
+          if (!logins.some(l => login.matches(l, true))) {
+            Services.logins.addLogin(login);
+          }
+        } catch (e) {
+          Cu.reportError(e);
+        }
+      }
+      crypto.finalize();
+      aCallback(true);
+    }),
   };
 }
 
 ChromeProfileMigrator.prototype.classDescription = "Chrome Profile Migrator";
 ChromeProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=chrome";
 ChromeProfileMigrator.prototype.classID = Components.ID("{4cec1de4-1671-4fc3-a53e-6c539dc77a26}");
 
 
--- a/browser/components/migration/MigrationUtils.jsm
+++ b/browser/components/migration/MigrationUtils.jsm
@@ -18,16 +18,18 @@ Cu.import("resource://gre/modules/XPCOMU
 XPCOMUtils.defineLazyModuleGetter(this, "AutoMigrate",
                                   "resource:///modules/AutoMigrate.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "BookmarkHTMLUtils",
                                   "resource://gre/modules/BookmarkHTMLUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
                                   "resource://gre/modules/PromiseUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Sqlite",
+                                  "resource://gre/modules/Sqlite.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
                                   "resource://gre/modules/TelemetryStopwatch.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
                                   "resource://gre/modules/WindowsRegistry.jsm");
 
 var gMigrators = null;
 var gProfileStartup = null;
 var gMigrationBundle = null;
@@ -533,16 +535,79 @@ this.MigrationUtils = Object.freeze({
   createImportedBookmarksFolder: Task.async(function* (sourceNameStr, parentGuid) {
     let source = this.getLocalizedString("sourceName" + sourceNameStr);
     let title = this.getLocalizedString("importedBookmarksFolder", [source]);
     return (yield PlacesUtils.bookmarks.insert({
       type: PlacesUtils.bookmarks.TYPE_FOLDER, parentGuid, title
     })).guid;
   }),
 
+  /**
+   * Get all the rows corresponding to a select query from a database, without
+   * requiring a lock on the database. If fetching data fails (because someone
+   * else tried to write to the DB at the same time, for example), we will
+   * retry the fetch after a 100ms timeout, up to 10 times.
+   *
+   * @param path
+   *        the file path to the database we want to open.
+   * @param description
+   *        a developer-readable string identifying what kind of database we're
+   *        trying to open.
+   * @param selectQuery
+   *        the SELECT query to use to fetch the rows.
+   *
+   * @return a promise that resolves to an array of rows. The promise will be
+   *         rejected if the read/fetch failed even after retrying.
+   */
+  getRowsFromDBWithoutLocks(path, description, selectQuery) {
+    let dbOptions = {
+      readOnly: true,
+      ignoreLockingMode: true,
+      path,
+    };
+
+    const RETRYLIMIT = 10;
+    const RETRYINTERVAL = 100;
+    return Task.spawn(function* innerGetRows() {
+      let rows = null;
+      for (let retryCount = RETRYLIMIT; retryCount && !rows; retryCount--) {
+        // Attempt to get the rows. If this succeeds, we will bail out of the loop,
+        // close the database in a failsafe way, and pass the rows back.
+        // If fetching the rows throws, we will wait RETRYINTERVAL ms
+        // and try again. This will repeat a maximum of RETRYLIMIT times.
+        let db;
+        let didOpen = false;
+        let exceptionSeen;
+        try {
+          db = yield Sqlite.openConnection(dbOptions);
+          didOpen = true;
+          rows = yield db.execute(selectQuery);
+        } catch (ex) {
+          if (!exceptionSeen) {
+            Cu.reportError(ex);
+          }
+          exceptionSeen = ex;
+        } finally {
+          try {
+            if (didOpen) {
+              yield db.close();
+            }
+          } catch (ex) {}
+        }
+        if (exceptionSeen) {
+          yield new Promise(resolve => setTimeout(resolve, RETRYINTERVAL));
+        }
+      }
+      if (!rows) {
+        throw new Error("Couldn't get rows from the " + description + " database.");
+      }
+      return rows;
+    });
+  },
+
   get _migrators() {
     return gMigrators ? gMigrators : gMigrators = new Map();
   },
 
   /*
    * Returns the migrator for the given source, if any data is available
    * for this source, or null otherwise.
    *
--- a/browser/components/newtab/tests/browser/browser_newtabwebchannel.js
+++ b/browser/components/newtab/tests/browser/browser_newtabwebchannel.js
@@ -236,16 +236,16 @@ add_task(function* open_webchannel_reloa
   });
 
   is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
   yield BrowserTestUtils.withNewTab(tabOptions, function*(browser) {
     let target = yield messagePromise;
     is(NewTabWebChannel.numBrowsers, 1, "One target expected");
     is(target.browser, browser, "Same browser");
 
-    browser.contentWindow.location.reload();
+    browser.reload();
   });
 
   Cu.forceGC();
   is(NewTabWebChannel.numBrowsers, 0, "Sanity check");
   yield unloadPromise;
   cleanup();
 });
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -28,16 +28,17 @@ XPCOMUtils.defineLazyServiceGetter(this,
   ["BookmarkHTMLUtils", "resource://gre/modules/BookmarkHTMLUtils.jsm"],
   ["BookmarkJSONUtils", "resource://gre/modules/BookmarkJSONUtils.jsm"],
   ["BrowserUITelemetry", "resource:///modules/BrowserUITelemetry.jsm"],
   ["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
   ["CaptivePortalWatcher", "resource:///modules/CaptivePortalWatcher.jsm"],
   ["ContentClick", "resource:///modules/ContentClick.jsm"],
   ["ContentPrefServiceParent", "resource://gre/modules/ContentPrefServiceParent.jsm"],
   ["ContentSearch", "resource:///modules/ContentSearch.jsm"],
+  ["DateTimePickerHelper", "resource://gre/modules/DateTimePickerHelper.jsm"],
   ["DirectoryLinksProvider", "resource:///modules/DirectoryLinksProvider.jsm"],
   ["Feeds", "resource:///modules/Feeds.jsm"],
   ["FileUtils", "resource://gre/modules/FileUtils.jsm"],
   ["FormValidationHandler", "resource:///modules/FormValidationHandler.jsm"],
   ["Integration", "resource://gre/modules/Integration.jsm"],
   ["LightweightThemeManager", "resource://gre/modules/LightweightThemeManager.jsm"],
   ["LoginHelper", "resource://gre/modules/LoginHelper.jsm"],
   ["LoginManagerParent", "resource://gre/modules/LoginManagerParent.jsm"],
@@ -697,17 +698,17 @@ BrowserGlue.prototype = {
     ReaderParent.init();
     URLBarZoom.init();
 
     SelfSupportBackend.init();
 
     // Ensure we keep track of places/pw-mananager undo by init'ing this early.
     Cu.import("resource:///modules/AutoMigrate.jsm");
 
-    if (!AppConstants.RELEASE_BUILD) {
+    if (!AppConstants.RELEASE_OR_BETA) {
       let themeName = gBrowserBundle.GetStringFromName("deveditionTheme.name");
       let vendorShortName = gBrandBundle.GetStringFromName("vendorShortName");
 
       LightweightThemeManager.addBuiltInTheme({
         id: "firefox-devedition@mozilla.org",
         name: themeName,
         headerURL: "resource:///chrome/browser/content/browser/defaultthemes/devedition.header.png",
         iconURL: "resource:///chrome/browser/content/browser/defaultthemes/devedition.icon.png",
@@ -1017,16 +1018,17 @@ BrowserGlue.prototype = {
       }
     }
 
     this._checkForOldBuildUpdates();
 
     CaptivePortalWatcher.init();
 
     AutoCompletePopup.init();
+    DateTimePickerHelper.init();
 
     this._firstWindowTelemetry(aWindow);
     this._firstWindowLoaded();
   },
 
   /**
    * Application shutdown handler.
    */
@@ -1048,16 +1050,17 @@ BrowserGlue.prototype = {
     BrowserUsageTelemetry.uninit();
     SelfSupportBackend.uninit();
     NewTabMessages.uninit();
     CaptivePortalWatcher.uninit();
     AboutNewTab.uninit();
     webrtcUI.uninit();
     FormValidationHandler.uninit();
     AutoCompletePopup.uninit();
+    DateTimePickerHelper.uninit();
     if (AppConstants.NIGHTLY_BUILD) {
       AddonWatcher.uninit();
     }
   },
 
   _initServiceDiscovery: function () {
     if (!Services.prefs.getBoolPref("browser.casting.enabled")) {
       return;
@@ -1142,17 +1145,17 @@ BrowserGlue.prototype = {
     }
 
     // Perform default browser checking.
     if (ShellService) {
       let shouldCheck = AppConstants.DEBUG ? false :
                                              ShellService.shouldCheckDefaultBrowser;
       let promptCount;
       let skipDefaultBrowserCheck = false;
-      if (!AppConstants.RELEASE_BUILD) {
+      if (!AppConstants.RELEASE_OR_BETA) {
         promptCount =
           Services.prefs.getIntPref("browser.shell.defaultBrowserCheckCount");
         skipDefaultBrowserCheck =
           Services.prefs.getBoolPref("browser.shell.skipDefaultBrowserCheck");
       }
       let willRecoverSession = false;
       try {
         let ss = Cc["@mozilla.org/browser/sessionstartup;1"].
@@ -1187,17 +1190,17 @@ BrowserGlue.prototype = {
         } else {
           promptCount++;
         }
         if (promptCount > 3) {
           willPrompt = false;
         }
       }
 
-      if (!AppConstants.RELEASE_BUILD) {
+      if (!AppConstants.RELEASE_OR_BETA) {
         if (willPrompt) {
           Services.prefs.setIntPref("browser.shell.defaultBrowserCheckCount",
                                     promptCount);
         }
       }
 
       try {
         // Report default browser status on startup to telemetry
--- a/browser/components/originattributes/test/browser/browser.ini
+++ b/browser/components/originattributes/test/browser/browser.ini
@@ -24,8 +24,9 @@ support-files =
   worker_blobify.js
   worker_deblobify.js
 
 [browser_firstPartyIsolation.js]
 [browser_localStorageIsolation.js]
 [browser_blobURLIsolation.js]
 [browser_imageCacheIsolation.js]
 [browser_sharedworker.js]
+[browser_httpauth.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/browser_httpauth.js
@@ -0,0 +1,54 @@
+let Cu = Components.utils;
+let {HttpServer} = Cu.import("resource://testing-common/httpd.js", {});
+
+let server = new HttpServer();
+server.registerPathHandler('/file.html', fileHandler);
+server.start(-1);
+
+let BASE_URI = 'http://localhost:' + server.identity.primaryPort;
+let FILE_URI = BASE_URI + '/file.html';
+
+let credentialQueue = [];
+
+// Ask the user agent for authorization.
+function fileHandler(metadata, response) {
+  if (!metadata.hasHeader("Authorization")) {
+    response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
+    response.setHeader("WWW-Authenticate", "Basic realm=\"User Visible Realm\"");
+    return;
+  }
+
+  // This will be "account:password" encoded in base64.
+  credentialQueue.push(metadata.getHeader("Authorization"));
+
+  response.setStatusLine(metadata.httpVersion, 200, "OK");
+  response.setHeader("Content-Type", "text/html", false);
+  let body = "<html><body></body></html>";
+  response.bodyOutputStream.write(body, body.length);
+}
+
+function onCommonDialogLoaded(subject) {
+  // Submit random account and password
+  let dialog = subject.Dialog;
+  dialog.ui.loginTextbox.setAttribute("value", Math.random());
+  dialog.ui.password1Textbox.setAttribute("value", Math.random());
+  dialog.ui.button0.click();
+}
+
+Services.obs.addObserver(onCommonDialogLoaded, "common-dialog-loaded", false);
+
+registerCleanupFunction(() => {
+  Services.obs.removeObserver(onCommonDialogLoaded, "common-dialog-loaded");
+  server.stop(() => {
+    server = null;
+  });
+});
+
+function getResult() {
+  // If two targets are isolated, they should get different credentials.
+  // Otherwise, the credentials will be cached and therefore the same.
+  return credentialQueue.shift();
+}
+
+IsolationTestTools.runTests(FILE_URI, getResult);
+
--- a/browser/components/originattributes/test/browser/test.html
+++ b/browser/components/originattributes/test/browser/test.html
@@ -7,19 +7,14 @@
   <script>
   window.onmessage = function (evt) {
     if (evt.data != "HI") {
       return;
     }
 
     window.parent.postMessage("OK", "http://mochi.test:8888");
   };
-
-  setTimeout(function() {
-    window.parent.postMessage("KO", "http://mochi.test:8888");
-  }, 1000);
-
   </script>
 </head>
 <body>
   Hello World.
 </body>
 </html>
--- a/browser/components/preferences/cookies.js
+++ b/browser/components/preferences/cookies.js
@@ -1,15 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
 /* 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/. */
 
 const nsICookie = Components.interfaces.nsICookie;
 
+Components.utils.import("resource://gre/modules/AppConstants.jsm");
 Components.utils.import("resource://gre/modules/PluralForm.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm")
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
                                   "resource://gre/modules/ContextualIdentityService.jsm");
 
 var gCookiesWindow = {
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -851,17 +851,17 @@
 
       <handler event="keypress" keycode="VK_UP" modifiers="alt"
                phase="capturing"
                action="return this.openSearch();"/>
 
       <handler event="dragover">
       <![CDATA[
         var types = event.dataTransfer.types;
-        if (types.contains("text/plain") || types.contains("text/x-moz-text-internal"))
+        if (types.includes("text/plain") || types.includes("text/x-moz-text-internal"))
           event.preventDefault();
       ]]>
       </handler>
 
       <handler event="drop">
       <![CDATA[
         var dataTransfer = event.dataTransfer;
         var data = dataTransfer.getData("text/plain");
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -165,16 +165,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "SessionSaver",
   "resource:///modules/sessionstore/SessionSaver.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionCookies",
   "resource:///modules/sessionstore/SessionCookies.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionFile",
   "resource:///modules/sessionstore/SessionFile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TabAttributes",
   "resource:///modules/sessionstore/TabAttributes.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TabCrashHandler",
+  "resource:///modules/ContentCrashHandlers.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TabState",
   "resource:///modules/sessionstore/TabState.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TabStateCache",
   "resource:///modules/sessionstore/TabStateCache.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TabStateFlusher",
   "resource:///modules/sessionstore/TabStateFlusher.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Utils",
   "resource:///modules/sessionstore/Utils.jsm");
@@ -914,17 +916,17 @@ var SessionStoreInternal = {
         this.onTabHide(win, target);
         break;
       case "TabPinned":
       case "TabUnpinned":
       case "SwapDocShells":
         this.saveStateDelayed(win);
         break;
       case "oop-browser-crashed":
-        this.onBrowserCrashed(win, target);
+        this.onBrowserCrashed(target);
         break;
       case "XULFrameLoaderCreated":
         if (target.namespaceURI == NS_XUL &&
             target.localName == "browser" &&
             target.frameLoader &&
             target.permanentKey) {
           this._lastKnownFrameLoader.set(target.permanentKey, target.frameLoader);
           this.resetEpoch(target);
@@ -1862,22 +1864,35 @@ var SessionStoreInternal = {
    * @param aWindow
    *        Window reference
    */
   onTabSelect: function ssi_onTabSelect(aWindow) {
     if (RunState.isRunning) {
       this._windows[aWindow.__SSi].selected = aWindow.gBrowser.tabContainer.selectedIndex;
 
       let tab = aWindow.gBrowser.selectedTab;
-      // If __SS_restoreState is still on the browser and it is
-      // TAB_STATE_NEEDS_RESTORE, then then we haven't restored
-      // this tab yet. Explicitly call restoreTabContent to kick off the restore.
-      if (tab.linkedBrowser.__SS_restoreState &&
-          tab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
-        this.restoreTabContent(tab);
+      let browser = tab.linkedBrowser;
+
+      if (browser.__SS_restoreState &&
+          browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
+        // If __SS_restoreState is still on the browser and it is
+        // TAB_STATE_NEEDS_RESTORE, then then we haven't restored
+        // this tab yet.
+        //
+        // It's possible that this tab was recently revived, and that
+        // we've deferred showing the tab crashed page for it (if the
+        // tab crashed in the background). If so, we need to re-enter
+        // the crashed state, since we'll be showing the tab crashed
+        // page.
+        if (TabCrashHandler.willShowCrashedTab(browser)) {
+          this.enterCrashedState(browser);
+        } else {
+          this.restoreTabContent(tab);
+        }
+      }
     }
   },
 
   onTabShow: function ssi_onTabShow(aWindow, aTab) {
     // If the tab hasn't been restored yet, move it into the right bucket
     if (aTab.linkedBrowser.__SS_restoreState &&
         aTab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
       TabRestoreQueue.hiddenToVisible(aTab);
@@ -1909,33 +1924,47 @@ var SessionStoreInternal = {
   /**
    * Handler for the event that is fired when a <xul:browser> crashes.
    *
    * @param aWindow
    *        The window that the crashed browser belongs to.
    * @param aBrowser
    *        The <xul:browser> that is now in the crashed state.
    */
-  onBrowserCrashed: function(aWindow, aBrowser) {
+  onBrowserCrashed: function(aBrowser) {
     NS_ASSERT(aBrowser.isRemoteBrowser,
               "Only remote browsers should be able to crash");
-    this._crashedBrowsers.add(aBrowser.permanentKey);
+
+    this.enterCrashedState(aBrowser);
+    // The browser crashed so we might never receive flush responses.
+    // Resolve all pending flush requests for the crashed browser.
+    TabStateFlusher.resolveAll(aBrowser);
+  },
+
+  /**
+   * Called when a browser is showing or is about to show the tab
+   * crashed page. This method causes SessionStore to ignore the
+   * tab until it's restored.
+   *
+   * @param browser
+   *        The <xul:browser> that is about to show the crashed page.
+   */
+  enterCrashedState(browser) {
+    this._crashedBrowsers.add(browser.permanentKey);
+
+    let win = browser.ownerGlobal;
 
     // If we hadn't yet restored, or were still in the midst of
     // restoring this browser at the time of the crash, we need
     // to reset its state so that we can try to restore it again
     // when the user revives the tab from the crash.
-    if (aBrowser.__SS_restoreState) {
-      let tab = aWindow.gBrowser.getTabForBrowser(aBrowser);
+    if (browser.__SS_restoreState) {
+      let tab = win.gBrowser.getTabForBrowser(browser);
       this._resetLocalTabRestoringState(tab);
     }
-
-    // The browser crashed so we might never receive flush responses.
-    // Resolve all pending flush requests for the crashed browser.
-    TabStateFlusher.resolveAll(aBrowser);
   },
 
   // Clean up data that has been closed a long time ago.
   // Do not reschedule a save. This will wait for the next regular
   // save.
   onIdleDaily: function() {
     // Remove old closed windows
     this._cleanupOldData([this._closedWindows]);
--- a/browser/components/sessionstore/test/browser.ini
+++ b/browser/components/sessionstore/test/browser.ini
@@ -227,8 +227,10 @@ run-if = e10s
 [browser_newtab_userTypedValue.js]
 [browser_parentProcessRestoreHash.js]
 run-if = e10s
 [browser_sessionStoreContainer.js]
 [browser_windowStateContainer.js]
 [browser_1234021.js]
 [browser_remoteness_flip_on_restore.js]
 run-if = e10s
+[browser_background_tab_crash.js]
+run-if = e10s && crashreporter
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_background_tab_crash.js
@@ -0,0 +1,221 @@
+"use strict";
+
+/**
+ * These tests the behaviour of the browser when background tabs crash,
+ * while the foreground tab remains.
+ *
+ * The current behavioural rule is this: if only background tabs crash,
+ * then only the first tab shown of that group should show the tab crash
+ * page, and subsequent ones should restore on demand.
+ */
+
+/**
+ * Makes the current browser tab non-remote, and then sets up two remote
+ * background tabs, ensuring that both belong to the same content process.
+ * Callers should pass in a testing function that will execute (and possibly
+ * yield Promises) taking the created background tabs as arguments. Once
+ * the testing function completes, this function will take care of closing
+ * the opened tabs.
+ *
+ * @param testFn (function)
+ *        A Promise-generating function that will be called once the tabs
+ *        are opened and ready.
+ * @return Promise
+ *        Resolves once the testing function completes and the opened tabs
+ *        have been completely closed.
+ */
+function* setupBackgroundTabs(testFn) {
+  const REMOTE_PAGE = "http://www.example.com";
+  const NON_REMOTE_PAGE = "about:robots";
+
+  // Browse the initial tab to a non-remote page, which we'll have in the
+  // foreground.
+  let initialTab = gBrowser.selectedTab;
+  let initialBrowser = initialTab.linkedBrowser;
+  initialBrowser.loadURI(NON_REMOTE_PAGE);
+  yield BrowserTestUtils.browserLoaded(initialBrowser);
+
+  // Open some tabs that should be running in the content process.
+  let tab1 =
+    yield BrowserTestUtils.openNewForegroundTab(gBrowser, REMOTE_PAGE);
+  let remoteBrowser1 = tab1.linkedBrowser;
+  yield TabStateFlusher.flush(remoteBrowser1);
+
+  let tab2 =
+    yield BrowserTestUtils.openNewForegroundTab(gBrowser, REMOTE_PAGE);
+  let remoteBrowser2 = tab2.linkedBrowser;
+  yield TabStateFlusher.flush(remoteBrowser2);
+
+  // Quick sanity check - the two browsers should be remote and share the
+  // same childID, or else this test is not going to work.
+  Assert.ok(remoteBrowser1.isRemoteBrowser,
+            "Browser should be remote in order to crash.");
+  Assert.ok(remoteBrowser2.isRemoteBrowser,
+            "Browser should be remote in order to crash.");
+  Assert.equal(remoteBrowser1.frameLoader.childID,
+               remoteBrowser2.frameLoader.childID,
+               "Both remote browsers should share the same content process.");
+
+  // Now switch back to the non-remote browser...
+  yield BrowserTestUtils.switchTab(gBrowser, initialTab);
+
+  yield testFn([tab1, tab2]);
+
+  yield BrowserTestUtils.removeTab(tab1);
+  yield BrowserTestUtils.removeTab(tab2);
+}
+
+/**
+ * Takes some set of background tabs that are assumed to all belong to
+ * the same content process, and crashes them.
+ *
+ * @param tabs (Array(<xul:tab>))
+ *        The tabs to crash.
+ * @return Promise
+ *        Resolves once the tabs have crashed and entered the pending
+ *        background state.
+ */
+function* crashBackgroundTabs(tabs) {
+  Assert.ok(tabs.length > 0, "Need to crash at least one tab.");
+  for (let tab of tabs) {
+    Assert.ok(tab.linkedBrowser.isRemoteBrowser, "tab is remote");
+  }
+
+  let remotenessChangePromises = tabs.map((t) => {
+    return BrowserTestUtils.waitForEvent(t, "TabRemotenessChange");
+  });
+
+  let tabsRevived = tabs.map((t) => {
+    return promiseTabRestoring(t);
+  });
+
+  yield BrowserTestUtils.crashBrowser(tabs[0].linkedBrowser, false);
+  yield Promise.all(remotenessChangePromises);
+  yield Promise.all(tabsRevived);
+
+  // Both background tabs should now be in the pending restore
+  // state.
+  for (let tab of tabs) {
+    Assert.ok(!tab.linkedBrowser.isRemoteBrowser, "tab is not remote");
+    Assert.ok(!tab.linkedBrowser.hasAttribute("crashed"), "tab is not crashed");
+    Assert.ok(tab.linkedBrowser.hasAttribute("pending"), "tab is pending");
+  }
+}
+
+add_task(function* setup() {
+  // We'll simplify by making sure we only ever one content process for this
+  // test.
+  yield SpecialPowers.pushPrefEnv({ set: [[ "dom.ipc.processCount", 1 ]] });
+
+  // On debug builds, crashing tabs results in much thinking, which
+  // slows down the test and results in intermittent test timeouts,
+  // so we'll pump up the expected timeout for this test.
+  requestLongerTimeout(5);
+});
+
+/**
+ * Tests that if a content process crashes taking down only
+ * background tabs, then the first of those tabs that the user
+ * selects will show the tab crash page, but the rest will restore
+ * on demand.
+ */
+add_task(function* test_background_crash_simple() {
+  yield setupBackgroundTabs(function*([tab1, tab2]) {
+    // Let's crash one of those background tabs now...
+    yield crashBackgroundTabs([tab1, tab2]);
+
+    // Selecting the first tab should now send it to the tab crashed page.
+    let tabCrashedPagePromise =
+      BrowserTestUtils.waitForContentEvent(tab1.linkedBrowser,
+                                           "AboutTabCrashedReady",
+                                           false, null, true);
+    yield BrowserTestUtils.switchTab(gBrowser, tab1);
+    yield tabCrashedPagePromise;
+
+    // Selecting the second tab should restore it.
+    let tabRestored = promiseTabRestored(tab2);
+    yield BrowserTestUtils.switchTab(gBrowser, tab2);
+    yield tabRestored;
+  });
+});
+
+/**
+ * Tests that if a content process crashes taking down only
+ * background tabs, and the user is configured to send backlogged
+ * crash reports automatically, that the tab crashed page is not
+ * shown.
+ */
+add_task(function* test_background_crash_autosubmit_backlogged() {
+  yield SpecialPowers.pushPrefEnv({
+    set: [["browser.crashReports.unsubmittedCheck.autoSubmit", true]],
+  });
+
+  yield setupBackgroundTabs(function*([tab1, tab2]) {
+    // Let's crash one of those background tabs now...
+    yield crashBackgroundTabs([tab1, tab2]);
+
+    // Selecting the first tab should restore it.
+    let tabRestored = promiseTabRestored(tab1);
+    yield BrowserTestUtils.switchTab(gBrowser, tab1);
+    yield tabRestored;
+
+    // Selecting the second tab should restore it.
+    tabRestored = promiseTabRestored(tab2);
+    yield BrowserTestUtils.switchTab(gBrowser, tab2);
+    yield tabRestored;
+  });
+
+  yield SpecialPowers.popPrefEnv();
+});
+
+/**
+ * Tests that if there are two background tab crashes in a row, that
+ * the two sets of background crashes don't interfere with one another.
+ *
+ * Specifically, if we start with two background tabs (1, 2) which crash,
+ * and we visit 1, 1 should go to the tab crashed page. If we then have
+ * two new background tabs (3, 4) crash, visiting 2 should still restore.
+ * Visiting 4 should show us the tab crashed page, and then visiting 3
+ * should restore.
+ */
+add_task(function* test_background_crash_multiple() {
+  let initialTab = gBrowser.selectedTab;
+
+  yield setupBackgroundTabs(function*([tab1, tab2]) {
+    // Let's crash one of those background tabs now...
+    yield crashBackgroundTabs([tab1, tab2]);
+
+    // Selecting the first tab should now send it to the tab crashed page.
+    let tabCrashedPagePromise =
+      BrowserTestUtils.waitForContentEvent(tab1.linkedBrowser,
+                                           "AboutTabCrashedReady",
+                                           false, null, true);
+    yield BrowserTestUtils.switchTab(gBrowser, tab1);
+    yield tabCrashedPagePromise;
+
+    // Now switch back to the original non-remote tab...
+    yield BrowserTestUtils.switchTab(gBrowser, initialTab);
+
+    yield setupBackgroundTabs(function*([tab3, tab4]) {
+      yield crashBackgroundTabs([tab3, tab4]);
+
+      // Selecting the second tab should restore it.
+      let tabRestored = promiseTabRestored(tab2);
+      yield BrowserTestUtils.switchTab(gBrowser, tab2);
+      yield tabRestored;
+
+      // Selecting the fourth tab should now send it to the tab crashed page.
+      let tabCrashedPagePromise =
+        BrowserTestUtils.waitForContentEvent(tab4.linkedBrowser,
+                                             "AboutTabCrashedReady",
+                                             false, null, true);
+      yield BrowserTestUtils.switchTab(gBrowser, tab4);
+      yield tabCrashedPagePromise;
+
+      // Selecting the third tab should restore it.
+      tabRestored = promiseTabRestored(tab3);
+      yield BrowserTestUtils.switchTab(gBrowser, tab3);
+      yield tabRestored;
+    });
+  });
+});
--- a/browser/components/translation/cld2/cld-worker.js
+++ b/browser/components/translation/cld2/cld-worker.js
@@ -1,114 +1,86 @@
-'use strict';var d;d||(d=eval("(function() { try { return Module || {} } catch(e) { return {} } })()"));var aa={},m;for(m in d)d.hasOwnProperty(m)&&(aa[m]=d[m]);var ba="object"===typeof window,ca="function"===typeof importScripts,ea="object"===typeof process&&"function"===typeof require&&!ba&&!ca,fa=!ba&&!ea&&!ca;
-if(ea){d.print||(d.print=function(a){process.stdout.write(a+"\n")});d.printErr||(d.printErr=function(a){process.stderr.write(a+"\n")});var ga=require("fs"),ha=require("path");d.read=function(a,b){a=ha.normalize(a);var c=ga.readFileSync(a);c||a==ha.resolve(a)||(a=path.join(__dirname,"..","src",a),c=ga.readFileSync(a));c&&!b&&(c=c.toString());return c};d.readBinary=function(a){a=d.read(a,!0);a.buffer||(a=new Uint8Array(a));assert(a.buffer);return a};d.load=function(a){ia(read(a))};d.thisProgram||(d.thisProgram=
-1<process.argv.length?process.argv[1].replace(/\\/g,"/"):"unknown-program");d.arguments=process.argv.slice(2);"undefined"!==typeof module&&(module.exports=d);process.on("uncaughtException",function(a){if(!(a instanceof n))throw a;});d.inspect=function(){return"[Emscripten Module object]"}}else if(fa)d.print||(d.print=print),"undefined"!=typeof printErr&&(d.printErr=printErr),d.read="undefined"!=typeof read?read:function(){throw"no read() available (jsc?)";},d.readBinary=function(a){if("function"===
-typeof readbuffer)return new Uint8Array(readbuffer(a));a=read(a,"binary");assert("object"===typeof a);return a},"undefined"!=typeof scriptArgs?d.arguments=scriptArgs:"undefined"!=typeof arguments&&(d.arguments=arguments),eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined");else if(ba||ca)d.read=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},"undefined"!=typeof arguments&&(d.arguments=arguments),"undefined"!==
-typeof console?(d.print||(d.print=function(a){console.log(a)}),d.printErr||(d.printErr=function(a){console.log(a)})):d.print||(d.print=function(){}),ca&&(d.load=importScripts),"undefined"===typeof d.setWindowTitle&&(d.setWindowTitle=function(a){document.title=a});else throw"Unknown runtime environment. Where are we?";function ia(a){eval.call(null,a)}!d.load&&d.read&&(d.load=function(a){ia(d.read(a))});d.print||(d.print=function(){});d.printErr||(d.printErr=d.print);d.arguments||(d.arguments=[]);
-d.thisProgram||(d.thisProgram="./this.program");d.print=d.print;d.C=d.printErr;d.preRun=[];d.postRun=[];for(m in aa)aa.hasOwnProperty(m)&&(d[m]=aa[m]);
-var u={ra:function(a){ja=a},la:function(){return ja},Q:function(){return t},I:function(a){t=a},Z:function(a){switch(a){case "i1":case "i8":return 1;case "i16":return 2;case "i32":return 4;case "i64":return 8;case "float":return 4;case "double":return 8;default:return"*"===a[a.length-1]?u.k:"i"===a[0]?(a=parseInt(a.substr(1)),assert(0===a%8),a/8):0}},ia:function(a){return Math.max(u.Z(a),u.k)},ua:16,Ma:function(a,b){"double"===b||"i64"===b?a&7&&(assert(4===(a&7)),a+=4):assert(0===(a&3));return a},
-Da:function(a,b,c){return c||"i64"!=a&&"double"!=a?a?Math.min(b||(a?u.ia(a):0),u.k):Math.min(b,8):8},n:function(a,b,c){return c&&c.length?(c.splice||(c=Array.prototype.slice.call(c)),c.splice(0,0,b),d["dynCall_"+a].apply(null,c)):d["dynCall_"+a].call(null,b)},F:[],da:function(a){for(var b=0;b<u.F.length;b++)if(!u.F[b])return u.F[b]=a,2*(1+b);throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.";},qa:function(a){u.F[(a-2)/2]=null},q:function(a){u.q.P||
-(u.q.P={});u.q.P[a]||(u.q.P[a]=1,d.C(a))},M:{},Fa:function(a,b){assert(b);u.M[b]||(u.M[b]={});var c=u.M[b];c[a]||(c[a]=function(){return u.n(b,a,arguments)});return c[a]},Ea:function(){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work";},H:function(a){var b=t;t=t+a|0;t=t+15&-16;return b},R:function(a){var b=w;w=w+a|0;w=w+15&-16;return b},p:function(a){var b=A;A=A+a|0;A=A+15&-16;return A>=B&&!ka()?(A=b,0):b},K:function(a,
-b){return Math.ceil(a/(b?b:16))*(b?b:16)},Ja:function(a,b,c){return c?+(a>>>0)+4294967296*+(b>>>0):+(a>>>0)+4294967296*+(b|0)},T:8,k:4,va:0};d.Runtime=u;u.addFunction=u.da;u.removeFunction=u.qa;var C=!1,la,na,ja;function assert(a,b){a||D("Assertion failed: "+b)}function oa(a){var b=d["_"+a];if(!b)try{b=eval("_"+a)}catch(c){}assert(b,"Cannot call unknown function "+a+" (perhaps LLVM optimizations or closure removed it?)");return b}var pa,qa;
-(function(){function a(a){a=a.toString().match(e).slice(1);return{arguments:a[0],body:a[1],returnValue:a[2]}}var b={stackSave:function(){u.Q()},stackRestore:function(){u.I()},arrayToC:function(a){var b=u.H(a.length);ra(a,b);return b},stringToC:function(a){var b=0;null!==a&&void 0!==a&&0!==a&&(b=u.H((a.length<<2)+1),sa(a,b));return b}},c={string:b.stringToC,array:b.arrayToC};qa=function(a,b,e,f,h){a=oa(a);var r=[],z=0;if(f)for(var E=0;E<f.length;E++){var ma=c[e[E]];ma?(0===z&&(z=u.Q()),r[E]=ma(f[E])):
-r[E]=f[E]}e=a.apply(null,r);"string"===b&&(e=F(e));if(0!==z){if(h&&h.async){EmterpreterAsync.wa.push(function(){u.I(z)});return}u.I(z)}return e};var e=/^function\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/,f={},h;for(h in b)b.hasOwnProperty(h)&&(f[h]=a(b[h]));pa=function(b,c,e){e=e||[];var h=oa(b);b=e.every(function(a){return"number"===a});var v="string"!==c;if(v&&b)return h;var r=e.map(function(a,b){return"$"+b});c="(function("+r.join(",")+") {";var z=e.length;if(!b){c+="var stack = "+
-f.stackSave.body+";";for(var E=0;E<z;E++){var ma=r[E],da=e[E];"number"!==da&&(da=f[da+"ToC"],c+="var "+da.arguments+" = "+ma+";",c+=da.body+";",c+=ma+"=("+da.returnValue+");")}}e=a(function(){return h}).returnValue;c+="var ret = "+e+"("+r.join(",")+");";v||(e=a(function(){return F}).returnValue,c+="ret = "+e+"(ret);");b||(c+=f.stackRestore.body.replace("()","(stack)")+";");return eval(c+"return ret})")}})();d.ccall=qa;d.cwrap=pa;
-function ta(a,b,c){c=c||"i8";"*"===c.charAt(c.length-1)&&(c="i32");switch(c){case "i1":G[a>>0]=b;break;case "i8":G[a>>0]=b;break;case "i16":H[a>>1]=b;break;case "i32":I[a>>2]=b;break;case "i64":na=[b>>>0,(la=b,1<=+ua(la)?0<la?(va(+wa(la/4294967296),4294967295)|0)>>>0:~~+xa((la-+(~~la>>>0))/4294967296)>>>0:0)];I[a>>2]=na[0];I[a+4>>2]=na[1];break;case "float":ya[a>>2]=b;break;case "double":za[a>>3]=b;break;default:D("invalid type for setValue: "+c)}}d.setValue=ta;
-function Aa(a,b){b=b||"i8";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":return G[a>>0];case "i8":return G[a>>0];case "i16":return H[a>>1];case "i32":return I[a>>2];case "i64":return I[a>>2];case "float":return ya[a>>2];case "double":return za[a>>3];default:D("invalid type for setValue: "+b)}return null}d.getValue=Aa;d.ALLOC_NORMAL=0;d.ALLOC_STACK=1;d.ALLOC_STATIC=2;d.ALLOC_DYNAMIC=3;d.ALLOC_NONE=4;
-function Ba(a,b,c,e){var f,h;"number"===typeof a?(f=!0,h=a):(f=!1,h=a.length);var k="string"===typeof b?b:null;c=4==c?e:["function"===typeof J?J:u.R,u.H,u.R,u.p][void 0===c?2:c](Math.max(h,k?1:b.length));if(f){e=c;assert(0==(c&3));for(a=c+(h&-4);e<a;e+=4)I[e>>2]=0;for(a=c+h;e<a;)G[e++>>0]=0;return c}if("i8"===k)return a.subarray||a.slice?K.set(a,c):K.set(new Uint8Array(a),c),c;e=0;for(var l,p;e<h;){var q=a[e];"function"===typeof q&&(q=u.Ga(q));f=k||b[e];0===f?e++:("i64"==f&&(f="i32"),ta(c+e,q,f),
-p!==f&&(l=u.Z(f),p=f),e+=l)}return c}d.allocate=Ba;d.getMemory=function(a){return Ca?"undefined"!==typeof L&&!L.g||!Da?u.p(a):J(a):u.R(a)};function F(a,b){if(0===b||!a)return"";for(var c=0,e,f=0;;){e=K[a+f>>0];c|=e;if(0==e&&!b)break;f++;if(b&&f==b)break}b||(b=f);e="";if(128>c){for(;0<b;)c=String.fromCharCode.apply(String,K.subarray(a,a+Math.min(b,1024))),e=e?e+c:c,a+=1024,b-=1024;return e}return d.UTF8ToString(a)}d.Pointer_stringify=F;
-d.AsciiToString=function(a){for(var b="";;){var c=G[a++>>0];if(!c)return b;b+=String.fromCharCode(c)}};d.stringToAscii=function(a,b){return Ea(a,b,!1)};
-function Fa(a,b){for(var c,e,f,h,k,l,p="";;){c=a[b++];if(!c)return p;c&128?(e=a[b++]&63,192==(c&224)?p+=String.fromCharCode((c&31)<<6|e):(f=a[b++]&63,224==(c&240)?c=(c&15)<<12|e<<6|f:(h=a[b++]&63,240==(c&248)?c=(c&7)<<18|e<<12|f<<6|h:(k=a[b++]&63,248==(c&252)?c=(c&3)<<24|e<<18|f<<12|h<<6|k:(l=a[b++]&63,c=(c&1)<<30|e<<24|f<<18|h<<12|k<<6|l))),65536>c?p+=String.fromCharCode(c):(c-=65536,p+=String.fromCharCode(55296|c>>10,56320|c&1023)))):p+=String.fromCharCode(c)}}d.UTF8ArrayToString=Fa;
-d.UTF8ToString=function(a){return Fa(K,a)};
-function Ga(a,b,c,e){if(!(0<e))return 0;var f=c;e=c+e-1;for(var h=0;h<a.length;++h){var k=a.charCodeAt(h);55296<=k&&57343>=k&&(k=65536+((k&1023)<<10)|a.charCodeAt(++h)&1023);if(127>=k){if(c>=e)break;b[c++]=k}else{if(2047>=k){if(c+1>=e)break;b[c++]=192|k>>6}else{if(65535>=k){if(c+2>=e)break;b[c++]=224|k>>12}else{if(2097151>=k){if(c+3>=e)break;b[c++]=240|k>>18}else{if(67108863>=k){if(c+4>=e)break;b[c++]=248|k>>24}else{if(c+5>=e)break;b[c++]=252|k>>30;b[c++]=128|k>>24&63}b[c++]=128|k>>18&63}b[c++]=128|
-k>>12&63}b[c++]=128|k>>6&63}b[c++]=128|k&63}}b[c]=0;return c-f}d.stringToUTF8Array=Ga;d.stringToUTF8=function(a,b,c){return Ga(a,K,b,c)};function Ha(a){for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);55296<=e&&57343>=e&&(e=65536+((e&1023)<<10)|a.charCodeAt(++c)&1023);127>=e?++b:b=2047>=e?b+2:65535>=e?b+3:2097151>=e?b+4:67108863>=e?b+5:b+6}return b}d.lengthBytesUTF8=Ha;d.UTF16ToString=function(a){for(var b=0,c="";;){var e=H[a+2*b>>1];if(0==e)return c;++b;c+=String.fromCharCode(e)}};
-d.stringToUTF16=function(a,b,c){void 0===c&&(c=2147483647);if(2>c)return 0;c-=2;var e=b;c=c<2*a.length?c/2:a.length;for(var f=0;f<c;++f)H[b>>1]=a.charCodeAt(f),b+=2;H[b>>1]=0;return b-e};d.lengthBytesUTF16=function(a){return 2*a.length};d.UTF32ToString=function(a){for(var b=0,c="";;){var e=I[a+4*b>>2];if(0==e)return c;++b;65536<=e?(e=e-65536,c+=String.fromCharCode(55296|e>>10,56320|e&1023)):c+=String.fromCharCode(e)}};
-d.stringToUTF32=function(a,b,c){void 0===c&&(c=2147483647);if(4>c)return 0;var e=b;c=e+c-4;for(var f=0;f<a.length;++f){var h=a.charCodeAt(f);if(55296<=h&&57343>=h)var k=a.charCodeAt(++f),h=65536+((h&1023)<<10)|k&1023;I[b>>2]=h;b+=4;if(b+4>c)break}I[b>>2]=0;return b-e};d.lengthBytesUTF32=function(a){for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);55296<=e&&57343>=e&&++c;b+=4}return b};
-function Ia(a){function b(c,e,f){e=e||Infinity;var h="",k=[],y;if("N"===a[l]){l++;"K"===a[l]&&l++;for(y=[];"E"!==a[l];)if("S"===a[l]){l++;var x=a.indexOf("_",l);y.push(q[a.substring(l,x)||0]||"?");l=x+1}else if("C"===a[l])y.push(y[y.length-1]),l+=2;else{var x=parseInt(a.substr(l)),r=x.toString().length;if(!x||!r){l--;break}var Ab=a.substr(l+r,x);y.push(Ab);q.push(Ab);l+=r+x}l++;y=y.join("::");e--;if(0===e)return c?[y]:y}else if(("K"===a[l]||v&&"L"===a[l])&&l++,x=parseInt(a.substr(l)))r=x.toString().length,
-y=a.substr(l+r,x),l+=r+x;v=!1;"I"===a[l]?(l++,x=b(!0),r=b(!0,1,!0),h+=r[0]+" "+y+"<"+x.join(", ")+">"):h=y;a:for(;l<a.length&&0<e--;)if(y=a[l++],y in p)k.push(p[y]);else switch(y){case "P":k.push(b(!0,1,!0)[0]+"*");break;case "R":k.push(b(!0,1,!0)[0]+"&");break;case "L":l++;x=a.indexOf("E",l)-l;k.push(a.substr(l,x));l+=x+2;break;case "A":x=parseInt(a.substr(l));l+=x.toString().length;if("_"!==a[l])throw"?";l++;k.push(b(!0,1,!0)[0]+" ["+x+"]");break;case "E":break a;default:h+="?"+y;break a}f||1!==
-k.length||"void"!==k[0]||(k=[]);return c?(h&&k.push(h+"?"),k):h+("("+k.join(", ")+")")}var c=!!d.___cxa_demangle;if(c)try{var e=J(a.length);sa(a.substr(1),e);var f=J(4),h=d.___cxa_demangle(e,0,0,f);if(0===Aa(f,"i32")&&h)return F(h)}catch(k){}finally{e&&Ja(e),f&&Ja(f),h&&Ja(h)}var l=3,p={v:"void",b:"bool",c:"char",s:"short",i:"int",l:"long",f:"float",d:"double",w:"wchar_t",a:"signed char",h:"unsigned char",t:"unsigned short",j:"unsigned int",m:"unsigned long",x:"long long",y:"unsigned long long",z:"..."},
-q=[],v=!0,e=a;try{if("Object._main"==a||"_main"==a)return"main()";"number"===typeof a&&(a=F(a));if("_"!==a[0]||"_"!==a[1]||"Z"!==a[2])return a;switch(a[3]){case "n":return"operator new()";case "d":return"operator delete()"}e=b()}catch(r){e+="?"}0<=e.indexOf("?")&&!c&&u.q("warning: a problem occurred in builtin C++ name demangling; build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling");return e}
-function Ka(){return La().replace(/__Z[\w\d_]+/g,function(a){var b=Ia(a);return a===b?a:a+" ["+b+"]"})}function La(){var a=Error();if(!a.stack){try{throw Error(0);}catch(b){a=b}if(!a.stack)return"(no stack trace available)"}return a.stack.toString()}d.stackTrace=function(){return Ka()};function Ma(a){0<a%4096&&(a+=4096-a%4096);return a}var buffer,G,K,H,Na,I,Oa,ya,za;
-function Pa(){d.HEAP8=G=new Int8Array(buffer);d.HEAP16=H=new Int16Array(buffer);d.HEAP32=I=new Int32Array(buffer);d.HEAPU8=K=new Uint8Array(buffer);d.HEAPU16=Na=new Uint16Array(buffer);d.HEAPU32=Oa=new Uint32Array(buffer);d.HEAPF32=ya=new Float32Array(buffer);d.HEAPF64=za=new Float64Array(buffer)}var Qa=0,w=0,Ca=!1,Ra=0,t=0,Sa=0,Ta=0,A=0;
-d.reallocBuffer||(d.reallocBuffer=function(a){var b;try{if(ArrayBuffer.g)b=ArrayBuffer.g(buffer,a);else{var c=G;b=new ArrayBuffer(a);(new Int8Array(b)).set(c)}}catch(e){return!1}return Ua(b)?b:!1});function ka(){var a=Math.pow(2,31);if(A>=a)return!1;for(;B<=A;)if(B<a/2)B=Ma(2*B);else{var b=B;B=Ma((3*B+a)/4);if(B<=b)return!1}B=Math.max(B,16777216);if(B>=a)return!1;a=d.reallocBuffer(B);if(!a)return!1;d.buffer=buffer=a;Pa();return!0}var Va;
-try{Va=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get),Va(new ArrayBuffer(4))}catch(Wa){Va=function(a){return a.byteLength}}for(var Xa=d.TOTAL_STACK||8192,B=d.TOTAL_MEMORY||2097152,M=65536;M<B||M<2*Xa;)M=16777216>M?2*M:M+16777216;M=Math.max(M,16777216);M!==B&&(B=M);assert("undefined"!==typeof Int32Array&&"undefined"!==typeof Float64Array&&!!(new Int32Array(1)).subarray&&!!(new Int32Array(1)).set,"JS engine does not provide full typed array support");
-d.buffer?(buffer=d.buffer,assert(buffer.byteLength===B,"provided buffer should be "+B+" bytes, but it is "+buffer.byteLength)):buffer=new ArrayBuffer(B);Pa();I[0]=255;assert(255===K[0]&&0===K[3],"Typed arrays 2 must be run on a little-endian system");d.HEAP=void 0;d.buffer=buffer;d.HEAP8=G;d.HEAP16=H;d.HEAP32=I;d.HEAPU8=K;d.HEAPU16=Na;d.HEAPU32=Oa;d.HEAPF32=ya;d.HEAPF64=za;
-function Ya(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b();else{var c=b.ga;"number"===typeof c?void 0===b.D?u.n("v",c):u.n("vi",c,[b.D]):c(void 0===b.D?null:b.D)}}}var Za=[],$a=[],ab=[],N=[],bb=[],Da=!1;function cb(a){Za.unshift(a)}d.addOnPreRun=cb;d.addOnInit=function(a){$a.unshift(a)};function db(a){ab.unshift(a)}d.addOnPreMain=db;d.addOnExit=function(a){N.unshift(a)};function eb(a){bb.unshift(a)}d.addOnPostRun=eb;
-function fb(a,b,c){c=Array(0<c?c:Ha(a)+1);a=Ga(a,c,0,c.length);b&&(c.length=a);return c}d.intArrayFromString=fb;d.intArrayToString=function(a){for(var b=[],c=0;c<a.length;c++){var e=a[c];255<e&&(e&=255);b.push(String.fromCharCode(e))}return b.join("")};function sa(a,b,c){a=fb(a,c);for(c=0;c<a.length;)G[b+c>>0]=a[c],c+=1}d.writeStringToMemory=sa;function ra(a,b){for(var c=0;c<a.length;c++)G[b++>>0]=a[c]}d.writeArrayToMemory=ra;
-function Ea(a,b,c){for(var e=0;e<a.length;++e)G[b++>>0]=a.charCodeAt(e);c||(G[b>>0]=0)}d.writeAsciiToMemory=Ea;Math.imul&&-5===Math.imul(4294967295,5)||(Math.imul=function(a,b){var c=a&65535,e=b&65535;return c*e+((a>>>16)*e+c*(b>>>16)<<16)|0});Math.Ha=Math.imul;Math.clz32||(Math.clz32=function(a){a=a>>>0;for(var b=0;32>b;b++)if(a&1<<31-b)return b;return 32});Math.ya=Math.clz32;var ua=Math.abs,xa=Math.ceil,wa=Math.floor,va=Math.min,O=0,gb=null,hb=null;
-function ib(){O++;d.monitorRunDependencies&&d.monitorRunDependencies(O)}d.addRunDependency=ib;function jb(){O--;d.monitorRunDependencies&&d.monitorRunDependencies(O);if(0==O&&(null!==gb&&(clearInterval(gb),gb=null),hb)){var a=hb;hb=null;a()}}d.removeRunDependency=jb;d.preloadedImages={};d.preloadedAudios={};var P=null,kb=[function(a,b){throw"Array index "+a+" out of bounds: [0,"+b+")";}],Qa=8,w=Qa+1097840;$a.push();var P="cld-worker.js.mem",lb=u.K(Ba(12,"i8",2),8);assert(0==lb%8);d._i64Subtract=mb;
-function nb(){return!!nb.g}var ob=0,pb=[],Q={};function qb(a){if(!a||Q[a])return a;for(var b in Q)if(Q[b].U===a)return b;return a}
-function rb(){var a=ob;if(!a)return(R.setTempRet0(0),0)|0;var b=Q[a],c=b.type;if(!c)return(R.setTempRet0(0),a)|0;var e=Array.prototype.slice.call(arguments);d.___cxa_is_pointer_type(c);rb.buffer||(rb.buffer=J(4));I[rb.buffer>>2]=a;for(var a=rb.buffer,f=0;f<e.length;f++)if(e[f]&&d.___cxa_can_catch(e[f],c,a))return a=I[a>>2],b.U=a,(R.setTempRet0(e[f]),a)|0;a=I[a>>2];return(R.setTempRet0(c),a)|0}d._memset=sb;d._bitshift64Shl=tb;function ub(a,b){ub.g||(ub.g={});a in ub.g||(u.n("v",b),ub.g[a]=1)}
-var vb={};function wb(a){d.___errno_location&&(I[d.___errno_location()>>2]=a);return a}var xb=1;
-function yb(a,b){zb=a;Bb=b;if(!Cb)return 1;if(0==a)S=function(){setTimeout(Db,b)},Eb="timeout";else if(1==a)S=function(){Fb(Db)},Eb="rAF";else if(2==a){if(!window.setImmediate){var c=[];window.addEventListener("message",function(a){a.source===window&&"__emcc"===a.data&&(a.stopPropagation(),c.shift()())},!0);window.setImmediate=function(a){c.push(a);window.postMessage("__emcc","*")}}S=function(){window.setImmediate(Db)};Eb="immediate"}return 0}
-function Gb(a,b,c,e,f){d.noExitRuntime=!0;assert(!Cb,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.");Cb=a;Hb=e;var h=Ib;Db=function(){if(!C)if(0<Jb.length){var b=Date.now(),c=Jb.shift();c.ga(c.D);if(Kb){var f=Kb,q=0==f%1?f-1:Math.floor(f);Kb=c.za?q:(8*f+(q+.5))/9}console.log('main loop blocker "'+c.name+'" took '+(Date.now()-b)+" ms");Lb();h<Ib||setTimeout(Db,
-0)}else h<Ib||(Mb=Mb+1|0,1==zb&&1<Bb&&0!=Mb%Bb?S():("timeout"===Eb&&d.L&&(d.C("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!"),Eb=""),Nb(function(){"undefined"!==typeof e?u.n("vi",a,[e]):u.n("v",a)}),h<Ib||("object"===typeof SDL&&SDL.audio&&SDL.audio.pa&&SDL.audio.pa(),S())))};f||(b&&0<b?yb(0,1E3/b):yb(1,1),S());
-if(c)throw"SimulateInfiniteLoop";}var S=null,Eb="",Ib=0,Cb=null,Hb=0,zb=0,Bb=0,Mb=0,Jb=[];function Lb(){if(d.setStatus){var a=d.statusMessage||"Please wait...",b=Kb,c=Ob.Ca;b?b<c?d.setStatus(a+" ("+(c-b)+"/"+c+")"):d.setStatus(a):d.setStatus("")}}function Nb(a){if(!(C||d.preMainLoop&&!1===d.preMainLoop())){try{a()}catch(b){if(b instanceof n)return;b&&"object"===typeof b&&b.stack&&d.C("exception thrown: "+[b,b.stack]);throw b;}d.postMainLoop&&d.postMainLoop()}}var Ob={},Db,Kb,Pb=!1,Qb=!1,Rb=[];
-function Sb(){function a(){Qb=document.pointerLockElement===c||document.mozPointerLockElement===c||document.webkitPointerLockElement===c||document.msPointerLockElement===c}d.preloadPlugins||(d.preloadPlugins=[]);if(!Tb){Tb=!0;try{Ub=!0}catch(b){Ub=!1,console.log("warning: no blob constructor, cannot create blobs with mimetypes")}Vb="undefined"!=typeof MozBlobBuilder?MozBlobBuilder:"undefined"!=typeof WebKitBlobBuilder?WebKitBlobBuilder:Ub?null:console.log("warning: no BlobBuilder");Wb="undefined"!=
-typeof window?window.URL?window.URL:window.webkitURL:void 0;d.$||"undefined"!==typeof Wb||(console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."),d.$=!0);d.preloadPlugins.push({canHandle:function(a){return!d.$&&/\.(jpg|jpeg|png|bmp)$/i.test(a)},handle:function(a,b,c,k){var l=null;if(Ub)try{l=new Blob([a],{type:Xb(b)}),l.size!==a.length&&(l=new Blob([(new Uint8Array(a)).buffer],{type:Xb(b)}))}catch(p){u.q("Blob constructor present but fails: "+
-p+"; falling back to blob builder")}l||(l=new Vb,l.append((new Uint8Array(a)).buffer),l=l.getBlob());var q=Wb.createObjectURL(l),v=new Image;v.onload=function(){assert(v.complete,"Image "+b+" could not be decoded");var k=document.createElement("canvas");k.width=v.width;k.height=v.height;k.getContext("2d").drawImage(v,0,0);d.preloadedImages[b]=k;Wb.revokeObjectURL(q);c&&c(a)};v.onerror=function(){console.log("Image "+q+" could not be decoded");k&&k()};v.src=q}});d.preloadPlugins.push({canHandle:function(a){return!d.La&&
-a.substr(-4)in{".ogg":1,".wav":1,".mp3":1}},handle:function(a,b,c,k){function l(k){q||(q=!0,d.preloadedAudios[b]=k,c&&c(a))}function p(){q||(q=!0,d.preloadedAudios[b]=new Audio,k&&k())}var q=!1;if(Ub){try{var v=new Blob([a],{type:Xb(b)})}catch(r){return p()}var v=Wb.createObjectURL(v),z=new Audio;z.addEventListener("canplaythrough",function(){l(z)},!1);z.onerror=function(){if(!q){console.log("warning: browser could not fully decode audio "+b+", trying slower base64 approach");for(var c="",h=0,k=0,
-p=0;p<a.length;p++)for(h=h<<8|a[p],k+=8;6<=k;)var r=h>>k-6&63,k=k-6,c=c+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[r];2==k?(c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(h&3)<<4],c+="=="):4==k&&(c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(h&15)<<2],c+="=");z.src="data:audio/x-"+b.substr(-3)+";base64,"+c;l(z)}};z.src=v;Yb(function(){l(z)})}else return p()}});var c=d.canvas;c&&(c.O=c.requestPointerLock||c.mozRequestPointerLock||
-c.webkitRequestPointerLock||c.msRequestPointerLock||function(){},c.X=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},c.X=c.X.bind(document),document.addEventListener("pointerlockchange",a,!1),document.addEventListener("mozpointerlockchange",a,!1),document.addEventListener("webkitpointerlockchange",a,!1),document.addEventListener("mspointerlockchange",a,!1),d.elementPointerLock&&c.addEventListener("click",function(a){!Qb&&
-c.O&&(c.O(),a.preventDefault())},!1))}}function Zb(a,b,c,e){if(b&&d.L&&a==d.canvas)return d.L;var f,h;if(b){h={antialias:!1,alpha:!1};if(e)for(var k in e)h[k]=e[k];if(h=GL.createContext(a,h))f=GL.getContext(h).ta;a.style.backgroundColor="black"}else f=a.getContext("2d");if(!f)return null;c&&(b||assert("undefined"===typeof GLctx,"cannot set in module if GLctx is used, but we are a non-GL context that would replace it"),d.L=f,b&&GL.Ka(h),d.Na=b,Rb.forEach(function(a){a()}),Sb());return f}
-var $b=!1,ac=void 0,bc=void 0;
-function cc(a,b,c){function e(){Pb=!1;var a=f.parentNode;(document.webkitFullScreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.mozFullscreenElement||document.fullScreenElement||document.fullscreenElement||document.msFullScreenElement||document.msFullscreenElement||document.webkitCurrentFullScreenElement)===a?(f.V=document.cancelFullScreen||document.mozCancelFullScreen||document.webkitCancelFullScreen||document.msExitFullscreen||document.exitFullscreen||function(){},
-f.V=f.V.bind(document),ac&&f.O(),Pb=!0,bc&&dc()):(a.parentNode.insertBefore(f,a),a.parentNode.removeChild(a),bc&&ec());if(d.onFullScreen)d.onFullScreen(Pb);fc(f)}ac=a;bc=b;gc=c;"undefined"===typeof ac&&(ac=!0);"undefined"===typeof bc&&(bc=!1);"undefined"===typeof gc&&(gc=null);var f=d.canvas;$b||($b=!0,document.addEventListener("fullscreenchange",e,!1),document.addEventListener("mozfullscreenchange",e,!1),document.addEventListener("webkitfullscreenchange",e,!1),document.addEventListener("MSFullscreenChange",
-e,!1));var h=document.createElement("div");f.parentNode.insertBefore(h,f);h.appendChild(f);h.g=h.requestFullScreen||h.mozRequestFullScreen||h.msRequestFullscreen||(h.webkitRequestFullScreen?function(){h.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null);c?h.g({Oa:c}):h.g()}var hc=0;function ic(a){var b=Date.now();if(0===hc)hc=b+1E3/60;else for(;b+2>=hc;)hc+=1E3/60;b=Math.max(hc-b,0);setTimeout(a,b)}
-function Fb(a){"undefined"===typeof window?ic(a):(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||ic),window.requestAnimationFrame(a))}function Yb(a){d.noExitRuntime=!0;setTimeout(function(){C||a()},1E4)}
-function Xb(a){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[a.substr(a.lastIndexOf(".")+1)]}function jc(a,b,c){var e=new XMLHttpRequest;e.open("GET",a,!0);e.responseType="arraybuffer";e.onload=function(){200==e.status||0==e.status&&e.response?b(e.response):c()};e.onerror=c;e.send(null)}
-function kc(a){var b=P,c=lc;jc(b,function(a){assert(a,'Loading data file "'+b+'" failed (no arrayBuffer).');c(new Uint8Array(a));jb()},function(){if(a)a();else throw'Loading data file "'+b+'" failed.';});ib()}var mc=[];function nc(){var a=d.canvas;mc.forEach(function(b){b(a.width,a.height)})}function dc(){if("undefined"!=typeof SDL){var a=Oa[SDL.screen+0*u.k>>2];I[SDL.screen+0*u.k>>2]=a|8388608}nc()}
-function ec(){if("undefined"!=typeof SDL){var a=Oa[SDL.screen+0*u.k>>2];I[SDL.screen+0*u.k>>2]=a&-8388609}nc()}
-function fc(a,b,c){b&&c?(a.sa=b,a.oa=c):(b=a.sa,c=a.oa);var e=b,f=c;d.forcedAspectRatio&&0<d.forcedAspectRatio&&(e/f<d.forcedAspectRatio?e=Math.round(f*d.forcedAspectRatio):f=Math.round(e/d.forcedAspectRatio));if((document.webkitFullScreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.mozFullscreenElement||document.fullScreenElement||document.fullscreenElement||document.msFullScreenElement||document.msFullscreenElement||document.webkitCurrentFullScreenElement)===
-a.parentNode&&"undefined"!=typeof screen)var h=Math.min(screen.width/e,screen.height/f),e=Math.round(e*h),f=Math.round(f*h);bc?(a.width!=e&&(a.width=e),a.height!=f&&(a.height=f),"undefined"!=typeof a.style&&(a.style.removeProperty("width"),a.style.removeProperty("height"))):(a.width!=b&&(a.width=b),a.height!=c&&(a.height=c),"undefined"!=typeof a.style&&(e!=b||f!=c?(a.style.setProperty("width",e+"px","important"),a.style.setProperty("height",f+"px","important")):(a.style.removeProperty("width"),a.style.removeProperty("height"))))}
-var Tb,Ub,Vb,Wb,gc;function J(a){return u.p(a+8)+8&4294967288}d._malloc=J;d._i64Add=oc;d._bitshift64Lshr=pc;function qc(a,b){N.push(function(){u.n("vi",a,[b])});qc.level=N.length}d._memcpy=rc;var sc=0;function tc(){sc+=4;return I[sc-4>>2]}var uc={};function L(a){L.g||(A=Ma(A),L.g=!0,assert(u.p),L.u=u.p,u.p=function(){D("cannot dynamically allocate, sbrk now has control")});var b=A;return 0==a||L.u(a)?b:4294967295}d._memmove=vc;
-function wc(a,b){sc=b;try{tc();var c=tc(),e=tc(),f=0;wc.buffer||(wc.buffer=[]);for(var h=wc.buffer,k=0;k<e;k++){for(var l=I[c+8*k>>2],p=I[c+(8*k+4)>>2],q=0;q<p;q++){var v=K[l+q];0===v||10===v?(d.print(Fa(h,0)),h.length=0):h.push(v)}f+=p}return f}catch(r){return"undefined"!==typeof FS&&r instanceof FS.S||D(r),-r.W}}d.requestFullScreen=function(a,b,c){cc(a,b,c)};d.requestAnimationFrame=function(a){Fb(a)};d.setCanvasSize=function(a,b,c){fc(d.canvas,a,b);c||nc()};d.pauseMainLoop=function(){S=null;Ib++};
-d.resumeMainLoop=function(){Ib++;var a=zb,b=Bb,c=Cb;Cb=null;Gb(c,0,!1,Hb,!0);yb(a,b);S()};d.getUserMedia=function(){window.g||(window.g=navigator.getUserMedia||navigator.mozGetUserMedia);window.g(void 0)};d.createContext=function(a,b,c,e){return Zb(a,b,c,e)};Ra=t=u.K(w);Ca=!0;Sa=Ra+Xa;Ta=A=u.K(Sa);assert(Ta<B,"TOTAL_MEMORY not big enough for stack");
-var xc=Ba([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,
-0,1,0,3,0,1,0,2,0,1,0],"i8",3);d.ea={Math:Math,Int8Array:Int8Array,Int16Array:Int16Array,Int32Array:Int32Array,Uint8Array:Uint8Array,Uint16Array:Uint16Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array,NaN:NaN,Infinity:Infinity,byteLength:Va};
-d.fa={abort:D,assert:assert,invoke_iiii:function(a,b,c,e){try{return d.dynCall_iiii(a,b,c,e)}catch(f){if("number"!==typeof f&&"longjmp"!==f)throw f;R.setThrew(1,0)}},invoke_viiiii:function(a,b,c,e,f,h){try{d.dynCall_viiiii(a,b,c,e,f,h)}catch(k){if("number"!==typeof k&&"longjmp"!==k)throw k;R.setThrew(1,0)}},invoke_vi:function(a,b){try{d.dynCall_vi(a,b)}catch(c){if("number"!==typeof c&&"longjmp"!==c)throw c;R.setThrew(1,0)}},invoke_ii:function(a,b){try{return d.dynCall_ii(a,b)}catch(c){if("number"!==
-typeof c&&"longjmp"!==c)throw c;R.setThrew(1,0)}},invoke_v:function(a){try{d.dynCall_v(a)}catch(b){if("number"!==typeof b&&"longjmp"!==b)throw b;R.setThrew(1,0)}},invoke_viiiiii:function(a,b,c,e,f,h,k){try{d.dynCall_viiiiii(a,b,c,e,f,h,k)}catch(l){if("number"!==typeof l&&"longjmp"!==l)throw l;R.setThrew(1,0)}},invoke_viiii:function(a,b,c,e,f){try{d.dynCall_viiii(a,b,c,e,f)}catch(h){if("number"!==typeof h&&"longjmp"!==h)throw h;R.setThrew(1,0)}},_pthread_cleanup_pop:function(){assert(qc.level==N.length,
-"cannot pop if something else added meanwhile!");N.pop();qc.level=N.length},_abort:function(){d.abort()},___setErrNo:wb,___gxx_personality_v0:function(){},___assert_fail:function(a,b,c,e){C=!0;throw"Assertion failed: "+F(a)+", at: "+[b?F(b):"unknown filename",c,e?F(e):"unknown function"]+" at "+Ka();},___cxa_allocate_exception:function(a){return J(a)},__ZSt18uncaught_exceptionv:nb,_emscripten_set_main_loop_timing:yb,_sbrk:L,___cxa_begin_catch:function(a){nb.g--;pb.push(a);var b=qb(a);b&&Q[b].aa++;
-return a},_emscripten_memcpy_big:function(a,b,c){K.set(K.subarray(b,b+c),a);return a},___resumeException:function(a){ob||(ob=a);var b=qb(a);b&&(Q[b].aa=0);throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";},___cxa_find_matching_catch:rb,_sysconf:function(a){switch(a){case 30:return 4096;case 85:return M/4096;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;
+'use strict';var c;c||(c=eval("(function() { try { return Module || {} } catch(e) { return {} } })()"));var aa={},g;for(g in c)c.hasOwnProperty(g)&&(aa[g]=c[g]);var ba=!1,k=!1,m=!1,ca=!1;
+if(c.ENVIRONMENT)if("WEB"===c.ENVIRONMENT)ba=!0;else if("WORKER"===c.ENVIRONMENT)k=!0;else if("NODE"===c.ENVIRONMENT)m=!0;else if("SHELL"===c.ENVIRONMENT)ca=!0;else throw Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");else ba="object"===typeof window,k="function"===typeof importScripts,m="object"===typeof process&&"function"===typeof require&&!ba&&!k,ca=!ba&&!m&&!k;
+if(m){c.print||(c.print=console.log);c.printErr||(c.printErr=console.warn);var da,ea;c.read=function(a,b){da||(da=require("fs"));ea||(ea=require("path"));a=ea.normalize(a);var d=da.readFileSync(a);d||a==ea.resolve(a)||(a=path.join(__dirname,"..","src",a),d=da.readFileSync(a));d&&!b&&(d=d.toString());return d};c.readBinary=function(a){a=c.read(a,!0);a.buffer||(a=new Uint8Array(a));assert(a.buffer);return a};c.load=function(a){fa(read(a))};c.thisProgram||(c.thisProgram=1<process.argv.length?process.argv[1].replace(/\\/g,
+"/"):"unknown-program");c.arguments=process.argv.slice(2);"undefined"!==typeof module&&(module.exports=c);process.on("uncaughtException",function(a){if(!(a instanceof n))throw a;});c.inspect=function(){return"[Emscripten Module object]"}}else if(ca)c.print||(c.print=print),"undefined"!=typeof printErr&&(c.printErr=printErr),c.read="undefined"!=typeof read?read:function(){throw"no read() available (jsc?)";},c.readBinary=function(a){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(a));
+a=read(a,"binary");assert("object"===typeof a);return a},"undefined"!=typeof scriptArgs?c.arguments=scriptArgs:"undefined"!=typeof arguments&&(c.arguments=arguments),eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined");else if(ba||k)c.read=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},c.readAsync=function(a,b,d){var e=new XMLHttpRequest;e.open("GET",a,!0);e.responseType="arraybuffer";e.onload=function(){200==
+e.status||0==e.status&&e.response?b(e.response):d()};e.onerror=d;e.send(null)},"undefined"!=typeof arguments&&(c.arguments=arguments),"undefined"!==typeof console?(c.print||(c.print=function(a){console.log(a)}),c.printErr||(c.printErr=function(a){console.warn(a)})):c.print||(c.print=function(){}),k&&(c.load=importScripts),"undefined"===typeof c.setWindowTitle&&(c.setWindowTitle=function(a){document.title=a});else throw"Unknown runtime environment. Where are we?";function fa(a){eval.call(null,a)}
+!c.load&&c.read&&(c.load=function(a){fa(c.read(a))});c.print||(c.print=function(){});c.printErr||(c.printErr=c.print);c.arguments||(c.arguments=[]);c.thisProgram||(c.thisProgram="./this.program");c.print=c.print;c.u=c.printErr;c.preRun=[];c.postRun=[];for(g in aa)aa.hasOwnProperty(g)&&(c[g]=aa[g]);
+var aa=void 0,t={V:function(a){tempRet0=a},R:function(){return tempRet0},w:function(){return p},o:function(a){p=a},H:function(a){switch(a){case "i1":case "i8":return 1;case "i16":return 2;case "i32":return 4;case "i64":return 8;case "float":return 4;case "double":return 8;default:return"*"===a[a.length-1]?t.q:"i"===a[0]?(a=parseInt(a.substr(1)),assert(0===a%8),a/8):0}},O:function(a){return Math.max(t.H(a),t.q)},W:16,la:function(a,b){"double"===b||"i64"===b?a&7&&(assert(4===(a&7)),a+=4):assert(0===
+(a&3));return a},ea:function(a,b,d){return d||"i64"!=a&&"double"!=a?a?Math.min(b||(a?t.O(a):0),t.q):Math.min(b,8):8},h:function(a,b,d){return d&&d.length?(d.splice||(d=Array.prototype.slice.call(d)),d.splice(0,0,b),c["dynCall_"+a].apply(null,d)):c["dynCall_"+a].call(null,b)},l:[],K:function(a){for(var b=0;b<t.l.length;b++)if(!t.l[b])return t.l[b]=a,2*(1+b);throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.";},U:function(a){t.l[(a-2)/2]=null},k:function(a){t.k.v||
+(t.k.v={});t.k.v[a]||(t.k.v[a]=1,c.u(a))},s:{},ga:function(a,b){assert(b);t.s[b]||(t.s[b]={});var d=t.s[b];d[a]||(d[a]=function(){return t.h(b,a,arguments)});return d[a]},fa:function(){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work";},n:function(a){var b=p;p=p+a|0;p=p+15&-16;return b},A:function(a){var b=u;u=u+a|0;u=u+15&-16;return b},d:function(a){var b=v;v=v+a|0;v=v+15&-16;return v>=w&&!ga()?(v=b,0):b},F:function(a,
+b){return Math.ceil(a/(b?b:16))*(b?b:16)},ka:function(a,b,d){return d?+(a>>>0)+4294967296*+(b>>>0):+(a>>>0)+4294967296*+(b|0)},C:8,q:4,X:0};c.Runtime=t;t.addFunction=t.K;t.removeFunction=t.U;var ia=!1;function assert(a,b){a||y("Assertion failed: "+b)}function ja(a){var b=c["_"+a];if(!b)try{b=eval("_"+a)}catch(d){}assert(b,"Cannot call unknown function "+a+" (perhaps LLVM optimizations or closure removed it?)");return b}var ka,la;
+(function(){function a(a){a=a.toString().match(f).slice(1);return{arguments:a[0],body:a[1],returnValue:a[2]}}function b(){if(!l){l={};for(var b in d)d.hasOwnProperty(b)&&(l[b]=a(d[b]))}}var d={stackSave:function(){t.w()},stackRestore:function(){t.o()},arrayToC:function(a){var b=t.n(a.length);ma(a,b);return b},stringToC:function(a){var b=0;null!==a&&void 0!==a&&0!==a&&(b=t.n((a.length<<2)+1),na(a,b));return b}},e={string:d.stringToC,array:d.arrayToC};la=function(a,b,d,f,l){a=ja(a);var O=[],P=0;if(f)for(var x=
+0;x<f.length;x++){var ha=e[d[x]];ha?(0===P&&(P=t.w()),O[x]=ha(f[x])):O[x]=f[x]}d=a.apply(null,O);"string"===b&&(d=z(d));if(0!==P){if(l&&l.async){EmterpreterAsync.Y.push(function(){t.o(P)});return}t.o(P)}return d};var f=/^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/,l=null;ka=function(d,e,f){f=f||[];var A=ja(d);d=f.every(function(a){return"number"===a});var X="string"!==e;if(X&&d)return A;var O=f.map(function(a,b){return"$"+b});e="(function("+O.join(",")+
+") {";var P=f.length;if(!d){b();e+="var stack = "+l.stackSave.body+";";for(var x=0;x<P;x++){var ha=O[x],Y=f[x];"number"!==Y&&(Y=l[Y+"ToC"],e+="var "+Y.arguments+" = "+ha+";",e+=Y.body+";",e+=ha+"=("+Y.returnValue+");")}}f=a(function(){return A}).returnValue;e+="var ret = "+f+"("+O.join(",")+");";X||(f=a(function(){return z}).returnValue,e+="ret = "+f+"(ret);");d||(b(),e+=l.stackRestore.body.replace("()","(stack)")+";");return eval(e+"return ret})")}})();c.ccall=la;c.cwrap=ka;
+function oa(a,b,d){d=d||"i8";"*"===d.charAt(d.length-1)&&(d="i32");switch(d){case "i1":B[a>>0]=b;break;case "i8":B[a>>0]=b;break;case "i16":pa[a>>1]=b;break;case "i32":C[a>>2]=b;break;case "i64":tempI64=[b>>>0,(tempDouble=b,1<=+qa(tempDouble)?0<tempDouble?(ra(+sa(tempDouble/4294967296),4294967295)|0)>>>0:~~+ta((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)];C[a>>2]=tempI64[0];C[a+4>>2]=tempI64[1];break;case "float":ua[a>>2]=b;break;case "double":va[a>>3]=b;break;default:y("invalid type for setValue: "+
+d)}}c.setValue=oa;function wa(a,b){b=b||"i8";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":return B[a>>0];case "i8":return B[a>>0];case "i16":return pa[a>>1];case "i32":return C[a>>2];case "i64":return C[a>>2];case "float":return ua[a>>2];case "double":return va[a>>3];default:y("invalid type for setValue: "+b)}return null}c.getValue=wa;c.ALLOC_NORMAL=0;c.ALLOC_STACK=1;c.ALLOC_STATIC=2;c.ALLOC_DYNAMIC=3;c.ALLOC_NONE=4;
+function xa(a,b,d,e){var f,l;"number"===typeof a?(f=!0,l=a):(f=!1,l=a.length);var h="string"===typeof b?b:null;d=4==d?e:["function"===typeof D?D:t.A,t.n,t.A,t.d][void 0===d?2:d](Math.max(l,h?1:b.length));if(f){e=d;assert(0==(d&3));for(a=d+(l&-4);e<a;e+=4)C[e>>2]=0;for(a=d+l;e<a;)B[e++>>0]=0;return d}if("i8"===h)return a.subarray||a.slice?E.set(a,d):E.set(new Uint8Array(a),d),d;e=0;for(var q,r;e<l;){var A=a[e];"function"===typeof A&&(A=t.ha(A));f=h||b[e];0===f?e++:("i64"==f&&(f="i32"),oa(d+e,A,f),
+r!==f&&(q=t.H(f),r=f),e+=q)}return d}c.allocate=xa;c.getMemory=function(a){return ya?"undefined"!==typeof F&&!F.b||!za?t.d(a):D(a):t.A(a)};function z(a,b){if(0===b||!a)return"";for(var d=0,e,f=0;;){e=E[a+f>>0];d|=e;if(0==e&&!b)break;f++;if(b&&f==b)break}b||(b=f);e="";if(128>d){for(;0<b;)d=String.fromCharCode.apply(String,E.subarray(a,a+Math.min(b,1024))),e=e?e+d:d,a+=1024,b-=1024;return e}return c.UTF8ToString(a)}c.Pointer_stringify=z;
+c.AsciiToString=function(a){for(var b="";;){var d=B[a++>>0];if(!d)return b;b+=String.fromCharCode(d)}};c.stringToAscii=function(a,b){return Aa(a,b,!1)};
+function Ba(a,b){for(var d,e,f,l,h,q,r="";;){d=a[b++];if(!d)return r;d&128?(e=a[b++]&63,192==(d&224)?r+=String.fromCharCode((d&31)<<6|e):(f=a[b++]&63,224==(d&240)?d=(d&15)<<12|e<<6|f:(l=a[b++]&63,240==(d&248)?d=(d&7)<<18|e<<12|f<<6|l:(h=a[b++]&63,248==(d&252)?d=(d&3)<<24|e<<18|f<<12|l<<6|h:(q=a[b++]&63,d=(d&1)<<30|e<<24|f<<18|l<<12|h<<6|q))),65536>d?r+=String.fromCharCode(d):(d-=65536,r+=String.fromCharCode(55296|d>>10,56320|d&1023)))):r+=String.fromCharCode(d)}}c.UTF8ArrayToString=Ba;
+c.UTF8ToString=function(a){return Ba(E,a)};
+function Ca(a,b,d,e){if(!(0<e))return 0;var f=d;e=d+e-1;for(var l=0;l<a.length;++l){var h=a.charCodeAt(l);55296<=h&&57343>=h&&(h=65536+((h&1023)<<10)|a.charCodeAt(++l)&1023);if(127>=h){if(d>=e)break;b[d++]=h}else{if(2047>=h){if(d+1>=e)break;b[d++]=192|h>>6}else{if(65535>=h){if(d+2>=e)break;b[d++]=224|h>>12}else{if(2097151>=h){if(d+3>=e)break;b[d++]=240|h>>18}else{if(67108863>=h){if(d+4>=e)break;b[d++]=248|h>>24}else{if(d+5>=e)break;b[d++]=252|h>>30;b[d++]=128|h>>24&63}b[d++]=128|h>>18&63}b[d++]=128|
+h>>12&63}b[d++]=128|h>>6&63}b[d++]=128|h&63}}b[d]=0;return d-f}c.stringToUTF8Array=Ca;c.stringToUTF8=function(a,b,d){return Ca(a,E,b,d)};function Da(a){for(var b=0,d=0;d<a.length;++d){var e=a.charCodeAt(d);55296<=e&&57343>=e&&(e=65536+((e&1023)<<10)|a.charCodeAt(++d)&1023);127>=e?++b:b=2047>=e?b+2:65535>=e?b+3:2097151>=e?b+4:67108863>=e?b+5:b+6}return b}c.lengthBytesUTF8=Da;
+function Ea(){return Fa().replace(/__Z[\w\d_]+/g,function(a){var b;a:{if(c.___cxa_demangle)try{var d=D(a.length);na(a.substr(1),d);var e=D(4),f=c.___cxa_demangle(d,0,0,e);if(0===wa(e,"i32")&&f){b=z(f);break a}}catch(l){b=a;break a}finally{d&&Ga(d),e&&Ga(e),f&&Ga(f)}t.k("warning: build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling");b=a}return a===b?a:a+" ["+b+"]"})}
+function Fa(){var a=Error();if(!a.stack){try{throw Error(0);}catch(b){a=b}if(!a.stack)return"(no stack trace available)"}return a.stack.toString()}c.stackTrace=function(){return Ea()};function Ha(a){0<a%4096&&(a+=4096-a%4096);return a}var buffer,B,E,pa,Ia,C,Ja,ua,va;
+function Ka(){c.HEAP8=B=new Int8Array(buffer);c.HEAP16=pa=new Int16Array(buffer);c.HEAP32=C=new Int32Array(buffer);c.HEAPU8=E=new Uint8Array(buffer);c.HEAPU16=Ia=new Uint16Array(buffer);c.HEAPU32=Ja=new Uint32Array(buffer);c.HEAPF32=ua=new Float32Array(buffer);c.HEAPF64=va=new Float64Array(buffer)}var La=0,u=0,ya=!1,Ma=0,p=0,Na=0,v=0;
+c.reallocBuffer||(c.reallocBuffer=function(a){var b;try{if(ArrayBuffer.b)b=ArrayBuffer.b(buffer,a);else{var d=B;b=new ArrayBuffer(a);(new Int8Array(b)).set(d)}}catch(e){return!1}return Oa(b)?b:!1});function ga(){var a=Math.pow(2,31);if(v>=a)return!1;for(;w<=v;)if(w<a/2)w=Ha(2*w);else{var b=w;w=Ha((3*w+a)/4);if(w<=b)return!1}w=Math.max(w,16777216);if(w>=a)return!1;a=c.reallocBuffer(w);if(!a)return!1;c.buffer=buffer=a;Ka();return!0}var Pa;
+try{Pa=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get),Pa(new ArrayBuffer(4))}catch(Qa){Pa=function(a){return a.byteLength}}for(var Ra=c.TOTAL_STACK||8192,w=c.TOTAL_MEMORY||2097152,G=65536;G<w||G<2*Ra;)G=16777216>G?2*G:G+16777216;G=Math.max(G,16777216);G!==w&&(w=G);c.buffer?buffer=c.buffer:buffer=new ArrayBuffer(w);Ka();C[0]=255;if(255!==E[0]||0!==E[3])throw"Typed arrays 2 must be run on a little-endian system";c.HEAP=void 0;c.buffer=buffer;
+c.HEAP8=B;c.HEAP16=pa;c.HEAP32=C;c.HEAPU8=E;c.HEAPU16=Ia;c.HEAPU32=Ja;c.HEAPF32=ua;c.HEAPF64=va;function H(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b();else{var d=b.da;"number"===typeof d?void 0===b.r?t.h("v",d):t.h("vi",d,[b.r]):d(void 0===b.r?null:b.r)}}}var Sa=[],Ta=[],Ua=[],I=[],Va=[],za=!1;function Wa(a){Sa.unshift(a)}c.addOnPreRun=Wa;c.addOnInit=function(a){Ta.unshift(a)};function Xa(a){Ua.unshift(a)}c.addOnPreMain=Xa;c.addOnExit=function(a){I.unshift(a)};
+function Ya(a){Va.unshift(a)}c.addOnPostRun=Ya;function Za(a,b,d){d=Array(0<d?d:Da(a)+1);a=Ca(a,d,0,d.length);b&&(d.length=a);return d}c.intArrayFromString=Za;c.intArrayToString=function(a){for(var b=[],d=0;d<a.length;d++){var e=a[d];255<e&&(e&=255);b.push(String.fromCharCode(e))}return b.join("")};function na(a,b,d){a=Za(a,d);for(d=0;d<a.length;)B[b+d>>0]=a[d],d+=1}c.writeStringToMemory=na;function ma(a,b){for(var d=0;d<a.length;d++)B[b++>>0]=a[d]}c.writeArrayToMemory=ma;
+function Aa(a,b,d){for(var e=0;e<a.length;++e)B[b++>>0]=a.charCodeAt(e);d||(B[b>>0]=0)}c.writeAsciiToMemory=Aa;Math.imul&&-5===Math.imul(4294967295,5)||(Math.imul=function(a,b){var d=a&65535,e=b&65535;return d*e+((a>>>16)*e+d*(b>>>16)<<16)|0});Math.ia=Math.imul;Math.clz32||(Math.clz32=function(a){a=a>>>0;for(var b=0;32>b;b++)if(a&1<<31-b)return b;return 32});Math.$=Math.clz32;var qa=Math.abs,ta=Math.ceil,sa=Math.floor,ra=Math.min,J=0,$a=null,ab=null;
+function bb(){J++;c.monitorRunDependencies&&c.monitorRunDependencies(J)}c.addRunDependency=bb;function cb(){J--;c.monitorRunDependencies&&c.monitorRunDependencies(J);if(0==J&&(null!==$a&&(clearInterval($a),$a=null),ab)){var a=ab;ab=null;a()}}c.removeRunDependency=cb;c.preloadedImages={};c.preloadedAudios={};var K=null,db=[function(a,b){throw"Array index "+a+" out of bounds: [0,"+b+")";}],La=8,u=La+1097872;Ta.push();var K="cld-worker.js.mem",eb=u,u=u+16;c._i64Add=fb;c._i64Subtract=gb;
+function hb(a){c.___errno_location&&(C[c.___errno_location()>>2]=a);return a}function ib(){return!!ib.b}var jb=0,kb=[],L={};function lb(a){if(!a||L[a])return a;for(var b in L)if(L[b].D===a)return b;return a}
+function mb(){var a=jb;if(!a)return(M.setTempRet0(0),0)|0;var b=L[a],d=b.type;if(!d)return(M.setTempRet0(0),a)|0;var e=Array.prototype.slice.call(arguments);c.___cxa_is_pointer_type(d);mb.buffer||(mb.buffer=D(4));C[mb.buffer>>2]=a;for(var a=mb.buffer,f=0;f<e.length;f++)if(e[f]&&c.___cxa_can_catch(e[f],d,a))return a=C[a>>2],b.D=a,(M.setTempRet0(e[f]),a)|0;a=C[a>>2];return(M.setTempRet0(d),a)|0}c._memset=nb;function ob(a,b){I.push(function(){t.h("vi",a,[b])});ob.level=I.length}c._bitshift64Lshr=pb;
+c._bitshift64Shl=qb;function rb(a,b){rb.b||(rb.b={});a in rb.b||(t.h("v",b),rb.b[a]=1)}c._memcpy=sb;var tb=0;function N(){tb+=4;return C[tb-4>>2]}var ub={},vb={};function F(a){F.b||(v=Ha(v),F.b=!0,assert(t.d),F.f=t.d,t.d=function(){y("cannot dynamically allocate, sbrk now has control")});var b=v;return 0==a||F.f(a)?b:4294967295}c._memmove=wb;var xb=1;
+function Q(a,b){tb=b;try{var d=N(),e=N(),f=N(),l=0;Q.buffer||(Q.b=[null,[],[]],Q.g=function(a,b){var d=Q.b[a];assert(d);0===b||10===b?((1===a?c.print:c.printErr)(Ba(d,0)),d.length=0):d.push(b)});for(var h=0;h<f;h++){for(var q=C[e+8*h>>2],r=C[e+(8*h+4)>>2],A=0;A<r;A++)Q.g(d,E[q+A]);l+=r}return l}catch(X){return"undefined"!==typeof FS&&X instanceof FS.B||y(X),-X.G}}function D(a){return t.d(a+8)+8&4294967288}c._malloc=D;
+I.push(function(){var a=c._fflush;a&&a(0);if(a=Q.g){var b=Q.b;b[1].length&&a(1,10);b[2].length&&a(2,10)}});
+var Ma=p=t.F(u),ya=!0,Na=Ma+Ra,v=t.F(Na),yb=xa([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,
+0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",3);c.L={Math:Math,Int8Array:Int8Array,Int16Array:Int16Array,Int32Array:Int32Array,Uint8Array:Uint8Array,Uint16Array:Uint16Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array,NaN:NaN,Infinity:Infinity,byteLength:Pa};
+c.M={abort:y,assert:assert,invoke_iiii:function(a,b,d,e){try{return c.dynCall_iiii(a,b,d,e)}catch(f){if("number"!==typeof f&&"longjmp"!==f)throw f;M.setThrew(1,0)}},invoke_viiiii:function(a,b,d,e,f,l){try{c.dynCall_viiiii(a,b,d,e,f,l)}catch(h){if("number"!==typeof h&&"longjmp"!==h)throw h;M.setThrew(1,0)}},invoke_vi:function(a,b){try{c.dynCall_vi(a,b)}catch(d){if("number"!==typeof d&&"longjmp"!==d)throw d;M.setThrew(1,0)}},invoke_ii:function(a,b){try{return c.dynCall_ii(a,b)}catch(d){if("number"!==
+typeof d&&"longjmp"!==d)throw d;M.setThrew(1,0)}},invoke_v:function(a){try{c.dynCall_v(a)}catch(b){if("number"!==typeof b&&"longjmp"!==b)throw b;M.setThrew(1,0)}},invoke_viiiiii:function(a,b,d,e,f,l,h){try{c.dynCall_viiiiii(a,b,d,e,f,l,h)}catch(q){if("number"!==typeof q&&"longjmp"!==q)throw q;M.setThrew(1,0)}},invoke_viiii:function(a,b,d,e,f){try{c.dynCall_viiii(a,b,d,e,f)}catch(l){if("number"!==typeof l&&"longjmp"!==l)throw l;M.setThrew(1,0)}},_pthread_cleanup_pop:function(){assert(ob.level==I.length,
+"cannot pop if something else added meanwhile!");I.pop();ob.level=I.length},___syscall6:function(a,b){tb=b;try{var d=ub.Q();FS.close(d);return 0}catch(e){return"undefined"!==typeof FS&&e instanceof FS.B||y(e),-e.G}},___gxx_personality_v0:function(){},___assert_fail:function(a,b,d,e){ia=!0;throw"Assertion failed: "+z(a)+", at: "+[b?z(b):"unknown filename",d,e?z(e):"unknown function"]+" at "+Ea();},___cxa_allocate_exception:function(a){return D(a)},___cxa_find_matching_catch:mb,___setErrNo:hb,_sbrk:F,
+___cxa_begin_catch:function(a){ib.b--;kb.push(a);var b=lb(a);b&&L[b].I++;return a},_emscripten_memcpy_big:function(a,b,d){E.set(E.subarray(b,b+d),a);return a},___resumeException:function(a){jb||(jb=a);var b=lb(a);b&&(L[b].I=0);throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";},__ZSt18uncaught_exceptionv:ib,_sysconf:function(a){switch(a){case 30:return 4096;case 85:return G/4096;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;
 case 79:return 0;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;
-case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1E3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:return"object"===typeof navigator?navigator.hardwareConcurrency||1:1}wb(22);return-1},
-_pthread_getspecific:function(a){return vb[a]||0},_pthread_self:function(){return 0},_pthread_once:ub,_pthread_key_create:function(a){if(0==a)return 22;I[a>>2]=xb;vb[xb]=0;xb++;return 0},_emscripten_set_main_loop:Gb,_emscripten_asm_const_iii:function(a,b,c){return kb[a](b,c)},_pthread_setspecific:function(a,b){if(!(a in vb))return 22;vb[a]=b;return 0},___cxa_throw:function(a,b,c){Q[a]={e:a,U:a,type:b,Aa:c,aa:0};ob=a;"uncaught_exception"in nb?nb.g++:nb.g=1;throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";
-},___syscall6:function(a,b){sc=b;try{var c=uc.ka();FS.close(c);return 0}catch(e){return"undefined"!==typeof FS&&e instanceof FS.S||D(e),-e.W}},_pthread_cleanup_push:qc,_time:function(a){var b=Date.now()/1E3|0;a&&(I[a>>2]=b);return b},___syscall140:function(a,b){sc=b;try{var c=uc.ka(),e=tc(),f=tc(),h=tc(),k=tc();assert(0===e);FS.Ia(c,f,k);I[h>>2]=c.position;c.na&&0===f&&0===k&&(c.na=null);return 0}catch(l){return"undefined"!==typeof FS&&l instanceof FS.S||D(l),-l.W}},___syscall146:wc,STACKTOP:t,STACK_MAX:Sa,
-tempDoublePtr:lb,ABORT:C,cttz_i8:xc};// EMSCRIPTEN_START_ASM
-var R=(function(global,env,buffer) {
-"almost asm";var a=global.Int8Array;var b=global.Int16Array;var c=global.Int32Array;var d=global.Uint8Array;var e=global.Uint16Array;var f=global.Uint32Array;var g=global.Float32Array;var h=global.Float64Array;var i=new a(buffer);var j=new b(buffer);var k=new c(buffer);var l=new d(buffer);var m=new e(buffer);var n=new f(buffer);var o=new g(buffer);var p=new h(buffer);var q=global.byteLength;var r=env.STACKTOP|0;var s=env.STACK_MAX|0;var t=env.tempDoublePtr|0;var u=env.ABORT|0;var v=env.cttz_i8|0;var w=0;var x=0;var y=0;var z=0;var A=global.NaN,B=global.Infinity;var C=0,D=0,E=0,F=0,G=0.0,H=0,I=0,J=0,K=0.0;var L=0;var M=0;var N=0;var O=0;var P=0;var Q=0;var R=0;var S=0;var T=0;var U=0;var V=global.Math.floor;var W=global.Math.abs;var X=global.Math.sqrt;var Y=global.Math.pow;var Z=global.Math.cos;var _=global.Math.sin;var $=global.Math.tan;var aa=global.Math.acos;var ba=global.Math.asin;var ca=global.Math.atan;var da=global.Math.atan2;var ea=global.Math.exp;var fa=global.Math.log;var ga=global.Math.ceil;var ha=global.Math.imul;var ia=global.Math.min;var ja=global.Math.clz32;var ka=env.abort;var la=env.assert;var ma=env.invoke_iiii;var na=env.invoke_viiiii;var oa=env.invoke_vi;var pa=env.invoke_ii;var qa=env.invoke_v;var ra=env.invoke_viiiiii;var sa=env.invoke_viiii;var ta=env._pthread_cleanup_pop;var ua=env._abort;var va=env.___setErrNo;var wa=env.___gxx_personality_v0;var xa=env.___assert_fail;var ya=env.___cxa_allocate_exception;var za=env.__ZSt18uncaught_exceptionv;var Aa=env._emscripten_set_main_loop_timing;var Ba=env._sbrk;var Ca=env.___cxa_begin_catch;var Da=env._emscripten_memcpy_big;var Ea=env.___resumeException;var Fa=env.___cxa_find_matching_catch;var Ga=env._sysconf;var Ha=env._pthread_getspecific;var Ia=env._pthread_self;var Ja=env._pthread_once;var Ka=env._pthread_key_create;var La=env._emscripten_set_main_loop;var Ma=env._emscripten_asm_const_iii;var Na=env._pthread_setspecific;var Oa=env.___cxa_throw;var Pa=env.___syscall6;var Qa=env._pthread_cleanup_push;var Ra=env._time;var Sa=env.___syscall140;var Ta=env.___syscall146;var Ua=0.0;function Va(newBuffer){if(q(newBuffer)&16777215||q(newBuffer)<=16777215||q(newBuffer)>2147483648)return false;i=new a(newBuffer);j=new b(newBuffer);k=new c(newBuffer);l=new d(newBuffer);m=new e(newBuffer);n=new f(newBuffer);o=new g(newBuffer);p=new h(newBuffer);buffer=newBuffer;return true}
+case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1E3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:return"object"===typeof navigator?navigator.hardwareConcurrency||1:1}hb(22);return-1},
+_pthread_getspecific:function(a){return vb[a]||0},_pthread_self:function(){return 0},_pthread_once:rb,_pthread_key_create:function(a){if(0==a)return 22;C[a>>2]=xb;vb[xb]=0;xb++;return 0},_emscripten_asm_const_iii:function(a,b,d){return db[a](b,d)},_pthread_setspecific:function(a,b){if(!(a in vb))return 22;vb[a]=b;return 0},___cxa_throw:function(a,b,d){L[a]={a:a,D:a,type:b,aa:d,I:0};jb=a;"uncaught_exception"in ib?ib.b++:ib.b=1;throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";
+},_abort:function(){c.abort()},_pthread_cleanup_push:ob,_time:function(a){var b=Date.now()/1E3|0;a&&(C[a>>2]=b);return b},___syscall140:function(a,b){tb=b;try{var d=ub.Q(),e=N(),f=N(),l=N(),h=N();assert(0===e);FS.ja(d,f,h);C[l>>2]=d.position;d.T&&0===f&&0===h&&(d.T=null);return 0}catch(q){return"undefined"!==typeof FS&&q instanceof FS.B||y(q),-q.G}},___syscall146:Q,STACKTOP:p,STACK_MAX:Na,tempDoublePtr:eb,ABORT:ia,cttz_i8:yb};// EMSCRIPTEN_START_ASM
+
+var M=(function(global,env,buffer) {
+"almost asm";var a=global.Int8Array;var b=global.Int16Array;var c=global.Int32Array;var d=global.Uint8Array;var e=global.Uint16Array;var f=global.Uint32Array;var g=global.Float32Array;var h=global.Float64Array;var i=new a(buffer);var j=new b(buffer);var k=new c(buffer);var l=new d(buffer);var m=new e(buffer);var n=new f(buffer);var o=new g(buffer);var p=new h(buffer);var q=global.byteLength;var r=env.STACKTOP|0;var s=env.STACK_MAX|0;var t=env.tempDoublePtr|0;var u=env.ABORT|0;var v=env.cttz_i8|0;var w=0;var x=0;var y=0;var z=0;var A=global.NaN,B=global.Infinity;var C=0,D=0,E=0,F=0,G=0.0,H=0,I=0,J=0,K=0.0;var L=0;var M=0;var N=0;var O=0;var P=0;var Q=0;var R=0;var S=0;var T=0;var U=0;var V=global.Math.floor;var W=global.Math.abs;var X=global.Math.sqrt;var Y=global.Math.pow;var Z=global.Math.cos;var _=global.Math.sin;var $=global.Math.tan;var aa=global.Math.acos;var ba=global.Math.asin;var ca=global.Math.atan;var da=global.Math.atan2;var ea=global.Math.exp;var fa=global.Math.log;var ga=global.Math.ceil;var ha=global.Math.imul;var ia=global.Math.min;var ja=global.Math.clz32;var ka=env.abort;var la=env.assert;var ma=env.invoke_iiii;var na=env.invoke_viiiii;var oa=env.invoke_vi;var pa=env.invoke_ii;var qa=env.invoke_v;var ra=env.invoke_viiiiii;var sa=env.invoke_viiii;var ta=env._pthread_cleanup_pop;var ua=env.___syscall6;var va=env.___gxx_personality_v0;var wa=env.___assert_fail;var xa=env.___cxa_allocate_exception;var ya=env.___cxa_find_matching_catch;var za=env.___setErrNo;var Aa=env._sbrk;var Ba=env.___cxa_begin_catch;var Ca=env._emscripten_memcpy_big;var Da=env.___resumeException;var Ea=env.__ZSt18uncaught_exceptionv;var Fa=env._sysconf;var Ga=env._pthread_getspecific;var Ha=env._pthread_self;var Ia=env._pthread_once;var Ja=env._pthread_key_create;var Ka=env._emscripten_asm_const_iii;var La=env._pthread_setspecific;var Ma=env.___cxa_throw;var Na=env._abort;var Oa=env._pthread_cleanup_push;var Pa=env._time;var Qa=env.___syscall140;var Ra=env.___syscall146;var Sa=0.0;function Ta(newBuffer){if(q(newBuffer)&16777215||q(newBuffer)<=16777215||q(newBuffer)>2147483648)return false;i=new a(newBuffer);j=new b(newBuffer);k=new c(newBuffer);l=new d(newBuffer);m=new e(newBuffer);n=new f(newBuffer);o=new g(newBuffer);p=new h(newBuffer);buffer=newBuffer;return true}
 // EMSCRIPTEN_START_FUNCS
-function bb(a){a=a|0;var b=0;b=r;r=r+a|0;r=r+15&-16;return b|0}function cb(){return r|0}function db(a){a=a|0;r=a}function eb(a,b){a=a|0;b=b|0;r=a;s=b}function fb(a,b){a=a|0;b=b|0;if(!w){w=a;x=b}}function gb(a){a=a|0;i[t>>0]=i[a>>0];i[t+1>>0]=i[a+1>>0];i[t+2>>0]=i[a+2>>0];i[t+3>>0]=i[a+3>>0]}function hb(a){a=a|0;i[t>>0]=i[a>>0];i[t+1>>0]=i[a+1>>0];i[t+2>>0]=i[a+2>>0];i[t+3>>0]=i[a+3>>0];i[t+4>>0]=i[a+4>>0];i[t+5>>0]=i[a+5>>0];i[t+6>>0]=i[a+6>>0];i[t+7>>0]=i[a+7>>0]}function ib(a){a=a|0;L=a}function jb(){return L|0}function kb(a,b){a=a|0;b=b|0;var c=0,d=0;d=980497+(a<<3&2040)|0;c=a>>>8;if(c&255|0)pd(b,c&255,l[d+5>>0]|0);c=a>>>16;if(c&255|0)pd(b,c&255,l[d+6>>0]|0);c=a>>>24;if(c|0)pd(b,c&255,l[d+7>>0]|0);return}function lb(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,m=0,n=0,o=0;o=r;r=r+16|0;n=o+4|0;m=o;f=a+b|0;g=a+c|0;j=e+8|0;h=k[e+4>>2]|0;b=k[j>>2]|0;c=(i[f>>0]|0)==32?f+1|0:f;do{if(c>>>0>=g>>>0)break;k[n>>2]=c;f=l[1009576+(l[c>>0]|0)>>0]|0;k[m>>2]=f;c=c+f|0;f=wd(d,n,m)|0;if(f<<24>>24){k[e+32+(b<<3)>>2]=c-a;k[e+32+(b<<3)+4>>2]=f&255;b=b+1|0}}while((b|0)<(h|0));k[j>>2]=b;n=c-a|0;k[e+32+(b<<3)>>2]=n;k[e+32+(k[j>>2]<<3)+4>>2]=0;r=o;return n|0}function mb(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;q=a+c|0;z=f+12|0;u=k[f+4>>2]|0;A=f+16|0;v=u+-1|0;w=d+16|0;r=d+12|0;y=a;s=e+16|0;t=e+12|0;h=k[z>>2]|0;g=k[A>>2]|0;p=a+b|0;while(1){if(p>>>0>=q>>>0){c=p;break}b=l[1009576+(l[p>>0]|0)>>0]|0;c=p+b|0;b=(l[1009576+(l[c>>0]|0)>>0]|0)+b|0;do if(b>>>0>5){o=sb(p,b)|0;a=k[d>>2]|0;m=k[w>>2]|0;n=(o>>>12)+o|0;i=(k[r>>2]|0)+-1&n;j=m&o;b=k[a+(i<<4)>>2]|0;if((b^j)&m){b=k[a+(i<<4)+4>>2]|0;if((b^j)&m){b=k[a+(i<<4)+8>>2]|0;if((b^j)&m){b=k[a+(i<<4)+12>>2]|0;if(!((b^j)&m))x=8}else x=8}else x=8}else x=8;if((x|0)==8){x=0;if(b){k[f+8040+(h<<3)>>2]=p-y;k[f+8040+(h<<3)+4>>2]=b&~m;h=h+1|0}}j=k[e>>2]|0;m=k[s>>2]|0;a=(k[t>>2]|0)+-1&n;i=m&o;b=k[j+(a<<4)>>2]|0;if((b^i)&m){b=k[j+(a<<4)+4>>2]|0;if((b^i)&m){b=k[j+(a<<4)+8>>2]|0;if((b^i)&m){b=k[j+(a<<4)+12>>2]|0;if((b^i)&m)break}}}if(b){k[f+16048+(g<<3)>>2]=p-y;k[f+16048+(g<<3)+4>>2]=b&~m;g=g+1|0}}while(0);if((g|0)<(v|0)&(h|0)<(u|0))p=c;else break}k[z>>2]=h;k[A>>2]=g;z=c-y|0;k[f+8040+(h<<3)>>2]=z;k[f+8040+(h<<3)+4>>2]=0;k[f+16048+(k[A>>2]<<3)>>2]=z;k[f+16048+(k[A>>2]<<3)+4>>2]=0;return}function nb(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;D=r;r=r+16|0;C=D;t=a+b|0;u=a+c|0;B=f+8|0;b=k[B>>2]|0;A=k[f+4>>2]|0;v=C;k[v>>2]=0;k[v+4>>2]=0;v=C+4|0;w=d+16|0;x=d+12|0;y=e+12|0;z=e+16|0;g=0;c=(i[t>>0]|0)==32?t+1|0:t;do{if(c>>>0>=u>>>0)break;s=c+(l[979972+(l[c>>0]|0)>>0]|0)|0;s=s+(l[979972+(l[s>>0]|0)>>0]|0)|0;t=s+(l[979972+(l[s>>0]|0)>>0]|0)|0;t=t+(l[979972+(l[t>>0]|0)>>0]|0)|0;q=c;p=ub(c,t-q|0)|0;do if(!((p|0)==(k[C>>2]|0)?1:(p|0)==(k[v>>2]|0))){j=k[d>>2]|0;h=k[w>>2]|0;o=(p>>>12)+p|0;m=(k[x>>2]|0)+-1&o;n=h&p;c=k[j+(m<<4)>>2]|0;if((c^n)&h){c=k[j+(m<<4)+4>>2]|0;if((c^n)&h){c=k[j+(m<<4)+8>>2]|0;if((c^n)&h){c=k[j+(m<<4)+12>>2]|0;if(!((c^n)&h))m=8;else m=9}else m=8}else m=8}else m=8;if((m|0)==8){m=0;if(!c)m=9;else j=0}if((m|0)==9){c=k[y>>2]|0;if(!c)break;n=k[e>>2]|0;h=k[z>>2]|0;j=c+-1&o;m=h&p;c=k[n+(j<<4)>>2]|0;if((c^m)&h){c=k[n+(j<<4)+4>>2]|0;if((c^m)&h){c=k[n+(j<<4)+8>>2]|0;if((c^m)&h){c=k[n+(j<<4)+12>>2]|0;if((c^m)&h)break}}}if(!c)break;else j=-2147483648}k[C+(g<<2)>>2]=p;k[f+32+(b<<3)>>2]=q-a;k[f+32+(b<<3)+4>>2]=c&~h|j;b=b+1|0;g=g&1^1}while(0);c=(i[t>>0]|0)==32?t:s;if(c>>>0<u>>>0)c=c+(l[980228+(l[c>>0]|0)>>0]|0)|0;else c=u}while((b|0)<(A|0));k[B>>2]=b;e=c-a|0;k[f+32+(b<<3)>>2]=e;k[f+32+(k[B>>2]<<3)+4>>2]=0;r=D;return e|0}function ob(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;J=r;r=r+16|0;F=J;u=a+b|0;A=a+(c+1)|0;H=f+12|0;g=k[H>>2]|0;B=k[f+4>>2]|0;I=f+16|0;b=k[I>>2]|0;C=B+-1|0;k[F>>2]=0;k[F+4>>2]=0;k[F+8>>2]=0;k[F+12>>2]=0;u=(i[u>>0]|0)==32?u+1|0:u;x=F+8|0;y=e+16|0;z=e+12|0;E=a;v=d+16|0;w=d+12|0;n=0;a=g;g=0;q=u;D=u;j=u;while(1){if(D>>>0>=A>>>0){c=D;break}c=i[D>>0]|0;if(c<<24>>24==32){t=u;p=wb(u,j-t|0)|0;s=L;n=F;o=x;do if(!(((p|0)==(k[n>>2]|0)?(s|0)==(k[n+4>>2]|0):0)|((p|0)==(k[o>>2]|0)?(s|0)==(k[o+4>>2]|0):0))){h=F+(g<<3)|0;k[h>>2]=p;k[h+4>>2]=s;g=1-g|0;h=F+(g<<3)|0;c=k[h>>2]|0;h=k[h+4>>2]|0;do if(!((c|0)==0&(h|0)==0|(c|0)==(p|0)&(h|0)==(s|0))){c=xb(c,h,p,s)|0;j=L;m=k[e>>2]|0;o=k[y>>2]|0;n=k[z>>2]|0;h=uf(c|0,j|0,12)|0;h=tf(h|0,L|0,c|0,j|0)|0;h=n+-1&h;j=uf(c|0,j|0,4)|0;j=o&j;c=k[m+(h<<4)>>2]|0;if((c^j)&o){c=k[m+(h<<4)+4>>2]|0;if((c^j)&o){c=k[m+(h<<4)+8>>2]|0;if((c^j)&o){c=k[m+(h<<4)+12>>2]|0;if((c^j)&o){c=n;break}}}}if(!c)c=n;else{k[f+16048+(b<<3)>>2]=q-E;k[f+16048+(b<<3)+4>>2]=c&~o;c=n;b=b+1|0}}else{c=k[z>>2]|0;o=k[y>>2]|0;m=k[e>>2]|0}while(0);q=uf(p|0,s|0,12)|0;q=tf(q|0,L|0,p|0,s|0)|0;j=c+-1&q;p=uf(p|0,s|0,4)|0;h=o&p;c=k[m+(j<<4)>>2]|0;if((c^h)&o){c=k[m+(j<<4)+4>>2]|0;if((c^h)&o){c=k[m+(j<<4)+8>>2]|0;if((c^h)&o){c=k[m+(j<<4)+12>>2]|0;if(!((c^h)&o))G=17}else G=17}else G=17}else G=17;if((G|0)==17){G=0;if(c){k[f+16048+(b<<3)>>2]=t-E;k[f+16048+(b<<3)+4>>2]=c&~o;b=b+1|0}}m=k[d>>2]|0;n=k[v>>2]|0;h=(k[w>>2]|0)+-1&q;j=n&p;c=k[m+(h<<4)>>2]|0;if((c^j)&n){c=k[m+(h<<4)+4>>2]|0;if((c^j)&n){c=k[m+(h<<4)+8>>2]|0;if((c^j)&n){c=k[m+(h<<4)+12>>2]|0;if((c^j)&n)break}}}if(c){k[f+8040+(a<<3)>>2]=t-E;k[f+8040+(a<<3)+4>>2]=c&~n;a=a+1|0}}while(0);m=D+1|0;c=i[D>>0]|0;o=0;h=u;j=m}else{o=n+1|0;h=q;m=u}c=D+(l[1009576+(c&255)>>0]|0)|0;if((b|0)<(C|0)&(a|0)<(B|0)){n=o;q=h;D=c;j=(o|0)<9?c:j;u=m}else break}k[H>>2]=a;k[I>>2]=b;H=c-E|0;k[f+8040+(a<<3)>>2]=H;k[f+8040+(a<<3)+4>>2]=0;k[f+16048+(k[I>>2]<<3)>>2]=H;k[f+16048+(k[I>>2]<<3)+4>>2]=0;r=J;return}function pb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=(c|0)<8?c*12|0:100;e=c*5>>3;e=(e|0)<3?3:(e|0)>16?16:e;c=a-b|0;if((c|0)<(e|0))if((c|0)<1)d=0;else{b=(c*100|0)/(e|0)|0;d=(d|0)<(b|0)?d:b}return d|0}function qb(a,b){a=a|0;b=b|0;var c=0.0;if(b)if(a){if((b|0)>(a|0))c=+(b|0)/+(a|0);else c=+(a|0)/+(b|0);if(!(c<=1.5))if(c>4.0)a=0;else a=~~((4.0-c)*100.0/2.5);else a=100}else a=0;else a=100;return a|0}function rb(a,b){a=a|0;b=b|0;a=((Jc(a)|0)&255)<<8;return a|(l[980484+b>>0]|0)|0}function sb(a,b){a=a|0;b=b|0;var c=0;do if(b){c=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;if((b|0)<5){c=k[120+((b&3)<<2)>>2]&c;c=c>>>3^c;break}else{a=a+4|0;a=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=(a<<18^a)+(c>>>3^c)|0;break}}else c=0;while(0);return c|0}function tb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;do if((b|0)>=5){d=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;d=d>>>3^d;e=a+4|0;e=l[e>>0]|l[e+1>>0]<<8|l[e+2>>0]<<16|l[e+3>>0]<<24;if((b|0)<9){a=k[120+((b&3)<<2)>>2]&e;d=(a<<4^a)+(d^c)|0;break}else{a=a+8|0;a=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);d=(d^c)+(e<<4^e)+(a<<2^a)|0;break}}else{d=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);d=d^c^d>>>3}while(0);return d|0}function ub(a,b){a=a|0;b=b|0;var c=0;if(!b)b=0;else{c=(i[a+-1>>0]|0)==32?17476:0;b=tb(a,b,(i[a+b>>0]|0)==32?c|1145307136:c)|0}return b|0}function vb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,m=0;f=(i[a+-1>>0]|0)==32;e=f?c|17476:c;f=f?d:d;d=(i[a+b>>0]|0)==32;e=d?e|1145307136:e;f=d?f:f;switch(b+-1>>2|0){case 0:{b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=b;d=0;b=(uf(b|0,0,3)|0)^b;a=L;break}case 1:{h=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;j=uf(h|0,0,3)|0;g=L;c=a+4|0;b=k[120+((b&3)<<2)>>2]&(l[c>>0]|l[c+1>>0]<<8|l[c+2>>0]<<16|l[c+3>>0]<<24);c=tf(b|0,0,h|0,0)|0;d=L;b=tf((sf(b|0,0,4)|0)^b|0,L|0,j^h|0,g|0)|0;a=L;break}case 2:{j=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;g=uf(j|0,0,3)|0;h=L;m=a+4|0;m=l[m>>0]|l[m+1>>0]<<8|l[m+2>>0]<<16|l[m+3>>0]<<24;d=tf(m|0,0,j|0,0)|0;c=L;h=tf((sf(m|0,0,4)|0)^m|0,L|0,g^j|0,h|0)|0;j=L;a=a+8|0;b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=tf(d|0,c|0,b|0,0)|0;d=L;b=tf(h|0,j|0,(sf(b|0,0,2)|0)^b|0,L|0)|0;a=L;break}case 3:{m=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;j=uf(m|0,0,3)|0;h=L;g=a+4|0;g=l[g>>0]|l[g+1>>0]<<8|l[g+2>>0]<<16|l[g+3>>0]<<24;c=tf(g|0,0,m|0,0)|0;d=L;h=tf((sf(g|0,0,4)|0)^g|0,L|0,j^m|0,h|0)|0;m=L;j=a+8|0;j=l[j>>0]|l[j+1>>0]<<8|l[j+2>>0]<<16|l[j+3>>0]<<24;d=tf(c|0,d|0,j|0,0)|0;c=L;j=tf(h|0,m|0,(sf(j|0,0,2)|0)^j|0,L|0)|0;m=L;a=a+12|0;b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=tf(d|0,c|0,b|0,0)|0;d=L;b=tf(j|0,m|0,(uf(b|0,0,8)|0)^b|0,L|0)|0;a=L;break}case 4:{m=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;h=uf(m|0,0,3)|0;j=L;g=a+4|0;g=l[g>>0]|l[g+1>>0]<<8|l[g+2>>0]<<16|l[g+3>>0]<<24;d=tf(g|0,0,m|0,0)|0;c=L;j=tf((sf(g|0,0,4)|0)^g|0,L|0,h^m|0,j|0)|0;m=L;h=a+8|0;h=l[h>>0]|l[h+1>>0]<<8|l[h+2>>0]<<16|l[h+3>>0]<<24;c=tf(d|0,c|0,h|0,0)|0;d=L;h=tf(j|0,m|0,(sf(h|0,0,2)|0)^h|0,L|0)|0;m=L;j=a+12|0;j=l[j>>0]|l[j+1>>0]<<8|l[j+2>>0]<<16|l[j+3>>0]<<24;d=tf(c|0,d|0,j|0,0)|0;c=L;j=tf(h|0,m|0,(uf(j|0,0,8)|0)^j|0,L|0)|0;m=L;a=a+16|0;b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=tf(d|0,c|0,b|0,0)|0;d=L;b=tf(j|0,m|0,(uf(b|0,0,4)|0)^b|0,L|0)|0;a=L;break}default:{m=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;j=uf(m|0,0,3)|0;h=L;g=a+4|0;g=l[g>>0]|l[g+1>>0]<<8|l[g+2>>0]<<16|l[g+3>>0]<<24;c=tf(g|0,0,m|0,0)|0;d=L;h=tf((sf(g|0,0,4)|0)^g|0,L|0,j^m|0,h|0)|0;m=L;j=a+8|0;j=l[j>>0]|l[j+1>>0]<<8|l[j+2>>0]<<16|l[j+3>>0]<<24;d=tf(c|0,d|0,j|0,0)|0;c=L;j=tf(h|0,m|0,(sf(j|0,0,2)|0)^j|0,L|0)|0;m=L;h=a+12|0;h=l[h>>0]|l[h+1>>0]<<8|l[h+2>>0]<<16|l[h+3>>0]<<24;c=tf(d|0,c|0,h|0,0)|0;d=L;h=tf(j|0,m|0,(uf(h|0,0,8)|0)^h|0,L|0)|0;m=L;j=a+16|0;j=l[j>>0]|l[j+1>>0]<<8|l[j+2>>0]<<16|l[j+3>>0]<<24;d=tf(c|0,d|0,j|0,0)|0;c=L;j=tf(h|0,m|0,(uf(j|0,0,4)|0)^j|0,L|0)|0;m=L;a=a+20|0;b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=tf(d|0,c|0,b|0,0)|0;d=L;b=tf(j|0,m|0,(uf(b|0,0,6)|0)^b|0,L|0)|0;a=L}}j=uf(c|0,d|0,17)|0;j=tf(j|0,L|0,c|0,d|0)|0;m=L;h=uf(j|0,m|0,9)|0;m=tf(h|0,L|0,j|0,m|0)|0;m=tf(0,m&255|0,b^e|0,a^f|0)|0;return m|0}function wb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;if(!b){b=0;a=0}else{c=(i[a+-1>>0]|0)==32;e=c?17476:0;c=c?0:0;d=(i[a+b>>0]|0)==32;a=vb(a,b,d?e|1145307136:e,d?c:c)|0;b=L}L=b;return a|0}function xb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;f=uf(a|0,b|0,13)|0;e=L;b=sf(a|0,b|0,51)|0;d=tf(f|b|0,e|L|0,c|0,d|0)|0;return d|0}function yb(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0;h=r;r=r+48|0;i=h+24|0;k[i>>2]=0;k[i+4>>2]=1097825;k[i+8>>2]=23;k[i+12>>2]=26;f=mc(a,b,c,i,0,d,e,h,f,g)|0;r=h;return ((f|0)==26?0:f)|0}function zb(a,b,c,d,e,f,g,h,i){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;return mc(a,b,c,d,0,e,f,g,h,i)|0}function Ab(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;a:do if(a<<16>>16){d=a&1023;e=k[b>>2]|0;do if((e|0)>0){c=0;while(1){f=b+4+(c<<1)|0;g=j[f>>1]|0;c=c+1|0;if((g&1023|0)==(d|0)){c=5;break}if((c|0)>=(e|0)){c=6;break}}if((c|0)==5){b=g<<16>>16>>10;a=a<<16>>16>>10;j[f>>1]=((b|0)>=(a|0)?b:a)<<10|d;break a}else if((c|0)==6)if((e|0)>13)break a;else break}while(0);k[b>>2]=e+1;j[b+4+(e<<1)>>1]=a}while(0);return}function Bb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;a:do if(a<<16>>16){d=a&1023;e=k[b>>2]|0;do if((e|0)>0){c=0;while(1){f=b+4+(c<<1)|0;g=m[f>>1]|0;c=c+1|0;if((g&1023|0)==(d|0)){c=5;break}if((c|0)>=(e|0)){c=6;break}}if((c|0)==5){j[f>>1]=g+2048&64512|d;break a}else if((c|0)==6)if((e|0)>13)break a;else break}while(0);k[b>>2]=e+1;j[b+4+(e<<1)>>1]=a}while(0);return}function Cb(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0;if((k[a>>2]|0)>4){g=0;do{f=j[a+4+(g<<1)>>1]|0;d=f<<16>>16>>10;d=(d|0)>-1?d:0-d|0;a:do if((g|0)>0){e=g;while(1){b=e+-1|0;c=j[a+4+(b<<1)>>1]|0;h=c<<16>>16>>10;if((((h|0)>-1?h:0-h|0)|0)>=(d|0)){b=e;break a}j[a+4+(e<<1)>>1]=c;if((e|0)>1)e=b;else break}}else b=g;while(0);j[a+4+(b<<1)>>1]=f;g=g+1|0}while((g|0)<(k[a>>2]|0));k[a>>2]=4}return}function Db(a){a=a|0;var b=0,c=0,d=0;d=i[a>>0]|0;b=(d&1)==0;d=b?(d&255)>>>1:k[a+4>>2]|0;if((d|0)>0){a=b?a+1|0:k[a+8>>2]|0;b=0;c=0;do{b=((i[a+c>>0]|0)==44&1)+b|0;c=c+1|0}while((c|0)!=(d|0))}else b=0;return b|0}function Eb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;g=c;c=0;a:while(1){if((c|0)<(g|0))f=c;else{c=0;break}while(1){d=f+g>>1;c=b+(d*12|0)|0;e=_e(k[c>>2]|0,a)|0;if((e|0)>=0)break;c=d+1|0;if((c|0)<(g|0))f=c;else{c=0;break a}}if((e|0)>0){g=d;c=f}else break}return c|0}function Fb(a){a=a|0;var b=0,c=0,d=0,e=0,f=0;f=181;b=0;a:while(1){if((b|0)<(f|0))e=b;else{b=0;break}while(1){c=e+f>>1;b=5776+(c<<3)|0;d=_e(k[b>>2]|0,a)|0;if((d|0)>=0)break;b=c+1|0;if((b|0)<(f|0))e=b;else{b=0;break a}}if((d|0)>0){f=c;b=e}else break}return b|0}function Gb(a){a=a|0;Ca(a|0)|0;je()}function Hb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=c+-3|0;a:do if((d|0)>(b|0))do{e=a+b|0;e=l[e>>0]|l[e+1>>0]<<8|l[e+2>>0]<<16|l[e+3>>0]<<24;if((e^1010580540)+-16843009&(e&-2139062144^-2139062144)|0)break a;b=b+4|0}while((b|0)<(d|0));while(0);b:do if((b|0)<(c|0))while(1){if((i[a+b>>0]|0)==60)break b;b=b+1|0;if((b|0)>=(c|0)){b=-1;break}}else b=-1;while(0);return b|0}function Ib(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;a:do if((b|0)<(c|0))while(1){b:do switch(i[a+b>>0]|0){case 61:break a;case 34:{e=b+1|0;if((e|0)<(c|0)){d=b;b=e;while(1){switch(i[a+b>>0]|0){case 34:break b;case 92:{d=d+2|0;break}default:d=b}b=d+1|0;if((b|0)>=(c|0))break b}}else b=e;break}case 39:{e=b+1|0;if((e|0)<(c|0)){d=b;b=e;while(1){switch(i[a+b>>0]|0){case 39:break b;case 92:{d=d+2|0;break}default:d=b}b=d+1|0;if((b|0)>=(c|0))break b}}else b=e;break}default:{}}while(0);b=b+1|0;if((b|0)>=(c|0)){b=-1;break a}}else b=-1;while(0);return b|0}function Jb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;g=Ve(d)|0;a:do if((c-b|0)>=(g|0)){f=g+b|0;while(1){if((c|0)<=(f|0))break;e=c+-1|0;if((i[a+e>>0]|0)==32)c=e;else break}c=c-g|0;if((c|0)>=(b|0)){c=a+c|0;if((g|0)>0){e=0;while(1){if((i[c+e>>0]|32|0)!=(i[d+e>>0]|0)){c=0;break a}e=e+1|0;if((e|0)>=(g|0)){c=1;break}}}else c=1}else c=0}else c=0;while(0);return c|0}function Kb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=Ve(d)|0;a:do if((c-b|0)>=(e|0)){c=c-e|0;b:do if((c|0)>(b|0))while(1){switch(i[a+b>>0]|0){case 39:case 34:case 32:break;default:break b}b=b+1|0;if((b|0)>=(c|0))break b}while(0);b=a+b|0;if((e|0)>0){c=0;while(1){if((i[b+c>>0]|32|0)!=(i[d+c>>0]|0)){b=0;break a}c=c+1|0;if((c|0)>=(e|0)){b=1;break}}}else b=1}else b=0;while(0);return b|0}function Lb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;if((c|0)<(d|0)){f=1;do{e=l[b+c>>0]|0;g=(l[984554+e>>0]|0)>>>(f*3|0);f=g&3;do if(g&4|0)if(!f){hf(a,i[984810+e>>0]|0);break}else{hf(a,44);break}while(0);c=c+1|0}while((c|0)!=(d|0));if(!f)hf(a,44)}return}function Mb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;a:do if((c|0)<(d|0)){b:while(1){switch(i[b+c>>0]|0){case 39:case 34:break b;case 32:break;default:{f=5;break a}}c=c+1|0;if((c|0)>=(d|0)){f=5;break a}}if((c|0)>=0){e=c+1|0;c:do if((e|0)<(d|0)){c=e;d:while(1){switch(i[b+c>>0]|0){case 39:case 34:break d;case 62:{f=8;break d}case 61:{f=9;break d}case 60:{f=10;break d}case 38:{f=11;break d}default:{}}c=c+1|0;if((c|0)>=(d|0))break c}if((f|0)==8)c=c+-1|0;else if((f|0)==9)c=c+-1|0;else if((f|0)==10)c=c+-1|0;else if((f|0)==11)c=c+-1|0;if((c|0)>=0){Lb(a,b,e,c);break a}}while(0);ef(a,1097825,0)}else f=5}else f=5;while(0);if((f|0)==5)ef(a,1097825,0);return}function Nb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,l=0,m=0,n=0,o=0;o=r;r=r+32|0;n=o;d=i[a>>0]|0;l=a+4|0;e=k[l>>2]|0;c=(d&1)==0?(d&255)>>>1:e;if((c|0?(Db(a)|0)<=4:0)?(c|0)>0:0){g=a+8|0;h=a+1|0;f=0;do{c=of(a,f)|0;if((c|0)==-1){if(!(d&1))e=(d&255)>>>1}else e=c;c=e-f|0;do if((c|0)<17){vf(n|0,((d&1)==0?h:k[g>>2]|0)+f|0,c|0)|0;i[n+c>>0]=0;c=Eb(n,136,213)|0;if(c|0){Ab(j[c+8>>1]|0,b);Ab(j[c+10>>1]|0,b);break}c=Te(n,45)|0;if(c|0)i[c>>0]=0;if((Ve(n)|0)<4?(m=Eb(n,2692,257)|0,m|0):0){Ab(j[m+8>>1]|0,b);Ab(j[m+10>>1]|0,b)}}while(0);f=e+1|0;d=i[a>>0]|0;e=k[l>>2]|0}while((f|0)<(((d&1)==0?(d&255)>>>1:e)|0))}r=o;return}function Ob(a,b){a=a|0;b=b|0;var c=0,d=0;c=r;r=r+16|0;d=c;Lb(d,a,0,Ve(a)|0);Nb(d,b);ff(d);r=c;return}function Pb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;e=r;r=r+16|0;d=e;c=Ve(a)|0;if((c|0)<=3){$e(d,a);i[d+3>>0]=0;if((c|0)>0){a=0;do{f=d+a|0;i[f>>0]=l[f>>0]|0|32;a=a+1|0}while((a|0)!=(c|0))}a=Fb(d)|0;if(a|0){Bb(j[a+4>>1]|0,b);Bb(j[a+6>>1]|0,b)}}r=e;return}function Qb(a,b){a=a|0;b=b|0;switch(a|0){case 62:case 48:case 46:case 45:case 14:{Bb(4112,b);break}case 47:case 20:case 13:{Bb(4165,b);break}case 12:case 21:case 11:case 10:{Bb(4104,b);break}case 44:case 16:{Bb(4105,b);break}default:{}}return}function Rb(a,b){a=a|0;b=b|0;Bb(a+8192&65535,b);return}function Sb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0;f=r;r=r+80|0;e=f;d=f+8|0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;if((k[b>>2]|0)>0){c=0;do{g=j[b+4+(c<<1)>>1]|0;h=Gc(g&1023)|0;k[e>>2]=h;k[e+4>>2]=g<<16>>16>>10;We(d,985273,e);lf(a,d);c=c+1|0}while((c|0)<(k[b>>2]|0))}r=f;return}function Tb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;D=r;r=r+16|0;C=D;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;y=(c|0)<8192?c:8192;a:do if((y|0)>0){s=C+4|0;t=a+1|0;u=C+8|0;v=C+1|0;w=a+8|0;x=a+4|0;c=0;do{c=Hb(b,c,y)|0;if((c|0)<0)break a;d=c+1|0;if((d|0)<(y|0))c=d;else break a;b:while(1){switch(i[b+c>>0]|0){case 62:break b;case 60:{z=6;break b}case 38:{z=7;break b}default:{}}c=c+1|0;if((c|0)>=(y|0))break a}if((z|0)==6){z=0;c=c+-1|0}else if((z|0)==7){z=0;c=c+-1|0}if((c|0)<0)break a;if((((((!(Kb(b,d,c,985280)|0)?!(Kb(b,d,c,985284)|0):0)?!(Kb(b,d,c,985290)|0):0)?!(Kb(b,d,c,985298)|0):0)?!(Kb(b,d,c,985304)|0):0)?!(Kb(b,d,c,985309)|0):0)?(A=Kb(b,d,c,985312)|0,B=Ib(b,d,c)|0,(B|0)>-1):0){g=B;f=0;e=d;while(1){do if(A){if(Jb(b,e,g,985318)|0?Kb(b,g+1|0,c,985330)|0:0){z=25;break}if(Jb(b,e,g,985348)|0){d=g+1|0;if(!(Kb(b,d,c,985354)|0)?!(f|(Kb(b,d,c,985367)|0)):0){d=0;z=26}else z=25}else z=24}else z=24;while(0);if((z|0)==24)if(f)z=25;else{d=0;z=26}if((z|0)==25)if(Jb(b,e,g,985377)|0){d=1;z=29}else{d=1;z=26}if((z|0)==26){z=0;if(!(Jb(b,e,g,985386)|0)?!(Jb(b,e,g,985392)|0):0)e=g+1|0;else z=29}if((z|0)==29){z=0;p=g+1|0;Mb(C,b,p,c);q=i[C>>0]|0;f=(q&1)==0;q=f?(q&255)>>>1:k[s>>2]|0;c:do if(q|0){e=i[a>>0]|0;if(!(e&1)){e=(e&255)>>>1;g=t}else{e=k[x>>2]|0;g=k[w>>2]|0}l=f?v:k[u>>2]|0;d:do if(e>>>0>=q>>>0){m=g+e|0;n=l+q|0;o=g;if((e|0)<(q|0))break;h=m+(1-q)|0;if((h|0)==(g|0))break;j=i[l>>0]|0;e=g;e:while(1){if((i[e>>0]|0)==j<<24>>24){f=e;g=l;do{g=g+1|0;if((g|0)==(n|0))break e;f=f+1|0}while((i[f>>0]|0)==(i[g>>0]|0))}e=e+1|0;if((e|0)==(h|0))break d}if(!((e|0)==(m|0)|(e-o|0)==-1))break c}while(0);kf(a,l,q)}while(0);ff(C);e=p}g=Ib(b,e,c)|0;if((g|0)<=-1)break;else f=d}}c=c+1|0}while((c|0)<(y|0))}while(0);c=i[a>>0]|0;d=(c&1)==0;if(d)e=(c&255)>>>1;else e=k[a+4>>2]|0;if(e>>>0>1){if(d)c=(c&255)>>>1;else c=k[a+4>>2]|0;nf(a,c+-1|0)}r=D;return}function Ub(a,b){a=a|0;b=b|0;var c=0;c=(b|0)<32?b:32;a:do if((c|0)>0){b=0;while(1){if((i[a+~b>>0]|0)==32)break a;b=b+1|0;if((b|0)>=(c|0)){b=0;break}}while(1){if((i[a+(0-b)>>0]&-64)<<24>>24!=-128)break a;b=b+1|0;if((b|0)>=(c|0)){b=0;break}}}else b=0;while(0);return b|0}function Vb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;d=(b|0)<32?b:32;c=0;while(1){if((c|0)>=(d|0)){e=3;break}b=c+1|0;if((i[a+c>>0]|0)==32)break;else c=b}a:do if((e|0)==3)if((d|0)>0){b=0;while(1){if((i[a+b>>0]&-64)<<24>>24!=-128)break a;b=b+1|0;if((b|0)>=(d|0)){b=0;break}}}else b=0;while(0);return b|0}function Wb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,m=0;j=a+b|0;e=k[c>>2]|0;if((b|0)>0){b=0;h=a;do{f=i[h>>0]|0;g=f&255;do if((f&255)>=192){if((g&224|0)==192){g=l[h+1>>0]|0|g<<8;a=2;break}a=i[h+1>>0]|0;f=i[h+2>>0]|0;if((g&240|0)==224){g=(a&255)<<8|g<<16|f&255;a=3;break}else{g=(a&255)<<16|g<<24|(f&255)<<8|(l[h+3>>0]|0);a=4;break}}else a=1;while(0);h=h+a|0;m=d+(e<<2)|0;f=k[m>>2]|0;k[m>>2]=g;b=((g|0)==(f|0)?a:0)+b|0;e=(g^e<<4)&4095}while(h>>>0<j>>>0)}else b=0;k[c>>2]=e;return b|0}function Xb(a,b){a=a|0;b=b|0;var c=0,d=0;c=b&-4;if((c|0)>0){d=0;b=0;do{b=((i[a+d>>0]|0)==32&1)+b+((i[a+(d|1)>>0]|0)==32&1)+((i[a+(d|2)>>0]|0)==32&1)+((i[a+(d|3)>>0]|0)==32&1)|0;d=d+4|0}while((d|0)<(c|0))}else b=0;return b|0}function Yb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;s=a+b|0;e=k[c>>2]|0;if((b|0)>0){q=a;p=0;r=a;m=a;n=0;while(1){g=i[r>>0]|0;j=g&255;f=q+1|0;i[q>>0]=g;do if(g<<24>>24!=32)if((g&255)>=192){if((j&224|0)==192){h=r+1|0;i[f>>0]=i[h>>0]|0;j=l[h>>0]|0|j<<8;f=q+2|0;h=p;o=2;break}h=r+1|0;i[f>>0]=i[h>>0]|0;g=r+2|0;f=q+3|0;i[q+2>>0]=i[g>>0]|0;if((j&240|0)==224){j=(l[h>>0]|0)<<8|j<<16|(l[g>>0]|0);h=p;o=3;break}else{o=r+3|0;i[f>>0]=i[o>>0]|0;j=(l[h>>0]|0)<<16|j<<24|(l[g>>0]|0)<<8|(l[o>>0]|0);f=q+4|0;h=p;o=4;break}}else{h=p;o=1}else{m=(p<<1|0)>(n|0)?m:f;f=m;h=0;o=1;n=0}while(0);r=r+o|0;q=d+(e<<2)|0;g=k[q>>2]|0;k[q>>2]=j;e=(j^e<<4)&4095;if(r>>>0>=s>>>0)break;else{q=f;p=((j|0)==(g|0)?o:0)+h|0;n=o+n|0}}}else f=a;k[c>>2]=e;e=f-a|0;if((e|0)>=(b+-3|0)){if((e|0)<(b|0))i[f>>0]=32}else{i[f>>0]=32;i[f+1>>0]=32;i[f+2>>0]=32;i[f+3>>0]=0}return e|0}function Zb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0;o=r;r=r+16|0;m=o;h=a+b|0;k[m>>2]=0;n=re(16384)|0;rf(n|0,0,16384)|0;if((b|0)>0){j=h;c=a;l=a+1|0;d=a;e=0;f=a;do{g=j-f|0;g=(g|0)>48?48:g;while(1)if((i[f+g>>0]&-64)<<24>>24==-128)g=g+1|0;else break;p=Xb(f,g)|0;if((p|0)<12&(Wb(f,g,m,n)|0)<19){if(e){p=Vb(f,g)|0;e=g-p|0;f=f+p|0}else e=g;if((e|0)>0){wf(d|0,f|0,e|0)|0;d=d+e|0;g=e;e=0}else{g=e;e=0}}else if(!e){d=d+(0-(Ub(d,d-c|0)|0))|0;if((d|0)==(a|0)){i[a>>0]=32;d=l;e=1}else e=1}else e=1;f=f+g|0}while(f>>>0<h>>>0)}else{c=a;d=a}c=d-c|0;if((c|0)>=(b+-3|0)){if((c|0)<(b|0))i[d>>0]=32}else{i[d>>0]=32;i[d+1>>0]=32;i[d+2>>0]=32;i[d+3>>0]=0}se(n);r=o;return c|0}function _b(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=r;r=r+16|0;d=e;if((b|0)<256)b=0;else{k[d>>2]=0;c=re(16384)|0;rf(c|0,0,16384)|0;if((Xb(a,256)|0)<64?(Wb(a,256,d,c)|0)<171:0)b=0;else b=1;se(c)}r=e;return b|0}function $b(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;y=r;r=r+48|0;x=y+32|0;t=y+16|0;s=y;q=0;do{d=j[a+568+(q<<1)>>1]|0;n=d&65535;do if(((((d<<16>>16!=-1?(o=k[a+616+(q<<2)>>2]|0,o|0):0)?(p=(k[a+808+(q<<2)>>2]|0)/(o|0)|0,(d&65535)<165&(p|0)<41):0)?(i=k[7224+(n<<2)>>2]|0,(i|0)!=26):0)?(l=td(a,i&65535)|0,(l|0)>=0):0)?(m=k[a+616+(l<<2)>>2]|0,m|0):0){d=(k[a+808+(l<<2)>>2]|0)/(m|0)|0;e=(d|0)<(p|0);if(!e?!((n|0)<(i|0)&(d|0)==(p|0)):0){f=q;g=0;h=l}else{f=l;g=1;h=q}z=e?p:d;e=m+o|0;z=ha((z|0)>41?z:41,e)|0;j[a+568+(f<<1)>>1]=-1;k[a+712+(f<<2)>>2]=0;k[a+808+(f<<2)>>2]=0;k[a+712+(h<<2)>>2]=e;k[a+808+(h<<2)>>2]=z;if(!(c|(e|0)>9&b^1))if(g){h=Gc(i)|0;z=Gc(n)|0;k[s>>2]=h;k[s+4>>2]=d;k[s+8>>2]=m;k[s+12>>2]=z;He(941120,985398,s);break}else{n=Gc(n)|0;z=Gc(i)|0;k[t>>2]=n;k[t+4>>2]=p;k[t+8>>2]=o;k[t+12>>2]=z;He(941120,985398,t);break}}while(0);q=q+1|0}while((q|0)!=24);f=0;do{d=a+568+(f<<1)|0;z=j[d>>1]|0;e=z&65535;if(((z<<16>>16!=-1?(u=k[a+616+(f<<2)>>2]|0,v=a+808+(f<<2)|0,u|0):0)?(w=(k[v>>2]|0)/(u|0)|0,(w|0)<=40):0)?(j[d>>1]=-1,k[a+712+(f<<2)>>2]=0,k[v>>2]=0,!(c|(u|0)>9&b^1)):0){z=Gc(e)|0;k[x>>2]=z;k[x+4>>2]=w;k[x+8>>2]=u;He(941120,985425,x)}f=f+1|0}while((f|0)!=24);r=y;return}function ac(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;e=c+616+(b<<2)|0;k[e>>2]=(k[c+616+(a<<2)>>2]|0)+(k[e>>2]|0);e=c+712+(b<<2)|0;d=c+712+(a<<2)|0;k[e>>2]=(k[d>>2]|0)+(k[e>>2]|0);e=c+808+(b<<2)|0;b=c+808+(a<<2)|0;k[e>>2]=(k[b>>2]|0)+(k[e>>2]|0);j[c+568+(a<<1)>>1]=-1;k[d>>2]=0;k[b>>2]=0;return}function bc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,n=0,o=0;j=r;r=r+16|0;i=j;f=b^1|c;g=0;do{d=m[a+568+(g<<1)>>1]|0;b=Hc(d)|0;a:do if(b|0){h=g;do{h=h+1|0;if((h|0)>=24)break a;e=m[a+568+(h<<1)>>1]|0}while((Hc(e)|0)!=(b|0));b=(k[a+616+(g<<2)>>2]|0)<(k[a+616+(h<<2)>>2]|0);c=b?g:h;if(!f){l=k[a+616+(c<<2)>>2]|0;n=(k[a+808+(c<<2)>>2]|0)/((l|0?l:1)|0)|0;o=Gc(b?d:e)|0;e=Gc(b?e:d)|0;k[i>>2]=o;k[i+4>>2]=n;k[i+8>>2]=l;k[i+12>>2]=e;He(941120,985446,i)}ac(c,b?h:g,a)}while(0);g=g+1|0}while((g|0)!=24);r=j;return}function cc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,l=0,m=0;l=r;r=r+48|0;h=l+32|0;j=l+24|0;g=l+16|0;f=l;Ze(985487,34,1,941120);e=k[a>>2]|0;if((e|0)!=26){m=Fc(e)|0;e=i[d>>0]|0?1097825:985485;d=k[b>>2]|0;k[f>>2]=m;k[f+4>>2]=e;k[f+8>>2]=d;He(941120,985522,f)}e=k[a+4>>2]|0;if((e|0)!=26){f=Fc(e)|0;m=k[b+4>>2]|0;k[g>>2]=f;k[g+4>>2]=m;He(941120,985535,g)}e=k[a+8>>2]|0;if((e|0)!=26){g=Fc(e)|0;m=k[b+8>>2]|0;k[j>>2]=g;k[j+4>>2]=m;He(941120,985535,j)}k[h>>2]=k[c>>2];He(941120,985546,h);Ze(1017206,5,1,941120);r=l;return}function dc(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var l=0.0,m=0,n=0,o=0,q=0,r=0,s=0,t=0,u=0,v=0;k[c>>2]=0;n=c+4|0;k[n>>2]=0;r=c+8|0;k[r>>2]=0;k[d>>2]=26;m=d+4|0;k[m>>2]=26;q=d+8|0;k[q>>2]=26;k[e>>2]=0;u=e+4|0;k[u>>2]=0;v=e+8|0;k[v>>2]=0;o=f+8|0;s=f+16|0;k[f>>2]=0;k[f+4>>2]=0;k[f+8>>2]=0;k[f+12>>2]=0;k[f+16>>2]=0;k[f+20>>2]=0;k[g>>2]=b;i[h>>0]=0;t=j[a+568>>1]|0;switch(t<<16>>16){case 26:case -1:{f=0;break}default:{k[d>>2]=t&65535;d=k[a+616>>2]|0;k[c>>2]=(k[a+808>>2]|0)/((d|0?d:1)|0)|0;if((d|0)<1)l=0.0;else l=+((k[a+712>>2]<<10|0)/(d|0)|0|0);p[f>>3]=l;f=d}}d=j[a+570>>1]|0;switch(d<<16>>16){case 26:case -1:{c=0;break}default:{k[m>>2]=d&65535;d=k[a+620>>2]|0;k[n>>2]=(k[a+812>>2]|0)/((d|0?d:1)|0)|0;if((d|0)<1)l=0.0;else l=+((k[a+716>>2]<<10|0)/(d|0)|0|0);p[o>>3]=l;c=d}}d=j[a+572>>1]|0;switch(d<<16>>16){case 26:case -1:{d=0;break}default:{k[q>>2]=d&65535;d=k[a+624>>2]|0;k[r>>2]=(k[a+816>>2]|0)/((d|0?d:1)|0)|0;if((d|0)<1)l=0.0;else l=+((k[a+720>>2]<<10|0)/(d|0)|0|0);p[s>>3]=l}}c=c+f|0;d=d+c|0;if((d|0)>(b|0)){k[g>>2]=d;b=d}r=(b|0)<1?1:b;f=(f*100|0)/(r|0)|0;k[e>>2]=f;s=(c*100|0)/(r|0)|0;c=((d*100|0)/(r|0)|0)-s|0;k[v>>2]=c;d=s-f|0;k[u>>2]=d;if((d|0)<(c|0)){d=d+1|0;k[u>>2]=d;k[v>>2]=c+-1}if((f|0)<(d|0)){k[e>>2]=f+1;k[u>>2]=d+-1}k[g>>2]=b;switch(t<<16>>16){case 26:case -1:{d=0;break}default:{d=k[a+616>>2]|0;d=((k[a+808>>2]|0)/((d|0?d:1)|0)|0|0)>40&1}}i[h>>0]=d;i[h>>0]=(100-(k[e>>2]|0)-(k[u>>2]|0)-(k[v>>2]|0)|0)>20?0:d;return}function ec(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;y=r;r=r+32|0;w=y+8|0;v=y;q=y+12|0;k[q>>2]=k[1971];k[q+4>>2]=k[1972];k[q+8>>2]=k[1973];h=k[c>>2]|0;k[d>>2]=k[b>>2];i[e>>0]=(h|0)>1&1;j=0;m=0;l=0;p=3;while(1){if((k[b+(m<<2)>>2]|0)==25){o=(k[c+(m<<2)>>2]|0)+l|0;n=m+1|0;if((n|0)<3){h=m;j=n;while(1){k[q+(h<<2)>>2]=k[q+(j<<2)>>2];h=j+1|0;if((h|0)==3)break;else{u=j;j=h;h=u}}j=k[q>>2]|0}l=p+-1|0;h=((k[c>>2]|0)*100|0)/(101-o|0)|0;k[d>>2]=k[b+(j<<2)>>2];if((k[c+(j<<2)>>2]|0)<2){i[e>>0]=0;m=n;s=j;t=o;u=l}else{m=n;s=j;t=o;u=l}}else{m=m+1|0;s=j;t=l;u=p}if((m|0)==3)break;else{j=s;l=t;p=u}}o=k[q+4>>2]|0;p=k[c+(o<<2)>>2]|0;n=ha(p,a)|0;o=b+(o<<2)|0;l=k[b+(s<<2)>>2]|0;m=(l|0)==0;a:do if(m){j=k[o>>2]|0;switch(j|0){case 26:case 0:{x=24;break a}default:{}}if((n|0)>1499&(p|0)>16){h=(p*100|0)/(101-t-(k[c+(s<<2)>>2]|0)|0)|0;k[d>>2]=j;if((p|0)<2)i[e>>0]=0}else x=23}else{b=l+-4|0;if(b>>>0<11?(1035>>>(b&2047)&1)!=0:0){j=k[o>>2]|0;if(j>>>0<15){if(16561>>>(j&32767)&1){x=23;break}}else if((j|0)==26){x=23;break}if((n|0)>1499&(p|0)>19){h=(p*100|0)/(101-t-(k[c+(s<<2)>>2]|0)|0)|0;k[d>>2]=j;if((p|0)<2)i[e>>0]=0}else x=23}else x=23}while(0);if((x|0)==23){j=k[o>>2]|0;x=24}do if((x|0)==24){if(!j){if(m)break;h=((k[c+(s<<2)>>2]|0)*100|0)/(101-t-p|0)|0;break}x=j+-4|0;if(x>>>0<11?(1035>>>(x&2047)&1)!=0:0){if(l>>>0<15?16561>>>(l&32767)&1:0)break;h=((k[c+(s<<2)>>2]|0)*100|0)/(101-t-p|0)|0}}while(0);if((h|0)<26){if(!(f^1|g)){x=Gc(k[d>>2]|0)|0;k[v>>2]=x;k[v+4>>2]=h;He(941120,985557,v)}k[d>>2]=26;i[e>>0]=0}if((h|0)<51)i[e>>0]=0;if((100-(k[c>>2]|0)-(k[c+4>>2]|0)-(k[c+8>>2]|0)|0)>20)i[e>>0]=0;if(!u){if(!(f^1|g)){x=Gc(k[d>>2]|0)|0;k[w>>2]=x;He(941120,985593,w)}k[d>>2]=26;i[e>>0]=0}r=y;return}function fc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;if(Lc(a)|0){d=c+16|0;e=k[d>>2]|0;k[c+20+(e<<2)>>2]=b;k[d>>2]=e+1&3}if(Mc(a)|0){e=c+36|0;d=k[e>>2]|0;k[c+40+(d<<2)>>2]=b;k[e>>2]=d+1&3}return}function gc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;d=rb(b,1)|0;if(Lc(a)|0?Lc(b)|0:0){e=c+56|0;f=k[e>>2]|0;k[c+60+(f<<2)>>2]=d;k[e>>2]=f+1&3}if(Mc(a)|0?Mc(b)|0:0){f=c+76|0;e=k[f>>2]|0;k[c+80+(e<<2)>>2]=d;k[f>>2]=e+1&3}return}function hc(a,b){a=a|0;b=b|0;var c=0,d=0;switch(a|0){case 16:{gc(16,69,b);break}case 69:{gc(69,16,b);break}default:{c=Hc(a)|0;if(c|0){d=0;do{if(!((d|0)==(a|0)|(c|0)!=(Hc(d)|0)))gc(a,d,b);d=d+1|0}while((d|0)!=512)}}}return}function ic(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,l=0,n=0,o=0,p=0;p=r;r=r+64|0;h=p+8|0;g=p;n=p+32|0;o=p+16|0;l=p+12|0;k[n>>2]=0;if(!c){Tb(o,a,b);Nb(o,n);if(i[e+5>>0]|0?(c=i[o>>0]|0,f=(c&1)==0,(f?(c&255)>>>1:k[o+4>>2]|0)|0):0){c=k[e>>2]|0;k[g>>2]=f?o+1|0:k[o+8>>2]|0;He(c,985624,g)}ff(o)}if(d|0){f=k[d>>2]|0;if(f|0?i[f>>0]|0:0)Ob(f,n);f=k[d+4>>2]|0;if(f|0?i[f>>0]|0:0)Pb(f,n);f=k[d+8>>2]|0;if((f|0)!=23)Qb(f,n);f=k[d+12>>2]|0;if((f|0)!=26)Rb(f,n)}Cb(n);if(i[e+5>>0]|0){Sb(o,n);d=i[o>>0]|0;f=(d&1)==0;if((f?(d&255)>>>1:k[o+4>>2]|0)|0){d=k[e>>2]|0;k[h>>2]=f?o+1|0:k[o+8>>2]|0;He(d,985648,h)}ff(o)}d=k[n>>2]|0;c=(d|0)>0;if(c){b=0;do{a=j[n+4+(b<<1)>>1]|0;f=a&1023;a=a<<16>>16>>10;if((a|0)>0)fc(f,rb(f,a)|0,e);b=b+1|0}while((b|0)<(d|0))}k[l>>2]=0;jc(o,l);g=k[o>>2]|0;if(c){b=g+40|0;f=0;while(1){l=m[n+4+(f<<1)>>1]&1023;h=g+((Hc(l)|0)<<2)|0;k[h>>2]=(k[h>>2]|0)+1;switch(l|0){case 16:{k[b>>2]=(k[b>>2]|0)+1;break}case 69:{k[b>>2]=(k[b>>2]|0)+1;break}default:{}}f=f+1|0;if((f|0)==(d|0)){a=0;break}}do{l=j[n+4+(a<<1)>>1]|0;f=l&1023;a:do if((l<<16>>16>>10|0)>0){l=Hc(f)|0;if((l|0)>0?(k[g+(l<<2)>>2]|0)==1:0)hc(f,e);switch(f|0){case 16:case 69:break;default:break a}if((k[b>>2]|0)==1)hc(f,e)}while(0);a=a+1|0}while((a|0)!=(d|0))}b=g;if(g|0){f=o+4|0;a=k[f>>2]|0;if((a|0)!=(g|0))k[f>>2]=a+(~((a+-4-b|0)>>>2)<<2);Xd(g)}r=p;return}function jc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;k[a>>2]=0;e=a+4|0;k[e>>2]=0;k[a+8>>2]=0;kc(a);c=k[e>>2]|0;a=11;d=c;while(1){k[d>>2]=k[b>>2];a=a+-1|0;if(!a)break;else d=d+4|0}k[e>>2]=c+44;return}function kc(a){a=a|0;var b=0;b=pe(44)|0;k[a+4>>2]=b;k[a>>2]=b;k[a+8>>2]=b+44;return}function lc(a){a=a|0;var b=0,c=0,d=0;c=k[a>>2]|0;d=c;if(c|0){a=a+4|0;b=k[a>>2]|0;if((b|0)!=(c|0))k[a>>2]=b+(~((b+-4-d|0)>>>2)<<2);Xd(c)}return}function mc(a,b,c,d,e,f,g,h,j,l){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0;U=r;r=r+3488|0;S=U+3112|0;O=U+3104|0;F=U+3096|0;E=U+3088|0;R=U+3080|0;L=U+3072|0;I=U+3064|0;H=U+3056|0;J=U+3040|0;C=U+3032|0;p=U+3024|0;o=U+3016|0;D=U+2112|0;m=U+3468|0;n=U+3308|0;z=U+3320|0;q=U;T=U+3168|0;A=U+3144|0;y=U+3136|0;G=U+3124|0;Q=U+3120|0;k[f>>2]=26;K=f+4|0;k[K>>2]=26;M=f+8|0;k[M>>2]=26;k[g>>2]=0;N=g+4|0;k[N>>2]=0;P=g+8|0;k[P>>2]=0;k[h>>2]=0;k[h+4>>2]=0;k[h+8>>2]=0;k[h+12>>2]=0;k[h+16>>2]=0;k[h+20>>2]=0;k[j>>2]=0;i[l>>0]=0;if(e&8192|0){ef(D,a,b);if(!(e&512)){nc(n);B=(i[n>>0]&1)==0?n+1|0:k[n+8>>2]|0;k[p>>2]=b;k[p+4>>2]=B;He(941120,985693,p);ff(n)}else{oc(m);B=(i[m>>0]&1)==0?m+1|0:k[m+8>>2]|0;k[o>>2]=b;k[o+4>>2]=B;He(941120,985674,o);ff(m)}ff(D)}if(!b)m=26;else{rd(D);k[z>>2]=941120;i[z+4>>0]=e>>>8&1;w=e>>>9&1;i[z+5>>0]=w;x=z+6|0;i[x>>0]=e>>>10&1;i[z+7>>0]=e>>>11&1;k[z+12>>2]=26;t=z+8|0;k[t>>2]=0;k[z+140>>2]=7896;o=z+144|0;k[o>>2]=0;m=z+16|0;n=m+120|0;do{k[m>>2]=0;m=m+4|0}while((m|0)<(n|0));u=e>>>12;ic(a,b,c,d,z);md(q);md(q+528|0);md(q+1056|0);md(q+1584|0);wc(T,a,b,c);k[o>>2]=T;n=A+4|0;o=A+12|0;k[A>>2]=0;k[A+4>>2]=0;k[A+8>>2]=0;k[A+12>>2]=0;k[A+16>>2]=26;k[y>>2]=0;s=re(16384)|0;p=(e&4|0)!=0;if(p)rf(s|0,0,16384)|0;q=(e&2|0)==0;v=(e&1|0)!=0;B=0;while(1){if(!(Cc(T,A)|0)){o=21;break}m=k[n>>2]|0;if(q){if(!(v|(m|0)<2049)?_b(k[A>>2]|0,m)|0:0){o=15;break}}else{m=Zb(k[A>>2]|0,m)|0;k[n>>2]=m}if(p){m=Yb(k[A>>2]|0,m,y,s)|0;k[n>>2]=m}k[t>>2]=k[o>>2];ld(A,z,D);B=m+B|0}if((o|0)==15){if(w|0){k[C>>2]=B;He(941120,985708,C)}se(s);m=mc(a,b,c,d,e|2,f,g,h,j,l)|0}else if((o|0)==21){se(s);n=(w|0)!=0;m=u&1;if(n&(m|0)==0){if(!(i[x>>0]|0))Ze(1017206,5,1,941120);vd(D)}p=(m|0)!=0;bc(D,n,p);ud(D);dc(D,B,G,f,g,h,j,l);do if(!(v|(B|0)<257)){if(i[l>>0]|0){m=k[g>>2]|0;if((m|0)>69){o=29;break}if(((k[N>>2]|0)+m|0)>92){o=29;break}}if(!(p|n^1))cc(f,g,j,l);if((B|0)<256){if(n){k[E>>2]=B;He(941120,985862,E)}m=mc(a,b,c,d,e|93,f,g,h,j,l)|0;break}else{if(n){k[F>>2]=B;He(941120,985937,F)}m=mc(a,b,c,d,e|13,f,g,h,j,l)|0;break}}else o=29;while(0);if((o|0)==29){$b(D,n,p);ud(D);dc(D,B,G,f,g,h,j,l);ec(B,f,g,Q,l,n,p);m=n^1;if(!(p|m)){o=0;do{n=k[f+(o<<2)>>2]|0;if((n|0)!=26){j=Gc(n)|0;E=k[G+(o<<2)>>2]|0;F=k[g+(o<<2)>>2]|0;k[J>>2]=j;k[J+4>>2]=E;k[J+8>>2]=F;He(941120,985771,J)}o=o+1|0}while((o|0)!=3);k[H>>2]=B;He(941120,985761,H);H=Fc(k[Q>>2]|0)|0;J=i[l>>0]|0?32:42;k[I>>2]=H;k[I+4>>2]=J;He(941120,985785,I);Ze(985793,9,1,941120)}if(m|p^1)m=k[Q>>2]|0;else{Ze(985803,37,1,941120);m=k[f>>2]|0;if((m|0)!=26){J=Gc(m)|0;g=k[g>>2]|0;k[L>>2]=J;k[L+4>>2]=g;He(941120,985841,L)}m=k[K>>2]|0;if((m|0)!=26){L=Gc(m)|0;N=k[N>>2]|0;k[O>>2]=L;k[O+4>>2]=N;He(941120,985841,O)}m=k[M>>2]|0;if((m|0)!=26){O=Gc(m)|0;P=k[P>>2]|0;k[S>>2]=O;k[S+4>>2]=P;He(941120,985841,S)}m=k[Q>>2]|0;Q=Fc(m)|0;S=i[l>>0]|0?32:42;k[R>>2]=Q;k[R+4>>2]=S;He(941120,985785,R);Ze(1017206,5,1,941120)}}}xc(T)}r=U;return m|0}function nc(a){a=a|0;ef(a,1097825,0);return}function oc(a){a=a|0;ef(a,1097825,0);return}function pc(a){a=a|0;a:do if(a>>>0>=256){if(a>>>0>=55296){switch(a&-16|0){case 64992:case 64976:{a=65533;break a}default:{}}if((a&65534|0)==65534)a=65533;else a=(a+-57344|0)>>>0<1056768?a:65533}}else a=k[7932+(a<<2)>>2]|0;while(0);return a|0}function qc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;a:do if((b|0)>0){g=0;c=0;d=0;while(1){f=i[a+g>>0]|0;if((f&-64)<<24>>24!=-128){e=(d|0)>7|((c|0)>24?1:((l[993817+((f&255)>>>4)>>0]|0)+g|0)>(b|0));if(e)break a;else d=(e&1^1)+d|0}switch(f<<24>>24){case 60:{f=1097792+c|0;i[f>>0]=38;i[f+1>>0]=108;i[f+2>>0]=116;i[f+3>>0]=59;c=c+4|0;break}case 62:{f=1097792+c|0;i[f>>0]=38;i[f+1>>0]=103;i[f+2>>0]=116;i[f+3>>0]=59;c=c+4|0;break}case 38:{f=1097792+c|0;i[f>>0]=i[993833]|0;i[f+1>>0]=i[993834]|0;i[f+2>>0]=i[993835]|0;i[f+3>>0]=i[993836]|0;i[f+4>>0]=i[993837]|0;c=c+5|0;break}case 39:{f=1097792+c|0;i[f>>0]=i[993839]|0;i[f+1>>0]=i[993840]|0;i[f+2>>0]=i[993841]|0;i[f+3>>0]=i[993842]|0;i[f+4>>0]=i[993843]|0;i[f+5>>0]=i[993844]|0;c=c+6|0;break}case 34:{f=1097792+c|0;i[f>>0]=i[993846]|0;i[f+1>>0]=i[993847]|0;i[f+2>>0]=i[993848]|0;i[f+3>>0]=i[993849]|0;i[f+4>>0]=i[993850]|0;i[f+5>>0]=i[993851]|0;c=c+6|0;break}default:{i[1097792+c>>0]=f;c=c+1|0}}g=g+1|0;if((g|0)>=(b|0))break a}}else c=0;while(0);i[1097792+c>>0]=0;return}function rc(a,b){a=a|0;b=b|0;do if(b>>>0>=128){if(b>>>0<2048){i[a>>0]=b>>>6|192;i[a+1>>0]=b&63|128;b=2;break}b=b>>>0>1114111?65533:b;if(b>>>0<65536){i[a>>0]=b>>>12|224;i[a+1>>0]=b>>>6&63|128;i[a+2>>0]=b&63|128;b=3;break}else{i[a>>0]=b>>>18|240;i[a+1>>0]=b>>>12&63|128;i[a+2>>0]=b>>>6&63|128;i[a+3>>0]=b&63|128;b=4;break}}else{i[a>>0]=b;b=1}while(0);return b|0}function sc(a,b){a=a|0;b=b|0;var c=0,d=0;d=r;r=r+16|0;c=d;if((b|0)>15)b=-1;else{vf(c|0,a|0,b|0)|0;i[c+b>>0]=0;b=Nc(c)|0;if((b|0)>-1)b=k[8956+(b<<3)+4>>2]|0;else b=-1}r=d;return b|0}function tc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0;j=a+b|0;a:do if((b|0)!=0?(i[a>>0]|0)==38:0){k[c>>2]=1;f=a+1|0;d=i[f>>0]|0;if(d<<24>>24==35){if((b|0)<4){d=-1;break}d=a+2|0;b:do switch(i[d>>0]|0){case 88:case 120:{d=a+3|0;do{if((i[d>>0]|0)!=48)break;d=d+1|0}while(d>>>0<j>>>0);if((d|0)==(j|0)){d=-1;break a}f=i[d>>0]|0;if((f+-48&255)>=10)switch(f<<24>>24){case 65:case 66:case 67:case 68:case 69:case 70:case 97:case 98:case 99:case 100:case 101:case 102:break;default:{d=-1;break a}}c:do if(d>>>0<j>>>0){e=f;b=d;while(1){if((e+-48&255)>=10)switch(e<<24>>24){case 65:case 66:case 67:case 68:case 69:case 70:case 97:case 98:case 99:case 100:case 101:case 102:break;default:{h=b;break c}}b=b+1|0;if(b>>>0>=j>>>0){h=b;break c}e=i[b>>0]|0}}else h=d;while(0);b=h;g=b-d|0;if((g|0)>=8?!((g|0)==8&f<<24>>24<56):0){d=65533;break b}d:do if(d>>>0<h>>>0){g=f;e=0;while(1){f=e<<4;e=g<<24>>24;do if((g+-48&255)>=10)if((g+-97&255)<6){e=e+-87|0;break}else{e=(g+-65&255)<6?e+-55|0:0;break}else e=e+-48|0;while(0);f=e+f|0;e=d+1|0;if((e|0)==(h|0)){d=f;break d}d=e;g=i[e>>0]|0;e=f}}else d=0;while(0);d=pc(d)|0;break}case 48:{while(1){d=d+1|0;if(d>>>0>=j>>>0){l=32;break b}if((i[d>>0]|0)!=48){l=32;break}}break}default:l=32}while(0);do if((l|0)==32){if((d|0)==(j|0)){d=-1;break a}f=i[d>>0]|0;if((f+-48&255)>=10){d=-1;break a}e:do if(d>>>0<j>>>0){b=d;while(1){b=b+1|0;if(b>>>0>=j>>>0){g=b;break e}if(((i[b>>0]|0)+-48&255)>=10){g=b;break}}}else g=d;while(0);b=g;e=b-d|0;if((e|0)>=9){if((e|0)!=10){d=65533;break}if((bf(d,993853,10)|0)>=1){d=65533;break}}if(d>>>0<g>>>0){e=(f<<24>>24)+-48|0;d=d+1|0;if((d|0)==(g|0))d=e;else{f=d;d=e;do{d=(d*10|0)+-48+(i[f>>0]|0)|0;f=f+1|0}while((f|0)!=(g|0))}}else d=0;d=pc(d)|0}while(0);if((d|0)==-1|b>>>0>j>>>0){d=-1;break}}else{g=f;if((b|0)>1?(d+-48&255)<10|((d&-33)+-65&255)<26:0){d=f;do{d=d+1|0;if(d>>>0>=j>>>0)break;h=i[d>>0]|0}while((h+-48&255)<10|((h&-33)+-65&255)<26);b=d;e=d}else{b=g;e=f}d=sc(f,b-g|0)|0;if((d|0)<0){d=-1;break}if((d|0)>255){if(e>>>0>=j>>>0){d=-1;break}if((i[e>>0]|0)!=59){d=-1;break}}}e=b;if(e>>>0<j>>>0?(i[e>>0]|0)==59:0)b=e+1|0;k[c>>2]=b-a}else l=3;while(0);if((l|0)==3){k[c>>2]=0;d=-1}return d|0}function uc(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;b=tc(a,b,d)|0;if((b|0)>0)b=rc(c,b)|0;else{k[d>>2]=1;b=0}k[e>>2]=b;return}function vc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;f=a+b|0;a:do if((b|0)>0){d=a;e=1008264;while(1){e=l[e+(l[1009064+(l[d>>0]|0)>>0]|0)>>0]|0;if((e|0)<=(c|0))break;d=d+1|0;if(d>>>0<f>>>0)e=1008264+(e*20|0)|0;else break a}switch(e|0){case 0:case 2:{b=d-a|0;break a}default:{}}b=d-a|0;while(1){d=b+-1|0;if((b|0)<=1)break a;if((i[a+d>>0]|0)==60)break;else b=d}}while(0);return b|0}function wc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;k[a>>2]=b;k[a+4>>2]=b;k[a+8>>2]=b+c;k[a+12>>2]=c;i[a+16>>0]=d&1;i[a+28>>0]=1;i[a+29>>0]=1;k[a+32>>2]=1;c=a+36|0;Pc(c);d=a+88|0;Pc(d);b=re(40960)|0;k[a+20>>2]=b;b=re(61440)|0;k[a+24>>2]=b;Qc(c);Qc(d);return}function xc(a){a=a|0;var b=0;b=k[a+20>>2]|0;if(b|0)se(b);b=k[a+24>>2]|0;if(b|0)se(b);Rc(a+88|0);Rc(a+36|0);return}function yc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0;u=r;r=r+32|0;o=u+12|0;s=u+8|0;q=u+4|0;n=u;p=u+16|0;k[q>>2]=0;a:do if((c|0)>0){m=a+16|0;j=a+32|0;a=0;e=0;while(1){yd(b+e|0,c-e|0,o);e=(k[o>>2]|0)+e|0;if((e|0)>=(c|0)){e=c;a=0;break a}g=b+e|0;h=i[g>>0]|0;f=h&255;b:do if(((h&-32)<<24>>24==32?(i[1009320+f>>0]|0)!=0:0)?(i[m>>0]|0)==0:0)switch(h<<24>>24){case 60:{a=vc(g,c-e|0,k[j>>2]|0)|0;k[q>>2]=a;break b}case 62:{k[q>>2]=1;a=1;break b}case 38:{uc(g,c-e|0,p,q,n);k[o>>2]=l[1009576+(l[p>>0]|0)>>0];k[s>>2]=p;a=(xd(s,o)|0)&255;t=12;break b}default:break b}else t=11;while(0);if((t|0)==11){a=l[1009576+f>>0]|0;k[q>>2]=a;k[o>>2]=a;k[s>>2]=g;a=(xd(s,o)|0)&255;t=12}if((t|0)==12){t=0;if(a|0)break a;a=k[q>>2]|0}e=a+e|0;if((e|0)>=(c|0)){a=0;break}}}else{e=0;a=0}while(0);k[d>>2]=a;r=u;return e|0}function zc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0;w=r;r=r+16|0;p=w+4|0;o=w;t=a+20|0;m=k[t>>2]|0;k[b>>2]=m;u=b+4|0;k[u>>2]=0;v=a+4|0;k[b+8>>2]=(k[v>>2]|0)-(k[a>>2]|0);k[b+12>>2]=0;k[b+16>>2]=26;l=b+20|0;i[l>>0]=0;s=a+12|0;n=k[s>>2]|0;n=(n+-40928|0)>>>0<40928?(n|0)/2|0:40896;i[m>>0]=32;i[(k[t>>2]|0)+1>>0]=0;b=k[s>>2]|0;if((b|0)<1)b=0;else{m=a+16|0;j=a+32|0;c=0;g=b;h=0;a=1;b=0;while(1){d=k[v>>2]|0;e=d+b|0;f=i[e>>0]|0;f=f<<24>>24==13?10:f;if(((f&-32)<<24>>24==32?(i[1009320+(f&255)>>0]|0)!=0:0)?(i[m>>0]|0)==0:0){a:do switch(f<<24>>24){case 60:{b:do if((b|0)<(g+-3|0))switch(i[d+(b+1)>>0]|32|0){case 112:{d=(i[d+(b+2)>>0]|0)<64?10:32;break b}case 98:{if((i[d+(b+2)>>0]|32|0)!=114){d=32;break b}d=(i[d+(b+3)>>0]|0)<64?10:32;break b}case 116:{if((i[d+(b+2)>>0]|32|0)!=114){d=32;break b}d=(i[d+(b+3)>>0]|0)<64?10:32;break b}default:{d=32;break b}}else d=32;while(0);c=(vc(e,g-b|0,k[j>>2]|0)|0)+1|0;k[p>>2]=c;if(h)switch(d<<24>>24){case 10:case 32:{e=d;d=1;break a}default:{}}i[(k[t>>2]|0)+a>>0]=d;e=d;d=d<<24>>24==32|d<<24>>24==10;a=a+1|0;break}case 62:{k[p>>2]=1;i[(k[t>>2]|0)+a>>0]=62;c=1;e=62;d=h;a=a+1|0;break}case 38:{uc(e,g-b|0,(k[t>>2]|0)+a|0,p,o);c=k[p>>2]|0;e=38;d=h;a=(k[o>>2]|0)+a|0;break}default:{e=f;d=h}}while(0);h=c;b=c+b|0}else{if(h)switch(f<<24>>24){case 10:case 32:{d=1;break}default:q=22}else q=22;if((q|0)==22){q=0;i[(k[t>>2]|0)+a>>0]=f;d=f<<24>>24==32|f<<24>>24==10;a=a+1|0}h=c;e=f;b=b+1|0}if(!((a|0)<(n|0)|e<<24>>24!=10&e<<24>>24!=32)){q=25;break}if((a|0)>40927){q=28;break}g=k[s>>2]|0;if((g|0)<=(b|0))break;else{c=h;h=d}}if((q|0)==25)i[l>>0]=1;else if((q|0)==28)i[l>>0]=1;d=k[v>>2]|0;c:do if((b|0)>0){c=b;while(1){if((i[d+c>>0]&-64)<<24>>24!=-128){b=c;break c}b=c+-1|0;a=a+-1|0;if((c|0)>1)c=b;else break}}while(0);k[v>>2]=d+b;k[s>>2]=(k[s>>2]|0)-b;i[(k[t>>2]|0)+a>>0]=32;i[(k[t>>2]|0)+(a+1)>>0]=32;i[(k[t>>2]|0)+(a+2)>>0]=32;i[(k[t>>2]|0)+(a+3)>>0]=0;k[u>>2]=a;b=1}r=w;return b|0}function Ac(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;C=r;r=r+32|0;s=C+16|0;v=C+12|0;c=C+8|0;u=C+4|0;t=C;if(!(i[a+28>>0]|0))b=zc(a,b)|0;else{z=a+20|0;y=k[z>>2]|0;k[b>>2]=y;A=b+4|0;k[A>>2]=0;B=a+4|0;o=b+8|0;k[o>>2]=(k[B>>2]|0)-(k[a>>2]|0);d=b+12|0;k[d>>2]=0;k[b+16>>2]=26;p=b+20|0;i[p>>0]=0;x=a+12|0;q=k[x>>2]|0;q=(q+-40928|0)>>>0<40928?(q|0)/2|0:40896;k[u>>2]=0;k[t>>2]=0;i[y>>0]=32;i[(k[z>>2]|0)+1>>0]=0;y=a+36|0;Qc(y);Xc(y,k[o>>2]|0);b=yc(a,k[B>>2]|0,k[x>>2]|0,c)|0;k[B>>2]=(k[B>>2]|0)+b;k[x>>2]=(k[x>>2]|0)-b;if((b|0)==1)Vc(y,1);else{Xc(y,b);Wc(y,1)}b=k[x>>2]|0;if((b|0)<1){Tc(y);b=0}else{o=k[c>>2]|0;k[d>>2]=o;m=a+16|0;n=a+29|0;j=a+32|0;d=b;c=1;a=0;b=0;do{a:do if((d|0)>(b|0)){g=a;while(1){f=(k[B>>2]|0)+b|0;a=i[f>>0]|0;e=a&255;b:do if(((a&-32)<<24>>24==32?(i[1009320+e>>0]|0)!=0:0)?(i[m>>0]|0)==0:0){switch(a<<24>>24){case 62:case 60:{h=c;c=0;break a}case 38:break;default:break b}uc(f,d-b|0,(k[z>>2]|0)+c|0,u,t);g=(k[z>>2]|0)+c|0;k[s>>2]=l[1009576+(l[g>>0]|0)>>0];k[v>>2]=g;g=(xd(v,s)|0)&255}else w=15;while(0);if((w|0)==15){w=0;a=l[1009576+e>>0]|0;k[t>>2]=a;k[u>>2]=a;e=(k[z>>2]|0)+c|0;if((b|0)<(d+-3|0)){h=l[f>>0]|l[f+1>>0]<<8|l[f+2>>0]<<16|l[f+3>>0]<<24;i[e>>0]=h;i[e+1>>0]=h>>8;i[e+2>>0]=h>>16;i[e+3>>0]=h>>24}else vf(e|0,f|0,a|0)|0;g=(k[B>>2]|0)+b|0;k[s>>2]=l[1009576+(l[g>>0]|0)>>0];k[v>>2]=g;g=(xd(v,s)|0)&255}if((g|0)!=40&(g|0)!=(o|0)){if(!g){h=c;c=0;break a}d=k[u>>2]|0;h=(k[B>>2]|0)+b+d|0;k[s>>2]=l[1009576+(l[h>>0]|0)>>0];k[v>>2]=h;h=xd(v,s)|0;if(!(h<<24>>24==0|(h&255|0)==(o|0))?(i[n>>0]|0)!=0:0){h=c;c=g;break a}}else d=k[u>>2]|0;b=d+b|0;a=k[t>>2]|0;c=a+c|0;do if((d|0)!=(a|0))if((d|0)<(a|0)){Vc(y,d);Wc(y,a-d|0);break}else{Vc(y,a);Xc(y,d-a|0);break}else Vc(y,d);while(0);if((c|0)>40927)break;d=k[x>>2]|0;if((d|0)<=(b|0)){h=c;c=g;break a}}i[p>>0]=1;h=c;c=g}else{h=c;c=a}while(0);d=k[x>>2]|0;c:do if((d|0)>(b|0))while(1){yd((k[B>>2]|0)+b|0,d-b|0,s);d=k[s>>2]|0;k[u>>2]=d;b=d+b|0;Xc(y,d);d=k[x>>2]|0;if((d|0)<=(b|0)){a=c;break c}a=(k[B>>2]|0)+b|0;e=i[a>>0]|0;f=e&255;d:do if(((e&-32)<<24>>24==32?(i[1009320+f>>0]|0)!=0:0)?(i[m>>0]|0)==0:0)switch(e<<24>>24){case 60:{c=vc(a,d-b|0,k[j>>2]|0)|0;k[u>>2]=c;break d}case 62:{k[u>>2]=1;c=1;break d}case 38:{uc(a,d-b|0,(k[z>>2]|0)+h|0,u,t);c=(k[z>>2]|0)+h|0;k[s>>2]=l[1009576+(l[c>>0]|0)>>0];k[v>>2]=c;c=(xd(v,s)|0)&255;w=42;break d}default:{w=42;break d}}else w=41;while(0);if((w|0)==41){c=l[1009576+f>>0]|0;k[u>>2]=c;k[s>>2]=c;k[v>>2]=a;c=(xd(v,s)|0)&255;w=42}if((w|0)==42){w=0;if(c|0){a=c;break c}c=k[u>>2]|0}b=c+b|0;Xc(y,c);d=k[x>>2]|0;if((d|0)<=(b|0)){a=0;break}else c=0}else a=c;while(0);c=h+1|0;i[(k[z>>2]|0)+h>>0]=32;Wc(y,1);if((a|0)!=40&(a|0)!=(o|0))break;if((c|0)>=(q|0)){w=48;break}d=k[x>>2]|0}while((b|0)<(d|0));if((w|0)==48)i[p>>0]=1;e=k[x>>2]|0;e:do if((b|0)>0){a=(b|0)<(e|0);d=b;while(1){if(!a){b=d;break e}if((i[(k[B>>2]|0)+d>>0]&-64)<<24>>24!=-128){b=d;break e}b=d+-1|0;c=c+-1|0;if((d|0)>1)d=b;else break}}while(0);k[B>>2]=(k[B>>2]|0)+b;k[x>>2]=e-b;i[(k[z>>2]|0)+c>>0]=32;i[(k[z>>2]|0)+(c+1)>>0]=32;i[(k[z>>2]|0)+(c+2)>>0]=32;i[(k[z>>2]|0)+(c+3)>>0]=0;Wc(y,4);Tc(y);k[A>>2]=c;b=1}}r=C;return b|0}function Bc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;c=r;r=r+16|0;g=c+4|0;d=a+88|0;Qc(d);e=b+4|0;f=a+24|0;zd(k[b>>2]|0,(k[e>>2]|0)+3|0,k[f>>2]|0,61440,(i[a+16>>0]|0)!=0,c+8|0,g,c,d);a=k[g>>2]|0;i[(k[f>>2]|0)+a>>0]=0;k[b>>2]=k[f>>2];k[e>>2]=a+-3;Tc(d);r=c;return}function Cc(a,b){a=a|0;b=b|0;var c=0;c=Ac(a,b)|0;Bc(a,b);return c|0}function Dc(a){a=a|0;a=(a|0)<0?0:a;return k[15988+(((a|0)>101?0:a)<<2)>>2]|0}function Ec(a){a=a|0;a=(a|0)<0?0:a;return k[16396+(((a|0)>101?0:a)<<2)>>2]|0}function Fc(a){a=a|0;a=(a|0)<0?26:a;return k[11076+(((a|0)>613?26:a)<<2)>>2]|0}function Gc(a){a=a|0;a=(a|0)<0?26:a;return k[13532+(((a|0)>613?26:a)<<2)>>2]|0}function Hc(a){a=a|0;do switch(a|0){case 40:case 38:{a=1;break}case 105:{a=2;break}case 135:{a=2;break}case 17:{a=3;break}case 68:{a=3;break}case 84:{a=4;break}case 83:{a=4;break}case 78:{a=5;break}case 28:{a=5;break}case 29:{a=5;break}case 160:{a=5;break}case 35:{a=6;break}case 64:{a=6;break}case 51:{a=6;break}case 43:{a=6;break}case 10:{a=7;break}case 80:{a=7;break}case 1:{a=7;break}case 31:{a=8;break}case 14:{a=8;break}case 12:{a=8;break}case 143:{a=9;break}case 147:{a=9;break}default:a=0}while(0);return a|0}function Ic(a){a=a|0;if(a>>>0>101)a=26;else a=k[16804+(a<<2)>>2]|0;return a|0}function Jc(a){a=a|0;if((a|0)<512)a=i[992810+a>>0]|0;else a=0;return a|0}function Kc(a,b){a=a|0;b=b|0;do if(a>>>0<=101){if((k[16396+(a<<2)>>2]|0)>>>0<2){b=k[16804+(a<<2)>>2]|0;break}b=b&255;if((a|0)==1){b=m[941344+(b<<1)>>1]|0;break}else{b=m[941856+(b<<1)>>1]|0;break}}else b=26;while(0);return b|0}function Lc(a){a=a|0;if((a|0)<512)a=(m[941344+((l[992810+a>>0]|0)<<1)>>1]|0|0)==(a|0);else a=0;return a|0}function Mc(a){a=a|0;if((a|0)<512)a=(m[941856+((l[992810+a>>0]|0)<<1)>>1]|0|0)==(a|0);else a=0;return a|0}function Nc(a){a=a|0;var b=0,c=0,d=0,e=0;c=0;e=265;a:while(1)while(1){if((c|0)>=(e|0)){b=-1;break a}b=c+e>>1;d=_e(a,k[8956+(b<<3)>>2]|0)|0;if((d|0)<0){e=b;continue a}if((d|0)>0)c=b+1|0;else break a}return b|0}function Oc(a){a=a|0;switch(a|0){case 1:{a=0;break}case 3:{a=1;break}case 6:{a=2;break}default:a=3}return a|0}function Pc(a){a=a|0;var b=0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=1;a=a+16|0;b=a+36|0;do{k[a>>2]=0;a=a+4|0}while((a|0)<(b|0));return}function Qc(a){a=a|0;var b=0;if(!(i[a>>0]&1)){i[a+1>>0]=0;i[a>>0]=0}else{i[k[a+8>>2]>>0]=0;k[a+4>>2]=0}k[a+12>>2]=1;a=a+16|0;b=a+36|0;do{k[a>>2]=0;a=a+4|0}while((a|0)<(b|0));return}function Rc(a){a=a|0;ff(a);return}function Sc(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0,j=0;j=a+16|0;g=k[j>>2]|0;do if(g|0){h=a+12|0;b=k[h>>2]|0;if((b|0)==1){e=i[a>>0]|0;f=(e&1)==0;if(f)c=(e&255)>>>1;else c=k[a+4>>2]|0;if(c|0){if(f){c=(e&255)>>>1;d=a+1|0}else{c=k[a+4>>2]|0;d=k[a+8>>2]|0}d=i[d+(c+-1)>>0]|0;if((d&-64)<<24>>24==64?(g+(d&63)|0)>>>0<64:0){if(f){c=(e&255)>>>1;b=a+1|0}else{c=k[a+4>>2]|0;b=k[a+8>>2]|0}a=b+(c+-1)|0;i[a>>0]=(l[a>>0]|0)+g;k[j>>2]=0;break}}}if(g>>>0>63){c=g;d=0;e=30;while(1){b=c>>>e&63;if(d|(b|0)!=0){mf(a,b&255);b=1}else b=0;if((e|0)<=6)break;c=k[j>>2]|0;d=b;e=e+-6|0}c=k[j>>2]|0;b=k[h>>2]|0}else c=g;mf(a,(c&63|b<<6)&255);k[j>>2]=0}while(0);return}function Tc(a){a=a|0;Uc(a);a=a+20|0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=0;k[a+16>>2]=0;k[a+20>>2]=0;return}function Uc(a){a=a|0;var b=0,c=0;if(!(k[a+16>>2]|0)){b=i[a>>0]|0;if(!(b&1))b=(b&255)>>>1;else b=k[a+4>>2]|0;if(!b)c=6}else c=6;if((c|0)==6){Vc(a,1);Sc(a)}return}function Vc(a,b){a=a|0;b=b|0;var c=0;do if(b|0){c=a+44|0;k[c>>2]=(k[c>>2]|0)+b;c=a+48|0;k[c>>2]=(k[c>>2]|0)+b;c=a+12|0;if((k[c>>2]|0)==1){a=a+16|0;k[a>>2]=(k[a>>2]|0)+b;break}else{Sc(a);k[c>>2]=1;k[a+16>>2]=b;break}}while(0);return}function Wc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;do if(b|0){d=a+48|0;k[d>>2]=(k[d>>2]|0)+b;d=a+12|0;e=k[d>>2]|0;if((e|0)==2){a=a+16|0;k[a>>2]=(k[a>>2]|0)+b;break}c=a+16|0;if((b|0)==1&(e|0)==3?(k[c>>2]|0)==1:0){k[d>>2]=1;break}Sc(a);k[d>>2]=2;k[c>>2]=b}while(0);return}function Xc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;do if(b|0){d=a+44|0;k[d>>2]=(k[d>>2]|0)+b;d=a+12|0;e=k[d>>2]|0;if((e|0)==3){a=a+16|0;k[a>>2]=(k[a>>2]|0)+b;break}c=a+16|0;if((b|0)==1&(e|0)==2?(k[c>>2]|0)==1:0){k[d>>2]=1;break}Sc(a);k[d>>2]=3;k[c>>2]=b}while(0);return}function Yc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,l=0,n=0,o=0,p=0,q=0,s=0,t=0;t=r;r=r+16|0;l=t;qd(f,l);h=k[l>>2]|0;o=Kc(a,h&255)|0;l=k[l+4>>2]|0;q=Kc(a,l&255)|0;n=f+16|0;if((d|0)>0)s=(m[n+(h<<1)>>1]<<10|0)/(d|0)|0;else s=0;p=(Oc(a)|0)+(o<<2)|0;p=j[(k[(k[e+140>>2]|0)+32>>2]|0)+(p<<1)>>1]|0;j[g>>1]=c;j[g+2>>1]=b;j[g+4>>1]=o;j[g+6>>1]=q;c=j[n+(h<<1)>>1]|0;j[g+8>>1]=c;h=j[n+(l<<1)>>1]|0;j[g+10>>1]=h;j[g+12>>1]=d;e=k[f+12>>2]|0;j[g+14>>1]=e;j[g+16>>1]=a;e=(pb(c&65535,h&65535,e&65535)|0)&255;h=g+18|0;i[h>>0]=e;e=Hc(o)|0;if(e|0?(e|0)==(Hc(q)|0):0)i[h>>0]=100;s=(qb(s,p)|0)&255;i[g+19>>0]=s;r=t;return}function Zc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;e=(k[a+8>>2]|0)==1;f=e?a+96|0:a+116|0;d=e?a+16|0:a+36|0;c=k[d+4>>2]|0;if(c|0)kb(c,b);c=k[d+8>>2]|0;if(c|0)kb(c,b);c=k[d+12>>2]|0;if(c|0)kb(c,b);c=k[d+16>>2]|0;if(c|0)kb(c,b);e=e?a+56|0:a+76|0;c=k[f+4>>2]|0;if(c|0)kb(c,b);c=k[f+8>>2]|0;if(c|0)kb(c,b);c=k[f+12>>2]|0;if(c|0)kb(c,b);c=k[f+16>>2]|0;if(c|0)kb(c,b);d=b+16|0;c=k[e+4>>2]|0;if(c|0)j[d+((c>>>8&255)<<1)>>1]=0;c=k[e+8>>2]|0;if(c|0)j[d+((c>>>8&255)<<1)>>1]=0;c=k[e+12>>2]|0;if(c|0)j[d+((c>>>8&255)<<1)>>1]=0;c=k[e+16>>2]|0;if(c|0)j[d+((c>>>8&255)<<1)>>1]=0;return}function _c(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,l=0,n=0,o=0,p=0,q=0,s=0,t=0;t=r;r=r+16|0;h=t;s=k[b+56064+(c<<2)>>2]|0;q=k[b+56064+(c+1<<2)>>2]|0;nd(f);k[e+16>>2]=0;k[e+20>>2]=0;if(i[d+7>>0]|0){p=k[d>>2]|0;k[h>>2]=s;k[h+4>>2]=q;He(p,1017069,h)}k[e>>2]=s;k[e+12>>2]=q-s;if((q|0)>(s|0)){h=d+96|0;l=d+8|0;n=d+116|0;p=s;do{o=k[b+24056+(p<<3)+4>>2]|0;kb(o,f);e=b+24056+(p<<3)+2|0;c=j[e>>1]|0;if((c&65535)<2){od(f);c=j[e>>1]|0}if(c<<16>>16==3){e=(k[l>>2]|0)==1?h:n;c=k[e>>2]|0;k[e+4+(c<<2)>>2]=o;k[e>>2]=c+1&3}p=p+1|0}while((p|0)!=(q|0))}Zc(d,f);p=m[b+24056+(s<<3)>>1]|0;Yc(a,s,p,(m[b+24056+(q<<3)>>1]|0)-p|0,d,f,g);k[d+12>>2]=m[g+4>>1];r=t;return}function $c(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0;x=r;r=r+608|0;w=x+552|0;s=x+528|0;p=x;q=x+576|0;k[w>>2]=0;k[w+4>>2]=0;k[w+8>>2]=0;k[w+12>>2]=0;k[w+16>>2]=0;k[w+20>>2]=0;k[s>>2]=0;k[s+4>>2]=0;k[s+8>>2]=0;k[s+12>>2]=0;k[s+16>>2]=0;k[s+20>>2]=0;g=b+24|0;if((k[g>>2]|0)>0){i=s+12|0;l=s+16|0;m=s+4|0;n=s+20|0;o=s+8|0;t=0;do{md(p);_c(a,b,t,c,s,p,q);h=k[d>>2]|0;if((h|0)<50){u=d+4+(h*20|0)|0;f=q;v=u+20|0;do{j[u>>1]=j[f>>1]|0;u=u+2|0;f=f+2|0}while((u|0)<(v|0));h=(k[d>>2]|0)+1|0;k[d>>2]=h};k[w>>2]=k[s>>2];k[w+4>>2]=k[s+4>>2];k[w+8>>2]=k[s+8>>2];k[w+12>>2]=k[s+12>>2];k[w+16>>2]=k[s+16>>2];k[w+20>>2]=k[s+20>>2];k[s>>2]=(k[s>>2]|0)+(k[i>>2]|0);k[m>>2]=(k[m>>2]|0)+(k[l>>2]|0);k[o>>2]=(k[o>>2]|0)+(k[n>>2]|0);t=t+1|0}while((t|0)<(k[g>>2]|0))}else h=k[d>>2]|0;i=k[b+20>>2]|0;f=j[b+24056+(i<<3)>>1]|0;g=d+4+(h*20|0)|0;u=g;v=u+20|0;do{j[u>>1]=0;u=u+2|0}while((u|0)<(v|0));j[g>>1]=f;j[d+4+(h*20|0)+2>>1]=i;k[e>>2]=k[w>>2];k[e+4>>2]=k[w+4>>2];k[e+8>>2]=k[w+8>>2];k[e+12>>2]=k[w+12>>2];k[e+16>>2]=k[w+16>>2];k[e+20>>2]=k[w+20>>2];r=x;return}function ad(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;if((k[a>>2]|0)>0){c=0;do{e=l[a+4+(c*20|0)+18>>0]|0;d=l[a+4+(c*20|0)+19>>0]|0;sd(b,j[a+4+(c*20|0)+4>>1]|0,m[a+4+(c*20|0)+12>>1]|0,m[a+4+(c*20|0)+8>>1]|0,e>>>0<d>>>0?e:d);c=c+1|0}while((c|0)<(k[a>>2]|0))}return}function bd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0;p=r;r=r+112|0;o=p+96|0;n=p+80|0;l=p+64|0;h=p+48|0;g=p+32|0;i=p+16|0;e=p;t=Dc(k[c>>2]|0)|0;d=c+8|0;s=k[d>>2]|0;j=c+12|0;q=k[j>>2]|0;m=c+16|0;f=k[m>>2]|0;k[e>>2]=t;k[e+4>>2]=s;k[e+8>>2]=q;k[e+12>>2]=f;He(a,1017096,e);e=c+4|0;a:do if((k[e>>2]|0)>0){f=0;do{if((f|0)<(k[d>>2]|0)){s=k[c+32+(f<<3)>>2]|0;t=k[c+32+(f<<3)+4>>2]|0;qc(b+s|0,6);k[i>>2]=f;k[i+4>>2]=s;k[i+8>>2]=(t|0)<0?(t&2147483647)+2e9|0:t;k[i+12>>2]=1097792;He(a,1017160,i)}if((f|0)<(k[j>>2]|0)){s=k[c+8040+(f<<3)>>2]|0;t=k[c+8040+(f<<3)+4>>2]|0;qc(b+s|0,12);k[g>>2]=f;k[g+4>>2]=s;k[g+8>>2]=t;k[g+12>>2]=1097792;He(a,1017175,g)}if((f|0)<(k[m>>2]|0)){s=k[c+16048+(f<<3)>>2]|0;t=k[c+16048+(f<<3)+4>>2]|0;qc(b+s|0,12);k[h>>2]=f;k[h+4>>2]=s;k[h+8>>2]=t;k[h+12>>2]=1097792;He(a,1017191,h)}if((f|0)<(k[d>>2]|0))Ze(1017206,5,1,a);if((f|0)>50)break a;f=f+1|0}while((f|0)<(k[e>>2]|0))}while(0);d=k[d>>2]|0;if((d|0)>50){s=k[c+32+(d<<3)>>2]|0;t=k[c+32+(d<<3)+4>>2]|0;qc(b+s|0,6);k[l>>2]=d;k[l+4>>2]=s;k[l+8>>2]=(t|0)<0?(t&2147483647)+2e9|0:t;k[l+12>>2]=1097792;He(a,1017160,l)}d=k[j>>2]|0;if((d|0)>50){s=k[c+8040+(d<<3)>>2]|0;t=k[c+8040+(d<<3)+4>>2]|0;qc(b+s|0,12);k[n>>2]=d;k[n+4>>2]=s;k[n+8>>2]=t;k[n+12>>2]=1097792;He(a,1017175,n)}d=k[m>>2]|0;if((d|0)>50){s=k[c+16048+(d<<3)>>2]|0;t=k[c+16048+(d<<3)+4>>2]|0;qc(b+s|0,12);k[o>>2]=d;k[o+4>>2]=s;k[o+8>>2]=t;k[o+12>>2]=1097792;He(a,1017191,o)}Ze(1017206,5,1,a);r=p;return}function cd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0,n=0,o=0;l=r;r=r+48|0;j=l+40|0;g=l+16|0;h=l+8|0;d=l;f=c+20|0;k[d>>2]=k[f>>2];He(a,1017212,d);d=k[f>>2]|0;if((d|0)>=0){e=0;while(1){if(!((e|0)>50&(e|0)<(d+-1|0))){o=m[c+24056+(e<<3)>>1]|0;n=i[1017266+(m[c+24056+(e<<3)+2>>1]|0)>>0]|0;d=k[c+24056+(e<<3)+4>>2]|0;qc(b+o|0,6);k[g>>2]=e;k[g+4>>2]=o;k[g+8>>2]=n;k[g+12>>2]=d;k[g+16>>2]=1097792;He(a,1017271,g);d=k[f>>2]|0}if((e|0)<(d|0))e=e+1|0;else break}}Ze(1017206,5,1,a);e=c+24|0;k[h>>2]=k[e>>2];He(a,1017242,h);if((k[e>>2]|0)>=0){d=0;while(1){o=k[c+56064+(d<<2)>>2]|0;k[j>>2]=d;k[j+4>>2]=o;He(a,1017294,j);if((d|0)<(k[e>>2]|0))d=d+1|0;else break}}Ze(1017206,5,1,a);r=l;return}function dd(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,l=0,n=0,o=0,p=0;c=r;r=r+48|0;d=c;p=m[b>>1]|0;o=m[b+2>>1]|0;n=Gc(m[b+4>>1]|0)|0;l=m[b+8>>1]|0;i=Gc(m[b+6>>1]|0)|0;h=m[b+10>>1]|0;g=m[b+12>>1]|0;f=m[b+14>>1]|0;e=Dc(m[b+16>>1]|0)|0;b=j[b+18>>1]|0;k[d>>2]=p;k[d+4>>2]=o;k[d+8>>2]=n;k[d+12>>2]=l;k[d+16>>2]=i;k[d+20>>2]=h;k[d+24>>2]=g;k[d+28>>2]=f;k[d+32>>2]=e;k[d+36>>2]=b&255;k[d+40>>2]=(b&65535)>>>8&65535;He(a,1017302,d);r=c;return}function ed(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=r;r=r+16|0;d=e+8|0;c=e;k[c>>2]=k[b>>2];He(a,1017351,c);Ze(1017382,101,1,a);if((k[b>>2]|0)>=0){c=0;while(1){k[d>>2]=c;He(a,1017484,d);dd(a,b+4+(c*20|0)|0);if((c|0)<(k[b>>2]|0))c=c+1|0;else break}}Ze(1017206,5,1,a);r=e;return}function fd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;d=k[a+140>>2]|0;if(b){t=k[d+4>>2]|0;r=0;s=t;b=d+8|0;d=d+12|0}else{r=1;s=k[d+16>>2]|0;t=k[d+20>>2]|0;b=d+24|0;d=d+28|0}e=k[b>>2]|0;b=k[d>>2]|0;o=c+8|0;d=k[o>>2]|0;p=k[c+12>>2]|0;q=k[c+16>>2]|0;j[c+24056>>1]=k[c+28>>2];j[c+24058>>1]=r;n=rb(Ic(k[a+8>>2]|0)|0,1)|0;k[c+24060>>2]=n;if((q|0)>0|((p|0)>0|(d|0)>0)){n=b+4|0;m=e+4|0;g=0;i=0;l=0;b=1;while(1){h=k[c+32+(g<<3)>>2]|0;f=k[c+8040+(i<<3)>>2]|0;a=k[c+16048+(l<<3)>>2]|0;do if((i|0)>=(p|0)|(f|0)>(h|0)|(f|0)>(a|0)){if(!((a|0)>(f|0)|((l|0)>=(q|0)|(a|0)>(h|0)))){f=l+1|0;e=k[(k[n>>2]|0)+(k[c+16048+(l<<3)+4>>2]<<2)>>2]|0;if(!e){a=i;e=f;break}j[c+24056+(b<<3)>>1]=a;j[c+24056+(b<<3)+2>>1]=3;k[c+24056+(b<<3)+4>>2]=e;a=i;e=f;b=b+1|0;break}f=k[c+32+(g<<3)+4>>2]|0;a=f&2147483647;f=(f|0)<0?t:s;g=g+1|0;e=k[f+8>>2]|0;if((a|0)<(e|0)){e=k[(k[f+4>>2]|0)+(a<<2)>>2]|0;if(!e){a=i;e=l;break}j[c+24056+(b<<3)>>1]=h;j[c+24056+(b<<3)+2>>1]=r;k[c+24056+(b<<3)+4>>2]=e;a=i;e=l;b=b+1|0;break}a=a-e+a|0;f=k[f+4>>2]|0;e=k[f+(a<<2)>>2]|0;a=k[f+(a+1<<2)>>2]|0;if(e){j[c+24056+(b<<3)>>1]=h;j[c+24056+(b<<3)+2>>1]=r;k[c+24056+(b<<3)+4>>2]=e;b=b+1|0}if(!a){a=i;e=l}else{j[c+24056+(b<<3)>>1]=h;j[c+24056+(b<<3)+2>>1]=r;k[c+24056+(b<<3)+4>>2]=a;a=i;e=l;b=b+1|0}}else{a=i+1|0;e=k[(k[m>>2]|0)+(k[c+8040+(i<<3)+4>>2]<<2)>>2]|0;if(!e)e=l;else{j[c+24056+(b<<3)>>1]=f;j[c+24056+(b<<3)+2>>1]=2;k[c+24056+(b<<3)+4>>2]=e;e=l;b=b+1|0}}while(0);if((e|0)<(q|0)|((a|0)<(p|0)|(g|0)<(d|0))){i=a;l=e}else break}d=k[o>>2]|0}else b=1;k[c+20>>2]=b;j[c+24056+(b<<3)>>1]=k[c+32+(d<<3)>>2];k[c+24056+(b<<3)+4>>2]=0;return}function gd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,n=0,o=0;o=b&1^1;i=b?50:20;j=c+20|0;e=k[j>>2]|0;b=k[c+8>>2]|0;if((b|0)>0){l=(i>>>1)+i|0;n=i<<1;h=b;f=0;d=0;b=a;do{if((h|0)>=(l|0))if((h|0)<(n|0))g=h+1>>1;else g=i;else g=h;k[c+56064+(d<<2)>>2]=f;k[c+56268+(d<<2)>>2]=b;d=d+1|0;if((f|0)<(e|0)&(g|0)>0){a=0;b=f;do{a=((m[c+24056+(b<<3)+2>>1]|0|0)==(o|0)&1)+a|0;b=b+1|0}while((b|0)<(e|0)&(a|0)<(g|0));f=b}b=m[c+24056+(f<<3)>>1]|0;h=h-g|0}while((h|0)>0);e=k[j>>2]|0}else{k[c+56064>>2]=0;k[c+56268>>2]=m[c+24056>>1];d=1;b=a}k[c+24>>2]=d;k[c+56064+(d<<2)>>2]=e;k[c+56268+(d<<2)>>2]=b;return}function hd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0;j=r;r=r+1056|0;h=j+24|0;g=c+7|0;if(i[g>>0]|0){Ze(1017490,12,1,k[c>>2]|0);bd(k[c>>2]|0,k[a>>2]|0,f)}fd(c,e,f);gd(b,e,f);if(i[g>>0]|0){Ze(1017503,9,1,k[c>>2]|0);cd(k[c>>2]|0,k[a>>2]|0,f)}k[h>>2]=0;$c(k[a+12>>2]|0,f,c,h,j);if(i[g>>0]|0)ed(k[c>>2]|0,h);ad(h,d);r=j;return}function id(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;sd(d,(Ic(b)|0)&65535,a,a,100);k[c+12>>2]=26;return}function jd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0;p=r;r=r+16|0;o=p;d=pe(56472)|0;k[d+4>>2]=1e3;l=d+8|0;k[d+8040>>2]=0;k[d+8044>>2]=0;k[d+16048>>2]=0;k[d+16052>>2]=0;j[d+24056>>1]=0;k[d+24060>>2]=0;k[d+56064>>2]=0;k[d+56268>>2]=0;k[l>>2]=0;k[l+4>>2]=0;k[l+8>>2]=0;k[l+12>>2]=0;k[l+16>>2]=0;k[l+20>>2]=0;k[l+24>>2]=0;k[l+28>>2]=0;k[d>>2]=k[a+12>>2];e=b+12|0;k[e>>2]=26;k[b+136>>2]=0;f=d+28|0;k[f>>2]=1;g=k[a+4>>2]|0;if((g|0)>1){h=b+7|0;n=b+140|0;m=1;do{if(i[h>>0]|0){q=k[b>>2]|0;k[o>>2]=m;k[o+4>>2]=g;He(q,1017513,o)}q=m;m=lb(k[a>>2]|0,m,g,k[k[n>>2]>>2]|0,d)|0;s=k[n>>2]|0;mb(k[a>>2]|0,q,m,k[s+8>>2]|0,k[s+12>>2]|0,d);hd(a,q,b,c,1,d);k[l>>2]=0;k[l+4>>2]=0;k[l+8>>2]=0;k[l+12>>2]=0;k[l+16>>2]=0;k[f>>2]=m}while((m|0)<(g|0))}Xd(d);k[e>>2]=26;r=p;return}function kd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,l=0,m=0;d=pe(56472)|0;k[d+4>>2]=1e3;g=d+8|0;k[d+8040>>2]=0;k[d+8044>>2]=0;k[d+16048>>2]=0;k[d+16052>>2]=0;j[d+24056>>1]=0;k[d+24060>>2]=0;k[d+56064>>2]=0;k[d+56268>>2]=0;k[g>>2]=0;k[g+4>>2]=0;k[g+8>>2]=0;k[g+12>>2]=0;k[g+16>>2]=0;k[g+20>>2]=0;k[g+24>>2]=0;k[g+28>>2]=0;k[d>>2]=k[a+12>>2];k[b+12>>2]=26;k[b+136>>2]=0;e=d+28|0;k[e>>2]=1;f=k[a+4>>2]|0;if((f|0)>1){i=b+140|0;h=1;do{m=k[i>>2]|0;l=h;h=nb(k[a>>2]|0,h,f,k[m+16>>2]|0,k[m+20>>2]|0,d)|0;m=k[i>>2]|0;ob(k[a>>2]|0,l,h,k[m+24>>2]|0,k[m+28>>2]|0,d);hd(a,l,b,c,0,d);k[g>>2]=0;k[g+4>>2]=0;k[g+8>>2]=0;k[g+12>>2]=0;k[g+16>>2]=0;k[e>>2]=h}while((h|0)<(f|0))}Xd(d);return}function ld(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0;g=r;r=r+32|0;f=g+16|0;e=g;d=g+20|0;if(!(i[b+7>>0]|0))d=a+12|0;else{l=k[b>>2]|0;h=a+12|0;n=Dc(k[h>>2]|0)|0;j=a+4|0;m=k[j>>2]|0;k[e>>2]=n;k[e+4>>2]=m;He(l,1017545,e);ef(e,k[a>>2]|0,k[j>>2]|0);j=k[b>>2]|0;oc(d);k[f>>2]=(i[d>>0]&1)==0?d+1|0:k[d+8>>2]|0;He(j,1017576,f);ff(d);Ze(1017206,5,1,k[b>>2]|0);ff(e);d=h}k[b+12>>2]=26;k[b+136>>2]=0;n=Ec(k[d>>2]|0)|0;switch(((n|0)!=3&(i[b+4>>0]|0)!=0?2:n)|0){case 1:case 0:{id(k[a+4>>2]|0,k[a+12>>2]|0,b,c);break}case 3:{jd(a,b,c);break}case 2:{kd(a,b,c);break}default:{}}r=g;return}function md(a){a=a|0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=0;return}function nd(a){a=a|0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=0;return}function od(a){a=a|0;a=a+12|0;k[a>>2]=(k[a>>2]|0)+1;return}function pd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0;b=b&255;d=b>>>2;e=sf(1,0,d|0)|0;f=L;h=a;g=k[h>>2]|0;h=k[h+4>>2]|0;if((g&e|0)==0&(h&f|0)==0){d=a+16+(d<<3)|0;k[d>>2]=0;k[d+4>>2]=0;d=a;k[d>>2]=g|e;k[d+4>>2]=h|f}a=a+16+(b<<1)|0;j[a>>1]=(m[a>>1]|0)+c;return}function qd(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,n=0,o=0,p=0,q=0;q=r;r=r+16|0;p=q;k[b>>2]=-1;n=b+4|0;k[n>>2]=-1;o=b+8|0;k[o>>2]=-1;k[p>>2]=-1;k[p+4>>2]=-1;k[p+8>>2]=-1;d=a;c=k[d>>2]|0;d=k[d+4>>2]|0;if(!((c|0)==0&(d|0)==0)){i=a+16|0;j=p+8|0;l=p+4|0;g=0;while(1){if(!((c&1|0)==0&0==0)){h=0;do{e=h+g|0;f=m[i+(e<<1)>>1]|0;if((f|0)>(k[j>>2]|0)){a=k[l>>2]|0;if((f|0)>(a|0)){k[j>>2]=a;k[o>>2]=k[n>>2];a=k[p>>2]|0;if((f|0)>(a|0)){k[l>>2]=a;k[n>>2]=k[b>>2];a=0}else a=1}else a=2;k[p+(a<<2)>>2]=f;k[b+(a<<2)>>2]=e}h=h+1|0}while((h|0)!=4)}c=uf(c|0,d|0,1)|0;d=L;if((c|0)==0&(d|0)==0)break;else g=g+4|0}}r=q;return}function rd(a){a=a|0;var b=0;b=a+536|0;k[b>>2]=0;k[b+4>>2]=0;k[b+8>>2]=0;k[b+12>>2]=0;k[b+16>>2]=0;k[b+20>>2]=0;k[b+24>>2]=0;k[b+28>>2]=0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=0;k[a+16>>2]=0;k[a+20>>2]=0;a=a+568|0;b=a+48|0;do{k[a>>2]=-1;a=a+4|0}while((a|0)<(b|0));return}function sd(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,l=0,m=0;k[a>>2]=(k[a>>2]|0)+1;g=b&65535;l=g&15;m=j[a+568+(l<<1)>>1]|0;do if(m<<16>>16==b<<16>>16){b=a+616+(l<<2)|0;k[b>>2]=(k[b>>2]|0)+c;b=a+712+(l<<2)|0;k[b>>2]=(k[b>>2]|0)+d;d=ha(e,c)|0;a=a+808+(l<<2)|0;k[a>>2]=(k[a>>2]|0)+d}else{f=l^8;i=j[a+568+(f<<1)>>1]|0;if(i<<16>>16==b<<16>>16){b=a+616+(f<<2)|0;k[b>>2]=(k[b>>2]|0)+c;b=a+712+(f<<2)|0;k[b>>2]=(k[b>>2]|0)+d;d=ha(e,c)|0;a=a+808+(f<<2)|0;k[a>>2]=(k[a>>2]|0)+d;break}g=g&7|16;h=j[a+568+(g<<1)>>1]|0;if(h<<16>>16==b<<16>>16){b=a+616+(g<<2)|0;k[b>>2]=(k[b>>2]|0)+c;b=a+712+(g<<2)|0;k[b>>2]=(k[b>>2]|0)+d;d=ha(e,c)|0;a=a+808+(g<<2)|0;k[a>>2]=(k[a>>2]|0)+d;break}if(m<<16>>16!=-1){if(i<<16>>16!=-1)if(h<<16>>16==-1)f=g;else{f=(k[a+616+(f<<2)>>2]|0)<(k[a+616+(l<<2)>>2]|0)?f:l;f=(k[a+616+(g<<2)>>2]|0)<(k[a+616+(f<<2)>>2]|0)?g:f}}else f=l;j[a+568+(f<<1)>>1]=b;k[a+616+(f<<2)>>2]=c;k[a+712+(f<<2)>>2]=d;d=ha(e,c)|0;k[a+808+(f<<2)>>2]=d}while(0);return}function td(a,b){a=a|0;b=b|0;var c=0,d=0;a:do if(!(k[a+4>>2]|0)){d=b&65535;c=d&15;if((j[a+568+(c<<1)>>1]|0)!=b<<16>>16){c=c^8;if((j[a+568+(c<<1)>>1]|0)!=b<<16>>16){c=d&7|16;c=(j[a+568+(c<<1)>>1]|0)==b<<16>>16?c:-1}}}else{c=0;while(1){if((j[a+568+(c<<1)>>1]|0)==b<<16>>16)break a;c=c+1|0;if((c|0)>=24){c=-1;break}}}while(0);return c|0}function ud(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0,l=0;l=0;while(1){g=a+568+(l<<1)|0;if((j[g>>1]|0)==-1)k[a+616+(l<<2)>>2]=-1;b=l;l=l+1|0;if((l|0)>=24)continue;h=a+616+(b<<2)|0;i=a+712+(b<<2)|0;e=a+808+(b<<2)|0;f=l;do{b=a+568+(f<<1)|0;c=a+616+(f<<2)|0;if((j[b>>1]|0)==-1){k[c>>2]=-1;d=-1}else d=k[c>>2]|0;if((k[h>>2]|0)<(d|0)){d=j[g>>1]|0;j[g>>1]=j[b>>1]|0;j[b>>1]=d;d=k[h>>2]|0;k[h>>2]=k[c>>2];k[c>>2]=d;d=k[i>>2]|0;c=a+712+(f<<2)|0;k[i>>2]=k[c>>2];k[c>>2]=d;c=k[e>>2]|0;d=a+808+(f<<2)|0;k[e>>2]=k[d>>2];k[d>>2]=c}f=f+1|0}while((f|0)!=24);if((l|0)==3)break}k[a+4>>2]=1;return}function vd(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=r;r=r+32|0;e=f+8|0;d=f;Ze(1017581,14,1,941120);c=0;do{b=j[a+568+(c<<1)>>1]|0;if(b<<16>>16!=-1){i=Gc(b&65535)|0;h=k[a+616+(c<<2)>>2]|0;g=k[a+712+(c<<2)>>2]|0;b=k[a+808+(c<<2)>>2]|0;k[e>>2]=c;k[e+4>>2]=i;k[e+8>>2]=h;k[e+12>>2]=g;k[e+16>>2]=b;He(941120,1017620,e)}c=c+1|0}while((c|0)!=24);k[d>>2]=k[a>>2];He(941120,1017596,d);r=f;return}function wd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0;e=k[c>>2]|0;do if((e|0)>=1){f=k[b>>2]|0;g=(k[a+32>>2]|0)+(k[a>>2]|0)|0;d=k[a+16>>2]|0;h=i[f>>0]|0;a=h&255;if(h<<24>>24>-1){a=i[g+a>>0]|0;k[b>>2]=f+1;k[c>>2]=e+-1;break}if((e|0)>1&(a&224|0)==192){a=i[g+(l[g+a>>0]<<d)+(l[f+1>>0]|0)>>0]|0;k[b>>2]=f+2;k[c>>2]=e+-2;break}if((e|0)>2&(a&240|0)==224){a=g+(l[g+a>>0]<<d+4)|0;a=i[a+(i[a+(l[f+1>>0]|0)>>0]<<d)+(l[f+2>>0]|0)>>0]|0;k[b>>2]=f+3;k[c>>2]=e+-3;break}if((a&248|0)==240&(e|0)>3){a=g+(l[g+(l[g+a>>0]<<d)+(l[f+1>>0]|0)>>0]<<d+4)|0;a=i[a+(i[a+(l[f+2>>0]|0)>>0]<<d)+(l[f+3>>0]|0)>>0]|0;k[b>>2]=f+4;k[c>>2]=e+-4;break}else{k[b>>2]=f+1;k[c>>2]=e+-1;a=0;break}}else a=0;while(0);return a|0}function xd(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=k[b>>2]|0;do if((c|0)>=1){d=k[a>>2]|0;f=i[d>>0]|0;e=f&255;if(f<<24>>24>-1){f=j[942368+(e<<1)>>1]|0;k[a>>2]=d+1;k[b>>2]=c+-1;c=f&255;break}if((c|0)>1&(e&224|0)==192){f=j[942368+((m[942368+(e<<1)>>1]|0)<<6<<1)+((l[d+1>>0]|0)<<1)>>1]|0;k[a>>2]=d+2;k[b>>2]=c+-2;c=f&255;break}if((c|0)>2&(e&240|0)==224){f=j[942368+((m[942368+((m[942368+(e<<1)>>1]|0)<<6<<1)+((l[d+1>>0]|0)<<1)>>1]|0)<<6<<1)+((l[d+2>>0]|0)<<1)>>1]|0;k[a>>2]=d+3;k[b>>2]=c+-3;c=f&255;break}if((e&248|0)==240&(c|0)>3){f=j[942368+((m[942368+((m[942368+((m[942368+(e<<1)>>1]|0)<<6<<1)+((l[d+1>>0]|0)<<1)>>1]|0)<<6<<1)+((l[d+2>>0]|0)<<1)>>1]|0)<<6<<1)+((l[d+3>>0]|0)<<1)>>1]|0;k[a>>2]=d+4;k[b>>2]=c+-4;c=f&255;break}else{k[a>>2]=d+1;k[b>>2]=c+-1;c=0;break}}else c=0;while(0);return c|0}function yd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,m=0;h=a+b|0;j=h+-7|0;k[c>>2]=0;if(b|0){b=a;a:do{b:do if(b>>>0<j>>>0){g=b;while(1){d=k[g>>2]|0;b=g+4|0;e=k[b>>2]|0;f=g+8|0;if((d+-656877351|d+1145324612|e+-656877351|e+1145324612)&-2139062144|0){if((i[1008008+(l[g+1>>0]|0)>>0]|i[1008008+(d&255)>>0]|i[1008008+(l[g+2>>0]|0)>>0]|i[1008008+(l[g+3>>0]|0)>>0])<<24>>24){b=g;break b}if((i[1008008+(l[g+5>>0]|0)>>0]|i[1008008+(e&255)>>0]|i[1008008+(l[g+6>>0]|0)>>0]|i[1008008+(l[g+7>>0]|0)>>0])<<24>>24)break b}if(f>>>0<j>>>0)g=f;else{b=f;break}}}while(0);if(b>>>0<h>>>0)d=993864;else{d=993864;m=13;break}while(1){f=i[d+(l[b>>0]|0)>>0]|0;e=b+1|0;if((f&255)>239)break;b=993864+((f&255)<<6)|0;if(e>>>0<h>>>0){d=b;b=e}else{d=b;b=e;m=13;break a}}c:do if((d-993864|0)>>>0>=64)do{b=b+-1|0;if(b>>>0<=a>>>0)break c}while((i[b>>0]&-64)<<24>>24==-128);while(0)}while(f<<24>>24==-3);d:do if((m|0)==13)if((d-993864|0)>>>0>=64)do{b=b+-1|0;if(b>>>0<=a>>>0)break d}while((i[b>>0]&-64)<<24>>24==-128);while(0);k[c>>2]=b-a}return}function zd(a,b,c,d,e,f,g,h,j){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;H=(j|0)==0;I=(j|0)!=0;E=0;F=0;G=0;while(1){C=a;x=a+b|0;D=c;y=c+d|0;z=x;if((d|0)<(b|0))if(H){r=239;q=0;o=0;n=0}else{Vc(j,0);r=239;q=0;o=0;n=0}else{A=1009832;u=0;B=a;p=D;r=0;o=C;n=0;a:while(1){s=o;if(s>>>0<x>>>0){q=i[s>>0]|0;w=i[A+(q&255)>>0]|0;r=w&255;i[p>>0]=q;o=s+1|0;p=p+1|0;if((w&255)>239)w=q;else{w=B;A=1009832+(r<<6)|0;u=q;B=w;continue}}else w=u;if((r|0)<=239){J=43;break}b:do switch(r|0){case 247:{if(H)q=B;else{Vc(j,-2-B+o|0);Xc(j,2);q=o}i[p+-3>>0]=i[A+((w&255)+64)>>0]|0;A=1009832;u=0;B=q;p=p+-2|0;r=0;n=n+1|0;continue a}case 248:{if(H)q=B;else{Vc(j,o+~B|0);Xc(j,1);q=o}u=w&255;i[p+-3>>0]=i[A+(u+128)>>0]|0;i[p+-2>>0]=i[A+(u+64)>>0]|0;A=1009832;u=0;B=q;p=p+-1|0;r=0;n=n+1|0;continue a}case 246:{if(H)q=B;else{Vc(j,o+~B|0);Xc(j,1);q=o}i[p+-2>>0]=i[A+((w&255)+64)>>0]|0;A=1009832;u=0;B=q;p=p+-1|0;r=0;n=n+1|0;continue a}case 245:{q=w&255;r=p;i[r+-3>>0]=i[A+(q+192)>>0]|0;J=23;break}case 244:{q=w&255;r=p;J=23;break}case 243:{q=w&255;r=p;J=24;break}case 251:{i[p+-1>>0]=i[A+(w&255|256)>>0]|0;w=B;A=1009832;u=0;r=0;n=n+1|0;B=w;continue a}case 250:{q=A;r=w&255;if((q-1009832|0)>>>0<320){r=l[A+(r|512)>>0]<<8;break b}else{r=l[A+(r+128)>>0]<<8;J=29;break b}}case 249:case 252:{r=0;J=29;break}default:{J=10;break a}}while(0);if((J|0)==23){i[r+-2>>0]=i[A+(q+128)>>0]|0;J=24}else if((J|0)==29){J=0;q=A}if((J|0)==24){J=0;i[r+-1>>0]=i[A+(q+64)>>0]|0;w=B;A=1009832;u=0;r=0;n=n+1|0;B=w;continue}s=w&255;r=l[A+((q-1009832|0)>>>0<320?s|256:s+64|0)>>0]|r;s=974880+(r<<2)|0;v=l[s>>0]&127;q=l[974880+(r<<2)+1>>0]|0;if(!((q&128|0)==0|e)){s=r+1|0;q=l[974880+(s<<2)+1>>0]|0;s=974880+(s<<2)|0}u=q&127;r=m[s+2>>1]|0;q=p+(0-v)|0;t=q+u|0;if((y-t|0)<(z-o|0)){r=239;J=39;break}vf(q|0,1016936+r|0,u|0)|0;n=n+1|0;do if(!H){if(u>>>0>v>>>0){Vc(j,o-B|0);Wc(j,u-v|0);p=o;break}if(u>>>0<v>>>0){Vc(j,o-B-v+u|0);Xc(j,v-u|0);p=o}else p=B}else p=B;while(0);if((i[s>>0]|0)>=0){A=1009832;u=0;B=p;p=t;r=0;continue}r=l[1016936+(r+u)>>0]|0;A=1009832+(r<<6)|0;u=w;B=p;p=t}c:do if((J|0)==10)J=39;else if((J|0)==43){J=0;if((A-1009832|0)>>>0<320)r=241;else while(1){q=o+-1|0;o=q;p=p+-1|0;if(q>>>0<=a>>>0){r=240;break c}if((i[q>>0]&-64)<<24>>24!=-128){r=240;break}}}while(0);d:do if((J|0)==39){J=0;o=o+-1|0;p=p+-1|0;if((A-1009832|0)>>>0>=320)do{q=o+-1|0;o=q;p=p+-1|0;if(q>>>0<=a>>>0)break d}while((i[q>>0]&-64)<<24>>24==-128)}while(0);if(I&o>>>0>B>>>0)Vc(j,o-B|0);q=o-C|0;o=p-D|0}F=q+F|0;G=o+G|0;E=n+E|0;if((r|0)!=253)break;else{a=a+q|0;b=b-q|0;c=c+o|0;d=d-o|0}}k[f>>2]=F;k[g>>2]=G;k[h>>2]=E;return}function Ad(a){a=a|0;if(a|0)Xd(a);return}function Bd(a){a=a|0;return Gc(k[a>>2]|0)|0}function Cd(a){a=a|0;return i[a+4>>0]|0}function Dd(a){a=a|0;if(a|0){Ed(a);Xd(a)}return}function Ed(a){a=a|0;var b=0;b=k[a+4>>2]|0;if(b|0)Xd(b);b=k[a+8>>2]|0;if(b|0)Xd(b);b=k[a+12>>2]|0;if(b|0)Xd(b);return}function Fd(a,b,c){a=a|0;b=b|0;c=c|0;return Gd(b,c)|0}function Gd(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=r;r=r+32|0;e=c+16|0;d=c+4|0;f=c+28|0;k[e>>2]=0;k[e+4>>2]=0;k[e+8>>2]=0;k[d>>2]=0;k[d+4>>2]=0;k[d+8>>2]=0;i[f>>0]=0;a=yb(a,Ve(a)|0,b,e,d,c,f)|0;b=pe(20)|0;Hd(b,(i[f>>0]|0)!=0,a,e,d);r=c;return b|0}function Hd(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;k[a>>2]=c;i[a+16>>0]=b&1;b=pe(8)|0;c=k[e>>2]&255;k[b>>2]=k[d>>2];i[b+4>>0]=c;k[a+4>>2]=b;b=pe(8)|0;c=k[e+4>>2]&255;k[b>>2]=k[d+4>>2];i[b+4>>0]=c;k[a+8>>2]=b;b=pe(8)|0;e=k[e+8>>2]&255;k[b>>2]=k[d+8>>2];i[b+4>>0]=e;k[a+12>>2]=b;return}function Id(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Jd(b,c,d,e,f)|0}function Jd(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,l=0;f=r;r=r+80|0;l=f+56|0;h=f+40|0;g=f+28|0;j=f+72|0;k[l>>2]=e;k[l+4>>2]=c;k[l+8>>2]=d;k[l+12>>2]=26;k[h>>2]=0;k[h+4>>2]=0;k[h+8>>2]=0;k[g>>2]=0;k[g+4>>2]=0;k[g+8>>2]=0;i[j>>0]=0;e=zb(a,Ve(a)|0,b,l,h,g,f,f+24|0,j)|0;c=pe(20)|0;Hd(c,(i[j>>0]|0)!=0,e,h,g);r=f;return c|0}function Kd(a){a=a|0;return (i[a+16>>0]|0)!=0|0}function Ld(a){a=a|0;return Gc(k[a>>2]|0)|0}function Md(a,b){a=a|0;b=b|0;if(b>>>0>=3)Ma(0,b|0,3)|0;return k[a+4+(b<<2)>>2]|0}function Nd(a){a=a|0;if(a|0)Xd(a);return}function Od(a){a=a|0;return Gc(k[a>>2]|0)|0}function Pd(a){a=a|0;if(a|0)Xd(a);return}function Qd(){var a=0,b=0,c=0,d=0,e=0,f=0,g=0,h=0;e=r;r=r+48|0;g=e+32|0;c=e+24|0;h=e+16|0;f=e;e=e+36|0;a=Rd()|0;if(a|0?(d=k[a>>2]|0,d|0):0){a=d+48|0;b=k[a>>2]|0;a=k[a+4>>2]|0;if(!((b&-256|0)==1126902528&(a|0)==1129074247)){k[c>>2]=1094380;Ud(1094475,c)}if((b|0)==1126902529&(a|0)==1129074247)a=k[d+44>>2]|0;else a=d+80|0;k[e>>2]=a;d=k[d>>2]|0;a=k[d+4>>2]|0;if(_d(8,d,e)|0){h=k[e>>2]|0;h=Za[k[(k[h>>2]|0)+8>>2]&3](h)|0;k[f>>2]=1094380;k[f+4>>2]=a;k[f+8>>2]=h;Ud(1094389,f)}else{k[h>>2]=1094380;k[h+4>>2]=a;Ud(1094434,h)}}Ud(1094513,g)}function Rd(){var a=0,b=0;a=r;r=r+16|0;if(!(Ja(1097276,2)|0)){b=Ha(k[274320]|0)|0;r=a;return b|0}else Ud(1094201,a);return 0}function Sd(){var a=0;a=r;r=r+16|0;if(!(Ka(1097280,8)|0)){r=a;return}else Ud(1094151,a)}function Td(a){a=a|0;var b=0;b=r;r=r+16|0;df(a);if(!(Na(k[274320]|0,0)|0)){r=b;return}else Ud(1094098,b)}function Ud(a,b){a=a|0;b=b|0;var c=0;c=r;r=r+16|0;k[c>>2]=b;Ie(941120,a,c)|0;Ye();ua()}function Vd(a){a=a|0;return}function Wd(a){a=a|0;Xd(a);return}function Xd(a){a=a|0;df(a);return}function Yd(a){a=a|0;return}function Zd(a){a=a|0;return}function _d(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;g=r;r=r+64|0;f=g;if((a|0)!=(b|0))if((b|0)!=0?(e=$d(b,16)|0,(e|0)!=0):0){b=f;d=b+56|0;do{k[b>>2]=0;b=b+4|0}while((b|0)<(d|0));k[f>>2]=e;k[f+8>>2]=a;k[f+12>>2]=-1;k[f+48>>2]=1;ab[k[(k[e>>2]|0)+28>>2]&3](e,f,k[c>>2]|0,1);if((k[f+24>>2]|0)==1){k[c>>2]=k[f+16>>2];b=1}else b=0}else b=0;else b=1;r=g;return b|0}function $d(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0;s=r;r=r+64|0;q=s;p=k[a>>2]|0;o=a+(k[p+-8>>2]|0)|0;p=k[p+-4>>2]|0;k[q>>2]=b;k[q+4>>2]=a;k[q+8>>2]=48;h=q+12|0;l=q+16|0;a=q+20|0;c=q+24|0;d=q+28|0;e=q+32|0;f=q+40|0;g=(p|0)==(b|0);m=h;n=m+40|0;do{k[m>>2]=0;m=m+4|0}while((m|0)<(n|0));j[h+40>>1]=0;i[h+42>>0]=0;a:do if(g){k[q+48>>2]=1;$a[k[(k[b>>2]|0)+20>>2]&3](b,q,o,o,1,0);a=(k[c>>2]|0)==1?o:0}else{Xa[k[(k[p>>2]|0)+24>>2]&3](p,q,o,1,0);switch(k[q+36>>2]|0){case 0:{a=(k[f>>2]|0)==1&(k[d>>2]|0)==1&(k[e>>2]|0)==1?k[a>>2]|0:0;break a}case 1:break;default:{a=0;break a}}if((k[c>>2]|0)!=1?!((k[f>>2]|0)==0&(k[d>>2]|0)==1&(k[e>>2]|0)==1):0){a=0;break}a=k[l>>2]|0}while(0);r=s;return a|0}function ae(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;if((a|0)==(k[b+8>>2]|0))be(b,c,d,e);else{a=k[a+8>>2]|0;$a[k[(k[a>>2]|0)+20>>2]&3](a,b,c,d,e,f)}return}function be(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;i[a+53>>0]=1;do if((k[a+4>>2]|0)==(c|0)){i[a+52>>0]=1;c=a+16|0;e=k[c>>2]|0;if(!e){k[c>>2]=b;k[a+24>>2]=d;k[a+36>>2]=1;if(!((d|0)==1?(k[a+48>>2]|0)==1:0))break;i[a+54>>0]=1;break}if((e|0)!=(b|0)){d=a+36|0;k[d>>2]=(k[d>>2]|0)+1;i[a+54>>0]=1;break}e=a+24|0;c=k[e>>2]|0;if((c|0)==2){k[e>>2]=d;c=d}if((c|0)==1?(k[a+48>>2]|0)==1:0)i[a+54>>0]=1}while(0);return}function ce(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;do if((a|0)==(k[b+8>>2]|0)){if((k[b+4>>2]|0)==(c|0)?(f=b+28|0,(k[f>>2]|0)!=1):0)k[f>>2]=d}else{if((a|0)!=(k[b>>2]|0)){h=k[a+8>>2]|0;Xa[k[(k[h>>2]|0)+24>>2]&3](h,b,c,d,e);break}if((k[b+16>>2]|0)!=(c|0)?(h=b+20|0,(k[h>>2]|0)!=(c|0)):0){k[b+32>>2]=d;g=b+44|0;if((k[g>>2]|0)==4)break;f=b+52|0;i[f>>0]=0;d=b+53|0;i[d>>0]=0;a=k[a+8>>2]|0;$a[k[(k[a>>2]|0)+20>>2]&3](a,b,c,c,1,e);if(i[d>>0]|0)if(!(i[f>>0]|0)){f=1;d=13}else d=17;else{f=0;d=13}do if((d|0)==13){k[h>>2]=c;c=b+40|0;k[c>>2]=(k[c>>2]|0)+1;if((k[b+36>>2]|0)==1?(k[b+24>>2]|0)==2:0){i[b+54>>0]=1;if(f){d=17;break}else{f=4;break}}if(f)d=17;else f=4}while(0);if((d|0)==17)f=3;k[g>>2]=f;break}if((d|0)==1)k[b+32>>2]=1}while(0);return}function de(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;if((a|0)==(k[b+8>>2]|0))ee(b,c,d);else{a=k[a+8>>2]|0;ab[k[(k[a>>2]|0)+28>>2]&3](a,b,c,d)}return}function ee(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=a+16|0;e=k[d>>2]|0;do if(e){if((e|0)!=(b|0)){c=a+36|0;k[c>>2]=(k[c>>2]|0)+1;k[a+24>>2]=2;i[a+54>>0]=1;break}d=a+24|0;if((k[d>>2]|0)==2)k[d>>2]=c}else{k[d>>2]=b;k[a+24>>2]=c;k[a+36>>2]=1}while(0);return}function fe(a){a=a|0;Xd(a);return}function ge(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;if((a|0)==(k[b+8>>2]|0))be(b,c,d,e);return}function he(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;do if((a|0)==(k[b+8>>2]|0)){if((k[b+4>>2]|0)==(c|0)?(g=b+28|0,(k[g>>2]|0)!=1):0)k[g>>2]=d}else if((a|0)==(k[b>>2]|0)){if((k[b+16>>2]|0)!=(c|0)?(f=b+20|0,(k[f>>2]|0)!=(c|0)):0){k[b+32>>2]=d;k[f>>2]=c;e=b+40|0;k[e>>2]=(k[e>>2]|0)+1;if((k[b+36>>2]|0)==1?(k[b+24>>2]|0)==2:0)i[b+54>>0]=1;k[b+44>>2]=4;break}if((d|0)==1)k[b+32>>2]=1}while(0);return}function ie(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;if((a|0)==(k[b+8>>2]|0))ee(b,c,d);return}function je(){var a=0,b=0,c=0,d=0;c=r;r=r+16|0;d=c+8|0;a=Rd()|0;if((a|0?(b=k[a>>2]|0,b|0):0)?(a=b+48|0,(k[a>>2]&-256|0)==1126902528?(k[a+4>>2]|0)==1129074247:0):0){_a[k[b+12>>2]&3]();Ud(1094525,c)}c=k[235254]|0;k[235254]=c+0;_a[c&3]();Ud(1094525,d)}function ke(a){a=a|0;return}function le(a){a=a|0;Xd(a);return}function me(a){a=a|0;return 1094578}function ne(){xa(1094684,1094713,1175,1094762)}function oe(){xa(1094783,1094713,1164,1094663)}function pe(a){a=a|0;var b=0,c=0;b=(a|0)==0?1:a;while(1){c=cf(b)|0;if(c|0){a=6;break}a=qe()|0;if(!a){a=5;break}_a[a&3]()}if((a|0)==5){c=ya(4)|0;k[c>>2]=941108;Oa(c|0,72,6)}else if((a|0)==6)return c|0;return 0}function qe(){var a=0;a=k[274321]|0;k[274321]=a+0;return a|0}function re(a){a=a|0;return pe(a)|0}function se(a){a=a|0;Xd(a);return}function te(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;e=r;r=r+16|0;d=e;k[d>>2]=k[c>>2];a=Wa[k[(k[a>>2]|0)+16>>2]&7](a,b,d)|0;if(a)k[c>>2]=k[d>>2];r=e;return a&1|0}function ue(a){a=a|0;if(!a)a=0;else a=($d(a,104)|0)!=0;return a&1|0}function ve(a){a=a|0;var b=0,c=0;b=r;r=r+16|0;c=b;k[c>>2]=k[a+60>>2];a=we(Pa(6,c|0)|0)|0;r=b;return a|0}function we(a){a=a|0;var b=0;if(a>>>0>4294963200){b=xe()|0;k[b>>2]=0-a;a=-1}return a|0}function xe(){var a=0;if(!0)a=1097288;else{a=(Ia()|0)+64|0;a=k[a>>2]|0}return a|0}function ye(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;e=r;r=r+32|0;f=e;d=e+20|0;k[f>>2]=k[a+60>>2];k[f+4>>2]=0;k[f+8>>2]=b;k[f+12>>2]=d;k[f+16>>2]=c;if((we(Sa(140,f|0)|0)|0)<0){k[d>>2]=-1;a=-1}else a=k[d>>2]|0;r=e;return a|0}function ze(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,m=0,n=0,o=0,p=0;p=r;r=r+48|0;m=p+16|0;l=p;i=p+32|0;n=a+28|0;g=k[n>>2]|0;k[i>>2]=g;o=a+20|0;g=(k[o>>2]|0)-g|0;k[i+4>>2]=g;k[i+8>>2]=b;k[i+12>>2]=c;h=a+60|0;j=a+44|0;e=2;b=g+c|0;while(1){if(!0){k[m>>2]=k[h>>2];k[m+4>>2]=i;k[m+8>>2]=e;f=we(Ta(146,m|0)|0)|0}else{Qa(9,a|0);k[l>>2]=k[h>>2];k[l+4>>2]=i;k[l+8>>2]=e;f=we(Ta(146,l|0)|0)|0;ta(0)}if((b|0)==(f|0)){b=6;break}if((f|0)<0){b=8;break}b=b-f|0;d=k[i+4>>2]|0;if(f>>>0<=d>>>0)if((e|0)==2){k[n>>2]=(k[n>>2]|0)+f;g=d;d=i;e=2}else{g=d;d=i}else{g=k[j>>2]|0;k[n>>2]=g;k[o>>2]=g;g=k[i+12>>2]|0;f=f-d|0;d=i+8|0;e=e+-1|0}k[d>>2]=(k[d>>2]|0)+f;k[d+4>>2]=g-f;i=d}if((b|0)==6){m=k[j>>2]|0;k[a+16>>2]=m+(k[a+48>>2]|0);a=m;k[n>>2]=a;k[o>>2]=a}else if((b|0)==8){k[a+16>>2]=0;k[n>>2]=0;k[o>>2]=0;k[a>>2]=k[a>>2]|32;if((e|0)==2)c=0;else c=c-(k[i+4>>2]|0)|0}r=p;return c|0}function Ae(a){a=a|0;return}function Be(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0;j=r;r=r+16|0;h=j;g=b&255;i[h>>0]=g;d=a+16|0;e=k[d>>2]|0;if(!e)if(!(Ce(a)|0)){e=k[d>>2]|0;f=4}else c=-1;else f=4;do if((f|0)==4){d=a+20|0;f=k[d>>2]|0;if(f>>>0<e>>>0?(c=b&255,(c|0)!=(i[a+75>>0]|0)):0){k[d>>2]=f+1;i[f>>0]=g;break}if((Wa[k[a+36>>2]&7](a,h,1)|0)==1)c=l[h>>0]|0;else c=-1}while(0);r=j;return c|0}function Ce(a){a=a|0;var b=0,c=0;b=a+74|0;c=i[b>>0]|0;i[b>>0]=c+255|c;b=k[a>>2]|0;if(!(b&8)){k[a+8>>2]=0;k[a+4>>2]=0;b=k[a+44>>2]|0;k[a+28>>2]=b;k[a+20>>2]=b;k[a+16>>2]=b+(k[a+48>>2]|0);b=0}else{k[a>>2]=b|32;b=-1}return b|0}function De(a,b){a=a|0;b=b|0;if(!a)a=0;else a=Ee(a,b)|0;return a|0}function Ee(a,b){a=a|0;b=b|0;do if(a){if(b>>>0<128){i[a>>0]=b;a=1;break}if(b>>>0<2048){i[a>>0]=b>>>6|192;i[a+1>>0]=b&63|128;a=2;break}if(b>>>0<55296|(b&-8192|0)==57344){i[a>>0]=b>>>12|224;i[a+1>>0]=b>>>6&63|128;i[a+2>>0]=b&63|128;a=3;break}if((b+-65536|0)>>>0<1048576){i[a>>0]=b>>>18|240;i[a+1>>0]=b>>>12&63|128;i[a+2>>0]=b>>>6&63|128;i[a+3>>0]=b&63|128;a=4;break}else{a=xe()|0;k[a>>2]=84;a=-1;break}}else a=1;while(0);return a|0}function Fe(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=c+16|0;e=k[d>>2]|0;if(!e)if(!(Ce(c)|0)){e=k[d>>2]|0;f=5}else d=0;else f=5;a:do if((f|0)==5){g=c+20|0;d=k[g>>2]|0;f=d;if((e-d|0)>>>0<b>>>0){d=Wa[k[c+36>>2]&7](c,a,b)|0;break}b:do if((i[c+75>>0]|0)>-1){d=b;while(1){if(!d){e=f;d=0;break b}e=d+-1|0;if((i[a+e>>0]|0)==10)break;else d=e}if((Wa[k[c+36>>2]&7](c,a,d)|0)>>>0<d>>>0)break a;b=b-d|0;a=a+d|0;e=k[g>>2]|0}else{e=f;d=0}while(0);vf(e|0,a|0,b|0)|0;k[g>>2]=(k[g>>2]|0)+b;d=d+b|0}while(0);return d|0}function Ge(){return 0}function He(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=r;r=r+16|0;e=d;k[e>>2]=c;Ie(a,b,e)|0;r=d;return}function Ie(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0;q=r;r=r+224|0;m=q+120|0;p=q+80|0;o=q;n=q+136|0;d=p;e=d+40|0;do{k[d>>2]=0;d=d+4|0}while((d|0)<(e|0));k[m>>2]=k[c>>2];if((Je(0,b,m,o,p)|0)<0)c=-1;else{c=k[a>>2]|0;l=c&32;if((i[a+74>>0]|0)<1)k[a>>2]=c&-33;j=a+48|0;if(!(k[j>>2]|0)){d=a+44|0;e=k[d>>2]|0;k[d>>2]=n;f=a+28|0;k[f>>2]=n;g=a+20|0;k[g>>2]=n;k[j>>2]=80;h=a+16|0;k[h>>2]=n+80;c=Je(a,b,m,o,p)|0;if(e){Wa[k[a+36>>2]&7](a,0,0)|0;c=(k[g>>2]|0)==0?-1:c;k[d>>2]=e;k[j>>2]=0;k[h>>2]=0;k[f>>2]=0;k[g>>2]=0}}else c=Je(a,b,m,o,p)|0;p=k[a>>2]|0;k[a>>2]=p|l;c=(p&32|0)==0?c:-1}r=q;return c|0}function Je(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,m=0.0,n=0,o=0,q=0,s=0,u=0,v=0,w=0.0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ia=0;ia=r;r=r+624|0;ca=ia+24|0;ea=ia+16|0;da=ia+588|0;$=ia+576|0;ba=ia;W=ia+536|0;ga=ia+8|0;fa=ia+528|0;M=(a|0)!=0;N=W+40|0;V=N;W=W+39|0;X=ga+4|0;Y=da;Z=0-Y|0;_=$+12|0;$=$+11|0;aa=_;O=aa-Y|0;P=-2-Y|0;Q=aa+2|0;R=ca+288|0;S=da+9|0;T=S;U=da+8|0;f=0;g=0;o=0;x=b;a:while(1){do if((f|0)>-1)if((g|0)>(2147483647-f|0)){f=xe()|0;k[f>>2]=75;f=-1;break}else{f=g+f|0;break}while(0);b=i[x>>0]|0;if(!(b<<24>>24)){K=244;break}else g=x;b:while(1){switch(b<<24>>24){case 37:{b=g;K=9;break b}case 0:{b=g;break b}default:{}}J=g+1|0;b=i[J>>0]|0;g=J}c:do if((K|0)==9)while(1){K=0;if((i[b+1>>0]|0)!=37)break c;g=g+1|0;b=b+2|0;if((i[b>>0]|0)==37)K=9;else break}while(0);v=g-x|0;if(M?(k[a>>2]&32|0)==0:0)Fe(x,v,a)|0;if((g|0)!=(x|0)){g=v;x=b;continue}n=b+1|0;g=i[n>>0]|0;h=(g<<24>>24)+-48|0;if(h>>>0<10){J=(i[b+2>>0]|0)==36;n=J?b+3|0:n;g=i[n>>0]|0;s=J?h:-1;o=J?1:o}else s=-1;b=g<<24>>24;d:do if((b&-32|0)==32){h=0;do{if(!(1<<b+-32&75913))break d;h=1<<(g<<24>>24)+-32|h;n=n+1|0;g=i[n>>0]|0;b=g<<24>>24}while((b&-32|0)==32)}else h=0;while(0);do if(g<<24>>24==42){g=n+1|0;b=(i[g>>0]|0)+-48|0;if(b>>>0<10?(i[n+2>>0]|0)==36:0){k[e+(b<<2)>>2]=10;b=1;n=n+3|0;g=k[d+((i[g>>0]|0)+-48<<3)>>2]|0}else{if(o|0){f=-1;break a}if(!M){u=h;J=0;n=g;I=0;break}b=(k[c>>2]|0)+(4-1)&~(4-1);J=k[b>>2]|0;k[c>>2]=b+4;b=0;n=g;g=J}if((g|0)<0){u=h|8192;J=b;I=0-g|0}else{u=h;J=b;I=g}}else{b=(g<<24>>24)+-48|0;if(b>>>0<10){g=0;do{g=(g*10|0)+b|0;n=n+1|0;b=(i[n>>0]|0)+-48|0}while(b>>>0<10);if((g|0)<0){f=-1;break a}else{u=h;J=o;I=g}}else{u=h;J=o;I=0}}while(0);e:do if((i[n>>0]|0)==46){b=n+1|0;g=i[b>>0]|0;if(g<<24>>24!=42){h=(g<<24>>24)+-48|0;if(h>>>0<10)g=0;else{o=0;break}while(1){g=(g*10|0)+h|0;b=b+1|0;h=(i[b>>0]|0)+-48|0;if(h>>>0>=10){o=g;break e}}}b=n+2|0;g=(i[b>>0]|0)+-48|0;if(g>>>0<10?(i[n+3>>0]|0)==36:0){k[e+(g<<2)>>2]=10;o=k[d+((i[b>>0]|0)+-48<<3)>>2]|0;b=n+4|0;break}if(J|0){f=-1;break a}if(M){H=(k[c>>2]|0)+(4-1)&~(4-1);o=k[H>>2]|0;k[c>>2]=H+4}else o=0}else{o=-1;b=n}while(0);q=0;while(1){g=(i[b>>0]|0)+-65|0;if(g>>>0>57){f=-1;break a}H=b+1|0;g=i[1094812+(q*58|0)+g>>0]|0;h=g&255;if((h+-1|0)>>>0<8){b=H;q=h}else break}if(!(g<<24>>24)){f=-1;break}n=(s|0)>-1;do if(g<<24>>24==19)if(n){f=-1;break a}else K=52;else{if(n){k[e+(s<<2)>>2]=h;F=d+(s<<3)|0;G=k[F+4>>2]|0;K=ba;k[K>>2]=k[F>>2];k[K+4>>2]=G;K=52;break}if(!M){f=0;break a}Ke(ba,h,c)}while(0);if((K|0)==52?(K=0,!M):0){g=v;o=J;x=H;continue}s=i[b>>0]|0;s=(q|0)!=0&(s&15|0)==3?s&-33:s;h=u&-65537;G=(u&8192|0)==0?u:h;f:do switch(s|0){case 110:switch(q|0){case 0:{k[k[ba>>2]>>2]=f;g=v;o=J;x=H;continue a}case 1:{k[k[ba>>2]>>2]=f;g=v;o=J;x=H;continue a}case 2:{g=k[ba>>2]|0;k[g>>2]=f;k[g+4>>2]=((f|0)<0)<<31>>31;g=v;o=J;x=H;continue a}case 3:{j[k[ba>>2]>>1]=f;g=v;o=J;x=H;continue a}case 4:{i[k[ba>>2]>>0]=f;g=v;o=J;x=H;continue a}case 6:{k[k[ba>>2]>>2]=f;g=v;o=J;x=H;continue a}case 7:{g=k[ba>>2]|0;k[g>>2]=f;k[g+4>>2]=((f|0)<0)<<31>>31;g=v;o=J;x=H;continue a}default:{g=v;o=J;x=H;continue a}}case 112:{q=G|8;o=o>>>0>8?o:8;s=120;K=64;break}case 88:case 120:{q=G;K=64;break}case 111:{h=ba;g=k[h>>2]|0;h=k[h+4>>2]|0;if((g|0)==0&(h|0)==0)b=N;else{b=N;do{b=b+-1|0;i[b>>0]=g&7|48;g=uf(g|0,h|0,3)|0;h=L}while(!((g|0)==0&(h|0)==0))}if(!(G&8)){g=G;q=0;n=1095292;K=77}else{q=V-b|0;g=G;o=(o|0)>(q|0)?o:q+1|0;q=0;n=1095292;K=77}break}case 105:case 100:{g=ba;b=k[g>>2]|0;g=k[g+4>>2]|0;if((g|0)<0){b=qf(0,0,b|0,g|0)|0;g=L;h=ba;k[h>>2]=b;k[h+4>>2]=g;h=1;n=1095292;K=76;break f}if(!(G&2048)){n=G&1;h=n;n=(n|0)==0?1095292:1095294;K=76}else{h=1;n=1095293;K=76}break}case 117:{g=ba;b=k[g>>2]|0;g=k[g+4>>2]|0;h=0;n=1095292;K=76;break}case 99:{i[W>>0]=k[ba>>2];b=W;s=1;v=0;u=1095292;g=N;break}case 109:{g=xe()|0;g=Me(k[g>>2]|0)|0;K=82;break}case 115:{g=k[ba>>2]|0;g=g|0?g:1097194;K=82;break}case 67:{k[ga>>2]=k[ba>>2];k[X>>2]=0;k[ba>>2]=ga;b=ga;o=-1;K=86;break}case 83:{b=k[ba>>2]|0;if(!o){Oe(a,32,I,0,G);b=0;K=97}else K=86;break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{m=+p[ba>>3];k[ea>>2]=0;p[t>>3]=m;if((k[t+4>>2]|0)>=0)if(!(G&2048)){F=G&1;E=F;F=(F|0)==0?1097202:1097207}else{E=1;F=1097204}else{m=-m;E=1;F=1097201}p[t>>3]=m;D=k[t+4>>2]&2146435072;do if(D>>>0<2146435072|(D|0)==2146435072&0<0){w=+Pe(m,ea)*2.0;g=w!=0.0;if(g)k[ea>>2]=(k[ea>>2]|0)+-1;B=s|32;if((B|0)==97){u=s&32;x=(u|0)==0?F:F+9|0;v=E|2;b=12-o|0;do if(!(o>>>0>11|(b|0)==0)){m=8.0;do{b=b+-1|0;m=m*16.0}while((b|0)!=0);if((i[x>>0]|0)==45){m=-(m+(-w-m));break}else{m=w+m-m;break}}else m=w;while(0);g=k[ea>>2]|0;b=(g|0)<0?0-g|0:g;b=Le(b,((b|0)<0)<<31>>31,_)|0;if((b|0)==(_|0)){i[$>>0]=48;b=$}i[b+-1>>0]=(g>>31&2)+43;q=b+-2|0;i[q>>0]=s+15;n=(o|0)<1;h=(G&8|0)==0;g=da;while(1){F=~~m;b=g+1|0;i[g>>0]=l[1095276+F>>0]|u;m=(m-+(F|0))*16.0;do if((b-Y|0)==1){if(h&(n&m==0.0))break;i[b>>0]=46;b=g+2|0}while(0);if(!(m!=0.0))break;else g=b}h=q;o=(o|0)!=0&(P+b|0)<(o|0)?Q+o-h|0:O-h+b|0;n=o+v|0;Oe(a,32,I,n,G);if(!(k[a>>2]&32))Fe(x,v,a)|0;Oe(a,48,I,n,G^65536);g=b-Y|0;if(!(k[a>>2]&32))Fe(da,g,a)|0;b=aa-h|0;Oe(a,48,o-(g+b)|0,0,0);if(!(k[a>>2]&32))Fe(q,b,a)|0;Oe(a,32,I,n,G^8192);b=(n|0)<(I|0)?I:n;break}b=(o|0)<0?6:o;if(g){g=(k[ea>>2]|0)+-28|0;k[ea>>2]=g;m=w*268435456.0}else{m=w;g=k[ea>>2]|0}D=(g|0)<0?ca:R;C=D;h=D;do{A=~~m>>>0;k[h>>2]=A;h=h+4|0;m=(m-+(A>>>0))*1.0e9}while(m!=0.0);g=k[ea>>2]|0;if((g|0)>0){n=D;o=h;while(1){q=(g|0)>29?29:g;g=o+-4|0;do if(g>>>0>=n>>>0){h=0;do{z=sf(k[g>>2]|0,0,q|0)|0;z=tf(z|0,L|0,h|0,0)|0;A=L;y=Ef(z|0,A|0,1e9,0)|0;k[g>>2]=y;h=Df(z|0,A|0,1e9,0)|0;g=g+-4|0}while(g>>>0>=n>>>0);if(!h)break;n=n+-4|0;k[n>>2]=h}while(0);h=o;while(1){if(h>>>0<=n>>>0)break;g=h+-4|0;if(!(k[g>>2]|0))h=g;else break}g=(k[ea>>2]|0)-q|0;k[ea>>2]=g;if((g|0)>0)o=h;else break}}else n=D;if((g|0)<0){x=((b+25|0)/9|0)+1|0;y=(B|0)==102;do{v=0-g|0;v=(v|0)>9?9:v;do if(n>>>0<h>>>0){g=(1<<v)+-1|0;o=1e9>>>v;u=0;q=n;do{A=k[q>>2]|0;k[q>>2]=(A>>>v)+u;u=ha(A&g,o)|0;q=q+4|0}while(q>>>0<h>>>0);g=(k[n>>2]|0)==0?n+4|0:n;if(!u){n=g;g=h;break}k[h>>2]=u;n=g;g=h+4|0}else{n=(k[n>>2]|0)==0?n+4|0:n;g=h}while(0);h=y?D:n;h=(g-h>>2|0)>(x|0)?h+(x<<2)|0:g;g=(k[ea>>2]|0)+v|0;k[ea>>2]=g}while((g|0)<0);x=n;y=h}else{x=n;y=h}do if(x>>>0<y>>>0){g=(C-x>>2)*9|0;n=k[x>>2]|0;if(n>>>0<10)break;else h=10;do{h=h*10|0;g=g+1|0}while(n>>>0>=h>>>0)}else g=0;while(0);z=(B|0)==103;A=(b|0)!=0;h=b-((B|0)!=102?g:0)+((A&z)<<31>>31)|0;if((h|0)<(((y-C>>2)*9|0)+-9|0)){o=h+9216|0;h=D+4+(((o|0)/9|0)+-1024<<2)|0;o=((o|0)%9|0)+1|0;if((o|0)<9){n=10;do{n=n*10|0;o=o+1|0}while((o|0)!=9)}else n=10;u=k[h>>2]|0;v=(u>>>0)%(n>>>0)|0;o=(h+4|0)==(y|0);do if(o&(v|0)==0)n=x;else{w=(((u>>>0)/(n>>>0)|0)&1|0)==0?9007199254740992.0:9007199254740994.0;q=(n|0)/2|0;if(v>>>0<q>>>0)m=.5;else m=o&(v|0)==(q|0)?1.0:1.5;do if(E){if((i[F>>0]|0)!=45)break;w=-w;m=-m}while(0);o=u-v|0;k[h>>2]=o;if(!(w+m!=w)){n=x;break}B=o+n|0;k[h>>2]=B;if(B>>>0>999999999){g=x;while(1){n=h+-4|0;k[h>>2]=0;if(n>>>0<g>>>0){g=g+-4|0;k[g>>2]=0}B=(k[n>>2]|0)+1|0;k[n>>2]=B;if(B>>>0>999999999)h=n;else{q=g;h=n;break}}}else q=x;g=(C-q>>2)*9|0;o=k[q>>2]|0;if(o>>>0<10){n=q;break}else n=10;do{n=n*10|0;g=g+1|0}while(o>>>0>=n>>>0);n=q}while(0);h=h+4|0;x=n;h=y>>>0>h>>>0?h:y}else h=y;v=0-g|0;B=h;while(1){if(B>>>0<=x>>>0){y=0;break}h=B+-4|0;if(!(k[h>>2]|0))B=h;else{y=1;break}}do if(z){b=(A&1^1)+b|0;if((b|0)>(g|0)&(g|0)>-5){s=s+-1|0;b=b+-1-g|0}else{s=s+-2|0;b=b+-1|0}h=G&8;if(h|0)break;do if(y){h=k[B+-4>>2]|0;if(!h){n=9;break}if(!((h>>>0)%10|0)){o=10;n=0}else{n=0;break}do{o=o*10|0;n=n+1|0}while(!((h>>>0)%(o>>>0)|0|0))}else n=9;while(0);h=((B-C>>2)*9|0)+-9|0;if((s|32|0)==102){h=h-n|0;h=(h|0)<0?0:h;b=(b|0)<(h|0)?b:h;h=0;break}else{h=h+g-n|0;h=(h|0)<0?0:h;b=(b|0)<(h|0)?b:h;h=0;break}}else h=G&8;while(0);u=b|h;o=(u|0)!=0&1;q=(s|32|0)==102;if(q){g=(g|0)>0?g:0;s=0}else{n=(g|0)<0?v:g;n=Le(n,((n|0)<0)<<31>>31,_)|0;if((aa-n|0)<2)do{n=n+-1|0;i[n>>0]=48}while((aa-n|0)<2);i[n+-1>>0]=(g>>31&2)+43;C=n+-2|0;i[C>>0]=s;g=aa-C|0;s=C}v=E+1+b+o+g|0;Oe(a,32,I,v,G);if(!(k[a>>2]&32))Fe(F,E,a)|0;Oe(a,48,I,v,G^65536);do if(q){n=x>>>0>D>>>0?D:x;h=n;do{g=Le(k[h>>2]|0,0,S)|0;do if((h|0)==(n|0)){if((g|0)!=(S|0))break;i[U>>0]=48;g=U}else{if(g>>>0<=da>>>0)break;rf(da|0,48,g-Y|0)|0;do g=g+-1|0;while(g>>>0>da>>>0)}while(0);if(!(k[a>>2]&32))Fe(g,T-g|0,a)|0;h=h+4|0}while(h>>>0<=D>>>0);do if(u|0){if(k[a>>2]&32|0)break;Fe(1097236,1,a)|0}while(0);if((b|0)>0&h>>>0<B>>>0)while(1){g=Le(k[h>>2]|0,0,S)|0;if(g>>>0>da>>>0){rf(da|0,48,g-Y|0)|0;do g=g+-1|0;while(g>>>0>da>>>0)}if(!(k[a>>2]&32))Fe(g,(b|0)>9?9:b,a)|0;h=h+4|0;g=b+-9|0;if(!((b|0)>9&h>>>0<B>>>0)){b=g;break}else b=g}Oe(a,48,b+9|0,9,0)}else{q=y?B:x+4|0;if((b|0)>-1){o=(h|0)==0;n=x;do{g=Le(k[n>>2]|0,0,S)|0;if((g|0)==(S|0)){i[U>>0]=48;g=U}do if((n|0)==(x|0)){h=g+1|0;if(!(k[a>>2]&32))Fe(g,1,a)|0;if(o&(b|0)<1){g=h;break}if(k[a>>2]&32|0){g=h;break}Fe(1097236,1,a)|0;g=h}else{if(g>>>0<=da>>>0)break;rf(da|0,48,g+Z|0)|0;do g=g+-1|0;while(g>>>0>da>>>0)}while(0);h=T-g|0;if(!(k[a>>2]&32))Fe(g,(b|0)>(h|0)?h:b,a)|0;b=b-h|0;n=n+4|0}while(n>>>0<q>>>0&(b|0)>-1)}Oe(a,48,b+18|0,18,0);if(k[a>>2]&32|0)break;Fe(s,aa-s|0,a)|0}while(0);Oe(a,32,I,v,G^8192);b=(v|0)<(I|0)?I:v}else{q=(s&32|0)!=0;o=m!=m|0.0!=0.0;g=o?0:E;n=g+3|0;Oe(a,32,I,n,h);b=k[a>>2]|0;if(!(b&32)){Fe(F,g,a)|0;b=k[a>>2]|0}if(!(b&32))Fe(o?(q?1097228:1097232):q?1097220:1097224,3,a)|0;Oe(a,32,I,n,G^8192);b=(n|0)<(I|0)?I:n}while(0);g=b;o=J;x=H;continue a}default:{b=x;h=G;s=o;v=0;u=1095292;g=N}}while(0);g:do if((K|0)==64){h=ba;g=k[h>>2]|0;h=k[h+4>>2]|0;n=s&32;if(!((g|0)==0&(h|0)==0)){b=N;do{b=b+-1|0;i[b>>0]=l[1095276+(g&15)>>0]|n;g=uf(g|0,h|0,4)|0;h=L}while(!((g|0)==0&(h|0)==0));K=ba;if((q&8|0)==0|(k[K>>2]|0)==0&(k[K+4>>2]|0)==0){g=q;q=0;n=1095292;K=77}else{g=q;q=2;n=1095292+(s>>4)|0;K=77}}else{b=N;g=q;q=0;n=1095292;K=77}}else if((K|0)==76){b=Le(b,g,N)|0;g=G;q=h;K=77}else if((K|0)==82){K=0;G=Ne(g,0,o)|0;F=(G|0)==0;b=g;s=F?o:G-g|0;v=0;u=1095292;g=F?g+o|0:G}else if((K|0)==86){K=0;h=0;g=0;q=b;while(1){n=k[q>>2]|0;if(!n)break;g=De(fa,n)|0;if((g|0)<0|g>>>0>(o-h|0)>>>0)break;h=g+h|0;if(o>>>0>h>>>0)q=q+4|0;else break}if((g|0)<0){f=-1;break a}Oe(a,32,I,h,G);if(!h){b=0;K=97}else{n=0;while(1){g=k[b>>2]|0;if(!g){b=h;K=97;break g}g=De(fa,g)|0;n=g+n|0;if((n|0)>(h|0)){b=h;K=97;break g}if(!(k[a>>2]&32))Fe(fa,g,a)|0;if(n>>>0>=h>>>0){b=h;K=97;break}else b=b+4|0}}}while(0);if((K|0)==97){K=0;Oe(a,32,I,b,G^8192);g=(I|0)>(b|0)?I:b;o=J;x=H;continue}if((K|0)==77){K=0;h=(o|0)>-1?g&-65537:g;g=ba;g=(k[g>>2]|0)!=0|(k[g+4>>2]|0)!=0;if((o|0)!=0|g){s=(g&1^1)+(V-b)|0;s=(o|0)>(s|0)?o:s;v=q;u=n;g=N}else{b=N;s=0;v=q;u=n;g=N}}q=g-b|0;n=(s|0)<(q|0)?q:s;o=v+n|0;g=(I|0)<(o|0)?o:I;Oe(a,32,g,o,h);if(!(k[a>>2]&32))Fe(u,v,a)|0;Oe(a,48,g,o,h^65536);Oe(a,48,n,q,0);if(!(k[a>>2]&32))Fe(b,q,a)|0;Oe(a,32,g,o,h^8192);o=J;x=H}h:do if((K|0)==244)if(!a)if(!o)f=0;else{f=1;while(1){b=k[e+(f<<2)>>2]|0;if(!b){b=0;break}Ke(d+(f<<3)|0,b,c);f=f+1|0;if((f|0)>=10){f=1;break h}}while(1){f=f+1|0;if(b|0){f=-1;break h}if((f|0)>=10){f=1;break h}b=k[e+(f<<2)>>2]|0}}while(0);r=ia;return f|0}function Ke(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0.0;a:do if(b>>>0<=20)do switch(b|0){case 9:{d=(k[c>>2]|0)+(4-1)&~(4-1);b=k[d>>2]|0;k[c>>2]=d+4;k[a>>2]=b;break a}case 10:{d=(k[c>>2]|0)+(4-1)&~(4-1);b=k[d>>2]|0;k[c>>2]=d+4;d=a;k[d>>2]=b;k[d+4>>2]=((b|0)<0)<<31>>31;break a}case 11:{d=(k[c>>2]|0)+(4-1)&~(4-1);b=k[d>>2]|0;k[c>>2]=d+4;d=a;k[d>>2]=b;k[d+4>>2]=0;break a}case 12:{d=(k[c>>2]|0)+(8-1)&~(8-1);b=d;e=k[b>>2]|0;b=k[b+4>>2]|0;k[c>>2]=d+8;d=a;k[d>>2]=e;k[d+4>>2]=b;break a}case 13:{e=(k[c>>2]|0)+(4-1)&~(4-1);d=k[e>>2]|0;k[c>>2]=e+4;d=(d&65535)<<16>>16;e=a;k[e>>2]=d;k[e+4>>2]=((d|0)<0)<<31>>31;break a}case 14:{e=(k[c>>2]|0)+(4-1)&~(4-1);d=k[e>>2]|0;k[c>>2]=e+4;e=a;k[e>>2]=d&65535;k[e+4>>2]=0;break a}case 15:{e=(k[c>>2]|0)+(4-1)&~(4-1);d=k[e>>2]|0;k[c>>2]=e+4;d=(d&255)<<24>>24;e=a;k[e>>2]=d;k[e+4>>2]=((d|0)<0)<<31>>31;break a}case 16:{e=(k[c>>2]|0)+(4-1)&~(4-1);d=k[e>>2]|0;k[c>>2]=e+4;e=a;k[e>>2]=d&255;k[e+4>>2]=0;break a}case 17:{e=(k[c>>2]|0)+(8-1)&~(8-1);f=+p[e>>3];k[c>>2]=e+8;p[a>>3]=f;break a}case 18:{e=(k[c>>2]|0)+(8-1)&~(8-1);f=+p[e>>3];k[c>>2]=e+8;p[a>>3]=f;break a}default:break a}while(0);while(0);return}function Le(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;if(b>>>0>0|(b|0)==0&a>>>0>4294967295)while(1){d=Ef(a|0,b|0,10,0)|0;c=c+-1|0;i[c>>0]=d|48;d=a;a=Df(a|0,b|0,10,0)|0;if(!(b>>>0>9|(b|0)==9&d>>>0>4294967295))break;else b=L}if(a)while(1){c=c+-1|0;i[c>>0]=(a>>>0)%10|0|48;if(a>>>0<10)break;else a=(a>>>0)/10|0}return c|0}function Me(a){a=a|0;var b=0,c=0;b=0;while(1){if((l[1095302+b>>0]|0)==(a|0)){c=2;break}b=b+1|0;if((b|0)==87){b=87;a=1095390;c=5;break}}if((c|0)==2)if(!b)b=1095390;else{a=1095390;c=5}if((c|0)==5)while(1){do{c=a;a=a+1|0}while((i[c>>0]|0)!=0);b=b+-1|0;if(!b){b=a;break}else c=5}return b|0}function Ne(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;f=b&255;d=(c|0)!=0;a:do if(d&(a&3|0)!=0){e=b&255;while(1){if((i[a>>0]|0)==e<<24>>24)break a;a=a+1|0;c=c+-1|0;d=(c|0)!=0;if(!(d&(a&3|0)!=0)){g=5;break}}}else g=5;while(0);b:do if((g|0)==5)if(d){e=b&255;if((i[a>>0]|0)!=e<<24>>24){d=ha(f,16843009)|0;c:do if(c>>>0>3)while(1){f=k[a>>2]^d;if((f&-2139062144^-2139062144)&f+-16843009|0)break;a=a+4|0;c=c+-4|0;if(c>>>0<=3){g=11;break c}}else g=11;while(0);if((g|0)==11)if(!c){c=0;break}while(1){if((i[a>>0]|0)==e<<24>>24)break b;a=a+1|0;c=c+-1|0;if(!c){c=0;break}}}}else c=0;while(0);return (c|0?a:0)|0}function Oe(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;g=r;r=r+256|0;f=g;do if((c|0)>(d|0)&(e&73728|0)==0){e=c-d|0;rf(f|0,b|0,(e>>>0>256?256:e)|0)|0;d=k[a>>2]|0;c=(d&32|0)==0;if(e>>>0>255){b=e;do{if(c){Fe(f,256,a)|0;d=k[a>>2]|0}b=b+-256|0;c=(d&32|0)==0}while(b>>>0>255);if(c)e=e&255;else break}else if(!c)break;Fe(f,e,a)|0}while(0);r=g;return}function Pe(a,b){a=+a;b=b|0;return +(+Qe(a,b))}function Qe(a,b){a=+a;b=b|0;var c=0,d=0,e=0;p[t>>3]=a;c=k[t>>2]|0;d=k[t+4>>2]|0;e=uf(c|0,d|0,52)|0;e=e&2047;switch(e|0){case 0:{if(a!=0.0){a=+Qe(a*18446744073709551616.0,b);c=(k[b>>2]|0)+-64|0}else c=0;k[b>>2]=c;break}case 2047:break;default:{k[b>>2]=e+-1022;k[t>>2]=c;k[t+4>>2]=d&-2146435073|1071644672;a=+p[t>>3]}}return +a}function Re(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0;o=r;r=r+128|0;j=o+112|0;l=o;m=l;p=941232;q=m+112|0;do{k[m>>2]=k[p>>2];m=m+4|0;p=p+4|0}while((m|0)<(q|0));if((b+-1|0)>>>0>2147483646)if(!b){e=j;f=1;n=4}else{q=xe()|0;k[q>>2]=75}else{e=a;f=b;n=4}if((n|0)==4?(q=-2-e|0,q=f>>>0>q>>>0?q:f,k[l+48>>2]=q,h=l+20|0,k[h>>2]=e,k[l+44>>2]=e,p=e+q|0,g=l+16|0,k[g>>2]=p,k[l+28>>2]=p,Ie(l,c,d)|0,q|0):0){q=k[h>>2]|0;i[q+(((q|0)==(k[g>>2]|0))<<31>>31)>>0]=0}r=o;return}function Se(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=a+20|0;e=k[d>>2]|0;a=(k[a+16>>2]|0)-e|0;a=a>>>0>c>>>0?c:a;vf(e|0,b|0,a|0)|0;k[d>>2]=(k[d>>2]|0)+a;return c|0}function Te(a,b){a=a|0;b=b|0;a=Ue(a,b)|0;return ((i[a>>0]|0)==(b&255)<<24>>24?a:0)|0}function Ue(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;d=b&255;a:do if(!d)a=a+(Ve(a)|0)|0;else{if(a&3){c=b&255;do{e=i[a>>0]|0;if(e<<24>>24==0?1:e<<24>>24==c<<24>>24)break a;a=a+1|0}while((a&3|0)!=0)}d=ha(d,16843009)|0;c=k[a>>2]|0;b:do if(!((c&-2139062144^-2139062144)&c+-16843009))do{e=c^d;if((e&-2139062144^-2139062144)&e+-16843009|0)break b;a=a+4|0;c=k[a>>2]|0}while(!((c&-2139062144^-2139062144)&c+-16843009|0));while(0);c=b&255;while(1){e=i[a>>0]|0;if(e<<24>>24==0?1:e<<24>>24==c<<24>>24)break;else a=a+1|0}}while(0);return a|0}function Ve(a){a=a|0;var b=0,c=0,d=0;d=a;a:do if(!(d&3))c=4;else{b=a;a=d;while(1){if(!(i[b>>0]|0))break a;b=b+1|0;a=b;if(!(a&3)){a=b;c=4;break}}}while(0);if((c|0)==4){while(1){b=k[a>>2]|0;if(!((b&-2139062144^-2139062144)&b+-16843009))a=a+4|0;else break}if((b&255)<<24>>24)do a=a+1|0;while((i[a>>0]|0)!=0)}return a-d|0}function We(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=r;r=r+16|0;e=d;k[e>>2]=c;Xe(a,b,e);r=d;return}function Xe(a,b,c){a=a|0;b=b|0;c=c|0;Re(a,2147483647,b,c);return}function Ye(){var a=0,b=0,c=0;do if((k[235299]|0)>=0?(Ge()|0)!=0:0){if((i[941195]|0)!=10?(a=k[235285]|0,a>>>0<(k[235284]|0)>>>0):0){k[235285]=a+1;i[a>>0]=10;break}Be(941120,10)|0}else c=3;while(0);do if((c|0)==3){if((i[941195]|0)!=10?(b=k[235285]|0,b>>>0<(k[235284]|0)>>>0):0){k[235285]=b+1;i[b>>0]=10;break}Be(941120,10)|0}while(0);return}function Ze(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Fe(a,ha(c,b)|0,d)|0;return}function _e(a,b){a=a|0;b=b|0;var c=0,d=0;d=i[a>>0]|0;c=i[b>>0]|0;if(d<<24>>24==0?1:d<<24>>24!=c<<24>>24)b=d;else{do{a=a+1|0;b=b+1|0;d=i[a>>0]|0;c=i[b>>0]|0}while(!(d<<24>>24==0?1:d<<24>>24!=c<<24>>24));b=d}return (b&255)-(c&255)|0}function $e(a,b){a=a|0;b=b|0;af(a,b,4);return}function af(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;e=b;a:do if(!((e^a)&3)){d=(c|0)!=0;if(d&(e&3|0)!=0)do{e=i[b>>0]|0;i[a>>0]=e;if(!(e<<24>>24))break a;c=c+-1|0;b=b+1|0;a=a+1|0;d=(c|0)!=0}while(d&(b&3|0)!=0);if(d){if(i[b>>0]|0){b:do if(c>>>0>3)do{d=k[b>>2]|0;if((d&-2139062144^-2139062144)&d+-16843009|0)break b;k[a>>2]=d;c=c+-4|0;b=b+4|0;a=a+4|0}while(c>>>0>3);while(0);f=11}}else c=0}else f=11;while(0);c:do if((f|0)==11)if(!c)c=0;else while(1){f=i[b>>0]|0;i[a>>0]=f;if(!(f<<24>>24))break c;c=c+-1|0;a=a+1|0;if(!c){c=0;break}else b=b+1|0}while(0);rf(a|0,0,c|0)|0;return}function bf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;a:do if(!c)c=0;else{while(1){d=i[a>>0]|0;e=i[b>>0]|0;if(d<<24>>24!=e<<24>>24)break;c=c+-1|0;if(!c){c=0;break a}else{a=a+1|0;b=b+1|0}}c=(d&255)-(e&255)|0}while(0);return c|0}
-function cf(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;do if(a>>>0<245){o=a>>>0<11?16:a+11&-8;a=o>>>3;i=k[274323]|0;b=i>>>a;if(b&3|0){b=(b&1^1)+a|0;c=1097332+(b<<1<<2)|0;d=c+8|0;e=k[d>>2]|0;f=e+8|0;g=k[f>>2]|0;do if((c|0)!=(g|0)){if(g>>>0<(k[274327]|0)>>>0)ua();a=g+12|0;if((k[a>>2]|0)==(e|0)){k[a>>2]=c;k[d>>2]=g;break}else ua()}else k[274323]=i&~(1<<b);while(0);G=b<<3;k[e+4>>2]=G|3;G=e+G+4|0;k[G>>2]=k[G>>2]|1;G=f;return G|0}g=k[274325]|0;if(o>>>0>g>>>0){if(b|0){c=2<<a;c=b<<a&(c|0-c);c=(c&0-c)+-1|0;h=c>>>12&16;c=c>>>h;e=c>>>5&8;c=c>>>e;f=c>>>2&4;c=c>>>f;d=c>>>1&2;c=c>>>d;b=c>>>1&1;b=(e|h|f|d|b)+(c>>>b)|0;c=1097332+(b<<1<<2)|0;d=c+8|0;f=k[d>>2]|0;h=f+8|0;e=k[h>>2]|0;do if((c|0)!=(e|0)){if(e>>>0<(k[274327]|0)>>>0)ua();a=e+12|0;if((k[a>>2]|0)==(f|0)){k[a>>2]=c;k[d>>2]=e;j=k[274325]|0;break}else ua()}else{k[274323]=i&~(1<<b);j=g}while(0);g=(b<<3)-o|0;k[f+4>>2]=o|3;d=f+o|0;k[d+4>>2]=g|1;k[d+g>>2]=g;if(j|0){e=k[274328]|0;b=j>>>3;c=1097332+(b<<1<<2)|0;a=k[274323]|0;b=1<<b;if(a&b){a=c+8|0;b=k[a>>2]|0;if(b>>>0<(k[274327]|0)>>>0)ua();else{l=a;m=b}}else{k[274323]=a|b;l=c+8|0;m=c}k[l>>2]=e;k[m+12>>2]=e;k[e+8>>2]=m;k[e+12>>2]=c}k[274325]=g;k[274328]=d;G=h;return G|0}a=k[274324]|0;if(a){h=(a&0-a)+-1|0;F=h>>>12&16;h=h>>>F;E=h>>>5&8;h=h>>>E;G=h>>>2&4;h=h>>>G;b=h>>>1&2;h=h>>>b;i=h>>>1&1;i=k[1097596+((E|F|G|b|i)+(h>>>i)<<2)>>2]|0;h=(k[i+4>>2]&-8)-o|0;b=i;while(1){a=k[b+16>>2]|0;if(!a){a=k[b+20>>2]|0;if(!a)break}b=(k[a+4>>2]&-8)-o|0;G=b>>>0<h>>>0;h=G?b:h;b=a;i=G?a:i}e=k[274327]|0;if(i>>>0<e>>>0)ua();g=i+o|0;if(i>>>0>=g>>>0)ua();f=k[i+24>>2]|0;c=k[i+12>>2]|0;do if((c|0)==(i|0)){b=i+20|0;a=k[b>>2]|0;if(!a){b=i+16|0;a=k[b>>2]|0;if(!a){n=0;break}}while(1){c=a+20|0;d=k[c>>2]|0;if(d|0){a=d;b=c;continue}c=a+16|0;d=k[c>>2]|0;if(!d)break;else{a=d;b=c}}if(b>>>0<e>>>0)ua();else{k[b>>2]=0;n=a;break}}else{d=k[i+8>>2]|0;if(d>>>0<e>>>0)ua();a=d+12|0;if((k[a>>2]|0)!=(i|0))ua();b=c+8|0;if((k[b>>2]|0)==(i|0)){k[a>>2]=c;k[b>>2]=d;n=c;break}else ua()}while(0);do if(f|0){a=k[i+28>>2]|0;b=1097596+(a<<2)|0;if((i|0)==(k[b>>2]|0)){k[b>>2]=n;if(!n){k[274324]=k[274324]&~(1<<a);break}}else{if(f>>>0<(k[274327]|0)>>>0)ua();a=f+16|0;if((k[a>>2]|0)==(i|0))k[a>>2]=n;else k[f+20>>2]=n;if(!n)break}b=k[274327]|0;if(n>>>0<b>>>0)ua();k[n+24>>2]=f;a=k[i+16>>2]|0;do if(a|0)if(a>>>0<b>>>0)ua();else{k[n+16>>2]=a;k[a+24>>2]=n;break}while(0);a=k[i+20>>2]|0;if(a|0)if(a>>>0<(k[274327]|0)>>>0)ua();else{k[n+20>>2]=a;k[a+24>>2]=n;break}}while(0);if(h>>>0<16){G=h+o|0;k[i+4>>2]=G|3;G=i+G+4|0;k[G>>2]=k[G>>2]|1}else{k[i+4>>2]=o|3;k[g+4>>2]=h|1;k[g+h>>2]=h;a=k[274325]|0;if(a|0){d=k[274328]|0;b=a>>>3;c=1097332+(b<<1<<2)|0;a=k[274323]|0;b=1<<b;if(a&b){a=c+8|0;b=k[a>>2]|0;if(b>>>0<(k[274327]|0)>>>0)ua();else{p=a;q=b}}else{k[274323]=a|b;p=c+8|0;q=c}k[p>>2]=d;k[q+12>>2]=d;k[d+8>>2]=q;k[d+12>>2]=c}k[274325]=h;k[274328]=g}G=i+8|0;return G|0}}}else if(a>>>0<=4294967231){a=a+11|0;o=a&-8;j=k[274324]|0;if(j){c=0-o|0;a=a>>>8;if(a)if(o>>>0>16777215)i=31;else{q=(a+1048320|0)>>>16&8;z=a<<q;p=(z+520192|0)>>>16&4;z=z<<p;i=(z+245760|0)>>>16&2;i=14-(p|q|i)+(z<<i>>>15)|0;i=o>>>(i+7|0)&1|i<<1}else i=0;b=k[1097596+(i<<2)>>2]|0;a:do if(!b){a=0;b=0;z=86}else{e=c;a=0;g=o<<((i|0)==31?0:25-(i>>>1)|0);h=b;b=0;while(1){d=k[h+4>>2]&-8;c=d-o|0;if(c>>>0<e>>>0)if((d|0)==(o|0)){a=h;b=h;z=90;break a}else b=h;else c=e;d=k[h+20>>2]|0;h=k[h+16+(g>>>31<<2)>>2]|0;a=(d|0)==0|(d|0)==(h|0)?a:d;d=(h|0)==0;if(d){z=86;break}else{e=c;g=g<<(d&1^1)}}}while(0);if((z|0)==86){if((a|0)==0&(b|0)==0){a=2<<i;a=j&(a|0-a);if(!a)break;q=(a&0-a)+-1|0;m=q>>>12&16;q=q>>>m;l=q>>>5&8;q=q>>>l;n=q>>>2&4;q=q>>>n;p=q>>>1&2;q=q>>>p;a=q>>>1&1;a=k[1097596+((l|m|n|p|a)+(q>>>a)<<2)>>2]|0}if(!a){h=c;i=b}else z=90}if((z|0)==90)while(1){z=0;q=(k[a+4>>2]&-8)-o|0;d=q>>>0<c>>>0;c=d?q:c;b=d?a:b;d=k[a+16>>2]|0;if(d|0){a=d;z=90;continue}a=k[a+20>>2]|0;if(!a){h=c;i=b;break}else z=90}if((i|0)!=0?h>>>0<((k[274325]|0)-o|0)>>>0:0){e=k[274327]|0;if(i>>>0<e>>>0)ua();g=i+o|0;if(i>>>0>=g>>>0)ua();f=k[i+24>>2]|0;c=k[i+12>>2]|0;do if((c|0)==(i|0)){b=i+20|0;a=k[b>>2]|0;if(!a){b=i+16|0;a=k[b>>2]|0;if(!a){s=0;break}}while(1){c=a+20|0;d=k[c>>2]|0;if(d|0){a=d;b=c;continue}c=a+16|0;d=k[c>>2]|0;if(!d)break;else{a=d;b=c}}if(b>>>0<e>>>0)ua();else{k[b>>2]=0;s=a;break}}else{d=k[i+8>>2]|0;if(d>>>0<e>>>0)ua();a=d+12|0;if((k[a>>2]|0)!=(i|0))ua();b=c+8|0;if((k[b>>2]|0)==(i|0)){k[a>>2]=c;k[b>>2]=d;s=c;break}else ua()}while(0);do if(f|0){a=k[i+28>>2]|0;b=1097596+(a<<2)|0;if((i|0)==(k[b>>2]|0)){k[b>>2]=s;if(!s){k[274324]=k[274324]&~(1<<a);break}}else{if(f>>>0<(k[274327]|0)>>>0)ua();a=f+16|0;if((k[a>>2]|0)==(i|0))k[a>>2]=s;else k[f+20>>2]=s;if(!s)break}b=k[274327]|0;if(s>>>0<b>>>0)ua();k[s+24>>2]=f;a=k[i+16>>2]|0;do if(a|0)if(a>>>0<b>>>0)ua();else{k[s+16>>2]=a;k[a+24>>2]=s;break}while(0);a=k[i+20>>2]|0;if(a|0)if(a>>>0<(k[274327]|0)>>>0)ua();else{k[s+20>>2]=a;k[a+24>>2]=s;break}}while(0);do if(h>>>0>=16){k[i+4>>2]=o|3;k[g+4>>2]=h|1;k[g+h>>2]=h;a=h>>>3;if(h>>>0<256){c=1097332+(a<<1<<2)|0;b=k[274323]|0;a=1<<a;if(b&a){a=c+8|0;b=k[a>>2]|0;if(b>>>0<(k[274327]|0)>>>0)ua();else{t=a;v=b}}else{k[274323]=b|a;t=c+8|0;v=c}k[t>>2]=g;k[v+12>>2]=g;k[g+8>>2]=v;k[g+12>>2]=c;break}a=h>>>8;if(a)if(h>>>0>16777215)c=31;else{F=(a+1048320|0)>>>16&8;G=a<<F;E=(G+520192|0)>>>16&4;G=G<<E;c=(G+245760|0)>>>16&2;c=14-(E|F|c)+(G<<c>>>15)|0;c=h>>>(c+7|0)&1|c<<1}else c=0;d=1097596+(c<<2)|0;k[g+28>>2]=c;a=g+16|0;k[a+4>>2]=0;k[a>>2]=0;a=k[274324]|0;b=1<<c;if(!(a&b)){k[274324]=a|b;k[d>>2]=g;k[g+24>>2]=d;k[g+12>>2]=g;k[g+8>>2]=g;break}c=h<<((c|0)==31?0:25-(c>>>1)|0);d=k[d>>2]|0;while(1){if((k[d+4>>2]&-8|0)==(h|0)){z=148;break}b=d+16+(c>>>31<<2)|0;a=k[b>>2]|0;if(!a){z=145;break}else{c=c<<1;d=a}}if((z|0)==145)if(b>>>0<(k[274327]|0)>>>0)ua();else{k[b>>2]=g;k[g+24>>2]=d;k[g+12>>2]=g;k[g+8>>2]=g;break}else if((z|0)==148){a=d+8|0;b=k[a>>2]|0;G=k[274327]|0;if(b>>>0>=G>>>0&d>>>0>=G>>>0){k[b+12>>2]=g;k[a>>2]=g;k[g+8>>2]=b;k[g+12>>2]=d;k[g+24>>2]=0;break}else ua()}}else{G=h+o|0;k[i+4>>2]=G|3;G=i+G+4|0;k[G>>2]=k[G>>2]|1}while(0);G=i+8|0;return G|0}}}else o=-1;while(0);c=k[274325]|0;if(c>>>0>=o>>>0){a=c-o|0;b=k[274328]|0;if(a>>>0>15){G=b+o|0;k[274328]=G;k[274325]=a;k[G+4>>2]=a|1;k[G+a>>2]=a;k[b+4>>2]=o|3}else{k[274325]=0;k[274328]=0;k[b+4>>2]=c|3;G=b+c+4|0;k[G>>2]=k[G>>2]|1}G=b+8|0;return G|0}a=k[274326]|0;if(a>>>0>o>>>0){E=a-o|0;k[274326]=E;G=k[274329]|0;F=G+o|0;k[274329]=F;k[F+4>>2]=E|1;k[G+4>>2]=o|3;G=G+8|0;return G|0}do if(!(k[274441]|0)){a=Ga(30)|0;if(!(a+-1&a)){k[274443]=a;k[274442]=a;k[274444]=-1;k[274445]=-1;k[274446]=0;k[274434]=0;v=(Ra(0)|0)&-16^1431655768;k[274441]=v;break}else ua()}while(0);g=o+48|0;d=k[274443]|0;h=o+47|0;c=d+h|0;d=0-d|0;i=c&d;if(i>>>0<=o>>>0){G=0;return G|0}a=k[274433]|0;if(a|0?(t=k[274431]|0,v=t+i|0,v>>>0<=t>>>0|v>>>0>a>>>0):0){G=0;return G|0}b:do if(!(k[274434]&4)){b=k[274329]|0;c:do if(b){e=1097740;while(1){a=k[e>>2]|0;if(a>>>0<=b>>>0?(r=e+4|0,(a+(k[r>>2]|0)|0)>>>0>b>>>0):0)break;a=k[e+8>>2]|0;if(!a){z=173;break c}else e=a}a=c-(k[274326]|0)&d;if(a>>>0<2147483647){b=Ba(a|0)|0;if((b|0)==((k[e>>2]|0)+(k[r>>2]|0)|0)){if((b|0)!=(-1|0)){g=b;f=a;z=193;break b}}else z=183}}else z=173;while(0);do if((z|0)==173?(u=Ba(0)|0,(u|0)!=(-1|0)):0){a=u;b=k[274442]|0;c=b+-1|0;if(!(c&a))a=i;else a=i-a+(c+a&0-b)|0;b=k[274431]|0;c=b+a|0;if(a>>>0>o>>>0&a>>>0<2147483647){v=k[274433]|0;if(v|0?c>>>0<=b>>>0|c>>>0>v>>>0:0)break;b=Ba(a|0)|0;if((b|0)==(u|0)){g=u;f=a;z=193;break b}else z=183}}while(0);d:do if((z|0)==183){c=0-a|0;do if(g>>>0>a>>>0&(a>>>0<2147483647&(b|0)!=(-1|0))?(w=k[274443]|0,w=h-a+w&0-w,w>>>0<2147483647):0)if((Ba(w|0)|0)==(-1|0)){Ba(c|0)|0;break d}else{a=w+a|0;break}while(0);if((b|0)!=(-1|0)){g=b;f=a;z=193;break b}}while(0);k[274434]=k[274434]|4;z=190}else z=190;while(0);if((((z|0)==190?i>>>0<2147483647:0)?(x=Ba(i|0)|0,y=Ba(0)|0,x>>>0<y>>>0&((x|0)!=(-1|0)&(y|0)!=(-1|0))):0)?(f=y-x|0,f>>>0>(o+40|0)>>>0):0){g=x;z=193}if((z|0)==193){a=(k[274431]|0)+f|0;k[274431]=a;if(a>>>0>(k[274432]|0)>>>0)k[274432]=a;j=k[274329]|0;do if(j){e=1097740;while(1){a=k[e>>2]|0;b=e+4|0;c=k[b>>2]|0;if((g|0)==(a+c|0)){z=203;break}d=k[e+8>>2]|0;if(!d)break;else e=d}if(((z|0)==203?(k[e+12>>2]&8|0)==0:0)?j>>>0<g>>>0&j>>>0>=a>>>0:0){k[b>>2]=c+f;G=j+8|0;G=(G&7|0)==0?0:0-G&7;F=j+G|0;G=f-G+(k[274326]|0)|0;k[274329]=F;k[274326]=G;k[F+4>>2]=G|1;k[F+G+4>>2]=40;k[274330]=k[274445];break}a=k[274327]|0;if(g>>>0<a>>>0){k[274327]=g;h=g}else h=a;b=g+f|0;a=1097740;while(1){if((k[a>>2]|0)==(b|0)){z=211;break}a=k[a+8>>2]|0;if(!a){b=1097740;break}}if((z|0)==211)if(!(k[a+12>>2]&8)){k[a>>2]=g;m=a+4|0;k[m>>2]=(k[m>>2]|0)+f;m=g+8|0;m=g+((m&7|0)==0?0:0-m&7)|0;a=b+8|0;a=b+((a&7|0)==0?0:0-a&7)|0;l=m+o|0;i=a-m-o|0;k[m+4>>2]=o|3;do if((a|0)!=(j|0)){if((a|0)==(k[274328]|0)){G=(k[274325]|0)+i|0;k[274325]=G;k[274328]=l;k[l+4>>2]=G|1;k[l+G>>2]=G;break}b=k[a+4>>2]|0;if((b&3|0)==1){g=b&-8;e=b>>>3;e:do if(b>>>0>=256){f=k[a+24>>2]|0;d=k[a+12>>2]|0;do if((d|0)==(a|0)){d=a+16|0;c=d+4|0;b=k[c>>2]|0;if(!b){b=k[d>>2]|0;if(!b){E=0;break}else c=d}while(1){d=b+20|0;e=k[d>>2]|0;if(e|0){b=e;c=d;continue}d=b+16|0;e=k[d>>2]|0;if(!e)break;else{b=e;c=d}}if(c>>>0<h>>>0)ua();else{k[c>>2]=0;E=b;break}}else{e=k[a+8>>2]|0;if(e>>>0<h>>>0)ua();b=e+12|0;if((k[b>>2]|0)!=(a|0))ua();c=d+8|0;if((k[c>>2]|0)==(a|0)){k[b>>2]=d;k[c>>2]=e;E=d;break}else ua()}while(0);if(!f)break;b=k[a+28>>2]|0;c=1097596+(b<<2)|0;do if((a|0)!=(k[c>>2]|0)){if(f>>>0<(k[274327]|0)>>>0)ua();b=f+16|0;if((k[b>>2]|0)==(a|0))k[b>>2]=E;else k[f+20>>2]=E;if(!E)break e}else{k[c>>2]=E;if(E|0)break;k[274324]=k[274324]&~(1<<b);break e}while(0);d=k[274327]|0;if(E>>>0<d>>>0)ua();k[E+24>>2]=f;b=a+16|0;c=k[b>>2]|0;do if(c|0)if(c>>>0<d>>>0)ua();else{k[E+16>>2]=c;k[c+24>>2]=E;break}while(0);b=k[b+4>>2]|0;if(!b)break;if(b>>>0<(k[274327]|0)>>>0)ua();else{k[E+20>>2]=b;k[b+24>>2]=E;break}}else{c=k[a+8>>2]|0;d=k[a+12>>2]|0;b=1097332+(e<<1<<2)|0;do if((c|0)!=(b|0)){if(c&g