Merge mozilla-central to inbound. a=merge CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Thu, 25 Oct 2018 01:04:19 +0300
changeset 491196 524c546c7ad5a2a73f56bb6858ffcac4f82a6088
parent 491149 40036a4302c376f6de9f5e767be9a0a4e4d89bf6 (current diff)
parent 491195 ddadc29de671917f66478e62a6accd4764892d25 (diff)
child 491197 02ac5668f849f1a23eb3702e468e32a0900c54f6
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersmerge
milestone65.0a1
Merge mozilla-central to inbound. a=merge CLOSED TREE
toolkit/locales/en-US/chrome/mozapps/update/history.dtd
--- a/.eslintignore
+++ b/.eslintignore
@@ -28,17 +28,18 @@ memory/replace/dmd/test/**
 modules/**
 netwerk/cookie/test/browser/**
 netwerk/protocol/**
 netwerk/dns/**
 netwerk/test/browser/**
 netwerk/test/httpserver/**
 netwerk/test/mochitests/**
 netwerk/test/unit*/**
-netwerk/wifi/**
+# Bug 1501445.
+netwerk/wifi/tests/wifi_access_point_test.html
 parser/**
 tools/update-packaging/**
 uriloader/exthandler/**
 uriloader/exthandler/tests/mochitest/**
 widget/headless/tests/**
 widget/tests/**
 
 # We currently have no js files in these directories, so we ignore them by
@@ -166,26 +167,24 @@ devtools/server/tests/unit/sourcemapped.
 
 # devtools specific format test file
 devtools/server/tests/unit/xpcshell_debugging_script.js
 
 # dom/ exclusions
 dom/abort/**
 dom/animation/**
 dom/asmjscache/**
-dom/audiochannel/**
 dom/base/**
 dom/battery/**
 dom/bindings/**
 dom/broadcastchannel/**
 dom/browser-element/**
 dom/cache/test/mochitest/**
 dom/cache/test/xpcshell/**
 dom/canvas/**
-dom/commandhandler/**
 dom/console/**
 dom/crypto/**
 dom/encoding/**
 dom/events/**
 dom/fetch/**
 dom/file/**
 dom/filehandle/**
 dom/filesystem/**
@@ -250,16 +249,17 @@ dom/workers/**
 dom/worklet/**
 dom/xbl/**
 dom/xhr/**
 dom/xml/**
 dom/xslt/**
 dom/xul/**
 
 # Third-party
+dom/canvas/test/webgl-conf/**
 dom/media/webvtt/**
 
 # Third-party
 editor/libeditor/tests/browserscope/**
 
 # Third-party
 gfx/ots/**
 gfx/skia/**
@@ -298,16 +298,21 @@ mobile/android/chrome/content/about.js
 
 # Not much JS to lint and non-standard at that
 mobile/android/installer/
 mobile/android/locales/
 
 # Non-standard `(catch ex if ...)`
 mobile/android/chrome/content/browser.js
 
+# Pre-processed/pref files
+modules/libpref/greprefs.js
+modules/libpref/init/all.js
+modules/libpref/test/unit/*data/**
+
 # Only contains non-standard test files.
 python/**
 
 # security/ exclusions (pref files).
 security/manager/ssl/security-prefs.js
 
 # NSS / taskcluster only.
 security/nss/**
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2309,92 +2309,91 @@
       <handler event="dragstart"><![CDATA[
         if (this.mOverCloseButton) {
           event.stopPropagation();
         }
       ]]></handler>
 
       <handler event="mousedown" phase="capturing">
       <![CDATA[
-        if (event.button == 0 && !this.selected && this.multiselected) {
-          gBrowser.lockClearMultiSelectionOnce();
-        }
+        let tabContainer = this.parentNode;
 
-        let tabContainer = this.parentNode;
         if (tabContainer._closeTabByDblclick &&
             event.button == 0 &&
             event.detail == 1) {
           this._selectedOnFirstMouseDown = this.selected;
         }
 
         if (this.selected) {
           this.style.MozUserFocus = "ignore";
-        } else {
-          // When browser.tabs.multiselect config is set to false,
-          // then we ignore the state of multi-selection keys (Ctrl/Cmd).
-          const tabSelectionToggled = tabContainer._multiselectEnabled &&
-            (event.getModifierState("Accel") || event.shiftKey);
-
-          if (this.mOverCloseButton || this._overPlayingIcon || tabSelectionToggled) {
+        } else if (this.mOverCloseButton || this._overPlayingIcon) {
             // Prevent tabbox.xml from selecting the tab.
             event.stopPropagation();
-          }
         }
 
         if (event.button == 1) {
           gBrowser.warmupTab(gBrowser._findTabToBlurTo(this));
         }
+
+        if (event.button == 0 && tabContainer._multiselectEnabled) {
+          let shiftKey = event.shiftKey;
+          let accelKey = event.getModifierState("Accel");
+          if (shiftKey) {
+            const lastSelectedTab = gBrowser.lastMultiSelectedTab;
+            if (!accelKey) {
+              gBrowser.selectedTab = lastSelectedTab;
+
+              // Make sure selection is cleared when tab-switch doesn't happen.
+              gBrowser.clearMultiSelectedTabs(false);
+            }
+            gBrowser.addRangeToMultiSelectedTabs(lastSelectedTab, this);
+
+            // Prevent tabbox.xml from selecting the tab.
+            event.stopPropagation();
+          } else if (accelKey) {
+            // Ctrl (Cmd for mac) key is pressed
+            if (this.multiselected) {
+              gBrowser.removeFromMultiSelectedTabs(this, true);
+            } else if (this != gBrowser.selectedTab) {
+              gBrowser.addToMultiSelectedTabs(this, false);
+              gBrowser.lastMultiSelectedTab = this;
+            }
+
+            // Prevent tabbox.xml from selecting the tab.
+            event.stopPropagation();
+          } else if (!this.selected && this.multiselected) {
+            gBrowser.lockClearMultiSelectionOnce();
+          }
+        }
       ]]>
       </handler>
       <handler event="mouseup">
         // Make sure that clear-selection is released.
         // Otherwise selection using Shift key may be broken.
         gBrowser.unlockClearMultiSelection();
 
         this.style.MozUserFocus = "";
       </handler>
 
       <handler event="click" button="0"><![CDATA[
-        let tabContainer = this.parentNode;
-        if (tabContainer._multiselectEnabled) {
-          let shiftKey = event.shiftKey;
-          let accelKey = event.getModifierState("Accel");
-          if (shiftKey) {
-            const lastSelectedTab = gBrowser.lastMultiSelectedTab;
-            if (!accelKey) {
-              gBrowser.selectedTab = lastSelectedTab;
+        if (event.getModifierState("Accel") || event.shiftKey) {
+          return;
+        }
 
-              // Make sure selection is cleared when tab-switch doesn't happen.
-              gBrowser.clearMultiSelectedTabs(false);
-            }
-            gBrowser.addRangeToMultiSelectedTabs(lastSelectedTab, this);
-            return;
-          }
-          if (accelKey) {
-            // Ctrl (Cmd for mac) key is pressed
-            if (this.multiselected) {
-              gBrowser.removeFromMultiSelectedTabs(this, true);
-            } else if (this != gBrowser.selectedTab) {
-              gBrowser.addToMultiSelectedTabs(this, false);
-              gBrowser.lastMultiSelectedTab = this;
-            }
-            return;
-          }
+        if (gBrowser.multiSelectedTabsCount > 0 &&
+          !this.mOverCloseButton &&
+          !this._overPlayingIcon) {
+          // Tabs were previously multi-selected and user clicks on a tab
+          // without holding Ctrl/Cmd Key
 
-          const overCloseButton = event.originalTarget.getAttribute("anonid") == "close-button";
-          if (gBrowser.multiSelectedTabsCount > 0 && !overCloseButton && !this._overPlayingIcon) {
-            // Tabs were previously multi-selected and user clicks on a tab
-            // without holding Ctrl/Cmd Key
+          // Force positional attributes to update when the
+          // target (of the click) is the "active" tab.
+          let updatePositionalAttr = gBrowser.selectedTab == this;
 
-            // Force positional attributes to update when the
-            // target (of the click) is the "active" tab.
-            let updatePositionalAttr = gBrowser.selectedTab == this;
-
-            gBrowser.clearMultiSelectedTabs(updatePositionalAttr);
-          }
+          gBrowser.clearMultiSelectedTabs(updatePositionalAttr);
         }
 
         if (this._overPlayingIcon) {
           if (this.multiselected) {
             gBrowser.toggleMuteAudioOnMultiSelectedTabs(this);
           } else {
             this.toggleMuteAudio();
           }
--- a/browser/base/content/test/tabs/browser_multiselect_tabs_close.js
+++ b/browser/base/content/test/tabs/browser_multiselect_tabs_close.js
@@ -43,17 +43,18 @@ add_task(async function usingTabCloseBut
   ok(tab2.multiselected, "Tab2 is multiselected");
   ok(!tab2.closing, "Tab2 is not closing");
   ok(!tab3.multiselected, "Tab3 is not multiselected");
   ok(!tab3.closing, "Tab3 is not closing");
   ok(tab4.closing, "Tab4 is closing");
   is(gBrowser.multiSelectedTabsCount, 2, "Two multiselected tabs");
 
   // Closing a selected tab
-  let tab2CloseBtn = document.getAnonymousElementByAttribute(tab1, "anonid", "close-button");
+  let tab2CloseBtn = document.getAnonymousElementByAttribute(tab2, "anonid", "close-button");
+  tab2.mOverCloseButton = true;
   let tab1Closing = BrowserTestUtils.waitForTabClosing(tab1);
   let tab2Closing = BrowserTestUtils.waitForTabClosing(tab2);
   tab2CloseBtn.click();
   await tab1Closing;
   await tab2Closing;
 
   ok(tab1.closing, "Tab1 is closing");
   ok(tab2.closing, "Tab2 is closing");
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -708,17 +708,17 @@ BrowserGlue.prototype = {
     const options = {filter: ACTIVITY_STREAM_ID};
     this.pingCentre.sendPing(payload, options);
   },
 
   // nsIObserver implementation
   observe: async function BG_observe(subject, topic, data) {
     switch (topic) {
       case "notifications-open-settings":
-        this._openPreferences("privacy", { origin: "notifOpenSettings" });
+        this._openPreferences("privacy-permissions", { origin: "notifOpenSettings" });
         break;
       case "final-ui-startup":
         this._beforeUIStartup();
         break;
       case "browser-delayed-startup-finished":
         this._onFirstWindowLoaded(subject);
         Services.obs.removeObserver(this, "browser-delayed-startup-finished");
         break;
--- a/browser/components/payments/paymentUIService.js
+++ b/browser/components/payments/paymentUIService.js
@@ -74,17 +74,17 @@ PaymentUIService.prototype = {
         return;
       }
       container.hidden = false;
 
       // Prevent focusing or interacting with the <browser>.
       merchantBrowser.setAttribute("tabmodalPromptShowing", "true");
 
       // Darken the merchant content area.
-      let tabModalBackground = chromeWindow.document.createElement("box");
+      let tabModalBackground = chromeWindow.document.createXULElement("box");
       tabModalBackground.classList.add("tabModalBackground", "paymentDialogBackground");
       // Insert the same way as <tabmodalprompt>.
       merchantBrowser.parentNode.insertBefore(tabModalBackground,
                                               merchantBrowser.nextElementSibling);
     }, {
       once: true,
     });
   },
--- a/browser/components/urlbar/UrlbarInput.jsm
+++ b/browser/components/urlbar/UrlbarInput.jsm
@@ -59,17 +59,17 @@ class UrlbarInput {
       "setAttribute", "hasAttribute", "removeAttribute", "getAttribute",
       "focus", "blur", "select"];
     const READ_ONLY_PROPERTIES = ["inputField", "editor"];
     const READ_WRITE_PROPERTIES = ["placeholder", "readOnly",
       "selectionStart", "selectionEnd"];
 
     for (let method of METHODS) {
       this[method] = (...args) => {
-        this.textbox[method](...args);
+        return this.textbox[method](...args);
       };
     }
 
     for (let property of READ_ONLY_PROPERTIES) {
       Object.defineProperty(this, property, {
         enumerable: true,
         get() {
           return this.textbox[property];
--- a/devtools/client/aboutdebugging-new/src/actions/debug-targets.js
+++ b/devtools/client/aboutdebugging-new/src/actions/debug-targets.js
@@ -123,17 +123,17 @@ function requestTabs() {
 
     const client = getCurrentClient(getState().runtimes);
 
     try {
       const { tabs } = await client.listTabs({ favicons: true });
 
       dispatch({ type: REQUEST_TABS_SUCCESS, tabs });
     } catch (e) {
-      dispatch({ type: REQUEST_TABS_FAILURE, error: e.message });
+      dispatch({ type: REQUEST_TABS_FAILURE, error: e });
     }
   };
 }
 
 function requestExtensions() {
   return async (dispatch, getState) => {
     dispatch({ type: REQUEST_EXTENSIONS_START });
 
@@ -146,17 +146,17 @@ function requestExtensions() {
       const temporaryExtensions = extensions.filter(e => e.temporarilyInstalled);
 
       dispatch({
         type: REQUEST_EXTENSIONS_SUCCESS,
         installedExtensions,
         temporaryExtensions,
       });
     } catch (e) {
-      dispatch({ type: REQUEST_EXTENSIONS_FAILURE, error: e.message });
+      dispatch({ type: REQUEST_EXTENSIONS_FAILURE, error: e });
     }
   };
 }
 
 function requestWorkers() {
   return async (dispatch, getState) => {
     dispatch({ type: REQUEST_WORKERS_START });
 
@@ -171,17 +171,17 @@ function requestWorkers() {
 
       dispatch({
         type: REQUEST_WORKERS_SUCCESS,
         otherWorkers,
         serviceWorkers,
         sharedWorkers,
       });
     } catch (e) {
-      dispatch({ type: REQUEST_WORKERS_FAILURE, error: e.message });
+      dispatch({ type: REQUEST_WORKERS_FAILURE, error: e });
     }
   };
 }
 
 function startServiceWorker(actor) {
   return async (_, getState) => {
     const client = getCurrentClient(getState().runtimes);
 
--- a/devtools/client/aboutdebugging-new/src/actions/runtimes.js
+++ b/devtools/client/aboutdebugging-new/src/actions/runtimes.js
@@ -109,17 +109,17 @@ function connectRuntime(id) {
         type: CONNECT_RUNTIME_SUCCESS,
         runtime: {
           id,
           runtimeDetails,
           type: runtime.type,
         },
       });
     } catch (e) {
-      dispatch({ type: CONNECT_RUNTIME_FAILURE, error: e.message });
+      dispatch({ type: CONNECT_RUNTIME_FAILURE, error: e });
     }
   };
 }
 
 function disconnectRuntime(id) {
   return async (dispatch, getState) => {
     dispatch({ type: DISCONNECT_RUNTIME_START });
     try {
@@ -132,17 +132,17 @@ function disconnectRuntime(id) {
       dispatch({
         type: DISCONNECT_RUNTIME_SUCCESS,
         runtime: {
           id,
           type: runtime.type,
         },
       });
     } catch (e) {
-      dispatch({ type: DISCONNECT_RUNTIME_FAILURE, error: e.message });
+      dispatch({ type: DISCONNECT_RUNTIME_FAILURE, error: e });
     }
   };
 }
 
 function updateConnectionPromptSetting(connectionPromptEnabled) {
   return async (dispatch, getState) => {
     dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_START });
     try {
@@ -153,18 +153,17 @@ function updateConnectionPromptSetting(c
                                         connectionPromptEnabled);
       // Re-get actual value from the runtime.
       connectionPromptEnabled =
         await preferenceFront.getBoolPref(RUNTIME_PREFERENCE.CONNECTION_PROMPT);
 
       dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS,
                  runtime, connectionPromptEnabled });
     } catch (e) {
-      dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_FAILURE,
-                 error: e.message });
+      dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_FAILURE, error: e });
     }
   };
 }
 
 function watchRuntime(id) {
   return async (dispatch, getState) => {
     dispatch({ type: WATCH_RUNTIME_START });
 
@@ -185,17 +184,17 @@ function watchRuntime(id) {
       if (isSupportedDebugTarget(runtime.type, DEBUG_TARGETS.TAB)) {
         dispatch(Actions.requestTabs());
       }
 
       if (isSupportedDebugTarget(runtime.type, DEBUG_TARGETS.WORKER)) {
         dispatch(Actions.requestWorkers());
       }
     } catch (e) {
-      dispatch({ type: WATCH_RUNTIME_FAILURE, error: e.message });
+      dispatch({ type: WATCH_RUNTIME_FAILURE, error: e });
     }
   };
 }
 
 function unwatchRuntime(id) {
   return async (dispatch, getState) => {
     const runtime = findRuntimeById(id, getState().runtimes);
 
@@ -204,17 +203,17 @@ function unwatchRuntime(id) {
     try {
       if (id === RUNTIMES.THIS_FIREFOX) {
         // THIS_FIREFOX connects and disconnects on the fly when opening the page.
         await dispatch(disconnectRuntime(RUNTIMES.THIS_FIREFOX));
       }
 
       dispatch({ type: UNWATCH_RUNTIME_SUCCESS });
     } catch (e) {
-      dispatch({ type: UNWATCH_RUNTIME_FAILURE, error: e.message });
+      dispatch({ type: UNWATCH_RUNTIME_FAILURE, error: e });
     }
   };
 }
 
 function updateUSBRuntimes(runtimes) {
   return async (dispatch, getState) => {
     const currentRuntime = getCurrentRuntime(getState().runtimes);
 
--- a/devtools/client/aboutdebugging-new/src/actions/ui.js
+++ b/devtools/client/aboutdebugging-new/src/actions/ui.js
@@ -79,30 +79,30 @@ function updateNetworkLocations(location
 function installAdbAddon() {
   return async (dispatch, getState) => {
     dispatch({ type: ADB_ADDON_INSTALL_START });
 
     try {
       await adbAddon.install();
       dispatch({ type: ADB_ADDON_INSTALL_SUCCESS });
     } catch (e) {
-      dispatch({ type: ADB_ADDON_INSTALL_FAILURE, error: e.message });
+      dispatch({ type: ADB_ADDON_INSTALL_FAILURE, error: e });
     }
   };
 }
 
 function uninstallAdbAddon() {
   return async (dispatch, getState) => {
     dispatch({ type: ADB_ADDON_UNINSTALL_START });
 
     try {
       await adbAddon.uninstall();
       dispatch({ type: ADB_ADDON_UNINSTALL_SUCCESS });
     } catch (e) {
-      dispatch({ type: ADB_ADDON_UNINSTALL_FAILURE, error: e.message });
+      dispatch({ type: ADB_ADDON_UNINSTALL_FAILURE, error: e });
     }
   };
 }
 
 module.exports = {
   addNetworkLocation,
   installAdbAddon,
   removeNetworkLocation,
--- a/devtools/client/aboutdebugging-new/src/create-store.js
+++ b/devtools/client/aboutdebugging-new/src/create-store.js
@@ -9,16 +9,17 @@ const Services = require("Services");
 const { applyMiddleware, createStore } = require("devtools/client/shared/vendor/redux");
 const { thunk } = require("devtools/client/shared/redux/middleware/thunk.js");
 
 const rootReducer = require("./reducers/index");
 const { DebugTargetsState } = require("./reducers/debug-targets-state");
 const { RuntimesState } = require("./reducers/runtimes-state");
 const { UiState } = require("./reducers/ui-state");
 const debugTargetListenerMiddleware = require("./middleware/debug-target-listener");
+const errorLoggingMiddleware = require("./middleware/error-logging");
 const extensionComponentDataMiddleware = require("./middleware/extension-component-data");
 const tabComponentDataMiddleware = require("./middleware/tab-component-data");
 const workerComponentDataMiddleware = require("./middleware/worker-component-data");
 const { getDebugTargetCollapsibilities } = require("./modules/debug-target-collapsibilities");
 const { getNetworkLocations } = require("./modules/network-locations");
 
 const { PREFERENCES } = require("./constants");
 
@@ -26,16 +27,17 @@ function configureStore() {
   const initialState = {
     debugTargets: new DebugTargetsState(),
     runtimes: new RuntimesState(),
     ui: getUiState(),
   };
 
   const middleware = applyMiddleware(thunk,
                                      debugTargetListenerMiddleware,
+                                     errorLoggingMiddleware,
                                      extensionComponentDataMiddleware,
                                      tabComponentDataMiddleware,
                                      workerComponentDataMiddleware);
 
   return createStore(rootReducer, initialState, middleware);
 }
 
 function getUiState() {
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/src/middleware/error-logging.js
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/**
+ * Error logging middleware that will forward all actions that contain an error property
+ * to the console.
+ */
+function errorLoggingMiddleware() {
+  return next => action => {
+    if (action.error) {
+      const { error } = action;
+      if (error.message) {
+        console.error(`[ACTION FAILED] ${action.type}: ${error.message}`);
+      } else if (typeof error === "string") {
+        // All failure actions should dispatch an error object instead of a message.
+        // We allow some flexibility to still provide some error logging.
+        console.error(`[ACTION FAILED] ${action.type}: ${error}`);
+        console.error(`[ACTION FAILED] ${action.type} should dispatch the error object!`);
+      }
+
+      if (error.stack) {
+        console.error(error.stack);
+      }
+    }
+
+    return next(action);
+  };
+}
+
+module.exports = errorLoggingMiddleware;
--- a/devtools/client/aboutdebugging-new/src/middleware/moz.build
+++ b/devtools/client/aboutdebugging-new/src/middleware/moz.build
@@ -1,10 +1,11 @@
 # 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/.
 
 DevToolsModules(
     'debug-target-listener.js',
+    'error-logging.js',
     'extension-component-data.js',
     'tab-component-data.js',
     'worker-component-data.js',
 )
--- a/devtools/client/framework/source-map-url-service.js
+++ b/devtools/client/framework/source-map-url-service.js
@@ -56,27 +56,27 @@ SourceMapURLService.prototype._getLoadin
     this._loadingPromise = (async () => {
       if (this._target.isWorkerTarget) {
         return;
       }
       this._stylesheetsFront = await this._target.getFront("stylesheets");
       this._stylesheetsFront.on("stylesheet-added", this._onNewStyleSheet);
       const styleSheetsLoadingPromise =
           this._stylesheetsFront.getStyleSheets().then(sheets => {
-            sheets.forEach(this._onNewStyleSheet);
+            sheets.forEach(this._registerNewStyleSheet, this);
           }, () => {
             // Ignore any protocol-based errors.
           });
 
       // Start fetching the sources now.
       const loadingPromise = this._toolbox.threadClient.getSources().then(({sources}) => {
         // Ignore errors.  Register the sources we got; we can't rely on
         // an event to arrive if the source actor already existed.
         for (const source of sources) {
-          this._onSourceUpdated({source});
+          this._registerNewSource(source);
         }
       }, e => {
         // Also ignore any protocol-based errors.
       });
 
       await styleSheetsLoadingPromise;
       await loadingPromise;
     })();
@@ -87,16 +87,17 @@ SourceMapURLService.prototype._getLoadin
 /**
  * Reset the service.  This flushes the internal cache.
  */
 SourceMapURLService.prototype.reset = function() {
   this._sourceMapService.clearSourceMaps();
   this._urls.clear();
   this._subscriptions.clear();
   this._idMap.clear();
+  this._loadingPromise = null;
 };
 
 /**
  * Shut down the service, unregistering its event listeners and
  * flushing the cache.  After this call the service will no longer
  * function.
  */
 SourceMapURLService.prototype.destroy = function() {
@@ -109,47 +110,84 @@ SourceMapURLService.prototype.destroy = 
   Services.prefs.removeObserver(SOURCE_MAP_PREF, this._onPrefChanged);
   this._target = this._urls = this._subscriptions = this._idMap = null;
 };
 
 /**
  * A helper function that is called when a new source is available.
  */
 SourceMapURLService.prototype._onSourceUpdated = function(sourceEvent) {
+  const url = this._registerNewSource(sourceEvent.source);
+
+  if (url) {
+    // Subscribers might have been added for this file before the
+    // "source-updated" event was fired.
+    this._dispatchSubscribersForURL(url);
+  }
+};
+
+/**
+ * A helper function that registers a new source file with the service.
+ *
+ * @param {SourceActor} source The new source's actor.
+ * @returns {string | undefined} A URL for the registered file,
+ *        if registered successfully.
+ */
+SourceMapURLService.prototype._registerNewSource = function(source) {
   // Maybe we were shut down while waiting.
   if (!this._urls) {
     return;
   }
 
-  const { source } = sourceEvent;
   const { generatedUrl, url, actor: id, sourceMapURL } = source;
 
   // |generatedUrl| comes from the actor and is extracted from the
   // source code by SpiderMonkey.
   const seenUrl = generatedUrl || url;
   this._urls.set(seenUrl, { id, url: seenUrl, sourceMapURL });
   this._idMap.set(id, seenUrl);
+
+  return seenUrl;
 };
 
 /**
  * A helper function that is called when a new style sheet is
  * available.
  * @param {StyleSheetActor} sheet
  *        The new style sheet's actor.
  */
 SourceMapURLService.prototype._onNewStyleSheet = function(sheet) {
+  const url = this._registerNewStyleSheet(sheet);
+
+  if (url) {
+    // Subscribers might have been added for this file before the
+    // "stylesheet-added" event was fired.
+    this._dispatchSubscribersForURL(url);
+  }
+};
+
+/**
+ * A helper function that registers a new stylesheet with the service.
+ * @param {StyleSheetActor} sheet
+ *        The new style sheet's actor.
+ * @returns {string | undefined} A URL for the registered file,
+ *        if registered successfully.
+ */
+SourceMapURLService.prototype._registerNewStyleSheet = function(sheet) {
   // Maybe we were shut down while waiting.
   if (!this._urls) {
     return;
   }
 
   const {href, nodeHref, sourceMapURL, actorID: id} = sheet;
   const url = href || nodeHref;
   this._urls.set(url, { id, url, sourceMapURL});
   this._idMap.set(id, url);
+
+  return url;
 };
 
 /**
  * A callback that is called from the lower-level source map service
  * proxy (see toolbox.js) when some tool has installed a new source
  * map.  This happens when pretty-printing a source.
  *
  * @param {String} id
@@ -162,27 +200,36 @@ SourceMapURLService.prototype.sourceMapC
     return;
   }
 
   const urlKey = this._idMap.get(id);
   if (urlKey) {
     // The source map URL here doesn't actually matter.
     this._urls.set(urlKey, { id, url: newUrl, sourceMapURL: "" });
 
-    // Walk over all the location subscribers, looking for any that
-    // are subscribed to a location coming from |urlKey|.  Then,
-    // re-notify any such subscriber by clearing the stored promise
-    // and forcing a re-evaluation.
-    for (const [, subscriptionEntry] of this._subscriptions) {
-      if (subscriptionEntry.url === urlKey) {
-        // Force an update.
-        subscriptionEntry.promise = null;
-        for (const callback of subscriptionEntry.callbacks) {
-          this._callOneCallback(subscriptionEntry, callback);
-        }
+    this._dispatchSubscribersForURL(urlKey);
+  }
+};
+
+/**
+ * A helper function that dispatches subscribers for a specific URL.
+ * @param {string} urlKey
+ *        The url to trigger subscribers for.
+ */
+SourceMapURLService.prototype._dispatchSubscribersForURL = function(urlKey) {
+  // Walk over all the location subscribers, looking for any that
+  // are subscribed to a location coming from |urlKey|.  Then,
+  // re-notify any such subscriber by clearing the stored promise
+  // and forcing a re-evaluation.
+  for (const [, subscriptionEntry] of this._subscriptions) {
+    if (subscriptionEntry.url === urlKey) {
+      // Force an update.
+      subscriptionEntry.promise = null;
+      for (const callback of subscriptionEntry.callbacks) {
+        this._callOneCallback(subscriptionEntry, callback);
       }
     }
   }
 };
 
 /**
  * Look up the original position for a given location.  This returns a
  * promise resolving to either the original location, or null if the
--- a/devtools/client/framework/test/browser.ini
+++ b/devtools/client/framework/test/browser.ini
@@ -6,16 +6,18 @@ support-files =
   browser_toolbox_options_disable_js_iframe.html
   browser_toolbox_options_disable_cache.sjs
   browser_toolbox_sidebar_existing_tabs.xul
   browser_toolbox_sidebar_events.xul
   browser_toolbox_sidebar_tool.xul
   browser_toolbox_sidebar_toolURL.xul
   browser_toolbox_window_title_changes_page.html
   browser_toolbox_window_title_frame_select_page.html
+  code_bundle_late_script.js
+  code_bundle_late_script.js.map
   code_binary_search.coffee
   code_binary_search.js
   code_binary_search.map
   code_binary_search_absolute.js
   code_binary_search_absolute.map
   code_bundle_cross_domain.js
   code_bundle_cross_domain.js.map
   code_bundle_no_race.js
@@ -66,16 +68,17 @@ skip-if = os == 'win' || debug # Bug 128
 [browser_new_activation_workflow.js]
 [browser_source_map-01.js]
 [browser_source_map-absolute.js]
 [browser_source_map-cross-domain.js]
 [browser_source_map-init.js]
 [browser_source_map-inline.js]
 [browser_source_map-no-race.js]
 [browser_source_map-reload.js]
+[browser_source_map-late-script.js]
 [browser_target_from_url.js]
 [browser_target_events.js]
 [browser_target_remote.js]
 [browser_target_support.js]
 [browser_toolbox_custom_host.js]
 [browser_toolbox_dynamic_registration.js]
 [browser_toolbox_getpanelwhenready.js]
 [browser_toolbox_highlight.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/framework/test/browser_source_map-late-script.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that you can subscribe to notifications on a source before it has loaded.
+
+"use strict";
+
+const PAGE_URL = `${URL_ROOT}doc_empty-tab-01.html`;
+const JS_URL = URL_ROOT + "code_bundle_late_script.js";
+
+const ORIGINAL_URL = "webpack:///code_late_script.js";
+
+const GENERATED_LINE = 107;
+const ORIGINAL_LINE = 11;
+
+add_task(async function() {
+  // Start with the empty page, then navigate, so that we can properly
+  // listen for new sources arriving.
+  const toolbox = await openNewTabAndToolbox(PAGE_URL, "webconsole");
+  const service = toolbox.sourceMapURLService;
+
+  const scriptMapped = new Promise(resolve => {
+    let count = 0;
+    service.subscribe(
+      JS_URL,
+      GENERATED_LINE,
+      undefined,
+      (...args) => {
+        if (count === 0) {
+          resolve(args);
+        }
+        count += 1;
+      }
+    );
+  });
+
+  // Inject JS script
+  const sourceSeen = waitForSourceLoad(toolbox, JS_URL);
+  await createScript(JS_URL);
+  await sourceSeen;
+
+  // Ensure that the URL service fired an event about the location loading.
+  const [isSourceMapped, url, line] = await scriptMapped;
+  is(isSourceMapped, true, "check is mapped");
+  is(url, ORIGINAL_URL, "check mapped URL");
+  is(line, ORIGINAL_LINE, "check mapped line number");
+
+  await toolbox.destroy();
+  gBrowser.removeCurrentTab();
+  finish();
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/framework/test/code_bundle_late_script.js
@@ -0,0 +1,116 @@
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./code_late_script.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./code_late_script.js":
+/*!*****************************!*\
+  !*** ./code_late_script.js ***!
+  \*****************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Original source code for the inline source map test.
+// The generated file was made with
+//    webpack --devtool source-map code_late_script.js code_bundle_late_script.js
+
+
+
+function f() {
+  console.log("The first version of the script");
+}
+
+f();
+
+
+/***/ })
+
+/******/ });
+//# sourceMappingURL=code_bundle_late_script.js.map
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/devtools/client/framework/test/code_bundle_late_script.js.map
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./code_late_script.js"],"names":[],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,kDAA0C,gCAAgC;AAC1E;AACA;;AAEA;AACA;AACA;AACA,gEAAwD,kBAAkB;AAC1E;AACA,yDAAiD,cAAc;AAC/D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAyC,iCAAiC;AAC1E,wHAAgH,mBAAmB,EAAE;AACrI;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;;AAGA;AACA;;;;;;;;;;;;;AClFA;AACA;;AAEA;AACA;AACA;;AAEa;;AAEb;AACA;AACA;;AAEA","file":"code_bundle_late_script.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./code_late_script.js\");\n","/* Any copyright is dedicated to the Public Domain.\n http://creativecommons.org/publicdomain/zero/1.0/ */\n\n// Original source code for the inline source map test.\n// The generated file was made with\n//    webpack --devtool source-map code_late_script.js code_bundle_late_script.js\n\n\"use strict\";\n\nfunction f() {\n  console.log(\"The first version of the script\");\n}\n\nf();\n"],"sourceRoot":""}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/devtools/client/framework/test/code_late_script.js
@@ -0,0 +1,14 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Original source code for the inline source map test.
+// The generated file was made with
+//    webpack --devtool source-map code_late_script.js --output code_bundle_late_script.js --mode development
+
+"use strict";
+
+function f() {
+  console.log("The first version of the script");
+}
+
+f();
--- a/devtools/client/inspector/rules/test/browser_rules_variables_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_variables_01.js
@@ -21,21 +21,30 @@ add_task(async function() {
   const setColor = unsetColor.previousElementSibling;
   is(unsetColor.textContent, " red", "red is unmatched in color");
   is(setColor.textContent, "--color", "--color is not set correctly");
   is(setColor.dataset.variable, "--color = chartreuse",
                                 "--color's dataset.variable is not set correctly");
   let previewTooltip = await assertShowPreviewTooltip(view, setColor);
   await assertTooltipHiddenOnMouseOut(previewTooltip, setColor);
 
+  ok(previewTooltip.panel.textContent.includes("--color = chartreuse"),
+    "CSS variable preview tooltip shows the expected CSS variable");
+
   const unsetVar = getRuleViewProperty(view, "div", "background-color").valueSpan
     .querySelector(".ruleview-unmatched-variable");
   const setVar = unsetVar.nextElementSibling;
   const setVarName = setVar.firstElementChild.firstElementChild;
   is(unsetVar.textContent, "--not-set",
      "--not-set is unmatched in background-color");
   is(setVar.textContent, " var(--bg)", "var(--bg) parsed incorrectly");
   is(setVarName.textContent, "--bg", "--bg is not set correctly");
   is(setVarName.dataset.variable, "--bg = seagreen",
                                   "--bg's dataset.variable is not set correctly");
   previewTooltip = await assertShowPreviewTooltip(view, setVarName);
+
+  ok(!previewTooltip.panel.textContent.includes("--color = chartreuse"),
+    "CSS variable preview tooltip no longer shows the previous CSS variable");
+  ok(previewTooltip.panel.textContent.includes("--bg = seagreen"),
+    "CSS variable preview tooltip shows the new CSS variable");
+
   await assertTooltipHiddenOnMouseOut(previewTooltip, setVarName);
 });
--- a/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
@@ -46,16 +46,17 @@ class SwatchColorPickerTooltip extends S
 
   /**
    * Fill the tooltip with a new instance of the spectrum color picker widget
    * initialized with the given color, and return the instance of spectrum
    */
 
   setColorPickerContent(color) {
     const { doc } = this.tooltip;
+    this.tooltip.panel.innerHTML = "";
 
     const container = doc.createElementNS(XHTML_NS, "div");
     container.id = "spectrum-tooltip";
 
     const node = doc.createElementNS(XHTML_NS, "div");
     node.id = "spectrum";
     container.appendChild(node);
 
--- a/devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip.js
@@ -36,16 +36,17 @@ class SwatchCubicBezierTooltip extends S
   /**
    * Fill the tooltip with a new instance of the cubic-bezier widget
    * initialized with the given value, and return a promise that resolves to
    * the instance of the widget
    */
 
   setCubicBezierContent(bezier) {
     const { doc } = this.tooltip;
+    this.tooltip.panel.innerHTML = "";
 
     const container = doc.createElementNS(XHTML_NS, "div");
     container.className = "cubic-bezier-container";
 
     this.tooltip.panel.appendChild(container);
     this.tooltip.setContentSize({ width: 510, height: 370 });
 
     const def = defer();
--- a/devtools/client/shared/widgets/tooltip/SwatchFilterTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchFilterTooltip.js
@@ -38,16 +38,17 @@ class SwatchFilterTooltip extends Swatch
   /**
    * Fill the tooltip with a new instance of the CSSFilterEditorWidget
    * widget initialized with the given filter value, and return a promise
    * that resolves to the instance of the widget when ready.
    */
 
   setFilterContent(filter) {
     const { doc } = this.tooltip;
+    this.tooltip.panel.innerHTML = "";
 
     const container = doc.createElementNS(XHTML_NS, "div");
     container.id = "filter-container";
 
     this.tooltip.panel.appendChild(container);
     this.tooltip.setContentSize({ width: 510, height: 200 });
 
     return new CSSFilterEditorWidget(container, filter, this._cssIsValid);
--- a/devtools/client/shared/widgets/tooltip/VariableTooltipHelper.js
+++ b/devtools/client/shared/widgets/tooltip/VariableTooltipHelper.js
@@ -18,12 +18,13 @@ const XHTML_NS = "http://www.w3.org/1999
  *         Text to display in tooltip.
  */
 function setVariableTooltip(tooltip, doc, text) {
   // Create tooltip content
   const div = doc.createElementNS(XHTML_NS, "div");
   div.classList.add("devtools-monospace", "devtools-tooltip-css-variable");
   div.textContent = text;
 
+  tooltip.panel.innerHTML = "";
   tooltip.panel.appendChild(div);
 }
 
 module.exports.setVariableTooltip = setVariableTooltip;
--- a/devtools/server/tests/mochitest/chrome.ini
+++ b/devtools/server/tests/mochitest/chrome.ini
@@ -21,19 +21,23 @@ support-files =
   inspector-search-data.html
   inspector-styles-data.css
   inspector-styles-data.html
   inspector-template.html
   inspector-traversal-data.html
   large-image.jpg
   memory-helpers.js
   nonchrome_unsafeDereference.html
+  suspendTimeouts_content.html
+  suspendTimeouts_content.js
+  suspendTimeouts_worker.js
   small-image.gif
   setup-in-child.js
   setup-in-parent.js
+  test_suspendTimeouts.js
   webconsole-helpers.js
   webextension-helpers.js
 [test_animation_actor-lifetime.html]
 [test_animation-type-longhand.html]
 [test_connection-manager.html]
 skip-if = (verify && debug && (os == 'win'))
 [test_connectToFrame.html]
 [test_css-logic.html]
@@ -108,8 +112,9 @@ skip-if = (verify && debug && (os == 'wi
 [test_styles-modify.html]
 [test_styles-svg.html]
 [test_unsafeDereference.html]
 [test_webconsole-node-grip.html]
 [test_webextension-addon-debugging-connect.html]
 disabled = true # Bug 1467313: broken, needs repair or removal
 [test_webextension-addon-debugging-reload.html]
 disabled = true # Bug 1467313: broken, needs repair or removal
+[test_suspendTimeouts.html]
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/mochitest/suspendTimeouts_content.html
@@ -0,0 +1,1 @@
+<script src='suspendTimeouts_content.js'></script>
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/mochitest/suspendTimeouts_content.js
@@ -0,0 +1,71 @@
+"use strict";
+
+// To make it easier to follow, this code is arranged so that the functions are
+// arranged in the order they are called.
+
+const worker = new Worker("suspendTimeouts_worker.js");
+worker.onerror = error => {
+  const message =
+      `error from worker: ${error.filename}:${error.lineno}: ${error.message}`;
+  throw new Error(message);
+};
+
+// Create a message channel. Send one end to the worker, and return the other to
+// the mochitest.
+/* exported create_channel */
+function create_channel() {
+  const { port1, port2 } = new MessageChannel();
+  info(`sending port to worker`);
+  worker.postMessage({ mochitestPort: port1 }, [ port1 ]);
+  return port2;
+}
+
+// Provoke the worker into sending us a message, and then refuse to receive said
+// message, causing it to be delayed for later delivery.
+//
+// The worker will also post a message to the MessagePort we sent it earlier.
+// That message should not be delayed, as it is handled by the mochitest window,
+// not the content window. Its receipt signals that the test can assume that the
+// runnable for step 2) is in the main thread's event queue, so the test can
+// prepare for step 3).
+/* exported start_worker */
+function start_worker() {
+  worker.onmessage = handle_echo;
+
+  // This should prevent worker.onmessage from being called, until
+  // resumeTimeouts is called.
+  //
+  // This function is provided by test_suspendTimeouts.js.
+  // eslint-disable-next-line no-undef
+  suspendTimeouts();
+
+  // The worker should echo this message back to us and to the mochitest.
+  worker.postMessage("HALLOOOOOO"); // suitable message for echoing
+  info(`posted message to worker`);
+}
+
+var resumeTimeouts_has_returned = false;
+
+// Resume timeouts. After this call, the worker's message should not be
+// delivered to our onmessage handler until control returns to the event loop.
+/* exported resume_timeouts */
+function resume_timeouts() {
+  // This function is provided by test_suspendTimeouts.js.
+  // eslint-disable-next-line no-undef
+  resumeTimeouts(); // onmessage handlers should not run from this call.
+
+  resumeTimeouts_has_returned = true;
+
+  // When this JavaScript invocation returns to the main thread's event loop,
+  // only then should onmessage handlers be invoked.
+}
+
+// The buggy code calls this handler from the resumeTimeouts call, before the
+// main thread returns to the event loop. The correct code calls this only once
+// the JavaScript invocation that called resumeTimeouts has run to completion.
+function handle_echo({data}) {
+  ok(resumeTimeouts_has_returned, "worker message delivered from main event loop");
+
+  // Finish the mochitest.
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/mochitest/suspendTimeouts_worker.js
@@ -0,0 +1,12 @@
+"use strict";
+
+// Once content sends us a port connected to the mochitest, we simply echo every
+// message we receive back to content and the mochitest.
+onmessage = ({ data: { mochitestPort }}) => {
+  onmessage = ({ data }) => {
+    // Send a message to both content and the mochitest, which the main thread's
+    // event loop will attempt to deliver as step 2).
+    postMessage(`worker echo to content: ${data}`);
+    mochitestPort.postMessage(`worker echo to port: ${data}`);
+  };
+};
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/mochitest/test_suspendTimeouts.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1426467
+
+When we use windowUtils.resumeTimeouts to resume timeouts in a window, that call
+should not immediately dispatch `onmessage` handlers for messages from workers.
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Mozilla Bug 1426467</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<pre id="test">
+<script src='test_suspendTimeouts.js'></script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/mochitest/test_suspendTimeouts.js
@@ -0,0 +1,136 @@
+"use strict";
+
+// The debugger uses nsIDOMWindowUtils::suspendTimeouts and ...::resumeTimeouts
+// to ensure that content event handlers do not run while a JavaScript
+// invocation is stepping or paused at a breakpoint. If a worker thread sends
+// messages to the content while the content is paused, those messages must not
+// run until the JavaScript invocation interrupted by the debugger has completed.
+//
+// Bug 1426467 is that calling nsIDOMWindowUtils::resumeTimeouts actually
+// delivers deferred messages itself, calling the content's 'onmessage' handler.
+// But the debugger calls suspend/resume around each individual interruption of
+// the debuggee -- each step, say -- meaning that hitting the "step into" button
+// causes you to step from the debuggee directly into an onmessage handler,
+// since the onmessage handler is the next function call the debugger sees.
+//
+// In other words, delivering deferred messages from resumeTimeouts, as it is
+// used by the debugger, breaks the run-to-completion rule. They must not be
+// delivered until after the JavaScript invocation at hand is complete. That's
+// what this test checks.
+//
+// For this test to detect the bug, the following steps must take place in
+// order:
+//
+// 1) The content page must call suspendTimeouts.
+// 2) A runnable conveying a message from the worker thread must attempt to
+//    deliver the message, see that the content page has suspended such things,
+//    and hold the message for later delivery.
+// 3) The content page must call resumeTimeouts.
+//
+// In a correct implementation, the message from the worker thread is delivered
+// only after the main thread returns to the event loop after calling
+// resumeTimeouts in step 3). In the buggy implementation, the onmessage handler
+// is called directly from the call to resumeTimeouts, so that the onmessage
+// handlers run in the midst of whatever JavaScript invocation resumed timeouts
+// (say, stepping in the debugger), in violation of the run-to-completion rule.
+//
+// In this specific bug, the handlers are called from resumeTimeouts, but
+// really, running them any time before that invocation returns to the main
+// event loop would be a bug.
+//
+// Posting the message and calling resumeTimeouts take place in different
+// threads, but if 2) and 3) don't occur in that order, the worker's message
+// will never be delayed and the test will pass spuriously. But the worker
+// can't communicate with the content page directly, to let it know that it
+// should proceed with step 3): the purpose of suspendTimeouts is to pause
+// all such communication.
+//
+// So instead, the content page creates a MessageChannel, and passes one
+// MessagePort to the worker and the other to this mochitest (which has its
+// own window, separate from the one calling suspendTimeouts). The worker
+// notifies the mochitest when it has posted the message, and then the
+// mochitest calls into the content to carry out step 3).
+
+// To help you follow all the callbacks and event handlers, this code pulls out
+// event handler functions so that control flows from top to bottom.
+
+window.onload = function() {
+  // This mochitest is not complete until we call SimpleTest.finish. Don't just
+  // exit as soon as we return to the main event loop.
+  SimpleTest.waitForExplicitFinish();
+
+  const iframe = document.createElement("iframe");
+  iframe.src = "http://mochi.test:8888/chrome/devtools/server/tests/mochitest/suspendTimeouts_content.html";
+  iframe.onload = iframe_onload_handler;
+  document.body.appendChild(iframe);
+
+  function iframe_onload_handler() {
+    const content = iframe.contentWindow.wrappedJSObject;
+
+    const windowUtils = iframe.contentWindow.windowUtils;
+
+    // Hand over the suspend and resume functions to the content page, along
+    // with some testing utilities.
+    content.suspendTimeouts = function() {
+      SimpleTest.info("test_suspendTimeouts", "calling suspendTimeouts");
+      windowUtils.suspendTimeouts();
+    };
+    content.resumeTimeouts = function() {
+      windowUtils.resumeTimeouts();
+      SimpleTest.info("test_suspendTimeouts", "resumeTimeouts called");
+    };
+    content.info = function(message) {
+      SimpleTest.info("suspendTimeouts_content.js", message);
+    };
+    content.ok = SimpleTest.ok;
+    content.finish = finish;
+
+    SimpleTest.info("Disappointed with National Tautology Day? Well, it is what it is.");
+
+    // Once the worker has sent a message to its parent (which should get delayed),
+    // it sends us a message directly on this channel.
+    const workerPort = content.create_channel();
+    workerPort.onmessage = handle_worker_echo;
+
+    // Have content send the worker a message that it should echo back to both
+    // content and us. The echo to content should get delayed; the echo to us
+    // should cause our handle_worker_echo to be called.
+    content.start_worker();
+
+    function handle_worker_echo({ data }) {
+      info(`mochitest received message from worker: ${data}`);
+
+      // As it turns out, it's not correct to assume that, if the worker posts a
+      // message to its parent via the global `postMessage` function, and then
+      // posts a message to the mochitest via the MessagePort, those two
+      // messages will be delivered in the order they were sent.
+      //
+      // - Messages sent via the worker's global's postMessage go through two
+      //   ThrottledEventQueues (one in the worker, and one on the parent), and
+      //   eventually find their way into the thread's primary event queue,
+      //   which is a PrioritizedEventQueue.
+      //
+      // - Messages sent via a MessageChannel whose ports are owned by different
+      //   threads are passed as IPDL messages.
+      //
+      // There's basically no reliable way to ensure that delivery to content
+      // has been attempted and the runnable deferred; there are too many
+      // variables affecting the order in which things are processed. Delaying
+      // for a second is the best I could think of.
+      //
+      // Fortunately, this tactic failing can only cause spurious test passes
+      // (the runnable never gets deferred, so things work by accident), not
+      // spurious failures. Without some kind of trustworthy notification that
+      // the runnable has been deferred, perhaps via some special white-box
+      // testing API, we can't do better.
+      setTimeout(() => {
+        content.resume_timeouts();
+      }, 1000);
+    }
+
+    function finish(message) {
+      SimpleTest.info("suspendTimeouts_content.js", "called finish");
+      SimpleTest.finish();
+    }
+  }
+};
--- a/dom/abort/tests/.eslintrc.js
+++ b/dom/abort/tests/.eslintrc.js
@@ -1,14 +1,12 @@
 "use strict";
 
 module.exports = {
   "extends": [
-    "plugin:mozilla/browser-test",
-    "plugin:mozilla/chrome-test",
     "plugin:mozilla/mochitest-test",
   ],
   "plugins": [
     "mozilla"
   ],
   "rules": {
     "brace-style": "off",
     "no-shadow": "off",
new file mode 100644
--- /dev/null
+++ b/dom/abort/tests/unit/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/xpcshell-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/chrome/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/chrome-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/mozilla/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/mochitest-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/style/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/mochitest-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/asmjscache/test/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/mochitest-test",
+  ],
+};
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1505,17 +1505,18 @@ nsIDocument::nsIDocument()
     mBoxObjectTable(nullptr),
     mCurrentOrientationAngle(0),
     mCurrentOrientationType(OrientationType::Portrait_primary),
     mServoRestyleRootDirtyBits(0),
     mThrowOnDynamicMarkupInsertionCounter(0),
     mIgnoreOpensDuringUnloadCounter(0),
     mNumTrackersFound(0),
     mNumTrackersBlocked(0),
-    mDocLWTheme(Doc_Theme_Uninitialized)
+    mDocLWTheme(Doc_Theme_Uninitialized),
+    mSavedResolution(1.0f)
 {
   SetIsInDocument();
   SetIsConnected(true);
 
   if (StaticPrefs::layout_css_use_counters_enabled()) {
     mStyleUseCounters.reset(Servo_UseCounters_Create());
   }
 }
@@ -2227,30 +2228,45 @@ nsIDocument::Reset(nsIChannel* aChannel,
       mChromeXHRDocBaseURI = nullptr;
     }
   }
 
   mChannel = aChannel;
 }
 
 /**
- * DocumentL10n is currently allowed for system
- * principal.
- *
- * In the future we'll want to expose it to non-web-exposed
- * about:* pages.
+ * Determine whether the principal is allowed access to the localization system.
+ * We don't want the web to ever see this but all our UI including in content
+ * pages should pass this test.
  */
 bool
 PrincipalAllowsL10n(nsIPrincipal* principal)
 {
+  // The system principal is always allowed.
   if (nsContentUtils::IsSystemPrincipal(principal)) {
     return true;
   }
 
-  return false;
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = principal->GetURI(getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  bool hasFlags;
+
+  // Allow access to uris that cannot be loaded by web content.
+  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD, &hasFlags);
+  NS_ENSURE_SUCCESS(rv, false);
+  if (hasFlags) {
+    return true;
+  }
+
+  // UI resources also get access.
+  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &hasFlags);
+  NS_ENSURE_SUCCESS(rv, false);
+  return hasFlags;
 }
 
 void
 nsIDocument::ResetToURI(nsIURI* aURI,
                         nsILoadGroup* aLoadGroup,
                         nsIPrincipal* aPrincipal)
 {
   MOZ_ASSERT(aURI, "Null URI passed to ResetToURI");
@@ -3395,17 +3411,18 @@ DocumentL10n*
 nsIDocument::GetL10n()
 {
   return mDocumentL10n;
 }
 
 bool
 nsDocument::DocumentSupportsL10n(JSContext* aCx, JSObject* aObject)
 {
-  return PrincipalAllowsL10n(nsContentUtils::SubjectPrincipal(aCx));
+  nsCOMPtr<nsIPrincipal> callerPrincipal = nsContentUtils::SubjectPrincipal(aCx);
+  return PrincipalAllowsL10n(callerPrincipal);
 }
 
 void
 nsIDocument::LocalizationLinkAdded(Element* aLinkElement)
 {
   if (!PrincipalAllowsL10n(NodePrincipal())) {
     return;
   }
@@ -11165,16 +11182,26 @@ nsIDocument::CleanupFullscreenState()
   // after bug 1195213.
   for (nsWeakPtr& weakPtr : Reversed(mFullscreenStack)) {
     if (nsCOMPtr<Element> element = do_QueryReferent(weakPtr)) {
       ClearFullscreenStateOnElement(element);
     }
   }
   mFullscreenStack.Clear();
   mFullscreenRoot = nullptr;
+
+  // Restore the zoom level that was in place prior to entering fullscreen.
+  if (nsIPresShell* shell = GetShell()) {
+    if (nsPresContext* context = shell->GetPresContext()) {
+      if (context->IsRootContentDocument()) {
+        shell->SetResolutionAndScaleTo(mSavedResolution);
+      }
+    }
+  }
+
   UpdateViewportScrollbarOverrideForFullscreen(this);
 }
 
 bool
 nsIDocument::FullscreenStackPush(Element* aElement)
 {
   NS_ASSERTION(aElement, "Must pass non-null to FullscreenStackPush()");
   Element* top = FullscreenStackTop();
@@ -11568,16 +11595,33 @@ nsIDocument::ApplyFullscreen(UniquePtr<F
   // Propagate up the document hierarchy, setting the fullscreen element as
   // the element's container in ancestor documents. This also sets the
   // appropriate css styles as well. Note we don't propagate down the
   // document hierarchy, the fullscreen element (or its container) is not
   // visible there. Stop when we reach the root document.
   nsIDocument* child = this;
   while (true) {
     child->SetFullscreenRoot(fullScreenRootDoc);
+
+    // When entering fullscreen, reset the RCD's zoom level to 1,
+    // otherwise the fullscreen content could be sized larger than the
+    // screen (since fullscreen is implemented using position:fixed and
+    // fixed elements are sized to the layout viewport).
+    // This also ensures that things like video controls aren't zoomed in
+    // when in fullscreen mode.
+    if (nsIPresShell* shell = child->GetShell()) {
+      if (nsPresContext* context = shell->GetPresContext()) {
+        if (context->IsRootContentDocument()) {
+          // Save the previous resolution so it can be restored.
+          child->mSavedResolution = shell->GetResolution();
+          shell->SetResolutionAndScaleTo(1.0f);
+        }
+      }
+    }
+
     NS_ASSERTION(child->GetFullscreenRoot() == fullScreenRootDoc,
         "Fullscreen root should be set!");
     if (child == fullScreenRootDoc) {
       break;
     }
     nsIDocument* parent = child->GetParentDocument();
     Element* element = parent->FindContentForSubDocument(child);
     if (static_cast<nsDocument*>(parent)->FullscreenStackPush(element)) {
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -4766,16 +4766,19 @@ protected:
   uint32_t mNumTrackersBlocked;
 
   mozilla::EnumSet<mozilla::Telemetry::LABELS_DOCUMENT_ANALYTICS_TRACKER_FASTBLOCKED>
     mTrackerBlockedReasons;
 
   // document lightweight theme for use with :-moz-lwtheme, :-moz-lwtheme-brighttext
   // and :-moz-lwtheme-darktext
   DocumentTheme                         mDocLWTheme;
+
+  // Pres shell resolution saved before entering fullscreen mode.
+  float mSavedResolution;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
 
 /**
  * mozAutoSubtreeModified batches DOM mutations so that a DOMSubtreeModified
  * event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
  * object is deleted.
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -102,16 +102,17 @@
 #include <algorithm>
 #include "nsGlobalWindow.h"
 #include "nsDOMMutationObserver.h"
 #include "GeometryUtils.h"
 #include "nsIAnimationObserver.h"
 #include "nsChildContentList.h"
 #include "mozilla/dom/NodeBinding.h"
 #include "mozilla/dom/BindingDeclarations.h"
+#include "xpcprivate.h"
 
 #include "XPathGenerator.h"
 
 #ifdef ACCESSIBILITY
 #include "mozilla/dom/AccessibleNode.h"
 #endif
 
 using namespace mozilla;
@@ -3139,17 +3140,28 @@ public:
         }
 
         if (!JS_DefineElement(aCx, untranslatedElements, i, wrappedElem, JSPROP_ENUMERATE)) {
           mReturnValuePromise->MaybeRejectWithUndefined();
           return;
         }
       }
     }
-    mReturnValuePromise->MaybeResolve(untranslatedElements);
+
+    JS::RootedObject sourceScope(aCx, JS::CurrentGlobalOrNull(aCx));
+
+    AutoEntryScript aes(mReturnValuePromise->GetParentObject(), "Promise resolution");
+    JSContext* cx = aes.cx();
+    JS::Rooted<JS::Value> result(cx, JS::ObjectValue(*untranslatedElements));
+
+    xpc::StackScopedCloneOptions options;
+    options.wrapReflectors = true;
+    StackScopedClone(cx, options, sourceScope, &result);
+
+    mReturnValuePromise->MaybeResolve(result);
   }
 
   virtual void
   RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
   {
     mReturnValuePromise->MaybeRejectWithUndefined();
   }
 
new file mode 100644
--- /dev/null
+++ b/dom/base/test/.eslintrc.js
@@ -0,0 +1,9 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test",
+    "plugin:mozilla/chrome-test",
+    "plugin:mozilla/mochitest-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/battery/test/.eslintrc.js
@@ -0,0 +1,8 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/chrome-test",
+    "plugin:mozilla/mochitest-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/.eslintrc.js
@@ -0,0 +1,8 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/chrome-test",
+    "plugin:mozilla/mochitest-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/broadcastchannel/tests/.eslintrc.js
@@ -0,0 +1,8 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test",
+    "plugin:mozilla/mochitest-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/.eslintrc.js
@@ -0,0 +1,8 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/chrome-test",
+    "plugin:mozilla/mochitest-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/cache/test/mochitest/.eslintrc.js
@@ -0,0 +1,9 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test",
+    "plugin:mozilla/chrome-test",
+    "plugin:mozilla/mochitest-test",
+  ]
+};
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -1862,31 +1862,17 @@ ValidateCopyDestUsage(WebGLContext* webg
         }
 
         return dstUsage;
     }
     // Alright, it's sized.
 
     const auto dstFormat = dstUsage->format;
 
-    const auto fnNarrowType = [&](webgl::ComponentType type) {
-        switch (type) {
-        case webgl::ComponentType::NormInt:
-        case webgl::ComponentType::NormUInt:
-            // These both count as "fixed-point".
-            return webgl::ComponentType::NormInt;
-
-        default:
-            return type;
-        }
-    };
-
-    const auto srcType = fnNarrowType(srcFormat->componentType);
-    const auto dstType = fnNarrowType(dstFormat->componentType);
-    if (dstType != srcType) {
+    if (dstFormat->componentType != srcFormat->componentType) {
         webgl->ErrorInvalidOperation("For sized internalFormats, source and dest"
                                      " component types must match. (source: %s, dest:"
                                      " %s)",
                                      srcFormat->name, dstFormat->name);
         return nullptr;
     }
 
     bool componentSizesMatch = true;
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/mochitest-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/chrome/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/chrome-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/dom/console/tests/.eslintrc.js
@@ -0,0 +1,8 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/chrome-test",
+    "plugin:mozilla/mochitest-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/dom/console/tests/xpcshell/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/xpcshell-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/dom/crypto/test/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/mochitest-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/dom/encoding/test/.eslintrc.js
@@ -0,0 +1,8 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/chrome-test",
+    "plugin:mozilla/mochitest-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/dom/encoding/test/unit/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/xpcshell-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/dom/events/test/.eslintrc.js
@@ -0,0 +1,9 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test",
+    "plugin:mozilla/chrome-test",
+    "plugin:mozilla/mochitest-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/dom/fetch/tests/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test",
+  ]
+};
--- a/dom/workers/MessageEventRunnable.cpp
+++ b/dom/workers/MessageEventRunnable.cpp
@@ -109,22 +109,27 @@ MessageEventRunnable::WorkerRun(JSContex
 {
   if (mBehavior == ParentThreadUnchangedBusyCount) {
     // Don't fire this event if the JS object has been disconnected from the
     // private object.
     if (!aWorkerPrivate->IsAcceptingEvents()) {
       return true;
     }
 
-    if (aWorkerPrivate->IsFrozen() ||
-        aWorkerPrivate->IsParentWindowPaused()) {
-      MOZ_ASSERT(!IsDebuggerRunnable());
-      aWorkerPrivate->QueueRunnable(this);
-      return true;
-    }
+    // Once a window has frozen its workers, their
+    // mMainThreadDebuggeeEventTargets should be paused, and their
+    // WorkerDebuggeeRunnables should not be being executed. The same goes for
+    // WorkerDebuggeeRunnables sent from child to parent workers, but since a
+    // frozen parent worker runs only control runnables anyway, that is taken
+    // care of naturally.
+    MOZ_ASSERT(!aWorkerPrivate->IsFrozen());
+
+    // Similarly for paused windows; all its workers should have been informed.
+    // (Subworkers are unaffected by paused windows.)
+    MOZ_ASSERT(!aWorkerPrivate->IsParentWindowPaused());
 
     aWorkerPrivate->AssertInnerWindowIsCorrect();
 
     return DispatchDOMEvent(aCx, aWorkerPrivate,
                             aWorkerPrivate->ParentEventTargetRef(),
                             !aWorkerPrivate->GetParent());
   }
 
--- a/dom/workers/WorkerError.cpp
+++ b/dom/workers/WorkerError.cpp
@@ -183,22 +183,27 @@ private:
 
     WorkerPrivate* parent = aWorkerPrivate->GetParent();
     if (parent) {
       innerWindowId = 0;
     }
     else {
       AssertIsOnMainThread();
 
-      if (aWorkerPrivate->IsFrozen() ||
-          aWorkerPrivate->IsParentWindowPaused()) {
-        MOZ_ASSERT(!IsDebuggerRunnable());
-        aWorkerPrivate->QueueRunnable(this);
-        return true;
-      }
+      // Once a window has frozen its workers, their
+      // mMainThreadDebuggeeEventTargets should be paused, and their
+      // WorkerDebuggeeRunnables should not be being executed. The same goes for
+      // WorkerDebuggeeRunnables sent from child to parent workers, but since a
+      // frozen parent worker runs only control runnables anyway, that is taken
+      // care of naturally.
+      MOZ_ASSERT(!aWorkerPrivate->IsFrozen());
+
+      // Similarly for paused windows; all its workers should have been informed.
+      // (Subworkers are unaffected by paused windows.)
+      MOZ_ASSERT(!aWorkerPrivate->IsParentWindowPaused());
 
       if (aWorkerPrivate->IsSharedWorker()) {
         aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, &mReport,
                                                       /* isErrorEvent */ true);
         return true;
       }
 
       // Service workers do not have a main thread parent global, so normal
@@ -268,22 +273,27 @@ private:
 
     // Dispatch may fail if the worker was canceled, no need to report that as
     // an error, so don't call base class PostDispatch.
   }
 
   bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
-    if (aWorkerPrivate->IsFrozen() ||
-        aWorkerPrivate->IsParentWindowPaused()) {
-      MOZ_ASSERT(!IsDebuggerRunnable());
-      aWorkerPrivate->QueueRunnable(this);
-      return true;
-    }
+    // Once a window has frozen its workers, their
+    // mMainThreadDebuggeeEventTargets should be paused, and their
+    // WorkerDebuggeeRunnables should not be being executed. The same goes for
+    // WorkerDebuggeeRunnables sent from child to parent workers, but since a
+    // frozen parent worker runs only control runnables anyway, that is taken
+    // care of naturally.
+    MOZ_ASSERT(!aWorkerPrivate->IsFrozen());
+
+    // Similarly for paused windows; all its workers should have been informed.
+    // (Subworkers are unaffected by paused windows.)
+    MOZ_ASSERT(!aWorkerPrivate->IsParentWindowPaused());
 
     if (aWorkerPrivate->IsSharedWorker()) {
       aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, nullptr,
                                                     /* isErrorEvent */ false);
       return true;
     }
 
     if (aWorkerPrivate->IsServiceWorker()) {
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1583,16 +1583,20 @@ WorkerPrivate::Dispatch(already_AddRefed
                  "down!");
       return NS_ERROR_UNEXPECTED;
     }
 
     nsresult rv;
     if (aSyncLoopTarget) {
       rv = aSyncLoopTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
     } else {
+      // WorkerDebuggeeRunnables don't need any special treatment here. True,
+      // they should not be delivered to a frozen worker. But frozen workers
+      // aren't drawing from the thread's main event queue anyway, only from
+      // mControlQueue.
       rv = mThread->DispatchAnyThread(WorkerThreadFriendKey(), runnable.forget());
     }
 
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     mCondVar.Notify();
@@ -1756,22 +1760,16 @@ WorkerPrivate::Notify(WorkerStatus aStat
     }
 #endif
 
     // Worker never got a chance to run, go ahead and delete it.
     ScheduleDeletion(WorkerPrivate::WorkerNeverRan);
     return true;
   }
 
-  NS_ASSERTION(aStatus != Canceling || mQueuedRunnables.IsEmpty(),
-               "Shouldn't have anything queued!");
-
-  // Anything queued will be discarded.
-  mQueuedRunnables.Clear();
-
   // No Canceling timeout is needed.
   if (mCancelingTimer) {
     mCancelingTimer->Cancel();
     mCancelingTimer = nullptr;
   }
 
   RefPtr<NotifyRunnable> runnable = new NotifyRunnable(this, aStatus);
   return runnable->Dispatch();
@@ -1808,16 +1806,31 @@ WorkerPrivate::Freeze(nsPIDOMWindowInner
 
     if (!allFrozen || mParentFrozen) {
       return true;
     }
   }
 
   mParentFrozen = true;
 
+  // WorkerDebuggeeRunnables sent from a worker to content must not be delivered
+  // while the worker is frozen.
+  //
+  // Since a top-level worker and all its children share the same
+  // mMainThreadDebuggeeEventTarget, it's sufficient to do this only in the
+  // top-level worker.
+  if (aWindow) {
+    // This is called from WorkerPrivate construction, and We may not have
+    // allocated mMainThreadDebuggeeEventTarget yet.
+    if (mMainThreadDebuggeeEventTarget) {
+      // Pausing a ThrottledEventQueue is infallible.
+      MOZ_ALWAYS_SUCCEEDS(mMainThreadDebuggeeEventTarget->SetIsPaused(true));
+    }
+  }
+
   {
     MutexAutoLock lock(mMutex);
 
     if (mParentStatus >= Canceling) {
       return true;
     }
   }
 
@@ -1865,53 +1878,62 @@ WorkerPrivate::Thaw(nsPIDOMWindowInner* 
       return true;
     }
   }
 
   MOZ_ASSERT(mParentFrozen);
 
   mParentFrozen = false;
 
+  // Delivery of WorkerDebuggeeRunnables to the window may resume.
+  //
+  // Since a top-level worker and all its children share the same
+  // mMainThreadDebuggeeEventTarget, it's sufficient to do this only in the
+  // top-level worker.
+  if (aWindow) {
+    // Since the worker is no longer frozen, only a paused parent window should
+    // require the queue to remain paused.
+    //
+    // This can only fail if the ThrottledEventQueue cannot dispatch its executor
+    // to the main thread, in which case the main thread was never going to draw
+    // runnables from it anyway, so the failure doesn't matter.
+    Unused << mMainThreadDebuggeeEventTarget->SetIsPaused(IsParentWindowPaused());
+  }
+
   {
     MutexAutoLock lock(mMutex);
 
     if (mParentStatus >= Canceling) {
       return true;
     }
   }
 
   EnableDebugger();
 
-  // Execute queued runnables before waking up the worker, otherwise the worker
-  // could post new messages before we run those that have been queued.
-  if (!IsParentWindowPaused() && !mQueuedRunnables.IsEmpty()) {
-    MOZ_ASSERT(IsDedicatedWorker());
-
-    nsTArray<nsCOMPtr<nsIRunnable>> runnables;
-    mQueuedRunnables.SwapElements(runnables);
-
-    for (uint32_t index = 0; index < runnables.Length(); index++) {
-      runnables[index]->Run();
-    }
-  }
-
   RefPtr<ThawRunnable> runnable = new ThawRunnable(this);
   if (!runnable->Dispatch()) {
     return false;
   }
 
   return true;
 }
 
 void
 WorkerPrivate::ParentWindowPaused()
 {
   AssertIsOnMainThread();
   MOZ_ASSERT_IF(IsDedicatedWorker(), mParentWindowPausedDepth == 0);
   mParentWindowPausedDepth += 1;
+
+  // This is called from WorkerPrivate construction, and we may not have
+  // allocated mMainThreadDebuggeeEventTarget yet.
+  if (mMainThreadDebuggeeEventTarget) {
+    // Pausing a ThrottledEventQueue is infallible.
+    MOZ_ALWAYS_SUCCEEDS(mMainThreadDebuggeeEventTarget->SetIsPaused(true));
+  }
 }
 
 void
 WorkerPrivate::ParentWindowResumed()
 {
   AssertIsOnMainThread();
 
   MOZ_ASSERT(mParentWindowPausedDepth > 0);
@@ -1924,28 +1946,23 @@ WorkerPrivate::ParentWindowResumed()
   {
     MutexAutoLock lock(mMutex);
 
     if (mParentStatus >= Canceling) {
       return;
     }
   }
 
-  // Execute queued runnables before waking up, otherwise the worker could post
-  // new messages before we run those that have been queued.
-  if (!IsFrozen() && !mQueuedRunnables.IsEmpty()) {
-    MOZ_ASSERT(IsDedicatedWorker());
-
-    nsTArray<nsCOMPtr<nsIRunnable>> runnables;
-    mQueuedRunnables.SwapElements(runnables);
-
-    for (uint32_t index = 0; index < runnables.Length(); index++) {
-      runnables[index]->Run();
-    }
-  }
+  // Since the window is no longer paused, the queue should only remain paused
+  // if the worker is frozen.
+  //
+  // This can only fail if the ThrottledEventQueue cannot dispatch its executor
+  // to the main thread, in which case the main thread was never going to draw
+  // runnables from it anyway, so the failure doesn't matter.
+  Unused << mMainThreadDebuggeeEventTarget->SetIsPaused(IsFrozen());
 }
 
 void
 WorkerPrivate::PropagateFirstPartyStorageAccessGranted()
 {
   AssertIsOnParentThread();
 
   {
@@ -2709,30 +2726,35 @@ WorkerPrivate::WorkerPrivate(WorkerPriva
   nsCOMPtr<nsISerialEventTarget> target;
 
   // A child worker just inherits the parent workers ThrottledEventQueue
   // and main thread target for now.  This is mainly due to the restriction
   // that ThrottledEventQueue can only be created on the main thread at the
   // moment.
   if (aParent) {
     mMainThreadEventTarget = aParent->mMainThreadEventTarget;
+    mMainThreadDebuggeeEventTarget = aParent->mMainThreadDebuggeeEventTarget;
     return;
   }
 
   MOZ_ASSERT(NS_IsMainThread());
   target = GetWindow() ? GetWindow()->EventTargetFor(TaskCategory::Worker) : nullptr;
 
   if (!target) {
     target = GetMainThreadSerialEventTarget();
     MOZ_DIAGNOSTIC_ASSERT(target);
   }
 
   // Throttle events to the main thread using a ThrottledEventQueue specific to
   // this tree of worker threads.
   mMainThreadEventTarget = ThrottledEventQueue::Create(target);
+  mMainThreadDebuggeeEventTarget = ThrottledEventQueue::Create(target);
+  if (IsParentWindowPaused() || IsFrozen()) {
+    MOZ_ALWAYS_SUCCEEDS(mMainThreadDebuggeeEventTarget->SetIsPaused(true));
+  }
 }
 
 WorkerPrivate::~WorkerPrivate()
 {
   DropJSObjects(this);
 
   mWorkerControlEventTarget->ForgetWorkerPrivate(this);
 
@@ -3296,19 +3318,21 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
 
     if (!debuggerRunnablesPending && !normalRunnablesPending) {
       // Both the debugger event queue and the normal event queue has been
       // exhausted, cancel the periodic GC timer and schedule the idle GC timer.
       SetGCTimerMode(IdleTimer);
     }
 
     // If the worker thread is spamming the main thread faster than it can
-    // process the work, then pause the worker thread until the MT catches
-    // up.
-    if (mMainThreadEventTarget->Length() > 5000) {
+    // process the work, then pause the worker thread until the main thread
+    // catches up.
+    size_t queuedEvents = mMainThreadEventTarget->Length() +
+                          mMainThreadDebuggeeEventTarget->Length();
+    if (queuedEvents > 5000) {
       mMainThreadEventTarget->AwaitIdle();
     }
   }
 
   MOZ_CRASH("Shouldn't get here!");
 }
 
 void
@@ -3353,16 +3377,23 @@ WorkerPrivate::DispatchToMainThread(nsIR
 
 nsresult
 WorkerPrivate::DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable,
                                     uint32_t aFlags)
 {
   return mMainThreadEventTarget->Dispatch(std::move(aRunnable), aFlags);
 }
 
+nsresult
+WorkerPrivate::DispatchDebuggeeToMainThread(already_AddRefed<WorkerDebuggeeRunnable> aRunnable,
+                                            uint32_t aFlags)
+{
+  return mMainThreadDebuggeeEventTarget->Dispatch(std::move(aRunnable), aFlags);
+}
+
 nsISerialEventTarget*
 WorkerPrivate::ControlEventTarget()
 {
   return mWorkerControlEventTarget;
 }
 
 nsISerialEventTarget*
 WorkerPrivate::HybridEventTarget()
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -48,16 +48,17 @@ class SharedWorker;
 class WorkerControlRunnable;
 class WorkerCSPEventListener;
 class WorkerDebugger;
 class WorkerDebuggerGlobalScope;
 class WorkerErrorReport;
 class WorkerEventTarget;
 class WorkerGlobalScope;
 class WorkerRunnable;
+class WorkerDebuggeeRunnable;
 class WorkerThread;
 
 // SharedMutex is a small wrapper around an (internal) reference-counted Mutex
 // object. It exists to avoid changing a lot of code to use Mutex* instead of
 // Mutex&.
 class SharedMutex
 {
   typedef mozilla::Mutex Mutex;
@@ -530,16 +531,20 @@ public:
   nsresult
   DispatchToMainThread(nsIRunnable* aRunnable,
                        uint32_t aFlags = NS_DISPATCH_NORMAL);
 
   nsresult
   DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable,
                        uint32_t aFlags = NS_DISPATCH_NORMAL);
 
+  nsresult
+  DispatchDebuggeeToMainThread(already_AddRefed<WorkerDebuggeeRunnable> aRunnable,
+                               uint32_t aFlags = NS_DISPATCH_NORMAL);
+
   // Get an event target that will dispatch runnables as control runnables on
   // the worker thread.  Implement nsICancelableRunnable if you wish to take
   // action on cancelation.
   nsISerialEventTarget*
   ControlEventTarget();
 
   // Get an event target that will attempt to dispatch a normal WorkerRunnable,
   // but if that fails will then fall back to a control runnable.
@@ -1063,23 +1068,16 @@ public:
   // top level script.
   void
   SetLoadingWorkerScript(bool aLoadingWorkerScript)
   {
     // any thread
     mLoadingWorkerScript = aLoadingWorkerScript;
   }
 
-  void
-  QueueRunnable(nsIRunnable* aRunnable)
-  {
-    AssertIsOnParentThread();
-    mQueuedRunnables.AppendElement(aRunnable);
-  }
-
   bool
   RegisterSharedWorker(SharedWorker* aSharedWorker, MessagePort* aPort);
 
   void
   BroadcastErrorToSharedWorkers(JSContext* aCx,
                                 const WorkerErrorReport* aReport,
                                 bool aIsErrorEvent);
 
@@ -1370,16 +1368,20 @@ private:
   RefPtr<WorkerDebuggerGlobalScope> mDebuggerScope;
   nsTArray<WorkerPrivate*> mChildWorkers;
   nsTObserverArray<WorkerHolder*> mHolders;
   nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
   RefPtr<ThrottledEventQueue> mMainThreadEventTarget;
   RefPtr<WorkerEventTarget> mWorkerControlEventTarget;
   RefPtr<WorkerEventTarget> mWorkerHybridEventTarget;
 
+  // A pauseable queue for WorkerDebuggeeRunnables directed at the main thread.
+  // See WorkerDebuggeeRunnable for details.
+  RefPtr<ThrottledEventQueue> mMainThreadDebuggeeEventTarget;
+
   struct SyncLoopInfo
   {
     explicit SyncLoopInfo(EventTarget* aEventTarget);
 
     RefPtr<EventTarget> mEventTarget;
     bool mCompleted;
     bool mResult;
 #ifdef DEBUG
@@ -1403,19 +1405,16 @@ private:
 
   // fired on the main thread if the worker script fails to load
   nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
 
   RefPtr<PerformanceStorage> mPerformanceStorage;
 
   RefPtr<WorkerCSPEventListener> mCSPEventListener;
 
-  // Only used for top level workers.
-  nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables;
-
   // Protected by mMutex.
   nsTArray<RefPtr<WorkerRunnable>> mPreStartRunnables;
 
   // Only touched on the parent thread (currently this is always the main
   // thread as SharedWorkers are always top-level).
   nsTArray<RefPtr<SharedWorker>> mSharedWorkers;
 
   JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -114,16 +114,23 @@ WorkerRunnable::DispatchInternal()
   }
 
   MOZ_ASSERT(mBehavior == ParentThreadUnchangedBusyCount);
 
   if (WorkerPrivate* parent = mWorkerPrivate->GetParent()) {
     return NS_SUCCEEDED(parent->Dispatch(runnable.forget()));
   }
 
+  if (IsDebuggeeRunnable()) {
+    RefPtr<WorkerDebuggeeRunnable> debuggeeRunnable =
+      runnable.forget().downcast<WorkerDebuggeeRunnable>();
+    return NS_SUCCEEDED(mWorkerPrivate->DispatchDebuggeeToMainThread(debuggeeRunnable.forget(),
+                                                                     NS_DISPATCH_NORMAL));
+  }
+
   return NS_SUCCEEDED(mWorkerPrivate->DispatchToMainThread(runnable.forget()));
 }
 
 void
 WorkerRunnable::PostDispatch(WorkerPrivate* aWorkerPrivate,
                              bool aDispatchResult)
 {
   MOZ_ASSERT(aWorkerPrivate);
@@ -743,10 +750,29 @@ WorkerProxyToMainThreadRunnable::PostDis
 }
 
 void
 WorkerProxyToMainThreadRunnable::ReleaseWorker()
 {
   mWorkerRef = nullptr;
 }
 
+bool
+WorkerDebuggeeRunnable::PreDispatch(WorkerPrivate* aWorkerPrivate)
+{
+  if (mBehavior == ParentThreadUnchangedBusyCount) {
+    RefPtr<StrongWorkerRef> strongRef =
+      StrongWorkerRef::Create(aWorkerPrivate, "WorkerDebuggeeRunnable::mSender");
+    if (!strongRef) {
+      return false;
+    }
+
+    mSender = new ThreadSafeWorkerRef(strongRef);
+    if (!mSender) {
+      return false;
+    }
+  }
+
+  return WorkerRunnable::PreDispatch(aWorkerPrivate);
+}
+
 } // dom namespace
 } // mozilla namespace
--- a/dom/workers/WorkerRunnable.h
+++ b/dom/workers/WorkerRunnable.h
@@ -536,22 +536,37 @@ private:
 class WorkerDebuggeeRunnable : public WorkerRunnable
 {
  protected:
   WorkerDebuggeeRunnable(WorkerPrivate* aWorkerPrivate,
                          TargetAndBusyBehavior aBehavior = ParentThreadUnchangedBusyCount)
     : WorkerRunnable(aWorkerPrivate, aBehavior)
   { }
 
+  bool
+  PreDispatch(WorkerPrivate* aWorkerPrivate) override;
+
  private:
   // This override is deliberately private: it doesn't make sense to call it if
   // we know statically that we are a WorkerDebuggeeRunnable.
   bool
   IsDebuggeeRunnable() const override
   {
     return true;
   }
+
+  // Runnables sent upwards, to the content window or parent worker, must keep
+  // their sender alive until they are delivered: they check back with the
+  // sender in case it has been terminated after having dispatched the runnable
+  // (in which case it should not be acted upon); and runnables sent to content
+  // wait until delivery to determine the target window, since
+  // WorkerPrivate::GetWindow may only be used on the main thread.
+  //
+  // Runnables sent downwards, from content to a worker or from a worker to a
+  // child, keep the sender alive because they are WorkerThreadModifyBusyCount
+  // runnables, and so leave this null.
+  RefPtr<ThreadSafeWorkerRef> mSender;
 };
 
 } // dom namespace
 } // mozilla namespace
 
 #endif // mozilla_dom_workers_workerrunnable_h__
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -4103,23 +4103,27 @@ AsyncPanZoomController::ReportCheckerboa
   UpdateCheckerboardEvent(lock, magnitude);
 }
 
 void
 AsyncPanZoomController::UpdateCheckerboardEvent(const MutexAutoLock& aProofOfLock,
                                                 uint32_t aMagnitude)
 {
   if (mCheckerboardEvent && mCheckerboardEvent->RecordFrameInfo(aMagnitude)) {
-    // This checkerboard event is done. Report some metrics to telemetry.
-    mozilla::Telemetry::Accumulate(mozilla::Telemetry::CHECKERBOARD_SEVERITY,
-      mCheckerboardEvent->GetSeverity());
-    mozilla::Telemetry::Accumulate(mozilla::Telemetry::CHECKERBOARD_PEAK,
-      mCheckerboardEvent->GetPeak());
-    mozilla::Telemetry::Accumulate(mozilla::Telemetry::CHECKERBOARD_DURATION,
-      (uint32_t)mCheckerboardEvent->GetDuration().ToMilliseconds());
+    // This checkerboard event is done. Report some metrics to telemetry, but
+    // skip reporting if the sanity checker window is running, because we get
+    // checkerboarding reported on that window that we don't really care about.
+    if (!gfxPrefs::SanityTestRunning()) {
+      mozilla::Telemetry::Accumulate(mozilla::Telemetry::CHECKERBOARD_SEVERITY,
+        mCheckerboardEvent->GetSeverity());
+      mozilla::Telemetry::Accumulate(mozilla::Telemetry::CHECKERBOARD_PEAK,
+        mCheckerboardEvent->GetPeak());
+      mozilla::Telemetry::Accumulate(mozilla::Telemetry::CHECKERBOARD_DURATION,
+        (uint32_t)mCheckerboardEvent->GetDuration().ToMilliseconds());
+    }
 
     mPotentialCheckerboardTracker.CheckerboardDone();
 
     if (gfxPrefs::APZRecordCheckerboarding()) {
       // if the pref is enabled, also send it to the storage class. it may be
       // chosen for public display on about:checkerboard, the hall of fame for
       // checkerboard events.
       uint32_t severity = mCheckerboardEvent->GetSeverity();
@@ -4422,16 +4426,26 @@ void AsyncPanZoomController::NotifyLayer
     // above.
     Metrics().CopySmoothScrollInfoFrom(aLayerMetrics);
     needContentRepaint = true;
     mExpectedGeckoMetrics = aLayerMetrics;
 
     SmoothScrollTo(Metrics().GetSmoothScrollOffset());
   }
 
+  if (viewportUpdated) {
+    // While we want to accept the main thread's layout viewport _size_,
+    // its position may be out of date in light of async scrolling, to
+    // adjust it if necessary to make sure it continues to enclose the
+    // visual viewport.
+    // Note: it's important to do this _after_ we've accepted any
+    // updated composition bounds.
+    Metrics().RecalculateViewportOffset();
+  }
+
   if (needContentRepaint) {
     // This repaint request is not driven by a user action on the APZ side
     RequestContentRepaint(false);
   }
   UpdateSharedCompositorFrameMetrics();
 }
 
 FrameMetrics& AsyncPanZoomController::Metrics() {
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -736,16 +736,18 @@ private:
                                                                MouseWheelRootScrollVerticalFactor, int32_t, 0);
   DECL_GFX_PREF(Live, "mousewheel.transaction.ignoremovedelay",MouseWheelIgnoreMoveDelayMs, int32_t, (int32_t)100);
   DECL_GFX_PREF(Live, "mousewheel.transaction.timeout",        MouseWheelTransactionTimeoutMs, int32_t, (int32_t)1500);
 
   DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false);
 
   DECL_GFX_PREF(Live, "print.font-variations-as-paths",        PrintFontVariationsAsPaths, bool, true);
 
+  DECL_GFX_PREF(Live, "sanity-test.running",                   SanityTestRunning, bool, false);
+
   DECL_GFX_PREF(Once, "slider.snapMultiplier",                 SliderSnapMultiplier, int32_t, 0);
 
   DECL_GFX_PREF(Live, "test.events.async.enabled",             TestEventsAsyncEnabled, bool, false);
   DECL_GFX_PREF(Live, "test.mousescroll",                      MouseScrollTestingEnabled, bool, false);
 
   DECL_GFX_PREF(Live, "toolkit.scrollbox.horizontalScrollDistance", ToolkitHorizontalScrollDistance, int32_t, 5);
   DECL_GFX_PREF(Live, "toolkit.scrollbox.verticalScrollDistance",   ToolkitVerticalScrollDistance, int32_t, 3);
 
--- a/gfx/webrender/src/batch.rs
+++ b/gfx/webrender/src/batch.rs
@@ -13,17 +13,17 @@ use gpu_types::{BrushFlags, BrushInstanc
 use gpu_types::{ClipMaskInstance, SplitCompositeInstance};
 use gpu_types::{PrimitiveInstanceData, RasterizationSpace, GlyphInstance};
 use gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, TransformPalette};
 use internal_types::{FastHashMap, SavedTargetIndex, TextureSource};
 use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureSurface};
 use prim_store::{BrushKind, BrushPrimitive, BrushSegmentTaskId, DeferredResolve};
 use prim_store::{EdgeAaSegmentMask, ImageSource};
 use prim_store::{VisibleGradientTile, PrimitiveInstance};
-use prim_store::{BrushSegment, BorderSource, Primitive, PrimitiveDetails};
+use prim_store::{BrushSegment, BorderSource, PrimitiveDetails};
 use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskTree};
 use renderer::{BlendMode, ImageBufferKind, ShaderColorMode};
 use renderer::BLOCKS_PER_UV_RECT;
 use resource_cache::{CacheItem, GlyphFetchResult, ImageRequest, ResourceCache, ImageProperties};
 use scene::FilterOpHelpers;
 use smallvec::SmallVec;
 use std::{f32, i32, usize};
 use tiling::{RenderTargetContext};
@@ -559,17 +559,17 @@ impl AlphaBatchBuilder {
         } else {
             gpu_cache.get_address(&prim_instance.gpu_location)
         };
 
         let clip_task_address = prim_instance
             .clip_task_id
             .map_or(OPAQUE_TASK_ADDRESS, |id| render_tasks.get_task_address(id));
 
-        let specified_blend_mode = prim.get_blend_mode();
+        let specified_blend_mode = prim_instance.get_blend_mode(&prim.details);
 
         let non_segmented_blend_mode = if !prim_instance.opacity.is_opaque ||
             prim_instance.clip_task_id.is_some() ||
             transform_kind == TransformedRectKind::Complex
         {
             specified_blend_mode
         } else {
             BlendMode::None
@@ -1728,19 +1728,22 @@ impl BrushPrimitive {
                     ],
                     0,
                 ))
             }
         }
     }
 }
 
-impl Primitive {
-    fn get_blend_mode(&self) -> BlendMode {
-        match self.details {
+impl PrimitiveInstance {
+    fn get_blend_mode(
+        &self,
+        details: &PrimitiveDetails,
+    ) -> BlendMode {
+        match *details {
             // Can only resolve the TextRun's blend mode once glyphs are fetched.
             PrimitiveDetails::TextRun(..) => {
                 BlendMode::PremultipliedAlpha
             }
 
             PrimitiveDetails::Brush(ref brush) => {
                 match brush.kind {
                     BrushKind::Clear => {
@@ -1763,19 +1766,20 @@ impl Primitive {
                     }
                 }
             }
         }
     }
 
     pub fn is_cacheable(
         &self,
+        details: &PrimitiveDetails,
         resource_cache: &ResourceCache
     ) -> bool {
-        let image_key = match self.details {
+        let image_key = match *details {
             PrimitiveDetails::Brush(BrushPrimitive { kind: BrushKind::Image{ request, ..  }, .. }) => {
                 request.key
             }
             PrimitiveDetails::Brush(BrushPrimitive { kind: BrushKind::YuvImage{ yuv_key, .. }, .. }) => {
                 yuv_key[0]
             }
             PrimitiveDetails::Brush(_) |
             PrimitiveDetails::TextRun(..) => {
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -1893,19 +1893,20 @@ impl PrimitiveStore {
             }
             None => {
                 (false, None)
             }
         };
 
         let prim = &mut self.primitives[prim_instance.prim_index.0];
 
-        if !prim.is_cacheable(frame_state.resource_cache) {
-            pic_state.is_cacheable = false;
-        }
+        pic_state.is_cacheable &= prim_instance.is_cacheable(
+            &prim.details,
+            frame_state.resource_cache,
+        );
 
         if is_passthrough {
             prim_instance.clipped_world_rect = Some(pic_state.map_pic_to_world.bounds);
         } else {
             if prim.local_rect.size.width <= 0.0 ||
                prim.local_rect.size.height <= 0.0 {
                 if cfg!(debug_assertions) && is_chased {
                     println!("\tculled for zero local rectangle");
@@ -1995,18 +1996,20 @@ impl PrimitiveStore {
                 Some(rect) => rect,
                 None => {
                     return false;
                 }
             };
 
             prim_instance.clipped_world_rect = Some(clipped_world_rect);
 
-            prim.update_clip_task(
-                prim_instance,
+            prim_instance.update_clip_task(
+                prim.local_rect,
+                prim.local_clip_rect,
+                &mut prim.details,
                 prim_context,
                 clipped_world_rect,
                 pic_context.raster_spatial_node_index,
                 &clip_chain,
                 pic_state,
                 frame_context,
                 frame_state,
                 is_chased,
@@ -2015,18 +2018,19 @@ impl PrimitiveStore {
 
             if cfg!(debug_assertions) && is_chased {
                 println!("\tconsidered visible and ready with local rect {:?}", local_rect);
             }
 
             pic_state.rect = pic_state.rect.union(&pic_rect);
         }
 
-        prim.prepare_prim_for_render_inner(
-            prim_instance,
+        prim_instance.prepare_prim_for_render_inner(
+            prim.local_rect,
+            &mut prim.details,
             prim_context,
             pic_context,
             pic_state,
             &mut self.pictures,
             frame_context,
             frame_state,
             display_list,
             plane_split_anchor,
@@ -2421,37 +2425,39 @@ impl BrushPrimitive {
                         segments,
                     });
                 }
             }
         }
     }
 }
 
-impl Primitive {
+impl PrimitiveInstance {
     fn update_clip_task_for_brush(
         &mut self,
-        prim_instance: &PrimitiveInstance,
+        prim_local_rect: LayoutRect,
+        prim_local_clip_rect: LayoutRect,
+        prim_details: &mut PrimitiveDetails,
         root_spatial_node_index: SpatialNodeIndex,
         prim_bounding_rect: WorldRect,
         prim_context: &PrimitiveContext,
         prim_clip_chain: &ClipChainInstance,
         pic_state: &mut PictureState,
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
         clip_node_collector: &Option<ClipNodeCollector>,
     ) -> bool {
-        let brush = match self.details {
+        let brush = match *prim_details {
             PrimitiveDetails::Brush(ref mut brush) => brush,
             PrimitiveDetails::TextRun(..) => return false,
         };
 
         brush.write_brush_segment_description(
-            self.local_rect,
-            self.local_clip_rect,
+            prim_local_rect,
+            prim_local_clip_rect,
             prim_clip_chain,
             frame_state,
         );
 
         let segment_desc = match brush.segment_desc {
             Some(ref mut description) => description,
             None => return false,
         };
@@ -2472,19 +2478,19 @@ impl Primitive {
         } else {
             for segment in &mut segment_desc.segments {
                 // Build a clip chain for the smaller segment rect. This will
                 // often manage to eliminate most/all clips, and sometimes
                 // clip the segment completely.
                 let segment_clip_chain = frame_state
                     .clip_store
                     .build_clip_chain_instance(
-                        prim_instance.clip_chain_id,
+                        self.clip_chain_id,
                         segment.local_rect,
-                        self.local_clip_rect,
+                        prim_local_clip_rect,
                         prim_context.spatial_node_index,
                         &pic_state.map_local_to_pic,
                         &pic_state.map_pic_to_world,
                         &frame_context.clip_scroll_tree,
                         frame_state.gpu_cache,
                         frame_state.resource_cache,
                         frame_context.device_pixel_scale,
                         &frame_context.world_rect,
@@ -2504,50 +2510,56 @@ impl Primitive {
         }
 
         true
     }
 
     // Returns true if the primitive *might* need a clip mask. If
     // false, there is no need to even check for clip masks for
     // this primitive.
-    fn reset_clip_task(&mut self, prim_instance: &mut PrimitiveInstance) {
-        prim_instance.clip_task_id = None;
-        match self.details {
+    fn reset_clip_task(
+        &mut self,
+        details: &mut PrimitiveDetails,
+    ) {
+        self.clip_task_id = None;
+        match *details {
             PrimitiveDetails::Brush(ref mut brush) => {
                 if let Some(ref mut desc) = brush.segment_desc {
                     for segment in &mut desc.segments {
                         segment.clip_task_id = BrushSegmentTaskId::Opaque;
                     }
                 }
             }
             PrimitiveDetails::TextRun(..) => {}
         }
     }
-
+}
+
+impl PrimitiveInstance {
     fn prepare_prim_for_render_inner(
         &mut self,
-        prim_instance: &mut PrimitiveInstance,
+        prim_local_rect: LayoutRect,
+        prim_details: &mut PrimitiveDetails,
         prim_context: &PrimitiveContext,
         pic_context: &PictureContext,
         pic_state: &mut PictureState,
         pictures: &mut [PicturePrimitive],
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
         display_list: &BuiltDisplayList,
         plane_split_anchor: usize,
         is_chased: bool,
     ) {
         let mut is_tiled = false;
         #[cfg(debug_assertions)]
         {
-            prim_instance.prepared_frame_id = frame_state.render_tasks.frame_id();
+            self.prepared_frame_id = frame_state.render_tasks.frame_id();
         }
 
-        match self.details {
+        match *prim_details {
             PrimitiveDetails::TextRun(ref mut text) => {
                 // The transform only makes sense for screen space rasterization
                 let transform = prim_context.spatial_node.world_content_transform.to_transform();
                 text.prepare_for_render(
                     frame_context.device_pixel_scale,
                     &transform,
                     pic_context.allow_subpixel_aa,
                     pic_context.raster_space,
@@ -2575,22 +2587,22 @@ impl Primitive {
 
                         // Set if we need to request the source image from the cache this frame.
                         if let Some(image_properties) = image_properties {
                             is_tiled = image_properties.tiling.is_some();
 
                             // If the opacity changed, invalidate the GPU cache so that
                             // the new color for this primitive gets uploaded.
                             if opacity_binding.update(frame_context.scene_properties) {
-                                frame_state.gpu_cache.invalidate(&mut prim_instance.gpu_location);
+                                frame_state.gpu_cache.invalidate(&mut self.gpu_location);
                             }
 
                             // Update opacity for this primitive to ensure the correct
                             // batching parameters are used.
-                            prim_instance.opacity.is_opaque =
+                            self.opacity.is_opaque =
                                 image_properties.descriptor.is_opaque &&
                                 opacity_binding.current == 1.0 &&
                                 color.a == 1.0;
 
                             if *tile_spacing != LayoutSize::zero() && !is_tiled {
                                 *source = ImageSource::Cache {
                                     // Size in device-pixels we need to allocate in render task cache.
                                     size: image_properties.descriptor.size.to_i32(),
@@ -2625,17 +2637,17 @@ impl Primitive {
                                         0,
                                     );
 
                                     let inner_size = *size;
                                     size.width += padding.horizontal();
                                     size.height += padding.vertical();
 
                                     if padding != DeviceIntSideOffsets::zero() {
-                                        prim_instance.opacity.is_opaque = false;
+                                        self.opacity.is_opaque = false;
                                     }
 
                                     let image_cache_key = ImageCacheKey {
                                         request,
                                         texel_rect: sub_rect,
                                     };
 
                                     // Request a pre-rendered image task.
@@ -2690,34 +2702,34 @@ impl Primitive {
                             }
 
                             if let Some(tile_size) = image_properties.tiling {
                                 let device_image_size = image_properties.descriptor.size;
 
                                 // Tighten the clip rect because decomposing the repeated image can
                                 // produce primitives that are partially covering the original image
                                 // rect and we want to clip these extra parts out.
-                                let tight_clip_rect = prim_instance
+                                let tight_clip_rect = self
                                     .combined_local_clip_rect
-                                    .intersection(&self.local_rect).unwrap();
+                                    .intersection(&prim_local_rect).unwrap();
 
                                 let visible_rect = compute_conservative_visible_rect(
                                     prim_context,
-                                    &prim_instance.clipped_world_rect.unwrap(),
+                                    &self.clipped_world_rect.unwrap(),
                                     &tight_clip_rect
                                 );
 
                                 let base_edge_flags = edge_flags_for_tile_spacing(tile_spacing);
 
                                 let stride = stretch_size + *tile_spacing;
 
                                 visible_tiles.clear();
 
                                 let repetitions = image::repetitions(
-                                    &self.local_rect,
+                                    &prim_local_rect,
                                     &visible_rect,
                                     stride,
                                 );
 
                                 for Repetition { origin, edge_flags } in repetitions {
                                     let edge_flags = base_edge_flags | edge_flags;
 
                                     let image_rect = LayoutRect {
@@ -2757,31 +2769,31 @@ impl Primitive {
                                 }
 
                                 if visible_tiles.is_empty() {
                                     // At this point if we don't have tiles to show it means we could probably
                                     // have done a better a job at culling during an earlier stage.
                                     // Clearing the screen rect has the effect of "culling out" the primitive
                                     // from the point of view of the batch builder, and ensures we don't hit
                                     // assertions later on because we didn't request any image.
-                                    prim_instance.clipped_world_rect = None;
+                                    self.clipped_world_rect = None;
                                 }
                             } else if request_source_image {
                                 frame_state.resource_cache.request_image(
                                     request,
                                     frame_state.gpu_cache,
                                 );
                             }
                         }
                     }
                     BrushKind::LineDecoration { ref mut handle, style, orientation, wavy_line_thickness, .. } => {
                         // Work out the device pixel size to be used to cache this line decoration.
 
                         let size = get_line_decoration_sizes(
-                            &self.local_rect.size,
+                            &prim_local_rect.size,
                             orientation,
                             style,
                             wavy_line_thickness,
                         );
 
                         if let Some((inline_size, block_size)) = size {
                             let size = match orientation {
                                 LineOrientation::Horizontal => LayoutSize::new(inline_size, block_size),
@@ -2789,33 +2801,33 @@ impl Primitive {
                             };
 
                             // If dotted, adjust the clip rect to ensure we don't draw a final
                             // partial dot.
                             if style == LineStyle::Dotted {
                                 let clip_size = match orientation {
                                     LineOrientation::Horizontal => {
                                         LayoutSize::new(
-                                            inline_size * (self.local_rect.size.width / inline_size).floor(),
-                                            self.local_rect.size.height,
+                                            inline_size * (prim_local_rect.size.width / inline_size).floor(),
+                                            prim_local_rect.size.height,
                                         )
                                     }
                                     LineOrientation::Vertical => {
                                         LayoutSize::new(
-                                            self.local_rect.size.width,
-                                            inline_size * (self.local_rect.size.height / inline_size).floor(),
+                                            prim_local_rect.size.width,
+                                            inline_size * (prim_local_rect.size.height / inline_size).floor(),
                                         )
                                     }
                                 };
                                 let clip_rect = LayoutRect::new(
-                                    self.local_rect.origin,
+                                    prim_local_rect.origin,
                                     clip_size,
                                 );
-                                prim_instance.combined_local_clip_rect = clip_rect
-                                    .intersection(&prim_instance.combined_local_clip_rect)
+                                self.combined_local_clip_rect = clip_rect
+                                    .intersection(&self.combined_local_clip_rect)
                                     .unwrap_or(LayoutRect::zero());
                             }
 
                             // TODO(gw): Do we ever need / want to support scales for text decorations
                             //           based on the current transform?
                             let scale_factor = TypedScale::new(1.0) * frame_context.device_pixel_scale;
                             let task_size = (size * scale_factor).ceil().to_i32();
 
@@ -2847,17 +2859,17 @@ impl Primitive {
                                     let task_id = render_tasks.add(task);
                                     pic_state.tasks.push(task_id);
                                     task_id
                                 }
                             ));
                         }
                     }
                     BrushKind::YuvImage { format, yuv_key, image_rendering, .. } => {
-                        prim_instance.opacity = PrimitiveOpacity::opaque();
+                        self.opacity = PrimitiveOpacity::opaque();
 
                         let channel_num = format.get_plane_num();
                         debug_assert!(channel_num <= 3);
                         for channel in 0 .. channel_num {
                             frame_state.resource_cache.request_image(
                                 ImageRequest {
                                     key: yuv_key[channel],
                                     rendering: image_rendering,
@@ -2872,17 +2884,17 @@ impl Primitive {
                             BorderSource::Image(request) => {
                                 let image_properties = frame_state
                                     .resource_cache
                                     .get_image_properties(request.key);
 
                                 if let Some(image_properties) = image_properties {
                                     // Update opacity for this primitive to ensure the correct
                                     // batching parameters are used.
-                                    prim_instance.opacity.is_opaque =
+                                    self.opacity.is_opaque =
                                         image_properties.descriptor.is_opaque;
 
                                     frame_state.resource_cache.request_image(
                                         request,
                                         frame_state.gpu_cache,
                                     );
                                 }
                             }
@@ -2950,18 +2962,18 @@ impl Primitive {
                             display_list,
                         );
 
                         if tile_spacing != LayoutSize::zero() {
                             is_tiled = true;
 
                             decompose_repeated_primitive(
                                 visible_tiles,
-                                prim_instance,
-                                &self.local_rect,
+                                self,
+                                &prim_local_rect,
                                 &stretch_size,
                                 &tile_spacing,
                                 prim_context,
                                 frame_state,
                                 &mut |rect, mut request| {
                                     request.push([
                                         center.x,
                                         center.y,
@@ -2993,18 +3005,18 @@ impl Primitive {
                         ..
                     } => {
                         // If the coverage of the gradient extends to or beyond
                         // the primitive rect, then the opacity can be determined
                         // by the colors of the stops. If we have tiling / spacing
                         // then we just assume the gradient is translucent for now.
                         // (In the future we could consider segmenting in some cases).
                         let stride = stretch_size + tile_spacing;
-                        prim_instance.opacity = if stride.width >= self.local_rect.size.width &&
-                           stride.height >= self.local_rect.size.height {
+                        self.opacity = if stride.width >= prim_local_rect.size.width &&
+                           stride.height >= prim_local_rect.size.height {
                             stops_opacity
                         } else {
                             PrimitiveOpacity::translucent()
                         };
 
                         build_gradient_stops_request(
                             stops_handle,
                             stops_range,
@@ -3013,18 +3025,18 @@ impl Primitive {
                             display_list,
                         );
 
                         if tile_spacing != LayoutSize::zero() {
                             is_tiled = true;
 
                             decompose_repeated_primitive(
                                 visible_tiles,
-                                prim_instance,
-                                &self.local_rect,
+                                self,
+                                &prim_local_rect,
                                 &stretch_size,
                                 &tile_spacing,
                                 prim_context,
                                 frame_state,
                                 &mut |rect, mut request| {
                                     request.push([
                                         start_point.x,
                                         start_point.y,
@@ -3041,111 +3053,115 @@ impl Primitive {
                                 }
                             );
                         }
                     }
                     BrushKind::Picture { pic_index, .. } => {
                         let pic = &mut pictures[pic_index.0];
                         if pic.prepare_for_render(
                             pic_index,
-                            prim_instance,
-                            &self.local_rect,
+                            self,
+                            &prim_local_rect,
                             pic_state,
                             frame_context,
                             frame_state,
                         ) {
                             if let Some(ref mut splitter) = pic_state.plane_splitter {
                                 PicturePrimitive::add_split_plane(
                                     splitter,
                                     frame_state.transforms,
-                                    prim_instance,
-                                    self.local_rect,
+                                    self,
+                                    prim_local_rect,
                                     plane_split_anchor,
                                 );
                             }
                         } else {
-                            prim_instance.clipped_world_rect = None;
+                            self.clipped_world_rect = None;
                         }
                     }
                     BrushKind::Solid { ref color, ref mut opacity_binding, .. } => {
                         // If the opacity changed, invalidate the GPU cache so that
                         // the new color for this primitive gets uploaded. Also update
                         // the opacity field that controls which batches this primitive
                         // will be added to.
                         if opacity_binding.update(frame_context.scene_properties) {
-                            frame_state.gpu_cache.invalidate(&mut prim_instance.gpu_location);
+                            frame_state.gpu_cache.invalidate(&mut self.gpu_location);
                         }
-                        prim_instance.opacity = PrimitiveOpacity::from_alpha(opacity_binding.current * color.a);
+                        self.opacity = PrimitiveOpacity::from_alpha(opacity_binding.current * color.a);
                     }
                     BrushKind::Clear => {}
                 }
             }
         }
 
         if is_tiled {
             // we already requested each tile's gpu data.
             return;
         }
 
         // Mark this GPU resource as required for this frame.
-        if let Some(mut request) = frame_state.gpu_cache.request(&mut prim_instance.gpu_location) {
-            match self.details {
+        if let Some(mut request) = frame_state.gpu_cache.request(&mut self.gpu_location) {
+            match *prim_details {
                 PrimitiveDetails::TextRun(ref mut text) => {
                     text.write_gpu_blocks(&mut request);
                 }
                 PrimitiveDetails::Brush(ref mut brush) => {
-                    brush.write_gpu_blocks(&mut request, self.local_rect);
+                    brush.write_gpu_blocks(&mut request, prim_local_rect);
 
                     match brush.segment_desc {
                         Some(ref segment_desc) => {
                             for segment in &segment_desc.segments {
                                 if cfg!(debug_assertions) && is_chased {
                                     println!("\t\t{:?}", segment);
                                 }
                                 // has to match VECS_PER_SEGMENT
                                 request.write_segment(
                                     segment.local_rect,
                                     segment.extra_data,
                                 );
                             }
                         }
                         None => {
                             request.write_segment(
-                                self.local_rect,
+                                prim_local_rect,
                                 [0.0; 4],
                             );
                         }
                     }
                 }
             }
         }
     }
 
     fn update_clip_task(
         &mut self,
-        prim_instance: &mut PrimitiveInstance,
+        prim_local_rect: LayoutRect,
+        prim_local_clip_rect: LayoutRect,
+        prim_details: &mut PrimitiveDetails,
         prim_context: &PrimitiveContext,
         prim_bounding_rect: WorldRect,
         root_spatial_node_index: SpatialNodeIndex,
         clip_chain: &ClipChainInstance,
         pic_state: &mut PictureState,
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
         is_chased: bool,
         clip_node_collector: &Option<ClipNodeCollector>,
     ) {
         if cfg!(debug_assertions) && is_chased {
             println!("\tupdating clip task with pic rect {:?}", clip_chain.pic_clip_rect);
         }
         // Reset clips from previous frames since we may clip differently each frame.
-        self.reset_clip_task(prim_instance);
+        self.reset_clip_task(prim_details);
 
         // First try to  render this primitive's mask using optimized brush rendering.
         if self.update_clip_task_for_brush(
-            prim_instance,
+            prim_local_rect,
+            prim_local_clip_rect,
+            prim_details,
             root_spatial_node_index,
             prim_bounding_rect,
             prim_context,
             &clip_chain,
             pic_state,
             frame_context,
             frame_state,
             clip_node_collector,
@@ -3175,17 +3191,17 @@ impl Primitive {
                     &mut frame_state.resources.clip_data_store,
                 );
 
                 let clip_task_id = frame_state.render_tasks.add(clip_task);
                 if cfg!(debug_assertions) && is_chased {
                     println!("\tcreated task {:?} with device rect {:?}",
                         clip_task_id, device_rect);
                 }
-                prim_instance.clip_task_id = Some(clip_task_id);
+                self.clip_task_id = Some(clip_task_id);
                 pic_state.tasks.push(clip_task_id);
             }
         }
     }
 }
 
 pub fn get_raster_rects(
     pic_rect: PictureRect,
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-4e9ed699f3be741102120ba2d499e91c0adba6ab
+70fd6273c3bc8ed0209e195d869fa3251e1184c7
--- a/intl/l10n/DocumentL10n.cpp
+++ b/intl/l10n/DocumentL10n.cpp
@@ -9,20 +9,70 @@
 #include "mozilla/dom/DocumentL10nBinding.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "nsQueryObject.h"
 #include "nsISupports.h"
 #include "nsContentUtils.h"
+#include "xpcprivate.h"
 
 namespace mozilla {
 namespace dom {
 
+NS_INTERFACE_MAP_BEGIN(PromiseResolver)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(PromiseResolver)
+NS_IMPL_RELEASE(PromiseResolver)
+
+PromiseResolver::PromiseResolver(Promise* aPromise)
+{
+  mPromise = aPromise;
+}
+
+void
+PromiseResolver::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
+{
+  JS::RootedObject sourceScope(aCx, JS::CurrentGlobalOrNull(aCx));
+
+  AutoEntryScript aes(mPromise->GetParentObject(), "Promise resolution");
+  JSContext* cx = aes.cx();
+  JS::Rooted<JS::Value> value(cx, aValue);
+
+  xpc::StackScopedCloneOptions options;
+  StackScopedClone(cx, options, sourceScope, &value);
+
+  mPromise->MaybeResolve(cx, value);
+  mPromise = nullptr;
+}
+
+void
+PromiseResolver::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
+{
+  JS::RootedObject sourceScope(aCx, JS::CurrentGlobalOrNull(aCx));
+
+  AutoEntryScript aes(mPromise->GetParentObject(), "Promise rejection");
+  JSContext* cx = aes.cx();
+  JS::Rooted<JS::Value> value(cx, aValue);
+
+  xpc::StackScopedCloneOptions options;
+  StackScopedClone(cx, options, sourceScope, &value);
+
+  mPromise->MaybeReject(cx, value);
+  mPromise = nullptr;
+}
+
+PromiseResolver::~PromiseResolver()
+{
+  mPromise = nullptr;
+}
+
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DocumentL10n)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DocumentL10n)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DocumentL10n)
@@ -75,16 +125,41 @@ DocumentL10n::Init(nsTArray<nsString>& a
 }
 
 JSObject*
 DocumentL10n::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return DocumentL10n_Binding::Wrap(aCx, this, aGivenProto);
 }
 
+already_AddRefed<Promise>
+DocumentL10n::MaybeWrapPromise(Promise* aInnerPromise)
+{
+  // For system principal we don't need to wrap the
+  // result promise at all.
+  if (nsContentUtils::IsSystemPrincipal(mDocument->NodePrincipal())) {
+    return RefPtr<Promise>(aInnerPromise).forget();
+  }
+
+  nsIGlobalObject* global = mDocument->GetScopeObject();
+  if (!global) {
+    return nullptr;
+  }
+
+  ErrorResult result;
+  RefPtr<Promise> docPromise = Promise::Create(global, result);
+  if (result.Failed()) {
+    return nullptr;
+  }
+
+  RefPtr<PromiseResolver> resolver = new PromiseResolver(docPromise);
+  aInnerPromise->AppendNativeHandler(resolver);
+  return docPromise.forget();
+}
+
 NS_IMETHODIMP
 DocumentL10n::HandleEvent(Event* aEvent)
 {
 #ifdef DEBUG
   nsAutoString eventType;
   aEvent->GetType(eventType);
   MOZ_ASSERT(eventType.EqualsLiteral("MozBeforeInitialXULLayout"));
 #endif
@@ -131,17 +206,17 @@ DocumentL10n::FormatMessages(JSContext* 
   }
 
   RefPtr<Promise> promise;
   aRv = mDOMLocalization->FormatMessages(jsKeys, getter_AddRefs(promise));
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  return promise.forget();
+  return MaybeWrapPromise(promise);
 }
 
 already_AddRefed<Promise>
 DocumentL10n::FormatValues(JSContext* aCx, const Sequence<L10nKey>& aKeys, ErrorResult& aRv)
 {
   nsTArray<JS::Value> jsKeys;
   SequenceRooter<JS::Value> rooter(aCx, &jsKeys);
   for (auto& key : aKeys) {
@@ -154,17 +229,17 @@ DocumentL10n::FormatValues(JSContext* aC
   }
 
   RefPtr<Promise> promise;
   aRv = mDOMLocalization->FormatValues(jsKeys, getter_AddRefs(promise));
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  return promise.forget();
+  return MaybeWrapPromise(promise);
 }
 
 already_AddRefed<Promise>
 DocumentL10n::FormatValue(JSContext* aCx, const nsAString& aId, const Optional<JS::Handle<JSObject*>>& aArgs, ErrorResult& aRv)
 {
   JS::Rooted<JS::Value> args(aCx);
 
   if (aArgs.WasPassed()) {
@@ -174,17 +249,17 @@ DocumentL10n::FormatValue(JSContext* aCx
   }
 
   RefPtr<Promise> promise;
   nsresult rv = mDOMLocalization->FormatValue(aId, args, getter_AddRefs(promise));
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
-  return promise.forget();
+  return MaybeWrapPromise(promise);
 }
 
 void
 DocumentL10n::SetAttributes(JSContext* aCx, Element& aElement, const nsAString& aId, const Optional<JS::Handle<JSObject*>>& aArgs, ErrorResult& aRv)
 {
   aElement.SetAttribute(NS_LITERAL_STRING("data-l10n-id"), aId, aRv);
   if (aRv.Failed()) {
     return;
@@ -230,34 +305,34 @@ already_AddRefed<Promise>
 DocumentL10n::TranslateFragment(nsINode& aNode, ErrorResult& aRv)
 {
   RefPtr<Promise> promise;
   nsresult rv = mDOMLocalization->TranslateFragment(&aNode, getter_AddRefs(promise));
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
-  return promise.forget();
+  return MaybeWrapPromise(promise);
 }
 
 already_AddRefed<Promise>
 DocumentL10n::TranslateElements(const Sequence<OwningNonNull<Element>>& aElements, ErrorResult& aRv)
 {
   AutoTArray<RefPtr<Element>, 10> elements;
   elements.SetCapacity(aElements.Length());
   for (auto& element : aElements) {
     elements.AppendElement(element);
   }
   RefPtr<Promise> promise;
   aRv = mDOMLocalization->TranslateElements(
       elements, getter_AddRefs(promise));
   if (aRv.Failed()) {
     return nullptr;
   }
-  return promise.forget();
+  return MaybeWrapPromise(promise);
 }
 
 class L10nReadyHandler final : public PromiseNativeHandler
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(L10nReadyHandler)
 
--- a/intl/l10n/DocumentL10n.h
+++ b/intl/l10n/DocumentL10n.h
@@ -12,24 +12,40 @@
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "nsIDOMEventListener.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
 #include "nsIDocument.h"
 #include "nsINode.h"
 #include "mozIDOMLocalization.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/PromiseNativeHandler.h"
 
 namespace mozilla {
 namespace dom {
 
 class Element;
-class Promise;
 struct L10nKey;
 
+class PromiseResolver final : public PromiseNativeHandler
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  explicit PromiseResolver(Promise* aPromise);
+  void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
+  void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
+
+protected:
+  virtual ~PromiseResolver();
+
+  RefPtr<Promise> mPromise;
+};
+
 enum class DocumentL10nState
 {
   Initialized = 0,
   InitialTranslationTriggered
 };
 
 /**
  * This class maintains localization status of the nsDocument.
@@ -56,16 +72,18 @@ public:
 protected:
   virtual ~DocumentL10n();
 
   nsCOMPtr<nsIDocument> mDocument;
   RefPtr<Promise> mReady;
   DocumentL10nState mState;
   nsCOMPtr<mozIDOMLocalization> mDOMLocalization;
 
+  already_AddRefed<Promise> MaybeWrapPromise(Promise* aPromise);
+
 public:
   nsIDocument* GetParentObject() const { return mDocument; };
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   /**
    * A method for adding resources to the localization context.
    *
--- a/intl/l10n/L10nRegistry.jsm
+++ b/intl/l10n/L10nRegistry.jsm
@@ -1,14 +1,17 @@
 const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {});
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
+// eslint-disable-next-line mozilla/use-services
+const appinfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
 const { FluentBundle, FluentResource } = ChromeUtils.import("resource://gre/modules/Fluent.jsm", {});
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
 
+const isParentProcess = appinfo.processType === appinfo.PROCESS_TYPE_DEFAULT;
 /**
  * L10nRegistry is a localization resource management system for Gecko.
  *
  * It manages the list of resource sources provided with the app and allows
  * for additional sources to be added and updated.
  *
  * It's primary purpose is to allow for building an iterator over FluentBundle objects
  * that will be utilized by a localization API.
@@ -71,32 +74,43 @@ XPCOMUtils.defineLazyGlobalGetters(this,
  *
  * This allows the localization API to consume the FluentBundle and lazily fallback
  * on the next in case of a missing string or error.
  *
  * If during the life-cycle of the app a new source is added, the generator can be called again
  * and will produce a new set of permutations placing the language pack provided resources
  * at the top.
  */
-const L10nRegistry = {
-  sources: new Map(),
-  bootstrap: null,
+class L10nRegistryService {
+  constructor() {
+    this.sources = new Map();
+
+    if (!isParentProcess) {
+      this._setSourcesFromSharedData();
+      Services.cpmm.sharedData.addEventListener("change", this);
+    }
+  }
+
+  handleEvent(event) {
+    if (event.type === "change") {
+      if (event.changedKeys.includes("L10nRegistry:Sources")) {
+        this._setSourcesFromSharedData();
+      }
+    }
+  }
 
   /**
    * Based on the list of requested languages and resource Ids,
    * this function returns an lazy iterator over message context permutations.
    *
    * @param {Array} requestedLangs
    * @param {Array} resourceIds
    * @returns {AsyncIterator<FluentBundle>}
    */
   async* generateBundles(requestedLangs, resourceIds) {
-    if (this.bootstrap !== null) {
-      await this.bootstrap;
-    }
     const sourcesOrder = Array.from(this.sources.keys()).reverse();
     const pseudoNameFromPref = Services.prefs.getStringPref("intl.l10n.pseudo", "");
     for (const locale of requestedLangs) {
       for await (const dataSets of generateResourceSetsForLocale(locale, sourcesOrder, resourceIds)) {
         const bundle = new FluentBundle(locale, {
           ...MSG_CONTEXT_OPTIONS,
           transform: PSEUDO_STRATEGIES[pseudoNameFromPref],
         });
@@ -104,74 +118,114 @@ const L10nRegistry = {
           if (data === null) {
             return;
           }
           bundle.addResource(data);
         }
         yield bundle;
       }
     }
-  },
+  }
 
   /**
    * Adds a new resource source to the L10nRegistry.
    *
    * @param {FileSource} source
    */
   registerSource(source) {
     if (this.sources.has(source.name)) {
       throw new Error(`Source with name "${source.name}" already registered.`);
     }
     this.sources.set(source.name, source);
-    Services.locale.availableLocales = this.getAvailableLocales();
-  },
+
+    if (isParentProcess) {
+      this._synchronizeSharedData();
+      Services.locale.availableLocales = this.getAvailableLocales();
+    }
+  }
 
   /**
    * Updates an existing source in the L10nRegistry
    *
    * That will usually happen when a new version of a source becomes
    * available (for example, an updated version of a language pack).
    *
    * @param {FileSource} source
    */
   updateSource(source) {
     if (!this.sources.has(source.name)) {
       throw new Error(`Source with name "${source.name}" is not registered.`);
     }
     this.sources.set(source.name, source);
-    Services.locale.availableLocales = this.getAvailableLocales();
-  },
+    if (isParentProcess) {
+      this._synchronizeSharedData();
+      Services.locale.availableLocales = this.getAvailableLocales();
+    }
+  }
 
   /**
    * Removes a source from the L10nRegistry.
    *
    * @param {String} sourceId
    */
   removeSource(sourceName) {
     this.sources.delete(sourceName);
-    Services.locale.availableLocales = this.getAvailableLocales();
-  },
+    if (isParentProcess) {
+      this._synchronizeSharedData();
+      Services.locale.availableLocales = this.getAvailableLocales();
+    }
+  }
+
+  _synchronizeSharedData() {
+    const sources = new Map();
+    for (const [name, source] of this.sources.entries()) {
+      if (source.indexed) {
+        continue;
+      }
+      sources.set(name, {
+        locales: source.locales,
+        prePath: source.prePath,
+      });
+    }
+    Services.ppmm.sharedData.set("L10nRegistry:Sources", sources);
+    Services.ppmm.sharedData.flush();
+  }
+
+  _setSourcesFromSharedData() {
+    let sources = Services.cpmm.sharedData.get("L10nRegistry:Sources");
+    for (let [name, data] of sources.entries()) {
+      if (!this.sources.has(name)) {
+        const source = new FileSource(name, data.locales, data.prePath);
+        this.registerSource(source);
+      }
+    }
+    for (let name of this.sources.keys()) {
+      if (!sources.has(name)) {
+        this.removeSource(name);
+      }
+    }
+  }
 
   /**
    * Returns a list of locales for which at least one source
    * has resources.
    *
    * @returns {Array<String>}
    */
   getAvailableLocales() {
     const locales = new Set();
 
     for (const source of this.sources.values()) {
       for (const locale of source.locales) {
         locales.add(locale);
       }
     }
     return Array.from(locales);
-  },
-};
+  }
+}
 
 /**
  * This function generates an iterator over FluentBundles for a single locale
  * for a given list of resourceIds for all possible combinations of sources.
  *
  * This function is called recursively to generate all possible permutations
  * and uses the last, optional parameter, to pass the already resolved
  * sources order.
@@ -479,32 +533,33 @@ class IndexedFileSource extends FileSour
     super(name, locales, prePath);
     this.indexed = true;
     for (const path of paths) {
       this.cache[path] = true;
     }
   }
 }
 
+this.L10nRegistry = new L10nRegistryService();
+
 /**
  * The low level wrapper around Fetch API. It unifies the error scenarios to
  * always produce a promise rejection.
  *
  * We keep it as a method to make it easier to override for testing purposes.
  *
  * @param {string} url
  *
  * @returns {Promise<string>}
  */
-L10nRegistry.load = function(url) {
+this.L10nRegistry.load = function(url) {
   return fetch(url).then(response => {
     if (!response.ok) {
       return Promise.reject(response.statusText);
     }
     return response.text();
   });
 };
 
-this.L10nRegistry = L10nRegistry;
 this.FileSource = FileSource;
 this.IndexedFileSource = IndexedFileSource;
 
 var EXPORTED_SYMBOLS = ["L10nRegistry", "FileSource", "IndexedFileSource"];
--- a/intl/l10n/moz.build
+++ b/intl/l10n/moz.build
@@ -27,18 +27,20 @@ EXPORTS.mozilla.dom += [
 ]
 
 UNIFIED_SOURCES += [
     'DocumentL10n.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
+    '/js/xpconnect/src',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
+BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 SPHINX_TREES['l10n'] = 'docs'
 
 FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/intl/l10n/test/browser.ini
@@ -0,0 +1,4 @@
+[document_l10n/non-system-principal/browser_resource_uri.js]
+support-files =
+  document_l10n/non-system-principal/test.html
+  document_l10n/non-system-principal/localization/test.ftl
new file mode 100644
--- /dev/null
+++ b/intl/l10n/test/document_l10n/README.txt
@@ -0,0 +1,3 @@
+Tests in this directory cover support for DocumentL10n
+WebIDL API across different use cases such as
+processes, principals and so on.
new file mode 100644
--- /dev/null
+++ b/intl/l10n/test/document_l10n/non-system-principal/README.txt
@@ -0,0 +1,3 @@
+Tests in this directory cover the functionality
+of DocumentL10n WebIDL API in non-system-principal
+scenario.
new file mode 100644
--- /dev/null
+++ b/intl/l10n/test/document_l10n/non-system-principal/browser_resource_uri.js
@@ -0,0 +1,70 @@
+const { L10nRegistry, FileSource } = ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm", {});
+
+let uri = "chrome://mochitests/content/browser/intl/l10n/test/document_l10n/non-system-principal/";
+let protocol = Services.io.getProtocolHandler("resource")
+                          .QueryInterface(Ci.nsIResProtocolHandler);
+
+protocol.setSubstitution("l10n-test", Services.io.newURI(uri));
+
+// Since we want the mock source to work with all locales, we're going
+// to register it for currently used locales, and we'll put the path that
+// doesn't use the `{locale}` component to make it work irrelevant of
+// what locale the mochitest is running in.
+//
+// Notice: we're using a `chrome://` protocol here only for convenience reasons.
+// Real sources should use `resource://` protocol.
+let locales = Services.locale.appLocalesAsBCP47;
+let mockSource = new FileSource("test", locales, `${uri}localization/`);
+L10nRegistry.registerSource(mockSource);
+
+registerCleanupFunction(() => {
+  protocol.setSubstitution("l10n-test", null);
+  L10nRegistry.removeSource("test");
+});
+
+
+add_task(async () => {
+  await BrowserTestUtils.withNewTab("resource://l10n-test/test.html", async (browser) => {
+    await ContentTask.spawn(browser, null, async function() {
+      let document = content.document;
+      let window = document.defaultView;
+
+      let {customMsg, l10nArgs} = await document.testsReadyPromise;
+
+      let desc = document.getElementById("main-desc");
+
+      // We can test here for a particular value because we're
+      // using a mock file source which is locale independent.
+      //
+      // If you're writing a test that verifies that a UI
+      // widget got real localization, you should not rely on
+      // the particular value, but rather on the content not
+      // being empty (to keep the test pass in non-en-US locales).
+      is(desc.textContent, "This is a mock page title");
+
+      // Test for l10n.getAttributes
+      let label = document.getElementById("label1");
+      is(l10nArgs.id, "subtitle");
+      is(l10nArgs.args.name, "Firefox");
+
+      // Test for manual value formatting
+      is(customMsg, "This is a custom message formatted from JS.");
+
+      // Since we applied the `data-l10n-id` attribute
+      // on `label` in this microtask, we have to wait for
+      // the next paint to verify that the MutationObserver
+      // applied the translation.
+      await new Promise((resolve) => {
+        let verifyL10n = () => {
+          if (!label.textContent.includes("Firefox")) {
+            window.requestAnimationFrame(verifyL10n);
+          } else {
+            resolve();
+          }
+        };
+
+        window.requestAnimationFrame(verifyL10n);
+      });
+    });
+  });
+});
new file mode 100644
--- /dev/null
+++ b/intl/l10n/test/document_l10n/non-system-principal/localization/test.ftl
@@ -0,0 +1,4 @@
+page-title = This is a mock page title
+subtitle = This is a label for { $name }
+
+custom-message = This is a custom message formatted from JS.
new file mode 100644
--- /dev/null
+++ b/intl/l10n/test/document_l10n/non-system-principal/test.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test DocumentL10n in HTML environment</title>
+  <link rel="localization" href="test.ftl"/>
+  <script type="text/javascript">
+    document.testsReadyPromise = new Promise(async (resolve) => {
+      // The test is in this file to ensure that we're testing
+      // the behavior in a non-system principal.
+      document.addEventListener("DOMContentLoaded", async () => {
+        await document.l10n.ready;
+
+        // Assign the localization from JS
+        let label = document.getElementById("label1");
+        document.l10n.setAttributes(
+          label,
+          "subtitle",
+          {
+            name: "Firefox",
+          }
+        );
+
+        const customMsg = await document.l10n.formatValue("custom-message");
+        const l10nArgs = document.l10n.getAttributes(label);
+        resolve({customMsg, l10nArgs});
+      }, {once: true});
+    });
+  </script>
+</head>
+<body>
+  <h1 id="main-desc" data-l10n-id="page-title"></h1>
+
+  <p id="label1"></p>
+</body>
+</html>
--- a/js/src/jit/JitSpewer.cpp
+++ b/js/src/jit/JitSpewer.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 #ifdef JS_JITSPEW
 
 #include "jit/JitSpewer.h"
 
 #include "mozilla/Atomics.h"
+#include "mozilla/Sprintf.h"
 
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #else
 #include <unistd.h>
 #endif
 #include "jit/Ion.h"
@@ -619,17 +620,19 @@ jit::CheckLogging()
         EnableChannel(JitSpew_BaselineOSR);
         EnableChannel(JitSpew_BaselineBailouts);
         EnableChannel(JitSpew_BaselineDebugModeOSR);
     }
 
     FILE* spewfh = stderr;
     const char* filename = getenv("ION_SPEW_FILENAME");
     if (filename && *filename) {
-        spewfh = fopen(filename, "w");
+        char actual_filename[2048] = {0};
+        SprintfLiteral(actual_filename, "%s.%d", filename, getpid());
+        spewfh = fopen(actual_filename, "w");
         MOZ_RELEASE_ASSERT(spewfh);
         setbuf(spewfh, nullptr); // Make unbuffered
     }
     JitSpewPrinter().init(spewfh);
 }
 
 JitSpewIndent::JitSpewIndent(JitSpewChannel channel)
   : channel_(channel)
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -3408,18 +3408,25 @@ MacroAssembler::branchIfPretenuredGroup(
 {
     movePtr(ImmGCPtr(group), scratch);
     branchIfPretenuredGroup(scratch, label);
 }
 
 void
 MacroAssembler::branchIfPretenuredGroup(Register group, Label* label)
 {
+    // To check for the pretenured flag we need OBJECT_FLAG_PRETENURED set, and
+    // OBJECT_FLAG_UNKNOWN_PROPERTIES unset, so check the latter first, and don't
+    // branch if it set.
+    Label unknownProperties;
+    branchTest32(Assembler::NonZero, Address(group, ObjectGroup::offsetOfFlags()),
+                Imm32(OBJECT_FLAG_UNKNOWN_PROPERTIES), &unknownProperties);
     branchTest32(Assembler::NonZero, Address(group, ObjectGroup::offsetOfFlags()),
                  Imm32(OBJECT_FLAG_PRE_TENURE), label);
+    bind(&unknownProperties);
 }
 
 
 void
 MacroAssembler::branchIfNonNativeObj(Register obj, Register scratch, Label* label)
 {
     loadObjClassUnsafe(obj, scratch);
     branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()),
--- a/js/src/vm/UnboxedObject.cpp
+++ b/js/src/vm/UnboxedObject.cpp
@@ -128,20 +128,25 @@ UnboxedLayout::makeConstructorCode(JSCon
     LiveGeneralRegisterSet savedNonVolatileRegisters = SavedNonVolatileRegisters(regs);
     masm.PushRegsInMask(savedNonVolatileRegisters);
 
     // The scratch double register might be used by MacroAssembler methods.
     if (ScratchDoubleReg.volatile_()) {
         masm.push(ScratchDoubleReg);
     }
 
-    Label failure, tenuredObject, allocated;
+    Label failure, tenuredObject, allocated, unknownProperties;
     masm.branch32(Assembler::NotEqual, newKindReg, Imm32(GenericObject), &tenuredObject);
-    masm.branchTest32(Assembler::NonZero, AbsoluteAddress(group->addressOfFlags()),
+
+    masm.load32(AbsoluteAddress(group->addressOfFlags()), scratch1);
+    masm.branchTest32(Assembler::NonZero, scratch1,
+                      Imm32(OBJECT_FLAG_UNKNOWN_PROPERTIES), &unknownProperties);
+    masm.branchTest32(Assembler::NonZero, scratch1,
                       Imm32(OBJECT_FLAG_PRE_TENURE), &tenuredObject);
+    masm.bind(&unknownProperties);
 
     // Allocate an object in the nursery
     TemplateObject templateObj(templateObject);
     masm.createGCObject(object, scratch1, templateObj, gc::DefaultHeap, &failure,
                         /* initFixedSlots = */ false);
 
     masm.jump(&allocated);
     masm.bind(&tenuredObject);
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -195,26 +195,16 @@ mozJSComponentLoader::mozJSComponentLoad
       mLocations(16),
       mInitialized(false),
       mShareLoaderGlobal(false),
       mLoaderGlobal(dom::RootingCx())
 {
     MOZ_ASSERT(!sSelf, "mozJSComponentLoader should be a singleton");
 }
 
-// static
-already_AddRefed<mozJSComponentLoader>
-mozJSComponentLoader::GetOrCreate()
-{
-    if (!sSelf) {
-        sSelf = new mozJSComponentLoader();
-    }
-    return do_AddRef(sSelf);
-}
-
 #define ENSURE_DEP(name) { nsresult rv = Ensure##name(); NS_ENSURE_SUCCESS(rv, rv); }
 #define ENSURE_DEPS(...) MOZ_FOR_EACH(ENSURE_DEP, (), (__VA_ARGS__));
 #define BEGIN_ENSURE(self, ...) { \
     if (m##self) \
         return NS_OK; \
     ENSURE_DEPS(__VA_ARGS__); \
 }
 
@@ -306,17 +296,17 @@ mozJSComponentLoader::~mozJSComponentLoa
     if (mInitialized) {
         NS_ERROR("'xpcom-shutdown-loaders' was not fired before cleaning up mozJSComponentLoader");
         UnloadModules();
     }
 
     sSelf = nullptr;
 }
 
-mozJSComponentLoader*
+StaticRefPtr<mozJSComponentLoader>
 mozJSComponentLoader::sSelf;
 
 NS_IMPL_ISUPPORTS(mozJSComponentLoader,
                   nsIObserver)
 
 nsresult
 mozJSComponentLoader::ReallyInit()
 {
@@ -535,16 +525,30 @@ mozJSComponentLoader::FindTargetObject(J
     // instead. This is needed when calling the subscript loader within a frame
     // script, since it the FrameScript NSVO will have been found.
     if (!aTargetObject ||
         !IsLoaderGlobal(JS::GetNonCCWObjectGlobal(aTargetObject))) {
         aTargetObject.set(CurrentGlobalOrNull(aCx));
     }
 }
 
+void
+mozJSComponentLoader::InitStatics()
+{
+    MOZ_ASSERT(!sSelf);
+    sSelf = new mozJSComponentLoader();
+}
+
+void
+mozJSComponentLoader::Shutdown()
+{
+    MOZ_ASSERT(sSelf);
+    sSelf = nullptr;
+}
+
 // This requires that the keys be strings and the values be pointers.
 template <class Key, class Data, class UserData>
 static size_t
 SizeOfTableExcludingThis(const nsBaseHashtable<Key, Data, UserData>& aTable,
                          MallocSizeOf aMallocSizeOf)
 {
     size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
     for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
--- a/js/xpconnect/loader/mozJSComponentLoader.h
+++ b/js/xpconnect/loader/mozJSComponentLoader.h
@@ -6,16 +6,17 @@
 
 #ifndef mozJSComponentLoader_h
 #define mozJSComponentLoader_h
 
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/FileLocation.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Module.h"
+#include "mozilla/StaticPtr.h"
 #include "nsAutoPtr.h"
 #include "nsISupports.h"
 #include "nsIObserver.h"
 #include "nsIURI.h"
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
 #include "jsapi.h"
 
@@ -25,23 +26,16 @@
 class nsIFile;
 class ComponentLoaderInfo;
 
 namespace mozilla {
     class ScriptPreloader;
 } // namespace mozilla
 
 
-/* 6bd13476-1dd2-11b2-bbef-f0ccb5fa64b6 (thanks, mozbot) */
-
-#define MOZJSCOMPONENTLOADER_CID                                              \
-  {0x6bd13476, 0x1dd2, 0x11b2,                                                \
-    { 0xbb, 0xef, 0xf0, 0xcc, 0xb5, 0xfa, 0x64, 0xb6 }}
-#define MOZJSCOMPONENTLOADER_CONTRACTID "@mozilla.org/moz/jsloader;1"
-
 #if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG)
 #define STARTUP_RECORDER_ENABLED
 #endif
 
 class mozJSComponentLoader final : public nsIObserver
 {
  public:
     NS_DECL_ISUPPORTS
@@ -54,19 +48,23 @@ class mozJSComponentLoader final : publi
     nsresult GetModuleImportStack(const nsACString& aLocation, nsACString& aRetval);
     nsresult GetComponentLoadStack(const nsACString& aLocation, nsACString& aRetval);
 
     const mozilla::Module* LoadModule(mozilla::FileLocation& aFile);
 
     void FindTargetObject(JSContext* aCx,
                           JS::MutableHandleObject aTargetObject);
 
-    static already_AddRefed<mozJSComponentLoader> GetOrCreate();
+    static void InitStatics();
+    static void Shutdown();
 
-    static mozJSComponentLoader* Get() { return sSelf; }
+    static mozJSComponentLoader* Get() {
+        MOZ_ASSERT(sSelf, "Should have already created the component loader");
+        return sSelf;
+    }
 
     nsresult ImportInto(const nsACString& aResourceURI, JS::HandleValue aTargetObj,
                         JSContext* aCx, uint8_t aArgc, JS::MutableHandleValue aRetval);
 
     nsresult Import(JSContext* aCx, const nsACString& aResourceURI,
                     JS::MutableHandleObject aModuleGlobal,
                     JS::MutableHandleObject aModuleExports,
                     bool aIgnoreExports = false);
@@ -96,17 +94,17 @@ class mozJSComponentLoader final : publi
     {
         if (mLoaderGlobal) {
             return mLoaderGlobal;
         }
         return GetSharedGlobal(aCx);
     }
 
  private:
-    static mozJSComponentLoader* sSelf;
+    static mozilla::StaticRefPtr<mozJSComponentLoader> sSelf;
 
     nsresult ReallyInit();
     void UnloadModules();
 
     void CreateLoaderGlobal(JSContext* aCx,
                             const nsACString& aLocation,
                             JS::MutableHandleObject aGlobal);
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -3349,17 +3349,17 @@ XPCJSRuntime::DeleteSingletonScopes()
     mUnprivilegedJunkScope = nullptr;
     mLoaderGlobal = nullptr;
 }
 
 JSObject*
 XPCJSRuntime::LoaderGlobal()
 {
     if (!mLoaderGlobal) {
-        RefPtr<mozJSComponentLoader> loader = mozJSComponentLoader::GetOrCreate();
+        RefPtr<mozJSComponentLoader> loader = mozJSComponentLoader::Get();
 
         dom::AutoJSAPI jsapi;
         jsapi.Init();
 
         mLoaderGlobal = loader->GetSharedGlobal(jsapi.cx());
         MOZ_RELEASE_ASSERT(!JS_IsExceptionPending(jsapi.cx()));
     }
     return mLoaderGlobal;
--- a/js/xpconnect/src/XPCModule.h
+++ b/js/xpconnect/src/XPCModule.h
@@ -1,43 +1,36 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
 /* 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 "xpcprivate.h"
 #include "mozilla/ModuleUtils.h"
-#include "mozJSComponentLoader.h"
 #include "mozJSSubScriptLoader.h"
 
 /* Module implementation for the xpconnect library. */
 
 #define XPCVARIANT_CONTRACTID "@mozilla.org/xpcvariant;1"
 
 // {FE4F7592-C1FC-4662-AC83-538841318803}
 #define SCRIPTABLE_INTERFACES_CID                                             \
     {0xfe4f7592, 0xc1fc, 0x4662,                                              \
       { 0xac, 0x83, 0x53, 0x88, 0x41, 0x31, 0x88, 0x3 } }
 
 #define MOZJSSUBSCRIPTLOADER_CONTRACTID "@mozilla.org/moz/jssubscript-loader;1"
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSID)
-
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(mozJSComponentLoader,
-                                         mozJSComponentLoader::GetOrCreate);
 NS_GENERIC_FACTORY_CONSTRUCTOR(mozJSSubScriptLoader)
 
 NS_DEFINE_NAMED_CID(NS_JS_ID_CID);
-NS_DEFINE_NAMED_CID(MOZJSCOMPONENTLOADER_CID);
 NS_DEFINE_NAMED_CID(MOZ_JSSUBSCRIPTLOADER_CID);
 
 #define XPCONNECT_CIDENTRIES                                                  \
   { &kNS_JS_ID_CID, false, nullptr,  nsJSIDConstructor },                     \
-  { &kMOZJSCOMPONENTLOADER_CID, false, nullptr, mozJSComponentLoaderConstructor },\
   { &kMOZ_JSSUBSCRIPTLOADER_CID, false, nullptr, mozJSSubScriptLoaderConstructor },
 
 #define XPCONNECT_CONTRACTS                                                   \
-  { MOZJSCOMPONENTLOADER_CONTRACTID, &kMOZJSCOMPONENTLOADER_CID },            \
   { MOZJSSUBSCRIPTLOADER_CONTRACTID, &kMOZ_JSSUBSCRIPTLOADER_CID },
 
 nsresult xpcModuleCtor();
 void xpcModuleDtor();
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -147,27 +147,31 @@ nsXPConnect::InitStatics()
         MOZ_CRASH("InitSelfHostedCode failed");
     }
     if (!gSelf->mRuntime->InitializeStrings(cx)) {
         MOZ_CRASH("InitializeStrings failed");
     }
 
     // Initialize our singleton scopes.
     gSelf->mRuntime->InitSingletonScopes();
+
+    mozJSComponentLoader::InitStatics();
 }
 
 // static
 void
 nsXPConnect::ReleaseXPConnectSingleton()
 {
     nsXPConnect* xpc = gSelf;
     if (xpc) {
         nsrefcnt cnt;
         NS_RELEASE2(xpc, cnt);
     }
+
+    mozJSComponentLoader::Shutdown();
 }
 
 // static
 XPCJSRuntime*
 nsXPConnect::GetRuntimeInstance()
 {
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     return gSelf->mRuntime;
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -205,49 +205,45 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(Noti
 NS_GENERIC_FACTORY_CONSTRUCTOR(PushNotifier)
 
 //-----------------------------------------------------------------------------
 
 static bool gInitialized = false;
 
 // Perform our one-time intialization for this module
 
-static nsresult
-Initialize()
+void
+nsLayoutModuleInitialize()
 {
   if (gInitialized) {
     MOZ_CRASH("Recursive layout module initialization");
-    return NS_ERROR_FAILURE;
-  }
-  if (XRE_GetProcessType() == GeckoProcessType_GPU) {
-    // We mark the layout module as being available in the GPU process so that
-    // XPCOM's component manager initializes the power manager service, which
-    // is needed for nsAppShell. However, we don't actually need anything in
-    // the layout module itself.
-    return NS_OK;
   }
 
   static_assert(sizeof(uintptr_t) == sizeof(void*),
                 "Eeek! You'll need to adjust the size of uintptr_t to the "
                 "size of a pointer on your platform.");
 
   gInitialized = true;
 
-  nsresult rv;
-  rv = xpcModuleCtor();
-  if (NS_FAILED(rv))
-    return rv;
-
-  rv = nsLayoutStatics::Initialize();
-  if (NS_FAILED(rv)) {
-    Shutdown();
-    return rv;
+  if (XRE_GetProcessType() == GeckoProcessType_GPU) {
+    // We mark the layout module as being available in the GPU process so that
+    // XPCOM's component manager initializes the power manager service, which
+    // is needed for nsAppShell. However, we don't actually need anything in
+    // the layout module itself.
+    return;
   }
 
-  return NS_OK;
+  if (NS_FAILED(xpcModuleCtor())) {
+    MOZ_CRASH("xpcModuleCtor failed");
+  }
+
+  if (NS_FAILED(nsLayoutStatics::Initialize())) {
+    Shutdown();
+    MOZ_CRASH("nsLayoutStatics::Initialize failed");
+  }
 }
 
 // Shutdown this module, releasing all of the module resources
 
 // static
 void
 Shutdown()
 {
@@ -681,16 +677,24 @@ static const mozilla::Module::CategoryEn
   CONTENTDLF_CATEGORIES
   { "profile-after-change", "PresentationDeviceManager", PRESENTATION_DEVICE_MANAGER_CONTRACTID },
   { "profile-after-change", "PresentationService", PRESENTATION_SERVICE_CONTRACTID },
   { "profile-after-change", "Notification Telemetry Service", NOTIFICATIONTELEMETRYSERVICE_CONTRACTID },
   { nullptr }
   // clang-format on
 };
 
+static nsresult
+Initialize()
+{
+  // nsLayoutModuleInitialize should be called first.
+  MOZ_RELEASE_ASSERT(gInitialized);
+  return NS_OK;
+}
+
 static void
 LayoutModuleDtor()
 {
   if (XRE_GetProcessType() == GeckoProcessType_GPU) {
     return;
   }
 
   Shutdown();
new file mode 100644
--- /dev/null
+++ b/layout/build/nsLayoutModule.h
@@ -0,0 +1,17 @@
+/* -*- 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 nsLayoutModule_h
+#define nsLayoutModule_h
+
+#include "nscore.h"
+
+// This function initializes various layout statics, as well as XPConnect.
+// It should be called only once, and before the first time any XPCOM module in
+// nsLayoutModule is used.
+void nsLayoutModuleInitialize();
+
+#endif // nsLayoutModule_h
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -953,16 +953,69 @@ nsDisplayListBuilder::AutoCurrentActiveS
         descendantASR->mParent = asr;
       }
     }
   }
 
   mUsed = true;
 }
 
+/* static */ nsRect
+nsDisplayListBuilder::OutOfFlowDisplayData::ComputeVisibleRectForFrame(
+    nsDisplayListBuilder* aBuilder,
+    nsIFrame* aFrame,
+    const nsRect& aVisibleRect,
+    const nsRect& aDirtyRect,
+    nsRect* aOutDirtyRect)
+{
+  nsRect visible = aVisibleRect;
+  nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect;
+
+#ifdef MOZ_WIDGET_ANDROID
+  if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) &&
+      aBuilder->IsPaintingToWindow()) {
+    // We want to ensure that fixed position elements are visible when
+    // being async scrolled, so we paint them at the size of the larger
+    // viewport.
+    dirtyRectRelativeToDirtyFrame =
+      nsRect(nsPoint(0, 0), aFrame->GetParent()->GetSize());
+
+    nsIPresShell* ps = aFrame->PresShell();
+    if (ps->IsVisualViewportSizeSet() &&
+        dirtyRectRelativeToDirtyFrame.Size() <
+          ps->GetVisualViewportSize()) {
+      dirtyRectRelativeToDirtyFrame.SizeTo(ps->GetVisualViewportSize());
+    }
+
+    visible = dirtyRectRelativeToDirtyFrame;
+  }
+#endif
+
+  *aOutDirtyRect = dirtyRectRelativeToDirtyFrame - aFrame->GetPosition();
+  visible -= aFrame->GetPosition();
+
+  nsRect overflowRect = aFrame->GetVisualOverflowRect();
+
+  if (aFrame->IsTransformed() &&
+      mozilla::EffectCompositor::HasAnimationsForCompositor(
+        aFrame, eCSSProperty_transform)) {
+    /**
+     * Add a fuzz factor to the overflow rectangle so that elements only
+     * just out of view are pulled into the display list, so they can be
+     * prerendered if necessary.
+     */
+    overflowRect.Inflate(nsPresContext::CSSPixelsToAppUnits(32));
+  }
+
+  visible.IntersectRect(visible, overflowRect);
+  aOutDirtyRect->IntersectRect(*aOutDirtyRect, overflowRect);
+
+  return visible;
+}
+
 nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
                                            nsDisplayListBuilderMode aMode,
                                            bool aBuildCaret,
                                            bool aRetainingDisplayList)
   : mReferenceFrame(aReferenceFrame)
   , mIgnoreScrollFrame(nullptr)
   , mCompositorHitTestInfo(nullptr)
   , mCurrentTableItem(nullptr)
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1624,62 +1624,17 @@ public:
     const ActiveScrolledRoot* mContainingBlockActiveScrolledRoot;
     nsRect mVisibleRect;
     nsRect mDirtyRect;
 
     static nsRect ComputeVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
                                              nsIFrame* aFrame,
                                              const nsRect& aVisibleRect,
                                              const nsRect& aDirtyRect,
-                                             nsRect* aOutDirtyRect)
-    {
-      nsRect visible = aVisibleRect;
-      nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect;
-
-#ifdef MOZ_WIDGET_ANDROID
-      if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) &&
-          aBuilder->IsPaintingToWindow()) {
-        // We want to ensure that fixed position elements are visible when
-        // being async scrolled, so we paint them at the size of the larger
-        // viewport.
-        dirtyRectRelativeToDirtyFrame =
-          nsRect(nsPoint(0, 0), aFrame->GetParent()->GetSize());
-
-        nsIPresShell* ps = aFrame->PresShell();
-        if (ps->IsVisualViewportSizeSet() &&
-            dirtyRectRelativeToDirtyFrame.Size() <
-              ps->GetVisualViewportSize()) {
-          dirtyRectRelativeToDirtyFrame.SizeTo(ps->GetVisualViewportSize());
-        }
-
-        visible = dirtyRectRelativeToDirtyFrame;
-      }
-#endif
-
-      *aOutDirtyRect = dirtyRectRelativeToDirtyFrame - aFrame->GetPosition();
-      visible -= aFrame->GetPosition();
-
-      nsRect overflowRect = aFrame->GetVisualOverflowRect();
-
-      if (aFrame->IsTransformed() &&
-          mozilla::EffectCompositor::HasAnimationsForCompositor(
-            aFrame, eCSSProperty_transform)) {
-        /**
-         * Add a fuzz factor to the overflow rectangle so that elements only
-         * just out of view are pulled into the display list, so they can be
-         * prerendered if necessary.
-         */
-        overflowRect.Inflate(nsPresContext::CSSPixelsToAppUnits(32));
-      }
-
-      visible.IntersectRect(visible, overflowRect);
-      aOutDirtyRect->IntersectRect(*aOutDirtyRect, overflowRect);
-
-      return visible;
-    }
+                                             nsRect* aOutDirtyRect);
 
     nsRect GetVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
                                   nsIFrame* aFrame,
                                   nsRect* aDirtyRect)
     {
       return ComputeVisibleRectForFrame(
         aBuilder, aFrame, mVisibleRect, mDirtyRect, aDirtyRect);
     }
--- a/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
@@ -9,16 +9,17 @@ import org.mozilla.gecko.db.BrowserContr
 import org.mozilla.gecko.overlays.ui.ShareDialog;
 import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.util.ActivityResultHandler;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.FileUtils;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.IntentUtils;
+import org.mozilla.gecko.util.StrictModeContext;
 import org.mozilla.gecko.widget.ExternalIntentDuringPrivateBrowsingPromptFragment;
 
 import android.app.Activity;
 import android.content.ClipData;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -430,42 +431,52 @@ public final class IntentHelper implemen
         final Intent intent = getOpenURIIntent(getContext(),
                                                message.getString("url", ""),
                                                message.getString("mime", ""),
                                                message.getString("action", ""),
                                                message.getString("title", ""));
         callback.sendSuccess(getHandlersForIntent(intent));
     }
 
+    @SuppressWarnings("try")
     private void open(final GeckoBundle message) {
-        openUriExternal(message.getString("url", ""),
-                        message.getString("mime", ""),
-                        message.getString("packageName", ""),
-                        message.getString("className", ""),
-                        message.getString("action", ""),
-                        message.getString("title", ""), false);
+        // Bug 1450449 - this is most likely a document from the publicly accessible storage which
+        // isn't owned exclusively by Firefox, so there's no real benefit to using content:// URIs
+        // here.
+        try (StrictModeContext unused = StrictModeContext.allowAllVmPolicies()) {
+            openUriExternal(message.getString("url", ""),
+                            message.getString("mime", ""),
+                            message.getString("packageName", ""),
+                            message.getString("className", ""),
+                            message.getString("action", ""),
+                            message.getString("title", ""), false);
+        }
     }
 
+    @SuppressWarnings("try")
     private void openForResult(final GeckoBundle message, final EventCallback callback) {
         Intent intent = getOpenURIIntent(getContext(),
                                          message.getString("url", ""),
                                          message.getString("mime", ""),
                                          message.getString("action", ""),
                                          message.getString("title", ""));
         intent.setClassName(message.getString("packageName", ""),
                             message.getString("className", ""));
         intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
         final FragmentActivity activity = getActivity();
         if (activity == null) {
             callback.sendError(null);
             return;
         }
         final ResultHandler handler = new ResultHandler(callback);
-        try {
+        // Bug 1450449 - this is most likely a document from the publicly accessible storage which
+        // isn't owned exclusively by Firefox, so there's no real benefit to using content:// URIs
+        // here.
+        try (StrictModeContext unused = StrictModeContext.allowAllVmPolicies()) {
             ActivityHandlerHelper.startIntentForActivity(activity, intent, handler);
         } catch (SecurityException e) {
             Log.w(LOGTAG, "Forbidden to launch activity.", e);
         }
     }
 
     /**
      * Opens a URI without any valid handlers on device. In the best case, a package is specified
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
@@ -557,17 +557,17 @@ public final class GeckoRuntimeSettings 
     public Rect getScreenSizeOverride() {
         if ((mScreenWidthOverride > 0) && (mScreenHeightOverride > 0)) {
             return new Rect(0, 0, mScreenWidthOverride, mScreenHeightOverride);
         }
         return null;
     }
 
     /**
-     * Gets the locale code in Gecko format ("en" or "en-US").
+     * @return The locale code in Gecko format ("en" or "en-US").
      */
     public String getLocale() {
         return mLocale;
     }
 
     /**
      * Set the locale.
      *
new file mode 100644
--- /dev/null
+++ b/modules/libjar/test/mochitest/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/mochitest-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/modules/libjar/test/unit/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/xpcshell-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/modules/libjar/zipwriter/test/unit/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/xpcshell-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/modules/libmar/tests/unit/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/xpcshell-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/modules/libpref/test/unit/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/xpcshell-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/modules/libpref/test/unit_ipc/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/xpcshell-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/netwerk/cookie/test/browser/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/netwerk/test/browser/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/netwerk/test/mochitests/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/mochitest-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/.eslintrc.js
@@ -0,0 +1,8 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test",
+    "plugin:mozilla/mochitest-test",
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/parser/xml/test/unit/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/xpcshell-test",
+  ]
+};
--- a/python/mozbuild/mozbuild/controller/building.py
+++ b/python/mozbuild/mozbuild/controller/building.py
@@ -765,17 +765,18 @@ class CCacheStats(object):
     Instances can be subtracted from each other to obtain differences.
     print() or str() the object to show a ``ccache -s`` like output
     of the captured stats.
 
     """
     STATS_KEYS = [
         # (key, description)
         # Refer to stats.c in ccache project for all the descriptions.
-        ('stats_zero_time', 'stats zero time'),
+        ('stats_zeroed', 'stats zero time'), # Old name prior to ccache 3.4
+        ('stats_zeroed', 'stats zeroed'),
         ('stats_updated', 'stats updated'),
         ('cache_hit_direct', 'cache hit (direct)'),
         ('cache_hit_preprocessed', 'cache hit (preprocessed)'),
         ('cache_hit_rate', 'cache hit rate'),
         ('cache_miss', 'cache miss'),
         ('link', 'called for link'),
         ('preprocessing', 'called for preprocessing'),
         ('multiple', 'multiple source files'),
--- a/python/mozbuild/mozbuild/test/controller/test_ccachestats.py
+++ b/python/mozbuild/mozbuild/test/controller/test_ccachestats.py
@@ -194,16 +194,41 @@ class TestCcacheStats(unittest.TestCase)
     autoconf compile/link                348
     no input file                        162
     cleanups performed                    77
     files in cache                     13464
     cache size                           6.2 GB
     max cache size                       7.0 GB
     """.format(timestamp=time.strftime('%c'))
 
+    STAT9 = """
+    cache directory                     /Users/tlin/.ccache
+    primary config                      /Users/tlin/.ccache/ccache.conf
+    secondary config      (readonly)    /usr/local/Cellar/ccache/3.5/etc/ccache.conf
+    stats updated                       {timestamp}
+    stats zeroed                        {timestamp2}
+    cache hit (direct)                 80147
+    cache hit (preprocessed)           21413
+    cache miss                        191128
+    cache hit rate                     34.70 %
+    called for link                     5194
+    called for preprocessing            1721
+    compile failed                       825
+    preprocessor error                  3838
+    cache file missing                  4863
+    bad compiler arguments                32
+    autoconf compile/link               3554
+    unsupported code directive             4
+    no input file                       5545
+    cleanups performed                  3154
+    files in cache                     18525
+    cache size                          13.4 GB
+    max cache size                      15.0 GB
+    """.format(timestamp=time.strftime('%c'), timestamp2=time.strftime('%c'))
+
     def test_parse_garbage_stats_message(self):
         self.assertRaises(ValueError, CCacheStats, self.STAT_GARBAGE)
 
     def test_parse_zero_stats_message(self):
         stats = CCacheStats(self.STAT0)
         self.assertEqual(stats.cache_dir, "/home/tlin/.ccache")
         self.assertEqual(stats.hit_rates(), (0, 0, 0))
 
@@ -256,10 +281,15 @@ class TestCcacheStats(unittest.TestCase)
         stat7 = CCacheStats(self.STAT7)
         self.assertTrue(stat7)
 
     def test_stats_version34(self):
         # Test parsing 3.4 output.
         stat8 = CCacheStats(self.STAT8)
         self.assertTrue(stat8)
 
+    def test_stats_version35(self):
+        # Test parsing 3.5 output.
+        stat9 = CCacheStats(self.STAT9)
+        self.assertTrue(stat9)
+
 if __name__ == '__main__':
     main()
--- a/taskcluster/ci/artifact-build/kind.yml
+++ b/taskcluster/ci/artifact-build/kind.yml
@@ -28,17 +28,17 @@ jobs:
         run-on-projects: ['trunk', 'try']
         worker-type: aws-provisioner-v1/gecko-{level}-b-linux
         worker:
             max-run-time: 3600
             env:
                 PERFHERDER_EXTRA_OPTIONS: artifact
         run:
             using: mozharness
-            actions: [get-secrets build]
+            actions: [get-secrets, build]
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_sub_linux_configs/64_artifact.py
             script: "mozharness/scripts/fx_desktop_build.py"
             secrets: true
             tooltool-downloads: public
             need-xvfb: true
             keep-artifacts: false
--- a/taskcluster/ci/build/android-stuff.yml
+++ b/taskcluster/ci/build/android-stuff.yml
@@ -26,17 +26,17 @@ android-test/opt:
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/reports/tests
               type: directory
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: android-test
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -69,17 +69,17 @@ android-test-ccov/opt:
             PERFHERDER_EXTRA_OPTIONS: android-test-ccov
         artifacts:
             - name: public/code-coverage-grcov.zip
               path: /builds/worker/workspace/build/src/obj-firefox/code-coverage-grcov.zip
               type: file
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: android-test-ccov
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -119,17 +119,17 @@ android-lint/opt:
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/reports/lint-results-officialWithoutGeckoBinariesNoMinApiPhotonDebug_files
               type: directory
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: android-lint
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -173,17 +173,17 @@ android-checkstyle/opt:
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/reports/checkstyle/checkstyle.xml
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: android-checkstyle
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -223,17 +223,17 @@ android-findbugs/opt:
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/reports/findbugs/findbugs-officialWithoutGeckoBinariesNoMinApiPhotonDebug-output.xml
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: android-findbugs
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -268,17 +268,17 @@ android-geckoview-docs/opt:
             GECKOVIEW_DOCS_UPLOAD_SECRET: "project/releng/gecko/build/level-{level}/geckoview-docs-upload"
         artifacts:
             - name: public/android/geckoview-docs/geckoview-javadoc.jar
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/libs/geckoview-javadoc.jar
               type: file
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: android-geckoview-docs
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
--- a/taskcluster/ci/build/android.yml
+++ b/taskcluster/ci/build/android.yml
@@ -36,17 +36,17 @@ android-api-16/debug:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: api-16-debug
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -96,17 +96,17 @@ android-api-16-ccov/debug:
             - name: public/build/target.jacoco-cli.jar
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/coverage/target.jacoco-cli.jar
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: api-16-debug-ccov
         tooltool-downloads: internal
     run-on-projects: ['mozilla-central']
     toolchains:
@@ -154,17 +154,17 @@ android-x86/opt:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: x86
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -205,17 +205,17 @@ android-x86-fuzzing/debug:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: x86-fuzzing-debug
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -266,17 +266,17 @@ android-x86-nightly/opt:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: x86
         tooltool-downloads: internal
     toolchains:
@@ -324,17 +324,17 @@ android-api-16/opt:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: api-16
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -377,17 +377,17 @@ android-api-16-without-google-play-servi
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: api-16-without-google-play-services
         tooltool-downloads: internal
     run-on-projects: ['mozilla-central']
     toolchains:
@@ -439,17 +439,17 @@ android-api-16-nightly/opt:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: api-16
         tooltool-downloads: internal
     toolchains:
@@ -497,17 +497,17 @@ android-aarch64/opt:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: aarch64
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -558,17 +558,17 @@ android-aarch64-nightly/opt:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: aarch64
         tooltool-downloads: internal
     toolchains:
@@ -616,17 +616,17 @@ android-x86_64/opt:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: x86_64
         tooltool-downloads: internal
     toolchains:
         - android-gradle-dependencies
@@ -677,17 +677,17 @@ android-x86_64-nightly/opt:
             - name: public/build/geckoview_example.apk
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
-        actions: [get-secrets build multi-l10n]
+        actions: [get-secrets, build, multi-l10n]
         config:
             - builds/releng_base_android_64_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: x86_64
         tooltool-downloads: internal
     toolchains:
--- a/taskcluster/ci/build/linux.yml
+++ b/taskcluster/ci/build/linux.yml
@@ -8,17 +8,17 @@ linux64/opt:
     treeherder:
         platform: linux64/opt
         symbol: B
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
     toolchains:
@@ -73,17 +73,17 @@ linux64/pgo:
     treeherder:
         platform: linux64/pgo
         symbol: B
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         options: [enable-pgo]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
@@ -107,17 +107,17 @@ linux64-fuzzing/debug:
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
         env:
             PERFHERDER_EXTRA_OPTIONS: fuzzing
             FORCE_GCC: '1'
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: fuzzing-debug
         mozconfig-variant: debug-fuzzing
         tooltool-downloads: public
@@ -141,17 +141,17 @@ linux64/debug:
     treeherder:
         platform: linux64/debug
         symbol: B
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
@@ -212,17 +212,17 @@ linux64-devedition-nightly/opt:
     treeherder:
         platform: linux64-devedition/opt
         symbol: N
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: 'linux64-devedition'
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
@@ -250,17 +250,17 @@ linux64-base-toolchains/opt:
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
         env:
             PERFHERDER_EXTRA_OPTIONS: base-toolchains
             FORCE_GCC: '1'
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
     toolchains:
@@ -282,17 +282,17 @@ linux64-base-toolchains/debug:
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
         env:
             PERFHERDER_EXTRA_OPTIONS: base-toolchains
             FORCE_GCC: '1'
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
@@ -316,17 +316,17 @@ linux/opt:
         platform: linux32/opt
         symbol: B
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         docker-image: {in-tree: debian7-i386-build}
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
     toolchains:
@@ -349,17 +349,17 @@ linux/debug:
         platform: linux32/debug
         symbol: B
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         docker-image: {in-tree: debian7-i386-build}
         max-run-time: 3600
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
@@ -384,17 +384,17 @@ linux/pgo:
         platform: linux32/pgo
         symbol: B
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         docker-image: {in-tree: debian7-i386-build}
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         options: [enable-pgo]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
@@ -419,17 +419,17 @@ linux-rusttests/opt:
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         docker-image: {in-tree: debian7-i386-build}
         max-run-time: 5400
         env:
             PERFHERDER_EXTRA_OPTIONS: rusttests
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: rusttests
         mozconfig-variant: rusttests
         tooltool-downloads: public
@@ -456,17 +456,17 @@ linux-rusttests/debug:
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         docker-image: {in-tree: debian7-i386-build}
         max-run-time: 5400
         env:
             PERFHERDER_EXTRA_OPTIONS: rusttests
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: rusttests-debug
         mozconfig-variant: rusttests-debug
         tooltool-downloads: public
@@ -496,17 +496,17 @@ linux-devedition-nightly/opt:
         platform: linux32-devedition/opt
         symbol: N
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         docker-image: {in-tree: debian7-i386-build}
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: linux-devedition
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
@@ -538,17 +538,17 @@ linux-nightly/opt:
         platform: linux32/opt
         symbol: N
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         docker-image: {in-tree: debian7-i386-build}
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
@@ -571,17 +571,17 @@ linux64-asan/opt:
         symbol: Bo
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         env:
             PERFHERDER_EXTRA_OPTIONS: "opt asan"
         max-run-time: 3600
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: asan-tc
         mozconfig-variant: nightly-asan
         tooltool-downloads: public
@@ -605,17 +605,17 @@ linux64-asan-fuzzing/opt:
         symbol: Bof
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         env:
             PERFHERDER_EXTRA_OPTIONS: asan-fuzzing
         max-run-time: 3600
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: fuzzing-asan-tc
         mozconfig-variant: nightly-fuzzing-asan
         tooltool-downloads: public
@@ -640,17 +640,17 @@ linux64-asan-fuzzing-ccov/opt:
     run-on-projects: ['mozilla-central', 'try']
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         env:
             PERFHERDER_EXTRA_OPTIONS: asan-fuzzing-ccov
         max-run-time: 3600
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         mozconfig-variant: asan-fuzzing-ccov
         tooltool-downloads: public
         need-xvfb: true
@@ -675,17 +675,17 @@ linux64-fuzzing-ccov/opt:
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
         env:
             PERFHERDER_EXTRA_OPTIONS: fuzzing-ccov
             FORCE_GCC: '1'
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         mozconfig-variant: fuzzing-ccov
         tooltool-downloads: public
         need-xvfb: true
@@ -711,17 +711,17 @@ linux64-asan-reporter-nightly/opt:
         symbol: BoR
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         env:
             PERFHERDER_EXTRA_OPTIONS: asan-reporter
         max-run-time: 3600
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: asan-reporter-tc
         mozconfig-variant: nightly-asan-reporter
@@ -746,17 +746,17 @@ linux64-asan/debug:
         symbol: Bd
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         env:
             PERFHERDER_EXTRA_OPTIONS: "debug asan"
         max-run-time: 3600
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: asan-tc-and-debug
         mozconfig-variant: debug-asan
         tooltool-downloads: public
@@ -784,17 +784,17 @@ linux64-nightly/opt:
     treeherder:
         platform: linux64/opt
         symbol: N
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
@@ -816,17 +816,17 @@ linux64-noopt/debug:
         platform: linux64-noopt/debug
         symbol: B
         tier: 2
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: noopt-debug
         mozconfig-variant: noopt-debug
         tooltool-downloads: public
@@ -853,17 +853,17 @@ linux64-rusttests/opt:
         tier: 2
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 5400
         env:
             PERFHERDER_EXTRA_OPTIONS: rusttests
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: rusttests
         mozconfig-variant: rusttests
         tooltool-downloads: public
@@ -889,17 +889,17 @@ linux64-rusttests/debug:
         tier: 2
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 5400
         env:
             PERFHERDER_EXTRA_OPTIONS: rusttests
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: rusttests-debug
         mozconfig-variant: rusttests-debug
         tooltool-downloads: public
@@ -924,17 +924,17 @@ linux64-tup/opt:
         symbol: Btup
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
         env:
             PERFHERDER_EXTRA_OPTIONS: tup
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: tup
         mozconfig-variant: tup
         tooltool-downloads: public
@@ -960,17 +960,17 @@ linux64-ccov/debug:
     run-on-projects: ['mozilla-central', 'try']
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
         env:
             FORCE_GCC: '1'
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage-debug
         mozconfig-variant: code-coverage-debug
         tooltool-downloads: public
@@ -995,17 +995,17 @@ linux64-ccov/opt:
     run-on-projects: ['mozilla-central', 'try']
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
         env:
             FORCE_GCC: '1'
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage-opt
         mozconfig-variant: code-coverage-opt
         tooltool-downloads: public
@@ -1027,17 +1027,17 @@ linux64-add-on-devel/opt:
         platform: linux64-add-on-devel/opt
         symbol: B
         tier: 2
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
     run:
         using: mozharness
-        actions: [get-secrets build check-test]
+        actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: add-on-devel
         mozconfig-variant: add-on-devel
         tooltool-downloads: public
--- a/taskcluster/ci/build/macosx.yml
+++ b/taskcluster/ci/build/macosx.yml
@@ -11,17 +11,17 @@ macosx64/debug:
         tier: 1
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-debug
         mozconfig-variant: debug
         tooltool-downloads: internal
@@ -50,17 +50,17 @@ macosx64/opt:
         tier: 1
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: internal
     toolchains:
         - linux64-cctools-port
@@ -85,17 +85,17 @@ macosx64-asan-fuzzing/opt:
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
         env:
             PERFHERDER_EXTRA_OPTIONS: asan-fuzzing
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-fuzzing-asan
         mozconfig-variant: nightly-fuzzing-asan
         tooltool-downloads: internal
@@ -128,17 +128,17 @@ macosx64-devedition-nightly/opt:
         tier: 1
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: macosx64-devedition
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
@@ -168,17 +168,17 @@ macosx64-noopt/debug:
         tier: 2
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-noopt-debug
         mozconfig-variant: cross-noopt-debug
         tooltool-downloads: internal
@@ -207,17 +207,17 @@ macosx64-add-on-devel/opt:
         tier: 2
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 3600
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: add-on-devel
         mozconfig-variant: add-on-devel
         tooltool-downloads: internal
@@ -251,17 +251,17 @@ macosx64-nightly/opt:
         tier: 1
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 7200
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: internal
     toolchains:
@@ -287,17 +287,17 @@ macosx64-ccov/debug:
         tier: 1
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 5400
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
     run:
         using: mozharness
-        actions: [get-secrets build]
+        actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage-debug
         mozconfig-variant: code-coverage-debug
         tooltool-downloads: internal
--- a/taskcluster/ci/l10n/kind.yml
+++ b/taskcluster/ci/l10n/kind.yml
@@ -163,18 +163,16 @@ job-template:
                     - single_locale/tc_win64.py
                     - single_locale/onchange.py
                 android-api-16:
                     - single_locale/{project}_android-api-16.py
                     - single_locale/tc_common.py
                     - single_locale/tc_android-api-16.py
                     - single_locale/onchange.py
         # no default, so we fail on new entries
-        options:
-            - revision=$GECKO_HEAD_REV
         actions:
             by-build-platform:
                 default: ['clone-locales', 'list-locales', 'setup', 'repack',
                           'summary']
                 android-api-16: ['get-secrets',
                                  'clone-locales', 'list-locales', 'setup', 'repack',
                                  'upload-repacks', 'summary']
         script:
--- a/taskcluster/ci/nightly-l10n/kind.yml
+++ b/taskcluster/ci/nightly-l10n/kind.yml
@@ -218,18 +218,16 @@ job-template:
                     - single_locale/tc_win64.py
                     - taskcluster_nightly.py
                 android-api-16-nightly:
                     - taskcluster_nightly.py
                     - single_locale/{project}_android-api-16.py
                     - single_locale/tc_common.py
                     - single_locale/tc_android-api-16.py
         # no default, so we fail on new entries
-        options:
-            - revision=$GECKO_HEAD_REV
         actions:
             by-build-platform:
                 default: ['clone-locales', 'list-locales', 'setup', 'repack',
                           'summary']
                 android-api-16-nightly: ['get-secrets',
                                          'clone-locales', 'list-locales', 'setup', 'repack',
                                          'upload-repacks', 'summary']
         script:
--- a/taskcluster/ci/release-generate-checksums/kind.yml
+++ b/taskcluster/ci/release-generate-checksums/kind.yml
@@ -35,17 +35,17 @@ job-defaults:
            path: /builds/worker/SHA512SUMMARY
            type: file
          - name: public/build/SHA512SUMS
            path: /builds/worker/SHA512SUMS
            type: file
    run:
       using: mozharness
       config: []  # See extra-config below
-      actions: [create-virtualenv collect-individual-checksums create-big-checksums create-summary]
+      actions: [create-virtualenv, collect-individual-checksums, create-big-checksums, create-summary]
       options:
          - "version={version}"
          - "build-number={build_number}"
       script: "mozharness/scripts/release/generate-checksums.py"
    treeherder:
       symbol: Rel(GenChcks)
       kind: test
       tier: 1
--- a/taskcluster/ci/searchfox/kind.yml
+++ b/taskcluster/ci/searchfox/kind.yml
@@ -63,17 +63,17 @@ jobs:
             max-run-time: 36000
             env:
                 TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
                 PERFHERDER_EXTRA_OPTIONS: searchfox
                 RUSTC_BOOTSTRAP: "1"
                 MOZSEARCH_PLATFORM: "macosx"
         run:
             using: mozharness
-            actions: [get-secrets build]
+            actions: [get-secrets, build]
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_base_mac_64_cross_builds.py
             script: "mozharness/scripts/fx_desktop_build.py"
             custom-build-variant-cfg: cross-debug-searchfox
             secrets: true
             tooltool-downloads: internal
             keep-artifacts: false
--- a/taskcluster/ci/test/raptor.yml
+++ b/taskcluster/ci/test/raptor.yml
@@ -340,8 +340,31 @@ raptor-assorted-dom-chrome:
     max-run-time: 1500
     mozharness:
         extra-options:
             - --test=raptor-assorted-dom
             - --app=chrome
     fetches:
         fetch:
             - assorted-dom
+
+raptor-wasm-godot-firefox:
+    description: "Raptor Wasm GoDot on Firefox"
+    try-name: raptor-wasm-godot-firefox
+    treeherder-symbol: Rap(godot)
+    run-on-projects: ['try', 'mozilla-central']
+    tier: 2
+    max-run-time: 1500
+    mozharness:
+        extra-options:
+            - --test=raptor-wasm-godot
+
+raptor-wasm-godot-chrome:
+    description: "Raptor Wasm GoDot on Chrome"
+    try-name: raptor-wasm-godot-chrome
+    treeherder-symbol: Rap-C(godot)
+    run-on-projects: ['try', 'mozilla-central']
+    tier: 2
+    max-run-time: 1500
+    mozharness:
+        extra-options:
+            - --test=raptor-wasm-godot
+            - --app=chrome
--- a/taskcluster/ci/test/test-sets.yml
+++ b/taskcluster/ci/test/test-sets.yml
@@ -83,26 +83,28 @@ raptor-firefox:
     - raptor-tp6-firefox
     - raptor-speedometer-firefox
     - raptor-stylebench-firefox
     - raptor-motionmark-htmlsuite-firefox
     - raptor-motionmark-animometer-firefox
     - raptor-webaudio-firefox
     - raptor-gdocs-firefox
     - raptor-sunspider-firefox
+    - raptor-wasm-godot-firefox
 
 raptor-chrome:
     - raptor-tp6-chrome
     - raptor-speedometer-chrome
     - raptor-stylebench-chrome
     - raptor-motionmark-htmlsuite-chrome
     - raptor-motionmark-animometer-chrome
     - raptor-webaudio-chrome
     - raptor-gdocs-chrome
     - raptor-sunspider-chrome
+    - raptor-wasm-godot-firefox
 
 # Fetch tasks are only supported on Linux for now,
 # so these need to be separate sets.
 raptor-fetch-firefox:
     - raptor-unity-webgl-firefox
     - raptor-wasm-misc-firefox
     - raptor-wasm-misc-baseline-firefox
     - raptor-wasm-misc-ion-firefox
--- a/taskcluster/ci/valgrind/kind.yml
+++ b/taskcluster/ci/valgrind/kind.yml
@@ -28,17 +28,17 @@ jobs:
         worker-type: aws-provisioner-v1/gecko-{level}-b-linux
         worker:
             docker-image: {in-tree: valgrind-build}
             max-run-time: 72000
             env:
                 PERFHERDER_EXTRA_OPTIONS: valgrind
         run:
             using: mozharness
-            actions: [get-secrets build valgrind-test]
+            actions: [get-secrets, build, valgrind-test]
             custom-build-variant-cfg: valgrind
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_base_linux_64_builds.py
             script: "mozharness/scripts/fx_desktop_build.py"
             secrets: true
             tooltool-downloads: public
             need-xvfb: true
--- a/taskcluster/taskgraph/transforms/job/mozharness.py
+++ b/taskcluster/taskgraph/transforms/job/mozharness.py
@@ -10,16 +10,17 @@ way, and certainly anything using mozhar
 
 from __future__ import absolute_import, print_function, unicode_literals
 import json
 
 from textwrap import dedent
 
 from taskgraph.util.schema import Schema
 from voluptuous import Required, Optional, Any
+from voluptuous.validators import Match
 
 from taskgraph.transforms.job import run_job_using
 from taskgraph.transforms.job.common import (
     docker_worker_add_workspace_cache,
     docker_worker_setup_secrets,
     docker_worker_add_artifacts,
     docker_worker_add_tooltool,
     generic_worker_add_artifacts,
@@ -39,20 +40,26 @@ mozharness_run_schema = Schema({
     Optional('config-paths'): [basestring],
 
     # the config files required for the task, relative to
     # testing/mozharness/configs or one of the paths specified in
     # `config-paths` and using forward slashes even on Windows
     Required('config'): [basestring],
 
     # any additional actions to pass to the mozharness command
-    Optional('actions'): [basestring],
+    Optional('actions'): [Match(
+        '^[a-z0-9-]+$',
+        "actions must be `-` seperated alphanumeric strings"
+    )],
 
     # any additional options (without leading --) to be passed to mozharness
-    Optional('options'): [basestring],
+    Optional('options'): [Match(
+        '^[a-z0-9-]+(=[^ ]+)?$',
+        "options must be `-` seperated alphanumeric strings (with optional argument)"
+    )],
 
     # --custom-build-variant-cfg value
     Optional('custom-build-variant-cfg'): basestring,
 
     # Extra configuration options to pass to mozharness.
     Optional('extra-config'): dict,
 
     # Extra metadata to use toward the workspace caching.
@@ -285,21 +292,19 @@ def mozharness_on_generic_worker(config,
                               r'.\build\src\{}'.format(path.replace('/', '\\')))
 
     for cfg in run['config']:
         mh_command.append('--config ' + cfg.replace('/', '\\'))
     if run['use-magic-mh-args']:
         mh_command.append('--branch ' + config.params['project'])
     mh_command.append(r'--work-dir %cd:Z:=z:%\build')
     for action in run.get('actions', []):
-        assert ' ' not in action
         mh_command.append('--' + action)
 
     for option in run.get('options', []):
-        assert ' ' not in option
         mh_command.append('--' + option)
     if run.get('custom-build-variant-cfg'):
         mh_command.append('--custom-build-variant')
         mh_command.append(run['custom-build-variant-cfg'])
 
     hg_commands = generic_worker_hg_commands(
         base_repo=env['GECKO_BASE_REPOSITORY'],
         head_repo=env['GECKO_HEAD_REPOSITORY'],
--- a/taskcluster/taskgraph/transforms/l10n.py
+++ b/taskcluster/taskgraph/transforms/l10n.py
@@ -67,17 +67,17 @@ l10n_description_schema = Schema({
         # Config files passed to the mozharness script
         Required('config'): _by_platform([basestring]),
 
         # Additional paths to look for mozharness configs in. These should be
         # relative to the base of the source checkout
         Optional('config-paths'): [basestring],
 
         # Options to pass to the mozharness script
-        Required('options'): _by_platform([basestring]),
+        Optional('options'): _by_platform([basestring]),
 
         # Action commands to provide to mozharness script
         Required('actions'): _by_platform([basestring]),
 
         # if true, perform a checkout of a comm-central based branch inside the
         # gecko checkout
         Required('comm-checkout', default=False): bool,
     },
--- a/testing/mozharness/configs/single_locale/mozilla-esr60.py
+++ b/testing/mozharness/configs/single_locale/mozilla-esr60.py
@@ -16,16 +16,15 @@ config = {
     "repos": [{
         "vcs": "hg",
         "repo": "https://hg.mozilla.org/build/tools",
         "branch": "default",
         "dest": "tools",
     }, {
         "vcs": "hg",
         "repo": "https://hg.mozilla.org/releases/mozilla-esr60",
-        "revision": "%(revision)s",
         "dest": "mozilla-esr60",
         "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
     }],
     # purge options
     'purge_minsize': 12,
     'is_automation': True,
 }
--- a/testing/mozharness/mozharness/mozilla/building/buildbase.py
+++ b/testing/mozharness/mozharness/mozilla/building/buildbase.py
@@ -997,35 +997,16 @@ or run without that action (ie: --no-{ac
         if cache:
             cmd.extend(['--cache-dir', cache])
         if toolchains:
             cmd.extend(toolchains.split())
         self.info(str(cmd))
         self.run_command(cmd, cwd=dirs['abs_src_dir'], halt_on_failure=True,
                          env=env)
 
-    def query_revision(self, source_path=None):
-        """ returns the revision of the build
-
-         This method is used both to figure out what revision to check out and
-         to figure out what revision *was* checked out.
-        """
-        revision = None
-        if not source_path:
-            dirs = self.query_abs_dirs()
-            source_path = dirs['abs_src_dir']  # let's take the default
-
-        # Look at what we have checked out
-        if os.path.exists(source_path):
-            hg = self.query_exe('hg', return_type='list')
-            revision = self.get_output_from_command(
-                hg + ['parent', '--template', '{node}'], cwd=source_path
-            )
-        return revision.encode('ascii', 'replace') if revision else None
-
     def generate_build_props(self, console_output=True, halt_on_failure=False):
         """sets props found from mach build and, in addition, buildid,
         sourcestamp,  appVersion, and appName."""
 
         error_level = ERROR
         if halt_on_failure:
             error_level = FATAL
 
--- a/testing/mozharness/scripts/desktop_l10n.py
+++ b/testing/mozharness/scripts/desktop_l10n.py
@@ -45,17 +45,17 @@ FAILURE_STR = "Failed"
 
 # mandatory configuration options, without them, this script will not work
 # it's a list of values that are already known before starting a build
 configuration_tokens = ('branch', 'update_channel')
 
 # some other values such as "%(version)s", ...
 # are defined at run time and they cannot be enforced in the _pre_config_lock
 # phase
-runtime_config_tokens = ('version', 'locale', 'abs_objdir', 'revision',
+runtime_config_tokens = ('version', 'locale', 'abs_objdir',
                          'en_us_installer_binary_url')
 
 
 # DesktopSingleLocale {{{1
 class DesktopSingleLocale(LocalesMixin, AutomationMixin,
                           VCSMixin, BaseScript, MarMixin):
     """Manages desktop repacks"""
     config_options = [[
@@ -67,23 +67,16 @@ class DesktopSingleLocale(LocalesMixin, 
                  " revision separated by colon, en-GB:default."}
     ], [
         ['--tag-override', ],
         {"action": "store",
          "dest": "tag_override",
          "type": "string",
          "help": "Override the tags set for all repos"}
     ], [
-        ['--revision', ],
-        {"action": "store",
-         "dest": "revision",
-         "type": "string",
-         "help": "Override the gecko revision to use (otherwise use automation supplied"
-                 " value, or en-US revision) "}
-    ], [
         ['--en-us-installer-url', ],
         {"action": "store",
          "dest": "en_us_installer_url",
          "type": "string",
          "help": "Specify the url of the en-us binary"}
     ], [
         ['--scm-level'], {  # Ignored on desktop for now: see Bug 1414678.
          "action": "store",
@@ -117,17 +110,16 @@ class DesktopSingleLocale(LocalesMixin, 
             self,
             config_options=self.config_options,
             require_config_file=require_config_file,
             **buildscript_kwargs
         )
 
         self.bootstrap_env = None
         self.upload_env = None
-        self.revision = None
         self.upload_urls = {}
         self.pushdate = None
         # upload_files is a dictionary of files to upload, keyed by locale.
         self.upload_files = {}
 
     def _pre_config_lock(self, rw_config):
         """replaces 'configuration_tokens' with their values, before the
            configuration gets locked. If some of the configuration_tokens
@@ -278,37 +270,16 @@ class DesktopSingleLocale(LocalesMixin, 
         self.upload_env = upload_env
         return self.upload_env
 
     def query_l10n_env(self):
         l10n_env = self._query_upload_env().copy()
         l10n_env.update(self.query_bootstrap_env())
         return l10n_env
 
-    def _query_revision(self):
-        """ Get the gecko revision in this order of precedence
-              * cached value
-              * command line arg --revision   (development, taskcluster)
-              * from the en-US build          (m-c & m-a)
-
-        This will fail the last case if the build hasn't been pulled yet.
-        """
-        if self.revision:
-            return self.revision
-
-        config = self.config
-        revision = None
-        if config.get("revision"):
-            revision = config["revision"]
-
-        if not revision:
-            self.fatal("Can't determine revision!")
-        self.revision = str(revision)
-        return self.revision
-
     def _query_make_variable(self, variable, make_args=None):
         """returns the value of make echo-variable-<variable>
            it accepts extra make arguements (make_args)
         """
         dirs = self.query_abs_dirs()
         make_args = make_args or []
         target = ["echo-variable-%s" % variable] + make_args
         cwd = dirs['abs_locales_dir']
--- a/testing/mozharness/scripts/mobile_l10n.py
+++ b/testing/mozharness/scripts/mobile_l10n.py
@@ -46,23 +46,16 @@ class MobileSingleLocale(LocalesMixin, T
     ], [
         ['--tag-override', ],
         {"action": "store",
          "dest": "tag_override",
          "type": "string",
          "help": "Override the tags set for all repos"
          }
     ], [
-        ['--revision', ],
-        {"action": "store",
-         "dest": "revision",
-         "type": "string",
-         "help": "Override the gecko revision to use (otherwise use automation supplied"
-                 " value, or en-US revision) "}
-    ], [
         ['--scm-level'],
         {"action": "store",
          "type": "int",
          "dest": "scm_level",
          "default": 1,
          "help": "This sets the SCM level for the branch being built."
                  " See https://www.mozilla.org/en-US/about/"
                  "governance/policies/commit/access-policy/"}
@@ -86,17 +79,16 @@ class MobileSingleLocale(LocalesMixin, T
         MercurialScript.__init__(
             self,
             config_options=self.config_options,
             require_config_file=require_config_file,
             **buildscript_kwargs
         )
         self.base_package_name = None
         self.repack_env = None
-        self.revision = None
         self.upload_env = None
         self.upload_urls = {}
 
     # Helper methods {{{2
     def query_repack_env(self):
         if self.repack_env:
             return self.repack_env
         c = self.config
@@ -123,36 +115,16 @@ class MobileSingleLocale(LocalesMixin, T
         if self.upload_env:
             return self.upload_env
 
         upload_env = self.query_env(partial_env=self.config.get("upload_env"),
                                     replace_dict=dict(self.config))
         self.upload_env = upload_env
         return self.upload_env
 
-    def query_revision(self):
-        """ Get the gecko revision in this order of precedence
-              * cached value
-              * command line arg --revision   (development, taskcluster)
-              * from the en-US build          (m-c & m-a)
-
-        This will fail the last case if the build hasn't been pulled yet.
-        """
-        if self.revision:
-            return self.revision
-
-        config = self.config
-        revision = None
-        if config.get("revision"):
-            revision = config["revision"]
-        if not revision:
-            self.fatal("Can't determine revision!")
-        self.revision = str(revision)
-        return self.revision
-
     def _query_make_variable(self, variable, make_args=None):
         make = self.query_exe('make')
         env = self.query_repack_env()
         dirs = self.query_abs_dirs()
         if make_args is None:
             make_args = []
         # TODO error checking
         output = self.get_output_from_command(
--- a/testing/raptor/raptor/manifest.py
+++ b/testing/raptor/raptor/manifest.py
@@ -98,16 +98,20 @@ def write_test_settings_json(test_detail
     val = test_details.get('subtest_unit', test_settings['raptor-options']['unit'])
     test_settings['raptor-options']['subtest_unit'] = val
     val = test_details.get('subtest_lower', test_settings['raptor-options']['lower_is_better'])
     test_settings['raptor-options']['subtest_lower_is_better'] = val
 
     if test_details.get("alert_threshold", None) is not None:
         test_settings['raptor-options']['alert_threshold'] = float(test_details['alert_threshold'])
 
+    if test_details.get("newtab_per_cycle", None) is not None:
+        test_settings['raptor-options']['newtab_per_cycle'] = \
+            bool(test_details['newtab_per_cycle'])
+
     settings_file = os.path.join(tests_dir, test_details['name'] + '.json')
     try:
         with open(settings_file, 'w') as out_file:
             json.dump(test_settings, out_file, indent=4, ensure_ascii=False)
             out_file.close()
     except IOError:
         LOG.info("abort: exception writing test settings json!")
 
--- a/testing/raptor/raptor/output.py
+++ b/testing/raptor/raptor/output.py
@@ -112,16 +112,18 @@ class Output(object):
                 elif 'webaudio' in test.measurements:
                     subtests, vals = self.parseWebaudioOutput(test)
                 elif 'unity-webgl' in test.measurements:
                     subtests, vals = self.parseUnityWebGLOutput(test)
                 elif 'assorted-dom' in test.measurements:
                     subtests, vals = self.parseAssortedDomOutput(test)
                 elif 'wasm-misc' in test.measurements:
                     subtests, vals = self.parseWASMMiscOutput(test)
+                elif 'wasm-godot' in test.measurements:
+                    subtests, vals = self.parseWASMGoDotOutput(test)
                 suite['subtests'] = subtests
 
             else:
                 LOG.error("output.summarize received unsupported test results type")
                 return
 
             # for pageload tests, if there are > 1 subtests here, that means there
             # were multiple measurements captured in each single pageload; we want
@@ -212,16 +214,55 @@ class Output(object):
         names.sort(reverse=True)
         for name in names:
             _subtests[name]['value'] = filter.median(_subtests[name]['replicates'])
             subtests.append(_subtests[name])
             vals.append([_subtests[name]['value'], name])
 
         return subtests, vals
 
+    def parseWASMGoDotOutput(self, test):
+        '''
+            {u'wasm-godot': [
+                {
+                  "name": "wasm-instantiate",
+                  "time": 349
+                },{
+                  "name": "engine-instantiate",
+                  "time": 1263
+                ...
+                }]}
+        '''
+        _subtests = {}
+        data = test.measurements['wasm-godot']
+        print (data)
+        for page_cycle in data:
+            for item in page_cycle[0]:
+                # for each pagecycle, build a list of subtests and append all related replicates
+                sub = item['name']
+                if sub not in _subtests.keys():
+                    # subtest not added yet, first pagecycle, so add new one
+                    _subtests[sub] = {'unit': test.subtest_unit,
+                                      'alertThreshold': float(test.alert_threshold),
+                                      'lowerIsBetter': test.subtest_lower_is_better,
+                                      'name': sub,
+                                      'replicates': []}
+                _subtests[sub]['replicates'].append(item['time'])
+
+        vals = []
+        subtests = []
+        names = _subtests.keys()
+        names.sort(reverse=True)
+        for name in names:
+            _subtests[name]['value'] = filter.median(_subtests[name]['replicates'])
+            subtests.append(_subtests[name])
+            vals.append([_subtests[name]['value'], name])
+
+        return subtests, vals
+
     def parseWebaudioOutput(self, test):
         # each benchmark 'index' becomes a subtest; each pagecycle / iteration
         # of the test has multiple values per index/subtest
 
         # this is the format we receive the results in from the benchmark
         # i.e. this is ONE pagecycle of speedometer:
 
         # {u'name': u'raptor-webaudio-firefox', u'type': u'benchmark', u'measurements':
@@ -519,16 +560,24 @@ class Output(object):
     def wasm_misc_score(cls, val_list):
         """
         wasm_misc_score: self reported as '__total__'
         """
         results = [i for i, j in val_list if j == '__total__']
         return filter.mean(results)
 
     @classmethod
+    def wasm_godot_score(cls, val_list):
+        """
+        wasm_godot_score: first-interactive mean
+        """
+        results = [i for i, j in val_list if j == 'first-interactive']
+        return filter.mean(results)
+
+    @classmethod
     def stylebench_score(cls, val_list):
         """
         stylebench_score: https://bug-172968-attachments.webkit.org/attachment.cgi?id=319888
         """
         correctionFactor = 3
         results = [i for i, j in val_list]
 
         # stylebench has 5 tests, each of these are made of up 5 subtests
@@ -596,12 +645,14 @@ class Output(object):
         elif testname.startswith('raptor-unity-webgl'):
             return self.unity_webgl_score(vals)
         elif testname.startswith('raptor-webaudio'):
             return self.webaudio_score(vals)
         elif testname.startswith('raptor-assorted-dom'):
             return self.assorted_dom_score(vals)
         elif testname.startswith('raptor-wasm-misc'):
             return self.wasm_misc_score(vals)
+        elif testname.startswith('raptor-wasm-godot'):
+            return self.wasm_godot_score(vals)
         elif len(vals) > 1:
             return round(filter.geometric_mean([i for i, j in vals]), 2)
         else:
             return round(filter.mean([i for i, j in vals]), 2)
--- a/testing/raptor/raptor/raptor.ini
+++ b/testing/raptor/raptor/raptor.ini
@@ -6,9 +6,10 @@
 [include:tests/raptor-motionmark-htmlsuite.ini]
 [include:tests/raptor-motionmark-animometer.ini]
 [include:tests/raptor-unity-webgl.ini]
 [include:tests/raptor-webaudio.ini]
 [include:tests/raptor-gdocs.ini]
 [include:tests/raptor-wasm-misc.ini]
 [include:tests/raptor-wasm-misc-baseline.ini]
 [include:tests/raptor-wasm-misc-ion.ini]
+[include:tests/raptor-wasm-godot.ini]
 [include:tests/raptor-assorted-dom.ini]
new file mode 100644
--- /dev/null
+++ b/testing/raptor/raptor/tests/raptor-wasm-godot.ini
@@ -0,0 +1,21 @@
+# 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/.
+
+# Wasm-godot benchmark for firefox and chrome
+
+[DEFAULT]
+type =  benchmark
+test_url = http://localhost:<port>/wasm-godot/index.html
+page_cycles = 5
+page_timeout = 120000
+unit = ms
+lower_is_better = true
+alert_threshold = 2.0
+newtab_per_cycle = true
+
+[raptor-wasm-godot-firefox]
+apps = firefox
+
+[raptor-wasm-godot-chrome]
+apps = chrome
--- a/testing/raptor/webext/raptor/manifest.json
+++ b/testing/raptor/webext/raptor/manifest.json
@@ -22,16 +22,17 @@
     {
       "matches": ["*://*/Speedometer/index.html*",
                   "*://*/StyleBench/*",
                   "*://*/MotionMark/*",
                   "*://*/SunSpider/*",
                   "*://*/webaudio/*",
                   "*://*/unity-webgl/index.html*",
                   "*://*/wasm-misc/index.html*",
+                  "*://*/wasm-godot/index.html*",
                   "*://*/assorted-dom/assorted/results.html*"],
       "js": ["benchmark-relay.js"]
     }
   ],
   "permissions": [
     "<all_urls>",
     "tabs",
     "storage",
--- a/testing/raptor/webext/raptor/runner.js
+++ b/testing/raptor/webext/raptor/runner.js
@@ -17,16 +17,19 @@
 
 // when the browser starts this webext runner will start automatically; we
 // want to give the browser some time (ms) to settle before starting tests
 var postStartupDelay = 30000;
 
 // delay (ms) between pageload cycles
 var pageCycleDelay = 1000;
 
+var newTabDelay = 1000;
+var reuseTab = false;
+
 var browserName;
 var ext;
 var testName = null;
 var settingsURL = null;
 var csPort = null;
 var benchmarkPort = null;
 var testType;
 var pageCycles = 0;
@@ -82,16 +85,20 @@ function getTestSettings() {
         results.type = testType;
         results.name = testName;
         results.unit = settings.unit;
         results.subtest_unit = settings.subtest_unit;
         results.lower_is_better = settings.lower_is_better === true;
         results.subtest_lower_is_better = settings.subtest_lower_is_better === true;
         results.alert_threshold = settings.alert_threshold;
 
+        if (settings.newtab_per_cycle !== undefined) {
+          reuseTab = settings.newtab_per_cycle;
+        }
+
         if (settings.page_timeout !== undefined) {
           pageTimeout = settings.page_timeout;
         }
         console.log("using page timeout (ms): " + pageTimeout);
 
         if (testType == "pageload") {
           if (settings.measure !== undefined) {
             if (settings.measure.fnbpaint !== undefined) {
@@ -160,22 +167,26 @@ function getBrowserInfo() {
       console.log("testing on " + results.browser);
       resolve();
     }
   });
 }
 
 function testTabCreated(tab) {
   testTabID = tab.id;
-  console.log("opened new empty tab " + testTabID);
-  nextCycle();
+  postToControlServer("status", "opened new empty tab " + testTabID);
+}
+
+function testTabRemoved(tab) {
+  postToControlServer("status", "Removed tab " + testTabID);
+  testTabID = 0;
 }
 
 async function testTabUpdated(tab) {
-  console.log("test tab updated");
+  postToControlServer("status", "test tab updated " + testTabID);
   // wait for pageload test result from content
   await waitForResult();
   // move on to next cycle (or test complete)
   nextCycle();
 }
 
 function waitForResult() {
   console.log("awaiting results...");
@@ -227,22 +238,35 @@ function nextCycle() {
           isFCPPending = true;
         if (getDCF)
           isDCFPending = true;
         if (getTTFI)
           isTTFIPending = true;
       } else if (testType == "benchmark") {
         isBenchmarkPending = true;
       }
-      // update the test page - browse to our test URL
-      ext.tabs.update(testTabID, {url: testURL}, testTabUpdated);
-    }, pageCycleDelay);
-  } else {
-    verifyResults();
-  }
+
+      if (reuseTab && testTabID != 0) {
+        // close previous test tab
+        ext.tabs.remove(testTabID);
+        postToControlServer("status", "closing Tab " + testTabID);
+
+        // open new tab
+        ext.tabs.create({url: "about:blank"});
+        postToControlServer("status", "Open new tab");
+      }
+      setTimeout(function() {
+        postToControlServer("status", "update tab " + testTabID);
+        // update the test page - browse to our test URL
+        ext.tabs.update(testTabID, {url: testURL}, testTabUpdated);
+        }, newTabDelay);
+      }, pageCycleDelay);
+    } else {
+      verifyResults();
+    }
 }
 
 function timeoutAlarmListener() {
   console.error("raptor-page-timeout on %s" % testURL);
   postToControlServer("raptor-page-timeout", [testName, testURL]);
   // call clean-up to shutdown gracefully
   cleanUp();
 }
@@ -397,29 +421,38 @@ function runner() {
         // webkit benchmark type of test
         console.log("benchmark test start");
       } else if (testType == "pageload") {
         // standard pageload test
         console.log("pageloader test start");
       }
       // results listener
       ext.runtime.onMessage.addListener(resultListener);
+
       // tab creation listener
       ext.tabs.onCreated.addListener(testTabCreated);
+
+      // tab remove listener
+      ext.tabs.onRemoved.addListener(testTabRemoved);
+
       // timeout alarm listener
       ext.alarms.onAlarm.addListener(timeoutAlarmListener);
 
       // create new empty tab, which starts the test; we want to
       // wait some time for the browser to settle before beginning
       var text = "* pausing " + postStartupDelay / 1000 + " seconds to let browser settle... *";
       postToControlServer("status", text);
 
+      // setTimeout(function() { nextCycle(); }, postStartupDelay);
       // on geckoview you can't create a new tab; only using existing tab - set it blank first
       if (config.browser == "geckoview") {
         setTimeout(function() { nextCycle(); }, postStartupDelay);
       } else {
-        setTimeout(function() { ext.tabs.create({url: "about:blank"}); }, postStartupDelay);
+        setTimeout(function() {
+          ext.tabs.create({url: "about:blank"});
+          nextCycle();
+        }, postStartupDelay);
       }
     });
   });
 }
 
 window.onload = runner();
--- a/testing/web-platform/tests/audio-output/setSinkId.html
+++ b/testing/web-platform/tests/audio-output/setSinkId.html
@@ -34,11 +34,11 @@ promise_test(async t => {
       r = await audio.setSinkId(deviceId);
       assert_equals(r, undefined, "resetting sinkid on same current value should always work");
       r = await audio.setSinkId("");
       assert_equals(r, undefined, "resetting sinkid on default audio output should always work");
     } catch (e) {
       assert_equals(e.name, "NotAllowedError", "Non-default devices are failing with NotAllowed error");
     }
   }
-}, "List device, setSinkId should on the default, the rest of the devices will get a NotAlowedError");
+}, "List device, setSinkId should be allowed on the default, the rest of the devices will get a NotAllowedError");
 
 </script>
--- a/testing/web-platform/tests/audio-output/setSinkId.https.html
+++ b/testing/web-platform/tests/audio-output/setSinkId.https.html
@@ -36,11 +36,11 @@ promise_test(async t => {
       r = await audio.setSinkId(deviceId);
       assert_equals(r, undefined, "resetting sinkid on same current value should always work");
       r = await audio.setSinkId("");
       assert_equals(r, undefined, "resetting sinkid on default audio output should always work");
     } catch (e) {
       assert_equals(e.name, "NotAllowedError", "Non-default devices are failing with NotAllowed error");
     }
   }
-}, "List device, setSinkId should on the default, the rest of the devices will get a NotAlowedError");
+}, "List device, setSinkId should be allowed on the default, the rest of the devices will get a NotAllowedError");
 
 </script>
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -1472,43 +1472,39 @@ function run_next_test() {
 
   if (_gRunningTest !== null) {
     // Close the previous test do_test_pending call.
     do_test_finished(_gRunningTest.name);
   }
 }
 
 try {
+  // Set global preferences
   if (runningInParent) {
     // Always use network provider for geolocation tests
     // so we bypass the OSX dialog raised by the corelocation provider
     _Services.prefs.setBoolPref("geo.provider.testing", true);
-  }
-} catch (e) { }
-// We need to avoid hitting the network with certain components.
-try {
-  if (runningInParent) {
+
+    // We need to avoid hitting the network with certain components.
     _Services.prefs.setCharPref("media.gmp-manager.url.override", "http://%(server)s/dummy-gmp-manager.xml");
     _Services.prefs.setCharPref("media.gmp-manager.updateEnabled", false);
     _Services.prefs.setCharPref("extensions.systemAddon.update.url", "http://%(server)s/dummy-system-addons.xml");
     _Services.prefs.setCharPref("app.normandy.api_url", "https://%(server)s/selfsupport-dummy/");
     _Services.prefs.setCharPref("toolkit.telemetry.server", "https://%(server)s/telemetry-dummy");
     _Services.prefs.setCharPref("browser.search.geoip.url", "https://%(server)s/geoip-dummy");
     _Services.prefs.setCharPref("browser.safebrowsing.downloads.remote.url", "https://%(server)s/safebrowsing-dummy");
-  }
-} catch (e) { }
 
-// Make tests run consistently on DevEdition (which has a lightweight theme
-// selected by default).
-try {
-  if (runningInParent) {
+    // Make tests run consistently on DevEdition (which has a lightweight theme
+    // selected by default).
     _Services.prefs.deleteBranch("lightweightThemes.selectedThemeID");
     _Services.prefs.deleteBranch("browser.devedition.theme.enabled");
   }
-} catch (e) { }
+} catch (e) {
+  do_throw(e);
+}
 
 function _load_mozinfo() {
   let mozinfoFile = Cc["@mozilla.org/file/local;1"]
     .createInstance(Ci.nsIFile);
   mozinfoFile.initWithPath(_MOZINFO_JS_PATH);
   let stream = Cc["@mozilla.org/network/file-input-stream;1"]
     .createInstance(Ci.nsIFileInputStream);
   stream.init(mozinfoFile, -1, 0, 0);
--- a/testing/xpcshell/remotexpcshelltests.py
+++ b/testing/xpcshell/remotexpcshelltests.py
@@ -124,29 +124,27 @@ class RemoteXPCShellTestThread(xpcshell.
     def buildXpcsCmd(self):
         # change base class' paths to remote paths and use base class to build command
         self.xpcshell = posixpath.join(self.remoteBinDir, "xpcw")
         self.headJSPath = posixpath.join(self.remoteScriptsDir, 'head.js')
         self.httpdJSPath = posixpath.join(self.remoteComponentsDir, 'httpd.js')
         self.httpdManifest = posixpath.join(self.remoteComponentsDir, 'httpd.manifest')
         self.testingModulesDir = self.remoteModulesDir
         self.testharnessdir = self.remoteScriptsDir
-        xpcshell.XPCShellTestThread.buildXpcsCmd(self)
+        xpcsCmd = xpcshell.XPCShellTestThread.buildXpcsCmd(self)
         # remove "-g <dir> -a <dir>" and add "--greomni <apk>"
-        del(self.xpcsCmd[1:5])
+        del xpcsCmd[1:5]
         if self.options['localAPK']:
-            self.xpcsCmd.insert(3, '--greomni')
-            self.xpcsCmd.insert(4, self.remoteAPK)
+            xpcsCmd.insert(3, '--greomni')
+            xpcsCmd.insert(4, self.remoteAPK)
 
         if self.remoteDebugger:
             # for example, "/data/local/gdbserver" "localhost:12345"
-            self.xpcsCmd = [
-              self.remoteDebugger,
-              self.remoteDebuggerArgs,
-              self.xpcsCmd]
+            xpcsCmd = [self.remoteDebugger, self.remoteDebuggerArgs] + xpcsCmd
+        return xpcsCmd
 
     def killTimeout(self, proc):
         self.kill(proc)
 
     def launchProcess(self, cmd, stdout, stderr, env, cwd, timeout=None):
         self.timedout = False
         cmd.insert(1, self.remoteHere)
         cmd = ADBDevice._escape_command_line(cmd)
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -163,17 +163,17 @@ class XPCShellTestThread(Thread):
         self.todoCount = 0
         self.failCount = 0
 
         # Context for output processing
         self.output_lines = []
         self.has_failure_output = False
         self.saw_proc_start = False
         self.saw_proc_end = False
-        self.complete_command = None
+        self.command = None
         self.harness_timeout = kwargs.get('harness_timeout')
         self.timedout = False
 
         # event from main thread to signal work done
         self.event = kwargs.get('event')
         self.done = False  # explicitly set flag so we don't rely on thread.isAlive
 
     def run(self):
@@ -382,30 +382,31 @@ class XPCShellTestThread(Thread):
         return profileDir
 
     def setupMozinfoJS(self):
         mozInfoJSPath = os.path.join(self.profileDir, 'mozinfo.json')
         mozInfoJSPath = mozInfoJSPath.replace('\\', '\\\\')
         mozinfo.output_to_file(mozInfoJSPath)
         return mozInfoJSPath
 
-    def buildCmdHead(self, headfiles, xpcscmd):
+    def buildCmdHead(self):
         """
           Build the command line arguments for the head files,
           along with the address of the webserver which some tests require.
 
           On a remote system, this is overloaded to resolve quoting issues over a
           secondary command line.
         """
+        headfiles = self.getHeadFiles(self.test_object)
         cmdH = ", ".join(['"' + f.replace('\\', '/') + '"'
                          for f in headfiles])
 
         dbgport = 0 if self.jsDebuggerInfo is None else self.jsDebuggerInfo.port
 
-        return xpcscmd + [
+        return [
             '-e', 'const _SERVER_ADDR = "localhost"',
             '-e', 'const _HEAD_FILES = [%s];' % cmdH,
             '-e', 'const _JSDEBUGGER_PORT = %d;' % dbgport,
         ]
 
     def getHeadFiles(self, test):
         """Obtain lists of head- files.  Returns a list of head files.
         """
@@ -433,49 +434,51 @@ class XPCShellTestThread(Thread):
           and test files. On a remote system, we overload this to add additional command
           line arguments, so this gets overloaded.
         """
         # - NOTE: if you rename/add any of the constants set here, update
         #   do_load_child_test_harness() in head.js
         if not self.appPath:
             self.appPath = self.xrePath
 
-        self.xpcsCmd = [
+        xpcsCmd = [
             self.xpcshell,
             '-g', self.xrePath,
             '-a', self.appPath,
             '-r', self.httpdManifest,
             '-m',
             '-s',
             '-e', 'const _HEAD_JS_PATH = "%s";' % self.headJSPath,
             '-e', 'const _MOZINFO_JS_PATH = "%s";' % self.mozInfoJSPath,
         ]
 
         if self.testingModulesDir:
             # Escape backslashes in string literal.
             sanitized = self.testingModulesDir.replace('\\', '\\\\')
-            self.xpcsCmd.extend([
+            xpcsCmd.extend([
                 '-e',
                 'const _TESTING_MODULES_DIR = "%s";' % sanitized
             ])
 
-        self.xpcsCmd.extend(['-f', os.path.join(self.testharnessdir, 'head.js')])
+        xpcsCmd.extend(['-f', os.path.join(self.testharnessdir, 'head.js')])
 
         if self.debuggerInfo:
-            self.xpcsCmd = [self.debuggerInfo.path] + self.debuggerInfo.args + self.xpcsCmd
+            xpcsCmd = [self.debuggerInfo.path] + self.debuggerInfo.args + xpcsCmd
 
         # Automation doesn't specify a pluginsPath and xpcshell defaults to
         # $APPDIR/plugins. We do the same here so we can carry on with
         # setting up every test with its own plugins directory.
         if not self.pluginsPath:
             self.pluginsPath = os.path.join(self.appPath, 'plugins')
 
         self.pluginsDir = self.setupPluginsDir()
         if self.pluginsDir:
-            self.xpcsCmd.extend(['-p', self.pluginsDir])
+            xpcsCmd.extend(['-p', self.pluginsDir])
+
+        return xpcsCmd
 
     def cleanupDir(self, directory, name):
         if not os.path.exists(directory):
             return
 
         # up to TRY_LIMIT attempts (one every second), because
         # the Windows filesystem is slow to react to the changes
         TRY_LIMIT = 25
@@ -524,17 +527,17 @@ class XPCShellTestThread(Thread):
 
     def log_line(self, line):
         """Log a line of output (either a parser json object or text output from
         the test process"""
         if isinstance(line, basestring):
             line = self.fix_text_output(line).rstrip('\r\n')
             self.log.process_output(self.proc_ident,
                                     line,
-                                    command=self.complete_command)
+                                    command=self.command)
         else:
             if 'message' in line:
                 line['message'] = self.fix_text_output(line['message'])
             if 'xpcshell_process' in line:
                 line['thread'] = ' '.join([current_thread().name, line['xpcshell_process']])
             else:
                 line['thread'] = current_thread().name
             self.log.log_raw(line)
@@ -625,37 +628,37 @@ class XPCShellTestThread(Thread):
         test_dir = os.path.dirname(path)
 
         # Create a profile and a temp dir that the JS harness can stick
         # a profile and temporary data in
         self.profileDir = self.setupProfileDir()
         self.tempDir = self.setupTempDir()
         self.mozInfoJSPath = self.setupMozinfoJS()
 
-        self.buildXpcsCmd()
-        head_files = self.getHeadFiles(self.test_object)
-        cmdH = self.buildCmdHead(head_files, self.xpcsCmd)
+        # The order of the command line is important:
+        # 1) Arguments for xpcshell itself
+        self.command = self.buildXpcsCmd()
 
-        # The test file will have to be loaded after the head files.
-        cmdT = self.buildCmdTestFile(path)
+        # 2) Arguments for the head files
+        self.command.extend(self.buildCmdHead())
 
-        args = self.xpcsRunArgs[:]
-        if 'debug' in self.test_object:
-            args.insert(0, '-d')
+        # 3) Arguments for the test file
+        self.command.extend(self.buildCmdTestFile(path))
+        self.command.extend(['-e', 'const _TEST_NAME = "%s";' % name])
 
-        # The test name to log
-        cmdI = ['-e', 'const _TEST_NAME = "%s"' % name]
+        # 4) Arguments for code coverage
+        if self.jscovdir:
+            self.command.extend(
+                ['-e', 'const _JSCOV_DIR = "%s";' % self.jscovdir.replace('\\', '/')])
 
-        # Directory for javascript code coverage output, null by default.
-        cmdC = ['-e', 'const _JSCOV_DIR = null']
-        if self.jscovdir:
-            cmdC = ['-e', 'const _JSCOV_DIR = "%s"' % self.jscovdir.replace('\\', '/')]
-            self.complete_command = cmdH + cmdT + cmdI + cmdC + args
-        else:
-            self.complete_command = cmdH + cmdT + cmdI + args
+        # 5) Runtime arguments
+        if 'debug' in self.test_object:
+            self.command.append('-d')
+
+        self.command.extend(self.xpcsRunArgs)
 
         if self.test_object.get('dmd') == 'true':
             self.env['PYTHON'] = sys.executable
             self.env['BREAKPAD_SYMBOLS_PATH'] = self.symbolsPath
 
         if self.test_object.get('subprocess') == 'true':
             self.env['PYTHON'] = sys.executable
 
@@ -674,19 +677,19 @@ class XPCShellTestThread(Thread):
             testTimer.start()
 
         proc = None
         process_output = None
 
         try:
             self.log.test_start(name)
             if self.verbose:
-                self.logCommand(name, self.complete_command, test_dir)
+                self.logCommand(name, self.command, test_dir)
 
-            proc = self.launchProcess(self.complete_command,
+            proc = self.launchProcess(self.command,
                                       stdout=self.pStdout, stderr=self.pStderr,
                                       env=self.env, cwd=test_dir,
                                       timeout=testTimeoutInterval)
 
             if hasattr(proc, "pid"):
                 self.proc_ident = proc.pid
             else:
                 # On mobile, "proc" is just a file.
new file mode 100644
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/wasm-godot/godot.js
@@ -0,0 +1,4 @@
+var Benchmark={};Benchmark["script-start"]=performance.now();var Engine={USING_WASM:true,RuntimeEnvironment:(function(Module){var Module;if(!Module)Module=(typeof Module!=="undefined"?Module:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;if(Module["ENVIRONMENT"]){if(Module["ENVIRONMENT"]==="WEB"){ENVIRONMENT_IS_WEB=true}else if(Module["ENVIRONMENT"]==="WORKER"){ENVIRONMENT_IS_WORKER=true}else if(Module["ENVIRONMENT"]==="NODE"){ENVIRONMENT_IS_NODE=true}else if(Module["ENVIRONMENT"]==="SHELL"){ENVIRONMENT_IS_SHELL=true}else{throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.")}}else{ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER}if(ENVIRONMENT_IS_NODE){if(!Module["print"])Module["print"]=console.log;if(!Module["printErr"])Module["printErr"]=console.warn;var nodeFS;var nodePath;Module["read"]=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](filename);return binary?ret:ret.toString()};Module["readBinary"]=function readBinary(filename){var ret=Module["read"](filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};Module["load"]=function load(f){globalEval(read(f))};if(!Module["thisProgram"]){if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}else{Module["thisProgram"]="unknown-program"}}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(!Module["print"])Module["print"]=print;if(typeof printErr!="undefined")Module["printErr"]=printErr;if(typeof read!="undefined"){Module["read"]=read}else{Module["read"]=function shell_read(){throw"no read() available"}}Module["readBinary"]=function readBinary(f){if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}var data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof quit==="function"){Module["quit"]=(function(status,toThrow){quit(status)})}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){Module["readBinary"]=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}Module["readAsync"]=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response)}else{onerror()}};xhr.onerror=onerror;xhr.send(null)};if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof console!=="undefined"){if(!Module["print"])Module["print"]=function shell_print(x){console.log(x)};if(!Module["printErr"])Module["printErr"]=function shell_printErr(x){console.warn(x)}}else{var TRY_USE_DUMP=false;if(!Module["print"])Module["print"]=TRY_USE_DUMP&&typeof dump!=="undefined"?(function(x){dump(x)}):(function(x){})}if(ENVIRONMENT_IS_WORKER){Module["load"]=importScripts}if(typeof Module["setWindowTitle"]==="undefined"){Module["setWindowTitle"]=(function(title){document.title=title})}}else{throw"Unknown runtime environment. Where are we?"}function globalEval(x){eval.call(null,x)}if(!Module["load"]&&Module["read"]){Module["load"]=function load(f){globalEval(Module["read"](f))}}if(!Module["print"]){Module["print"]=(function(){})}if(!Module["printErr"]){Module["printErr"]=Module["print"]}if(!Module["arguments"]){Module["arguments"]=[]}if(!Module["thisProgram"]){Module["thisProgram"]="./this.program"}if(!Module["quit"]){Module["quit"]=(function(status,toThrow){throw toThrow})}Module.print=Module["print"];Module.printErr=Module["printErr"];Module["preRun"]=[];Module["postRun"]=[];for(var key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=undefined;var Runtime={setTempRet0:(function(value){tempRet0=value;return value}),getTempRet0:(function(){return tempRet0}),stackSave:(function(){return STACKTOP}),stackRestore:(function(stackTop){STACKTOP=stackTop}),getNativeTypeSize:(function(type){switch(type){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:{if(type[type.length-1]==="*"){return Runtime.QUANTUM_SIZE}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}),getNativeFieldSize:(function(type){return Math.max(Runtime.getNativeTypeSize(type),Runtime.QUANTUM_SIZE)}),STACK_ALIGN:16,prepVararg:(function(ptr,type){if(type==="double"||type==="i64"){if(ptr&7){assert((ptr&7)===4);ptr+=4}}else{assert((ptr&3)===0)}return ptr}),getAlignSize:(function(type,size,vararg){if(!vararg&&(type=="i64"||type=="double"))return 8;if(!type)return Math.min(size,8);return Math.min(size||(type?Runtime.getNativeFieldSize(type):0),Runtime.QUANTUM_SIZE)}),dynCall:(function(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}),functionPointers:[],addFunction:(function(func){for(var i=0;i<Runtime.functionPointers.length;i++){if(!Runtime.functionPointers[i]){Runtime.functionPointers[i]=func;return 2*(1+i)}}throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."}),removeFunction:(function(index){Runtime.functionPointers[(index-2)/2]=null}),warnOnce:(function(text){if(!Runtime.warnOnce.shown)Runtime.warnOnce.shown={};if(!Runtime.warnOnce.shown[text]){Runtime.warnOnce.shown[text]=1;Module.printErr(text)}}),funcWrappers:{},getFuncWrapper:(function(func,sig){assert(sig);if(!Runtime.funcWrappers[sig]){Runtime.funcWrappers[sig]={}}var sigCache=Runtime.funcWrappers[sig];if(!sigCache[func]){if(sig.length===1){sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func)}}else if(sig.length===2){sigCache[func]=function dynCall_wrapper(arg){return Runtime.dynCall(sig,func,[arg])}}else{sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func,Array.prototype.slice.call(arguments))}}}return sigCache[func]}),getCompilerSetting:(function(name){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work"}),stackAlloc:(function(size){var ret=STACKTOP;STACKTOP=STACKTOP+size|0;STACKTOP=STACKTOP+15&-16;return ret}),staticAlloc:(function(size){var ret=STATICTOP;STATICTOP=STATICTOP+size|0;STATICTOP=STATICTOP+15&-16;return ret}),dynamicAlloc:(function(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=(ret+size+15|0)&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;if(end>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){HEAP32[DYNAMICTOP_PTR>>2]=ret;return 0}}return ret}),alignMemory:(function(size,quantum){var ret=size=Math.ceil(size/(quantum?quantum:16))*(quantum?quantum:16);return ret}),makeBigInt:(function(low,high,unsigned){var ret=unsigned?+(low>>>0)+ +(high>>>0)*4294967296:+(low>>>0)+ +(high|0)*4294967296;return ret}),GLOBAL_BASE:1024,QUANTUM_SIZE:4,__dummy__:0};Module["Runtime"]=Runtime;var ABORT=0;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];if(!func){try{func=eval("_"+ident)}catch(e){}}assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)");return func}var cwrap,ccall;((function(){var JSfuncs={"stackSave":(function(){Runtime.stackSave()}),"stackRestore":(function(){Runtime.stackRestore()}),"arrayToC":(function(arr){var ret=Runtime.stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=Runtime.stackAlloc(len);stringToUTF8(str,ret,len)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};ccall=function ccallFunc(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=Runtime.stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);if(returnType==="string")ret=Pointer_stringify(ret);if(stack!==0){if(opts&&opts.async){EmterpreterAsync.asyncFinalizers.push((function(){Runtime.stackRestore(stack)}));return}Runtime.stackRestore(stack)}return ret};var sourceRegex=/^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;function parseJSFunc(jsfunc){var parsed=jsfunc.toString().match(sourceRegex).slice(1);return{arguments:parsed[0],body:parsed[1],returnValue:parsed[2]}}var JSsource=null;function ensureJSsource(){if(!JSsource){JSsource={};for(var fun in JSfuncs){if(JSfuncs.hasOwnProperty(fun)){JSsource[fun]=parseJSFunc(JSfuncs[fun])}}}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident);var numericArgs=argTypes.every((function(type){return type==="number"}));var numericRet=returnType!=="string";if(numericRet&&numericArgs){return cfunc}var argNames=argTypes.map((function(x,i){return"$"+i}));var funcstr="(function("+argNames.join(",")+") {";var nargs=argTypes.length;if(!numericArgs){ensureJSsource();funcstr+="var stack = "+JSsource["stackSave"].body+";";for(var i=0;i<nargs;i++){var arg=argNames[i],type=argTypes[i];if(type==="number")continue;var convertCode=JSsource[type+"ToC"];funcstr+="var "+convertCode.arguments+" = "+arg+";";funcstr+=convertCode.body+";";funcstr+=arg+"=("+convertCode.returnValue+");"}}var cfuncname=parseJSFunc((function(){return cfunc})).returnValue;funcstr+="var ret = "+cfuncname+"("+argNames.join(",")+");";if(!numericRet){var strgfy=parseJSFunc((function(){return Pointer_stringify})).returnValue;funcstr+="ret = "+strgfy+"(ret);"}if(!numericArgs){ensureJSsource();funcstr+=JSsource["stackRestore"].body.replace("()","(stack)")+";"}funcstr+="return ret})";return eval(funcstr)}}))();Module["ccall"]=ccall;Module["cwrap"]=cwrap;function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}Module["setValue"]=setValue;function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for setValue: "+type)}return null}Module["getValue"]=getValue;var ALLOC_NORMAL=0;var ALLOC_STACK=1;var ALLOC_STATIC=2;var ALLOC_DYNAMIC=3;var ALLOC_NONE=4;Module["ALLOC_NORMAL"]=ALLOC_NORMAL;Module["ALLOC_STACK"]=ALLOC_STACK;Module["ALLOC_STATIC"]=ALLOC_STATIC;Module["ALLOC_DYNAMIC"]=ALLOC_DYNAMIC;Module["ALLOC_NONE"]=ALLOC_NONE;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[typeof _malloc==="function"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var ptr=ret,stop;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];if(typeof curr==="function"){curr=Runtime.getFunctionIndex(curr)}type=singleType||types[i];if(type===0){i++;continue}if(type=="i64")type="i32";setValue(ret+i,curr,type);if(previousType!==type){typeSize=Runtime.getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}Module["allocate"]=allocate;function getMemory(size){if(!staticSealed)return Runtime.staticAlloc(size);if(!runtimeInitialized)return Runtime.dynamicAlloc(size);return _malloc(size)}Module["getMemory"]=getMemory;function Pointer_stringify(ptr,length){if(length===0||!ptr)return"";var hasUtf=0;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return Module["UTF8ToString"](ptr)}Module["Pointer_stringify"]=Pointer_stringify;function AsciiToString(ptr){var str="";while(1){var ch=HEAP8[ptr++>>0];if(!ch)return str;str+=String.fromCharCode(ch)}}Module["AsciiToString"]=AsciiToString;function stringToAscii(str,outPtr){return writeAsciiToMemory(str,outPtr,false)}Module["stringToAscii"]=stringToAscii;var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx){var endPtr=idx;while(u8Array[endPtr])++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}}Module["UTF8ArrayToString"]=UTF8ArrayToString;function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}Module["UTF8ToString"]=UTF8ToString;function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}Module["stringToUTF8Array"]=stringToUTF8Array;function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}Module["stringToUTF8"]=stringToUTF8;function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}Module["lengthBytesUTF8"]=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function demangle(func){var __cxa_demangle_func=Module["___cxa_demangle"]||Module["__cxa_demangle"];if(__cxa_demangle_func){try{var s=func.substr(1);var len=lengthBytesUTF8(s)+1;var buf=_malloc(len);stringToUTF8(s,buf,len);var status=_malloc(4);var ret=__cxa_demangle_func(buf,0,0,status);if(getValue(status,"i32")===0&&ret){return Pointer_stringify(ret)}}catch(e){}finally{if(buf)_free(buf);if(status)_free(status);if(ret)_free(ret)}return func}Runtime.warnOnce("warning: build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/__Z[\w\d_]+/g;return text.replace(regex,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}Module["stackTrace"]=stackTrace;var PAGE_SIZE=16384;var WASM_PAGE_SIZE=65536;var ASMJS_PAGE_SIZE=16777216;var MIN_TOTAL_MEMORY=16777216;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBuffer(buf){Module["buffer"]=buffer=buf}function updateGlobalBufferViews(){Module["HEAP8"]=HEAP8=new Int8Array(buffer);Module["HEAP16"]=HEAP16=new Int16Array(buffer);Module["HEAP32"]=HEAP32=new Int32Array(buffer);Module["HEAPU8"]=HEAPU8=new Uint8Array(buffer);Module["HEAPU16"]=HEAPU16=new Uint16Array(buffer);Module["HEAPU32"]=HEAPU32=new Uint32Array(buffer);Module["HEAPF32"]=HEAPF32=new Float32Array(buffer);Module["HEAPF64"]=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed;var STACK_BASE,STACKTOP,STACK_MAX;var DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0;staticSealed=false;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value "+TOTAL_MEMORY+", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ")}if(!Module["reallocBuffer"])Module["reallocBuffer"]=(function(size){var ret;try{if(ArrayBuffer.transfer){ret=ArrayBuffer.transfer(buffer,size)}else{var oldHEAP8=HEAP8;ret=new ArrayBuffer(size);var temp=new Int8Array(ret);temp.set(oldHEAP8)}}catch(e){return false}var success=_emscripten_replace_memory(ret);if(!success)return false;return ret});function enlargeMemory(){var PAGE_MULTIPLE=Module["usingWasm"]?WASM_PAGE_SIZE:ASMJS_PAGE_SIZE;var LIMIT=2147483648-PAGE_MULTIPLE;if(HEAP32[DYNAMICTOP_PTR>>2]>LIMIT){return false}var OLD_TOTAL_MEMORY=TOTAL_MEMORY;TOTAL_MEMORY=Math.max(TOTAL_MEMORY,MIN_TOTAL_MEMORY);while(TOTAL_MEMORY<HEAP32[DYNAMICTOP_PTR>>2]){if(TOTAL_MEMORY<=536870912){TOTAL_MEMORY=alignUp(2*TOTAL_MEMORY,PAGE_MULTIPLE)}else{TOTAL_MEMORY=Math.min(alignUp((3*TOTAL_MEMORY+2147483648)/4,PAGE_MULTIPLE),LIMIT)}}var replacement=Module["reallocBuffer"](TOTAL_MEMORY);if(!replacement||replacement.byteLength!=TOTAL_MEMORY){TOTAL_MEMORY=OLD_TOTAL_MEMORY;return false}updateGlobalBuffer(replacement);updateGlobalBufferViews();return true}var byteLength;try{byteLength=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get);byteLength(new ArrayBuffer(4))}catch(e){byteLength=(function(buffer){return buffer.byteLength})}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;if(TOTAL_MEMORY<TOTAL_STACK)Module.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+TOTAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");if(Module["buffer"]){buffer=Module["buffer"]}else{if(typeof WebAssembly==="object"&&typeof WebAssembly.Memory==="function"){Module["wasmMemory"]=new WebAssembly.Memory({"initial":TOTAL_MEMORY/WASM_PAGE_SIZE});buffer=Module["wasmMemory"].buffer}else{buffer=new ArrayBuffer(TOTAL_MEMORY)}}updateGlobalBufferViews();function getTotalMemory(){return TOTAL_MEMORY}HEAP32[0]=1668509029;HEAP16[1]=25459;if(HEAPU8[2]!==115||HEAPU8[3]!==99)throw"Runtime error: expected the system to be little-endian!";Module["HEAP"]=HEAP;Module["buffer"]=buffer;Module["HEAP8"]=HEAP8;Module["HEAP16"]=HEAP16;Module["HEAP32"]=HEAP32;Module["HEAPU8"]=HEAPU8;Module["HEAPU16"]=HEAPU16;Module["HEAPU32"]=HEAPU32;Module["HEAPF32"]=HEAPF32;Module["HEAPF64"]=HEAPF64;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}Module["addOnPreRun"]=addOnPreRun;function addOnInit(cb){__ATINIT__.unshift(cb)}Module["addOnInit"]=addOnInit;function addOnPreMain(cb){__ATMAIN__.unshift(cb)}Module["addOnPreMain"]=addOnPreMain;function addOnExit(cb){__ATEXIT__.unshift(cb)}Module["addOnExit"]=addOnExit;function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}Module["addOnPostRun"]=addOnPostRun;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;function intArrayToString(array){var ret=[];for(var i=0;i<array.length;i++){var chr=array[i];if(chr>255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}Module["intArrayToString"]=intArrayToString;function writeStringToMemory(string,buffer,dontAddNull){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var lastChar,end;if(dontAddNull){end=buffer+lengthBytesUTF8(string);lastChar=HEAP8[end]}stringToUTF8(string,buffer,Infinity);if(dontAddNull)HEAP8[end]=lastChar}Module["writeStringToMemory"]=writeStringToMemory;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}Module["writeArrayToMemory"]=writeArrayToMemory;function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}Module["writeAsciiToMemory"]=writeAsciiToMemory;if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["fround"]){var froundBuffer=new Float32Array(1);Math["fround"]=(function(x){froundBuffer[0]=x;return froundBuffer[0]})}Math.fround=Math["fround"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];if(!Math["trunc"])Math["trunc"]=(function(x){return x<0?Math.ceil(x):Math.floor(x)});Math.trunc=Math["trunc"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_round=Math.round;var Math_min=Math.min;var Math_clz32=Math.clz32;var Math_trunc=Math.trunc;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}Module["addRunDependency"]=addRunDependency;function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["removeRunDependency"]=removeRunDependency;Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;function integrateWasmJS(Module){var method=Module["wasmJSMethod"]||"native-wasm";Module["wasmJSMethod"]=method;var wasmTextFile=Module["wasmTextFile"]||"godot.javascript.opt.webassembly.wast";var wasmBinaryFile=Module["wasmBinaryFile"]||"godot.javascript.opt.webassembly.wasm";var asmjsCodeFile=Module["asmjsCodeFile"]||"godot.javascript.opt.webassembly.temp.asm.js";if(typeof Module["locateFile"]==="function"){wasmTextFile=Module["locateFile"](wasmTextFile);wasmBinaryFile=Module["locateFile"](wasmBinaryFile);asmjsCodeFile=Module["locateFile"](asmjsCodeFile)}var wasmPageSize=64*1024;var asm2wasmImports={"f64-rem":(function(x,y){return x%y}),"f64-to-int":(function(x){return x|0}),"i32s-div":(function(x,y){return(x|0)/(y|0)|0}),"i32u-div":(function(x,y){return(x>>>0)/(y>>>0)>>>0}),"i32s-rem":(function(x,y){return(x|0)%(y|0)|0}),"i32u-rem":(function(x,y){return(x>>>0)%(y>>>0)>>>0}),"debugger":(function(){debugger})};var info={"global":null,"env":null,"asm2wasm":asm2wasmImports,"parent":Module};var exports=null;function lookupImport(mod,base){var lookup=info;if(mod.indexOf(".")<0){lookup=(lookup||{})[mod]}else{var parts=mod.split(".");lookup=(lookup||{})[parts[0]];lookup=(lookup||{})[parts[1]]}if(base){lookup=(lookup||{})[base]}if(lookup===undefined){abort("bad lookupImport to ("+mod+")."+base)}return lookup}function mergeMemory(newBuffer){var oldBuffer=Module["buffer"];if(newBuffer.byteLength<oldBuffer.byteLength){Module["printErr"]("the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here")}var oldView=new Int8Array(oldBuffer);var newView=new Int8Array(newBuffer);if(!memoryInitializer){oldView.set(newView.subarray(Module["STATIC_BASE"],Module["STATIC_BASE"]+Module["STATIC_BUMP"]),Module["STATIC_BASE"])}newView.set(oldView);updateGlobalBuffer(newBuffer);updateGlobalBufferViews()}var WasmTypes={none:0,i32:1,i64:2,f32:3,f64:4};function fixImports(imports){if(!0)return imports;var ret={};for(var i in imports){var fixed=i;if(fixed[0]=="_")fixed=fixed.substr(1);ret[fixed]=imports[i]}return ret}function getBinary(){try{var binary;if(Module["wasmBinary"]){binary=Module["wasmBinary"];binary=new Uint8Array(binary)}else if(Module["readBinary"]){binary=Module["readBinary"](wasmBinaryFile)}else{throw"on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)"}return binary}catch(err){abort(err)}}function getBinaryPromise(){if(!Module["wasmBinary"]&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then((function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}))}return new Promise((function(resolve,reject){resolve(getBinary())}))}function doNativeWasm(global,env,providedBuffer){if(typeof WebAssembly!=="object"){Module["printErr"]("no native wasm support detected");return false}if(!(Module["wasmMemory"]instanceof WebAssembly.Memory)){Module["printErr"]("no native wasm Memory in use");return false}env["memory"]=Module["wasmMemory"];info["global"]={"NaN":NaN,"Infinity":Infinity};info["global.Math"]=global.Math;info["env"]=env;function receiveInstance(instance){exports=instance.exports;if(exports.memory)mergeMemory(exports.memory);Module["asm"]=exports;Module["usingWasm"]=true;removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){Module["printErr"]("Module.instantiateWasm callback failed with error: "+e);return false}}getBinaryPromise().then((function(binary){return WebAssembly.instantiate(binary,info)})).then((function(output){receiveInstance(output["instance"])})).catch((function(reason){Module["printErr"]("failed to asynchronously prepare wasm: "+reason);abort(reason)}));return{}}Module["asmPreload"]=Module["asm"];var asmjsReallocBuffer=Module["reallocBuffer"];var wasmReallocBuffer=(function(size){var PAGE_MULTIPLE=Module["usingWasm"]?WASM_PAGE_SIZE:ASMJS_PAGE_SIZE;size=alignUp(size,PAGE_MULTIPLE);var old=Module["buffer"];var oldSize=old.byteLength;if(Module["usingWasm"]){try{var result=Module["wasmMemory"].grow((size-oldSize)/wasmPageSize);if(result!==(-1|0)){return Module["buffer"]=Module["wasmMemory"].buffer}else{return null}}catch(e){return null}}else{exports["__growWasmMemory"]((size-oldSize)/wasmPageSize);return Module["buffer"]!==old?Module["buffer"]:null}});Module["reallocBuffer"]=(function(size){if(finalMethod==="asmjs"){return asmjsReallocBuffer(size)}else{return wasmReallocBuffer(size)}});var finalMethod="";Module["asm"]=(function(global,env,providedBuffer){global=fixImports(global);env=fixImports(env);if(!env["table"]){var TABLE_SIZE=Module["wasmTableSize"];if(TABLE_SIZE===undefined)TABLE_SIZE=1024;var MAX_TABLE_SIZE=Module["wasmMaxTableSize"];if(typeof WebAssembly==="object"&&typeof WebAssembly.Table==="function"){if(MAX_TABLE_SIZE!==undefined){env["table"]=new WebAssembly.Table({"initial":TABLE_SIZE,"maximum":MAX_TABLE_SIZE,"element":"anyfunc"})}else{env["table"]=new WebAssembly.Table({"initial":TABLE_SIZE,element:"anyfunc"})}}else{env["table"]=new Array(TABLE_SIZE)}Module["wasmTable"]=env["table"]}if(!env["memoryBase"]){env["memoryBase"]=Module["STATIC_BASE"]}if(!env["tableBase"]){env["tableBase"]=0}var exports;exports=doNativeWasm(global,env,providedBuffer);return exports});var methodHandler=Module["asm"]}integrateWasmJS(Module);var ASM_CONSTS=[(function($0){var locale="";if(Module.locale){locale=Module.locale}else{locale=navigator.languages?navigator.languages[0]:navigator.language}locale=locale.split(".")[0];stringToUTF8(locale,$0,16)}),(function($0){window.alert(UTF8ToString($0))}),(function($0){Module.canvas.style.cursor=Module.UTF8ToString($0)}),(function($0){Module.stringToUTF8(Module.canvas.style.cursor?Module.canvas.style.cursor:"auto",$0,16)}),(function($0){document.title=UTF8ToString($0)}),(function($0,$1,$2,$3){const send_notification=Module.cwrap("send_notification",null,["number"]);const notifs=arguments;["mouseover","mouseleave","focus","blur"].forEach((function(event,i){Module.canvas.addEventListener(event,send_notification.bind(null,notifs[i]))}))}),(function(){FS.syncfs((function(err){if(err){Module.printErr("Failed to save IDB file system: "+err.message)}}))}),(function(){return"ontouchstart"in window}),(function($0){window.open(UTF8ToString($0),"_blank")}),(function(){return document.activeElement==Module.canvas}),(function(){Module.canvas.focus()}),(function(){Benchmark["main-loop-ready"]=performance.now();Benchmark.loops=[{frameTime:performance.now()}]}),(function(){if(!Benchmark["game-interactive"]){Benchmark.loops[Benchmark.loops.length-1].cpuTime=performance.now()}}),(function(){if(!Benchmark["game-interactive"]){var currentLoop=Benchmark.loops[Benchmark.loops.length-1];currentLoop.cpuTime=performance.now()-currentLoop.cpuTime;currentLoop.frameTime=performance.now()-currentLoop.frameTime;if(currentLoop.frameTime<1e3/55){Benchmark["game-interactive"]=performance.now();Benchmark.print()}else{Benchmark.loops.push({frameTime:performance.now()})}}}),(function(){Module.noExitRuntime=true;FS.mkdir("/userfs");FS.mount(IDBFS,{},"/userfs");FS.syncfs(true,(function(err){Module["ccall"]("main_after_fs_sync",null,["string"],[err?err.message:""])}))}),(function($0,$1,$2,$3,$4,$5){const CODE=$0;const USE_GLOBAL_EXEC_CONTEXT=$1;const PTR=$2;const ELEM_LEN=$3;const BYTEARRAY_PTR=$4;const BYTEARRAY_WRITE_PTR=$5;var eval_ret;try{if(USE_GLOBAL_EXEC_CONTEXT){var global_eval=eval;eval_ret=global_eval(UTF8ToString(CODE))}else{eval_ret=eval(UTF8ToString(CODE))}}catch(e){Module.printErr(e);eval_ret=null}switch(typeof eval_ret){case"boolean":setValue(PTR,eval_ret,"i32");return 1;case"number":setValue(PTR,eval_ret,"double");return 3;case"string":var array_len=lengthBytesUTF8(eval_ret)+1;var array_ptr=_malloc(array_len);try{if(array_ptr===0){throw new Error("String allocation failed (probably out of memory)")}setValue(PTR,array_ptr,"*");stringToUTF8(eval_ret,array_ptr,array_len);return 4}catch(e){if(array_ptr!==0){_free(array_ptr)}Module.printErr(e)}break;case"object":if(eval_ret===null){break}if(ArrayBuffer.isView(eval_ret)&&!(eval_ret instanceof Uint8Array)){eval_ret=new Uint8Array(eval_ret.buffer)}else if(eval_ret instanceof ArrayBuffer){eval_ret=new Uint8Array(eval_ret)}if(eval_ret instanceof Uint8Array){var bytes_ptr=ccall("resize_poolbytearray_and_open_write","number",["number","number","number"],[BYTEARRAY_PTR,BYTEARRAY_WRITE_PTR,eval_ret.length]);HEAPU8.set(eval_ret,bytes_ptr);return 20}if(typeof eval_ret.x==="number"&&typeof eval_ret.y==="number"){setValue(PTR,eval_ret.x,"double");setValue(PTR+ELEM_LEN,eval_ret.y,"double");if(typeof eval_ret.z==="number"){setValue(PTR+ELEM_LEN*2,eval_ret.z,"double");return 7}else if(typeof eval_ret.width==="number"&&typeof eval_ret.height==="number"){setValue(PTR+ELEM_LEN*2,eval_ret.width,"double");setValue(PTR+ELEM_LEN*3,eval_ret.height,"double");return 6}return 5}if(typeof eval_ret.r==="number"&&typeof eval_ret.g==="number"&&typeof eval_ret.b==="number"){setValue(PTR,eval_ret.r,"double");setValue(PTR+ELEM_LEN,eval_ret.g,"double");setValue(PTR+ELEM_LEN*2,eval_ret.b,"double");setValue(PTR+ELEM_LEN*3,typeof eval_ret.a==="number"?eval_ret.a:1,"double");return 14}break}return 0}),(function($0){_free($0)}),(function(){if(!Benchmark["first-frame"]){Benchmark["first-frame"]=performance.now()}})];function _emscripten_asm_const_i(code){return ASM_CONSTS[code]()}function _emscripten_asm_const_ii(code,a0){return ASM_CONSTS[code](a0)}function _emscripten_asm_const_iiiiiii(code,a0,a1,a2,a3,a4,a5){return ASM_CONSTS[code](a0,a1,a2,a3,a4,a5)}function _emscripten_asm_const_iiiii(code,a0,a1,a2,a3){return ASM_CONSTS[code](a0,a1,a2,a3)}STATIC_BASE=Runtime.GLOBAL_BASE;STATICTOP=STATIC_BASE+1032944;__ATINIT__.push({func:(function(){__GLOBAL__sub_I_os_javascript_cpp()})},{func:(function(){__GLOBAL__sub_I_main_cpp()})},{func:(function(){__GLOBAL__sub_I_gdnative_cpp()})},{func:(function(){__GLOBAL__sub_I_register_types_cpp()})},{func:(function(){__GLOBAL__sub_I_image_loader_svg_cpp()})},{func:(function(){__GLOBAL__sub_I_visual_script_nodes_cpp()})},{func:(function(){__GLOBAL__sub_I_thread_posix_cpp()})},{func:(function(){__GLOBAL__sub_I_particles_cpp()})},{func:(function(){__GLOBAL__sub_I_canvas_item_cpp()})},{func:(function(){__GLOBAL__sub_I_dynamic_font_cpp()})},{func:(function(){__GLOBAL__sub_I_material_cpp()})},{func:(function(){__GLOBAL__sub_I_theme_cpp()})},{func:(function(){__GLOBAL__sub_I_audio_server_cpp()})},{func:(function(){__GLOBAL__sub_I_class_db_cpp()})},{func:(function(){__GLOBAL__sub_I_color_cpp()})},{func:(function(){__GLOBAL__sub_I_global_constants_cpp()})},{func:(function(){__GLOBAL__sub_I_object_cpp()})},{func:(function(){__GLOBAL__sub_I_resource_cpp()})},{func:(function(){__GLOBAL__sub_I_matrix3_cpp()})},{func:(function(){__GLOBAL__sub_I_resource_loader_cpp()})});memoryInitializer=Module["wasmJSMethod"].indexOf("asmjs")>=0||Module["wasmJSMethod"].indexOf("interpret-asm2wasm")>=0?"godot.javascript.opt.webassembly.js.mem":null;var STATIC_BUMP=1032944;Module["STATIC_BASE"]=STATIC_BASE;Module["STATIC_BUMP"]=STATIC_BUMP;var tempDoublePtr=STATICTOP;STATICTOP+=16;function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};var Sockets={BUFFER_SIZE:10240,MAX_BUFFER_SIZE:10485760,nextFd:1,fds:{},nextport:1,maxport:65535,peer:null,connections:{},portmap:{},localAddr:4261412874,addrPool:[33554442,50331658,67108874,83886090,100663306,117440522,134217738,150994954,167772170,184549386,201326602,218103818,234881034]};function __inet_pton4_raw(str){var b=str.split(".");for(var i=0;i<4;i++){var tmp=Number(b[i]);if(isNaN(tmp))return null;b[i]=tmp}return(b[0]|b[1]<<8|b[2]<<16|b[3]<<24)>>>0}function __inet_pton6_raw(str){var words;var w,offset,z;var valid6regx=/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;var parts=[];if(!valid6regx.test(str)){return null}if(str==="::"){return[0,0,0,0,0,0,0,0]}if(str.indexOf("::")===0){str=str.replace("::","Z:")}else{str=str.replace("::",":Z:")}if(str.indexOf(".")>0){str=str.replace(new RegExp("[.]","g"),":");words=str.split(":");words[words.length-4]=parseInt(words[words.length-4])+parseInt(words[words.length-3])*256;words[words.length-3]=parseInt(words[words.length-2])+parseInt(words[words.length-1])*256;words=words.slice(0,words.length-2)}else{words=str.split(":")}offset=0;z=0;for(w=0;w<words.length;w++){if(typeof words[w]==="string"){if(words[w]==="Z"){for(z=0;z<8-words.length+1;z++){parts[w+z]=0}offset=z-1}else{parts[w+offset]=_htons(parseInt(words[w],16))}}else{parts[w+offset]=words[w]}}return[parts[1]<<16|parts[0],parts[3]<<16|parts[2],parts[5]<<16|parts[4],parts[7]<<16|parts[6]]}var DNS={address_map:{id:1,addrs:{},names:{}},lookup_name:(function(name){var res=__inet_pton4_raw(name);if(res!==null){return name}res=__inet_pton6_raw(name);if(res!==null){return name}var addr;if(DNS.address_map.addrs[name]){addr=DNS.address_map.addrs[name]}else{var id=DNS.address_map.id++;assert(id<65535,"exceeded max address mappings of 65535");addr="172.29."+(id&255)+"."+(id&65280);DNS.address_map.names[addr]=name;DNS.address_map.addrs[name]=addr}return addr}),lookup_addr:(function(addr){if(DNS.address_map.names[addr]){return DNS.address_map.names[addr]}return null})};function __inet_ntop4_raw(addr){return(addr&255)+"."+(addr>>8&255)+"."+(addr>>16&255)+"."+(addr>>24&255)}function __inet_ntop6_raw(ints){var str="";var word=0;var longest=0;var lastzero=0;var zstart=0;var len=0;var i=0;var parts=[ints[0]&65535,ints[0]>>16,ints[1]&65535,ints[1]>>16,ints[2]&65535,ints[2]>>16,ints[3]&65535,ints[3]>>16];var hasipv4=true;var v4part="";for(i=0;i<5;i++){if(parts[i]!==0){hasipv4=false;break}}if(hasipv4){v4part=__inet_ntop4_raw(parts[6]|parts[7]<<16);if(parts[5]===-1){str="::ffff:";str+=v4part;return str}if(parts[5]===0){str="::";if(v4part==="0.0.0.0")v4part="";if(v4part==="0.0.0.1")v4part="1";str+=v4part;return str}}for(word=0;word<8;word++){if(parts[word]===0){if(word-lastzero>1){len=0}lastzero=word;len++}if(len>longest){longest=len;zstart=word-longest+1}}for(word=0;word<8;word++){if(longest>1){if(parts[word]===0&&word>=zstart&&word<zstart+longest){if(word===zstart){str+=":";if(zstart===0)str+=":"}continue}}str+=Number(_ntohs(parts[word]&65535)).toString(16);str+=word<7?":":""}return str}function __write_sockaddr(sa,family,addr,port){switch(family){case 2:addr=__inet_pton4_raw(addr);HEAP16[sa>>1]=family;HEAP32[sa+4>>2]=addr;HEAP16[sa+2>>1]=_htons(port);break;case 10:addr=__inet_pton6_raw(addr);HEAP32[sa>>2]=family;HEAP32[sa+8>>2]=addr[0];HEAP32[sa+12>>2]=addr[1];HEAP32[sa+16>>2]=addr[2];HEAP32[sa+20>>2]=addr[3];HEAP16[sa+2>>1]=_htons(port);HEAP32[sa+4>>2]=0;HEAP32[sa+24>>2]=0;break;default:return{errno:ERRNO_CODES.EAFNOSUPPORT}}return{}}function _getaddrinfo(node,service,hint,out){var addrs=[];var addr=0;var port=0;var flags=0;var family=0;var type=0;var proto=0;var ai;function allocaddrinfo(family,type,proto,canon,addr,port){var sa,salen,ai;var res;salen=family===10?28:16;addr=family===10?__inet_ntop6_raw(addr):__inet_ntop4_raw(addr);sa=_malloc(salen);res=__write_sockaddr(sa,family,addr,port);assert(!res.errno);ai=_malloc(32);HEAP32[ai+4>>2]=family;HEAP32[ai+8>>2]=type;HEAP32[ai+12>>2]=proto;HEAP32[ai+24>>2]=canon;HEAP32[ai+20>>2]=sa;if(family===10){HEAP32[ai+16>>2]=28}else{HEAP32[ai+16>>2]=16}HEAP32[ai+28>>2]=0;return ai}if(hint){flags=HEAP32[hint>>2];family=HEAP32[hint+4>>2];type=HEAP32[hint+8>>2];proto=HEAP32[hint+12>>2]}if(type&&!proto){proto=type===2?17:6}if(!type&&proto){type=proto===17?2:1}if(proto===0){proto=6}if(type===0){type=1}if(!node&&!service){return-2}if(flags&~(1|2|4|1024|8|16|32)){return-1}if(hint!==0&&HEAP32[hint>>2]&2&&!node){return-1}if(flags&32){return-2}if(type!==0&&type!==1&&type!==2){return-7}if(family!==0&&family!==2&&family!==10){return-6}if(service){service=Pointer_stringify(service);port=parseInt(service,10);if(isNaN(port)){if(flags&1024){return-2}return-8}}if(!node){if(family===0){family=2}if((flags&1)===0){if(family===2){addr=_htonl(2130706433)}else{addr=[0,0,0,1]}}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAP32[out>>2]=ai;return 0}node=Pointer_stringify(node);addr=__inet_pton4_raw(node);if(addr!==null){if(family===0||family===2){family=2}else if(family===10&&flags&8){addr=[0,0,_htonl(65535),addr];family=10}else{return-2}}else{addr=__inet_pton6_raw(node);if(addr!==null){if(family===0||family===10){family=10}else{return-2}}}if(addr!=null){ai=allocaddrinfo(family,type,proto,node,addr,port);HEAP32[out>>2]=ai;return 0}if(flags&4){return-2}node=DNS.lookup_name(node);addr=__inet_pton4_raw(node);if(family===0){family=2}else if(family===10){addr=[0,0,_htonl(65535),addr]}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAP32[out>>2]=ai;return 0}function _sem_wait(){}function _fork(){___setErrNo(ERRNO_CODES.EAGAIN);return-1}function _posix_spawn(){return _fork.apply(null,arguments)}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],programInfos:{},stringCache:{},stringiCache:{},tempFixedLengthArray:[],packAlignment:4,unpackAlignment:4,init:(function(){GL.miniTempBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i<GL.MINI_TEMP_BUFFER_SIZE;i++){GL.miniTempBufferViews[i]=GL.miniTempBuffer.subarray(0,i+1)}for(var i=0;i<32;i++){GL.tempFixedLengthArray.push(new Array(i))}}),recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:(function(table){var ret=GL.counter++;for(var i=table.length;i<ret;i++){table[i]=null}return ret}),MINI_TEMP_BUFFER_SIZE:256,miniTempBuffer:null,miniTempBufferViews:[0],getSource:(function(shader,count,string,length){var source="";for(var i=0;i<count;++i){var frag;if(length){var len=HEAP32[length+i*4>>2];if(len<0){frag=Pointer_stringify(HEAP32[string+i*4>>2])}else{frag=Pointer_stringify(HEAP32[string+i*4>>2],len)}}else{frag=Pointer_stringify(HEAP32[string+i*4>>2])}source+=frag}return source}),createContext:(function(canvas,webGLContextAttributes){if(typeof webGLContextAttributes["majorVersion"]==="undefined"&&typeof webGLContextAttributes["minorVersion"]==="undefined"){if(typeof WebGL2RenderingContext!=="undefined")webGLContextAttributes["majorVersion"]=2;else webGLContextAttributes["majorVersion"]=1;webGLContextAttributes["minorVersion"]=0}var ctx;var errorInfo="?";function onContextCreationError(event){errorInfo=event.statusMessage||errorInfo}try{canvas.addEventListener("webglcontextcreationerror",onContextCreationError,false);try{if(webGLContextAttributes["majorVersion"]==1&&webGLContextAttributes["minorVersion"]==0){ctx=canvas.getContext("webgl",webGLContextAttributes)||canvas.getContext("experimental-webgl",webGLContextAttributes)}else if(webGLContextAttributes["majorVersion"]==2&&webGLContextAttributes["minorVersion"]==0){ctx=canvas.getContext("webgl2",webGLContextAttributes)}else{throw"Unsupported WebGL context version "+majorVersion+"."+minorVersion+"!"}}finally{canvas.removeEventListener("webglcontextcreationerror",onContextCreationError,false)}if(!ctx)throw":("}catch(e){Module.print("Could not create canvas: "+[errorInfo,e,JSON.stringify(webGLContextAttributes)]);return 0}if(!ctx)return 0;return GL.registerContext(ctx,webGLContextAttributes)}),registerContext:(function(ctx,webGLContextAttributes){var handle=GL.getNewId(GL.contexts);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes["majorVersion"],GLctx:ctx};function getChromeVersion(){var raw=navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);return raw?parseInt(raw[2],10):false}context.supportsWebGL2EntryPoints=context.version>=2&&(getChromeVersion()===false||getChromeVersion()>=58);if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes["enableExtensionsByDefault"]==="undefined"||webGLContextAttributes["enableExtensionsByDefault"]){GL.initExtensions(context)}return handle}),makeContextCurrent:(function(contextHandle){var context=GL.contexts[contextHandle];if(!context)return false;GLctx=Module.ctx=context.GLctx;GL.currentContext=context;return true}),getContext:(function(contextHandle){return GL.contexts[contextHandle]}),deleteContext:(function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;GL.contexts[contextHandle]=null}),initExtensions:(function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;context.maxVertexAttribs=GLctx.getParameter(GLctx.MAX_VERTEX_ATTRIBS);if(context.version<2){var instancedArraysExt=GLctx.getExtension("ANGLE_instanced_arrays");if(instancedArraysExt){GLctx["vertexAttribDivisor"]=(function(index,divisor){instancedArraysExt["vertexAttribDivisorANGLE"](index,divisor)});GLctx["drawArraysInstanced"]=(function(mode,first,count,primcount){instancedArraysExt["drawArraysInstancedANGLE"](mode,first,count,primcount)});GLctx["drawElementsInstanced"]=(function(mode,count,type,indices,primcount){instancedArraysExt["drawElementsInstancedANGLE"](mode,count,type,indices,primcount)})}var vaoExt=GLctx.getExtension("OES_vertex_array_object");if(vaoExt){GLctx["createVertexArray"]=(function(){return vaoExt["createVertexArrayOES"]()});GLctx["deleteVertexArray"]=(function(vao){vaoExt["deleteVertexArrayOES"](vao)});GLctx["bindVertexArray"]=(function(vao){vaoExt["bindVertexArrayOES"](vao)});GLctx["isVertexArray"]=(function(vao){return vaoExt["isVertexArrayOES"](vao)})}var drawBuffersExt=GLctx.getExtension("WEBGL_draw_buffers");if(drawBuffersExt){GLctx["drawBuffers"]=(function(n,bufs){drawBuffersExt["drawBuffersWEBGL"](n,bufs)})}}GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","WEBGL_compressed_texture_atc","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_frag_depth","EXT_sRGB","WEBGL_draw_buffers","WEBGL_shared_resources","EXT_shader_texture_lod","EXT_color_buffer_float"];var exts=GLctx.getSupportedExtensions();if(exts&&exts.length>0){GLctx.getSupportedExtensions().forEach((function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext)}}))}}),populateUniformTable:(function(program){var p=GL.programs[program];GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var ptable=GL.programInfos[program];var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,GLctx.ACTIVE_UNIFORMS);for(var i=0;i<numUniforms;++i){var u=GLctx.getActiveUniform(p,i);var name=u.name;ptable.maxUniformLength=Math.max(ptable.maxUniformLength,name.length+1);if(name.indexOf("]",name.length-1)!==-1){var ls=name.lastIndexOf("[");name=name.slice(0,ls)}var loc=GLctx.getUniformLocation(p,name);if(loc!=null){var id=GL.getNewId(GL.uniforms);utable[name]=[u.size,id];GL.uniforms[id]=loc;for(var j=1;j<u.size;++j){var n=name+"["+j+"]";loc=GLctx.getUniformLocation(p,n);id=GL.getNewId(GL.uniforms);GL.uniforms[id]=loc}}}})};function _glBeginTransformFeedback(x0){GLctx["beginTransformFeedback"](x0)}function _glLinkProgram(program){GLctx.linkProgram(GL.programs[program]);GL.programInfos[program]=null;GL.populateUniformTable(program)}function _glBindTexture(target,texture){GLctx.bindTexture(target,texture?GL.textures[texture]:null)}function _glFramebufferRenderbuffer(target,attachment,renderbuffertarget,renderbuffer){GLctx.framebufferRenderbuffer(target,attachment,renderbuffertarget,GL.renderbuffers[renderbuffer])}function _glGetString(name_){if(GL.stringCache[name_])return GL.stringCache[name_];var ret;switch(name_){case 7936:case 7937:case 37445:case 37446:ret=allocate(intArrayFromString(GLctx.getParameter(name_)),"i8",ALLOC_NORMAL);break;case 7938:var glVersion=GLctx.getParameter(GLctx.VERSION);if(GLctx.canvas.GLctxObject.version>=2)glVersion="OpenGL ES 3.0 ("+glVersion+")";else{glVersion="OpenGL ES 2.0 ("+glVersion+")"}ret=allocate(intArrayFromString(glVersion),"i8",ALLOC_NORMAL);break;case 7939:var exts=GLctx.getSupportedExtensions();var gl_exts=[];for(var i=0;i<exts.length;++i){gl_exts.push(exts[i]);gl_exts.push("GL_"+exts[i])}ret=allocate(intArrayFromString(gl_exts.join(" ")),"i8",ALLOC_NORMAL);break;case 35724:var glslVersion=GLctx.getParameter(GLctx.SHADING_LANGUAGE_VERSION);var ver_re=/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+"0";glslVersion="OpenGL ES GLSL ES "+ver_num[1]+" ("+glslVersion+")"}ret=allocate(intArrayFromString(glslVersion),"i8",ALLOC_NORMAL);break;default:GL.recordError(1280);return 0}GL.stringCache[name_]=ret;return ret}function _posix_spawn_file_actions_init(){Module["printErr"]("missing function: posix_spawn_file_actions_init");abort(-1)}function _glCompressedTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,imageSize,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx["compressedTexSubImage3D"](target,level,xoffset,yoffset,zoffset,width,height,depth,format,HEAPU8,data,imageSize)}else{GLctx["compressedTexSubImage3D"](target,level,xoffset,yoffset,zoffset,width,height,depth,format,data?HEAPU8.subarray(data,data+imageSize):null)}}var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can   access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"};var PATH={splitPath:(function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)}),normalizeArray:(function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts}),normalize:(function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter((function(p){return!!p})),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path}),dirname:(function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir}),basename:(function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)}),extname:(function(path){return PATH.splitPath(path)[3]}),join:(function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))}),join2:(function(l,r){return PATH.normalize(l+"/"+r)}),resolve:(function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter((function(p){return!!p})),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."}),relative:(function(from,to){from=PATH.resolve(from).substr(1);to=PATH.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=="")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push("..")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join("/")})};var TTY={ttys:[],init:(function(){}),shutdown:(function(){}),register:(function(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)}),stream_ops:{open:(function(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}stream.tty=tty;stream.seekable=false}),close:(function(stream){stream.tty.ops.flush(stream.tty)}),flush:(function(stream){stream.tty.ops.flush(stream.tty)}),read:(function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(ERRNO_CODES.ENXIO)}var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=stream.tty.ops.get_char(stream.tty)}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EIO)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(ERRNO_CODES.EAGAIN)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead}),write:(function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.put_char){throw new FS.ErrnoError(ERRNO_CODES.ENXIO)}for(var i=0;i<length;i++){try{stream.tty.ops.put_char(stream.tty,buffer[offset+i])}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EIO)}}if(length){stream.node.timestamp=Date.now()}return i})},default_tty_ops:{get_char:(function(tty){if(!tty.input.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=new Buffer(BUFSIZE);var bytesRead=0;var isPosixPlatform=process.platform!="win32";var fd=process.stdin.fd;if(isPosixPlatform){var usingDevice=false;try{fd=fs.openSync("/dev/stdin","r");usingDevice=true}catch(e){}}try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE,null)}catch(e){if(e.toString().indexOf("EOF")!=-1)bytesRead=0;else throw e}if(usingDevice){fs.closeSync(fd)}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()}),put_char:(function(tty,val){if(val===null||val===10){Module["print"](UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}}),flush:(function(tty){if(tty.output&&tty.output.length>0){Module["print"](UTF8ArrayToString(tty.output,0));tty.output=[]}})},default_tty1_ops:{put_char:(function(tty,val){if(val===null||val===10){Module["printErr"](UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}}),flush:(function(tty){if(tty.output&&tty.output.length>0){Module["printErr"](UTF8ArrayToString(tty.output,0));tty.output=[]}})}};var MEMFS={ops_table:null,mount:(function(mount){return MEMFS.createNode(null,"/",16384|511,0)}),createNode:(function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node}return node}),getFileDataAsRegularArray:(function(node){if(node.contents&&node.contents.subarray){var arr=[];for(var i=0;i<node.usedBytes;++i)arr.push(node.contents[i]);return arr}return node.contents}),getFileDataAsTypedArray:(function(node){if(!node.contents)return new Uint8Array;if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)}),expandFileStorage:(function(node,newCapacity){if(node.contents&&node.contents.subarray&&newCapacity>node.contents.length){node.contents=MEMFS.getFileDataAsRegularArray(node);node.usedBytes=node.contents.length}if(!node.contents||node.contents.subarray){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity<CAPACITY_DOUBLING_MAX?2:1.125)|0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0);return}if(!node.contents&&newCapacity>0)node.contents=[];while(node.contents.length<newCapacity)node.contents.push(0)}),resizeFileStorage:(function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0;return}if(!node.contents||node.contents.subarray){var oldContents=node.contents;node.contents=new Uint8Array(new ArrayBuffer(newSize));if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize;return}if(!node.contents)node.contents=[];if(node.contents.length>newSize)node.contents.length=newSize;else while(node.contents.length<newSize)node.contents.push(0);node.usedBytes=newSize}),node_ops:{getattr:(function(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr}),setattr:(function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}}),lookup:(function(parent,name){throw FS.genericErrors[ERRNO_CODES.ENOENT]}),mknod:(function(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)}),rename:(function(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY)}}}delete old_node.parent.contents[old_node.name];old_node.name=new_name;new_dir.contents[new_name]=old_node;old_node.parent=new_dir}),unlink:(function(parent,name){delete parent.contents[name]}),rmdir:(function(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY)}delete parent.contents[name]}),readdir:(function(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries}),symlink:(function(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node}),readlink:(function(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return node.link})},stream_ops:{read:(function(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);assert(size>=0);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i<size;i++)buffer[offset+i]=contents[position+i]}return size}),write:(function(stream,buffer,offset,length,position,canOwn){if(!length)return 0;var node=stream.node;node.timestamp=Date.now();if(buffer.subarray&&(!node.contents||node.contents.subarray)){if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length;return length}else if(node.usedBytes===0&&position===0){node.contents=new Uint8Array(buffer.subarray(offset,offset+length));node.usedBytes=length;return length}else if(position+length<=node.usedBytes){node.contents.set(buffer.subarray(offset,offset+length),position);return length}}MEMFS.expandFileStorage(node,position+length);if(node.contents.subarray&&buffer.subarray)node.contents.set(buffer.subarray(offset,offset+length),position);else{for(var i=0;i<length;i++){node.contents[position+i]=buffer[offset+i]}}node.usedBytes=Math.max(node.usedBytes,position+length);return length}),llseek:(function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return position}),allocate:(function(stream,offset,length){MEMFS.expandFileStorage(stream.node,offset+length);stream.node.usedBytes=Math.max(stream.node.usedBytes,offset+length)}),mmap:(function(stream,buffer,offset,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&(contents.buffer===buffer||contents.buffer===buffer.buffer)){allocated=false;ptr=contents.byteOffset}else{if(position>0||position+length<stream.node.usedBytes){if(contents.subarray){contents=contents.subarray(position,position+length)}else{contents=Array.prototype.slice.call(contents,position,position+length)}}allocated=true;ptr=_malloc(length);if(!ptr){throw new FS.ErrnoError(ERRNO_CODES.ENOMEM)}buffer.set(contents,ptr)}return{ptr:ptr,allocated:allocated}}),msync:(function(stream,buffer,offset,length,mmapFlags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}if(mmapFlags&2){return 0}var bytesWritten=MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0})}};var IDBFS={dbs:{},indexedDB:(function(){if(typeof indexedDB!=="undefined")return indexedDB;var ret=null;if(typeof window==="object")ret=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB;assert(ret,"IDBFS used, but indexedDB not supported");return ret}),DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:(function(mount){return MEMFS.mount.apply(null,arguments)}),syncfs:(function(mount,populate,callback){IDBFS.getLocalSet(mount,(function(err,local){if(err)return callback(err);IDBFS.getRemoteSet(mount,(function(err,remote){if(err)return callback(err);var src=populate?remote:local;var dst=populate?local:remote;IDBFS.reconcile(src,dst,callback)}))}))}),getDB:(function(name,callback){var db=IDBFS.dbs[name];if(db){return callback(null,db)}var req;try{req=IDBFS.indexedDB().open(name,IDBFS.DB_VERSION)}catch(e){return callback(e)}if(!req){return callback("Unable to connect to IndexedDB")}req.onupgradeneeded=(function(e){var db=e.target.result;var transaction=e.target.transaction;var fileStore;if(db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)){fileStore=transaction.objectStore(IDBFS.DB_STORE_NAME)}else{fileStore=db.createObjectStore(IDBFS.DB_STORE_NAME)}if(!fileStore.indexNames.contains("timestamp")){fileStore.createIndex("timestamp","timestamp",{unique:false})}});req.onsuccess=(function(){db=req.result;IDBFS.dbs[name]=db;callback(null,db)});req.onerror=(function(e){callback(this.error);e.preventDefault()})}),getLocalSet:(function(mount,callback){var entries={};function isRealDir(p){return p!=="."&&p!==".."}function toAbsolute(root){return(function(p){return PATH.join2(root,p)})}var check=FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint));while(check.length){var path=check.pop();var stat;try{stat=FS.stat(path)}catch(e){return callback(e)}if(FS.isDir(stat.mode)){check.push.apply(check,FS.readdir(path).filter(isRealDir).map(toAbsolute(path)))}entries[path]={timestamp:stat.mtime}}return callback(null,{type:"local",entries:entries})}),getRemoteSet:(function(mount,callback){var entries={};IDBFS.getDB(mount.mountpoint,(function(err,db){if(err)return callback(err);var transaction=db.transaction([IDBFS.DB_STORE_NAME],"readonly");transaction.onerror=(function(e){callback(this.error);e.preventDefault()});var store=transaction.objectStore(IDBFS.DB_STORE_NAME);var index=store.index("timestamp");index.openKeyCursor().onsuccess=(function(event){var cursor=event.target.result;if(!cursor){return callback(null,{type:"remote",db:db,entries:entries})}entries[cursor.primaryKey]={timestamp:cursor.key};cursor.continue()})}))}),loadLocalEntry:(function(path,callback){var stat,node;try{var lookup=FS.lookupPath(path);node=lookup.node;stat=FS.stat(path)}catch(e){return callback(e)}if(FS.isDir(stat.mode)){return callback(null,{timestamp:stat.mtime,mode:stat.mode})}else if(FS.isFile(stat.mode)){node.contents=MEMFS.getFileDataAsTypedArray(node);return callback(null,{timestamp:stat.mtime,mode:stat.mode,contents:node.contents})}else{return callback(new Error("node type not supported"))}}),storeLocalEntry:(function(path,entry,callback){try{if(FS.isDir(entry.mode)){FS.mkdir(path,entry.mode)}else if(FS.isFile(entry.mode)){FS.writeFile(path,entry.contents,{encoding:"binary",canOwn:true})}else{return callback(new Error("node type not supported"))}FS.chmod(path,entry.mode);FS.utime(path,entry.timestamp,entry.timestamp)}catch(e){return callback(e)}callback(null)}),removeLocalEntry:(function(path,callback){try{var lookup=FS.lookupPath(path);var stat=FS.stat(path);if(FS.isDir(stat.mode)){FS.rmdir(path)}else if(FS.isFile(stat.mode)){FS.unlink(path)}}catch(e){return callback(e)}callback(null)}),loadRemoteEntry:(function(store,path,callback){var req=store.get(path);req.onsuccess=(function(event){callback(null,event.target.result)});req.onerror=(function(e){callback(this.error);e.preventDefault()})}),storeRemoteEntry:(function(store,path,entry,callback){var req=store.put(entry,path);req.onsuccess=(function(){callback(null)});req.onerror=(function(e){callback(this.error);e.preventDefault()})}),removeRemoteEntry:(function(store,path,callback){var req=store.delete(path);req.onsuccess=(function(){callback(null)});req.onerror=(function(e){callback(this.error);e.preventDefault()})}),reconcile:(function(src,dst,callback){var total=0;var create=[];Object.keys(src.entries).forEach((function(key){var e=src.entries[key];var e2=dst.entries[key];if(!e2||e.timestamp>e2.timestamp){create.push(key);total++}}));var remove=[];Object.keys(dst.entries).forEach((function(key){var e=dst.entries[key];var e2=src.entries[key];if(!e2){remove.push(key);total++}}));if(!total){return callback(null)}var completed=0;var db=src.type==="remote"?src.db:dst.db;var transaction=db.transaction([IDBFS.DB_STORE_NAME],"readwrite");var store=transaction.objectStore(IDBFS.DB_STORE_NAME);function done(err){if(err){if(!done.errored){done.errored=true;return callback(err)}return}if(++completed>=total){return callback(null)}}transaction.onerror=(function(e){done(this.error);e.preventDefault()});create.sort().forEach((function(path){if(dst.type==="local"){IDBFS.loadRemoteEntry(store,path,(function(err,entry){if(err)return done(err);IDBFS.storeLocalEntry(path,entry,done)}))}else{IDBFS.loadLocalEntry(path,(function(err,entry){if(err)return done(err);IDBFS.storeRemoteEntry(store,path,entry,done)}))}}));remove.sort().reverse().forEach((function(path){if(dst.type==="local"){IDBFS.removeLocalEntry(path,done)}else{IDBFS.removeRemoteEntry(store,path,done)}}))})};var NODEFS={isWindows:false,staticInit:(function(){NODEFS.isWindows=!!process.platform.match(/^win/)}),mount:(function(mount){assert(ENVIRONMENT_IS_NODE);return NODEFS.createNode(null,"/",NODEFS.getMode(mount.opts.root),0)}),createNode:(function(parent,name,mode,dev){if(!FS.isDir(mode)&&!FS.isFile(mode)&&!FS.isLink(mode)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var node=FS.createNode(parent,name,mode);node.node_ops=NODEFS.node_ops;node.stream_ops=NODEFS.stream_ops;return node}),getMode:(function(path){var stat;try{stat=fs.lstatSync(path);if(NODEFS.isWindows){stat.mode=stat.mode|(stat.mode&146)>>1}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}return stat.mode}),realPath:(function(node){var parts=[];while(node.parent!==node){parts.push(node.name);node=node.parent}parts.push(node.mount.opts.root);parts.reverse();return PATH.join.apply(null,parts)}),flagsToPermissionStringMap:{0:"r",1:"r+",2:"r+",64:"r",65:"r+",66:"r+",129:"rx+",193:"rx+",514:"w+",577:"w",578:"w+",705:"wx",706:"wx+",1024:"a",1025:"a",1026:"a+",1089:"a",1090:"a+",1153:"ax",1154:"ax+",1217:"ax",1218:"ax+",4096:"rs",4098:"rs+"},flagsToPermissionString:(function(flags){flags&=~2097152;flags&=~2048;flags&=~32768;flags&=~524288;if(flags in NODEFS.flagsToPermissionStringMap){return NODEFS.flagsToPermissionStringMap[flags]}else{throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}}),node_ops:{getattr:(function(node){var path=NODEFS.realPath(node);var stat;try{stat=fs.lstatSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}if(NODEFS.isWindows&&!stat.blksize){stat.blksize=4096}if(NODEFS.isWindows&&!stat.blocks){stat.blocks=(stat.size+stat.blksize-1)/stat.blksize|0}return{dev:stat.dev,ino:stat.ino,mode:stat.mode,nlink:stat.nlink,uid:stat.uid,gid:stat.gid,rdev:stat.rdev,size:stat.size,atime:stat.atime,mtime:stat.mtime,ctime:stat.ctime,blksize:stat.blksize,blocks:stat.blocks}}),setattr:(function(node,attr){var path=NODEFS.realPath(node);try{if(attr.mode!==undefined){fs.chmodSync(path,attr.mode);node.mode=attr.mode}if(attr.timestamp!==undefined){var date=new Date(attr.timestamp);fs.utimesSync(path,date,date)}if(attr.size!==undefined){fs.truncateSync(path,attr.size)}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),lookup:(function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);var mode=NODEFS.getMode(path);return NODEFS.createNode(parent,name,mode)}),mknod:(function(parent,name,mode,dev){var node=NODEFS.createNode(parent,name,mode,dev);var path=NODEFS.realPath(node);try{if(FS.isDir(node.mode)){fs.mkdirSync(path,node.mode)}else{fs.writeFileSync(path,"",{mode:node.mode})}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}return node}),rename:(function(oldNode,newDir,newName){var oldPath=NODEFS.realPath(oldNode);var newPath=PATH.join2(NODEFS.realPath(newDir),newName);try{fs.renameSync(oldPath,newPath)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),unlink:(function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);try{fs.unlinkSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),rmdir:(function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);try{fs.rmdirSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),readdir:(function(node){var path=NODEFS.realPath(node);try{return fs.readdirSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),symlink:(function(parent,newName,oldPath){var newPath=PATH.join2(NODEFS.realPath(parent),newName);try{fs.symlinkSync(oldPath,newPath)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),readlink:(function(node){var path=NODEFS.realPath(node);try{path=fs.readlinkSync(path);path=NODEJS_PATH.relative(NODEJS_PATH.resolve(node.mount.opts.root),path);return path}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}})},stream_ops:{open:(function(stream){var path=NODEFS.realPath(stream.node);try{if(FS.isFile(stream.node.mode)){stream.nfd=fs.openSync(path,NODEFS.flagsToPermissionString(stream.flags))}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),close:(function(stream){try{if(FS.isFile(stream.node.mode)&&stream.nfd){fs.closeSync(stream.nfd)}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),read:(function(stream,buffer,offset,length,position){if(length===0)return 0;var nbuffer=new Buffer(length);var res;try{res=fs.readSync(stream.nfd,nbuffer,0,length,position)}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}if(res>0){for(var i=0;i<res;i++){buffer[offset+i]=nbuffer[i]}}return res}),write:(function(stream,buffer,offset,length,position){var nbuffer=new Buffer(buffer.subarray(offset,offset+length));var res;try{res=fs.writeSync(stream.nfd,nbuffer,0,length,position)}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}return res}),llseek:(function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){try{var stat=fs.fstatSync(stream.nfd);position+=stat.size}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}}}if(position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return position})}};var WORKERFS={DIR_MODE:16895,FILE_MODE:33279,reader:null,mount:(function(mount){assert(ENVIRONMENT_IS_WORKER);if(!WORKERFS.reader)WORKERFS.reader=new FileReaderSync;var root=WORKERFS.createNode(null,"/",WORKERFS.DIR_MODE,0);var createdParents={};function ensureParent(path){var parts=path.split("/");var parent=root;for(var i=0;i<parts.length-1;i++){var curr=parts.slice(0,i+1).join("/");if(!createdParents[curr]){createdParents[curr]=WORKERFS.createNode(parent,parts[i],WORKERFS.DIR_MODE,0)}parent=createdParents[curr]}return parent}function base(path){var parts=path.split("/");return parts[parts.length-1]}Array.prototype.forEach.call(mount.opts["files"]||[],(function(file){WORKERFS.createNode(ensureParent(file.name),base(file.name),WORKERFS.FILE_MODE,0,file,file.lastModifiedDate)}));(mount.opts["blobs"]||[]).forEach((function(obj){WORKERFS.createNode(ensureParent(obj["name"]),base(obj["name"]),WORKERFS.FILE_MODE,0,obj["data"])}));(mount.opts["packages"]||[]).forEach((function(pack){pack["metadata"].files.forEach((function(file){var name=file.filename.substr(1);WORKERFS.createNode(ensureParent(name),base(name),WORKERFS.FILE_MODE,0,pack["blob"].slice(file.start,file.end))}))}));return root}),createNode:(function(parent,name,mode,dev,contents,mtime){var node=FS.createNode(parent,name,mode);node.mode=mode;node.node_ops=WORKERFS.node_ops;node.stream_ops=WORKERFS.stream_ops;node.timestamp=(mtime||new Date).getTime();assert(WORKERFS.FILE_MODE!==WORKERFS.DIR_MODE);if(mode===WORKERFS.FILE_MODE){node.size=contents.size;node.contents=contents}else{node.size=4096;node.contents={}}if(parent){parent.contents[name]=node}return node}),node_ops:{getattr:(function(node){return{dev:1,ino:undefined,mode:node.mode,nlink:1,uid:0,gid:0,rdev:undefined,size:node.size,atime:new Date(node.timestamp),mtime:new Date(node.timestamp),ctime:new Date(node.timestamp),blksize:4096,blocks:Math.ceil(node.size/4096)}}),setattr:(function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}}),lookup:(function(parent,name){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}),mknod:(function(parent,name,mode,dev){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),rename:(function(oldNode,newDir,newName){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),unlink:(function(parent,name){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),rmdir:(function(parent,name){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),readdir:(function(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries}),symlink:(function(parent,newName,oldPath){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),readlink:(function(node){throw new FS.ErrnoError(ERRNO_CODES.EPERM)})},stream_ops:{read:(function(stream,buffer,offset,length,position){if(position>=stream.node.size)return 0;var chunk=stream.node.contents.slice(position,position+length);var ab=WORKERFS.reader.readAsArrayBuffer(chunk);buffer.set(new Uint8Array(ab),offset);return chunk.size}),write:(function(stream,buffer,offset,length,position){throw new FS.ErrnoError(ERRNO_CODES.EIO)}),llseek:(function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.size}}if(position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return position})}};STATICTOP+=16;STATICTOP+=16;STATICTOP+=16;var FS={root:null,mounts:[],devices:[null],streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:(function(e){if(!(e instanceof FS.ErrnoError))throw e+" : "+stackTrace();return ___setErrNo(e.errno)}),lookupPath:(function(path,opts){path=PATH.resolve(FS.cwd(),path);opts=opts||{};if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};for(var key in defaults){if(opts[key]===undefined){opts[key]=defaults[key]}}if(opts.recurse_count>8){throw new FS.ErrnoError(ERRNO_CODES.ELOOP)}var parts=PATH.normalizeArray(path.split("/").filter((function(p){return!!p})),false);var current=FS.root;var current_path="/";for(var i=0;i<parts.length;i++){var islast=i===parts.length-1;if(islast&&opts.parent){break}current=FS.lookupNode(current,parts[i]);current_path=PATH.join2(current_path,parts[i]);if(FS.isMountpoint(current)){if(!islast||islast&&opts.follow_mount){current=current.mounted.root}}if(!islast||opts.follow){var count=0;while(FS.isLink(current.mode)){var link=FS.readlink(current_path);current_path=PATH.resolve(PATH.dirname(current_path),link);var lookup=FS.lookupPath(current_path,{recurse_count:opts.recurse_count});current=lookup.node;if(count++>40){throw new FS.ErrnoError(ERRNO_CODES.ELOOP)}}}}return{path:current_path,node:current}}),getPath:(function(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?mount+"/"+path:mount+path}path=path?node.name+"/"+path:node.name;node=node.parent}}),hashName:(function(parentid,name){var hash=0;for(var i=0;i<name.length;i++){hash=(hash<<5)-hash+name.charCodeAt(i)|0}return(parentid+hash>>>0)%FS.nameTable.length}),hashAddNode:(function(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node}),hashRemoveNode:(function(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}}),lookupNode:(function(parent,name){var err=FS.mayLookup(parent);if(err){throw new FS.ErrnoError(err,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)}),createNode:(function(parent,name,mode,rdev){if(!FS.FSNode){FS.FSNode=(function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev});FS.FSNode.prototype={};var readMode=292|73;var writeMode=146;Object.defineProperties(FS.FSNode.prototype,{read:{get:(function(){return(this.mode&readMode)===readMode}),set:(function(val){val?this.mode|=readMode:this.mode&=~readMode})},write:{get:(function(){return(this.mode&writeMode)===writeMode}),set:(function(val){val?this.mode|=writeMode:this.mode&=~writeMode})},isFolder:{get:(function(){return FS.isDir(this.mode)})},isDevice:{get:(function(){return FS.isChrdev(this.mode)})}})}var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node}),destroyNode:(function(node){FS.hashRemoveNode(node)}),isRoot:(function(node){return node===node.parent}),isMountpoint:(function(node){return!!node.mounted}),isFile:(function(mode){return(mode&61440)===32768}),isDir:(function(mode){return(mode&61440)===16384}),isLink:(function(mode){return(mode&61440)===40960}),isChrdev:(function(mode){return(mode&61440)===8192}),isBlkdev:(function(mode){return(mode&61440)===24576}),isFIFO:(function(mode){return(mode&61440)===4096}),isSocket:(function(mode){return(mode&49152)===49152}),flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:(function(str){var flags=FS.flagModes[str];if(typeof flags==="undefined"){throw new Error("Unknown file open mode: "+str)}return flags}),flagsToPermissionString:(function(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms}),nodePermissions:(function(node,perms){if(FS.ignorePermissions){return 0}if(perms.indexOf("r")!==-1&&!(node.mode&292)){return ERRNO_CODES.EACCES}else if(perms.indexOf("w")!==-1&&!(node.mode&146)){return ERRNO_CODES.EACCES}else if(perms.indexOf("x")!==-1&&!(node.mode&73)){return ERRNO_CODES.EACCES}return 0}),mayLookup:(function(dir){var err=FS.nodePermissions(dir,"x");if(err)return err;if(!dir.node_ops.lookup)return ERRNO_CODES.EACCES;return 0}),mayCreate:(function(dir,name){try{var node=FS.lookupNode(dir,name);return ERRNO_CODES.EEXIST}catch(e){}return FS.nodePermissions(dir,"wx")}),mayDelete:(function(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var err=FS.nodePermissions(dir,"wx");if(err){return err}if(isdir){if(!FS.isDir(node.mode)){return ERRNO_CODES.ENOTDIR}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return ERRNO_CODES.EBUSY}}else{if(FS.isDir(node.mode)){return ERRNO_CODES.EISDIR}}return 0}),mayOpen:(function(node,flags){if(!node){return ERRNO_CODES.ENOENT}if(FS.isLink(node.mode)){return ERRNO_CODES.ELOOP}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return ERRNO_CODES.EISDIR}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))}),MAX_OPEN_FDS:4096,nextfd:(function(fd_start,fd_end){fd_start=fd_start||0;fd_end=fd_end||FS.MAX_OPEN_FDS;for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(ERRNO_CODES.EMFILE)}),getStream:(function(fd){return FS.streams[fd]}),createStream:(function(stream,fd_start,fd_end){if(!FS.FSStream){FS.FSStream=(function(){});FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get:(function(){return this.node}),set:(function(val){this.node=val})},isRead:{get:(function(){return(this.flags&2097155)!==1})},isWrite:{get:(function(){return(this.flags&2097155)!==0})},isAppend:{get:(function(){return this.flags&1024})}})}var newStream=new FS.FSStream;for(var p in stream){newStream[p]=stream[p]}stream=newStream;var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream}),closeStream:(function(fd){FS.streams[fd]=null}),chrdev_stream_ops:{open:(function(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}}),llseek:(function(){throw new FS.ErrnoError(ERRNO_CODES.ESPIPE)})},major:(function(dev){return dev>>8}),minor:(function(dev){return dev&255}),makedev:(function(ma,mi){return ma<<8|mi}),registerDevice:(function(dev,ops){FS.devices[dev]={stream_ops:ops}}),getDevice:(function(dev){return FS.devices[dev]}),getMounts:(function(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts}),syncfs:(function(populate,callback){if(typeof populate==="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){console.log("warning: "+FS.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(err){assert(FS.syncFSRequests>0);FS.syncFSRequests--;return callback(err)}function done(err){if(err){if(!done.errored){done.errored=true;return doCallback(err)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach((function(mount){if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)}))}),mount:(function(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot}),unmount:(function(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach((function(hash){var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.indexOf(current.mount)!==-1){FS.destroyNode(current)}current=next}}));node.mounted=null;var idx=node.mount.mounts.indexOf(mount);assert(idx!==-1);node.mount.mounts.splice(idx,1)}),lookup:(function(parent,name){return parent.node_ops.lookup(parent,name)}),mknod:(function(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var err=FS.mayCreate(parent,name);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}return parent.node_ops.mknod(parent,name,mode,dev)}),create:(function(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)}),mkdir:(function(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)}),mkdirTree:(function(path,mode){var dirs=path.split("/");var d="";for(var i=0;i<dirs.length;++i){if(!dirs[i])continue;d+="/"+dirs[i];try{FS.mkdir(d,mode)}catch(e){if(e.errno!=ERRNO_CODES.EEXIST)throw e}}}),mkdev:(function(path,mode,dev){if(typeof dev==="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)}),symlink:(function(oldpath,newpath){if(!PATH.resolve(oldpath)){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}var newname=PATH.basename(newpath);var err=FS.mayCreate(parent,newname);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}return parent.node_ops.symlink(parent,newname,oldpath)}),rename:(function(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;try{lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}if(!old_dir||!new_dir)throw new FS.ErrnoError(ERRNO_CODES.ENOENT);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(ERRNO_CODES.EXDEV)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}relative=PATH.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var err=FS.mayDelete(old_dir,old_name,isdir);if(err){throw new FS.ErrnoError(err)}err=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(err){throw new FS.ErrnoError(err)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}if(new_dir!==old_dir){err=FS.nodePermissions(old_dir,"w");if(err){throw new FS.ErrnoError(err)}}try{if(FS.trackingDelegate["willMovePath"]){FS.trackingDelegate["willMovePath"](old_path,new_path)}}catch(e){console.log("FS.trackingDelegate['willMovePath']('"+old_path+"', '"+new_path+"') threw an exception: "+e.message)}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}try{if(FS.trackingDelegate["onMovePath"])FS.trackingDelegate["onMovePath"](old_path,new_path)}catch(e){console.log("FS.trackingDelegate['onMovePath']('"+old_path+"', '"+new_path+"') threw an exception: "+e.message)}}),rmdir:(function(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var err=FS.mayDelete(parent,name,true);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}try{if(FS.trackingDelegate["willDeletePath"]){FS.trackingDelegate["willDeletePath"](path)}}catch(e){console.log("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: "+e.message)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node);try{if(FS.trackingDelegate["onDeletePath"])FS.trackingDelegate["onDeletePath"](path)}catch(e){console.log("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: "+e.message)}}),readdir:(function(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR)}return node.node_ops.readdir(node)}),unlink:(function(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var err=FS.mayDelete(parent,name,false);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}try{if(FS.trackingDelegate["willDeletePath"]){FS.trackingDelegate["willDeletePath"](path)}}catch(e){console.log("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: "+e.message)}parent.node_ops.unlink(parent,name);FS.destroyNode(node);try{if(FS.trackingDelegate["onDeletePath"])FS.trackingDelegate["onDeletePath"](path)}catch(e){console.log("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: "+e.message)}}),readlink:(function(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}if(!link.node_ops.readlink){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return PATH.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))}),stat:(function(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}if(!node.node_ops.getattr){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}return node.node_ops.getattr(node)}),lstat:(function(path){return FS.stat(path,true)}),chmod:(function(path,mode,dontFollow){var node;if(typeof path==="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})}),lchmod:(function(path,mode){FS.chmod(path,mode,true)}),fchmod:(function(fd,mode){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}FS.chmod(stream.node,mode)}),chown:(function(path,uid,gid,dontFollow){var node;if(typeof path==="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}node.node_ops.setattr(node,{timestamp:Date.now()})}),lchown:(function(path,uid,gid){FS.chown(path,uid,gid,true)}),fchown:(function(fd,uid,gid){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}FS.chown(stream.node,uid,gid)}),truncate:(function(path,len){if(len<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var node;if(typeof path==="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EISDIR)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var err=FS.nodePermissions(node,"w");if(err){throw new FS.ErrnoError(err)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})}),ftruncate:(function(fd,len){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}FS.truncate(stream.node,len)}),utime:(function(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})}),open:(function(path,flags,mode,fd_start,fd_end){if(path===""){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}flags=typeof flags==="string"?FS.modeStringToFlags(flags):flags;mode=typeof mode==="undefined"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path==="object"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(ERRNO_CODES.EEXIST)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR)}if(!created){var err=FS.mayOpen(node,flags);if(err){throw new FS.ErrnoError(err)}}if(flags&512){FS.truncate(node,0)}flags&=~(128|512);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false},fd_start,fd_end);if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module["logReadFiles"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1;Module["printErr"]("read file: "+path)}}try{if(FS.trackingDelegate["onOpenFile"]){var trackingFlags=0;if((flags&2097155)!==1){trackingFlags|=FS.tracking.openFlags.READ}if((flags&2097155)!==0){trackingFlags|=FS.tracking.openFlags.WRITE}FS.trackingDelegate["onOpenFile"](path,trackingFlags)}}catch(e){console.log("FS.trackingDelegate['onOpenFile']('"+path+"', flags) threw an exception: "+e.message)}return stream}),close:(function(stream){if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}}),llseek:(function(stream,offset,whence){if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(ERRNO_CODES.ESPIPE)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position}),read:(function(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EISDIR)}if(!stream.stream_ops.read){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var seeking=true;if(typeof position==="undefined"){position=stream.position;seeking=false}else if(!stream.seekable){throw new FS.ErrnoError(ERRNO_CODES.ESPIPE)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead}),write:(function(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EISDIR)}if(!stream.stream_ops.write){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}if(stream.flags&1024){FS.llseek(stream,0,2)}var seeking=true;if(typeof position==="undefined"){position=stream.position;seeking=false}else if(!stream.seekable){throw new FS.ErrnoError(ERRNO_CODES.ESPIPE)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;try{if(stream.path&&FS.trackingDelegate["onWriteToFile"])FS.trackingDelegate["onWriteToFile"](stream.path)}catch(e){console.log("FS.trackingDelegate['onWriteToFile']('"+path+"') threw an exception: "+e.message)}return bytesWritten}),allocate:(function(stream,offset,length){if(offset<0||length<=0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP)}stream.stream_ops.allocate(stream,offset,length)}),mmap:(function(stream,buffer,offset,length,position,prot,flags){if((stream.flags&2097155)===1){throw new FS.ErrnoError(ERRNO_CODES.EACCES)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}return stream.stream_ops.mmap(stream,buffer,offset,length,position,prot,flags)}),msync:(function(stream,buffer,offset,length,mmapFlags){if(!stream||!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)}),munmap:(function(stream){return 0}),ioctl:(function(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(ERRNO_CODES.ENOTTY)}return stream.stream_ops.ioctl(stream,cmd,arg)}),readFile:(function(path,opts){opts=opts||{};opts.flags=opts.flags||"r";opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error('Invalid encoding type "'+opts.encoding+'"')}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret}),writeFile:(function(path,data,opts){opts=opts||{};opts.flags=opts.flags||"w";opts.encoding=opts.encoding||"utf8";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error('Invalid encoding type "'+opts.encoding+'"')}var stream=FS.open(path,opts.flags,opts.mode);if(opts.encoding==="utf8"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,0,opts.canOwn)}else if(opts.encoding==="binary"){FS.write(stream,data,0,data.length,0,opts.canOwn)}FS.close(stream)}),cwd:(function(){return FS.currentPath}),chdir:(function(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR)}var err=FS.nodePermissions(lookup.node,"x");if(err){throw new FS.ErrnoError(err)}FS.currentPath=lookup.path}),createDefaultDirectories:(function(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")}),createDefaultDevices:(function(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:(function(){return 0}),write:(function(stream,buffer,offset,length,pos){return length})});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var random_device;if(typeof crypto!=="undefined"){var randomBuffer=new Uint8Array(1);random_device=(function(){crypto.getRandomValues(randomBuffer);return randomBuffer[0]})}else if(ENVIRONMENT_IS_NODE){random_device=(function(){return require("crypto").randomBytes(1)[0]})}else{random_device=(function(){return Math.random()*256|0})}FS.createDevice("/dev","random",random_device);FS.createDevice("/dev","urandom",random_device);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")}),createSpecialDirectories:(function(){FS.mkdir("/proc");FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount:(function(){var node=FS.createNode("/proc/self","fd",16384|511,73);node.node_ops={lookup:(function(parent,name){var fd=+name;var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(ERRNO_CODES.EBADF);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:(function(){return stream.path})}};ret.parent=ret;return ret})};return node})},{},"/proc/self/fd")}),createStandardStreams:(function(){if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin","r");assert(stdin.fd===0,"invalid handle for stdin ("+stdin.fd+")");var stdout=FS.open("/dev/stdout","w");assert(stdout.fd===1,"invalid handle for stdout ("+stdout.fd+")");var stderr=FS.open("/dev/stderr","w");assert(stderr.fd===2,"invalid handle for stderr ("+stderr.fd+")")}),ensureErrnoError:(function(){if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.node=node;this.setErrno=(function(errno){this.errno=errno;for(var key in ERRNO_CODES){if(ERRNO_CODES[key]===errno){this.code=key;break}}});this.setErrno(errno);this.message=ERRNO_MESSAGES[errno]};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[ERRNO_CODES.ENOENT].forEach((function(code){FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack="<generic error, no stack>"}))}),staticInit:(function(){FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS,"IDBFS":IDBFS,"NODEFS":NODEFS,"WORKERFS":WORKERFS}}),init:(function(input,output,error){assert(!FS.init.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");FS.init.initialized=true;FS.ensureErrnoError();Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()}),quit:(function(){FS.init.initialized=false;var fflush=Module["_fflush"];if(fflush)fflush(0);for(var i=0;i<FS.streams.length;i++){var stream=FS.streams[i];if(!stream){continue}FS.close(stream)}}),getMode:(function(canRead,canWrite){var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode}),joinPath:(function(parts,forceRelative){var path=PATH.join.apply(null,parts);if(forceRelative&&path[0]=="/")path=path.substr(1);return path}),absolutePath:(function(relative,base){return PATH.resolve(base,relative)}),standardizePath:(function(path){return PATH.normalize(path)}),findObject:(function(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(ret.exists){return ret.object}else{___setErrNo(ret.error);return null}}),analyzePath:(function(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret}),createFolder:(function(parent,name,canRead,canWrite){var path=PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name);var mode=FS.getMode(canRead,canWrite);return FS.mkdir(path,mode)}),createPath:(function(parent,path,canRead,canWrite){parent=typeof parent==="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current}),createFile:(function(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name);var mode=FS.getMode(canRead,canWrite);return FS.create(path,mode)}),createDataFile:(function(parent,name,data,canRead,canWrite,canOwn){var path=name?PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name):parent;var mode=FS.getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data==="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i<len;++i)arr[i]=data.charCodeAt(i);data=arr}FS.chmod(node,mode|146);var stream=FS.open(node,"w");FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}return node}),createDevice:(function(parent,name,input,output){var path=PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name);var mode=FS.getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open:(function(stream){stream.seekable=false}),close:(function(stream){if(output&&output.buffer&&output.buffer.length){output(10)}}),read:(function(stream,buffer,offset,length,pos){var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=input()}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EIO)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(ERRNO_CODES.EAGAIN)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead}),write:(function(stream,buffer,offset,length,pos){for(var i=0;i<length;i++){try{output(buffer[offset+i])}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EIO)}}if(length){stream.node.timestamp=Date.now()}return i})});return FS.mkdev(path,mode,dev)}),createLink:(function(parent,name,target,canRead,canWrite){var path=PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name);return FS.symlink(target,path)}),forceLoadFile:(function(obj){if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;var success=true;if(typeof XMLHttpRequest!=="undefined"){throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")}else if(Module["read"]){try{obj.contents=intArrayFromString(Module["read"](obj.url),true);obj.usedBytes=obj.contents.length}catch(e){success=false}}else{throw new Error("Cannot load without read() or XMLHttpRequest.")}if(!success)___setErrNo(ERRNO_CODES.EIO);return success}),createLazyFile:(function(parent,name,url,canRead,canWrite){function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(function(from,to){if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);if(typeof Uint8Array!="undefined")xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}else{return intArrayFromString(xhr.responseText||"",true)}});var lazyArray=this;lazyArray.setDataGetter((function(chunkNum){var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]}));if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;console.log("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:(function(){if(!this.lengthKnown){this.cacheLength()}return this._length})},chunkSize:{get:(function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize})}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:(function(){return this.contents.length})}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach((function(key){var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(ERRNO_CODES.EIO)}return fn.apply(null,arguments)}}));stream_ops.read=function stream_ops_read(stream,buffer,offset,length,position){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(ERRNO_CODES.EIO)}var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);assert(size>=0);if(contents.slice){for(var i=0;i<size;i++){buffer[offset+i]=contents[position+i]}}else{for(var i=0;i<size;i++){buffer[offset+i]=contents.get(position+i)}}return size};node.stream_ops=stream_ops;return node}),createPreloadedFile:(function(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish){Browser.init();var fullname=name?PATH.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency("cp "+fullname);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}var handled=false;Module["preloadPlugins"].forEach((function(plugin){if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,(function(){if(onerror)onerror();removeRunDependency(dep)}));handled=true}}));if(!handled)finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){Browser.asyncLoad(url,(function(byteArray){processData(byteArray)}),onerror)}else{processData(url)}}),indexedDB:(function(){return window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB}),DB_NAME:(function(){return"EM_FS_"+window.location.pathname}),DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:(function(paths,onload,onerror){onload=onload||(function(){});onerror=onerror||(function(){});var indexedDB=FS.indexedDB();try{var openRequest=indexedDB.open(FS.DB_NAME(),FS.DB_VERSION)}catch(e){return onerror(e)}openRequest.onupgradeneeded=function openRequest_onupgradeneeded(){console.log("creating db");var db=openRequest.result;db.createObjectStore(FS.DB_STORE_NAME)};openRequest.onsuccess=function openRequest_onsuccess(){var db=openRequest.result;var transaction=db.transaction([FS.DB_STORE_NAME],"readwrite");var files=transaction.objectStore(FS.DB_STORE_NAME);var ok=0,fail=0,total=paths.length;function finish(){if(fail==0)onload();else onerror()}paths.forEach((function(path){var putRequest=files.put(FS.analyzePath(path).object.contents,path);putRequest.onsuccess=function putRequest_onsuccess(){ok++;if(ok+fail==total)finish()};putRequest.onerror=function putRequest_onerror(){fail++;if(ok+fail==total)finish()}}));transaction.onerror=onerror};openRequest.onerror=onerror}),loadFilesFromDB:(function(paths,onload,onerror){onload=onload||(function(){});onerror=onerror||(function(){});var indexedDB=FS.indexedDB();try{var openRequest=indexedDB.open(FS.DB_NAME(),FS.DB_VERSION)}catch(e){return onerror(e)}openRequest.onupgradeneeded=onerror;openRequest.onsuccess=function openRequest_onsuccess(){var db=openRequest.result;try{var transaction=db.transaction([FS.DB_STORE_NAME],"readonly")}catch(e){onerror(e);return}var files=transaction.objectStore(FS.DB_STORE_NAME);var ok=0,fail=0,total=paths.length;function finish(){if(fail==0)onload();else onerror()}paths.forEach((function(path){var getRequest=files.get(path);getRequest.onsuccess=function getRequest_onsuccess(){if(FS.analyzePath(path).exists){FS.unlink(path)}FS.createDataFile(PATH.dirname(path),PATH.basename(path),getRequest.result,true,true,true);ok++;if(ok+fail==total)finish()};getRequest.onerror=function getRequest_onerror(){fail++;if(ok+fail==total)finish()}}));transaction.onerror=onerror};openRequest.onerror=onerror})};var SYSCALLS={DEFAULT_POLLMASK:5,mappings:{},umask:511,calculateAt:(function(dirfd,path){if(path[0]!=="/"){var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=FS.getStream(dirfd);if(!dirstream)throw new FS.ErrnoError(ERRNO_CODES.EBADF);dir=dirstream.path}path=PATH.join2(dir,path)}return path}),doStat:(function(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-ERRNO_CODES.ENOTDIR}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=0;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAP32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;HEAP32[buf+32>>2]=0;HEAP32[buf+36>>2]=stat.size;HEAP32[buf+40>>2]=4096;HEAP32[buf+44>>2]=stat.blocks;HEAP32[buf+48>>2]=stat.atime.getTime()/1e3|0;HEAP32[buf+52>>2]=0;HEAP32[buf+56>>2]=stat.mtime.getTime()/1e3|0;HEAP32[buf+60>>2]=0;HEAP32[buf+64>>2]=stat.ctime.getTime()/1e3|0;HEAP32[buf+68>>2]=0;HEAP32[buf+72>>2]=stat.ino;return 0}),doMsync:(function(addr,stream,len,flags){var buffer=new Uint8Array(HEAPU8.subarray(addr,addr+len));FS.msync(stream,buffer,0,len,flags)}),doMkdir:(function(path,mode){path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}),doMknod:(function(path,mode,dev){switch(mode&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-ERRNO_CODES.EINVAL}FS.mknod(path,mode,dev);return 0}),doReadlink:(function(path,buf,bufsize){if(bufsize<=0)return-ERRNO_CODES.EINVAL;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}),doAccess:(function(path,amode){if(amode&~7){return-ERRNO_CODES.EINVAL}var node;var lookup=FS.lookupPath(path,{follow:true});node=lookup.node;var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-ERRNO_CODES.EACCES}return 0}),doDup:(function(path,flags,suggestFD){var suggest=FS.getStream(suggestFD);if(suggest)FS.close(suggest);return FS.open(path,flags,0,suggestFD,suggestFD).fd}),doReadv:(function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAP32[iov+i*8>>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len)break}return ret}),doWritev:(function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAP32[iov+i*8>>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret}),varargs:0,get:(function(varargs){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret}),getStr:(function(){var ret=Pointer_stringify(SYSCALLS.get());return ret}),getStreamFromFD:(function(){var stream=FS.getStream(SYSCALLS.get());if(!stream)throw new FS.ErrnoError(ERRNO_CODES.EBADF);return stream}),getSocketFromFD:(function(){var socket=SOCKFS.getSocket(SYSCALLS.get());if(!socket)throw new FS.ErrnoError(ERRNO_CODES.EBADF);return socket}),getSocketAddress:(function(allowNull){var addrp=SYSCALLS.get(),addrlen=SYSCALLS.get();if(allowNull&&addrp===0)return null;var info=__read_sockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info}),get64:(function(){var low=SYSCALLS.get(),high=SYSCALLS.get();if(low>=0)assert(high===0);else assert(high===-1);return low}),getZero:(function(){assert(SYSCALLS.get()===0)})};function ___syscall114(which,varargs){SYSCALLS.varargs=varargs;try{abort("cannot wait on child processes")}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _pthread_mutex_init(){}var _llvm_pow_f32=Math_pow;var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,lastGamepadState:null,lastGamepadStateFrame:null,numGamepadsConnected:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,staticInit:(function(){if(typeof window!=="undefined"){window.addEventListener("gamepadconnected",(function(){++JSEvents.numGamepadsConnected}));window.addEventListener("gamepaddisconnected",(function(){--JSEvents.numGamepadsConnected}));var firstState=navigator.getGamepads?navigator.getGamepads():navigator.webkitGetGamepads?navigator.webkitGetGamepads():null;if(firstState){JSEvents.numGamepadsConnected=firstState.length}}}),registerRemoveEventListeners:(function(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push((function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}}));JSEvents.removeEventListenersRegistered=true}}),findEventTarget:(function(target){if(target){if(typeof target=="number"){target=Pointer_stringify(target)}if(target=="#window")return window;else if(target=="#document")return document;else if(target=="#screen")return window.screen;else if(target=="#canvas")return Module["canvas"];if(typeof target=="string")return document.getElementById(target);else return target}else{return window}}),deferredCalls:[],deferCall:(function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort((function(x,y){return x.precedence<y.precedence}))}),removeDeferredCalls:(function(targetFunction){for(var i=0;i<JSEvents.deferredCalls.length;++i){if(JSEvents.deferredCalls[i].targetFunction==targetFunction){JSEvents.deferredCalls.splice(i,1);--i}}}),canPerformEventHandlerRequests:(function(){return JSEvents.inEventHandler&&JSEvents.currentEventHandler.allowsDeferredCalls}),runDeferredCalls:(function(){if(!JSEvents.canPerformEventHandlerRequests()){return}for(var i=0;i<JSEvents.deferredCalls.length;++i){var call=JSEvents.deferredCalls[i];JSEvents.deferredCalls.splice(i,1);--i;call.targetFunction.apply(this,call.argsList)}}),inEventHandler:0,currentEventHandler:null,eventHandlers:[],isInternetExplorer:(function(){return navigator.userAgent.indexOf("MSIE")!==-1||navigator.appVersion.indexOf("Trident/")>0}),removeAllHandlersOnTarget:(function(target,eventTypeString){for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==target&&(!eventTypeString||eventTypeString==JSEvents.eventHandlers[i].eventTypeString)){JSEvents._removeHandler(i--)}}}),_removeHandler:(function(i){var h=JSEvents.eventHandlers[i];h.target.removeEventListener(h.eventTypeString,h.eventListenerFunc,h.useCapture);JSEvents.eventHandlers.splice(i,1)}),registerOrRemoveHandler:(function(eventHandler){var jsEventHandler=function jsEventHandler(event){++JSEvents.inEventHandler;JSEvents.currentEventHandler=eventHandler;JSEvents.runDeferredCalls();eventHandler.handlerFunc(event);JSEvents.runDeferredCalls();--JSEvents.inEventHandler};if(eventHandler.callbackfunc){eventHandler.eventListenerFunc=jsEventHandler;eventHandler.target.addEventListener(eventHandler.eventTypeString,jsEventHandler,eventHandler.useCapture);JSEvents.eventHandlers.push(eventHandler);JSEvents.registerRemoveEventListeners()}else{for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==eventHandler.target&&JSEvents.eventHandlers[i].eventTypeString==eventHandler.eventTypeString){JSEvents._removeHandler(i--)}}}}),registerKeyEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.keyEvent){JSEvents.keyEvent=_malloc(164)}var handlerFunc=(function(event){var e=event||window.event;stringToUTF8(e.key?e.key:"",JSEvents.keyEvent+0,32);stringToUTF8(e.code?e.code:"",JSEvents.keyEvent+32,32);HEAP32[JSEvents.keyEvent+64>>2]=e.location;HEAP32[JSEvents.keyEvent+68>>2]=e.ctrlKey;HEAP32[JSEvents.keyEvent+72>>2]=e.shiftKey;HEAP32[JSEvents.keyEvent+76>>2]=e.altKey;HEAP32[JSEvents.keyEvent+80>>2]=e.metaKey;HEAP32[JSEvents.keyEvent+84>>2]=e.repeat;stringToUTF8(e.locale?e.locale:"",JSEvents.keyEvent+88,32);stringToUTF8(e.char?e.char:"",JSEvents.keyEvent+120,32);HEAP32[JSEvents.keyEvent+152>>2]=e.charCode;HEAP32[JSEvents.keyEvent+156>>2]=e.keyCode;HEAP32[JSEvents.keyEvent+160>>2]=e.which;var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.keyEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:JSEvents.isInternetExplorer()?false:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),getBoundingClientRectOrZeros:(function(target){return target.getBoundingClientRect?target.getBoundingClientRect():{left:0,top:0}}),fillMouseEventData:(function(eventStruct,e,target){HEAPF64[eventStruct>>3]=JSEvents.tick();HEAP32[eventStruct+8>>2]=e.screenX;HEAP32[eventStruct+12>>2]=e.screenY;HEAP32[eventStruct+16>>2]=e.clientX;HEAP32[eventStruct+20>>2]=e.clientY;HEAP32[eventStruct+24>>2]=e.ctrlKey;HEAP32[eventStruct+28>>2]=e.shiftKey;HEAP32[eventStruct+32>>2]=e.altKey;HEAP32[eventStruct+36>>2]=e.metaKey;HEAP16[eventStruct+40>>1]=e.button;HEAP16[eventStruct+42>>1]=e.buttons;HEAP32[eventStruct+44>>2]=e["movementX"]||e["mozMovementX"]||e["webkitMovementX"]||e.screenX-JSEvents.previousScreenX;HEAP32[eventStruct+48>>2]=e["movementY"]||e["mozMovementY"]||e["webkitMovementY"]||e.screenY-JSEvents.previousScreenY;if(Module["canvas"]){var rect=Module["canvas"].getBoundingClientRect();HEAP32[eventStruct+60>>2]=e.clientX-rect.left;HEAP32[eventStruct+64>>2]=e.clientY-rect.top}else{HEAP32[eventStruct+60>>2]=0;HEAP32[eventStruct+64>>2]=0}if(target){var rect=JSEvents.getBoundingClientRectOrZeros(target);HEAP32[eventStruct+52>>2]=e.clientX-rect.left;HEAP32[eventStruct+56>>2]=e.clientY-rect.top}else{HEAP32[eventStruct+52>>2]=0;HEAP32[eventStruct+56>>2]=0}if(e.type!=="wheel"&&e.type!=="mousewheel"){JSEvents.previousScreenX=e.screenX;JSEvents.previousScreenY=e.screenY}}),registerMouseEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.mouseEvent){JSEvents.mouseEvent=_malloc(72)}target=JSEvents.findEventTarget(target);var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillMouseEventData(JSEvents.mouseEvent,e,target);var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.mouseEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:eventTypeString!="mousemove"&&eventTypeString!="mouseenter"&&eventTypeString!="mouseleave",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};if(JSEvents.isInternetExplorer()&&eventTypeString=="mousedown")eventHandler.allowsDeferredCalls=false;JSEvents.registerOrRemoveHandler(eventHandler)}),registerWheelEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.wheelEvent){JSEvents.wheelEvent=_malloc(104)}target=JSEvents.findEventTarget(target);var wheelHandlerFunc=(function(event){var e=event||window.event;JSEvents.fillMouseEventData(JSEvents.wheelEvent,e,target);HEAPF64[JSEvents.wheelEvent+72>>3]=e["deltaX"];HEAPF64[JSEvents.wheelEvent+80>>3]=e["deltaY"];HEAPF64[JSEvents.wheelEvent+88>>3]=e["deltaZ"];HEAP32[JSEvents.wheelEvent+96>>2]=e["deltaMode"];var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.wheelEvent,userData);if(shouldCancel){e.preventDefault()}});var mouseWheelHandlerFunc=(function(event){var e=event||window.event;JSEvents.fillMouseEventData(JSEvents.wheelEvent,e,target);HEAPF64[JSEvents.wheelEvent+72>>3]=e["wheelDeltaX"]||0;HEAPF64[JSEvents.wheelEvent+80>>3]=-(e["wheelDeltaY"]?e["wheelDeltaY"]:e["wheelDelta"]);HEAPF64[JSEvents.wheelEvent+88>>3]=0;HEAP32[JSEvents.wheelEvent+96>>2]=0;var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.wheelEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:eventTypeString=="wheel"?wheelHandlerFunc:mouseWheelHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),pageScrollPos:(function(){if(window.pageXOffset>0||window.pageYOffset>0){return[window.pageXOffset,window.pageYOffset]}if(typeof document.documentElement.scrollLeft!=="undefined"||typeof document.documentElement.scrollTop!=="undefined"){return[document.documentElement.scrollLeft,document.documentElement.scrollTop]}return[document.body.scrollLeft|0,document.body.scrollTop|0]}),registerUiEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.uiEvent){JSEvents.uiEvent=_malloc(36)}if(eventTypeString=="scroll"&&!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;if(e.target!=target){return}var scrollPos=JSEvents.pageScrollPos();HEAP32[JSEvents.uiEvent>>2]=e.detail;HEAP32[JSEvents.uiEvent+4>>2]=document.body.clientWidth;HEAP32[JSEvents.uiEvent+8>>2]=document.body.clientHeight;HEAP32[JSEvents.uiEvent+12>>2]=window.innerWidth;HEAP32[JSEvents.uiEvent+16>>2]=window.innerHeight;HEAP32[JSEvents.uiEvent+20>>2]=window.outerWidth;HEAP32[JSEvents.uiEvent+24>>2]=window.outerHeight;HEAP32[JSEvents.uiEvent+28>>2]=scrollPos[0];HEAP32[JSEvents.uiEvent+32>>2]=scrollPos[1];var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.uiEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),getNodeNameForTarget:(function(target){if(!target)return"";if(target==window)return"#window";if(target==window.screen)return"#screen";return target&&target.nodeName?target.nodeName:""}),registerFocusEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.focusEvent){JSEvents.focusEvent=_malloc(256)}var handlerFunc=(function(event){var e=event||window.event;var nodeName=JSEvents.getNodeNameForTarget(e.target);var id=e.target.id?e.target.id:"";stringToUTF8(nodeName,JSEvents.focusEvent+0,128);stringToUTF8(id,JSEvents.focusEvent+128,128);var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.focusEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),tick:(function(){if(window["performance"]&&window["performance"]["now"])return window["performance"]["now"]();else return Date.now()}),registerDeviceOrientationEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.deviceOrientationEvent){JSEvents.deviceOrientationEvent=_malloc(40)}var handlerFunc=(function(event){var e=event||window.event;HEAPF64[JSEvents.deviceOrientationEvent>>3]=JSEvents.tick();HEAPF64[JSEvents.deviceOrientationEvent+8>>3]=e.alpha;HEAPF64[JSEvents.deviceOrientationEvent+16>>3]=e.beta;HEAPF64[JSEvents.deviceOrientationEvent+24>>3]=e.gamma;HEAP32[JSEvents.deviceOrientationEvent+32>>2]=e.absolute;var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.deviceOrientationEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerDeviceMotionEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.deviceMotionEvent){JSEvents.deviceMotionEvent=_malloc(80)}var handlerFunc=(function(event){var e=event||window.event;HEAPF64[JSEvents.deviceMotionEvent>>3]=JSEvents.tick();HEAPF64[JSEvents.deviceMotionEvent+8>>3]=e.acceleration.x;HEAPF64[JSEvents.deviceMotionEvent+16>>3]=e.acceleration.y;HEAPF64[JSEvents.deviceMotionEvent+24>>3]=e.acceleration.z;HEAPF64[JSEvents.deviceMotionEvent+32>>3]=e.accelerationIncludingGravity.x;HEAPF64[JSEvents.deviceMotionEvent+40>>3]=e.accelerationIncludingGravity.y;HEAPF64[JSEvents.deviceMotionEvent+48>>3]=e.accelerationIncludingGravity.z;HEAPF64[JSEvents.deviceMotionEvent+56>>3]=e.rotationRate.alpha;HEAPF64[JSEvents.deviceMotionEvent+64>>3]=e.rotationRate.beta;HEAPF64[JSEvents.deviceMotionEvent+72>>3]=e.rotationRate.gamma;var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.deviceMotionEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),screenOrientation:(function(){if(!window.screen)return undefined;return window.screen.orientation||window.screen.mozOrientation||window.screen.webkitOrientation||window.screen.msOrientation}),fillOrientationChangeEventData:(function(eventStruct,e){var orientations=["portrait-primary","portrait-secondary","landscape-primary","landscape-secondary"];var orientations2=["portrait","portrait","landscape","landscape"];var orientationString=JSEvents.screenOrientation();var orientation=orientations.indexOf(orientationString);if(orientation==-1){orientation=orientations2.indexOf(orientationString)}HEAP32[eventStruct>>2]=1<<orientation;HEAP32[eventStruct+4>>2]=window.orientation}),registerOrientationChangeEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.orientationChangeEvent){JSEvents.orientationChangeEvent=_malloc(8)}if(!target){target=window.screen}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillOrientationChangeEventData(JSEvents.orientationChangeEvent,e);var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.orientationChangeEvent,userData);if(shouldCancel){e.preventDefault()}});if(eventTypeString=="orientationchange"&&window.screen.mozOrientation!==undefined){eventTypeString="mozorientationchange"}var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),fullscreenEnabled:(function(){return document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled}),fillFullscreenChangeEventData:(function(eventStruct,e){var fullscreenElement=document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement;var isFullscreen=!!fullscreenElement;HEAP32[eventStruct>>2]=isFullscreen;HEAP32[eventStruct+4>>2]=JSEvents.fullscreenEnabled();var reportedElement=isFullscreen?fullscreenElement:JSEvents.previousFullscreenElement;var nodeName=JSEvents.getNodeNameForTarget(reportedElement);var id=reportedElement&&reportedElement.id?reportedElement.id:"";stringToUTF8(nodeName,eventStruct+8,128);stringToUTF8(id,eventStruct+136,128);HEAP32[eventStruct+264>>2]=reportedElement?reportedElement.clientWidth:0;HEAP32[eventStruct+268>>2]=reportedElement?reportedElement.clientHeight:0;HEAP32[eventStruct+272>>2]=screen.width;HEAP32[eventStruct+276>>2]=screen.height;if(isFullscreen){JSEvents.previousFullscreenElement=fullscreenElement}}),registerFullscreenChangeEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.fullscreenChangeEvent){JSEvents.fullscreenChangeEvent=_malloc(280)}if(!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillFullscreenChangeEventData(JSEvents.fullscreenChangeEvent,e);var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.fullscreenChangeEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),resizeCanvasForFullscreen:(function(target,strategy){var restoreOldStyle=__registerRestoreOldStyle(target);var cssWidth=strategy.softFullscreen?window.innerWidth:screen.width;var cssHeight=strategy.softFullscreen?window.innerHeight:screen.height;var rect=target.getBoundingClientRect();var windowedCssWidth=rect.right-rect.left;var windowedCssHeight=rect.bottom-rect.top;var windowedRttWidth=target.width;var windowedRttHeight=target.height;if(strategy.scaleMode==3){__setLetterbox(target,(cssHeight-windowedCssHeight)/2,(cssWidth-windowedCssWidth)/2);cssWidth=windowedCssWidth;cssHeight=windowedCssHeight}else if(strategy.scaleMode==2){if(cssWidth*windowedRttHeight<windowedRttWidth*cssHeight){var desiredCssHeight=windowedRttHeight*cssWidth/windowedRttWidth;__setLetterbox(target,(cssHeight-desiredCssHeight)/2,0);cssHeight=desiredCssHeight}else{var desiredCssWidth=windowedRttWidth*cssHeight/windowedRttHeight;__setLetterbox(target,0,(cssWidth-desiredCssWidth)/2);cssWidth=desiredCssWidth}}if(!target.style.backgroundColor)target.style.backgroundColor="black";if(!document.body.style.backgroundColor)document.body.style.backgroundColor="black";target.style.width=cssWidth+"px";target.style.height=cssHeight+"px";if(strategy.filteringMode==1){target.style.imageRendering="optimizeSpeed";target.style.imageRendering="-moz-crisp-edges";target.style.imageRendering="-o-crisp-edges";target.style.imageRendering="-webkit-optimize-contrast";target.style.imageRendering="optimize-contrast";target.style.imageRendering="crisp-edges";target.style.imageRendering="pixelated"}var dpiScale=strategy.canvasResolutionScaleMode==2?window.devicePixelRatio:1;if(strategy.canvasResolutionScaleMode!=0){target.width=cssWidth*dpiScale;target.height=cssHeight*dpiScale;if(target.GLctxObject)target.GLctxObject.GLctx.viewport(0,0,target.width,target.height)}return restoreOldStyle}),requestFullscreen:(function(target,strategy){if(strategy.scaleMode!=0||strategy.canvasResolutionScaleMode!=0){JSEvents.resizeCanvasForFullscreen(target,strategy)}if(target.requestFullscreen){target.requestFullscreen()}else if(target.msRequestFullscreen){target.msRequestFullscreen()}else if(target.mozRequestFullScreen){target.mozRequestFullScreen()}else if(target.mozRequestFullscreen){target.mozRequestFullscreen()}else if(target.webkitRequestFullscreen){target.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}else{if(typeof JSEvents.fullscreenEnabled()==="undefined"){return-1}else{return-3}}if(strategy.canvasResizedCallback){Module["dynCall_iiii"](strategy.canvasResizedCallback,37,0,strategy.canvasResizedCallbackUserData)}return 0}),fillPointerlockChangeEventData:(function(eventStruct,e){var pointerLockElement=document.pointerLockElement||document.mozPointerLockElement||document.webkitPointerLockElement||document.msPointerLockElement;var isPointerlocked=!!pointerLockElement;HEAP32[eventStruct>>2]=isPointerlocked;var nodeName=JSEvents.getNodeNameForTarget(pointerLockElement);var id=pointerLockElement&&pointerLockElement.id?pointerLockElement.id:"";stringToUTF8(nodeName,eventStruct+4,128);stringToUTF8(id,eventStruct+132,128)}),registerPointerlockChangeEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.pointerlockChangeEvent){JSEvents.pointerlockChangeEvent=_malloc(260)}if(!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillPointerlockChangeEventData(JSEvents.pointerlockChangeEvent,e);var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.pointerlockChangeEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerPointerlockErrorEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,0,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),requestPointerLock:(function(target){if(target.requestPointerLock){target.requestPointerLock()}else if(target.mozRequestPointerLock){target.mozRequestPointerLock()}else if(target.webkitRequestPointerLock){target.webkitRequestPointerLock()}else if(target.msRequestPointerLock){target.msRequestPointerLock()}else{if(document.body.requestPointerLock||document.body.mozRequestPointerLock||document.body.webkitRequestPointerLock||document.body.msRequestPointerLock){return-3}else{return-1}}return 0}),fillVisibilityChangeEventData:(function(eventStruct,e){var visibilityStates=["hidden","visible","prerender","unloaded"];var visibilityState=visibilityStates.indexOf(document.visibilityState);HEAP32[eventStruct>>2]=document.hidden;HEAP32[eventStruct+4>>2]=visibilityState}),registerVisibilityChangeEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.visibilityChangeEvent){JSEvents.visibilityChangeEvent=_malloc(8)}if(!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillVisibilityChangeEventData(JSEvents.visibilityChangeEvent,e);var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.visibilityChangeEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerTouchEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.touchEvent){JSEvents.touchEvent=_malloc(1684)}target=JSEvents.findEventTarget(target);var handlerFunc=(function(event){var e=event||window.event;var touches={};for(var i=0;i<e.touches.length;++i){var touch=e.touches[i];touches[touch.identifier]=touch}for(var i=0;i<e.changedTouches.length;++i){var touch=e.changedTouches[i];touches[touch.identifier]=touch;touch.changed=true}for(var i=0;i<e.targetTouches.length;++i){var touch=e.targetTouches[i];touches[touch.identifier].onTarget=true}var ptr=JSEvents.touchEvent;HEAP32[ptr+4>>2]=e.ctrlKey;HEAP32[ptr+8>>2]=e.shiftKey;HEAP32[ptr+12>>2]=e.altKey;HEAP32[ptr+16>>2]=e.metaKey;ptr+=20;var canvasRect=Module["canvas"]?Module["canvas"].getBoundingClientRect():undefined;var targetRect=JSEvents.getBoundingClientRectOrZeros(target);var numTouches=0;for(var i in touches){var t=touches[i];HEAP32[ptr>>2]=t.identifier;HEAP32[ptr+4>>2]=t.screenX;HEAP32[ptr+8>>2]=t.screenY;HEAP32[ptr+12>>2]=t.clientX;HEAP32[ptr+16>>2]=t.clientY;HEAP32[ptr+20>>2]=t.pageX;HEAP32[ptr+24>>2]=t.pageY;HEAP32[ptr+28>>2]=t.changed;HEAP32[ptr+32>>2]=t.onTarget;if(canvasRect){HEAP32[ptr+44>>2]=t.clientX-canvasRect.left;HEAP32[ptr+48>>2]=t.clientY-canvasRect.top}else{HEAP32[ptr+44>>2]=0;HEAP32[ptr+48>>2]=0}HEAP32[ptr+36>>2]=t.clientX-targetRect.left;HEAP32[ptr+40>>2]=t.clientY-targetRect.top;ptr+=52;if(++numTouches>=32){break}}HEAP32[JSEvents.touchEvent>>2]=numTouches;var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.touchEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:eventTypeString=="touchstart"||eventTypeString=="touchend",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),fillGamepadEventData:(function(eventStruct,e){HEAPF64[eventStruct>>3]=e.timestamp;for(var i=0;i<e.axes.length;++i){HEAPF64[eventStruct+i*8+16>>3]=e.axes[i]}for(var i=0;i<e.buttons.length;++i){if(typeof e.buttons[i]==="object"){HEAPF64[eventStruct+i*8+528>>3]=e.buttons[i].value}else{HEAPF64[eventStruct+i*8+528>>3]=e.buttons[i]}}for(var i=0;i<e.buttons.length;++i){if(typeof e.buttons[i]==="object"){HEAP32[eventStruct+i*4+1040>>2]=e.buttons[i].pressed}else{HEAP32[eventStruct+i*4+1040>>2]=e.buttons[i]==1}}HEAP32[eventStruct+1296>>2]=e.connected;HEAP32[eventStruct+1300>>2]=e.index;HEAP32[eventStruct+8>>2]=e.axes.length;HEAP32[eventStruct+12>>2]=e.buttons.length;stringToUTF8(e.id,eventStruct+1304,64);stringToUTF8(e.mapping,eventStruct+1368,64)}),registerGamepadEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.gamepadEvent){JSEvents.gamepadEvent=_malloc(1432)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillGamepadEventData(JSEvents.gamepadEvent,e.gamepad);var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.gamepadEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerBeforeUnloadEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){var handlerFunc=(function(event){var e=event||window.event;var confirmationMessage=Module["dynCall_iiii"](callbackfunc,eventTypeId,0,userData);if(confirmationMessage){confirmationMessage=Pointer_stringify(confirmationMessage)}if(confirmationMessage){e.preventDefault();e.returnValue=confirmationMessage;return confirmationMessage}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),battery:(function(){return navigator.battery||navigator.mozBattery||navigator.webkitBattery}),fillBatteryEventData:(function(eventStruct,e){HEAPF64[eventStruct>>3]=e.chargingTime;HEAPF64[eventStruct+8>>3]=e.dischargingTime;HEAPF64[eventStruct+16>>3]=e.level;HEAP32[eventStruct+24>>2]=e.charging}),registerBatteryEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.batteryEvent){JSEvents.batteryEvent=_malloc(32)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillBatteryEventData(JSEvents.batteryEvent,JSEvents.battery());var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,JSEvents.batteryEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerWebGlEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!target){target=Module["canvas"]}var handlerFunc=(function(event){var e=event||window.event;var shouldCancel=Module["dynCall_iiii"](callbackfunc,eventTypeId,0,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)})};function _emscripten_set_fullscreenchange_callback(target,userData,useCapture,callbackfunc){if(typeof JSEvents.fullscreenEnabled()==="undefined")return-1;if(!target)target=document;else{target=JSEvents.findEventTarget(target);if(!target)return-4}JSEvents.registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"fullscreenchange");JSEvents.registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"mozfullscreenchange");JSEvents.registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"webkitfullscreenchange");JSEvents.registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"msfullscreenchange");return 0}var DLFCN={error:null,errorMsg:null,loadedLibs:{},loadedLibNames:{}};function _dlerror(){if(DLFCN.errorMsg===null){return 0}else{if(DLFCN.error)_free(DLFCN.error);var msgArr=intArrayFromString(DLFCN.errorMsg);DLFCN.error=allocate(msgArr,"i8",ALLOC_NORMAL);DLFCN.errorMsg=null;return DLFCN.error}}function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function ___syscall54(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),op=SYSCALLS.get();switch(op){case 21505:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};case 21506:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};case 21519:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0};case 21520:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return-ERRNO_CODES.EINVAL};case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)};case 21523:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};default:abort("bad ioctl syscall "+op)}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}var ___tm_current=STATICTOP;STATICTOP+=48;var ___tm_timezone=allocate(intArrayFromString("GMT"),"i8",ALLOC_STATIC);var _tzname=STATICTOP;STATICTOP+=16;var _daylight=STATICTOP;STATICTOP+=16;var _timezone=STATICTOP;STATICTOP+=16;function _tzset(){if(_tzset.called)return;_tzset.called=true;HEAP32[_timezone>>2]=-(new Date).getTimezoneOffset()*60;var winter=new Date(2e3,0,1);var summer=new Date(2e3,6,1);HEAP32[_daylight>>2]=Number(winter.getTimezoneOffset()!=summer.getTimezoneOffset());function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=allocate(intArrayFromString(winterName),"i8",ALLOC_NORMAL);var summerNamePtr=allocate(intArrayFromString(summerName),"i8",ALLOC_NORMAL);if(summer.getTimezoneOffset()<winter.getTimezoneOffset()){HEAP32[_tzname>>2]=winterNamePtr;HEAP32[_tzname+4>>2]=summerNamePtr}else{HEAP32[_tzname>>2]=summerNamePtr;HEAP32[_tzname+4>>2]=winterNamePtr}}function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var start=new Date(date.getFullYear(),0,1);var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var summerOffset=(new Date(2e3,6,1)).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=date.getTimezoneOffset()==Math.min(winterOffset,summerOffset)|0;HEAP32[tmPtr+32>>2]=dst;var zonePtr=HEAP32[_tzname+(dst?Runtime.QUANTUM_SIZE:0)>>2];HEAP32[tmPtr+40>>2]=zonePtr;return tmPtr}function _localtime(time){return _localtime_r(time,___tm_current)}function _glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP32[textures+i*4>>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}var PTHREAD_SPECIFIC={};function _pthread_setspecific(key,value){if(!(key in PTHREAD_SPECIFIC)){return ERRNO_CODES.EINVAL}PTHREAD_SPECIFIC[key]=value;return 0}function _glVertexAttrib4f(x0,x1,x2,x3,x4){GLctx["vertexAttrib4f"](x0,x1,x2,x3,x4)}function _glVertexAttribIPointer(index,size,type,stride,ptr){GLctx.vertexAttribIPointer(index,size,type,stride,ptr)}function _dlclose(handle){if(!DLFCN.loadedLibs[handle]){DLFCN.errorMsg="Tried to dlclose() unopened handle: "+handle;return 1}else{var lib_record=DLFCN.loadedLibs[handle];if(--lib_record.refcount==0){if(lib_record.module.cleanups){lib_record.module.cleanups.forEach((function(cleanup){cleanup()}))}delete DLFCN.loadedLibNames[lib_record.name];delete DLFCN.loadedLibs[handle]}return 0}}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}function _pthread_mutexattr_init(){}function _glUniform1f(location,v0){GLctx.uniform1f(GL.uniforms[location],v0)}function ___syscall168(which,varargs){SYSCALLS.varargs=varargs;try{var fds=SYSCALLS.get(),nfds=SYSCALLS.get(),timeout=SYSCALLS.get();var nonzero=0;for(var i=0;i<nfds;i++){var pollfd=fds+8*i;var fd=HEAP32[pollfd>>2];var events=HEAP16[pollfd+4>>1];var mask=32;var stream=FS.getStream(fd);if(stream){mask=SYSCALLS.DEFAULT_POLLMASK;if(stream.stream_ops.poll){mask=stream.stream_ops.poll(stream)}}mask&=events|8|16;if(mask)nonzero++;HEAP16[pollfd+6>>1]=mask}return nonzero}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall195(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr(),buf=SYSCALLS.get();return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _glUniform1i(location,v0){GLctx.uniform1i(GL.uniforms[location],v0)}function _glInvalidateFramebuffer(target,numAttachments,attachments){var list=GL.tempFixedLengthArray[numAttachments];for(var i=0;i<numAttachments;i++){list[i]=HEAP32[attachments+i*4>>2]}GLctx["invalidateFramebuffer"](target,list)}function _glCompressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx["compressedTexImage2D"](target,level,internalFormat,width,height,border,HEAPU8,data,imageSize);return}GLctx["compressedTexImage2D"](target,level,internalFormat,width,height,border,data?HEAPU8.subarray(data,data+imageSize):null)}function _glDisable(x0){GLctx["disable"](x0)}function _glBlendFuncSeparate(x0,x1,x2,x3){GLctx["blendFuncSeparate"](x0,x1,x2,x3)}function _glDrawBuffers(n,bufs){var bufArray=GL.tempFixedLengthArray[n];for(var i=0;i<n;i++){bufArray[i]=HEAP32[bufs+i*4>>2]}GLctx["drawBuffers"](bufArray)}function _emscripten_set_touchcancel_callback(target,userData,useCapture,callbackfunc){JSEvents.registerTouchEventCallback(target,userData,useCapture,callbackfunc,25,"touchcancel");return 0}function _glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(target,framebuffer?GL.framebuffers[framebuffer]:null)}function ___lock(){}function _glCullFace(x0){GLctx["cullFace"](x0)}function _emscripten_set_keyup_callback(target,userData,useCapture,callbackfunc){JSEvents.registerKeyEventCallback(target,userData,useCapture,callbackfunc,3,"keyup");return 0}function _emscripten_webgl_make_context_current(contextHandle){var success=GL.makeContextCurrent(contextHandle);return success?0:-5}function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null;GL.programInfos[id]=null}function _glRenderbufferStorage(x0,x1,x2,x3){GLctx["renderbufferStorage"](x0,x1,x2,x3)}function _emscripten_get_pointerlock_status(pointerlockStatus){if(pointerlockStatus)JSEvents.fillPointerlockChangeEventData(pointerlockStatus);if(!document.body||!document.body.requestPointerLock&&!document.body.mozRequestPointerLock&&!document.body.webkitRequestPointerLock&&!document.body.msRequestPointerLock){return-1}return 0}function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _glClearBufferfv(buffer,drawbuffer,value){GLctx["clearBufferfv"](buffer,drawbuffer,HEAPF32,value>>2)}function _pthread_attr_setdetachstate(){}function _emscripten_set_touchstart_callback(target,userData,useCapture,callbackfunc){JSEvents.registerTouchEventCallback(target,userData,useCapture,callbackfunc,22,"touchstart");return 0}function ___syscall10(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr();FS.unlink(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _glClearBufferfi(x0,x1,x2,x3){GLctx["clearBufferfi"](x0,x1,x2,x3)}function _pthread_attr_init(attr){return 0}function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.timingMode=mode;Browser.mainLoop.timingValue=value;if(!Browser.mainLoop.func){return 1}if(mode==0){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setTimeout(){var timeUntilNextTick=Math.max(0,Browser.mainLoop.tickStartTime+value-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,timeUntilNextTick)};Browser.mainLoop.method="timeout"}else if(mode==1){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_rAF(){Browser.requestAnimationFrame(Browser.mainLoop.runner)};Browser.mainLoop.method="rAF"}else if(mode==2){if(!window["setImmediate"]){var setImmediates=[];var emscriptenMainLoopMessageId="setimmediate";function Browser_setImmediate_messageHandler(event){if(event.source===window&&event.data===emscriptenMainLoopMessageId){event.stopPropagation();setImmediates.shift()()}}window.addEventListener("message",Browser_setImmediate_messageHandler,true);window["setImmediate"]=function Browser_emulated_setImmediate(func){setImmediates.push(func);if(ENVIRONMENT_IS_WORKER){if(Module["setImmediates"]===undefined)Module["setImmediates"]=[];Module["setImmediates"].push(func);window.postMessage({target:emscriptenMainLoopMessageId})}else window.postMessage(emscriptenMainLoopMessageId,"*")}}Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setImmediate(){window["setImmediate"](Browser.mainLoop.runner)};Browser.mainLoop.method="immediate"}return 0}function _emscripten_get_now(){abort()}function _emscripten_set_main_loop(func,fps,simulateInfiniteLoop,arg,noSetTiming){Module["noExitRuntime"]=true;assert(!Browser.mainLoop.func,"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.");Browser.mainLoop.func=func;Browser.mainLoop.arg=arg;var browserIterationFunc;if(typeof arg!=="undefined"){browserIterationFunc=(function(){Module["dynCall_vi"](func,arg)})}else{browserIterationFunc=(function(){Module["dynCall_v"](func)})}var thisMainLoopId=Browser.mainLoop.currentlyRunningMainloop;Browser.mainLoop.runner=function Browser_mainLoop_runner(){if(ABORT)return;if(Browser.mainLoop.queue.length>0){var start=Date.now();var blocker=Browser.mainLoop.queue.shift();blocker.func(blocker.arg);if(Browser.mainLoop.remainingBlockers){var remaining=Browser.mainLoop.remainingBlockers;var next=remaining%1==0?remaining-1:Math.floor(remaining);if(blocker.counted){Browser.mainLoop.remainingBlockers=next}else{next=next+.5;Browser.mainLoop.remainingBlockers=(8*remaining+next)/9}}console.log('main loop blocker "'+blocker.name+'" took '+(Date.now()-start)+" ms");Browser.mainLoop.updateStatus();if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;setTimeout(Browser.mainLoop.runner,0);return}if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0;if(Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else if(Browser.mainLoop.timingMode==0){Browser.mainLoop.tickStartTime=_emscripten_get_now()}if(Browser.mainLoop.method==="timeout"&&Module.ctx){Module.printErr("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!");Browser.mainLoop.method=""}Browser.mainLoop.runIter(browserIterationFunc);if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;if(typeof SDL==="object"&&SDL.audio&&SDL.audio.queueNewAudioData)SDL.audio.queueNewAudioData();Browser.mainLoop.scheduler()};if(!noSetTiming){if(fps&&fps>0)_emscripten_set_main_loop_timing(0,1e3/fps);else _emscripten_set_main_loop_timing(1,1);Browser.mainLoop.scheduler()}if(simulateInfiniteLoop){throw"SimulateInfiniteLoop"}}var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:(function(){Browser.mainLoop.scheduler=null;Browser.mainLoop.currentlyRunningMainloop++}),resume:(function(){Browser.mainLoop.currentlyRunningMainloop++;var timingMode=Browser.mainLoop.timingMode;var timingValue=Browser.mainLoop.timingValue;var func=Browser.mainLoop.func;Browser.mainLoop.func=null;_emscripten_set_main_loop(func,0,false,Browser.mainLoop.arg,true);_emscripten_set_main_loop_timing(timingMode,timingValue);Browser.mainLoop.scheduler()}),updateStatus:(function(){if(Module["setStatus"]){var message=Module["statusMessage"]||"Please wait...";var remaining=Browser.mainLoop.remainingBlockers;var expected=Browser.mainLoop.expectedBlockers;if(remaining){if(remaining<expected){Module["setStatus"](message+" ("+(expected-remaining)+"/"+expected+")")}else{Module["setStatus"](message)}}else{Module["setStatus"]("")}}}),runIter:(function(func){if(ABORT)return;if(Module["preMainLoop"]){var preRet=Module["preMainLoop"]();if(preRet===false){return}}try{func()}catch(e){if(e instanceof ExitStatus){return}else{if(e&&typeof e==="object"&&e.stack)Module.printErr("exception thrown: "+[e,e.stack]);throw e}}if(Module["postMainLoop"])Module["postMainLoop"]()})},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:(function(){if(!Module["preloadPlugins"])Module["preloadPlugins"]=[];if(Browser.initted)return;Browser.initted=true;try{new Blob;Browser.hasBlobConstructor=true}catch(e){Browser.hasBlobConstructor=false;console.log("warning: no blob constructor, cannot create blobs with mimetypes")}Browser.BlobBuilder=typeof MozBlobBuilder!="undefined"?MozBlobBuilder:typeof WebKitBlobBuilder!="undefined"?WebKitBlobBuilder:!Browser.hasBlobConstructor?console.log("warning: no BlobBuilder"):null;Browser.URLObject=typeof window!="undefined"?window.URL?window.URL:window.webkitURL:undefined;if(!Module.noImageDecoding&&typeof Browser.URLObject==="undefined"){console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.");Module.noImageDecoding=true}var imagePlugin={};imagePlugin["canHandle"]=function imagePlugin_canHandle(name){return!Module.noImageDecoding&&/\.(jpg|jpeg|png|bmp)$/i.test(name)};imagePlugin["handle"]=function imagePlugin_handle(byteArray,name,onload,onerror){var b=null;if(Browser.hasBlobConstructor){try{b=new Blob([byteArray],{type:Browser.getMimetype(name)});if(b.size!==byteArray.length){b=new Blob([(new Uint8Array(byteArray)).buffer],{type:Browser.getMimetype(name)})}}catch(e){Runtime.warnOnce("Blob constructor present but fails: "+e+"; falling back to blob builder")}}if(!b){var bb=new Browser.BlobBuilder;bb.append((new Uint8Array(byteArray)).buffer);b=bb.getBlob()}var url=Browser.URLObject.createObjectURL(b);var img=new Image;img.onload=function img_onload(){assert(img.complete,"Image "+name+" could not be decoded");var canvas=document.createElement("canvas");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext("2d");ctx.drawImage(img,0,0);Module["preloadedImages"][name]=canvas;Browser.URLObject.revokeObjectURL(url);if(onload)onload(byteArray)};img.onerror=function img_onerror(event){console.log("Image "+url+" could not be decoded");if(onerror)onerror()};img.src=url};Module["preloadPlugins"].push(imagePlugin);var audioPlugin={};audioPlugin["canHandle"]=function audioPlugin_canHandle(name){return!Module.noAudioDecoding&&name.substr(-4)in{".ogg":1,".wav":1,".mp3":1}};audioPlugin["handle"]=function audioPlugin_handle(byteArray,name,onload,onerror){var done=false;function finish(audio){if(done)return;done=true;Module["preloadedAudios"][name]=audio;if(onload)onload(byteArray)}function fail(){if(done)return;done=true;Module["preloadedAudios"][name]=new Audio;if(onerror)onerror()}if(Browser.hasBlobConstructor){try{var b=new Blob([byteArray],{type:Browser.getMimetype(name)})}catch(e){return fail()}var url=Browser.URLObject.createObjectURL(b);var audio=new Audio;audio.addEventListener("canplaythrough",(function(){finish(audio)}),false);audio.onerror=function audio_onerror(event){if(done)return;console.log("warning: browser could not fully decode audio "+name+", trying slower base64 approach");function encode64(data){var BASE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var PAD="=";var ret="";var leftchar=0;var leftbits=0;for(var i=0;i<data.length;i++){leftchar=leftchar<<8|data[i];leftbits+=8;while(leftbits>=6){var curr=leftchar>>leftbits-6&63;leftbits-=6;ret+=BASE[curr]}}if(leftbits==2){ret+=BASE[(leftchar&3)<<4];ret+=PAD+PAD}else if(leftbits==4){ret+=BASE[(leftchar&15)<<2];ret+=PAD}return ret}audio.src="data:audio/x-"+name.substr(-3)+";base64,"+encode64(byteArray);finish(audio)};audio.src=url;Browser.safeSetTimeout((function(){finish(audio)}),1e4)}else{return fail()}};Module["preloadPlugins"].push(audioPlugin);function pointerLockChange(){Browser.pointerLock=document["pointerLockElement"]===Module["canvas"]||document["mozPointerLockElement"]===Module["canvas"]||document["webkitPointerLockElement"]===Module["canvas"]||document["msPointerLockElement"]===Module["canvas"]}var canvas=Module["canvas"];if(canvas){canvas.requestPointerLock=canvas["requestPointerLock"]||canvas["mozRequestPointerLock"]||canvas["webkitRequestPointerLock"]||canvas["msRequestPointerLock"]||(function(){});canvas.exitPointerLock=document["exitPointerLock"]||document["mozExitPointerLock"]||document["webkitExitPointerLock"]||document["msExitPointerLock"]||(function(){});canvas.exitPointerLock=canvas.exitPointerLock.bind(document);document.addEventListener("pointerlockchange",pointerLockChange,false);document.addEventListener("mozpointerlockchange",pointerLockChange,false);document.addEventListener("webkitpointerlockchange",pointerLockChange,false);document.addEventListener("mspointerlockchange",pointerLockChange,false);if(Module["elementPointerLock"]){canvas.addEventListener("click",(function(ev){if(!Browser.pointerLock&&Module["canvas"].requestPointerLock){Module["canvas"].requestPointerLock();ev.preventDefault()}}),false)}}}),createContext:(function(canvas,useWebGL,setInModule,webGLContextAttributes){if(useWebGL&&Module.ctx&&canvas==Module.canvas)return Module.ctx;var ctx;var contextHandle;if(useWebGL){var contextAttributes={antialias:false,alpha:false};if(webGLContextAttributes){for(var attribute in webGLContextAttributes){contextAttributes[attribute]=webGLContextAttributes[attribute]}}contextHandle=GL.createContext(canvas,contextAttributes);if(contextHandle){ctx=GL.getContext(contextHandle).GLctx}}else{ctx=canvas.getContext("2d")}if(!ctx)return null;if(setInModule){if(!useWebGL)assert(typeof GLctx==="undefined","cannot set in module if GLctx is used, but we are a non-GL context that would replace it");Module.ctx=ctx;if(useWebGL)GL.makeContextCurrent(contextHandle);Module.useWebGL=useWebGL;Browser.moduleContextCreatedCallbacks.forEach((function(callback){callback()}));Browser.init()}return ctx}),destroyContext:(function(canvas,useWebGL,setInModule){}),fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:(function(lockPointer,resizeCanvas,vrDevice){Browser.lockPointer=lockPointer;Browser.resizeCanvas=resizeCanvas;Browser.vrDevice=vrDevice;if(typeof Browser.lockPointer==="undefined")Browser.lockPointer=true;if(typeof Browser.resizeCanvas==="undefined")Browser.resizeCanvas=false;if(typeof Browser.vrDevice==="undefined")Browser.vrDevice=null;var canvas=Module["canvas"];function fullscreenChange(){Browser.isFullscreen=false;var canvasContainer=canvas.parentNode;if((document["fullscreenElement"]||document["mozFullScreenElement"]||document["msFullscreenElement"]||document["webkitFullscreenElement"]||document["webkitCurrentFullScreenElement"])===canvasContainer){canvas.exitFullscreen=document["exitFullscreen"]||document["cancelFullScreen"]||document["mozCancelFullScreen"]||document["msExitFullscreen"]||document["webkitCancelFullScreen"]||(function(){});canvas.exitFullscreen=canvas.exitFullscreen.bind(document);if(Browser.lockPointer)canvas.requestPointerLock();Browser.isFullscreen=true;if(Browser.resizeCanvas)Browser.setFullscreenCanvasSize()}else{canvasContainer.parentNode.insertBefore(canvas,canvasContainer);canvasContainer.parentNode.removeChild(canvasContainer);if(Browser.resizeCanvas)Browser.setWindowedCanvasSize()}if(Module["onFullScreen"])Module["onFullScreen"](Browser.isFullscreen);if(Module["onFullscreen"])Module["onFullscreen"](Browser.isFullscreen);Browser.updateCanvasDimensions(canvas)}if(!Browser.fullscreenHandlersInstalled){Browser.fullscreenHandlersInstalled=true;document.addEventListener("fullscreenchange",fullscreenChange,false);document.addEventListener("mozfullscreenchange",fullscreenChange,false);document.addEventListener("webkitfullscreenchange",fullscreenChange,false);document.addEventListener("MSFullscreenChange",fullscreenChange,false)}var canvasContainer=document.createElement("div");canvas.parentNode.insertBefore(canvasContainer,canvas);canvasContainer.appendChild(canvas);canvasContainer.requestFullscreen=canvasContainer["requestFullscreen"]||canvasContainer["mozRequestFullScreen"]||canvasContainer["msRequestFullscreen"]||(canvasContainer["webkitRequestFullscreen"]?(function(){canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"])}):null)||(canvasContainer["webkitRequestFullScreen"]?(function(){canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"])}):null);if(vrDevice){canvasContainer.requestFullscreen({vrDisplay:vrDevice})}else{canvasContainer.requestFullscreen()}}),requestFullScreen:(function(lockPointer,resizeCanvas,vrDevice){Module.printErr("Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead.");Browser.requestFullScreen=(function(lockPointer,resizeCanvas,vrDevice){return Browser.requestFullscreen(lockPointer,resizeCanvas,vrDevice)});return Browser.requestFullscreen(lockPointer,resizeCanvas,vrDevice)}),nextRAF:0,fakeRequestAnimationFrame:(function(func){var now=Date.now();if(Browser.nextRAF===0){Browser.nextRAF=now+1e3/60}else{while(now+2>=Browser.nextRAF){Browser.nextRAF+=1e3/60}}var delay=Math.max(Browser.nextRAF-now,0);setTimeout(func,delay)}),requestAnimationFrame:function requestAnimationFrame(func){if(typeof window==="undefined"){Browser.fakeRequestAnimationFrame(func)}else{if(!window.requestAnimationFrame){window.requestAnimationFrame=window["requestAnimationFrame"]||window["mozRequestAnimationFrame"]||window["webkitRequestAnimationFrame"]||window["msRequestAnimationFrame"]||window["oRequestAnimationFrame"]||Browser.fakeRequestAnimationFrame}window.requestAnimationFrame(func)}},safeCallback:(function(func){return(function(){if(!ABORT)return func.apply(null,arguments)})}),allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:(function(){Browser.allowAsyncCallbacks=false}),resumeAsyncCallbacks:(function(){Browser.allowAsyncCallbacks=true;if(Browser.queuedAsyncCallbacks.length>0){var callbacks=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[];callbacks.forEach((function(func){func()}))}}),safeRequestAnimationFrame:(function(func){return Browser.requestAnimationFrame((function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}}))}),safeSetTimeout:(function(func,timeout){Module["noExitRuntime"]=true;return setTimeout((function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}}),timeout)}),safeSetInterval:(function(func,timeout){Module["noExitRuntime"]=true;return setInterval((function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}}),timeout)}),getMimetype:(function(name){return{"jpg":"image/jpeg","jpeg":"image/jpeg","png":"image/png","bmp":"image/bmp","ogg":"audio/ogg","wav":"audio/wav","mp3":"audio/mpeg"}[name.substr(name.lastIndexOf(".")+1)]}),getUserMedia:(function(func){if(!window.getUserMedia){window.getUserMedia=navigator["getUserMedia"]||navigator["mozGetUserMedia"]}window.getUserMedia(func)}),getMovementX:(function(event){return event["movementX"]||event["mozMovementX"]||event["webkitMovementX"]||0}),getMovementY:(function(event){return event["movementY"]||event["mozMovementY"]||event["webkitMovementY"]||0}),getMouseWheelDelta:(function(event){var delta=0;switch(event.type){case"DOMMouseScroll":delta=event.detail;break;case"mousewheel":delta=event.wheelDelta;break;case"wheel":delta=event["deltaY"];break;default:throw"unrecognized mouse wheel event: "+event.type}return delta}),mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:(function(event){if(Browser.pointerLock){if(event.type!="mousemove"&&"mozMovementX"in event){Browser.mouseMovementX=Browser.mouseMovementY=0}else{Browser.mouseMovementX=Browser.getMovementX(event);Browser.mouseMovementY=Browser.getMovementY(event)}if(typeof SDL!="undefined"){Browser.mouseX=SDL.mouseX+Browser.mouseMovementX;Browser.mouseY=SDL.mouseY+Browser.mouseMovementY}else{Browser.mouseX+=Browser.mouseMovementX;Browser.mouseY+=Browser.mouseMovementY}}else{var rect=Module["canvas"].getBoundingClientRect();var cw=Module["canvas"].width;var ch=Module["canvas"].height;var scrollX=typeof window.scrollX!=="undefined"?window.scrollX:window.pageXOffset;var scrollY=typeof window.scrollY!=="undefined"?window.scrollY:window.pageYOffset;if(event.type==="touchstart"||event.type==="touchend"||event.type==="touchmove"){var touch=event.touch;if(touch===undefined){return}var adjustedX=touch.pageX-(scrollX+rect.left);var adjustedY=touch.pageY-(scrollY+rect.top);adjustedX=adjustedX*(cw/rect.width);adjustedY=adjustedY*(ch/rect.height);var coords={x:adjustedX,y:adjustedY};if(event.type==="touchstart"){Browser.lastTouches[touch.identifier]=coords;Browser.touches[touch.identifier]=coords}else if(event.type==="touchend"||event.type==="touchmove"){var last=Browser.touches[touch.identifier];if(!last)last=coords;Browser.lastTouches[touch.identifier]=last;Browser.touches[touch.identifier]=coords}return}var x=event.pageX-(scrollX+rect.left);var y=event.pageY-(scrollY+rect.top);x=x*(cw/rect.width);y=y*(ch/rect.height);Browser.mouseMovementX=x-Browser.mouseX;Browser.mouseMovementY=y-Browser.mouseY;Browser.mouseX=x;Browser.mouseY=y}}),asyncLoad:(function(url,onload,onerror,noRunDep){var dep=!noRunDep?getUniqueRunDependency("al "+url):"";Module["readAsync"](url,(function(arrayBuffer){assert(arrayBuffer,'Loading data file "'+url+'" failed (no arrayBuffer).');onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)}),(function(event){if(onerror){onerror()}else{throw'Loading data file "'+url+'" failed.'}}));if(dep)addRunDependency(dep)}),resizeListeners:[],updateResizeListeners:(function(){var canvas=Module["canvas"];Browser.resizeListeners.forEach((function(listener){listener(canvas.width,canvas.height)}))}),setCanvasSize:(function(width,height,noUpdates){var canvas=Module["canvas"];Browser.updateCanvasDimensions(canvas,width,height);if(!noUpdates)Browser.updateResizeListeners()}),windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:(function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];flags=flags|8388608;HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=flags}Browser.updateResizeListeners()}),setWindowedCanvasSize:(function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];flags=flags&~8388608;HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=flags}Browser.updateResizeListeners()}),updateCanvasDimensions:(function(canvas,wNative,hNative){if(wNative&&hNative){canvas.widthNative=wNative;canvas.heightNative=hNative}else{wNative=canvas.widthNative;hNative=canvas.heightNative}var w=wNative;var h=hNative;if(Module["forcedAspectRatio"]&&Module["forcedAspectRatio"]>0){if(w/h<Module["forcedAspectRatio"]){w=Math.round(h*Module["forcedAspectRatio"])}else{h=Math.round(w/Module["forcedAspectRatio"])}}if((document["fullscreenElement"]||document["mozFullScreenElement"]||document["msFullscreenElement"]||document["webkitFullscreenElement"]||document["webkitCurrentFullScreenElement"])===canvas.parentNode&&typeof screen!="undefined"){var factor=Math.min(screen.width/w,screen.height/h);w=Math.round(w*factor);h=Math.round(h*factor)}if(Browser.resizeCanvas){if(canvas.width!=w)canvas.width=w;if(canvas.height!=h)canvas.height=h;if(typeof canvas.style!="undefined"){canvas.style.removeProperty("width");canvas.style.removeProperty("height")}}else{if(canvas.width!=wNative)canvas.width=wNative;if(canvas.height!=hNative)canvas.height=hNative;if(typeof canvas.style!="undefined"){if(w!=wNative||h!=hNative){canvas.style.setProperty("width",w+"px","important");canvas.style.setProperty("height",h+"px","important")}else{canvas.style.removeProperty("width");canvas.style.removeProperty("height")}}}}),wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:(function(){var handle=Browser.nextWgetRequestHandle;Browser.nextWgetRequestHandle++;return handle})};function _emscripten_get_canvas_size(width,height,isFullscreen){var canvas=Module["canvas"];HEAP32[width>>2]=canvas.width;HEAP32[height>>2]=canvas.height;HEAP32[isFullscreen>>2]=Browser.isFullscreen?1:0}function _glDrawElements(mode,count,type,indices){GLctx.drawElements(mode,count,type,indices)}function ___syscall5(which,varargs){SYSCALLS.varargs=varargs;try{var pathname=SYSCALLS.getStr(),flags=SYSCALLS.get(),mode=SYSCALLS.get();var stream=FS.open(pathname,flags,mode);return stream.fd}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}var _environ=STATICTOP;STATICTOP+=16;var ___environ=_environ;function ___buildEnvironment(env){var MAX_ENV_VALUES=64;var TOTAL_ENV_SIZE=1024;var poolPtr;var envPtr;if(!___buildEnvironment.called){___buildEnvironment.called=true;ENV["USER"]=ENV["LOGNAME"]="web_user";ENV["PATH"]="/";ENV["PWD"]="/";ENV["HOME"]="/home/web_user";ENV["LANG"]="C";ENV["_"]=Module["thisProgram"];poolPtr=allocate(TOTAL_ENV_SIZE,"i8",ALLOC_STATIC);envPtr=allocate(MAX_ENV_VALUES*4,"i8*",ALLOC_STATIC);HEAP32[envPtr>>2]=poolPtr;HEAP32[_environ>>2]=envPtr}else{envPtr=HEAP32[_environ>>2];poolPtr=HEAP32[envPtr>>2]}var strings=[];var totalSize=0;for(var key in env){if(typeof env[key]==="string"){var line=key+"="+env[key];strings.push(line);totalSize+=line.length}}if(totalSize>TOTAL_ENV_SIZE){throw new Error("Environment size exceeded TOTAL_ENV_SIZE!")}var ptrSize=4;for(var i=0;i<strings.length;i++){var line=strings[i];writeAsciiToMemory(line,poolPtr);HEAP32[envPtr+i*ptrSize>>2]=poolPtr;poolPtr+=line.length+1}HEAP32[envPtr+strings.length*ptrSize>>2]=0}var ENV={};function _dlopen(filename,flag){abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/kripken/emscripten/wiki/Linking");var searchpaths=[];if(filename===0){filename="__self__"}else{var strfilename=Pointer_stringify(filename);var isValidFile=(function(filename){var target=FS.findObject(filename);return target&&!target.isFolder&&!target.isDevice});if(isValidFile(strfilename)){filename=strfilename}else{if(ENV["LD_LIBRARY_PATH"]){searchpaths=ENV["LD_LIBRARY_PATH"].split(":")}for(var ident in searchpaths){var searchfile=PATH.join2(searchpaths[ident],strfilename);if(isValidFile(searchfile)){filename=searchfile;break}}}}if(DLFCN.loadedLibNames[filename]){var handle=DLFCN.loadedLibNames[filename];DLFCN.loadedLibs[handle].refcount++;return handle}if(filename==="__self__"){var handle=-1;var lib_module=Module;var cached_functions={}}else{var target=FS.findObject(filename);if(!target||target.isFolder||target.isDevice){DLFCN.errorMsg="Could not find dynamic lib: "+filename;return 0}FS.forceLoadFile(target);var lib_module;try{var lib_data=FS.readFile(filename,{encoding:"binary"});if(!(lib_data instanceof Uint8Array))lib_data=new Uint8Array(lib_data);lib_module=Runtime.loadWebAssemblyModule(lib_data)}catch(e){DLFCN.errorMsg="Could not evaluate dynamic lib: "+filename+"\n"+e;return 0}var handle=1;for(var key in DLFCN.loadedLibs){if(DLFCN.loadedLibs.hasOwnProperty(key))handle++}if(flag&256){for(var ident in lib_module){if(lib_module.hasOwnProperty(ident)){if(ident[0]=="_"){Module[ident]=lib_module[ident]}}}}var cached_functions={}}DLFCN.loadedLibs[handle]={refcount:1,name:filename,module:lib_module,cached_functions:cached_functions};DLFCN.loadedLibNames[filename]=handle;return handle}function ___syscall6(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD();FS.close(stream);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _glGenVertexArrays(n,arrays){for(var i=0;i<n;i++){var vao=GLctx["createVertexArray"]();if(!vao){GL.recordError(1282);while(i<n)HEAP32[arrays+i++*4>>2]=0;return}var id=GL.getNewId(GL.vaos);vao.name=id;GL.vaos[id]=vao;HEAP32[arrays+i*4>>2]=id}}function _pthread_rwlock_init(){return 0}function _glUniform1iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform1iv(GL.uniforms[location],HEAP32,value>>2,count);return}GLctx.uniform1iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*4>>2))}function _glReadBuffer(x0){GLctx["readBuffer"](x0)}function _sigemptyset(set){HEAP32[set>>2]=0;return 0}function emscriptenWebGLComputeImageSize(width,height,sizePerPixel,alignment){function roundedToNextMultipleOf(x,y){return Math.floor((x+y-1)/y)*y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height<=0?0:(height-1)*alignedRowSize+plainRowSize}function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat){var sizePerPixel;var numChannels;switch(format){case 6406:case 6409:case 6402:case 6403:case 36244:numChannels=1;break;case 6410:case 33319:case 33320:numChannels=2;break;case 6407:case 35904:case 36248:numChannels=3;break;case 6408:case 35906:case 36249:numChannels=4;break;default:GL.recordError(1280);return null}switch(type){case 5121:case 5120:sizePerPixel=numChannels*1;break;case 5123:case 36193:case 5131:case 5122:sizePerPixel=numChannels*2;break;case 5125:case 5126:case 5124:sizePerPixel=numChannels*4;break;case 34042:case 35902:case 33640:case 35899:case 34042:sizePerPixel=4;break;case 33635:case 32819:case 32820:sizePerPixel=2;break;default:GL.recordError(1280);return null}var bytes=emscriptenWebGLComputeImageSize(width,height,sizePerPixel,GL.unpackAlignment);switch(type){case 5120:return HEAP8.subarray(pixels,pixels+bytes);case 5121:return HEAPU8.subarray(pixels,pixels+bytes);case 5122:return HEAP16.subarray(pixels>>1,pixels+bytes>>1);case 5124:return HEAP32.subarray(pixels>>2,pixels+bytes>>2);case 5126:return HEAPF32.subarray(pixels>>2,pixels+bytes>>2);case 5125:case 34042:case 35902:case 33640:case 35899:case 34042:return HEAPU32.subarray(pixels>>2,pixels+bytes>>2);case 5123:case 33635:case 32819:case 32820:case 36193:case 5131:return HEAPU16.subarray(pixels>>1,pixels+bytes>>1);default:GL.recordError(1280);return null}}function emscriptenWebGLGetHeapForType(type){switch(type){case 5120:return HEAP8;case 5121:return HEAPU8;case 5122:return HEAP16;case 5123:case 33635:case 32819:case 32820:case 36193:case 5131:return HEAPU16;case 5124:return HEAP32;case 5125:case 34042:case 35902:case 33640:case 35899:case 34042:return HEAPU32;case 5126:return HEAPF32;default:return null}}function emscriptenWebGLGetShiftForType(type){switch(type){case 5120:case 5121:return 0;case 5122:case 5123:case 33635:case 32819:case 32820:case 36193:case 5131:return 1;case 5124:case 5126:case 5125:case 34042:case 35902:case 33640:case 35899:case 34042:return 2;default:return 0}}function _glTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels){if(GLctx.currentPixelUnpackBufferBinding){GLctx["texSubImage3D"](target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)}else if(pixels!=0){GLctx["texSubImage3D"](target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx["texSubImage3D"](target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,null)}}function _glDrawArraysInstanced(mode,first,count,primcount){GLctx["drawArraysInstanced"](mode,first,count,primcount)}function _glGenerateMipmap(x0){GLctx["generateMipmap"](x0)}function ___syscall140(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),offset_high=SYSCALLS.get(),offset_low=SYSCALLS.get(),result=SYSCALLS.get(),whence=SYSCALLS.get();var offset=offset_low;FS.llseek(stream,offset,whence);HEAP32[result>>2]=stream.position;if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall268(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr(),size=SYSCALLS.get(),buf=SYSCALLS.get();assert(size===64);HEAP32[buf+4>>2]=4096;HEAP32[buf+40>>2]=4096;HEAP32[buf+8>>2]=1e6;HEAP32[buf+12>>2]=5e5;HEAP32[buf+16>>2]=5e5;HEAP32[buf+20>>2]=FS.nextInode;HEAP32[buf+24>>2]=1e6;HEAP32[buf+28>>2]=42;HEAP32[buf+44>>2]=2;HEAP32[buf+36>>2]=255;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall146(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();return SYSCALLS.doWritev(stream,iov,iovcnt)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]);return sum}var __MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var __MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function __addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=__isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?Pointer_stringify(tm_zone):""};var pattern=Pointer_stringify(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value==="number"?value.toString():value||"";while(str.length<digits){str=character[0]+str}return str}function leadingNulls(value,digits){return leadingSomething(value,digits,"0")}function compareByDay(date1,date2){function sgn(value){return value<0?-1:value>0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}else{return thisDate.getFullYear()}}else{return thisDate.getFullYear()-1}}var EXPANSION_RULES_2={"%a":(function(date){return WEEKDAYS[date.tm_wday].substring(0,3)}),"%A":(function(date){return WEEKDAYS[date.tm_wday]}),"%b":(function(date){return MONTHS[date.tm_mon].substring(0,3)}),"%B":(function(date){return MONTHS[date.tm_mon]}),"%C":(function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)}),"%d":(function(date){return leadingNulls(date.tm_mday,2)}),"%e":(function(date){return leadingSomething(date.tm_mday,2," ")}),"%g":(function(date){return getWeekBasedYear(date).toString().substring(2)}),"%G":(function(date){return getWeekBasedYear(date)}),"%H":(function(date){return leadingNulls(date.tm_hour,2)}),"%I":(function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)}),"%j":(function(date){return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900)?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,date.tm_mon-1),3)}),"%m":(function(date){return leadingNulls(date.tm_mon+1,2)}),"%M":(function(date){return leadingNulls(date.tm_min,2)}),"%n":(function(){return"\n"}),"%p":(function(date){if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}else{return"PM"}}),"%S":(function(date){return leadingNulls(date.tm_sec,2)}),"%t":(function(){return"\t"}),"%u":(function(date){var day=new Date(date.tm_year+1900,date.tm_mon+1,date.tm_mday,0,0,0,0);return day.getDay()||7}),"%U":(function(date){var janFirst=new Date(date.tm_year+1900,0,1);var firstSunday=janFirst.getDay()===0?janFirst:__addDays(janFirst,7-janFirst.getDay());var endDate=new Date(date.tm_year+1900,date.tm_mon,date.tm_mday);if(compareByDay(firstSunday,endDate)<0){var februaryFirstUntilEndMonth=__arraySum(__isLeapYear(endDate.getFullYear())?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,endDate.getMonth()-1)-31;var firstSundayUntilEndJanuary=31-firstSunday.getDate();var days=firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();return leadingNulls(Math.ceil(days/7),2)}return compareByDay(firstSunday,janFirst)===0?"01":"00"}),"%V":(function(date){var janFourthThisYear=new Date(date.tm_year+1900,0,4);var janFourthNextYear=new Date(date.tm_year+1901,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);var endDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);if(compareByDay(endDate,firstWeekStartThisYear)<0){return"53"}if(compareByDay(firstWeekStartNextYear,endDate)<=0){return"01"}var daysDifference;if(firstWeekStartThisYear.getFullYear()<date.tm_year+1900){daysDifference=date.tm_yday+32-firstWeekStartThisYear.getDate()}else{daysDifference=date.tm_yday+1-firstWeekStartThisYear.getDate()}return leadingNulls(Math.ceil(daysDifference/7),2)}),"%w":(function(date){var day=new Date(date.tm_year+1900,date.tm_mon+1,date.tm_mday,0,0,0,0);return day.getDay()}),"%W":(function(date){var janFirst=new Date(date.tm_year,0,1);var firstMonday=janFirst.getDay()===1?janFirst:__addDays(janFirst,janFirst.getDay()===0?1:7-janFirst.getDay()+1);var endDate=new Date(date.tm_year+1900,date.tm_mon,date.tm_mday);if(compareByDay(firstMonday,endDate)<0){var februaryFirstUntilEndMonth=__arraySum(__isLeapYear(endDate.getFullYear())?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,endDate.getMonth()-1)-31;var firstMondayUntilEndJanuary=31-firstMonday.getDate();var days=firstMondayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();return leadingNulls(Math.ceil(days/7),2)}return compareByDay(firstMonday,janFirst)===0?"01":"00"}),"%y":(function(date){return(date.tm_year+1900).toString().substring(2)}),"%Y":(function(date){return date.tm_year+1900}),"%z":(function(date){var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)}),"%Z":(function(date){return date.tm_zone}),"%%":(function(){return"%"})};for(var rule in EXPANSION_RULES_2){if(pattern.indexOf(rule)>=0){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function ___syscall145(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();return SYSCALLS.doReadv(stream,iov,iovcnt)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _atexit(func,arg){__ATEXIT__.unshift({func:func,arg:arg})}function ___cxa_atexit(){return _atexit.apply(null,arguments)}function _glUnmapBuffer(){Module["printErr"]("missing function: glUnmapBuffer");abort(-1)}function _emscripten_set_touchend_callback(target,userData,useCapture,callbackfunc){JSEvents.registerTouchEventCallback(target,userData,useCapture,callbackfunc,23,"touchend");return 0}function __setLetterbox(element,topBottom,leftRight){if(JSEvents.isInternetExplorer()){element.style.marginLeft=element.style.marginRight=leftRight+"px";element.style.marginTop=element.style.marginBottom=topBottom+"px"}else{element.style.paddingLeft=element.style.paddingRight=leftRight+"px";element.style.paddingTop=element.style.paddingBottom=topBottom+"px"}}function _emscripten_do_request_fullscreen(target,strategy){if(typeof JSEvents.fullscreenEnabled()==="undefined")return-1;if(!JSEvents.fullscreenEnabled())return-3;if(!target)target="#canvas";target=JSEvents.findEventTarget(target);if(!target)return-4;if(!target.requestFullscreen&&!target.msRequestFullscreen&&!target.mozRequestFullScreen&&!target.mozRequestFullscreen&&!target.webkitRequestFullscreen){return-3}var canPerformRequests=JSEvents.canPerformEventHandlerRequests();if(!canPerformRequests){if(strategy.deferUntilInEventHandler){JSEvents.deferCall(JSEvents.requestFullscreen,1,[target,strategy]);return 1}else{return-2}}return JSEvents.requestFullscreen(target,strategy)}var __currentFullscreenStrategy={};function __registerRestoreOldStyle(canvas){var oldWidth=canvas.width;var oldHeight=canvas.height;var oldCssWidth=canvas.style.width;var oldCssHeight=canvas.style.height;var oldBackgroundColor=canvas.style.backgroundColor;var oldDocumentBackgroundColor=document.body.style.backgroundColor;var oldPaddingLeft=canvas.style.paddingLeft;var oldPaddingRight=canvas.style.paddingRight;var oldPaddingTop=canvas.style.paddingTop;var oldPaddingBottom=canvas.style.paddingBottom;var oldMarginLeft=canvas.style.marginLeft;var oldMarginRight=canvas.style.marginRight;var oldMarginTop=canvas.style.marginTop;var oldMarginBottom=canvas.style.marginBottom;var oldDocumentBodyMargin=document.body.style.margin;var oldDocumentOverflow=document.documentElement.style.overflow;var oldDocumentScroll=document.body.scroll;var oldImageRendering=canvas.style.imageRendering;function restoreOldStyle(){var fullscreenElement=document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement;if(!fullscreenElement){document.removeEventListener("fullscreenchange",restoreOldStyle);document.removeEventListener("mozfullscreenchange",restoreOldStyle);document.removeEventListener("webkitfullscreenchange",restoreOldStyle);document.removeEventListener("MSFullscreenChange",restoreOldStyle);canvas.width=oldWidth;canvas.height=oldHeight;canvas.style.width=oldCssWidth;canvas.style.height=oldCssHeight;canvas.style.backgroundColor=oldBackgroundColor;if(!oldDocumentBackgroundColor)document.body.style.backgroundColor="white";document.body.style.backgroundColor=oldDocumentBackgroundColor;canvas.style.paddingLeft=oldPaddingLeft;canvas.style.paddingRight=oldPaddingRight;canvas.style.paddingTop=oldPaddingTop;canvas.style.paddingBottom=oldPaddingBottom;canvas.style.marginLeft=oldMarginLeft;canvas.style.marginRight=oldMarginRight;canvas.style.marginTop=oldMarginTop;canvas.style.marginBottom=oldMarginBottom;document.body.style.margin=oldDocumentBodyMargin;document.documentElement.style.overflow=oldDocumentOverflow;document.body.scroll=oldDocumentScroll;canvas.style.imageRendering=oldImageRendering;if(canvas.GLctxObject)canvas.GLctxObject.GLctx.viewport(0,0,oldWidth,oldHeight);if(__currentFullscreenStrategy.canvasResizedCallback){Module["dynCall_iiii"](__currentFullscreenStrategy.canvasResizedCallback,37,0,__currentFullscreenStrategy.canvasResizedCallbackUserData)}}}document.addEventListener("fullscreenchange",restoreOldStyle);document.addEventListener("mozfullscreenchange",restoreOldStyle);document.addEventListener("webkitfullscreenchange",restoreOldStyle);document.addEventListener("MSFullscreenChange",restoreOldStyle);return restoreOldStyle}function _emscripten_request_fullscreen_strategy(target,deferUntilInEventHandler,fullscreenStrategy){var strategy={};strategy.scaleMode=HEAP32[fullscreenStrategy>>2];strategy.canvasResolutionScaleMode=HEAP32[fullscreenStrategy+4>>2];strategy.filteringMode=HEAP32[fullscreenStrategy+8>>2];strategy.deferUntilInEventHandler=deferUntilInEventHandler;strategy.canvasResizedCallback=HEAP32[fullscreenStrategy+12>>2];strategy.canvasResizedCallbackUserData=HEAP32[fullscreenStrategy+16>>2];__currentFullscreenStrategy=strategy;return _emscripten_do_request_fullscreen(target,strategy)}function _glBindRenderbuffer(target,renderbuffer){GLctx.bindRenderbuffer(target,renderbuffer?GL.renderbuffers[renderbuffer]:null)}function _pthread_rwlock_tryrdlock(){return 0}function _glDeleteFramebuffers(n,framebuffers){for(var i=0;i<n;++i){var id=HEAP32[framebuffers+i*4>>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}}function _glDrawArrays(mode,first,count){GLctx.drawArrays(mode,first,count)}function _glUniform1ui(location,v0){GLctx.uniform1ui(GL.uniforms[location],v0)}function __emscripten_sample_gamepad_data(){if(!JSEvents.numGamepadsConnected)return;if(Browser.mainLoop.currentFrameNumber!==JSEvents.lastGamepadStateFrame||!Browser.mainLoop.currentFrameNumber){JSEvents.lastGamepadState=navigator.getGamepads?navigator.getGamepads():navigator.webkitGetGamepads?navigator.webkitGetGamepads:null;JSEvents.lastGamepadStateFrame=Browser.mainLoop.currentFrameNumber}}function _emscripten_get_num_gamepads(){if(!JSEvents.numGamepadsConnected)return 0;__emscripten_sample_gamepad_data();if(!JSEvents.lastGamepadState)return-1;return JSEvents.lastGamepadState.length}function _sigaction(signum,act,oldact){return 0}function _usleep(useconds){var msec=useconds/1e3;if((ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&self["performance"]&&self["performance"]["now"]){var start=self["performance"]["now"]();while(self["performance"]["now"]()-start<msec){}}else{var start=Date.now();while(Date.now()-start<msec){}}return 0}function _nanosleep(rqtp,rmtp){var seconds=HEAP32[rqtp>>2];var nanoseconds=HEAP32[rqtp+4>>2];if(rmtp!==0){HEAP32[rmtp>>2]=0;HEAP32[rmtp+4>>2]=0}return _usleep(seconds*1e6+nanoseconds/1e3)}function _glClear(x0){GLctx["clear"](x0)}function _emscripten_set_resize_callback(target,userData,useCapture,callbackfunc){JSEvents.registerUiEventCallback(target,userData,useCapture,callbackfunc,10,"resize");return 0}function _glActiveTexture(x0){GLctx["activeTexture"](x0)}function _glEnableVertexAttribArray(index){GLctx.enableVertexAttribArray(index)}function _emscripten_get_fullscreen_status(fullscreenStatus){if(typeof JSEvents.fullscreenEnabled()==="undefined")return-1;JSEvents.fillFullscreenChangeEventData(fullscreenStatus);return 0}function _posix_spawn_file_actions_destroy(){Module["printErr"]("missing function: posix_spawn_file_actions_destroy");abort(-1)}function _glUniform4f(location,v0,v1,v2,v3){GLctx.uniform4f(GL.uniforms[location],v0,v1,v2,v3)}function _glRenderbufferStorageMultisample(x0,x1,x2,x3,x4){GLctx["renderbufferStorageMultisample"](x0,x1,x2,x3,x4)}function _emscripten_request_pointerlock(target,deferUntilInEventHandler){if(!target)target="#canvas";target=JSEvents.findEventTarget(target);if(!target)return-4;if(!target.requestPointerLock&&!target.mozRequestPointerLock&&!target.webkitRequestPointerLock&&!target.msRequestPointerLock){return-1}var canPerformRequests=JSEvents.canPerformEventHandlerRequests();if(!canPerformRequests){if(deferUntilInEventHandler){JSEvents.deferCall(JSEvents.requestPointerLock,2,[target]);return 1}else{return-2}}return JSEvents.requestPointerLock(target)}function _execl(){___setErrNo(ERRNO_CODES.ENOEXEC);return-1}function _execvp(){return _execl.apply(null,arguments)}function _emscripten_webgl_create_context(target,attributes){var contextAttributes={};contextAttributes["alpha"]=!!HEAP32[attributes>>2];contextAttributes["depth"]=!!HEAP32[attributes+4>>2];contextAttributes["stencil"]=!!HEAP32[attributes+8>>2];contextAttributes["antialias"]=!!HEAP32[attributes+12>>2];contextAttributes["premultipliedAlpha"]=!!HEAP32[attributes+16>>2];contextAttributes["preserveDrawingBuffer"]=!!HEAP32[attributes+20>>2];contextAttributes["preferLowPowerToHighPerformance"]=!!HEAP32[attributes+24>>2];contextAttributes["failIfMajorPerformanceCaveat"]=!!HEAP32[attributes+28>>2];contextAttributes["majorVersion"]=HEAP32[attributes+32>>2];contextAttributes["minorVersion"]=HEAP32[attributes+36>>2];contextAttributes["explicitSwapControl"]=HEAP32[attributes+44>>2];target=Pointer_stringify(target);var canvas;if((!target||target==="#canvas")&&Module["canvas"]){canvas=Module["canvas"].id?GL.offscreenCanvases[Module["canvas"].id]||JSEvents.findEventTarget(Module["canvas"].id):Module["canvas"]}else{canvas=GL.offscreenCanvases[target]||JSEvents.findEventTarget(target)}if(!canvas){return 0}if(contextAttributes["explicitSwapControl"]){console.error("emscripten_webgl_create_context failed: explicitSwapControl is not supported, please rebuild with -s OFFSCREENCANVAS_SUPPORT=1 to enable targeting the experimental OffscreenCanvas specification!");return 0}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _gettimeofday(ptr){var now=Date.now();HEAP32[ptr>>2]=now/1e3|0;HEAP32[ptr+4>>2]=now%1e3*1e3|0;return 0}function _glGenFramebuffers(n,ids){for(var i=0;i<n;++i){var framebuffer=GLctx.createFramebuffer();if(!framebuffer){GL.recordError(1282);while(i<n)HEAP32[ids+i++*4>>2]=0;return}var id=GL.getNewId(GL.framebuffers);framebuffer.name=id;GL.framebuffers[id]=framebuffer;HEAP32[ids+i*4>>2]=id}}function _pthread_mutex_destroy(){}function _glUniformBlockBinding(program,uniformBlockIndex,uniformBlockBinding){program=GL.programs[program];GLctx["uniformBlockBinding"](program,uniformBlockIndex,uniformBlockBinding)}function _glDeleteVertexArrays(n,vaos){for(var i=0;i<n;i++){var id=HEAP32[vaos+i*4>>2];GLctx["deleteVertexArray"](GL.vaos[id]);GL.vaos[id]=null}}function _llvm_trap(){abort("trap!")}function _pthread_rwlock_unlock(){return 0}function _glDisableVertexAttribArray(index){GLctx.disableVertexAttribArray(index)}function _sysconf(name){switch(name){case 30:return PAGE_SIZE;case 85:var maxHeapSize=2*1024*1024*1024-65536;return maxHeapSize/PAGE_SIZE;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:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}___setErrNo(ERRNO_CODES.EINVAL);return-1}function _dlsym(handle,symbol){symbol=Pointer_stringify(symbol);if(!DLFCN.loadedLibs[handle]){DLFCN.errorMsg="Tried to dlsym() from an unopened handle: "+handle;return 0}else{var lib=DLFCN.loadedLibs[handle];symbol="_"+symbol;if(lib.cached_functions.hasOwnProperty(symbol)){return lib.cached_functions[symbol]}if(!lib.module.hasOwnProperty(symbol)){DLFCN.errorMsg='Tried to lookup unknown symbol "'+symbol+'" in dynamic lib: '+lib.name;return 0}else{var result=lib.module[symbol];if(typeof result=="function"){result=Runtime.addFunction(result);lib.cached_functions=result}return result}}}function _glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";if(maxLength>0&&infoLog){var numBytesWrittenExclNull=stringToUTF8(log,infoLog,maxLength);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}}function _abort(){Module["abort"]()}function _glDepthFunc(x0){GLctx["depthFunc"](x0)}function _pthread_getspecific(key){return PTHREAD_SPECIFIC[key]||0}function _glEnable(x0){GLctx["enable"](x0)}var cttz_i8=allocate([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",ALLOC_STATIC);function _llvm_cttz_i32(x){x=x|0;var ret=0;ret=HEAP8[cttz_i8+(x&255)>>0]|0;if((ret|0)<8)return ret|0;ret=HEAP8[cttz_i8+(x>>8&255)>>0]|0;if((ret|0)<8)return ret+8|0;ret=HEAP8[cttz_i8+(x>>16&255)>>0]|0;if((ret|0)<8)return ret+16|0;return(HEAP8[cttz_i8+(x>>>24)>>0]|0)+24|0}function _glGenBuffers(n,buffers){for(var i=0;i<n;i++){var buffer=GLctx.createBuffer();if(!buffer){GL.recordError(1282);while(i<n)HEAP32[buffers+i++*4>>2]=0;return}var id=GL.getNewId(GL.buffers);buffer.name=id;GL.buffers[id]=buffer;HEAP32[buffers+i*4>>2]=id}}function ___syscall331(which,varargs){SYSCALLS.varargs=varargs;try{return-ERRNO_CODES.ENOSYS}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _wait(stat_loc){___setErrNo(ERRNO_CODES.ECHILD);return-1}function _waitpid(){return _wait.apply(null,arguments)}function _glBlendFunc(x0,x1){GLctx["blendFunc"](x0,x1)}function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;GL.programs[id]=program;return id}function _glTexImage3D(target,level,internalFormat,width,height,depth,border,format,type,pixels){if(GLctx.currentPixelUnpackBufferBinding){GLctx["texImage3D"](target,level,internalFormat,width,height,depth,border,format,type,pixels)}else if(pixels!=0){GLctx["texImage3D"](target,level,internalFormat,width,height,depth,border,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx["texImage3D"](target,level,internalFormat,width,height,depth,border,format,type,null)}}function ___cxa_pure_virtual(){ABORT=true;throw"Pure virtual function called!"}function _longjmp(env,value){Module["setThrew"](env,value||1);throw"longjmp"}function _emscripten_set_mousedown_callback(target,userData,useCapture,callbackfunc){JSEvents.registerMouseEventCallback(target,userData,useCapture,callbackfunc,5,"mousedown");return 0}function __hideEverythingExceptGivenElement(onlyVisibleElement){var child=onlyVisibleElement;var parent=child.parentNode;var hiddenElements=[];while(child!=document.body){var children=parent.children;for(var i=0;i<children.length;++i){if(children[i]!=child){hiddenElements.push({node:children[i],displayState:children[i].style.display});children[i].style.display="none"}}child=parent;parent=parent.parentNode}return hiddenElements}var __restoreOldWindowedStyle=null;function __restoreHiddenElements(hiddenElements){for(var i=0;i<hiddenElements.length;++i){hiddenElements[i].node.style.display=hiddenElements[i].displayState}}function __softFullscreenResizeWebGLRenderTarget(){var inHiDPIFullscreenMode=__currentFullscreenStrategy.canvasResolutionScaleMode==2;var inAspectRatioFixedFullscreenMode=__currentFullscreenStrategy.scaleMode==2;var inPixelPerfectFullscreenMode=__currentFullscreenStrategy.canvasResolutionScaleMode!=0;var inCenteredWithoutScalingFullscreenMode=__currentFullscreenStrategy.scaleMode==3;var screenWidth=inHiDPIFullscreenMode?Math.round(window.innerWidth*window.devicePixelRatio):window.innerWidth;var screenHeight=inHiDPIFullscreenMode?Math.round(window.innerHeight*window.devicePixelRatio):window.innerHeight;var w=screenWidth;var h=screenHeight;var canvas=__currentFullscreenStrategy.target;var x=canvas.width;var y=canvas.height;var topMargin;if(inAspectRatioFixedFullscreenMode){if(w*y<x*h)h=w*y/x|0;else if(w*y>x*h)w=h*x/y|0;topMargin=(screenHeight-h)/2|0}if(inPixelPerfectFullscreenMode){canvas.width=w;canvas.height=h;if(canvas.GLctxObject)canvas.GLctxObject.GLctx.viewport(0,0,canvas.width,canvas.height)}if(inHiDPIFullscreenMode){topMargin/=window.devicePixelRatio;w/=window.devicePixelRatio;h/=window.devicePixelRatio;w=Math.round(w*1e4)/1e4;h=Math.round(h*1e4)/1e4;topMargin=Math.round(topMargin*1e4)/1e4}if(inCenteredWithoutScalingFullscreenMode){var t=(window.innerHeight-parseInt(canvas.style.height))/2;var b=(window.innerWidth-parseInt(canvas.style.width))/2;__setLetterbox(canvas,t,b)}else{canvas.style.width=w+"px";canvas.style.height=h+"px";var b=(window.innerWidth-w)/2;__setLetterbox(canvas,topMargin,b)}if(!inCenteredWithoutScalingFullscreenMode&&__currentFullscreenStrategy.canvasResizedCallback){Module["dynCall_iiii"](__currentFullscreenStrategy.canvasResizedCallback,37,0,__currentFullscreenStrategy.canvasResizedCallbackUserData)}}function _emscripten_enter_soft_fullscreen(target,fullscreenStrategy){if(!target)target="#canvas";target=JSEvents.findEventTarget(target);if(!target)return-4;var strategy={};strategy.scaleMode=HEAP32[fullscreenStrategy>>2];strategy.canvasResolutionScaleMode=HEAP32[fullscreenStrategy+4>>2];strategy.filteringMode=HEAP32[fullscreenStrategy+8>>2];strategy.canvasResizedCallback=HEAP32[fullscreenStrategy+12>>2];strategy.canvasResizedCallbackUserData=HEAP32[fullscreenStrategy+16>>2];strategy.target=target;strategy.softFullscreen=true;var restoreOldStyle=JSEvents.resizeCanvasForFullscreen(target,strategy);document.documentElement.style.overflow="hidden";document.body.scroll="no";document.body.style.margin="0px";var hiddenElements=__hideEverythingExceptGivenElement(target);function restoreWindowedState(){restoreOldStyle();__restoreHiddenElements(hiddenElements);window.removeEventListener("resize",__softFullscreenResizeWebGLRenderTarget);if(strategy.canvasResizedCallback){Module["dynCall_iiii"](strategy.canvasResizedCallback,37,0,strategy.canvasResizedCallbackUserData)}}__restoreOldWindowedStyle=restoreWindowedState;__currentFullscreenStrategy=strategy;window.addEventListener("resize",__softFullscreenResizeWebGLRenderTarget);if(strategy.canvasResizedCallback){Module["dynCall_iiii"](strategy.canvasResizedCallback,37,0,strategy.canvasResizedCallbackUserData)}return 0}function _emscripten_exit_fullscreen(){if(typeof JSEvents.fullscreenEnabled()==="undefined")return-1;JSEvents.removeDeferredCalls(JSEvents.requestFullscreen);if(document.exitFullscreen){document.exitFullscreen()}else if(document.msExitFullscreen){document.msExitFullscreen()}else if(document.mozCancelFullScreen){document.mozCancelFullScreen()}else if(document.webkitExitFullscreen){document.webkitExitFullscreen()}else{return-1}if(__currentFullscreenStrategy.canvasResizedCallback){Module["dynCall_iiii"](__currentFullscreenStrategy.canvasResizedCallback,37,0,__currentFullscreenStrategy.canvasResizedCallbackUserData)}return 0}function _pthread_rwlock_rdlock(){return 0}function _pthread_rwlock_wrlock(){return 0}function _pthread_join(){}var SOCKFS={mount:(function(mount){Module["websocket"]=Module["websocket"]&&"object"===typeof Module["websocket"]?Module["websocket"]:{};Module["websocket"]._callbacks={};Module["websocket"]["on"]=(function(event,callback){if("function"===typeof callback){this._callbacks[event]=callback}return this});Module["websocket"].emit=(function(event,param){if("function"===typeof this._callbacks[event]){this._callbacks[event].call(this,param)}});return FS.createNode(null,"/",16384|511,0)}),createSocket:(function(family,type,protocol){var streaming=type==1;if(protocol){assert(streaming==(protocol==6))}var sock={family:family,type:type,protocol:protocol,server:null,error:null,peers:{},pending:[],recv_queue:[],sock_ops:SOCKFS.websocket_sock_ops};var name=SOCKFS.nextname();var node=FS.createNode(SOCKFS.root,name,49152,0);node.sock=sock;var stream=FS.createStream({path:name,node:node,flags:FS.modeStringToFlags("r+"),seekable:false,stream_ops:SOCKFS.stream_ops});sock.stream=stream;return sock}),getSocket:(function(fd){var stream=FS.getStream(fd);if(!stream||!FS.isSocket(stream.node.mode)){return null}return stream.node.sock}),stream_ops:{poll:(function(stream){var sock=stream.node.sock;return sock.sock_ops.poll(sock)}),ioctl:(function(stream,request,varargs){var sock=stream.node.sock;return sock.sock_ops.ioctl(sock,request,varargs)}),read:(function(stream,buffer,offset,length,position){var sock=stream.node.sock;var msg=sock.sock_ops.recvmsg(sock,length);if(!msg){return 0}buffer.set(msg.buffer,offset);return msg.buffer.length}),write:(function(stream,buffer,offset,length,position){var sock=stream.node.sock;return sock.sock_ops.sendmsg(sock,buffer,offset,length)}),close:(function(stream){var sock=stream.node.sock;sock.sock_ops.close(sock)})},nextname:(function(){if(!SOCKFS.nextname.current){SOCKFS.nextname.current=0}return"socket["+SOCKFS.nextname.current++ +"]"}),websocket_sock_ops:{createPeer:(function(sock,addr,port){var ws;if(typeof addr==="object"){ws=addr;addr=null;port=null}if(ws){if(ws._socket){addr=ws._socket.remoteAddress;port=ws._socket.remotePort}else{var result=/ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);if(!result){throw new Error("WebSocket URL must be in the format ws(s)://address:port")}addr=result[1];port=parseInt(result[2],10)}}else{try{var runtimeConfig=Module["websocket"]&&"object"===typeof Module["websocket"];var url="ws:#".replace("#","//");if(runtimeConfig){if("string"===typeof Module["websocket"]["url"]){url=Module["websocket"]["url"]}}if(url==="ws://"||url==="wss://"){var parts=addr.split("/");url=url+parts[0]+":"+port+"/"+parts.slice(1).join("/")}var subProtocols="binary";if(runtimeConfig){if("string"===typeof Module["websocket"]["subprotocol"]){subProtocols=Module["websocket"]["subprotocol"]}}subProtocols=subProtocols.replace(/^ +| +$/g,"").split(/ *, */);var opts=ENVIRONMENT_IS_NODE?{"protocol":subProtocols.toString()}:subProtocols;var WebSocketConstructor;if(ENVIRONMENT_IS_NODE){WebSocketConstructor=require("ws")}else if(ENVIRONMENT_IS_WEB){WebSocketConstructor=window["WebSocket"]}else{WebSocketConstructor=WebSocket}ws=new WebSocketConstructor(url,opts);ws.binaryType="arraybuffer"}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EHOSTUNREACH)}}var peer={addr:addr,port:port,socket:ws,dgram_send_queue:[]};SOCKFS.websocket_sock_ops.addPeer(sock,peer);SOCKFS.websocket_sock_ops.handlePeerEvents(sock,peer);if(sock.type===2&&typeof sock.sport!=="undefined"){peer.dgram_send_queue.push(new Uint8Array([255,255,255,255,"p".charCodeAt(0),"o".charCodeAt(0),"r".charCodeAt(0),"t".charCodeAt(0),(sock.sport&65280)>>8,sock.sport&255]))}return peer}),getPeer:(function(sock,addr,port){return sock.peers[addr+":"+port]}),addPeer:(function(sock,peer){sock.peers[peer.addr+":"+peer.port]=peer}),removePeer:(function(sock,peer){delete sock.peers[peer.addr+":"+peer.port]}),handlePeerEvents:(function(sock,peer){var first=true;var handleOpen=(function(){Module["websocket"].emit("open",sock.stream.fd);try{var queued=peer.dgram_send_queue.shift();while(queued){peer.socket.send(queued);queued=peer.dgram_send_queue.shift()}}catch(e){peer.socket.close()}});function handleMessage(data){assert(typeof data!=="string"&&data.byteLength!==undefined);if(data.byteLength==0){return}data=new Uint8Array(data);var wasfirst=first;first=false;if(wasfirst&&data.length===10&&data[0]===255&&data[1]===255&&data[2]===255&&data[3]===255&&data[4]==="p".charCodeAt(0)&&data[5]==="o".charCodeAt(0)&&data[6]==="r".charCodeAt(0)&&data[7]==="t".charCodeAt(0)){var newport=data[8]<<8|data[9];SOCKFS.websocket_sock_ops.removePeer(sock,peer);peer.port=newport;SOCKFS.websocket_sock_ops.addPeer(sock,peer);return}sock.recv_queue.push({addr:peer.addr,port:peer.port,data:data});Module["websocket"].emit("message",sock.stream.fd)}if(ENVIRONMENT_IS_NODE){peer.socket.on("open",handleOpen);peer.socket.on("message",(function(data,flags){if(!flags.binary){return}handleMessage((new Uint8Array(data)).buffer)}));peer.socket.on("close",(function(){Module["websocket"].emit("close",sock.stream.fd)}));peer.socket.on("error",(function(error){sock.error=ERRNO_CODES.ECONNREFUSED;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}))}else{peer.socket.onopen=handleOpen;peer.socket.onclose=(function(){Module["websocket"].emit("close",sock.stream.fd)});peer.socket.onmessage=function peer_socket_onmessage(event){handleMessage(event.data)};peer.socket.onerror=(function(error){sock.error=ERRNO_CODES.ECONNREFUSED;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])})}}),poll:(function(sock){if(sock.type===1&&sock.server){return sock.pending.length?64|1:0}var mask=0;var dest=sock.type===1?SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport):null;if(sock.recv_queue.length||!dest||dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=64|1}if(!dest||dest&&dest.socket.readyState===dest.socket.OPEN){mask|=4}if(dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=16}return mask}),ioctl:(function(sock,request,arg){switch(request){case 21531:var bytes=0;if(sock.recv_queue.length){bytes=sock.recv_queue[0].data.length}HEAP32[arg>>2]=bytes;return 0;default:return ERRNO_CODES.EINVAL}}),close:(function(sock){if(sock.server){try{sock.server.close()}catch(e){}sock.server=null}var peers=Object.keys(sock.peers);for(var i=0;i<peers.length;i++){var peer=sock.peers[peers[i]];try{peer.socket.close()}catch(e){}SOCKFS.websocket_sock_ops.removePeer(sock,peer)}return 0}),bind:(function(sock,addr,port){if(typeof sock.saddr!=="undefined"||typeof sock.sport!=="undefined"){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}sock.saddr=addr;sock.sport=port;if(sock.type===2){if(sock.server){sock.server.close();sock.server=null}try{sock.sock_ops.listen(sock,0)}catch(e){if(!(e instanceof FS.ErrnoError))throw e;if(e.errno!==ERRNO_CODES.EOPNOTSUPP)throw e}}}),connect:(function(sock,addr,port){if(sock.server){throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP)}if(typeof sock.daddr!=="undefined"&&typeof sock.dport!=="undefined"){var dest=SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport);if(dest){if(dest.socket.readyState===dest.socket.CONNECTING){throw new FS.ErrnoError(ERRNO_CODES.EALREADY)}else{throw new FS.ErrnoError(ERRNO_CODES.EISCONN)}}}var peer=SOCKFS.websocket_sock_ops.createPeer(sock,addr,port);sock.daddr=peer.addr;sock.dport=peer.port;throw new FS.ErrnoError(ERRNO_CODES.EINPROGRESS)}),listen:(function(sock,backlog){if(!ENVIRONMENT_IS_NODE){throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP)}if(sock.server){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var WebSocketServer=require("ws").Server;var host=sock.saddr;sock.server=new WebSocketServer({host:host,port:sock.sport});Module["websocket"].emit("listen",sock.stream.fd);sock.server.on("connection",(function(ws){if(sock.type===1){var newsock=SOCKFS.createSocket(sock.family,sock.type,sock.protocol);var peer=SOCKFS.websocket_sock_ops.createPeer(newsock,ws);newsock.daddr=peer.addr;newsock.dport=peer.port;sock.pending.push(newsock);Module["websocket"].emit("connection",newsock.stream.fd)}else{SOCKFS.websocket_sock_ops.createPeer(sock,ws);Module["websocket"].emit("connection",sock.stream.fd)}}));sock.server.on("closed",(function(){Module["websocket"].emit("close",sock.stream.fd);sock.server=null}));sock.server.on("error",(function(error){sock.error=ERRNO_CODES.EHOSTUNREACH;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"EHOSTUNREACH: Host is unreachable"])}))}),accept:(function(listensock){if(!listensock.server){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var newsock=listensock.pending.shift();newsock.stream.flags=listensock.stream.flags;return newsock}),getname:(function(sock,peer){var addr,port;if(peer){if(sock.daddr===undefined||sock.dport===undefined){throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN)}addr=sock.daddr;port=sock.dport}else{addr=sock.saddr||0;port=sock.sport||0}return{addr:addr,port:port}}),sendmsg:(function(sock,buffer,offset,length,addr,port){if(sock.type===2){if(addr===undefined||port===undefined){addr=sock.daddr;port=sock.dport}if(addr===undefined||port===undefined){throw new FS.ErrnoError(ERRNO_CODES.EDESTADDRREQ)}}else{addr=sock.daddr;port=sock.dport}var dest=SOCKFS.websocket_sock_ops.getPeer(sock,addr,port);if(sock.type===1){if(!dest||dest.socket.readyState===dest.socket.CLOSING||dest.socket.readyState===dest.socket.CLOSED){throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN)}else if(dest.socket.readyState===dest.socket.CONNECTING){throw new FS.ErrnoError(ERRNO_CODES.EAGAIN)}}var data;if(buffer instanceof Array||buffer instanceof ArrayBuffer){data=buffer.slice(offset,offset+length)}else{data=buffer.buffer.slice(buffer.byteOffset+offset,buffer.byteOffset+offset+length)}if(sock.type===2){if(!dest||dest.socket.readyState!==dest.socket.OPEN){if(!dest||dest.socket.readyState===dest.socket.CLOSING||dest.socket.readyState===dest.socket.CLOSED){dest=SOCKFS.websocket_sock_ops.createPeer(sock,addr,port)}dest.dgram_send_queue.push(data);return length}}try{dest.socket.send(data);return length}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}}),recvmsg:(function(sock,length){if(sock.type===1&&sock.server){throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN)}var queued=sock.recv_queue.shift();if(!queued){if(sock.type===1){var dest=SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport);if(!dest){throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN)}else if(dest.socket.readyState===dest.socket.CLOSING||dest.socket.readyState===dest.socket.CLOSED){return null}else{throw new FS.ErrnoError(ERRNO_CODES.EAGAIN)}}else{throw new FS.ErrnoError(ERRNO_CODES.EAGAIN)}}var queuedLength=queued.data.byteLength||queued.data.length;var queuedOffset=queued.data.byteOffset||0;var queuedBuffer=queued.data.buffer||queued.data;var bytesRead=Math.min(length,queuedLength);var res={buffer:new Uint8Array(queuedBuffer,queuedOffset,bytesRead),addr:queued.addr,port:queued.port};if(sock.type===1&&bytesRead<queuedLength){var bytesRemaining=queuedLength-bytesRead;queued.data=new Uint8Array(queuedBuffer,queuedOffset+bytesRead,bytesRemaining);sock.recv_queue.unshift(queued)}return res})}};function __read_sockaddr(sa,salen){var family=HEAP16[sa>>1];var port=_ntohs(HEAP16[sa+2>>1]);var addr;switch(family){case 2:if(salen!==16){return{errno:ERRNO_CODES.EINVAL}}addr=HEAP32[sa+4>>2];addr=__inet_ntop4_raw(addr);break;case 10:if(salen!==28){return{errno:ERRNO_CODES.EINVAL}}addr=[HEAP32[sa+8>>2],HEAP32[sa+12>>2],HEAP32[sa+16>>2],HEAP32[sa+20>>2]];addr=__inet_ntop6_raw(addr);break;default:return{errno:ERRNO_CODES.EAFNOSUPPORT}}return{family:family,addr:addr,port:port}}function ___syscall102(which,varargs){SYSCALLS.varargs=varargs;try{var call=SYSCALLS.get(),socketvararg=SYSCALLS.get();SYSCALLS.varargs=socketvararg;switch(call){case 1:{var domain=SYSCALLS.get(),type=SYSCALLS.get(),protocol=SYSCALLS.get();var sock=SOCKFS.createSocket(domain,type,protocol);assert(sock.stream.fd<64);return sock.stream.fd};case 2:{var sock=SYSCALLS.getSocketFromFD(),info=SYSCALLS.getSocketAddress();sock.sock_ops.bind(sock,info.addr,info.port);return 0};case 3:{var sock=SYSCALLS.getSocketFromFD(),info=SYSCALLS.getSocketAddress();sock.sock_ops.connect(sock,info.addr,info.port);return 0};case 4:{var sock=SYSCALLS.getSocketFromFD(),backlog=SYSCALLS.get();sock.sock_ops.listen(sock,backlog);return 0};case 5:{var sock=SYSCALLS.getSocketFromFD(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();var newsock=sock.sock_ops.accept(sock);if(addr){var res=__write_sockaddr(addr,newsock.family,DNS.lookup_name(newsock.daddr),newsock.dport);assert(!res.errno)}return newsock.stream.fd};case 6:{var sock=SYSCALLS.getSocketFromFD(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();var res=__write_sockaddr(addr,sock.family,DNS.lookup_name(sock.saddr||"0.0.0.0"),sock.sport);assert(!res.errno);return 0};case 7:{var sock=SYSCALLS.getSocketFromFD(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();if(!sock.daddr){return-ERRNO_CODES.ENOTCONN}var res=__write_sockaddr(addr,sock.family,DNS.lookup_name(sock.daddr),sock.dport);assert(!res.errno);return 0};case 11:{var sock=SYSCALLS.getSocketFromFD(),message=SYSCALLS.get(),length=SYSCALLS.get(),flags=SYSCALLS.get(),dest=SYSCALLS.getSocketAddress(true);if(!dest){return FS.write(sock.stream,HEAP8,message,length)}else{return sock.sock_ops.sendmsg(sock,HEAP8,message,length,dest.addr,dest.port)}};case 12:{var sock=SYSCALLS.getSocketFromFD(),buf=SYSCALLS.get(),len=SYSCALLS.get(),flags=SYSCALLS.get(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();var msg=sock.sock_ops.recvmsg(sock,len);if(!msg)return 0;if(addr){var res=__write_sockaddr(addr,sock.family,DNS.lookup_name(msg.addr),msg.port);assert(!res.errno)}HEAPU8.set(msg.buffer,buf);return msg.buffer.byteLength};case 14:{return-ERRNO_CODES.ENOPROTOOPT};case 15:{var sock=SYSCALLS.getSocketFromFD(),level=SYSCALLS.get(),optname=SYSCALLS.get(),optval=SYSCALLS.get(),optlen=SYSCALLS.get();if(level===1){if(optname===4){HEAP32[optval>>2]=sock.error;HEAP32[optlen>>2]=4;sock.error=null;return 0}}return-ERRNO_CODES.ENOPROTOOPT};case 16:{var sock=SYSCALLS.getSocketFromFD(),message=SYSCALLS.get(),flags=SYSCALLS.get();var iov=HEAP32[message+8>>2];var num=HEAP32[message+12>>2];var addr,port;var name=HEAP32[message>>2];var namelen=HEAP32[message+4>>2];if(name){var info=__read_sockaddr(name,namelen);if(info.errno)return-info.errno;port=info.port;addr=DNS.lookup_addr(info.addr)||info.addr}var total=0;for(var i=0;i<num;i++){total+=HEAP32[iov+(8*i+4)>>2]}var view=new Uint8Array(total);var offset=0;for(var i=0;i<num;i++){var iovbase=HEAP32[iov+(8*i+0)>>2];var iovlen=HEAP32[iov+(8*i+4)>>2];for(var j=0;j<iovlen;j++){view[offset++]=HEAP8[iovbase+j>>0]}}return sock.sock_ops.sendmsg(sock,view,0,total,addr,port)};case 17:{var sock=SYSCALLS.getSocketFromFD(),message=SYSCALLS.get(),flags=SYSCALLS.get();var iov=HEAP32[message+8>>2];var num=HEAP32[message+12>>2];var total=0;for(var i=0;i<num;i++){total+=HEAP32[iov+(8*i+4)>>2]}var msg=sock.sock_ops.recvmsg(sock,total);if(!msg)return 0;var name=HEAP32[message>>2];if(name){var res=__write_sockaddr(name,sock.family,DNS.lookup_name(msg.addr),msg.port);assert(!res.errno)}var bytesRead=0;var bytesRemaining=msg.buffer.byteLength;for(var i=0;bytesRemaining>0&&i<num;i++){var iovbase=HEAP32[iov+(8*i+0)>>2];var iovlen=HEAP32[iov+(8*i+4)>>2];if(!iovlen){continue}var length=Math.min(iovlen,bytesRemaining);var buf=msg.buffer.subarray(bytesRead,bytesRead+length);HEAPU8.set(buf,iovbase+bytesRead);bytesRead+=length;bytesRemaining-=length}return bytesRead};default:abort("unsupported socketcall syscall "+call)}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[buffers+i*4>>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GL.currArrayBuffer)GL.currArrayBuffer=0;if(id==GL.currElementArrayBuffer)GL.currElementArrayBuffer=0}}function _emscripten_set_gamepaddisconnected_callback(userData,useCapture,callbackfunc){if(!navigator.getGamepads&&!navigator.webkitGetGamepads)return-1;JSEvents.registerGamepadEventCallback(window,userData,useCapture,callbackfunc,27,"gamepaddisconnected");return 0}function _glDrawElementsInstanced(mode,count,type,indices,primcount){GLctx["drawElementsInstanced"](mode,count,type,indices,primcount)}function _glClearColor(x0,x1,x2,x3){GLctx["clearColor"](x0,x1,x2,x3)}function _kill(pid,sig){___setErrNo(ERRNO_CODES.EPERM);return-1}function _glGetStringi(name,index){if(GLctx.canvas.GLctxObject.version<2){GL.recordError(1282);return 0}var stringiCache=GL.stringiCache[name];if(stringiCache){if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index]}switch(name){case 7939:var exts=GLctx.getSupportedExtensions();var gl_exts=[];for(var i=0;i<exts.length;++i){gl_exts.push(allocate(intArrayFromString(exts[i]),"i8",ALLOC_NORMAL));gl_exts.push(allocate(intArrayFromString("GL_"+exts[i]),"i8",ALLOC_NORMAL))}stringiCache=GL.stringiCache[name]=gl_exts;if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index];default:GL.recordError(1280);return 0}}function _sem_destroy(){}function _emscripten_exit_soft_fullscreen(){if(__restoreOldWindowedStyle)__restoreOldWindowedStyle();__restoreOldWindowedStyle=null;return 0}function _emscripten_get_gamepad_status(index,gamepadState){__emscripten_sample_gamepad_data();if(!JSEvents.lastGamepadState)return-1;if(index<0||index>=JSEvents.lastGamepadState.length)return-5;if(!JSEvents.lastGamepadState[index])return-7;JSEvents.fillGamepadEventData(gamepadState,JSEvents.lastGamepadState[index]);return 0}function _sem_init(){}function _glUniform2fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform2fv(GL.uniforms[location],HEAPF32,value>>2,count*2);return}var view;if(2*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(GL.uniforms[location],view)}function _emscripten_set_mouseup_callback(target,userData,useCapture,callbackfunc){JSEvents.registerMouseEventCallback(target,userData,useCapture,callbackfunc,6,"mouseup");return 0}function ___syscall39(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr(),mode=SYSCALLS.get();return SYSCALLS.doMkdir(path,mode)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall38(which,varargs){SYSCALLS.varargs=varargs;try{var old_path=SYSCALLS.getStr(),new_path=SYSCALLS.getStr();FS.rename(old_path,new_path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall33(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr(),amode=SYSCALLS.get();return SYSCALLS.doAccess(path,amode)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _glClearDepthf(x0){GLctx["clearDepth"](x0)}function _glGenTextures(n,textures){for(var i=0;i<n;i++){var texture=GLctx.createTexture();if(!texture){GL.recordError(1282);while(i<n)HEAP32[textures+i++*4>>2]=0;return}var id=GL.getNewId(GL.textures);texture.name=id;GL.textures[id]=texture;HEAP32[textures+i*4>>2]=id}}function _glColorMask(red,green,blue,alpha){GLctx.colorMask(!!red,!!green,!!blue,!!alpha)}var PIPEFS={BUCKET_BUFFER_SIZE:8192,mount:(function(mount){return FS.createNode(null,"/",16384|511,0)}),createPipe:(function(){var pipe={buckets:[]};pipe.buckets.push({buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:0,roffset:0});var rName=PIPEFS.nextname();var wName=PIPEFS.nextname();var rNode=FS.createNode(PIPEFS.root,rName,4096,0);var wNode=FS.createNode(PIPEFS.root,wName,4096,0);rNode.pipe=pipe;wNode.pipe=pipe;var readableStream=FS.createStream({path:rName,node:rNode,flags:FS.modeStringToFlags("r"),seekable:false,stream_ops:PIPEFS.stream_ops});rNode.stream=readableStream;var writableStream=FS.createStream({path:wName,node:wNode,flags:FS.modeStringToFlags("w"),seekable:false,stream_ops:PIPEFS.stream_ops});wNode.stream=writableStream;return{readable_fd:readableStream.fd,writable_fd:writableStream.fd}}),stream_ops:{poll:(function(stream){var pipe=stream.node.pipe;if((stream.flags&2097155)===1){return 256|4}else{if(pipe.buckets.length>0){for(var i=0;i<pipe.buckets.length;i++){var bucket=pipe.buckets[i];if(bucket.offset-bucket.roffset>0){return 64|1}}}}return 0}),ioctl:(function(stream,request,varargs){return ERRNO_CODES.EINVAL}),read:(function(stream,buffer,offset,length,position){var pipe=stream.node.pipe;var currentLength=0;for(var i=0;i<pipe.buckets.length;i++){var bucket=pipe.buckets[i];currentLength+=bucket.offset-bucket.roffset}assert(buffer instanceof ArrayBuffer||ArrayBuffer.isView(buffer));var data=buffer.subarray(offset,offset+length);if(length<=0){return 0}if(currentLength==0){throw new FS.ErrnoError(ERRNO_CODES.EAGAIN)}var toRead=Math.min(currentLength,length);var totalRead=toRead;var toRemove=0;for(var i=0;i<pipe.buckets.length;i++){var currBucket=pipe.buckets[i];var bucketSize=currBucket.offset-currBucket.roffset;if(toRead<=bucketSize){var tmpSlice=currBucket.buffer.subarray(currBucket.roffset,currBucket.offset);if(toRead<bucketSize){tmpSlice=tmpSlice.subarray(0,toRead);currBucket.roffset+=toRead}else{toRemove++}data.set(tmpSlice);break}else{var tmpSlice=currBucket.buffer.subarray(currBucket.roffset,currBucket.offset);data.set(tmpSlice);data=data.subarray(tmpSlice.byteLength);toRead-=tmpSlice.byteLength;toRemove++}}if(toRemove&&toRemove==pipe.buckets.length){toRemove--;pipe.buckets[toRemove].offset=0;pipe.buckets[toRemove].roffset=0}pipe.buckets.splice(0,toRemove);return totalRead}),write:(function(stream,buffer,offset,length,position){var pipe=stream.node.pipe;assert(buffer instanceof ArrayBuffer||ArrayBuffer.isView(buffer));var data=buffer.subarray(offset,offset+length);var dataLen=data.byteLength;if(dataLen<=0){return 0}var currBucket=null;if(pipe.buckets.length==0){currBucket={buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:0,roffset:0};pipe.buckets.push(currBucket)}else{currBucket=pipe.buckets[pipe.buckets.length-1]}assert(currBucket.offset<=PIPEFS.BUCKET_BUFFER_SIZE);var freeBytesInCurrBuffer=PIPEFS.BUCKET_BUFFER_SIZE-currBucket.offset;if(freeBytesInCurrBuffer>=dataLen){currBucket.buffer.set(data,currBucket.offset);currBucket.offset+=dataLen;return dataLen}else if(freeBytesInCurrBuffer>0){currBucket.buffer.set(data.subarray(0,freeBytesInCurrBuffer),currBucket.offset);currBucket.offset+=freeBytesInCurrBuffer;data=data.subarray(freeBytesInCurrBuffer,data.byteLength)}var numBuckets=data.byteLength/PIPEFS.BUCKET_BUFFER_SIZE|0;var remElements=data.byteLength%PIPEFS.BUCKET_BUFFER_SIZE;for(var i=0;i<numBuckets;i++){var newBucket={buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:PIPEFS.BUCKET_BUFFER_SIZE,roffset:0};pipe.buckets.push(newBucket);newBucket.buffer.set(data.subarray(0,PIPEFS.BUCKET_BUFFER_SIZE));data=data.subarray(PIPEFS.BUCKET_BUFFER_SIZE,data.byteLength)}if(remElements>0){var newBucket={buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:data.byteLength,roffset:0};pipe.buckets.push(newBucket);newBucket.buffer.set(data)}return dataLen}),close:(function(stream){var pipe=stream.node.pipe;pipe.buckets=null})},nextname:(function(){if(!PIPEFS.nextname.current){PIPEFS.nextname.current=0}return"pipe["+PIPEFS.nextname.current++ +"]"})};function ___syscall42(which,varargs){SYSCALLS.varargs=varargs;try{var fdPtr=SYSCALLS.get();if(fdPtr==0){throw new FS.ErrnoError(ERRNO_CODES.EFAULT)}var res=PIPEFS.createPipe();HEAP32[fdPtr>>2]=res.readable_fd;HEAP32[fdPtr+4>>2]=res.writable_fd;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall40(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr();FS.rmdir(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _glDeleteRenderbuffers(n,renderbuffers){for(var i=0;i<n;i++){var id=HEAP32[renderbuffers+i*4>>2];var renderbuffer=GL.renderbuffers[id];if(!renderbuffer)continue;GLctx.deleteRenderbuffer(renderbuffer);renderbuffer.name=0;GL.renderbuffers[id]=null}}function _glGetProgramiv(program,pname,p){if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}var ptable=GL.programInfos[program];if(!ptable){GL.recordError(1282);return}if(pname==35716){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35719){HEAP32[p>>2]=ptable.maxUniformLength}else if(pname==35722){if(ptable.maxAttributeLength==-1){var program=GL.programs[program];var numAttribs=GLctx.getProgramParameter(program,GLctx.ACTIVE_ATTRIBUTES);ptable.maxAttributeLength=0;for(var i=0;i<numAttribs;++i){var activeAttrib=GLctx.getActiveAttrib(program,i);ptable.maxAttributeLength=Math.max(ptable.maxAttributeLength,activeAttrib.name.length+1)}}HEAP32[p>>2]=ptable.maxAttributeLength}else if(pname==35381){if(ptable.maxUniformBlockNameLength==-1){var program=GL.programs[program];var numBlocks=GLctx.getProgramParameter(program,GLctx.ACTIVE_UNIFORM_BLOCKS);ptable.maxUniformBlockNameLength=0;for(var i=0;i<numBlocks;++i){var activeBlockName=GLctx.getActiveUniformBlockName(program,i);ptable.maxUniformBlockNameLength=Math.max(ptable.maxUniformBlockNameLength,activeBlockName.length+1)}}HEAP32[p>>2]=ptable.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(GL.programs[program],pname)}}function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _emscripten_exit_pointerlock(){JSEvents.removeDeferredCalls(JSEvents.requestPointerLock);if(document.exitPointerLock){document.exitPointerLock()}else if(document.msExitPointerLock){document.msExitPointerLock()}else if(document.mozExitPointerLock){document.mozExitPointerLock()}else if(document.webkitExitPointerLock){document.webkitExitPointerLock()}else{return-1}return 0}function _glFramebufferTextureLayer(target,attachment,texture,level,layer){GLctx.framebufferTextureLayer(target,attachment,GL.textures[texture],level,layer)}function _pthread_create(){return 11}function _glGetUniformLocation(program,name){name=Pointer_stringify(name);var arrayOffset=0;if(name.indexOf("]",name.length-1)!==-1){var ls=name.lastIndexOf("[");var arrayIndex=name.slice(ls+1,-1);if(arrayIndex.length>0){arrayOffset=parseInt(arrayIndex);if(arrayOffset<0){return-1}}name=name.slice(0,ls)}var ptable=GL.programInfos[program];if(!ptable){return-1}var utable=ptable.uniforms;var uniformInfo=utable[name];if(uniformInfo&&arrayOffset<uniformInfo[0]){return uniformInfo[1]+arrayOffset}else{return-1}}function _sem_getvalue(){Module["printErr"]("missing function: sem_getvalue");abort(-1)}function _glTexStorage2D(x0,x1,x2,x3,x4){GLctx["texStorage2D"](x0,x1,x2,x3,x4)}function _glUniform4fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform4fv(GL.uniforms[location],HEAPF32,value>>2,count*4);return}var view;if(4*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4fv(GL.uniforms[location],view)}function _llvm_bswap_i64(l,h){var retl=_llvm_bswap_i32(h)>>>0;var reth=_llvm_bswap_i32(l)>>>0;return(Runtime.setTempRet0(reth),retl)|0}function _glVertexAttribDivisor(index,divisor){GLctx["vertexAttribDivisor"](index,divisor)}function _glViewport(x0,x1,x2,x3){GLctx["viewport"](x0,x1,x2,x3)}function _pthread_attr_setstacksize(){}function _pthread_rwlock_destroy(){return 0}function _glCheckFramebufferStatus(x0){return GLctx["checkFramebufferStatus"](x0)}function _pthread_rwlock_trywrlock(){return 0}function ___syscall15(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr(),mode=SYSCALLS.get();FS.chmod(path,mode);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _gmtime_r(time,tmPtr){var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();HEAP32[tmPtr+36>>2]=0;HEAP32[tmPtr+32>>2]=0;var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+40>>2]=___tm_timezone;return tmPtr}function _gmtime(time){return _gmtime_r(time,___tm_current)}function ___syscall12(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr();FS.chdir(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _glBlitFramebuffer(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9){GLctx["blitFramebuffer"](x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)}function _glBindAttribLocation(program,index,name){name=Pointer_stringify(name);GLctx.bindAttribLocation(GL.programs[program],index,name)}function _emscripten_webgl_init_context_attributes(attributes){HEAP32[attributes>>2]=1;HEAP32[attributes+4>>2]=1;HEAP32[attributes+8>>2]=0;HEAP32[attributes+12>>2]=1;HEAP32[attributes+16>>2]=1;HEAP32[attributes+20>>2]=0;HEAP32[attributes+24>>2]=0;HEAP32[attributes+28>>2]=0;HEAP32[attributes+32>>2]=1;HEAP32[attributes+36>>2]=0;HEAP32[attributes+40>>2]=1;HEAP32[attributes+44>>2]=0}function _glUniform2iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform2iv(GL.uniforms[location],HEAP32,value>>2,count*2);return}GLctx.uniform2iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*8>>2))}function _glBindBufferBase(target,index,buffer){var bufferObj=buffer?GL.buffers[buffer]:null;GLctx["bindBufferBase"](target,index,bufferObj)}function _glBufferSubData(target,offset,size,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.bufferSubData(target,offset,HEAPU8,data,size);return}GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))}function _glMapBufferRange(){Module["printErr"]("missing function: glMapBufferRange");abort(-1)}function _llvm_exp2_f32(x){return Math.pow(2,x)}function _glGetShaderiv(shader,pname,p){if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source===null||source.length==0?0:source.length+1;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}}function _glGenRenderbuffers(n,renderbuffers){for(var i=0;i<n;i++){var renderbuffer=GLctx.createRenderbuffer();if(!renderbuffer){GL.recordError(1282);while(i<n)HEAP32[renderbuffers+i++*4>>2]=0;return}var id=GL.getNewId(GL.renderbuffers);renderbuffer.name=id;GL.renderbuffers[id]=renderbuffer;HEAP32[renderbuffers+i*4>>2]=id}}function _sem_post(){}function _emscripten_set_touchmove_callback(target,userData,useCapture,callbackfunc){JSEvents.registerTouchEventCallback(target,userData,useCapture,callbackfunc,24,"touchmove");return 0}function _glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _glTexSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels){if(GL.currentContext.supportsWebGL2EntryPoints){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels!=0){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)}function _emscripten_set_keypress_callback(target,userData,useCapture,callbackfunc){JSEvents.registerKeyEventCallback(target,userData,useCapture,callbackfunc,1,"keypress");return 0}var PTHREAD_SPECIFIC_NEXT_KEY=1;function _pthread_key_create(key,destructor){if(key==0){return ERRNO_CODES.EINVAL}HEAP32[key>>2]=PTHREAD_SPECIFIC_NEXT_KEY;PTHREAD_SPECIFIC[PTHREAD_SPECIFIC_NEXT_KEY]=0;PTHREAD_SPECIFIC_NEXT_KEY++;return 0}var PROCINFO={ppid:1,pid:42,sid:42,pgid:42};function ___syscall20(which,varargs){SYSCALLS.varargs=varargs;try{return PROCINFO.pid}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _glUniformMatrix4fv(location,count,transpose,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniformMatrix4fv(GL.uniforms[location],!!transpose,HEAPF32,value>>2,count*16);return}var view;if(16*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[16*count-1];for(var i=0;i<16*count;i+=16){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2];view[i+9]=HEAPF32[value+(4*i+36)>>2];view[i+10]=HEAPF32[value+(4*i+40)>>2];view[i+11]=HEAPF32[value+(4*i+44)>>2];view[i+12]=HEAPF32[value+(4*i+48)>>2];view[i+13]=HEAPF32[value+(4*i+52)>>2];view[i+14]=HEAPF32[value+(4*i+56)>>2];view[i+15]=HEAPF32[value+(4*i+60)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(GL.uniforms[location],!!transpose,view)}function _glBindBuffer(target,buffer){var bufferObj=buffer?GL.buffers[buffer]:null;if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,bufferObj)}function _glUniform3fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform3fv(GL.uniforms[location],HEAPF32,value>>2,count*3);return}var view;if(3*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3fv(GL.uniforms[location],view)}function _glBufferData(target,size,data,usage){if(!data){GLctx.bufferData(target,size,usage)}else{if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.bufferData(target,HEAPU8,usage,data,size);return}GLctx.bufferData(target,HEAPU8.subarray(data,data+size),usage)}}function _glCompressedTexImage3D(target,level,internalFormat,width,height,depth,border,imageSize,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx["compressedTexImage3D"](target,level,internalFormat,width,height,depth,border,HEAPU8,data,imageSize)}else{GLctx["compressedTexImage3D"](target,level,internalFormat,width,height,depth,border,data?HEAPU8.subarray(data,data+imageSize):null)}}function _emscripten_longjmp(env,value){_longjmp(env,value)}function _getenv(name){if(name===0)return 0;name=Pointer_stringify(name);if(!ENV.hasOwnProperty(name))return 0;if(_getenv.ret)_free(_getenv.ret);_getenv.ret=allocate(intArrayFromString(ENV[name]),"i8",ALLOC_NORMAL);return _getenv.ret}function emscriptenWebGLGet(name_,p,type){if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!=="Integer"&&type!=="Integer64"){GL.recordError(1280)}return;case 34814:case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats.length;break;case 33309:if(GLctx.canvas.GLctxObject.version<2){GL.recordError(1282);return}var exts=GLctx.getSupportedExtensions();ret=2*exts.length;break;case 33307:case 33308:if(GLctx.canvas.GLctxObject.version<2){GL.recordError(1280);return}ret=name_==33307?3:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case"number":ret=result;break;case"boolean":ret=result?1:0;break;case"string":GL.recordError(1280);return;case"object":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 35097:case 36389:case 34068:{ret=0;break};default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i<result.length;++i){switch(type){case"Integer":HEAP32[p+i*4>>2]=result[i];break;case"Float":HEAPF32[p+i*4>>2]=result[i];break;case"Boolean":HEAP8[p+i>>0]=result[i]?1:0;break;default:throw"internal glGet error, bad type: "+type}}return}else if(result instanceof WebGLBuffer||result instanceof WebGLProgram||result instanceof WebGLFramebuffer||result instanceof WebGLRenderbuffer||result instanceof WebGLQuery||result instanceof WebGLSampler||result instanceof WebGLSync||result instanceof WebGLTransformFeedback||result instanceof WebGLVertexArrayObject||result instanceof WebGLTexture){ret=result.name|0}else{GL.recordError(1280);return}break;default:GL.recordError(1280);return}}switch(type){case"Integer64":tempI64=[ret>>>0,(tempDouble=ret,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[p>>2]=tempI64[0],HEAP32[p+4>>2]=tempI64[1];break;case"Integer":HEAP32[p>>2]=ret;break;case"Float":HEAPF32[p>>2]=ret;break;case"Boolean":HEAP8[p>>0]=ret?1:0;break;default:throw"internal glGet error, bad type: "+type}}function _glGetFloatv(name_,p){emscriptenWebGLGet(name_,p,"Float")}function _emscripten_set_keydown_callback(target,userData,useCapture,callbackfunc){JSEvents.registerKeyEventCallback(target,userData,useCapture,callbackfunc,2,"keydown");return 0}var _llvm_pow_f64=Math_pow;function _glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,"Integer")}function _glFramebufferTexture2D(target,attachment,textarget,texture,level){GLctx.framebufferTexture2D(target,attachment,textarget,GL.textures[texture],level)}function _emscripten_set_gamepadconnected_callback(userData,useCapture,callbackfunc){if(!navigator.getGamepads&&!navigator.webkitGetGamepads)return-1;JSEvents.registerGamepadEventCallback(window,userData,useCapture,callbackfunc,26,"gamepadconnected");return 0}function _glUseProgram(program){GLctx.useProgram(program?GL.programs[program]:null)}function _glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){if(GL.currentContext.supportsWebGL2EntryPoints){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels!=0){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixelData)}function _glGetProgramInfoLog(program,maxLength,length,infoLog){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";if(maxLength>0&&infoLog){var numBytesWrittenExclNull=stringToUTF8(log,infoLog,maxLength);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}}function _glBlendEquation(x0){GLctx["blendEquation"](x0)}function _glBindVertexArray(vao){GLctx["bindVertexArray"](GL.vaos[vao])}function _pthread_mutexattr_settype(){}function _emscripten_set_wheel_callback(target,userData,useCapture,callbackfunc){target=JSEvents.findEventTarget(target);if(typeof target.onwheel!=="undefined"){JSEvents.registerWheelEventCallback(target,userData,useCapture,callbackfunc,9,"wheel");return 0}else if(typeof target.onmousewheel!=="undefined"){JSEvents.registerWheelEventCallback(target,userData,useCapture,callbackfunc,9,"mousewheel");return 0}else{return-1}}function ___unlock(){}function _glScissor(x0,x1,x2,x3){GLctx["scissor"](x0,x1,x2,x3)}function _llvm_exp2_f64(){return _llvm_exp2_f32.apply(null,arguments)}function _posix_spawn_file_actions_adddup2(){Module["printErr"]("missing function: posix_spawn_file_actions_adddup2");abort(-1)}function _setenv(envname,envval,overwrite){if(envname===0){___setErrNo(ERRNO_CODES.EINVAL);return-1}var name=Pointer_stringify(envname);var val=Pointer_stringify(envval);if(name===""||name.indexOf("=")!==-1){___setErrNo(ERRNO_CODES.EINVAL);return-1}if(ENV.hasOwnProperty(name)&&!overwrite)return 0;ENV[name]=val;___buildEnvironment(ENV);return 0}function _glEndTransformFeedback(){GLctx["endTransformFeedback"]()}function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _glCopyBufferSubData(x0,x1,x2,x3,x4){GLctx["copyBufferSubData"](x0,x1,x2,x3,x4)}function _glTransformFeedbackVaryings(program,count,varyings,bufferMode){program=GL.programs[program];var vars=[];for(var i=0;i<count;i++)vars.push(Pointer_stringify(HEAP32[varyings+i*4>>2]));GLctx["transformFeedbackVaryings"](program,vars,bufferMode)}function ___syscall183(which,varargs){SYSCALLS.varargs=varargs;try{var buf=SYSCALLS.get(),size=SYSCALLS.get();if(size===0)return-ERRNO_CODES.EINVAL;var cwd=FS.cwd();if(size<cwd.length+1)return-ERRNO_CODES.ERANGE;writeAsciiToMemory(cwd,buf);return buf}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _glDepthMask(flag){GLctx.depthMask(!!flag)}function _glGetUniformBlockIndex(program,uniformBlockName){program=GL.programs[program];uniformBlockName=Pointer_stringify(uniformBlockName);return GLctx["getUniformBlockIndex"](program,uniformBlockName)}function _glTexParameterf(x0,x1,x2){GLctx["texParameterf"](x0,x1,x2)}function _glTexParameteri(x0,x1,x2){GLctx["texParameteri"](x0,x1,x2)}function _glFrontFace(x0){GLctx["frontFace"](x0)}function _emscripten_set_mousemove_callback(target,userData,useCapture,callbackfunc){JSEvents.registerMouseEventCallback(target,userData,useCapture,callbackfunc,8,"mousemove");return 0}function _emscripten_set_canvas_size(width,height){Browser.setCanvasSize(width,height)}function _glPixelStorei(pname,param){if(pname==3333){GL.packAlignment=param}else if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}function ___syscall221(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),cmd=SYSCALLS.get();switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-ERRNO_CODES.EINVAL}var newStream;newStream=FS.open(stream.path,stream.flags,0,arg);return newStream.fd};case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0};case 12:case 12:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0};case 13:case 14:case 13:case 14:return 0;case 16:case 8:return-ERRNO_CODES.EINVAL;case 9:___setErrNo(ERRNO_CODES.EINVAL);return-1;default:{return-ERRNO_CODES.EINVAL}}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall220(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),dirp=SYSCALLS.get(),count=SYSCALLS.get();if(!stream.getdents){stream.getdents=FS.readdir(stream.path)}var pos=0;while(stream.getdents.length>0&&pos+268<=count){var id;var type;var name=stream.getdents.pop();assert(name.length<256);if(name[0]==="."){id=1;type=4}else{var child=FS.lookupNode(stream.node,name);id=child.id;type=FS.isChrdev(child.mode)?2:FS.isDir(child.mode)?4:FS.isLink(child.mode)?10:8}HEAP32[dirp+pos>>2]=id;HEAP32[dirp+pos+4>>2]=stream.position;HEAP16[dirp+pos+8>>1]=268;HEAP8[dirp+pos+10>>0]=type;for(var i=0;i<name.length;i++){HEAP8[dirp+pos+(11+i)>>0]=name.charCodeAt(i)}HEAP8[dirp+pos+(11+i)>>0]=0;pos+=268}return pos}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}var ___dso_handle=STATICTOP;STATICTOP+=16;var GLctx;GL.init();FS.staticInit();__ATINIT__.unshift((function(){if(!Module["noFSInit"]&&!FS.init.initialized)FS.init()}));__ATMAIN__.push((function(){FS.ignorePermissions=false}));__ATEXIT__.push((function(){FS.quit()}));Module["FS_createFolder"]=FS.createFolder;Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createLink"]=FS.createLink;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;__ATINIT__.unshift((function(){TTY.init()}));__ATEXIT__.push((function(){TTY.shutdown()}));if(ENVIRONMENT_IS_NODE){var fs=require("fs");var NODEJS_PATH=require("path");NODEFS.staticInit()}JSEvents.staticInit();Module["requestFullScreen"]=function Module_requestFullScreen(lockPointer,resizeCanvas,vrDevice){Module.printErr("Module.requestFullScreen is deprecated. Please call Module.requestFullscreen instead.");Module["requestFullScreen"]=Module["requestFullscreen"];Browser.requestFullScreen(lockPointer,resizeCanvas,vrDevice)};Module["requestFullscreen"]=function Module_requestFullscreen(lockPointer,resizeCanvas,vrDevice){Browser.requestFullscreen(lockPointer,resizeCanvas,vrDevice)};Module["requestAnimationFrame"]=function Module_requestAnimationFrame(func){Browser.requestAnimationFrame(func)};Module["setCanvasSize"]=function Module_setCanvasSize(width,height,noUpdates){Browser.setCanvasSize(width,height,noUpdates)};Module["pauseMainLoop"]=function Module_pauseMainLoop(){Browser.mainLoop.pause()};Module["resumeMainLoop"]=function Module_resumeMainLoop(){Browser.mainLoop.resume()};Module["getUserMedia"]=function Module_getUserMedia(){Browser.getUserMedia()};Module["createContext"]=function Module_createContext(canvas,useWebGL,setInModule,webGLContextAttributes){return Browser.createContext(canvas,useWebGL,setInModule,webGLContextAttributes)};if(ENVIRONMENT_IS_NODE){_emscripten_get_now=function _emscripten_get_now_actual(){var t=process["hrtime"]();return t[0]*1e3+t[1]/1e6}}else if(typeof dateNow!=="undefined"){_emscripten_get_now=dateNow}else if(typeof self==="object"&&self["performance"]&&typeof self["performance"]["now"]==="function"){_emscripten_get_now=(function(){return self["performance"]["now"]()})}else if(typeof performance==="object"&&typeof performance["now"]==="function"){_emscripten_get_now=(function(){return performance["now"]()})}else{_emscripten_get_now=Date.now}___buildEnvironment(ENV);__ATINIT__.push((function(){SOCKFS.root=FS.mount(SOCKFS,{},null)}));__ATINIT__.push((function(){PIPEFS.root=FS.mount(PIPEFS,{},null)}));DYNAMICTOP_PTR=allocate(1,"i32",ALLOC_STATIC);STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP);STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=Runtime.alignMemory(STACK_MAX);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;staticSealed=true;Module["wasmTableSize"]=38095;Module["wasmMaxTableSize"]=38095;function invoke_viij(index,a1,a2,a3,a4){try{Module["dynCall_viij"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_fifi(index,a1,a2,a3){try{return Module["dynCall_fifi"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){try{return Module["dynCall_iiiiiii"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){try{Module["dynCall_viiiiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8){try{Module["dynCall_viiiiiifi"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiffii(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiffii"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vidi(index,a1,a2,a3){try{Module["dynCall_vidi"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiifiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){try{return Module["dynCall_iiiiifiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_jii(index,a1,a2){try{return Module["dynCall_jii"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_fif(index,a1,a2){try{return Module["dynCall_fif"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15){try{Module["dynCall_viiiiiiiiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiifffi(index,a1,a2,a3,a4,a5,a6,a7,a8){try{Module["dynCall_viiiifffi"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_fii(index,a1,a2){try{return Module["dynCall_fii"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiff(index,a1,a2,a3,a4,a5,a6,a7){try{Module["dynCall_viiiiiff"](index,a1,a2,a3,a4,a5,a6,a7)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_di(index,a1){try{return Module["dynCall_di"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viff(index,a1,a2,a3){try{Module["dynCall_viff"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiifiii(index,a1,a2,a3,a4,a5,a6){try{return Module["dynCall_iiifiii"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiifi(index,a1,a2,a3,a4,a5,a6,a7){try{Module["dynCall_viiiiifi"](index,a1,a2,a3,a4,a5,a6,a7)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiifiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){try{return Module["dynCall_iiiifiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiffi(index,a1,a2,a3,a4,a5){try{Module["dynCall_viiffi"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_dii(index,a1,a2){try{return Module["dynCall_dii"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){try{return Module["dynCall_iiiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiiiff(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){try{Module["dynCall_viiiiiiiff"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiff(index,a1,a2,a3,a4,a5){try{Module["dynCall_viiiff"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){try{return Module["dynCall_iiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_j(index){try{return Module["dynCall_j"](index)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiffif(index,a1,a2,a3,a4,a5,a6,a7,a8){try{Module["dynCall_viiiiffif"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiji(index,a1,a2,a3,a4,a5){try{return Module["dynCall_iiiji"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viidddi(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viidddi"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiffii(index,a1,a2,a3,a4,a5,a6,a7,a8){try{Module["dynCall_viiiiffii"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiifi(index,a1,a2,a3,a4,a5){try{Module["dynCall_viiifi"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_diiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){try{return Module["dynCall_diiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiifii(index,a1,a2,a3,a4,a5){try{return Module["dynCall_iiifii"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiffiii(index,a1,a2,a3,a4,a5,a6,a7,a8){try{Module["dynCall_viiiffiii"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiiiif"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiifiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){try{return Module["dynCall_iiiifiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vifi(index,a1,a2,a3){try{Module["dynCall_vifi"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vifff(index,a1,a2,a3,a4){try{Module["dynCall_vifff"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiiiii"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_fiii(index,a1,a2,a3){try{return Module["dynCall_fiii"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiifffi(index,a1,a2,a3,a4,a5,a6,a7){try{Module["dynCall_viiifffi"](index,a1,a2,a3,a4,a5,a6,a7)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_ji(index,a1){try{return Module["dynCall_ji"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){try{Module["dynCall_viiiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viif(index,a1,a2,a3){try{Module["dynCall_viif"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_diii(index,a1,a2,a3){try{return Module["dynCall_diii"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_fiiii(index,a1,a2,a3,a4){try{return Module["dynCall_fiiii"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){try{return Module["dynCall_iiiiii"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiffffffii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){try{Module["dynCall_viiiffffffii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vijii(index,a1,a2,a3,a4,a5){try{Module["dynCall_vijii"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){try{return Module["dynCall_iiiii"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiif(index,a1,a2,a3,a4){try{return Module["dynCall_iiiif"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiifif(index,a1,a2,a3,a4,a5,a6,a7){try{Module["dynCall_viiiifif"](index,a1,a2,a3,a4,a5,a6,a7)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiiifiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){try{return Module["dynCall_iiiiiifiif"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiii(index,a1,a2,a3,a4){try{Module["dynCall_viiii"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){try{Module["dynCall_viiiii"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vif(index,a1,a2){try{Module["dynCall_vif"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vid(index,a1,a2){try{Module["dynCall_vid"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vij(index,a1,a2,a3){try{Module["dynCall_vij"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vii(index,a1,a2){try{Module["dynCall_vii"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiif(index,a1,a2,a3,a4,a5){try{Module["dynCall_viiiif"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiifiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){try{return Module["dynCall_iiiiifiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viifii(index,a1,a2,a3,a4,a5){try{Module["dynCall_viifii"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_fi(index,a1){try{return Module["dynCall_fi"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viifif(index,a1,a2,a3,a4,a5){try{Module["dynCall_viifif"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiifffiffi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){try{Module["dynCall_viiiifffiffi"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiffiffff(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){try{Module["dynCall_viiiffiffff"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){try{Module["dynCall_viiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_diiii(index,a1,a2,a3,a4){try{return Module["dynCall_diiii"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiifi(index,a1,a2,a3,a4,a5,a6){try{return Module["dynCall_iiiiifi"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viji(index,a1,a2,a3,a4){try{Module["dynCall_viji"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iif(index,a1,a2){try{return Module["dynCall_iif"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){try{Module["dynCall_viiiiiii"](index,a1,a2,a3,a4,a5,a6,a7)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){try{Module["dynCall_viiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iii(index,a1,a2){try{return Module["dynCall_iii"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_fiiiif(index,a1,a2,a3,a4,a5){try{return Module["dynCall_fiiiif"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iij(index,a1,a2,a3){try{return Module["dynCall_iij"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_f(index){try{return Module["dynCall_f"](index)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_jiiii(index,a1,a2,a3,a4){try{return Module["dynCall_jiiii"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viii(index,a1,a2,a3){try{Module["dynCall_viii"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiifi(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiiifi"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_v(index){try{Module["dynCall_v"](index)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viid(index,a1,a2,a3){try{Module["dynCall_viid"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiff(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiiiff"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiifiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){try{return Module["dynCall_iiifiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiifj(index,a1,a2,a3,a4,a5,a6){try{return Module["dynCall_iiiifj"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vi(index,a1){try{Module["dynCall_vi"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){try{return Module["dynCall_iiiiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_ii(index,a1){try{return Module["dynCall_ii"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viifi(index,a1,a2,a3,a4){try{Module["dynCall_viifi"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiifiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){try{return Module["dynCall_iiiiifiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_fffff(index,a1,a2,a3,a4){try{return Module["dynCall_fffff"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiifi(index,a1,a2,a3,a4){try{return Module["dynCall_iiifi"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiif(index,a1,a2,a3,a4){try{Module["dynCall_viiif"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiffif(index,a1,a2,a3,a4,a5,a6,a7){try{Module["dynCall_viiiffif"](index,a1,a2,a3,a4,a5,a6,a7)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiffii(index,a1,a2,a3,a4,a5,a6){try{return Module["dynCall_iiiffii"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_fiiiiii(index,a1,a2,a3,a4,a5,a6){try{return Module["dynCall_fiiiiii"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viffff(index,a1,a2,a3,a4,a5){try{Module["dynCall_viffff"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiii(index,a1,a2,a3){try{return Module["dynCall_iiii"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viifff(index,a1,a2,a3,a4,a5){try{Module["dynCall_viifff"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiiiifiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){try{return Module["dynCall_iiiiiiifiif"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiffiii(index,a1,a2,a3,a4,a5,a6,a7){try{Module["dynCall_viiffiii"](index,a1,a2,a3,a4,a5,a6,a7)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiif(index,a1,a2,a3){try{return Module["dynCall_iiif"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiffi(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiiffi"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiifff(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiifff"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiifiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){try{return Module["dynCall_iiiifiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){try{Module["dynCall_viiiiiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_i(index){try{return Module["dynCall_i"](index)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiffff(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiffff"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){try{return Module["dynCall_iiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_iiiiif(index,a1,a2,a3,a4,a5){try{return Module["dynCall_iiiiif"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}Module.asmGlobalArg={"Math":Math,"Int8Array":Int8Array,"Int16Array":Int16Array,"Int32Array":Int32Array,"Uint8Array":Uint8Array,"Uint16Array":Uint16Array,"Uint32Array":Uint32Array,"Float32Array":Float32Array,"Float64Array":Float64Array,"NaN":NaN,"Infinity":Infinity,"byteLength":byteLength};Module.asmLibraryArg={"abort":abort,"assert":assert,"enlargeMemory":enlargeMemory,"getTotalMemory":getTotalMemory,"abortOnCannotGrowMemory":abortOnCannotGrowMemory,"invoke_viij":invoke_viij,"invoke_fifi":invoke_fifi,"invoke_iiiiiii":invoke_iiiiiii,"invoke_viiiiiiiiiii":invoke_viiiiiiiiiii,"invoke_viiiiiifi":invoke_viiiiiifi,"invoke_viiffii":invoke_viiffii,"invoke_vidi":invoke_vidi,"invoke_iiiiifiiiii":invoke_iiiiifiiiii,"invoke_jii":invoke_jii,"invoke_fif":invoke_fif,"invoke_viiiiiiiiiiiiiii":invoke_viiiiiiiiiiiiiii,"invoke_viiiifffi":invoke_viiiifffi,"invoke_fii":invoke_fii,"invoke_viiiiiff":invoke_viiiiiff,"invoke_di":invoke_di,"invoke_viff":invoke_viff,"invoke_iiifiii":invoke_iiifiii,"invoke_viiiiifi":invoke_viiiiifi,"invoke_iiiifiiiiii":invoke_iiiifiiiiii,"invoke_viiffi":invoke_viiffi,"invoke_dii":invoke_dii,"invoke_iiiiiiiiii":invoke_iiiiiiiiii,"invoke_viiiiiiiff":invoke_viiiiiiiff,"invoke_viiiff":invoke_viiiff,"invoke_iiiiiiii":invoke_iiiiiiii,"invoke_j":invoke_j,"invoke_viiiiffif":invoke_viiiiffif,"invoke_iiiji":invoke_iiiji,"invoke_viidddi":invoke_viidddi,"invoke_viiiiffii":invoke_viiiiffii,"invoke_viiifi":invoke_viiifi,"invoke_diiiiiiii":invoke_diiiiiiii,"invoke_iiifii":invoke_iiifii,"invoke_viiiffiii":invoke_viiiffiii,"invoke_viiiiif":invoke_viiiiif,"invoke_iiiifiiii":invoke_iiiifiiii,"invoke_vifi":invoke_vifi,"invoke_vifff":invoke_vifff,"invoke_viiiiii":invoke_viiiiii,"invoke_fiii":invoke_fiii,"invoke_viiifffi":invoke_viiifffi,"invoke_ji":invoke_ji,"invoke_viiiiiiiiii":invoke_viiiiiiiiii,"invoke_viif":invoke_viif,"invoke_diii":invoke_diii,"invoke_fiiii":invoke_fiiii,"invoke_iiiiii":invoke_iiiiii,"invoke_viiiffffffii":invoke_viiiffffffii,"invoke_vijii":invoke_vijii,"invoke_iiiii":invoke_iiiii,"invoke_iiiif":invoke_iiiif,"invoke_viiiifif":invoke_viiiifif,"invoke_iiiiiifiif":invoke_iiiiiifiif,"invoke_viiii":invoke_viiii,"invoke_viiiii":invoke_viiiii,"invoke_vif":invoke_vif,"invoke_vid":invoke_vid,"invoke_vij":invoke_vij,"invoke_vii":invoke_vii,"invoke_viiiif":invoke_viiiif,"invoke_iiiiifiiii":invoke_iiiiifiiii,"invoke_viifii":invoke_viifii,"invoke_fi":invoke_fi,"invoke_viifif":invoke_viifif,"invoke_viiiifffiffi":invoke_viiiifffiffi,"invoke_viiiffiffff":invoke_viiiffiffff,"invoke_viiiiiiii":invoke_viiiiiiii,"invoke_diiii":invoke_diiii,"invoke_iiiiifi":invoke_iiiiifi,"invoke_viji":invoke_viji,"invoke_iif":invoke_iif,"invoke_viiiiiii":invoke_viiiiiii,"invoke_viiiiiiiii":invoke_viiiiiiiii,"invoke_iii":invoke_iii,"invoke_fiiiif":invoke_fiiiif,"invoke_iij":invoke_iij,"invoke_f":invoke_f,"invoke_jiiii":invoke_jiiii,"invoke_viii":invoke_viii,"invoke_viiiifi":invoke_viiiifi,"invoke_v":invoke_v,"invoke_viid":invoke_viid,"invoke_viiiiff":invoke_viiiiff,"invoke_iiifiiiiii":invoke_iiifiiiiii,"invoke_iiiifj":invoke_iiiifj,"invoke_vi":invoke_vi,"invoke_iiiiiiiiiii":invoke_iiiiiiiiiii,"invoke_ii":invoke_ii,"invoke_viifi":invoke_viifi,"invoke_iiiiifiiiiii":invoke_iiiiifiiiiii,"invoke_fffff":invoke_fffff,"invoke_iiifi":invoke_iiifi,"invoke_viiif":invoke_viiif,"invoke_viiiffif":invoke_viiiffif,"invoke_iiiffii":invoke_iiiffii,"invoke_fiiiiii":invoke_fiiiiii,"invoke_viffff":invoke_viffff,"invoke_iiii":invoke_iiii,"invoke_viifff":invoke_viifff,"invoke_iiiiiiifiif":invoke_iiiiiiifiif,"invoke_viiffiii":invoke_viiffiii,"invoke_iiif":invoke_iiif,"invoke_viiiffi":invoke_viiiffi,"invoke_viiifff":invoke_viiifff,"invoke_iiiifiiiii":invoke_iiiifiiiii,"invoke_viiiiiiiiiiii":invoke_viiiiiiiiiiii,"invoke_i":invoke_i,"invoke_viiffff":invoke_viiffff,"invoke_iiiiiiiii":invoke_iiiiiiiii,"invoke_iiiiif":invoke_iiiiif,"__softFullscreenResizeWebGLRenderTarget":__softFullscreenResizeWebGLRenderTarget,"___syscall221":___syscall221,"_glCullFace":_glCullFace,"__inet_ntop6_raw":__inet_ntop6_raw,"_emscripten_set_fullscreenchange_callback":_emscripten_set_fullscreenchange_callback,"_dlsym":_dlsym,"_pthread_rwlock_wrlock":_pthread_rwlock_wrlock,"_llvm_cttz_i32":_llvm_cttz_i32,"_glUniformMatrix4fv":_glUniformMatrix4fv,"__inet_pton4_raw":__inet_pton4_raw,"___setErrNo":___setErrNo,"_glUniform2fv":_glUniform2fv,"_glDeleteProgram":_glDeleteProgram,"___syscall268":___syscall268,"_pthread_attr_setdetachstate":_pthread_attr_setdetachstate,"_glBlendEquation":_glBlendEquation,"_longjmp":_longjmp,"_glVertexAttrib4f":_glVertexAttrib4f,"_pthread_rwlock_destroy":_pthread_rwlock_destroy,"_llvm_exp2_f64":_llvm_exp2_f64,"_glGetShaderInfoLog":_glGetShaderInfoLog,"__addDays":__addDays,"_emscripten_request_fullscreen_strategy":_emscripten_request_fullscreen_strategy,"emscriptenWebGLGetShiftForType":emscriptenWebGLGetShiftForType,"_emscripten_set_touchmove_callback":_emscripten_set_touchmove_callback,"_emscripten_set_main_loop_timing":_emscripten_set_main_loop_timing,"_emscripten_set_gamepaddisconnected_callback":_emscripten_set_gamepaddisconnected_callback,"_glBlendFunc":_glBlendFunc,"_glDisableVertexAttribArray":_glDisableVertexAttribArray,"_emscripten_memcpy_big":_emscripten_memcpy_big,"_pthread_attr_init":_pthread_attr_init,"_sysconf":_sysconf,"_execl":_execl,"_emscripten_set_touchstart_callback":_emscripten_set_touchstart_callback,"emscriptenWebGLComputeImageSize":emscriptenWebGLComputeImageSize,"_pthread_rwlock_rdlock":_pthread_rwlock_rdlock,"_glShaderSource":_glShaderSource,"_glUniform4f":_glUniform4f,"_glInvalidateFramebuffer":_glInvalidateFramebuffer,"_glBeginTransformFeedback":_glBeginTransformFeedback,"_pthread_mutexattr_settype":_pthread_mutexattr_settype,"_glDrawElementsInstanced":_glDrawElementsInstanced,"emscriptenWebGLGetHeapForType":emscriptenWebGLGetHeapForType,"_glUseProgram":_glUseProgram,"_glRenderbufferStorage":_glRenderbufferStorage,"_emscripten_get_canvas_size":_emscripten_get_canvas_size,"__write_sockaddr":__write_sockaddr,"_emscripten_webgl_make_context_current":_emscripten_webgl_make_context_current,"_glTexStorage2D":_glTexStorage2D,"_glGenBuffers":_glGenBuffers,"_glEndTransformFeedback":_glEndTransformFeedback,"_glFramebufferRenderbuffer":_glFramebufferRenderbuffer,"___syscall220":___syscall220,"_gmtime_r":_gmtime_r,"___cxa_atexit":___cxa_atexit,"_emscripten_exit_pointerlock":_emscripten_exit_pointerlock,"_getaddrinfo":_getaddrinfo,"___syscall140":___syscall140,"_emscripten_do_request_fullscreen":_emscripten_do_request_fullscreen,"_posix_spawn_file_actions_adddup2":_posix_spawn_file_actions_adddup2,"___syscall145":___syscall145,"___syscall146":___syscall146,"_glGenerateMipmap":_glGenerateMipmap,"_emscripten_set_keyup_callback":_emscripten_set_keyup_callback,"_emscripten_asm_const_iiiii":_emscripten_asm_const_iiiii,"__inet_ntop4_raw":__inet_ntop4_raw,"_sem_getvalue":_sem_getvalue,"__restoreHiddenElements":__restoreHiddenElements,"__arraySum":__arraySum,"_glVertexAttribIPointer":_glVertexAttribIPointer,"_sem_init":_sem_init,"___syscall42":___syscall42,"_glBindRenderbuffer":_glBindRenderbuffer,"_glDrawElements":_glDrawElements,"_glDepthMask":_glDepthMask,"_glBufferSubData":_glBufferSubData,"_glReadBuffer":_glReadBuffer,"_glClearBufferfi":_glClearBufferfi,"_glViewport":_glViewport,"_wait":_wait,"_glDeleteVertexArrays":_glDeleteVertexArrays,"_glGetStringi":_glGetStringi,"_llvm_pow_f32":_llvm_pow_f32,"_glDepthFunc":_glDepthFunc,"_emscripten_set_mousedown_callback":_emscripten_set_mousedown_callback,"_emscripten_set_canvas_size":_emscripten_set_canvas_size,"_glClearBufferfv":_glClearBufferfv,"___syscall331":___syscall331,"_dlclose":_dlclose,"_nanosleep":_nanosleep,"_gmtime":_gmtime,"_posix_spawn":_posix_spawn,"_glDrawBuffers":_glDrawBuffers,"_glCompressedTexImage2D":_glCompressedTexImage2D,"_kill":_kill,"___syscall114":___syscall114,"_llvm_trap":_llvm_trap,"_glGenTextures":_glGenTextures,"_glUnmapBuffer":_glUnmapBuffer,"_dlopen":_dlopen,"_glEnable":_glEnable,"_glDrawArraysInstanced":_glDrawArraysInstanced,"emscriptenWebGLGet":emscriptenWebGLGet,"___syscall15":___syscall15,"_emscripten_set_mouseup_callback":_emscripten_set_mouseup_callback,"___syscall12":___syscall12,"_emscripten_get_now":_emscripten_get_now,"___syscall10":___syscall10,"_glUniform1ui":_glUniform1ui,"_glAttachShader":_glAttachShader,"_glCreateProgram":_glCreateProgram,"__registerRestoreOldStyle":__registerRestoreOldStyle,"_pthread_rwlock_trywrlock":_pthread_rwlock_trywrlock,"___lock":___lock,"emscriptenWebGLGetTexPixelData":emscriptenWebGLGetTexPixelData,"___syscall6":___syscall6,"_glBindBuffer":_glBindBuffer,"___cxa_pure_virtual":___cxa_pure_virtual,"_time":_time,"_glBindFramebuffer":_glBindFramebuffer,"_gettimeofday":_gettimeofday,"_glDeleteTextures":_glDeleteTextures,"_glGenFramebuffers":_glGenFramebuffers,"_glGetIntegerv":_glGetIntegerv,"_emscripten_set_resize_callback":_emscripten_set_resize_callback,"_glGetString":_glGetString,"_dlerror":_dlerror,"_pthread_join":_pthread_join,"___syscall102":___syscall102,"_llvm_pow_f64":_llvm_pow_f64,"_emscripten_set_keypress_callback":_emscripten_set_keypress_callback,"_localtime_r":_localtime_r,"_glDeleteFramebuffers":_glDeleteFramebuffers,"_emscripten_get_gamepad_status":_emscripten_get_gamepad_status,"_glMapBufferRange":_glMapBufferRange,"__isLeapYear":__isLeapYear,"_glCheckFramebufferStatus":_glCheckFramebufferStatus,"_emscripten_webgl_create_context":_emscripten_webgl_create_context,"_glFramebufferTextureLayer":_glFramebufferTextureLayer,"___syscall20":___syscall20,"_pthread_rwlock_unlock":_pthread_rwlock_unlock,"_glVertexAttribPointer":_glVertexAttribPointer,"_emscripten_get_num_gamepads":_emscripten_get_num_gamepads,"___buildEnvironment":___buildEnvironment,"_glBlendFuncSeparate":_glBlendFuncSeparate,"_glUniform3fv":_glUniform3fv,"_glClearDepthf":_glClearDepthf,"__emscripten_sample_gamepad_data":__emscripten_sample_gamepad_data,"_tzset":_tzset,"_glClearColor":_glClearColor,"_glBindTexture":_glBindTexture,"_glUniform1f":_glUniform1f,"___syscall195":___syscall195,"_glGetFloatv":_glGetFloatv,"_sigemptyset":_sigemptyset,"_glUniform1i":_glUniform1i,"_strftime":_strftime,"_sem_wait":_sem_wait,"_glDrawArrays":_glDrawArrays,"_glCreateShader":_glCreateShader,"_pthread_mutex_destroy":_pthread_mutex_destroy,"_glCopyBufferSubData":_glCopyBufferSubData,"_glUniform2iv":_glUniform2iv,"_getenv":_getenv,"_glTransformFeedbackVaryings":_glTransformFeedbackVaryings,"_emscripten_asm_const_iiiiiii":_emscripten_asm_const_iiiiiii,"___syscall33":___syscall33,"_pthread_key_create":_pthread_key_create,"_glActiveTexture":_glActiveTexture,"__setLetterbox":__setLetterbox,"___syscall39":___syscall39,"___syscall38":___syscall38,"_glGenVertexArrays":_glGenVertexArrays,"_pthread_rwlock_init":_pthread_rwlock_init,"_glFrontFace":_glFrontFace,"_glCompileShader":_glCompileShader,"_execvp":_execvp,"_emscripten_set_gamepadconnected_callback":_emscripten_set_gamepadconnected_callback,"_glEnableVertexAttribArray":_glEnableVertexAttribArray,"_abort":_abort,"_glBindVertexArray":_glBindVertexArray,"___syscall183":___syscall183,"_glDeleteBuffers":_glDeleteBuffers,"_glBufferData":_glBufferData,"_glTexImage2D":_glTexImage2D,"_glGetProgramInfoLog":_glGetProgramInfoLog,"_glGetUniformBlockIndex":_glGetUniformBlockIndex,"_glCompressedTexImage3D":_glCompressedTexImage3D,"_waitpid":_waitpid,"_pthread_getspecific":_pthread_getspecific,"_glDeleteShader":_glDeleteShader,"_fork":_fork,"_glRenderbufferStorageMultisample":_glRenderbufferStorageMultisample,"_glGetProgramiv":_glGetProgramiv,"_llvm_exp2_f32":_llvm_exp2_f32,"___syscall168":___syscall168,"_glScissor":_glScissor,"_emscripten_request_pointerlock":_emscripten_request_pointerlock,"___syscall40":___syscall40,"_sigaction":_sigaction,"_sem_destroy":_sem_destroy,"___syscall5":___syscall5,"_emscripten_set_keydown_callback":_emscripten_set_keydown_callback,"_llvm_bswap_i64":_llvm_bswap_i64,"_emscripten_set_touchcancel_callback":_emscripten_set_touchcancel_callback,"_emscripten_set_mousemove_callback":_emscripten_set_mousemove_callback,"_glDeleteRenderbuffers":_glDeleteRenderbuffers,"__read_sockaddr":__read_sockaddr,"_glBlitFramebuffer":_glBlitFramebuffer,"_usleep":_usleep,"_glDisable":_glDisable,"_glLinkProgram":_glLinkProgram,"_emscripten_set_touchend_callback":_emscripten_set_touchend_callback,"_emscripten_exit_fullscreen":_emscripten_exit_fullscreen,"_glGenRenderbuffers":_glGenRenderbuffers,"_glGetUniformLocation":_glGetUniformLocation,"_glBindBufferBase":_glBindBufferBase,"_glClear":_glClear,"_glUniform4fv":_glUniform4fv,"_glTexSubImage3D":_glTexSubImage3D,"_sem_post":_sem_post,"_localtime":_localtime,"_posix_spawn_file_actions_init":_posix_spawn_file_actions_init,"_glBindAttribLocation":_glBindAttribLocation,"_glPixelStorei":_glPixelStorei,"_glUniform1iv":_glUniform1iv,"_glGetShaderiv":_glGetShaderiv,"_glTexImage3D":_glTexImage3D,"_glVertexAttribDivisor":_glVertexAttribDivisor,"_pthread_attr_setstacksize":_pthread_attr_setstacksize,"_emscripten_enter_soft_fullscreen":_emscripten_enter_soft_fullscreen,"_emscripten_get_pointerlock_status":_emscripten_get_pointerlock_status,"_emscripten_asm_const_ii":_emscripten_asm_const_ii,"_emscripten_set_wheel_callback":_emscripten_set_wheel_callback,"_emscripten_exit_soft_fullscreen":_emscripten_exit_soft_fullscreen,"___syscall54":___syscall54,"___unlock":___unlock,"_glFramebufferTexture2D":_glFramebufferTexture2D,"_pthread_create":_pthread_create,"_emscripten_set_main_loop":_emscripten_set_main_loop,"_glUniformBlockBinding":_glUniformBlockBinding,"_pthread_mutexattr_init":_pthread_mutexattr_init,"_pthread_setspecific":_pthread_setspecific,"_emscripten_asm_const_i":_emscripten_asm_const_i,"_emscripten_webgl_init_context_attributes":_emscripten_webgl_init_context_attributes,"_glCompressedTexSubImage3D":_glCompressedTexSubImage3D,"__inet_pton6_raw":__inet_pton6_raw,"_glColorMask":_glColorMask,"__hideEverythingExceptGivenElement":__hideEverythingExceptGivenElement,"_pthread_rwlock_tryrdlock":_pthread_rwlock_tryrdlock,"_glTexParameteri":_glTexParameteri,"_emscripten_longjmp":_emscripten_longjmp,"_posix_spawn_file_actions_destroy":_posix_spawn_file_actions_destroy,"_atexit":_atexit,"_pthread_mutex_init":_pthread_mutex_init,"_emscripten_get_fullscreen_status":_emscripten_get_fullscreen_status,"_glTexParameterf":_glTexParameterf,"_setenv":_setenv,"_glTexSubImage2D":_glTexSubImage2D,"DYNAMICTOP_PTR":DYNAMICTOP_PTR,"tempDoublePtr":tempDoublePtr,"ABORT":ABORT,"STACKTOP":STACKTOP,"STACK_MAX":STACK_MAX,"cttz_i8":cttz_i8,"___dso_handle":___dso_handle,"___environ":___environ};var asm=Module["asm"](Module.asmGlobalArg,Module.asmLibraryArg,buffer);Module["asm"]=asm;var stackSave=Module["stackSave"]=(function(){return Module["asm"]["stackSave"].apply(null,arguments)});var __GLOBAL__sub_I_global_constants_cpp=Module["__GLOBAL__sub_I_global_constants_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_global_constants_cpp"].apply(null,arguments)});var _main=Module["_main"]=(function(){return Module["asm"]["_main"].apply(null,arguments)});var __GLOBAL__sub_I_image_loader_svg_cpp=Module["__GLOBAL__sub_I_image_loader_svg_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_image_loader_svg_cpp"].apply(null,arguments)});var __GLOBAL__sub_I_color_cpp=Module["__GLOBAL__sub_I_color_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_color_cpp"].apply(null,arguments)});var __GLOBAL__sub_I_main_cpp=Module["__GLOBAL__sub_I_main_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_main_cpp"].apply(null,arguments)});var _resize_poolbytearray_and_open_write=Module["_resize_poolbytearray_and_open_write"]=(function(){return Module["asm"]["_resize_poolbytearray_and_open_write"].apply(null,arguments)});var __GLOBAL__sub_I_material_cpp=Module["__GLOBAL__sub_I_material_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_material_cpp"].apply(null,arguments)});var getTempRet0=Module["getTempRet0"]=(function(){return Module["asm"]["getTempRet0"].apply(null,arguments)});var __GLOBAL__sub_I_matrix3_cpp=Module["__GLOBAL__sub_I_matrix3_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_matrix3_cpp"].apply(null,arguments)});var __GLOBAL__sub_I_thread_posix_cpp=Module["__GLOBAL__sub_I_thread_posix_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_thread_posix_cpp"].apply(null,arguments)});var _pthread_mutex_trylock=Module["_pthread_mutex_trylock"]=(function(){return Module["asm"]["_pthread_mutex_trylock"].apply(null,arguments)});var _fflush=Module["_fflush"]=(function(){return Module["asm"]["_fflush"].apply(null,arguments)});var setTempRet0=Module["setTempRet0"]=(function(){return Module["asm"]["setTempRet0"].apply(null,arguments)});var _memset=Module["_memset"]=(function(){return Module["asm"]["_memset"].apply(null,arguments)});var __GLOBAL__sub_I_theme_cpp=Module["__GLOBAL__sub_I_theme_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_theme_cpp"].apply(null,arguments)});var _sbrk=Module["_sbrk"]=(function(){return Module["asm"]["_sbrk"].apply(null,arguments)});var _memcpy=Module["_memcpy"]=(function(){return Module["asm"]["_memcpy"].apply(null,arguments)});var _llvm_bswap_i32=Module["_llvm_bswap_i32"]=(function(){return Module["asm"]["_llvm_bswap_i32"].apply(null,arguments)});var __GLOBAL__sub_I_audio_server_cpp=Module["__GLOBAL__sub_I_audio_server_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_audio_server_cpp"].apply(null,arguments)});var _main_after_fs_sync=Module["_main_after_fs_sync"]=(function(){return Module["asm"]["_main_after_fs_sync"].apply(null,arguments)});var _send_notification=Module["_send_notification"]=(function(){return Module["asm"]["_send_notification"].apply(null,arguments)});var stackAlloc=Module["stackAlloc"]=(function(){return Module["asm"]["stackAlloc"].apply(null,arguments)});var __GLOBAL__sub_I_particles_cpp=Module["__GLOBAL__sub_I_particles_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_particles_cpp"].apply(null,arguments)});var _ntohs=Module["_ntohs"]=(function(){return Module["asm"]["_ntohs"].apply(null,arguments)});var _htonl=Module["_htonl"]=(function(){return Module["asm"]["_htonl"].apply(null,arguments)});var _realloc=Module["_realloc"]=(function(){return Module["asm"]["_realloc"].apply(null,arguments)});var _pthread_mutex_unlock=Module["_pthread_mutex_unlock"]=(function(){return Module["asm"]["_pthread_mutex_unlock"].apply(null,arguments)});var __GLOBAL__sub_I_resource_loader_cpp=Module["__GLOBAL__sub_I_resource_loader_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_resource_loader_cpp"].apply(null,arguments)});var _llvm_bswap_i16=Module["_llvm_bswap_i16"]=(function(){return Module["asm"]["_llvm_bswap_i16"].apply(null,arguments)});var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=(function(){return Module["asm"]["_emscripten_get_global_libc"].apply(null,arguments)});var __GLOBAL__sub_I_resource_cpp=Module["__GLOBAL__sub_I_resource_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_resource_cpp"].apply(null,arguments)});var _htons=Module["_htons"]=(function(){return Module["asm"]["_htons"].apply(null,arguments)});var __GLOBAL__sub_I_class_db_cpp=Module["__GLOBAL__sub_I_class_db_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_class_db_cpp"].apply(null,arguments)});var ___errno_location=Module["___errno_location"]=(function(){return Module["asm"]["___errno_location"].apply(null,arguments)});var _testSetjmp=Module["_testSetjmp"]=(function(){return Module["asm"]["_testSetjmp"].apply(null,arguments)});var _saveSetjmp=Module["_saveSetjmp"]=(function(){return Module["asm"]["_saveSetjmp"].apply(null,arguments)});var __GLOBAL__sub_I_canvas_item_cpp=Module["__GLOBAL__sub_I_canvas_item_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_canvas_item_cpp"].apply(null,arguments)});var _free=Module["_free"]=(function(){return Module["asm"]["_free"].apply(null,arguments)});var runPostSets=Module["runPostSets"]=(function(){return Module["asm"]["runPostSets"].apply(null,arguments)});var setThrew=Module["setThrew"]=(function(){return Module["asm"]["setThrew"].apply(null,arguments)});var _round=Module["_round"]=(function(){return Module["asm"]["_round"].apply(null,arguments)});var establishStackSpace=Module["establishStackSpace"]=(function(){return Module["asm"]["establishStackSpace"].apply(null,arguments)});var _memmove=Module["_memmove"]=(function(){return Module["asm"]["_memmove"].apply(null,arguments)});var stackRestore=Module["stackRestore"]=(function(){return Module["asm"]["stackRestore"].apply(null,arguments)});var __GLOBAL__sub_I_dynamic_font_cpp=Module["__GLOBAL__sub_I_dynamic_font_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_dynamic_font_cpp"].apply(null,arguments)});var _malloc=Module["_malloc"]=(function(){return Module["asm"]["_malloc"].apply(null,arguments)});var __GLOBAL__sub_I_object_cpp=Module["__GLOBAL__sub_I_object_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_object_cpp"].apply(null,arguments)});var _pthread_mutex_lock=Module["_pthread_mutex_lock"]=(function(){return Module["asm"]["_pthread_mutex_lock"].apply(null,arguments)});var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=(function(){return Module["asm"]["_emscripten_replace_memory"].apply(null,arguments)});var __GLOBAL__sub_I_register_types_cpp=Module["__GLOBAL__sub_I_register_types_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_register_types_cpp"].apply(null,arguments)});var __GLOBAL__sub_I_visual_script_nodes_cpp=Module["__GLOBAL__sub_I_visual_script_nodes_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_visual_script_nodes_cpp"].apply(null,arguments)});var __GLOBAL__sub_I_gdnative_cpp=Module["__GLOBAL__sub_I_gdnative_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_gdnative_cpp"].apply(null,arguments)});var __GLOBAL__sub_I_os_javascript_cpp=Module["__GLOBAL__sub_I_os_javascript_cpp"]=(function(){return Module["asm"]["__GLOBAL__sub_I_os_javascript_cpp"].apply(null,arguments)});var dynCall_viij=Module["dynCall_viij"]=(function(){return Module["asm"]["dynCall_viij"].apply(null,arguments)});var dynCall_fifi=Module["dynCall_fifi"]=(function(){return Module["asm"]["dynCall_fifi"].apply(null,arguments)});var dynCall_iiiiiii=Module["dynCall_iiiiiii"]=(function(){return Module["asm"]["dynCall_iiiiiii"].apply(null,arguments)});var dynCall_viiiiiiiiiii=Module["dynCall_viiiiiiiiiii"]=(function(){return Module["asm"]["dynCall_viiiiiiiiiii"].apply(null,arguments)});var dynCall_viiiiiifi=Module["dynCall_viiiiiifi"]=(function(){return Module["asm"]["dynCall_viiiiiifi"].apply(null,arguments)});var dynCall_viiffii=Module["dynCall_viiffii"]=(function(){return Module["asm"]["dynCall_viiffii"].apply(null,arguments)});var dynCall_vidi=Module["dynCall_vidi"]=(function(){return Module["asm"]["dynCall_vidi"].apply(null,arguments)});var dynCall_iiiiifiiiii=Module["dynCall_iiiiifiiiii"]=(function(){return Module["asm"]["dynCall_iiiiifiiiii"].apply(null,arguments)});var dynCall_jii=Module["dynCall_jii"]=(function(){return Module["asm"]["dynCall_jii"].apply(null,arguments)});var dynCall_fif=Module["dynCall_fif"]=(function(){return Module["asm"]["dynCall_fif"].apply(null,arguments)});var dynCall_viiiiiiiiiiiiiii=Module["dynCall_viiiiiiiiiiiiiii"]=(function(){return Module["asm"]["dynCall_viiiiiiiiiiiiiii"].apply(null,arguments)});var dynCall_viiiifffi=Module["dynCall_viiiifffi"]=(function(){return Module["asm"]["dynCall_viiiifffi"].apply(null,arguments)});var dynCall_fii=Module["dynCall_fii"]=(function(){return Module["asm"]["dynCall_fii"].apply(null,arguments)});var dynCall_viiiiiff=Module["dynCall_viiiiiff"]=(function(){return Module["asm"]["dynCall_viiiiiff"].apply(null,arguments)});var dynCall_di=Module["dynCall_di"]=(function(){return Module["asm"]["dynCall_di"].apply(null,arguments)});var dynCall_viff=Module["dynCall_viff"]=(function(){return Module["asm"]["dynCall_viff"].apply(null,arguments)});var dynCall_iiifiii=Module["dynCall_iiifiii"]=(function(){return Module["asm"]["dynCall_iiifiii"].apply(null,arguments)});var dynCall_viiiiifi=Module["dynCall_viiiiifi"]=(function(){return Module["asm"]["dynCall_viiiiifi"].apply(null,arguments)});var dynCall_iiiifiiiiii=Module["dynCall_iiiifiiiiii"]=(function(){return Module["asm"]["dynCall_iiiifiiiiii"].apply(null,arguments)});var dynCall_viiffi=Module["dynCall_viiffi"]=(function(){return Module["asm"]["dynCall_viiffi"].apply(null,arguments)});var dynCall_dii=Module["dynCall_dii"]=(function(){return Module["asm"]["dynCall_dii"].apply(null,arguments)});var dynCall_iiiiiiiiii=Module["dynCall_iiiiiiiiii"]=(function(){return Module["asm"]["dynCall_iiiiiiiiii"].apply(null,arguments)});var dynCall_viiiiiiiff=Module["dynCall_viiiiiiiff"]=(function(){return Module["asm"]["dynCall_viiiiiiiff"].apply(null,arguments)});var dynCall_viiiff=Module["dynCall_viiiff"]=(function(){return Module["asm"]["dynCall_viiiff"].apply(null,arguments)});var dynCall_iiiiiiii=Module["dynCall_iiiiiiii"]=(function(){return Module["asm"]["dynCall_iiiiiiii"].apply(null,arguments)});var dynCall_j=Module["dynCall_j"]=(function(){return Module["asm"]["dynCall_j"].apply(null,arguments)});var dynCall_viiiiffif=Module["dynCall_viiiiffif"]=(function(){return Module["asm"]["dynCall_viiiiffif"].apply(null,arguments)});var dynCall_iiiji=Module["dynCall_iiiji"]=(function(){return Module["asm"]["dynCall_iiiji"].apply(null,arguments)});var dynCall_viidddi=Module["dynCall_viidddi"]=(function(){return Module["asm"]["dynCall_viidddi"].apply(null,arguments)});var dynCall_viiiiffii=Module["dynCall_viiiiffii"]=(function(){return Module["asm"]["dynCall_viiiiffii"].apply(null,arguments)});var dynCall_viiifi=Module["dynCall_viiifi"]=(function(){return Module["asm"]["dynCall_viiifi"].apply(null,arguments)});var dynCall_diiiiiiii=Module["dynCall_diiiiiiii"]=(function(){return Module["asm"]["dynCall_diiiiiiii"].apply(null,arguments)});var dynCall_iiifii=Module["dynCall_iiifii"]=(function(){return Module["asm"]["dynCall_iiifii"].apply(null,arguments)});var dynCall_viiiffiii=Module["dynCall_viiiffiii"]=(function(){return Module["asm"]["dynCall_viiiffiii"].apply(null,arguments)});var dynCall_viiiiif=Module["dynCall_viiiiif"]=(function(){return Module["asm"]["dynCall_viiiiif"].apply(null,arguments)});var dynCall_iiiifiiii=Module["dynCall_iiiifiiii"]=(function(){return Module["asm"]["dynCall_iiiifiiii"].apply(null,arguments)});var dynCall_vifi=Module["dynCall_vifi"]=(function(){return Module["asm"]["dynCall_vifi"].apply(null,arguments)});var dynCall_vifff=Module["dynCall_vifff"]=(function(){return Module["asm"]["dynCall_vifff"].apply(null,arguments)});var dynCall_viiiiii=Module["dynCall_viiiiii"]=(function(){return Module["asm"]["dynCall_viiiiii"].apply(null,arguments)});var dynCall_fiii=Module["dynCall_fiii"]=(function(){return Module["asm"]["dynCall_fiii"].apply(null,arguments)});var dynCall_viiifffi=Module["dynCall_viiifffi"]=(function(){return Module["asm"]["dynCall_viiifffi"].apply(null,arguments)});var dynCall_ji=Module["dynCall_ji"]=(function(){return Module["asm"]["dynCall_ji"].apply(null,arguments)});var dynCall_viiiiiiiiii=Module["dynCall_viiiiiiiiii"]=(function(){return Module["asm"]["dynCall_viiiiiiiiii"].apply(null,arguments)});var dynCall_viif=Module["dynCall_viif