diff -pruN 1:60.2.1-1/accessible/tests/mochitest/jsat/test_output_mathml.html 1:60.2.1+build1-0ubuntu1/accessible/tests/mochitest/jsat/test_output_mathml.html --- 1:60.2.1-1/accessible/tests/mochitest/jsat/test_output_mathml.html 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/accessible/tests/mochitest/jsat/test_output_mathml.html 2018-10-02 14:08:34.000000000 +0000 @@ -0,0 +1,313 @@ + + + [AccessFu] MathML Accessibility Support + + + + + + + + + +
+ + Mozilla Bug 1163374 + +

+ +

+
+    (x,y)
+
+    
+      
+        a
+        b
+      
+    
+
+    
+      
+        a
+        b
+      
+    
+
+    
+      
+        a
+        b
+      
+    
+    
+      
+        a
+        b
+      
+    
+    
+      
+        a
+        b
+        c
+      
+    
+    
+      
+        a
+        b
+        c
+        
+        d
+        
+        e
+        
+        f
+        g
+      
+    
+
+    
+      
+        a
+        b
+      
+    
+    
+      
+        a
+        b
+      
+    
+    
+      
+        a
+        b
+        c
+      
+    
+
+    
+      
+        a
+        b
+      
+    
+
+    
+      
+        
+          a
+          b
+          c
+        
+        
+          d
+          e
+          f
+        
+      
+    
+
+    
+      a
+    
+    
+      a
+    
+    
+      a
+    
+
+  
+ + diff -pruN 1:60.2.1-1/browser/app/profile/firefox.js 1:60.2.1+build1-0ubuntu1/browser/app/profile/firefox.js --- 1:60.2.1-1/browser/app/profile/firefox.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/app/profile/firefox.js 2018-10-02 14:08:34.000000000 +0000 @@ -0,0 +1,1750 @@ +# -*- indent-tabs-mode: nil; js-indent-level: 2 -*- +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// XXX Toolkit-specific preferences should be moved into toolkit.js + +#filter substitution + +# +# SYNTAX HINTS: +# +# - Dashes are delimiters; use underscores instead. +# - The first character after a period must be alphabetic. +# - Computed values (e.g. 50 * 1024) don't work. +# + +#ifdef XP_UNIX +#ifndef XP_MACOSX +#define UNIX_BUT_NOT_MAC +#endif +#endif + +pref("browser.chromeURL","chrome://browser/content/"); +pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul"); + +// Enables some extra Extension System Logging (can reduce performance) +pref("extensions.logging.enabled", false); + +// Disables strict compatibility, making addons compatible-by-default. +pref("extensions.strictCompatibility", false); + +// Specifies a minimum maxVersion an addon needs to say it's compatible with +// for it to be compatible by default. +pref("extensions.minCompatibleAppVersion", "4.0"); +// Temporary preference to forcibly make themes more safe with Australis even if +// extensions.checkCompatibility=false has been set. +pref("extensions.checkCompatibility.temporaryThemeOverride_minAppVersion", "29.0a1"); + +pref("xpinstall.customConfirmationUI", true); +pref("extensions.webextPermissionPrompts", true); +pref("extensions.webextOptionalPermissionPrompts", true); + +// Preferences for AMO integration +pref("extensions.getAddons.cache.enabled", true); +pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/api/v3/addons/search/?guid=%IDS%&lang=%LOCALE%"); +pref("extensions.getAddons.compatOverides.url", "https://services.addons.mozilla.org/api/v3/addons/compat-override/?guid=%IDS%&lang=%LOCALE%"); +pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/search?q=%TERMS%&platform=%OS%&appver=%VERSION%"); +pref("extensions.webservice.discoverURL", "https://discovery.addons.mozilla.org/%LOCALE%/firefox/discovery/pane/%VERSION%/%OS%/%COMPATIBILITY_MODE%"); +pref("extensions.getAddons.link.url", "https://addons.mozilla.org/%LOCALE%/firefox/"); +pref("extensions.getAddons.themes.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes/?src=firefox"); + +pref("extensions.update.autoUpdateDefault", true); + +// Check AUS for system add-on updates. +pref("extensions.systemAddon.update.url", "https://aus5.mozilla.org/update/3/SystemAddons/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml"); + +// Disable add-ons that are not installed by the user in all scopes by default. +// See the SCOPE constants in AddonManager.jsm for values to use here. +pref("extensions.autoDisableScopes", 15); +// Scopes to scan for changes at startup. +pref("extensions.startupScanScopes", 0); + +// This is where the profiler WebExtension API will look for breakpad symbols. +// NOTE: deliberately http right now since https://symbols.mozilla.org is not supported. +pref("extensions.geckoProfiler.symbols.url", "http://symbols.mozilla.org/"); +pref("extensions.geckoProfiler.acceptedExtensionIds", "geckoprofiler@mozilla.com,quantum-foxfooding@mozilla.com"); +#if defined(XP_LINUX) || defined (XP_MACOSX) +pref("extensions.geckoProfiler.getSymbolRules", "localBreakpad,remoteBreakpad,nm"); +#else // defined(XP_WIN) +pref("extensions.geckoProfiler.getSymbolRules", "localBreakpad,remoteBreakpad"); +#endif + + +// Add-on content security policies. +pref("extensions.webextensions.base-content-security-policy", "script-src 'self' https://* moz-extension: blob: filesystem: 'unsafe-eval' 'unsafe-inline'; object-src 'self' https://* moz-extension: blob: filesystem:;"); +pref("extensions.webextensions.default-content-security-policy", "script-src 'self'; object-src 'self';"); + +#if defined(XP_WIN) +pref("extensions.webextensions.remote", true); +#elif defined(XP_MACOSX) && !defined(RELEASE_OR_BETA) +pref("extensions.webextensions.remote", true); +#endif + +// Extensions that should not be flagged as legacy in about:addons +pref("extensions.legacy.exceptions", "{972ce4c6-7e08-4474-a285-3208198ce6fd},testpilot@cliqz.com,@testpilot-containers,jid1-NeEaf3sAHdKHPA@jetpack,@activity-streams,pulse@mozilla.com,@testpilot-addon,@min-vid,tabcentertest1@mozilla.com,snoozetabs@mozilla.com,speaktome@mozilla.com,hoverpad@mozilla.com"); + +// Require signed add-ons by default +pref("extensions.langpacks.signatures.required", true); +pref("xpinstall.signatures.required", true); +pref("xpinstall.signatures.devInfoURL", "https://wiki.mozilla.org/Addons/Extension_Signing"); + +// Dictionary download preference +pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/firefox/dictionaries/"); + +// At startup, should we check to see if the installation +// date is older than some threshold +pref("app.update.checkInstallTime", true); + +// The number of days a binary is permitted to be old without checking is defined in +// firefox-branding.js (app.update.checkInstallTime.days) + +// The minimum delay in seconds for the timer to fire between the notification +// of each consumer of the timer manager. +// minimum=30 seconds, default=120 seconds, and maximum=300 seconds +pref("app.update.timerMinimumDelay", 120); + +// The minimum delay in milliseconds for the first firing after startup of the timer +// to notify consumers of the timer manager. +// minimum=10 seconds, default=30 seconds, and maximum=120 seconds +pref("app.update.timerFirstInterval", 30000); + +// App-specific update preferences + +// The interval to check for updates (app.update.interval) is defined in +// firefox-branding.js + +// Alternative windowtype for an application update user interface window. When +// a window with this windowtype is open the application update service won't +// open the normal application update user interface window. +pref("app.update.altwindowtype", "Browser:About"); + +// Enables some extra Application Update Logging (can reduce performance) +pref("app.update.log", false); + +// The number of general background check failures to allow before notifying the +// user of the failure. User initiated update checks always notify the user of +// the failure. +pref("app.update.backgroundMaxErrors", 10); + +// Whether or not app updates are enabled +#ifdef MOZ_UPDATER +pref("app.update.enabled", true); +#else +pref("app.update.enabled", false); +#endif + +// Whether or not to use the doorhanger application update UI. +pref("app.update.doorhanger", true); + +// Ids of the links to the "What's new" update documentation +pref("app.update.link.updateAvailableWhatsNew", "update-available-whats-new"); +pref("app.update.link.updateManualWhatsNew", "update-manual-whats-new"); + +// How many times we should let downloads fail before prompting the user to +// download a fresh installer. +pref("app.update.download.promptMaxAttempts", 2); + +// How many times we should let an elevation prompt fail before prompting the user to +// download a fresh installer. +pref("app.update.elevation.promptMaxAttempts", 2); + +// If set to true, the Update Service will automatically download updates when +// app updates are enabled per the app.update.enabled preference and if the user +// can apply updates. +pref("app.update.auto", true); + +// If set to true, the Update Service will present no UI for any event. +pref("app.update.silent", false); + +// app.update.badgeWaitTime is in branding section + +// If set to true, the Update Service will apply updates in the background +// when it finishes downloading them. Disabled in bug 1397562. +pref("app.update.staging.enabled", false); + +// Update service URL: +pref("app.update.url", "https://aus5.mozilla.org/update/6/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%SYSTEM_CAPABILITIES%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml"); +// app.update.url.manual is in branding section +// app.update.url.details is in branding section + +// app.update.interval is in branding section +// app.update.promptWaitTime is in branding section + +// Show the Update Checking/Ready UI when the user was idle for x seconds +pref("app.update.idletime", 60); + +// Whether or not to attempt using the service for updates. +#ifdef MOZ_MAINTENANCE_SERVICE +pref("app.update.service.enabled", true); +#endif + +// Symmetric (can be overridden by individual extensions) update preferences. +// e.g. +// extensions.{GUID}.update.enabled +// extensions.{GUID}.update.url +// .. etc .. +// +pref("extensions.update.enabled", true); +pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%"); +pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%"); +pref("extensions.update.interval", 86400); // Check for updates to Extensions and + // Themes every day +// Non-symmetric (not shared by extensions) extension-specific [update] preferences +pref("extensions.dss.switchPending", false); // Non-dynamic switch pending after next + // restart. + +pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name", "chrome://browser/locale/browser.properties"); +pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description", "chrome://browser/locale/browser.properties"); + +pref("extensions.webextensions.themes.enabled", true); +pref("extensions.webextensions.themes.icons.buttons", "back,forward,reload,stop,bookmark_star,bookmark_menu,downloads,home,app_menu,cut,copy,paste,new_window,new_private_window,save_page,print,history,full_screen,find,options,addons,developer,synced_tabs,open_file,sidebars,share_page,subscribe,text_encoding,email_link,forget,pocket"); + +pref("lightweightThemes.update.enabled", true); +pref("lightweightThemes.getMoreURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes"); +pref("lightweightThemes.recommendedThemes", "[{\"id\":\"recommended-1\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/a-web-browser-renaissance/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.header.jpg\",\"textcolor\":\"#000000\",\"accentcolor\":\"#834d29\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.preview.jpg\",\"author\":\"Sean.Martell\",\"version\":\"0\"},{\"id\":\"recommended-2\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/space-fantasy/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.header.jpg\",\"textcolor\":\"#ffffff\",\"accentcolor\":\"#d9d9d9\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.preview.jpg\",\"author\":\"fx5800p\",\"version\":\"1.0\"},{\"id\":\"recommended-4\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/pastel-gradient/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.header.png\",\"textcolor\":\"#000000\",\"accentcolor\":\"#000000\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.preview.png\",\"author\":\"darrinhenein\",\"version\":\"1.0\"}]"); + +#if defined(MOZ_WIDEVINE_EME) +pref("browser.eme.ui.enabled", true); +#else +pref("browser.eme.ui.enabled", false); +#endif + +// UI tour experience. +pref("browser.uitour.enabled", true); +pref("browser.uitour.loglevel", "Error"); +pref("browser.uitour.requireSecure", true); +pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/"); +pref("browser.uitour.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tour/"); +// How long to show a Hearbeat survey (two hours, in seconds) +pref("browser.uitour.surveyDuration", 7200); + +pref("keyword.enabled", true); +pref("browser.fixup.domainwhitelist.localhost", true); + +pref("general.skins.selectedSkin", "classic/1.0"); + +pref("general.smoothScroll", true); +#ifdef UNIX_BUT_NOT_MAC +pref("general.autoScroll", false); +#else +pref("general.autoScroll", true); +#endif + +pref("browser.stopReloadAnimation.enabled", true); +pref("browser.schedulePressure.enabled", true); +pref("browser.schedulePressure.defaultCount", 3); +pref("browser.schedulePressure.timeoutMs", 300); + +// UI density of the browser chrome. This mostly affects toolbarbutton +// and urlbar spacing. The possible values are 0=normal, 1=compact, 2=touch. +pref("browser.uidensity", 0); +// Whether Firefox will automatically override the uidensity to "touch" +// while the user is in a touch environment (such as Windows tablet mode). +pref("browser.touchmode.auto", true); + +// At startup, check if we're the default browser and prompt user if not. +pref("browser.shell.checkDefaultBrowser", true); +pref("browser.shell.shortcutFavicons",true); +pref("browser.shell.mostRecentDateSetAsDefault", ""); +pref("browser.shell.skipDefaultBrowserCheckOnFirstRun", true); +pref("browser.shell.didSkipDefaultBrowserCheckOnFirstRun", false); +pref("browser.shell.defaultBrowserCheckCount", 0); +pref("browser.defaultbrowser.notificationbar", false); + +// 0 = blank, 1 = home (browser.startup.homepage), 2 = last visited page, 3 = resume previous browser session +// The behavior of option 3 is detailed at: http://wiki.mozilla.org/Session_Restore +pref("browser.startup.page", 1); +pref("browser.startup.homepage", "chrome://branding/locale/browserconfig.properties"); +// Whether we should skip the homepage when opening the first-run page +pref("browser.startup.firstrunSkipsHomepage", true); + +// Show an about:blank window as early as possible for quick startup feedback. +pref("browser.startup.blankWindow", false); + +pref("browser.slowStartup.notificationDisabled", false); +pref("browser.slowStartup.timeThreshold", 20000); +pref("browser.slowStartup.maxSamples", 5); + +// This url, if changed, MUST continue to point to an https url. Pulling arbitrary content to inject into +// this page over http opens us up to a man-in-the-middle attack that we'd rather not face. If you are a downstream +// repackager of this code using an alternate snippet url, please keep your users safe +pref("browser.aboutHomeSnippets.updateUrl", "https://snippets.cdn.mozilla.net/%STARTPAGE_VERSION%/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/"); + +pref("browser.enable_automatic_image_resizing", true); +pref("browser.chrome.site_icons", true); +pref("browser.chrome.favicons", true); +// browser.warnOnQuit == false will override all other possible prompts when quitting or restarting +pref("browser.warnOnQuit", true); +// browser.showQuitWarning specifically controls the quit warning dialog. We +// might still show the window closing dialog with showQuitWarning == false. +pref("browser.showQuitWarning", false); +pref("browser.fullscreen.autohide", true); +pref("browser.overlink-delay", 80); + +#ifdef UNIX_BUT_NOT_MAC +pref("browser.urlbar.clickSelectsAll", false); +#else +pref("browser.urlbar.clickSelectsAll", true); +#endif +#ifdef UNIX_BUT_NOT_MAC +pref("browser.urlbar.doubleClickSelectsAll", true); +#else +pref("browser.urlbar.doubleClickSelectsAll", false); +#endif + +// Control autoFill behavior +pref("browser.urlbar.autoFill", true); +pref("browser.urlbar.autoFill.typed", true); +pref("browser.urlbar.speculativeConnect.enabled", true); + +// 0: Match anywhere (e.g., middle of words) +// 1: Match on word boundaries and then try matching anywhere +// 2: Match only on word boundaries (e.g., after / or .) +// 3: Match at the beginning of the url or title +pref("browser.urlbar.matchBehavior", 1); +pref("browser.urlbar.filter.javascript", true); + +// the maximum number of results to show in autocomplete when doing richResults +pref("browser.urlbar.maxRichResults", 10); +// The amount of time (ms) to wait after the user has stopped typing +// before starting to perform autocomplete. 50 is the default set in +// autocomplete.xml. +pref("browser.urlbar.delay", 50); + +// The maximum number of historical search results to show. +pref("browser.urlbar.maxHistoricalSearchSuggestions", 0); + +// The default behavior for the urlbar can be configured to use any combination +// of the match filters with each additional filter adding more results (union). +pref("browser.urlbar.suggest.history", true); +pref("browser.urlbar.suggest.bookmark", true); +pref("browser.urlbar.suggest.openpage", true); +pref("browser.urlbar.suggest.searches", true); + +// Whether the user made a choice in the old search suggestions opt-in bar. +pref("browser.urlbar.userMadeSearchSuggestionsChoice", false); +// The suggestion opt-out hint will be hidden after being shown 4 times. +pref("browser.urlbar.timesBeforeHidingSuggestionsHint", 4); + +// Limit the number of characters sent to the current search engine to fetch +// suggestions. +pref("browser.urlbar.maxCharsForSearchSuggestions", 20); + +// Restrictions to current suggestions can also be applied (intersection). +// Typed suggestion works only if history is set to true. +pref("browser.urlbar.suggest.history.onlyTyped", false); + +pref("browser.urlbar.formatting.enabled", true); +pref("browser.urlbar.trimURLs", true); + +pref("browser.urlbar.oneOffSearches", true); + +// If changed to true, copying the entire URL from the location bar will put the +// human readable (percent-decoded) URL on the clipboard. +pref("browser.urlbar.decodeURLsOnCopy", false); + +// Whether or not to move tabs into the active window when using the "Switch to +// Tab" feature of the awesomebar. +pref("browser.urlbar.switchTabs.adoptIntoActiveWindow", false); + +// Whether addresses and search results typed into the address bar +// should be opened in new tabs by default. +pref("browser.urlbar.openintab", false); + +pref("browser.altClickSave", false); + +// Enable logging downloads operations to the Console. +pref("browser.download.loglevel", "Error"); + +// Number of milliseconds to wait for the http headers (and thus +// the Content-Disposition filename) before giving up and falling back to +// picking a filename without that info in hand so that the user sees some +// feedback from their action. +pref("browser.download.saveLinkAsFilenameTimeout", 4000); + +pref("browser.download.useDownloadDir", true); +pref("browser.download.folderList", 1); +pref("browser.download.manager.addToRecentDocs", true); +pref("browser.download.manager.resumeOnWakeDelay", 10000); + +// This allows disabling the animated notifications shown by +// the Downloads Indicator when a download starts or completes. +pref("browser.download.animateNotifications", true); + +// This records whether or not the panel has been shown at least once. +pref("browser.download.panel.shown", false); + +// This controls whether the button is automatically shown/hidden depending +// on whether there are downloads to show. +pref("browser.download.autohideButton", true); + +#ifndef XP_MACOSX +pref("browser.helperApps.deleteTempFileOnExit", true); +#endif + +// search engines URL +pref("browser.search.searchEnginesURL", "https://addons.mozilla.org/%LOCALE%/firefox/search-engines/"); + +// pointer to the default engine name +pref("browser.search.defaultenginename", "chrome://browser-region/locale/region.properties"); + +// Ordering of Search Engines in the Engine list. +pref("browser.search.order.1", "chrome://browser-region/locale/region.properties"); +pref("browser.search.order.2", "chrome://browser-region/locale/region.properties"); +pref("browser.search.order.3", "chrome://browser-region/locale/region.properties"); + +// Market-specific search defaults +pref("browser.search.geoSpecificDefaults", true); +pref("browser.search.geoSpecificDefaults.url", "https://search.services.mozilla.com/1/%APP%/%VERSION%/%CHANNEL%/%LOCALE%/%REGION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%"); + +// US specific default (used as a fallback if the geoSpecificDefaults request fails). +pref("browser.search.defaultenginename.US", "data:text/plain,browser.search.defaultenginename.US=Google"); +pref("browser.search.order.US.1", "data:text/plain,browser.search.order.US.1=Google"); +pref("browser.search.order.US.2", "data:text/plain,browser.search.order.US.2=Bing"); + +// search bar results always open in a new tab +pref("browser.search.openintab", false); + +// context menu searches open in the foreground +pref("browser.search.context.loadInBackground", false); + +// comma seperated list of of engines to hide in the search panel. +pref("browser.search.hiddenOneOffs", ""); + +// Mirrors whether the search-container widget is in the navigation toolbar. +pref("browser.search.widget.inNavBar", false); + +#ifndef RELEASE_OR_BETA +pref("browser.search.reset.enabled", true); +#endif + +pref("browser.sessionhistory.max_entries", 50); + +// Built-in default permissions. +pref("permissions.manager.defaultsUrl", "resource://app/defaults/permissions"); + +// Set default fallback values for site permissions we want +// the user to be able to globally change. +pref("permissions.default.camera", 0); +pref("permissions.default.microphone", 0); +pref("permissions.default.geo", 0); +pref("permissions.default.desktop-notification", 0); +pref("permissions.default.shortcuts", 0); + +// handle links targeting new windows +// 1=current window/tab, 2=new window, 3=new tab in most recent window +pref("browser.link.open_newwindow", 3); + +// handle external links (i.e. links opened from a different application) +// default: use browser.link.open_newwindow +// 1-3: see browser.link.open_newwindow for interpretation +pref("browser.link.open_newwindow.override.external", -1); + +// 0: no restrictions - divert everything +// 1: don't divert window.open at all +// 2: don't divert window.open with features +pref("browser.link.open_newwindow.restriction", 2); + +// If true, this pref causes windows opened by window.open to be forced into new +// tabs (rather than potentially opening separate windows, depending on +// window.open arguments) when the browser is in fullscreen mode. +// We set this differently on Mac because the fullscreen implementation there is +// different. +#ifdef XP_MACOSX +pref("browser.link.open_newwindow.disabled_in_fullscreen", true); +#else +pref("browser.link.open_newwindow.disabled_in_fullscreen", false); +#endif + +// Tabbed browser +pref("browser.tabs.closeWindowWithLastTab", true); +pref("browser.tabs.insertRelatedAfterCurrent", true); +pref("browser.tabs.warnOnClose", true); +pref("browser.tabs.warnOnCloseOtherTabs", true); +pref("browser.tabs.warnOnOpen", true); +pref("browser.tabs.maxOpenBeforeWarn", 15); +pref("browser.tabs.loadInBackground", true); +pref("browser.tabs.opentabfor.middleclick", true); +pref("browser.tabs.loadDivertedInBackground", false); +pref("browser.tabs.loadBookmarksInBackground", false); +pref("browser.tabs.loadBookmarksInTabs", false); +pref("browser.tabs.tabClipWidth", 140); +pref("browser.tabs.tabMinWidth", 76); +#ifdef UNIX_BUT_NOT_MAC +pref("browser.tabs.drawInTitlebar", false); +#else +pref("browser.tabs.drawInTitlebar", true); +#endif + +// Offer additional drag space to the user. The drag space +// will only be shown if browser.tabs.drawInTitlebar is true. +pref("browser.tabs.extraDragSpace", false); + +// 0 - Disable the tabbar session restore button. +// 1 - Enable the tabbar session restore button. +// 2 - Control group. The tabbar session restore button is disabled, +// but we will record data on other session restore usage. +// To be enabled with shield. +pref("browser.tabs.restorebutton", 0); + +// When tabs opened by links in other tabs via a combination of +// browser.link.open_newwindow being set to 3 and target="_blank" etc are +// closed: +// true return to the tab that opened this tab (its owner) +// false return to the adjacent tab (old default) +pref("browser.tabs.selectOwnerOnClose", true); + +pref("browser.tabs.showAudioPlayingIcon", true); +// This should match Chromium's audio indicator delay. +pref("browser.tabs.delayHidingAudioPlayingIconMS", 3000); + +pref("browser.ctrlTab.previews", false); + +// By default, do not export HTML at shutdown. +// If true, at shutdown the bookmarks in your menu and toolbar will +// be exported as HTML to the bookmarks.html file. +pref("browser.bookmarks.autoExportHTML", false); + +// The maximum number of daily bookmark backups to +// keep in {PROFILEDIR}/bookmarkbackups. Special values: +// -1: unlimited +// 0: no backups created (and deletes all existing backups) +pref("browser.bookmarks.max_backups", 15); + +// Whether menu should close after Ctrl-click, middle-click, etc. +pref("browser.bookmarks.openInTabClosesMenu", true); + +// Scripts & Windows prefs +pref("dom.disable_open_during_load", true); +pref("javascript.options.showInConsole", true); +#ifdef DEBUG +pref("general.warnOnAboutConfig", false); +#endif + +// This is the pref to control the location bar, change this to true to +// force this - this makes the origin of popup windows more obvious to avoid +// spoofing. We would rather not do it by default because it affects UE for web +// applications, but without it there isn't a really good way to prevent chrome +// spoofing, see bug 337344 +pref("dom.disable_window_open_feature.location", true); +// allow JS to move and resize existing windows +pref("dom.disable_window_move_resize", false); +// prevent JS from monkeying with window focus, etc +pref("dom.disable_window_flip", true); + +// popups.policy 1=allow,2=reject +pref("privacy.popups.policy", 1); +pref("privacy.popups.usecustom", true); +pref("privacy.popups.showBrowserMessage", true); + +pref("privacy.item.cookies", false); + +pref("privacy.clearOnShutdown.history", true); +pref("privacy.clearOnShutdown.formdata", true); +pref("privacy.clearOnShutdown.downloads", true); +pref("privacy.clearOnShutdown.cookies", true); +pref("privacy.clearOnShutdown.cache", true); +pref("privacy.clearOnShutdown.sessions", true); +pref("privacy.clearOnShutdown.offlineApps", false); +pref("privacy.clearOnShutdown.siteSettings", false); +pref("privacy.clearOnShutdown.openWindows", false); + +pref("privacy.cpd.history", true); +pref("privacy.cpd.formdata", true); +pref("privacy.cpd.passwords", false); +pref("privacy.cpd.downloads", true); +pref("privacy.cpd.cookies", true); +pref("privacy.cpd.cache", true); +pref("privacy.cpd.sessions", true); +pref("privacy.cpd.offlineApps", false); +pref("privacy.cpd.siteSettings", false); +pref("privacy.cpd.openWindows", false); + +pref("privacy.history.custom", false); + +// What default should we use for the time span in the sanitizer: +// 0 - Clear everything +// 1 - Last Hour +// 2 - Last 2 Hours +// 3 - Last 4 Hours +// 4 - Today +// 5 - Last 5 minutes +// 6 - Last 24 hours +pref("privacy.sanitize.timeSpan", 1); +pref("privacy.sanitize.sanitizeOnShutdown", false); + +pref("privacy.sanitize.migrateFx3Prefs", false); + +pref("privacy.panicButton.enabled", true); + +// Time until temporary permissions expire, in ms +pref("privacy.temporary_permission_expire_time_ms", 3600000); + +// If Accept-Language should be spoofed by en-US +// 0 - will prompt +// 1 - don't spoof +// 2 - spoof +pref("privacy.spoof_english", 0); + +pref("network.proxy.share_proxy_settings", false); // use the same proxy settings for all protocols + +// simple gestures support +pref("browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"); +pref("browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"); +pref("browser.gesture.swipe.up", "cmd_scrollTop"); +pref("browser.gesture.swipe.down", "cmd_scrollBottom"); +#ifdef XP_MACOSX +pref("browser.gesture.pinch.latched", true); +pref("browser.gesture.pinch.threshold", 150); +#else +pref("browser.gesture.pinch.latched", false); +pref("browser.gesture.pinch.threshold", 25); +#endif +#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) +// Enabled for touch input display zoom. +pref("browser.gesture.pinch.out", "cmd_fullZoomEnlarge"); +pref("browser.gesture.pinch.in", "cmd_fullZoomReduce"); +pref("browser.gesture.pinch.out.shift", "cmd_fullZoomReset"); +pref("browser.gesture.pinch.in.shift", "cmd_fullZoomReset"); +#else +// Disabled by default due to issues with track pad input. +pref("browser.gesture.pinch.out", ""); +pref("browser.gesture.pinch.in", ""); +pref("browser.gesture.pinch.out.shift", ""); +pref("browser.gesture.pinch.in.shift", ""); +#endif +pref("browser.gesture.twist.latched", false); +pref("browser.gesture.twist.threshold", 0); +pref("browser.gesture.twist.right", "cmd_gestureRotateRight"); +pref("browser.gesture.twist.left", "cmd_gestureRotateLeft"); +pref("browser.gesture.twist.end", "cmd_gestureRotateEnd"); +pref("browser.gesture.tap", "cmd_fullZoomReset"); + +pref("browser.snapshots.limit", 0); + +// 0: Nothing happens +// 1: Scrolling contents +// 2: Go back or go forward, in your history +// 3: Zoom in or out. +// 4: Treat vertical wheel as horizontal scroll +#ifdef XP_MACOSX +// On macOS, if the wheel has one axis only, shift+wheel comes through as a +// horizontal scroll event. Thus, we can't assign anything other than normal +// scrolling to shift+wheel. +pref("mousewheel.with_shift.action", 1); +pref("mousewheel.with_alt.action", 2); +// On MacOS X, control+wheel is typically handled by system and we don't +// receive the event. So, command key which is the main modifier key for +// acceleration is the best modifier for zoom-in/out. However, we should keep +// the control key setting for backward compatibility. +pref("mousewheel.with_meta.action", 3); // command key on Mac +// Disable control-/meta-modified horizontal wheel events, since those are +// used on Mac as part of modified swipe gestures (e.g. Left swipe+Cmd is +// "go back" in a new tab). +pref("mousewheel.with_control.action.override_x", 0); +pref("mousewheel.with_meta.action.override_x", 0); +#else +// On the other platforms (non-macOS), user may use legacy mouse which supports +// only vertical wheel but want to scroll horizontally. For such users, we +// should provide horizontal scroll with shift+wheel (same as Chrome). +// However, shift+wheel was used for navigating history. For users who want +// to keep using this feature, let's enable it with alt+wheel. This is better +// for consistency with macOS users. +pref("mousewheel.with_shift.action", 4); +pref("mousewheel.with_alt.action", 2); +pref("mousewheel.with_meta.action", 1); // win key on Win, Super/Hyper on Linux +#endif +pref("mousewheel.with_control.action",3); +pref("mousewheel.with_win.action", 1); + +pref("browser.xul.error_pages.enabled", true); +pref("browser.xul.error_pages.expert_bad_cert", false); +pref("browser.xul.error_pages.show_safe_browsing_details_on_load", false); + +// Enable captive portal detection. +pref("network.captive-portal-service.enabled", true); + +// If true, network link events will change the value of navigator.onLine +pref("network.manage-offline-status", true); + +// We want to make sure mail URLs are handled externally... +pref("network.protocol-handler.external.mailto", true); // for mail +pref("network.protocol-handler.external.news", true); // for news +pref("network.protocol-handler.external.snews", true); // for secure news +pref("network.protocol-handler.external.nntp", true); // also news +#ifdef XP_WIN +pref("network.protocol-handler.external.ms-windows-store", true); +#endif + +// ...without warning dialogs +pref("network.protocol-handler.warn-external.mailto", false); +pref("network.protocol-handler.warn-external.news", false); +pref("network.protocol-handler.warn-external.snews", false); +pref("network.protocol-handler.warn-external.nntp", false); +#ifdef XP_WIN +pref("network.protocol-handler.warn-external.ms-windows-store", false); +#endif + +// By default, all protocol handlers are exposed. This means that +// the browser will respond to openURL commands for all URL types. +// It will also try to open link clicks inside the browser before +// failing over to the system handlers. +pref("network.protocol-handler.expose-all", true); +pref("network.protocol-handler.expose.mailto", false); +pref("network.protocol-handler.expose.news", false); +pref("network.protocol-handler.expose.snews", false); +pref("network.protocol-handler.expose.nntp", false); + +pref("accessibility.typeaheadfind", false); +pref("accessibility.typeaheadfind.timeout", 5000); +pref("accessibility.typeaheadfind.linksonly", false); +pref("accessibility.typeaheadfind.flashBar", 1); + +// Accessibility indicator preferences such as support URL, enabled flag. +pref("accessibility.support.url", "https://support.mozilla.org/%LOCALE%/kb/accessibility-services"); +pref("accessibility.indicator.enabled", false); + +pref("plugins.click_to_play", true); +pref("plugins.testmode", false); + +// Should plugins that are hidden show the infobar UI? +pref("plugins.show_infobar", false); + +// Should dismissing the hidden plugin infobar suppress it permanently? +pref("plugins.remember_infobar_dismissal", true); + +pref("plugin.default.state", 1); + +// Plugins bundled in XPIs are enabled by default. +pref("plugin.defaultXpi.state", 2); + +// Java is Click-to-Activate by default on all channels. +pref("plugin.state.java", 1); + +// Flash is Click-to-Activate by default on all channels. +pref("plugin.state.flash", 1); + +// Enables the download and use of the flash blocklists. +pref("plugins.flashBlock.enabled", true); + +// Prefer HTML5 video over Flash content, and don't +// load plugin instances with no src declared. +// These prefs are documented in details on all.js. +// With the "follow-ctp" setting, this will only +// apply to users that have plugin.state.flash = 1. +pref("plugins.favorfallback.mode", "follow-ctp"); +pref("plugins.favorfallback.rules", "nosrc,video"); + + +#ifdef XP_WIN +pref("browser.preferences.instantApply", false); +#else +pref("browser.preferences.instantApply", true); +#endif + +// Toggling Search bar on and off in about:preferences +pref("browser.preferences.search", true); + +pref("browser.preferences.defaultPerformanceSettings.enabled", true); + +pref("browser.download.show_plugins_in_list", true); +pref("browser.download.hide_plugins_without_extensions", true); + +// Backspace and Shift+Backspace behavior +// 0 goes Back/Forward +// 1 act like PgUp/PgDown +// 2 and other values, nothing +#ifdef UNIX_BUT_NOT_MAC +pref("browser.backspace_action", 2); +#else +pref("browser.backspace_action", 0); +#endif + +// this will automatically enable inline spellchecking (if it is available) for +// editable elements in HTML +// 0 = spellcheck nothing +// 1 = check multi-line controls [default] +// 2 = check multi/single line controls +pref("layout.spellcheckDefault", 1); + +pref("browser.send_pings", false); + +/* initial web feed readers list */ +pref("browser.contentHandlers.types.0.title", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.0.uri", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.0.type", "application/vnd.mozilla.maybe.feed"); +pref("browser.contentHandlers.types.1.title", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.1.uri", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.1.type", "application/vnd.mozilla.maybe.feed"); +pref("browser.contentHandlers.types.2.title", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.2.uri", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.2.type", "application/vnd.mozilla.maybe.feed"); +pref("browser.contentHandlers.types.3.title", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.3.uri", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.3.type", "application/vnd.mozilla.maybe.feed"); +pref("browser.contentHandlers.types.4.title", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.4.uri", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.4.type", "application/vnd.mozilla.maybe.feed"); +pref("browser.contentHandlers.types.5.title", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.5.uri", "chrome://browser-region/locale/region.properties"); +pref("browser.contentHandlers.types.5.type", "application/vnd.mozilla.maybe.feed"); + +pref("browser.feeds.handler", "ask"); +pref("browser.videoFeeds.handler", "ask"); +pref("browser.audioFeeds.handler", "ask"); + +// At startup, if the handler service notices that the version number in the +// region.properties file is newer than the version number in the handler +// service datastore, it will add any new handlers it finds in the prefs (as +// seeded by this file) to its datastore. +pref("gecko.handlerService.defaultHandlersVersion", "chrome://browser-region/locale/region.properties"); + +// The default set of web-based protocol handlers shown in the application +// selection dialog for webcal: ; I've arbitrarily picked 4 default handlers +// per protocol, but if some locale wants more than that (or defaults for some +// protocol not currently listed here), we should go ahead and add those. + +// webcal +pref("gecko.handlerService.schemes.webcal.0.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.webcal.0.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.webcal.1.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.webcal.1.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.webcal.2.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.webcal.2.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.webcal.3.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.webcal.3.uriTemplate", "chrome://browser-region/locale/region.properties"); + +// mailto +pref("gecko.handlerService.schemes.mailto.0.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.mailto.0.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.mailto.1.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.mailto.1.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.mailto.2.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.mailto.2.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.mailto.3.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.mailto.3.uriTemplate", "chrome://browser-region/locale/region.properties"); + +// irc +pref("gecko.handlerService.schemes.irc.0.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.irc.0.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.irc.1.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.irc.1.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.irc.2.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.irc.2.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.irc.3.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.irc.3.uriTemplate", "chrome://browser-region/locale/region.properties"); + +// ircs +pref("gecko.handlerService.schemes.ircs.0.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.ircs.0.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.ircs.1.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.ircs.1.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.ircs.2.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.ircs.2.uriTemplate", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.ircs.3.name", "chrome://browser-region/locale/region.properties"); +pref("gecko.handlerService.schemes.ircs.3.uriTemplate", "chrome://browser-region/locale/region.properties"); + +pref("browser.geolocation.warning.infoURL", "https://www.mozilla.org/%LOCALE%/firefox/geolocation/"); + +pref("browser.EULA.version", 3); +pref("browser.rights.version", 3); +pref("browser.rights.3.shown", false); + +#ifdef DEBUG +// Don't show the about:rights notification in debug builds. +pref("browser.rights.override", true); +#endif + +pref("browser.sessionstore.resume_from_crash", true); +pref("browser.sessionstore.resume_session_once", false); + +// Minimal interval between two save operations in milliseconds (while the user is active). +pref("browser.sessionstore.interval", 15000); // 15 seconds + +// Minimal interval between two save operations in milliseconds (while the user is idle). +pref("browser.sessionstore.interval.idle", 3600000); // 1h + +// Time (ms) before we assume that the user is idle and that we don't need to +// collect/save the session quite as often. +pref("browser.sessionstore.idleDelay", 180000); // 3 minutes + +// on which sites to save text data, POSTDATA and cookies +// 0 = everywhere, 1 = unencrypted sites, 2 = nowhere +pref("browser.sessionstore.privacy_level", 0); +// how many tabs can be reopened (per window) +pref("browser.sessionstore.max_tabs_undo", 10); +// how many windows can be reopened (per session) - on non-OS X platforms this +// pref may be ignored when dealing with pop-up windows to ensure proper startup +pref("browser.sessionstore.max_windows_undo", 3); +// number of crashes that can occur before the about:sessionrestore page is displayed +// (this pref has no effect if more than 6 hours have passed since the last crash) +pref("browser.sessionstore.max_resumed_crashes", 1); +// number of back button session history entries to restore (-1 = all of them) +pref("browser.sessionstore.max_serialize_back", 10); +// number of forward button session history entries to restore (-1 = all of them) +pref("browser.sessionstore.max_serialize_forward", -1); +// restore_on_demand overrides MAX_CONCURRENT_TAB_RESTORES (sessionstore constant) +// and restore_hidden_tabs. When true, tabs will not be restored until they are +// focused (also applies to tabs that aren't visible). When false, the values +// for MAX_CONCURRENT_TAB_RESTORES and restore_hidden_tabs are respected. +// Selected tabs are always restored regardless of this pref. +pref("browser.sessionstore.restore_on_demand", true); +// Whether to automatically restore hidden tabs (i.e., tabs in other tab groups) or not +pref("browser.sessionstore.restore_hidden_tabs", false); +// If restore_on_demand is set, pinned tabs are restored on startup by default. +// When set to true, this pref overrides that behavior, and pinned tabs will only +// be restored when they are focused. +pref("browser.sessionstore.restore_pinned_tabs_on_demand", false); +// The version at which we performed the latest upgrade backup +pref("browser.sessionstore.upgradeBackup.latestBuildID", ""); +// How many upgrade backups should be kept +pref("browser.sessionstore.upgradeBackup.maxUpgradeBackups", 3); +// End-users should not run sessionstore in debug mode +pref("browser.sessionstore.debug", false); +// Causes SessionStore to ignore non-final update messages from +// browser tabs that were not caused by a flush from the parent. +// This is a testing flag and should not be used by end-users. +pref("browser.sessionstore.debug.no_auto_updates", false); +// Forget closed windows/tabs after two weeks +pref("browser.sessionstore.cleanup.forget_closed_after", 1209600000); +// Maximum number of bytes of DOMSessionStorage data we collect per origin. +pref("browser.sessionstore.dom_storage_limit", 2048); +// Amount of failed SessionFile writes until we restart the worker. +pref("browser.sessionstore.max_write_failures", 5); + +// allow META refresh by default +pref("accessibility.blockautorefresh", false); + +// Whether history is enabled or not. +pref("places.history.enabled", true); + +// the (maximum) number of the recent visits to sample +// when calculating frecency +pref("places.frecency.numVisits", 10); + +// buckets (in days) for frecency calculation +pref("places.frecency.firstBucketCutoff", 4); +pref("places.frecency.secondBucketCutoff", 14); +pref("places.frecency.thirdBucketCutoff", 31); +pref("places.frecency.fourthBucketCutoff", 90); + +// weights for buckets for frecency calculations +pref("places.frecency.firstBucketWeight", 100); +pref("places.frecency.secondBucketWeight", 70); +pref("places.frecency.thirdBucketWeight", 50); +pref("places.frecency.fourthBucketWeight", 30); +pref("places.frecency.defaultBucketWeight", 10); + +// bonus (in percent) for visit transition types for frecency calculations +pref("places.frecency.embedVisitBonus", 0); +pref("places.frecency.framedLinkVisitBonus", 0); +pref("places.frecency.linkVisitBonus", 100); +pref("places.frecency.typedVisitBonus", 2000); +// The bookmarks bonus is always added on top of any other bonus, including +// the redirect source and the typed ones. +pref("places.frecency.bookmarkVisitBonus", 75); +// The redirect source bonus overwrites any transition bonus. +// 0 would hide these pages, instead we want them low ranked. Thus we use +// linkVisitBonus - bookmarkVisitBonus, so that a bookmarked source is in par +// with a common link. +pref("places.frecency.redirectSourceVisitBonus", 25); +pref("places.frecency.downloadVisitBonus", 0); +// The perm/temp redirects here relate to redirect targets, not sources. +pref("places.frecency.permRedirectVisitBonus", 50); +pref("places.frecency.tempRedirectVisitBonus", 40); +pref("places.frecency.reloadVisitBonus", 0); +pref("places.frecency.defaultVisitBonus", 0); + +// bonus (in percent) for place types for frecency calculations +pref("places.frecency.unvisitedBookmarkBonus", 140); +pref("places.frecency.unvisitedTypedBonus", 200); + +// Controls behavior of the "Add Exception" dialog launched from SSL error pages +// 0 - don't pre-populate anything +// 1 - pre-populate site URL, but don't fetch certificate +// 2 - pre-populate site URL and pre-fetch certificate +pref("browser.ssl_override_behavior", 2); + +// True if the user should be prompted when a web application supports +// offline apps. +pref("browser.offline-apps.notify", true); + +// if true, use full page zoom instead of text zoom +pref("browser.zoom.full", true); + +// Whether or not to save and restore zoom levels on a per-site basis. +pref("browser.zoom.siteSpecific", true); + +// Whether or not to update background tabs to the current zoom level. +pref("browser.zoom.updateBackgroundTabs", true); + +// The breakpad report server to link to in about:crashes +pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/"); + +// URL for "Learn More" for DataCollection +pref("toolkit.datacollection.infoURL", + "https://www.mozilla.org/legal/privacy/firefox.html"); + +// URL for "Learn More" for Crash Reporter +pref("toolkit.crashreporter.infoURL", + "https://www.mozilla.org/legal/privacy/firefox.html#crash-reporter"); + +// base URL for web-based support pages +pref("app.support.baseURL", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/"); + +// base url for web-based feedback pages +#ifdef MOZ_DEV_EDITION +pref("app.feedback.baseURL", "https://input.mozilla.org/%LOCALE%/feedback/firefoxdev/%VERSION%/"); +#else +pref("app.feedback.baseURL", "https://input.mozilla.org/%LOCALE%/feedback/%APP%/%VERSION%/"); +#endif + +// base URL for web-based marketing pages +pref("app.productInfo.baseURL", "https://www.mozilla.org/firefox/features/"); + +// Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror) +pref("security.alternate_certificate_error_page", "certerror"); + +// Whether to start the private browsing mode at application startup +pref("browser.privatebrowsing.autostart", false); + +// Don't try to alter this pref, it'll be reset the next time you use the +// bookmarking dialog +pref("browser.bookmarks.editDialog.firstEditField", "namePicker"); + +pref("dom.ipc.plugins.flash.disable-protected-mode", false); + +// Feature-disable the protected-mode auto-flip +pref("browser.flash-protected-mode-flip.enable", false); + +// Whether we've already flipped protected mode automatically +pref("browser.flash-protected-mode-flip.done", false); + +pref("dom.ipc.shims.enabledWarnings", false); + +#if defined(XP_WIN) && defined(MOZ_SANDBOX) +// Controls whether and how the Windows NPAPI plugin process is sandboxed. +// To get a different setting for a particular plugin replace "default", with +// the plugin's nice file name, see: nsPluginTag::GetNiceFileName. +// On windows these levels are: +// 0 - no sandbox +// 1 - sandbox with USER_NON_ADMIN access token level +// 2 - a more strict sandbox, which might cause functionality issues. This now +// includes running at low integrity. +// 3 - the strongest settings we seem to be able to use without breaking +// everything, but will probably cause some functionality restrictions +pref("dom.ipc.plugins.sandbox-level.default", 0); +#if defined(_AMD64_) +// The lines in PluginModuleParent.cpp should be changed in line with this. +pref("dom.ipc.plugins.sandbox-level.flash", 2); +#else +pref("dom.ipc.plugins.sandbox-level.flash", 0); +#endif + +#if defined(MOZ_CONTENT_SANDBOX) +// This controls the strength of the Windows content process sandbox for testing +// purposes. This will require a restart. +// On windows these levels are: +// See - security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp +// SetSecurityLevelForContentProcess() for what the different settings mean. +pref("security.sandbox.content.level", 5); + +// This controls the depth of stack trace that is logged when Windows sandbox +// logging is turned on. This is only currently available for the content +// process because the only other sandbox (for GMP) has too strict a policy to +// allow stack tracing. This does not require a restart to take effect. +pref("security.sandbox.windows.log.stackTraceDepth", 0); +#endif + +// This controls the strength of the Windows GPU process sandbox. Changes +// will require restart. +// For information on what the level number means, see +// SetSecurityLevelForGPUProcess() in +// security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp +pref("security.sandbox.gpu.level", 0); +#endif + +#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX) +// This pref is discussed in bug 1083344, the naming is inspired from its +// Windows counterpart, but on Mac it's an integer which means: +// 0 -> "no sandbox" (nightly only) +// 1 -> "preliminary content sandboxing enabled: write access to +// home directory is prevented" +// 2 -> "preliminary content sandboxing enabled with profile protection: +// write access to home directory is prevented, read and write access +// to ~/Library and profile directories are prevented (excluding +// $PROFILE/{extensions,chrome})" +// 3 -> "no global read/write access, read access permitted to +// $PROFILE/{extensions,chrome}" +// This setting is read when the content process is started. On Mac the content +// process is killed when all windows are closed, so a change will take effect +// when the 1st window is opened. +pref("security.sandbox.content.level", 3); +#endif + +#if defined(NIGHTLY_BUILD) && defined(XP_MACOSX) && defined(MOZ_SANDBOX) +pref("security.sandbox.mac.flash.enabled", false); +#endif + +#if defined(XP_LINUX) && defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX) +// This pref is introduced as part of bug 742434, the naming is inspired from +// its Windows/Mac counterpart, but on Linux it's an integer which means: +// 0 -> "no sandbox" +// 1 -> "content sandbox using seccomp-bpf when available" +// 2 -> "seccomp-bpf + write file broker" +// 3 -> "seccomp-bpf + read/write file brokering" +// 4 -> all of the above + network/socket restrictions +// Content sandboxing on Linux is currently in the stage of +// 'just getting it enabled', which includes a very permissive whitelist. We +// enable seccomp-bpf on nightly to see if everything is running, or if we need +// to whitelist more system calls. +// +// So the purpose of this setting is to allow nightly users to disable the +// sandbox while we fix their problems. This way, they won't have to wait for +// another nightly release which disables seccomp-bpf again. +// +// This setting may not be required anymore once we decide to permanently +// enable the content sandbox. +pref("security.sandbox.content.level", 4); +pref("security.sandbox.content.write_path_whitelist", ""); +pref("security.sandbox.content.read_path_whitelist", ""); +pref("security.sandbox.content.syscall_whitelist", ""); +#endif + +#if defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX) +// ID (a UUID when set by gecko) that is used to form the name of a +// sandbox-writable temporary directory to be used by content processes +// when a temporary writable file is required in a level 1 sandbox. +pref("security.sandbox.content.tempDirSuffix", ""); +#endif + +#if defined(MOZ_SANDBOX) +// This pref determines if messages relevant to sandbox violations are +// logged. +#if defined(XP_WIN) || defined(XP_MACOSX) +pref("security.sandbox.logging.enabled", false); +#else +pref("security.sandbox.logging.enabled", true); +#endif +#endif + +// This pref governs whether we attempt to work around problems caused by +// plugins using OS calls to manipulate the cursor while running out-of- +// process. These workarounds all involve intercepting (hooking) certain +// OS calls in the plugin process, then arranging to make certain OS calls +// in the browser process. Eventually plugins will be required to use the +// NPAPI to manipulate the cursor, and these workarounds will be removed. +// See bug 621117. +#ifdef XP_MACOSX +pref("dom.ipc.plugins.nativeCursorSupport", true); +#endif + +#ifdef XP_WIN +pref("browser.taskbar.previews.enable", false); +pref("browser.taskbar.previews.max", 20); +pref("browser.taskbar.previews.cachetime", 5); +pref("browser.taskbar.lists.enabled", true); +pref("browser.taskbar.lists.frequent.enabled", true); +pref("browser.taskbar.lists.recent.enabled", false); +pref("browser.taskbar.lists.maxListItemCount", 7); +pref("browser.taskbar.lists.tasks.enabled", true); +pref("browser.taskbar.lists.refreshInSeconds", 120); +#endif + +// Preferences to be synced by default +pref("services.sync.prefs.sync.accessibility.blockautorefresh", true); +pref("services.sync.prefs.sync.accessibility.browsewithcaret", true); +pref("services.sync.prefs.sync.accessibility.typeaheadfind", true); +pref("services.sync.prefs.sync.accessibility.typeaheadfind.linksonly", true); +pref("services.sync.prefs.sync.addons.ignoreUserEnabledChanges", true); +// The addons prefs related to repository verification are intentionally +// not synced for security reasons. If a system is compromised, a user +// could weaken the pref locally, install an add-on from an untrusted +// source, and this would propagate automatically to other, +// uncompromised Sync-connected devices. +pref("services.sync.prefs.sync.browser.ctrlTab.previews", true); +pref("services.sync.prefs.sync.browser.download.useDownloadDir", true); +pref("services.sync.prefs.sync.browser.formfill.enable", true); +pref("services.sync.prefs.sync.browser.link.open_newwindow", true); +pref("services.sync.prefs.sync.browser.newtabpage.enabled", true); +pref("services.sync.prefs.sync.browser.newtabpage.pinned", true); +pref("services.sync.prefs.sync.browser.offline-apps.notify", true); +pref("services.sync.prefs.sync.browser.safebrowsing.phishing.enabled", true); +pref("services.sync.prefs.sync.browser.safebrowsing.malware.enabled", true); +pref("services.sync.prefs.sync.browser.safebrowsing.downloads.enabled", true); +pref("services.sync.prefs.sync.browser.safebrowsing.passwords.enabled", true); +pref("services.sync.prefs.sync.browser.search.update", true); +pref("services.sync.prefs.sync.browser.sessionstore.restore_on_demand", true); +pref("services.sync.prefs.sync.browser.startup.homepage", true); +pref("services.sync.prefs.sync.browser.startup.page", true); +pref("services.sync.prefs.sync.browser.tabs.loadInBackground", true); +pref("services.sync.prefs.sync.browser.tabs.warnOnClose", true); +pref("services.sync.prefs.sync.browser.tabs.warnOnOpen", true); +pref("services.sync.prefs.sync.browser.urlbar.autocomplete.enabled", true); +pref("services.sync.prefs.sync.browser.urlbar.matchBuckets", true); +pref("services.sync.prefs.sync.browser.urlbar.maxRichResults", true); +pref("services.sync.prefs.sync.browser.urlbar.suggest.bookmark", true); +pref("services.sync.prefs.sync.browser.urlbar.suggest.history", true); +pref("services.sync.prefs.sync.browser.urlbar.suggest.history.onlyTyped", true); +pref("services.sync.prefs.sync.browser.urlbar.suggest.openpage", true); +pref("services.sync.prefs.sync.browser.urlbar.suggest.searches", true); +pref("services.sync.prefs.sync.dom.disable_open_during_load", true); +pref("services.sync.prefs.sync.dom.disable_window_flip", true); +pref("services.sync.prefs.sync.dom.disable_window_move_resize", true); +pref("services.sync.prefs.sync.dom.event.contextmenu.enabled", true); +pref("services.sync.prefs.sync.extensions.personas.current", true); +pref("services.sync.prefs.sync.extensions.update.enabled", true); +pref("services.sync.prefs.sync.intl.accept_languages", true); +pref("services.sync.prefs.sync.layout.spellcheckDefault", true); +pref("services.sync.prefs.sync.lightweightThemes.selectedThemeID", true); +pref("services.sync.prefs.sync.lightweightThemes.usedThemes", true); +pref("services.sync.prefs.sync.network.cookie.cookieBehavior", true); +pref("services.sync.prefs.sync.network.cookie.lifetimePolicy", true); +pref("services.sync.prefs.sync.network.cookie.lifetime.days", true); +pref("services.sync.prefs.sync.network.cookie.thirdparty.sessionOnly", true); +pref("services.sync.prefs.sync.permissions.default.image", true); +pref("services.sync.prefs.sync.pref.advanced.images.disable_button.view_image", true); +pref("services.sync.prefs.sync.pref.advanced.javascript.disable_button.advanced", true); +pref("services.sync.prefs.sync.pref.downloads.disable_button.edit_actions", true); +pref("services.sync.prefs.sync.pref.privacy.disable_button.cookie_exceptions", true); +pref("services.sync.prefs.sync.privacy.clearOnShutdown.cache", true); +pref("services.sync.prefs.sync.privacy.clearOnShutdown.cookies", true); +pref("services.sync.prefs.sync.privacy.clearOnShutdown.downloads", true); +pref("services.sync.prefs.sync.privacy.clearOnShutdown.formdata", true); +pref("services.sync.prefs.sync.privacy.clearOnShutdown.history", true); +pref("services.sync.prefs.sync.privacy.clearOnShutdown.offlineApps", true); +pref("services.sync.prefs.sync.privacy.clearOnShutdown.sessions", true); +pref("services.sync.prefs.sync.privacy.clearOnShutdown.siteSettings", true); +pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true); +pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true); +pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true); +pref("services.sync.prefs.sync.privacy.trackingprotection.pbmode.enabled", true); +pref("services.sync.prefs.sync.privacy.resistFingerprinting", true); +pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true); +pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.microseconds", true); +pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.jitter", true); +pref("services.sync.prefs.sync.security.OCSP.enabled", true); +pref("services.sync.prefs.sync.security.OCSP.require", true); +pref("services.sync.prefs.sync.security.default_personal_cert", true); +pref("services.sync.prefs.sync.security.tls.version.min", true); +pref("services.sync.prefs.sync.security.tls.version.max", true); +pref("services.sync.prefs.sync.services.sync.syncedTabs.showRemoteIcons", true); +pref("services.sync.prefs.sync.signon.rememberSignons", true); +pref("services.sync.prefs.sync.spellchecker.dictionary", true); +pref("services.sync.prefs.sync.xpinstall.whitelist.required", true); + +// A preference that controls whether we should show the icon for a remote tab. +// This pref has no UI but exists because some people may be concerned that +// fetching these icons to show remote tabs may leak information about that +// user's tabs and bookmarks. Note this pref is also synced. +pref("services.sync.syncedTabs.showRemoteIcons", true); + +// Developer edition preferences +#ifdef MOZ_DEV_EDITION +pref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org", + sticky); +#else +pref("lightweightThemes.selectedThemeID", "", sticky); +#endif + +// Whether the character encoding menu is under the main Firefox button. This +// preference is a string so that localizers can alter it. +pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties"); + +// Allow using tab-modal prompts when possible. +pref("prompts.tab_modal.enabled", true); + +// Activates preloading of the new tab url. +pref("browser.newtab.preload", true); + +// Indicates if about:newtab shows content (enabled) or just blank +pref("browser.newtabpage.enabled", true); + +// Activity Stream prefs that control to which page to redirect +pref("browser.newtabpage.activity-stream.prerender", true); +#ifndef RELEASE_OR_BETA +#ifdef MOZILLA_OFFICIAL +pref("browser.newtabpage.activity-stream.debug", false); +#else +pref("browser.newtabpage.activity-stream.debug", true); +#endif +#endif + +pref("browser.library.activity-stream.enabled", true); + +// Enable the DOM fullscreen API. +pref("full-screen-api.enabled", true); + +// Startup Crash Tracking +// number of startup crashes that can occur before starting into safe mode automatically +// (this pref has no effect if more than 6 hours have passed since the last crash) +pref("toolkit.startup.max_resumed_crashes", 3); + +// Whether we use pdfium to view content with the pdf mime type. +// Note: if the pref is set to false while Firefox is open, it won't +// take effect until there are no open pdfium tabs. +pref("pdfium.enabled", false); + +// Completely disable pdf.js as an option to preview pdfs within firefox. +// Note: if this is not disabled it does not necessarily mean pdf.js is the pdf +// handler just that it is an option. +pref("pdfjs.disabled", false); +// Used by pdf.js to know the first time firefox is run with it installed so it +// can become the default pdf viewer. +pref("pdfjs.firstRun", true); +// The values of preferredAction and alwaysAskBeforeHandling before pdf.js +// became the default. +pref("pdfjs.previousHandler.preferredAction", 0); +pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false); + +// The maximum amount of decoded image data we'll willingly keep around (we +// might keep around more than this, but we'll try to get down to this value). +// (This is intentionally on the high side; see bug 746055.) +pref("image.mem.max_decoded_image_kb", 256000); + +// Is the sidebar positioned ahead of the content browser +pref("sidebar.position_start", true); + +// Block insecure active content on https pages +pref("security.mixed_content.block_active_content", true); + +// Show degraded UI for http pages with password fields. +pref("security.insecure_password.ui.enabled", true); + +// Show in-content login form warning UI for insecure login fields +pref("security.insecure_field_warning.contextual.enabled", true); + +// Show degraded UI for http pages; disabled for now +pref("security.insecure_connection_icon.enabled", false); +// Show degraded UI for http pages in private mode only for Nightly: Bug 1434626 +#if defined(NIGHTLY_BUILD) +pref("security.insecure_connection_icon.pbmode.enabled", true); +#else +pref("security.insecure_connection_icon.pbmode.enabled", false); +#endif + +// Show "Not Secure" text for http pages; disabled for now +pref("security.insecure_connection_text.enabled", false); +pref("security.insecure_connection_text.pbmode.enabled", false); + +// 1 = allow MITM for certificate pinning checks. +pref("security.cert_pinning.enforcement_level", 1); + + +// Override the Gecko-default value of false for Firefox. +pref("plain_text.wrap_long_lines", true); + +// If this turns true, Moz*Gesture events are not called stopPropagation() +// before content. +pref("dom.debug.propagate_gesture_events_through_content", false); + +// All the Geolocation preferences are here. +// + +// Geolocation preferences for the RELEASE and "later" Beta channels. +// Some of these prefs are specified even though they are redundant; they are +// here for clarity and end-user experiments. +#ifndef EARLY_BETA_OR_EARLIER +pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%"); + +#ifdef XP_MACOSX +pref("geo.provider.use_corelocation", false); +#endif + +#ifdef XP_WIN +pref("geo.provider.ms-windows-location", false); +#endif + +#ifdef MOZ_WIDGET_GTK +pref("geo.provider.use_gpsd", false); +#endif + +#else + +// Geolocation preferences for Nightly/Aurora/Beta. +pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%"); + +#ifdef XP_MACOSX +pref("geo.provider.use_corelocation", true); +#endif + +// The native Windows location provider is only enabled in Nightly and likely to +// be unstable. Set to false if things are really broken. +#if defined(XP_WIN) && defined(NIGHTLY_BUILD) +pref("geo.provider.ms-windows-location", true); +#endif + +#if defined(MOZ_WIDGET_GTK) && defined(MOZ_GPSD) +pref("geo.provider.use_gpsd", true); +#endif + +#endif + +// Necko IPC security checks only needed for app isolation for cookies/cache/etc: +// currently irrelevant for desktop e10s +pref("network.disable.ipc.security", true); + +// CustomizableUI debug logging. +pref("browser.uiCustomization.debug", false); + +// CustomizableUI state of the browser's user interface +pref("browser.uiCustomization.state", ""); + +// If set to false, FxAccounts and Sync will be unavailable. +// A restart is mandatory after flipping that preference. +pref("identity.fxaccounts.enabled", true); + +// The remote FxA root content URL. Must use HTTPS. +pref("identity.fxaccounts.remote.root", "https://accounts.firefox.com/"); + +// The value of the context query parameter passed in fxa requests. +pref("identity.fxaccounts.contextParam", "fx_desktop_v3"); + +// The remote URL of the FxA Profile Server +pref("identity.fxaccounts.remote.profile.uri", "https://profile.accounts.firefox.com/v1"); + +// The remote URL of the FxA OAuth Server +pref("identity.fxaccounts.remote.oauth.uri", "https://oauth.accounts.firefox.com/v1"); + +// Token server used by the FxA Sync identity. +pref("identity.sync.tokenserver.uri", "https://token.services.mozilla.com/1.0/sync/1.5"); + +// URLs for promo links to mobile browsers. Note that consumers are expected to +// append a value for utm_campaign. +pref("identity.mobilepromo.android", "https://www.mozilla.org/firefox/android/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign="); +pref("identity.mobilepromo.ios", "https://www.mozilla.org/firefox/ios/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign="); + +// Migrate any existing Firefox Account data from the default profile to the +// Developer Edition profile. +#ifdef MOZ_DEV_EDITION +pref("identity.fxaccounts.migrateToDevEdition", true); +#else +pref("identity.fxaccounts.migrateToDevEdition", false); +#endif + +// On GTK, we now default to showing the menubar only when alt is pressed: +#ifdef MOZ_WIDGET_GTK +pref("ui.key.menuAccessKeyFocuses", true); +#endif + +// Encrypted media extensions. +#ifdef XP_LINUX +// On Linux EME is visible but disabled by default. This is so that the +// "Play DRM content" checkbox in the Firefox UI is unchecked by default. +// DRM requires downloading and installing proprietary binaries, which +// users on an open source operating systems didn't opt into. The first +// time a site using EME is encountered, the user will be prompted to +// enable DRM, whereupon the EME plugin binaries will be downloaded if +// permission is granted. +pref("media.eme.enabled", false); +#else +pref("media.eme.enabled", true); +#endif + +#ifdef NIGHTLY_BUILD +pref("media.eme.vp9-in-mp4.enabled", true); +#else +pref("media.eme.vp9-in-mp4.enabled", false); +#endif + +pref("media.eme.hdcp-policy-check.enabled", false); + +// Whether we should run a test-pattern through EME GMPs before assuming they'll +// decode H.264. +pref("media.gmp.trial-create.enabled", true); + +// Note: when media.gmp-*.visible is true, provided we're running on a +// supported platform/OS version, the corresponding CDM appears in the +// plugins list, Firefox will download the GMP/CDM if enabled, and our +// UI to re-enable EME prompts the user to re-enable EME if it's disabled +// and script requests EME. If *.visible is false, we won't show the UI +// to enable the CDM if its disabled; it's as if the keysystem is completely +// unsupported. + +#ifdef MOZ_WIDEVINE_EME +pref("media.gmp-widevinecdm.visible", true); +pref("media.gmp-widevinecdm.enabled", true); +#endif + +// Play with different values of the decay time and get telemetry, +// 0 means to randomize (and persist) the experiment value in users' profiles, +// -1 means no experiment is run and we use the preferred value for frecency (6h) +pref("browser.cache.frecency_experiment", 0); + +pref("browser.translation.detectLanguage", false); +pref("browser.translation.neverForLanguages", ""); +// Show the translation UI bits, like the info bar, notification icon and preferences. +pref("browser.translation.ui.show", false); +// Allows to define the translation engine. Bing is default, Yandex may optionally switched on. +pref("browser.translation.engine", "bing"); + +// Telemetry settings. +// Determines if Telemetry pings can be archived locally. +pref("toolkit.telemetry.archive.enabled", true); +// Enables sending the shutdown ping when Firefox shuts down. +pref("toolkit.telemetry.shutdownPingSender.enabled", true); +// Enables sending the shutdown ping using the pingsender from the first session. +pref("toolkit.telemetry.shutdownPingSender.enabledFirstSession", false); +// Enables sending a duplicate of the first shutdown ping from the first session. +pref("toolkit.telemetry.firstShutdownPing.enabled", true); +// Enables sending the 'new-profile' ping on new profiles. +pref("toolkit.telemetry.newProfilePing.enabled", true); +// Enables sending 'update' pings on Firefox updates. +pref("toolkit.telemetry.updatePing.enabled", true); +// Enables sending 'bhr' pings when the browser hangs. +pref("toolkit.telemetry.bhrPing.enabled", true); +// Enables using Hybrid Content Telemetry from Mozilla privileged pages. +pref("toolkit.telemetry.hybridContent.enabled", true); + +// Telemetry experiments settings. +pref("experiments.enabled", true); +pref("experiments.manifest.fetchIntervalSeconds", 86400); +pref("experiments.manifest.uri", "https://telemetry-experiment.cdn.mozilla.net/manifest/v1/firefox/%VERSION%/%CHANNEL%"); +// Whether experiments are supported by the current application profile. +pref("experiments.supported", true); + +// Ping Centre Telemetry settings. +pref("browser.ping-centre.telemetry", true); +pref("browser.ping-centre.log", false); +pref("browser.ping-centre.staging.endpoint", "https://onyx_tiles.stage.mozaws.net/v3/links/ping-centre"); +pref("browser.ping-centre.production.endpoint", "https://tiles.services.mozilla.com/v3/links/ping-centre"); + +// Enable GMP support in the addon manager. +pref("media.gmp-provider.enabled", true); + +pref("privacy.trackingprotection.ui.enabled", true); +pref("privacy.trackingprotection.introCount", 0); +pref("privacy.trackingprotection.introURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tracking-protection/start/"); + +// Enable Contextual Identity Containers +#ifdef NIGHTLY_BUILD +pref("privacy.userContext.enabled", true); +pref("privacy.userContext.ui.enabled", true); +pref("privacy.usercontext.about_newtab_segregation.enabled", true); + +// 0 disables long press, 1 when clicked, the menu is shown, 2 the menu is shown after X milliseconds. +pref("privacy.userContext.longPressBehavior", 2); +#else +pref("privacy.userContext.enabled", false); +pref("privacy.userContext.ui.enabled", false); +pref("privacy.usercontext.about_newtab_segregation.enabled", false); + +// 0 disables long press, 1 when clicked, the menu is shown, 2 the menu is shown after X milliseconds. +pref("privacy.userContext.longPressBehavior", 0); +#endif +pref("privacy.userContext.extension", ""); + +// Start the browser in e10s mode +pref("browser.tabs.remote.autostart", true); +pref("browser.tabs.remote.desktopbehavior", true); + +// For speculatively warming up tabs to improve perceived +// performance while using the async tab switcher. +// Disabled until bug 1397426 is fixed. +pref("browser.tabs.remote.warmup.enabled", false); +pref("browser.tabs.remote.warmup.maxTabs", 3); +pref("browser.tabs.remote.warmup.unloadDelayMs", 2000); + +// For the about:tabcrashed page +pref("browser.tabs.crashReporting.sendReport", true); +pref("browser.tabs.crashReporting.includeURL", false); +pref("browser.tabs.crashReporting.requestEmail", false); +pref("browser.tabs.crashReporting.emailMe", false); +pref("browser.tabs.crashReporting.email", ""); + +// But don't allow non-MPC extensions by default on Nightly +#if defined(NIGHTLY_BUILD) +pref("extensions.allow-non-mpc-extensions", false); +#endif + +pref("extensions.legacy.enabled", false); + +// How often to check for CPOW timeouts. CPOWs are only timed out by +// the hang monitor. +pref("dom.ipc.cpow.timeout", 500); + +// Causes access on unsafe CPOWs from browser code to throw by default. +pref("dom.ipc.cpows.forbid-unsafe-from-browser", true); + +// Don't allow add-ons marked as multiprocessCompatible to use CPOWs. +pref("dom.ipc.cpows.forbid-cpows-in-compat-addons", true); + +// ...except for these add-ons: +pref("dom.ipc.cpows.allow-cpows-in-compat-addons", "{b9db16a4-6edc-47ec-a1f4-b86292ed211d},firegestures@xuldev.org,{DDC359D1-844A-42a7-9AA1-88A850A938A8},privateTab@infocatcher,mousegesturessuite@lemon_juice.addons.mozilla.org,treestyletab@piro.sakura.ne.jp,cliqz@cliqz.com,{AE93811A-5C9A-4d34-8462-F7B864FC4696},contextsearch2@lwz.addons.mozilla.org,{EF522540-89F5-46b9-B6FE-1829E2B572C6},{677a8f98-fd64-40b0-a883-b8c95d0cbf17},images@wink.su,fx-devtools,url_advisor@kaspersky.com,{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d},{dc572301-7619-498c-a57d-39143191b318},dta@downthemall.net,{86095750-AD15-46d8-BF32-C0789F7E6A32},screenwise-prod@google.com,{91aa5abe-9de4-4347-b7b5-322c38dd9271},secureLogin@blueimp.net,ich@maltegoetz.de,come.back.block.image.from@cat-in-136.blogspot.com,{7b1bf0b6-a1b9-42b0-b75d-252036438bdc},s3crypto@data,{1e0fd655-5aea-4b4c-a583-f76ef1e3af9c},akahuku.fx.sp@toshiakisp.github.io,{aff87fa2-a58e-4edd-b852-0a20203c1e17},{1018e4d6-728f-4b20-ad56-37578a4de76b},rehostimage@engy.us,lazarus@interclue.com,{b2e69492-2358-071a-7056-24ad0c3defb1},flashstopper@byo.co.il,{e4a8a97b-f2ed-450b-b12d-ee082ba24781},jid1-f3mYMbCpz2AZYl@jetpack,{8c550e28-88c9-4764-bb52-aa489cf2efcd},{37fa1426-b82d-11db-8314-0800200c9a66},{ac2cfa60-bc96-11e0-962b-0800200c9a66},igetter@presenta.net,killspinners@byo.co.il,abhere2@moztw.org,{fc6339b8-9581-4fc7-b824-dffcb091fcb7},wampi@wink.su,backtrack@byalexv.co.uk,Gladiator_X@mail.ru,{73a6fe31-595d-460b-a920-fcc0f8843232},{46551EC9-40F0-4e47-8E18-8E5CF550CFB8},acewebextension_unlisted@acestream.org,@screen_maker,yasearch@yandex.ru,sp@avast.com,s3google@translator,igetterextension@presenta.net,{C1A2A613-35F1-4FCF-B27F-2840527B6556},screenwise-testing@google.com,helper-sig@savefrom.net,ImageSaver@Merci.chao,proxtube@abz.agency,wrc@avast.com,{9AA46F4F-4DC7-4c06-97AF-5035170634FE},jid1-CikLKKPVkw6ipw@jetpack,artur.dubovoy@gmail.com,nlgfeb@nlgfeb.ext,{A065A84F-95B6-433A-A0C8-4C040B77CE8A},fdm_ffext@freedownloadmanager.org"); + +// Enable e10s hang monitoring (slow script checking and plugin hang +// detection). +pref("dom.ipc.processHangMonitor", true); + +#ifdef DEBUG +// Don't report hangs in DEBUG builds. They're too slow and often a +// debugger is attached. +pref("dom.ipc.reportProcessHangs", false); +#else +pref("dom.ipc.reportProcessHangs", true); +#endif + +// Don't limit how many nodes we care about on desktop: +pref("reader.parse-node-limit", 0); + +// On desktop, we want the URLs to be included here for ease of debugging, +// and because (normally) these errors are not persisted anywhere. +pref("reader.errors.includeURLs", true); + +pref("dom.serviceWorkers.enabled", false); + +// Enable Push API. +pref("dom.push.enabled", false); + +// These are the thumbnail width/height set in about:newtab. +// If you change this, ENSURE IT IS THE SAME SIZE SET +// by about:newtab. These values are in CSS pixels. +pref("toolkit.pageThumbs.minWidth", 280); +pref("toolkit.pageThumbs.minHeight", 190); + +// Enable speech synthesis +pref("media.webspeech.synth.enabled", true); + +pref("browser.esedbreader.loglevel", "Error"); + +pref("browser.laterrun.enabled", false); + +pref("dom.ipc.processPrelaunch.enabled", true); + +pref("browser.migrate.automigrate.enabled", false); +// 4 here means the suggestion notification will be automatically +// hidden the 4th day, so it will actually be shown on 3 different days. +pref("browser.migrate.automigrate.daysToOfferUndo", 4); +pref("browser.migrate.automigrate.ui.enabled", true); +pref("browser.migrate.automigrate.inpage.ui.enabled", false); + +// See comments in bug 1340115 on how we got to these numbers. +pref("browser.migrate.chrome.history.limit", 2000); +pref("browser.migrate.chrome.history.maxAgeInDays", 180); + +// Enable browser frames for use on desktop. Only exposed to chrome callers. +pref("dom.mozBrowserFramesEnabled", true); + +pref("extensions.pocket.enabled", true); + +pref("signon.schemeUpgrades", true); + +// Enable the "Simplify Page" feature in Print Preview. This feature +// is disabled by default in toolkit. +pref("print.use_simplify_page", true); + +// Space separated list of URLS that are allowed to send objects (instead of +// only strings) through webchannels. This list is duplicated in mobile/android/app/mobile.js +pref("webchannel.allowObject.urlWhitelist", "https://content.cdn.mozilla.net https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org"); + +// Whether or not the browser should scan for unsubmitted +// crash reports, and then show a notification for submitting +// those reports. +#ifdef NIGHTLY_BUILD +pref("browser.crashReports.unsubmittedCheck.enabled", true); +#else +pref("browser.crashReports.unsubmittedCheck.enabled", false); +#endif + +// chancesUntilSuppress is how many times we'll show the unsubmitted +// crash report notification across different days and shutdown +// without a user choice before we suppress the notification for +// some number of days. +pref("browser.crashReports.unsubmittedCheck.chancesUntilSuppress", 4); +pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false); + +// Preferences for the form autofill system extension +// The truthy values of "extensions.formautofill.available" are "on" and "detect", +// any other value means autofill isn't available. +// "detect" means it's enabled if conditions defined in the extension are met. +#ifdef NIGHTLY_BUILD +pref("extensions.formautofill.available", "on"); +pref("extensions.formautofill.creditCards.available", true); +#else +pref("extensions.formautofill.available", "detect"); +pref("extensions.formautofill.creditCards.available", false); +#endif +pref("extensions.formautofill.addresses.enabled", true); +pref("extensions.formautofill.creditCards.enabled", true); +// Pref for shield/heartbeat to recognize users who have used Credit Card +// Autofill. The valid values can be: +// 0: none +// 1: submitted a manually-filled credit card form (but didn't see the doorhanger +// because of a duplicate profile in the storage) +// 2: saw the doorhanger +// 3: submitted an autofill'ed credit card form +pref("extensions.formautofill.creditCards.used", 0); +pref("extensions.formautofill.firstTimeUse", true); +pref("extensions.formautofill.heuristics.enabled", true); +pref("extensions.formautofill.section.enabled", true); +pref("extensions.formautofill.loglevel", "Warn"); + +#ifdef NIGHTLY_BUILD +// Comma separated list of countries Form Autofill supports. +// This affects feature availability and the address edit form country picker. +pref("extensions.formautofill.supportedCountries", "US,CA,DE"); +pref("extensions.formautofill.supportRTL", true); +#else +pref("extensions.formautofill.supportedCountries", "US"); +pref("extensions.formautofill.supportRTL", false); +#endif + +// Whether or not to restore a session with lazy-browser tabs. +pref("browser.sessionstore.restore_tabs_lazily", true); + +pref("browser.suppress_first_window_animation", true); + +// Preferences for Photon onboarding system extension +pref("browser.onboarding.enabled", true); +// Mark this as an upgraded profile so we don't offer the initial new user onboarding tour. +pref("browser.onboarding.tourset-version", 2); +pref("browser.onboarding.state", "default"); +// On the Activity-Stream page, the snippet's position overlaps with our notification. +// So use `browser.onboarding.notification.finished` to let the AS page know +// if our notification is finished and safe to show their snippet. +pref("browser.onboarding.notification.finished", false); +pref("browser.onboarding.notification.mute-duration-on-first-session-ms", 300000); // 5 mins +pref("browser.onboarding.notification.max-life-time-per-tour-ms", 432000000); // 5 days +pref("browser.onboarding.notification.max-life-time-all-tours-ms", 1209600000); // 14 days +pref("browser.onboarding.notification.max-prompt-count-per-tour", 8); +pref("browser.onboarding.newtour", "performance,private,screenshots,addons,customize,default"); +pref("browser.onboarding.updatetour", "performance,library,screenshots,singlesearch,customize,sync"); + +// Preference that allows individual users to disable Screenshots. +pref("extensions.screenshots.disabled", false); +// Preference that allows individual users to leave Screenshots enabled, but +// disable uploading to the server. +pref("extensions.screenshots.upload-disabled", false); + +// Preferences for BrowserErrorReporter.jsm +// Only collect errors on Nightly, and specifically not local builds +#if defined(NIGHTLY_BUILD) && MOZ_UPDATE_CHANNEL != default +pref("browser.chrome.errorReporter.enabled", true); +#else +pref("browser.chrome.errorReporter.enabled", false); +#endif +pref("browser.chrome.errorReporter.sampleRate", "0.001"); +pref("browser.chrome.errorReporter.publicKey", "c709cb7a2c0b4f0882fcc84a5af161ec"); +pref("browser.chrome.errorReporter.projectId", "339"); +pref("browser.chrome.errorReporter.submitUrl", "https://sentry.prod.mozaws.net/api/339/store/"); +pref("browser.chrome.errorReporter.logLevel", "Error"); + +// URL for Learn More link for browser error logging in preferences +pref("browser.chrome.errorReporter.infoURL", + "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/nightly-error-collection"); + +// Normandy client preferences +pref("app.normandy.api_url", "https://normandy.cdn.mozilla.net/api/v1"); +pref("app.normandy.dev_mode", false); +pref("app.normandy.enabled", true); +pref("app.normandy.first_run", true); +pref("app.normandy.logging.level", 50); // Warn +pref("app.normandy.run_interval_seconds", 86400); // 24 hours +pref("app.normandy.shieldLearnMoreUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/shield"); +#ifdef MOZ_DATA_REPORTING +pref("app.shield.optoutstudies.enabled", true); +#else +pref("app.shield.optoutstudies.enabled", false); +#endif diff -pruN 1:60.2.1-1/browser/base/content/test/general/browser_bug477014.js 1:60.2.1+build1-0ubuntu1/browser/base/content/test/general/browser_bug477014.js --- 1:60.2.1-1/browser/base/content/test/general/browser_bug477014.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/base/content/test/general/browser_bug477014.js 2018-10-02 14:08:34.000000000 +0000 @@ -0,0 +1,25 @@ +/* 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/. */ + +// That's a gecko! +const iconURLSpec = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="; +var testPage = "data:text/plain,test bug 477014"; + +add_task(async function() { + let tabToDetach = BrowserTestUtils.addTab(gBrowser, testPage); + await BrowserTestUtils.browserStopped(tabToDetach.linkedBrowser); + + gBrowser.setIcon(tabToDetach, iconURLSpec, + Services.scriptSecurityManager.getSystemPrincipal()); + tabToDetach.setAttribute("busy", "true"); + + // detach and set the listener on the new window + let newWindow = gBrowser.replaceTabWithWindow(tabToDetach); + await promiseWaitForEvent(tabToDetach.linkedBrowser, "SwapDocShells"); + + is(newWindow.gBrowser.selectedTab.hasAttribute("busy"), true, "Busy attribute should be correct"); + is(newWindow.gBrowser.getIcon(), iconURLSpec, "Icon should be correct"); + + newWindow.close(); +}); diff -pruN 1:60.2.1-1/browser/base/content/test/general/browser_contentAreaClick.js 1:60.2.1+build1-0ubuntu1/browser/base/content/test/general/browser_contentAreaClick.js --- 1:60.2.1-1/browser/base/content/test/general/browser_contentAreaClick.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/base/content/test/general/browser_contentAreaClick.js 2018-10-02 14:08:34.000000000 +0000 @@ -0,0 +1,306 @@ +/* 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/. */ + +/** + * Test for bug 549340. + * Test for browser.js::contentAreaClick() util. + * + * The test opens a new browser window, then replaces browser.js methods invoked + * by contentAreaClick with a mock function that tracks which methods have been + * called. + * Each sub-test synthesizes a mouse click event on links injected in content, + * the event is collected by a click handler that ensures that contentAreaClick + * correctly prevent default events, and follows the correct code path. + */ + +var gTests = [ + + { + desc: "Simple left click", + setup() {}, + clean() {}, + event: {}, + targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], + expectedInvokedMethods: [], + preventDefault: false, + }, + + { + desc: "Ctrl/Cmd left click", + setup() {}, + clean() {}, + event: { ctrlKey: true, + metaKey: true }, + targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], + expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ], + preventDefault: true, + }, + + // The next test was once handling feedService.forcePreview(). Now it should + // just be like Alt click. + { + desc: "Shift+Alt left click", + setup() { + Services.prefs.setBoolPref("browser.altClickSave", true); + }, + clean() { + Services.prefs.clearUserPref("browser.altClickSave"); + }, + event: { shiftKey: true, + altKey: true }, + targets: [ "commonlink", "maplink" ], + expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ], + preventDefault: true, + }, + + { + desc: "Shift+Alt left click on XLinks", + setup() { + Services.prefs.setBoolPref("browser.altClickSave", true); + }, + clean() { + Services.prefs.clearUserPref("browser.altClickSave"); + }, + event: { shiftKey: true, + altKey: true }, + targets: [ "mathxlink", "svgxlink"], + expectedInvokedMethods: [ "saveURL" ], + preventDefault: true, + }, + + { + desc: "Shift click", + setup() {}, + clean() {}, + event: { shiftKey: true }, + targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], + expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ], + preventDefault: true, + }, + + { + desc: "Alt click", + setup() { + Services.prefs.setBoolPref("browser.altClickSave", true); + }, + clean() { + Services.prefs.clearUserPref("browser.altClickSave"); + }, + event: { altKey: true }, + targets: [ "commonlink", "maplink" ], + expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ], + preventDefault: true, + }, + + { + desc: "Alt click on XLinks", + setup() { + Services.prefs.setBoolPref("browser.altClickSave", true); + }, + clean() { + Services.prefs.clearUserPref("browser.altClickSave"); + }, + event: { altKey: true }, + targets: [ "mathxlink", "svgxlink" ], + expectedInvokedMethods: [ "saveURL" ], + preventDefault: true, + }, + + { + desc: "Panel click", + setup() {}, + clean() {}, + event: {}, + targets: [ "panellink" ], + expectedInvokedMethods: [ "urlSecurityCheck", "loadURI" ], + preventDefault: true, + }, + + { + desc: "Simple middle click opentab", + setup() {}, + clean() {}, + event: { button: 1 }, + targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], + expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ], + preventDefault: true, + }, + + { + desc: "Simple middle click openwin", + setup() { + Services.prefs.setBoolPref("browser.tabs.opentabfor.middleclick", false); + }, + clean() { + Services.prefs.clearUserPref("browser.tabs.opentabfor.middleclick"); + }, + event: { button: 1 }, + targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], + expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ], + preventDefault: true, + }, + + { + desc: "Middle mouse paste", + setup() { + Services.prefs.setBoolPref("middlemouse.contentLoadURL", true); + Services.prefs.setBoolPref("general.autoScroll", false); + }, + clean() { + Services.prefs.clearUserPref("middlemouse.contentLoadURL"); + Services.prefs.clearUserPref("general.autoScroll"); + }, + event: { button: 1 }, + targets: [ "emptylink" ], + expectedInvokedMethods: [ "middleMousePaste" ], + preventDefault: true, + }, + +]; + +// Array of method names that will be replaced in the new window. +var gReplacedMethods = [ + "middleMousePaste", + "urlSecurityCheck", + "loadURI", + "gatherTextUnder", + "saveURL", + "openLinkIn", + "getShortcutOrURIAndPostData", +]; + +// Reference to the new window. +var gTestWin = null; + +// List of methods invoked by a specific call to contentAreaClick. +var gInvokedMethods = []; + +// The test currently running. +var gCurrentTest = null; + +function test() { + waitForExplicitFinish(); + + gTestWin = openDialog(location, "", "chrome,all,dialog=no", "about:blank"); + whenDelayedStartupFinished(gTestWin, function() { + info("Browser window opened"); + waitForFocus(function() { + info("Browser window focused"); + waitForFocus(function() { + info("Setting up browser..."); + setupTestBrowserWindow(); + info("Running tests..."); + executeSoon(runNextTest); + }, gTestWin.content, true); + }, gTestWin); + }); +} + +// Click handler used to steal click events. +var gClickHandler = { + handleEvent(event) { + let linkId = event.target.id || event.target.localName; + is(event.type, "click", + gCurrentTest.desc + ":Handler received a click event on " + linkId); + + let isPanelClick = linkId == "panellink"; + gTestWin.contentAreaClick(event, isPanelClick); + let prevent = event.defaultPrevented; + is(prevent, gCurrentTest.preventDefault, + gCurrentTest.desc + ": event.defaultPrevented is correct (" + prevent + ")"); + + // Check that all required methods have been called. + gCurrentTest.expectedInvokedMethods.forEach(function(aExpectedMethodName) { + isnot(gInvokedMethods.indexOf(aExpectedMethodName), -1, + gCurrentTest.desc + ":" + aExpectedMethodName + " was invoked"); + }); + + if (gInvokedMethods.length != gCurrentTest.expectedInvokedMethods.length) { + ok(false, "Wrong number of invoked methods"); + gInvokedMethods.forEach(method => info(method + " was invoked")); + } + + event.preventDefault(); + event.stopPropagation(); + + executeSoon(runNextTest); + } +}; + +// Wraps around the methods' replacement mock function. +function wrapperMethod(aInvokedMethods, aMethodName) { + return function() { + aInvokedMethods.push(aMethodName); + // At least getShortcutOrURIAndPostData requires to return url + return (aMethodName == "getShortcutOrURIAndPostData") ? arguments.url : arguments[0]; + }; +} + +function setupTestBrowserWindow() { + // Steal click events and don't propagate them. + gTestWin.addEventListener("click", gClickHandler, true); + + // Replace methods. + gReplacedMethods.forEach(function(aMethodName) { + gTestWin["old_" + aMethodName] = gTestWin[aMethodName]; + gTestWin[aMethodName] = wrapperMethod(gInvokedMethods, aMethodName); + }); + + // Inject links in content. + let doc = gTestWin.content.document; + let mainDiv = doc.createElement("div"); + mainDiv.innerHTML = + '

Common link

' + + '

Panel link

' + + '

Empty link

' + + '

MathML XLink

' + + '

SVG XLink

' + + '

'; + doc.body.appendChild(mainDiv); +} + +function runNextTest() { + if (!gCurrentTest) { + gCurrentTest = gTests.shift(); + gCurrentTest.setup(); + } + + if (gCurrentTest.targets.length == 0) { + info(gCurrentTest.desc + ": cleaning up..."); + gCurrentTest.clean(); + + if (gTests.length > 0) { + gCurrentTest = gTests.shift(); + gCurrentTest.setup(); + } else { + finishTest(); + return; + } + } + + // Move to next target. + gInvokedMethods.length = 0; + let target = gCurrentTest.targets.shift(); + + info(gCurrentTest.desc + ": testing " + target); + + // Fire click event. + let targetElt = gTestWin.content.document.getElementById(target); + ok(targetElt, gCurrentTest.desc + ": target is valid (" + targetElt.id + ")"); + EventUtils.synthesizeMouseAtCenter(targetElt, gCurrentTest.event, gTestWin.content); +} + +function finishTest() { + info("Restoring browser..."); + gTestWin.removeEventListener("click", gClickHandler, true); + + // Restore original methods. + gReplacedMethods.forEach(function(aMethodName) { + gTestWin[aMethodName] = gTestWin["old_" + aMethodName]; + delete gTestWin["old_" + aMethodName]; + }); + + gTestWin.close(); + finish(); +} diff -pruN 1:60.2.1-1/browser/base/content/test/general/browser_tabkeynavigation.js 1:60.2.1+build1-0ubuntu1/browser/base/content/test/general/browser_tabkeynavigation.js --- 1:60.2.1-1/browser/base/content/test/general/browser_tabkeynavigation.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/base/content/test/general/browser_tabkeynavigation.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,156 @@ +/* + * This test checks that keyboard navigation for tabs isn't blocked by content + */ +add_task(async function test() { + + let testPage1 = "data:text/html,"; + let testPage2 = "data:text/html,"; + let testPage3 = "data:text/html,"; + + let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, testPage1); + let browser1 = gBrowser.getBrowserForTab(tab1); + let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, testPage2); + let tab3 = await BrowserTestUtils.openNewForegroundTab(gBrowser, testPage3); + + // Kill the animation for simpler test. + Services.prefs.setBoolPref("toolkit.cosmeticAnimations.enabled", false); + + gBrowser.selectedTab = tab1; + browser1.focus(); + + is(gBrowser.selectedTab, tab1, + "Tab1 should be activated"); + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+Tab on Tab1"); + + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }); + is(gBrowser.selectedTab, tab3, + "Tab3 should be activated by pressing Ctrl+Tab on Tab2"); + + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+Shift+Tab on Tab3"); + + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }); + is(gBrowser.selectedTab, tab1, + "Tab1 should be activated by pressing Ctrl+Shift+Tab on Tab2"); + + gBrowser.selectedTab = tab1; + browser1.focus(); + + is(gBrowser.selectedTab, tab1, + "Tab1 should be activated"); + EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+PageDown on Tab1"); + + EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }); + is(gBrowser.selectedTab, tab3, + "Tab3 should be activated by pressing Ctrl+PageDown on Tab2"); + + EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+PageUp on Tab3"); + + EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }); + is(gBrowser.selectedTab, tab1, + "Tab1 should be activated by pressing Ctrl+PageUp on Tab2"); + + if (gBrowser.tabbox._handleMetaAltArrows) { + gBrowser.selectedTab = tab1; + browser1.focus(); + + let ltr = window.getComputedStyle(gBrowser.tabbox).direction == "ltr"; + let advanceKey = ltr ? "VK_RIGHT" : "VK_LEFT"; + let reverseKey = ltr ? "VK_LEFT" : "VK_RIGHT"; + + is(gBrowser.selectedTab, tab1, + "Tab1 should be activated"); + EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1"); + + EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }); + is(gBrowser.selectedTab, tab3, + "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2"); + + EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3"); + + EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }); + is(gBrowser.selectedTab, tab1, + "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2"); + } + + gBrowser.selectedTab = tab2; + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated"); + is(gBrowser.tabContainer.selectedIndex, 2, + "Tab2 index should be 2"); + + EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true, shiftKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated after Ctrl+Shift+PageDown"); + is(gBrowser.tabContainer.selectedIndex, 3, + "Tab2 index should be 1 after Ctrl+Shift+PageDown"); + + EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true, shiftKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated after Ctrl+Shift+PageUp"); + is(gBrowser.tabContainer.selectedIndex, 2, + "Tab2 index should be 2 after Ctrl+Shift+PageUp"); + + if (navigator.platform.indexOf("Mac") == 0) { + gBrowser.selectedTab = tab1; + browser1.focus(); + + // XXX Currently, Command + "{" and "}" don't work if keydown event is + // consumed because following keypress event isn't fired. + + let ltr = window.getComputedStyle(gBrowser.tabbox).direction == "ltr"; + let advanceKey = ltr ? "}" : "{"; + let reverseKey = ltr ? "{" : "}"; + + is(gBrowser.selectedTab, tab1, + "Tab1 should be activated"); + + EventUtils.synthesizeKey(advanceKey, { metaKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1"); + + EventUtils.synthesizeKey(advanceKey, { metaKey: true }); + is(gBrowser.selectedTab, tab3, + "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2"); + + EventUtils.synthesizeKey(reverseKey, { metaKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3"); + + EventUtils.synthesizeKey(reverseKey, { metaKey: true }); + is(gBrowser.selectedTab, tab1, + "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2"); + } else { + gBrowser.selectedTab = tab2; + EventUtils.synthesizeKey("VK_F4", { type: "keydown", ctrlKey: true }); + + isnot(gBrowser.selectedTab, tab2, + "Tab2 should be closed by pressing Ctrl+F4 on Tab2"); + is(gBrowser.tabs.length, 3, + "The count of tabs should be 3 since tab2 should be closed"); + + // NOTE: keypress event shouldn't be fired since the keydown event should + // be consumed by tab2. + EventUtils.synthesizeKey("VK_F4", { type: "keyup", ctrlKey: true }); + is(gBrowser.tabs.length, 3, + "The count of tabs should be 3 since renaming key events shouldn't close other tabs"); + } + + gBrowser.selectedTab = tab3; + while (gBrowser.tabs.length > 1) { + gBrowser.removeCurrentTab(); + } + + Services.prefs.clearUserPref("toolkit.cosmeticAnimations.enabled"); +}); diff -pruN 1:60.2.1-1/browser/base/content/test/urlbar/browser_action_searchengine_alias.js 1:60.2.1+build1-0ubuntu1/browser/base/content/test/urlbar/browser_action_searchengine_alias.js --- 1:60.2.1-1/browser/base/content/test/urlbar/browser_action_searchengine_alias.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/base/content/test/urlbar/browser_action_searchengine_alias.js 2018-10-02 14:08:34.000000000 +0000 @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +add_task(async function() { + let iconURI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC"; + Services.search.addEngineWithDetails("MozSearch", iconURI, "moz", "", "GET", + "http://example.com/?q={searchTerms}"); + let engine = Services.search.getEngineByName("MozSearch"); + let originalEngine = Services.search.currentEngine; + Services.search.currentEngine = engine; + + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla"); + + registerCleanupFunction(async function() { + Services.search.currentEngine = originalEngine; + Services.search.removeEngine(engine); + try { + await BrowserTestUtils.removeTab(tab); + } catch (ex) { /* tab may have already been closed in case of failure */ } + await PlacesUtils.history.clear(); + }); + + await promiseAutocompleteResultPopup("moz open a search"); + let result = await waitForAutocompleteResultAt(0); + ok(result.hasAttribute("image"), "Result should have an image attribute"); + ok(result.getAttribute("image") === engine.iconURI.spec, + "Image attribute should have the search engine's icon"); + + let tabPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + EventUtils.synthesizeKey("KEY_Enter"); + await tabPromise; + + is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search"); + + gURLBar.popup.hidePopup(); + await promisePopupHidden(gURLBar.popup); +}); diff -pruN 1:60.2.1-1/browser/components/enterprisepolicies/tests/browser/browser_policy_block_set_desktop_background.js 1:60.2.1+build1-0ubuntu1/browser/components/enterprisepolicies/tests/browser/browser_policy_block_set_desktop_background.js --- 1:60.2.1-1/browser/components/enterprisepolicies/tests/browser/browser_policy_block_set_desktop_background.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/components/enterprisepolicies/tests/browser/browser_policy_block_set_desktop_background.js 2018-10-02 14:08:34.000000000 +0000 @@ -0,0 +1,38 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +add_task(async function setup() { + await setupPolicyEngineWithJson({ + "policies": { + "DisableSetDesktopBackground": true + } + }); +}); + +add_task(async function test_check_set_desktop_background() { + const imageUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII="; + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, imageUrl, true); + + // Right click on the image and wait for the context menu to open + let contextMenu = document.getElementById("contentAreaContextMenu"); + let promiseContextMenuOpen = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); + await BrowserTestUtils.synthesizeMouse("img", 0, 0, + { + type: "contextmenu", + button: 2, + centered: true + }, + gBrowser.selectedBrowser); + await promiseContextMenuOpen; + info("Context Menu Shown"); + + let buttonElement = document.getElementById("context-setDesktopBackground"); + is(buttonElement.hidden, true, + "The \"Set Desktop Background\" context menu element should be hidden"); + + let promiseContextMenuHidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden"); + contextMenu.hidePopup(); + await promiseContextMenuHidden; + await BrowserTestUtils.removeTab(tab); +}); diff -pruN 1:60.2.1-1/browser/components/enterprisepolicies/tests/browser/browser_policy_bookmarks.js 1:60.2.1+build1-0ubuntu1/browser/components/enterprisepolicies/tests/browser/browser_policy_bookmarks.js --- 1:60.2.1-1/browser/components/enterprisepolicies/tests/browser/browser_policy_bookmarks.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/components/enterprisepolicies/tests/browser/browser_policy_bookmarks.js 2018-10-02 14:08:34.000000000 +0000 @@ -0,0 +1,272 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); +ChromeUtils.import("resource://gre/modules/Services.jsm"); +ChromeUtils.import("resource://gre/modules/PlacesUtils.jsm"); + +const FAVICON_DATA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII="; + +const { BookmarksPolicies } = ChromeUtils.import("resource:///modules/policies/BookmarksPolicies.jsm", {}); + +let CURRENT_POLICY; + +const BASE_POLICY = { + "policies": { + "DisplayBookmarksToolbar": true, + "Bookmarks": [ + { + "Title": "Bookmark 1", + "URL": "https://bookmark1.example.com/", + "Favicon": FAVICON_DATA + }, + { + "Title": "Bookmark 2", + "URL": "https://bookmark2.example.com/", + "Folder": "Folder 1" + }, + { + "Title": "Bookmark 3", + "URL": "https://bookmark3.example.com/", + "Placement": "menu" + }, + { + "Title": "Bookmark 4", + "URL": "https://bookmark4.example.com/", + "Folder": "Folder 1" + }, + { + "Title": "Bookmark 5", + "URL": "https://bookmark5.example.com/", + "Placement": "menu", + "Folder": "Folder 2" + } + ] + } +}; + +/* + * ================================= + * = HELPER FUNCTIONS FOR THE TEST = + * ================================= + */ +function deepClone(obj) { + return JSON.parse(JSON.stringify(obj)); +} + +function findBookmarkInPolicy(bookmark) { + // Find the entry in the given policy that corresponds + // to this bookmark object from Places. + for (let entry of CURRENT_POLICY.policies.Bookmarks) { + if (entry.Title == bookmark.title) { + return entry; + } + } + return null; +} + +async function promiseAllChangesMade({itemsToAdd, itemsToRemove}) { + return new Promise(resolve => { + let bmObserver = { + onItemAdded() { + itemsToAdd--; + if (itemsToAdd == 0 && itemsToRemove == 0) { + PlacesUtils.bookmarks.removeObserver(bmObserver); + resolve(); + } + }, + + onItemRemoved() { + itemsToRemove--; + if (itemsToAdd == 0 && itemsToRemove == 0) { + PlacesUtils.bookmarks.removeObserver(bmObserver); + resolve(); + } + }, + + onBeginUpdateBatch() {}, + onEndUpdateBatch() {}, + onItemChanged() {}, + onItemVisited() {}, + onItemMoved() {}, + }; + PlacesUtils.bookmarks.addObserver(bmObserver); + }); +} + +/* + * ================== + * = CHECK FUNCTION = + * ================== + * + * Performs all the checks comparing what was given in + * the policy JSON with what was retrieved from Places. + */ +async function check({expectedNumberOfFolders}) { + let bookmarks = [], folders = []; + + await PlacesUtils.bookmarks.fetch({ guidPrefix: BookmarksPolicies.BOOKMARK_GUID_PREFIX }, (r) => { + bookmarks.push(r); + }); + await PlacesUtils.bookmarks.fetch({ guidPrefix: BookmarksPolicies.FOLDER_GUID_PREFIX }, (r) => { + folders.push(r); + }); + + let foldersToGuids = new Map(); + + for (let folder of folders) { + is(folder.type, PlacesUtils.bookmarks.TYPE_FOLDER, "Correct type for folder"); + foldersToGuids.set(folder.title, folder.guid); + } + + // For simplification and accuracy purposes, the number of expected + // folders is manually specified in the test. + is(folders.length, expectedNumberOfFolders, "Correct number of folders expected"); + is(foldersToGuids.size, expectedNumberOfFolders, "There aren't two different folders with the same name"); + + is(CURRENT_POLICY.policies.Bookmarks.length, bookmarks.length, "The correct number of bookmarks exist"); + + for (let bookmark of bookmarks) { + is(bookmark.type, PlacesUtils.bookmarks.TYPE_BOOKMARK, "Correct type for bookmark"); + + let entry = findBookmarkInPolicy(bookmark); + + is(bookmark.title, entry.Title, "Title matches"); + is(bookmark.url.href, entry.URL, "URL matches"); + + let expectedPlacementGuid; + if (entry.Folder) { + expectedPlacementGuid = foldersToGuids.get(entry.Folder); + } else { + expectedPlacementGuid = entry.Placement == "menu" ? + PlacesUtils.bookmarks.menuGuid : + PlacesUtils.bookmarks.toolbarGuid; + } + + is(bookmark.parentGuid, expectedPlacementGuid, "Correctly placed"); + } +} + +/* + * ================ + * = ACTUAL TESTS = + * ================ + * + * Note: the order of these tests is important, as we want to test not + * only the end result of each configuration, but also the diff algorithm + * that will add or remove bookmarks depending on how the policy changed. + */ + +add_task(async function test_initial_bookmarks() { + // Make a copy of the policy because we will be adding/removing entries from it + CURRENT_POLICY = deepClone(BASE_POLICY); + + await Promise.all( + [ + promiseAllChangesMade({ + itemsToAdd: 7, // 5 bookmarks + 2 folders + itemsToRemove: 0, + }), + setupPolicyEngineWithJson(CURRENT_POLICY) + ]); + + await check({ expectedNumberOfFolders: 2 }); +}); + +add_task(async function checkFavicon() { + let bookmark1url = CURRENT_POLICY.policies.Bookmarks[0].URL; + + let result = await new Promise(resolve => { + PlacesUtils.favicons.getFaviconDataForPage( + Services.io.newURI(bookmark1url), + (uri, _, data) => resolve({uri, data}) + ); + }); + + is(result.uri.spec, "fake-favicon-uri:" + bookmark1url, "Favicon URI is correct"); + // data is an array of octets, which will be a bit hard to compare against + // FAVICON_DATA, which is base64 encoded. Checking the expected length should + // be good indication that this is working properly. + is(result.data.length, 464, "Favicon data has the correct length"); + + let faviconsExpiredNotification = TestUtils.topicObserved("places-favicons-expired"); + PlacesUtils.favicons.expireAllFavicons(); + await faviconsExpiredNotification; +}); + +add_task(async function test_remove_Bookmark_2() { + // Continuing from the previous policy: + // + // Remove the 2nd bookmark. It is inside "Folder 1", but that + // folder won't be empty, so it must not be removed. + CURRENT_POLICY.policies.Bookmarks.splice(2, 1); + + await Promise.all( + [ + promiseAllChangesMade({ + itemsToAdd: 0, + itemsToRemove: 1, // 1 bookmark + }), + setupPolicyEngineWithJson(CURRENT_POLICY) + ]); + + await check({ expectedNumberOfFolders: 2 }); +}); + +add_task(async function test_remove_Bookmark_5() { + // Continuing from the previous policy: + // + // Remove the last bookmark in the policy, + // which means the "Folder 2" should also disappear + CURRENT_POLICY.policies.Bookmarks.splice(-1, 1); + + await Promise.all( + [ + promiseAllChangesMade({ + itemsToAdd: 0, + itemsToRemove: 2, // 1 bookmark and 1 folder + }), + setupPolicyEngineWithJson(CURRENT_POLICY) + ]); + + await check({ expectedNumberOfFolders: 1 }); +}); + +add_task(async function test_revert_to_original_policy() { + CURRENT_POLICY = deepClone(BASE_POLICY); + + // Reverts to the original policy, which means that: + // - "Bookmark 2" + // - "Bookmark 5" + // - "Folder 2" + // should be recreated + await Promise.all( + [ + promiseAllChangesMade({ + itemsToAdd: 3, // 2 bookmarks and 1 folder + itemsToRemove: 0, + }), + setupPolicyEngineWithJson(CURRENT_POLICY) + ]); + + await check({ expectedNumberOfFolders: 2 }); +}); + +// Leave this one at the end, so that it cleans up any +// bookmarks created during this test. +add_task(async function test_empty_all_bookmarks() { + CURRENT_POLICY = { policies: { Bookmarks: [] } }; + + await Promise.all( + [ + promiseAllChangesMade({ + itemsToAdd: 0, + itemsToRemove: 7, // 5 bookmarks and 2 folders + }), + setupPolicyEngineWithJson(CURRENT_POLICY) + ]); + + check({ expectedNumberOfFolders: 0 }); +}); diff -pruN 1:60.2.1-1/browser/components/extensions/test/browser/browser_ext_contextMenus_icons.js 1:60.2.1+build1-0ubuntu1/browser/components/extensions/test/browser/browser_ext_contextMenus_icons.js --- 1:60.2.1-1/browser/components/extensions/test/browser/browser_ext_contextMenus_icons.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/components/extensions/test/browser/browser_ext_contextMenus_icons.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,176 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +const PAGE = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html?test=icons"; + +add_task(async function test_root_icon() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE); + + let encodedImageData = "iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAC4klEQVRYhdWXLWzbQBSADQtDAwsHC1tUhUxqfL67lk2tdn+OJg0ODU0rLByqgqINBY6tmlbn7LMTJ5FaFVVBk1G0oUGjG2jT2Y7jxmmcbU/6iJ+f36fz+e5sGP9riCGm9hB37RG+scd4Yo/wsDXCZyIE2xuXsce4bY+wXkAsQtzYmExrfFgvkJkRbkzo1ehoxx5iXcgI/9iYUGt8WH9MqDXEcmNChmEYrRCf2SHWeYgQx3x0tLNRIeKQLTtEFyJEep4NTuhk8BC+yMrwEE3+iozo42d8gK7FAOkMsRiiN8QhW2ttSK5QTfRRV4QoymVeJMvPvDp7gCZigD613MN6yRFA3SWarow9QB9LCfG+NeF9qCtjAKOSQjCqVKhfVsiHEQ+grgx/lRGqUihAc1uL8EFD+KCRO+GrF4J61phcoRoPoEzkYhZYpykh5sMb7kOdIeY+jHKur4QI4Feh4AFX1nVeLxrAvQchGsBz5ls6wa2QdwcvIcE2863bTH79KOvsz/uUYJsp+J0pSzNlDckVqqVGUAF+n6uS7txcOl6wot4JVy70ufDLy4pWLUQVPE81pRI0mGe9oxLMHSeohHvMs/STUNaUK6vDPCvOyxMFDx4achehRDJmHnydnkPww5OFfLxrGIZBFDyYl4LpMzlTQFIP6AQx86w2UeYBccFpJrcKv5L9eGDtUAU6RIELqsB74uynjy/UBRF1gS5BTFxwQT1wTiXoUg9MH7m/3NZRRoi5IJytUbMgzv4Wc832+oQkiKgEehmyMkkpKsFkQV11QsRJL5rJYBLItQgRaUZEmnoZXsomz3vGiWw+I9KMF9SVFOqZEemZekli1jN3U/UOqhHHvC6oWWGElhfSpGdOk6+O9prdwvtLj5BjRsQxdRnot+Zeifpy/2/0stktKTRNLmbk0mwXyl8253fyojj+8rxOHNAhjjm5n0/5OOCGOKBzkrMO0Z75lvSAzKlrF32Z/3z8BqLAn+yMV7VhAAAAAElFTkSuQmCC"; + const IMAGE_ARRAYBUFFER = imageBufferFromDataURI(encodedImageData); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + "name": "contextMenus icons", + "permissions": ["contextMenus"], + "icons": { + "18": "extension.png", + }, + }, + + files: { + "extension.png": IMAGE_ARRAYBUFFER, + }, + + background: function() { + let menuitemId = browser.contextMenus.create({ + title: "child-to-delete", + onclick: () => { + browser.contextMenus.remove(menuitemId); + browser.test.sendMessage("child-deleted"); + }, + }); + + browser.contextMenus.create({ + title: "child", + }, () => { + browser.test.sendMessage("contextmenus-icons"); + }); + }, + }); + + let confirmContextMenuIcon = (rootElements) => { + let expectedURL = new RegExp(String.raw`^moz-extension://[^/]+/extension\.png$`); + is(rootElements.length, 1, "Found exactly one menu item"); + let imageUrl = rootElements[0].getAttribute("image"); + ok(expectedURL.test(imageUrl), "The context menu should display the extension icon next to the root element"); + }; + + await extension.startup(); + await extension.awaitMessage("contextmenus-icons"); + + let extensionMenu = await openExtensionContextMenu(); + + let contextMenu = document.getElementById("contentAreaContextMenu"); + let topLevelMenuItem = contextMenu.getElementsByAttribute("ext-type", "top-level-menu"); + confirmContextMenuIcon(topLevelMenuItem); + + let childToDelete = extensionMenu.getElementsByAttribute("label", "child-to-delete"); + is(childToDelete.length, 1, "Found exactly one child to delete"); + await closeExtensionContextMenu(childToDelete[0]); + await extension.awaitMessage("child-deleted"); + + await openExtensionContextMenu(); + + contextMenu = document.getElementById("contentAreaContextMenu"); + topLevelMenuItem = contextMenu.getElementsByAttribute("label", "child"); + + confirmContextMenuIcon(topLevelMenuItem); + await closeContextMenu(); + + await extension.unload(); + await BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_child_icon() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE); + + let blackIconData = "iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QYGEhkO2P07+gAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAARSURBVCjPY2AYBaNgFAxPAAAD3gABo0ohTgAAAABJRU5ErkJggg=="; + const IMAGE_ARRAYBUFFER_BLACK = imageBufferFromDataURI(blackIconData); + + let redIconData = "iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QYGEgw1XkM0ygAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAYSURBVCjPY/zPQA5gYhjVNqptVNsg1wYAItkBI/GNR3YAAAAASUVORK5CYII="; + const IMAGE_ARRAYBUFFER_RED = imageBufferFromDataURI(redIconData); + + let blueIconData = "iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QYGEg0QDFzRzAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAbSURBVCjPY2SQ+89AOmBiIAuMahvVNqqNftoAlKMBQZXKX9kAAAAASUVORK5CYII="; + const IMAGE_ARRAYBUFFER_BLUE = imageBufferFromDataURI(blueIconData); + + let greenIconData = "iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QYGEg0rvVc46AAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAaSURBVCjPY+Q8xkAGYGJgGNU2qm1U2+DWBgBolADz1beTnwAAAABJRU5ErkJggg=="; + const IMAGE_ARRAYBUFFER_GREEN = imageBufferFromDataURI(greenIconData); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + "permissions": ["contextMenus"], + "icons": { + "18": "black_icon.png", + }, + }, + + files: { + "black_icon.png": IMAGE_ARRAYBUFFER_BLACK, + "red_icon.png": IMAGE_ARRAYBUFFER_RED, + "blue_icon.png": IMAGE_ARRAYBUFFER_BLUE, + "green_icon.png": IMAGE_ARRAYBUFFER_GREEN, + }, + + background: function() { + browser.test.onMessage.addListener(msg => { + if (msg !== "add-additional-contextmenu-items") { + return; + } + + browser.contextMenus.create({ + title: "child2", + id: "contextmenu-child2", + icons: { + 18: "blue_icon.png", + }, + }); + + browser.contextMenus.create({ + title: "child3", + id: "contextmenu-child3", + icons: { + 18: "green_icon.png", + }, + }, () => { + browser.test.sendMessage("extra-contextmenu-items-added"); + }); + }); + + browser.contextMenus.create({ + title: "child1", + id: "contextmenu-child1", + icons: { + 18: "red_icon.png", + }, + }, () => { + browser.test.sendMessage("single-contextmenu-item-added"); + }); + }, + }); + + let confirmContextMenuIcon = (element, imageName) => { + let imageURL = element.getAttribute("image"); + ok(imageURL.endsWith(imageName), "The context menu should display the extension icon next to the child element"); + }; + + await extension.startup(); + + await extension.awaitMessage("single-contextmenu-item-added"); + + let contextMenu = await openContextMenu(); + let contextMenuChild1 = contextMenu.getElementsByAttribute("label", "child1")[0]; + confirmContextMenuIcon(contextMenuChild1, "black_icon.png"); + + await closeContextMenu(); + + extension.sendMessage("add-additional-contextmenu-items"); + await extension.awaitMessage("extra-contextmenu-items-added"); + + contextMenu = await openExtensionContextMenu(); + + contextMenuChild1 = contextMenu.getElementsByAttribute("label", "child1")[0]; + confirmContextMenuIcon(contextMenuChild1, "red_icon.png"); + + let contextMenuChild2 = contextMenu.getElementsByAttribute("label", "child2")[0]; + confirmContextMenuIcon(contextMenuChild2, "blue_icon.png"); + + let contextMenuChild3 = contextMenu.getElementsByAttribute("label", "child3")[0]; + confirmContextMenuIcon(contextMenuChild3, "green_icon.png"); + + await closeContextMenu(); + + await extension.unload(); + await BrowserTestUtils.removeTab(tab); +}); diff -pruN 1:60.2.1-1/browser/components/extensions/test/browser/browser_ext_themes_icons.js 1:60.2.1+build1-0ubuntu1/browser/components/extensions/test/browser/browser_ext_themes_icons.js --- 1:60.2.1-1/browser/components/extensions/test/browser/browser_ext_themes_icons.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/components/extensions/test/browser/browser_ext_themes_icons.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,248 @@ +"use strict"; + +const ENCODED_IMAGE_DATA = "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgNjQgNjQiPjxwYXRoIGQ9Im01NS45IDMyLjFsLTIyLjctMTQuOWMwIDAgMTIuOS0xNy40IDE5LjQtMTQuOSAzLjEgMS4xIDUuNCAyNS4xIDMuMyAyOS44IiBmaWxsPSIjM2U0MzQ3Ii8+PHBhdGggZD0ibTU0LjkgMzMuOWwtOS00LjFjMCAwLTUuMy0xNCA2LjEtMjQuMSAyLjQgMiA1LjEgMjUgMi45IDI4LjIiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJtOC4xIDMyLjFsMjIuNi0xNC45YzAgMC0xMi45LTE3LjQtMTkuNC0xNC45LTMgMS4xLTUuMyAyNS4xLTMuMiAyOS44IiBmaWxsPSIjM2U0MzQ3Ii8+PHBhdGggZD0ibTkuMSAzMy45bDktNC4xYzAgMCA1LjMtMTQtNi4xLTI0LjEtMi40IDItNS4xIDI1LTIuOSAyOC4yIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTMyLDEzQzE4LjksMTMsMiwzMy42LDIsNDUuNEMyMC41LDQ1LjQsMTkuNyw2MiwzMiw2MnMxMS41LTE2LjYsMzAtMTYuNkM2MiwzMy42LDQ1LjEsMTMsMzIsMTN6IiBmaWxsPSIjZmY4NzM2Ii8+PGcgZmlsbD0iI2ZmZiI+PHBhdGggZD0iTTMyLDU2LjJjMCw1LjEsOS42LDQuMiw5LjUtMi45YzYuNy05LjQsMTkuOS04LjcsMTkuOS04LjdDMzkuNiwzMi40LDMyLDU2LjIsMzIsNTYuMnoiLz48cGF0aCBkPSJNMzIsNTYuMmMwLDUuMS05LjYsNC4yLTkuNS0yLjlDMTUuOCw0NCwyLjYsNDQuNywyLjYsNDQuN0MyNC40LDMyLjQsMzIsNTYuMiwzMiw1Ni4yeiIvPjwvZz48ZyBmaWxsPSIjZmY4NzM2Ij48cGF0aCBkPSJtNTMuNCAxOC41Yy00IC43LTQuOSA2LjMtNC45IDYuM2w2IDUuM2MtMi4zLTUuOS0xLjEtMTEuNi0xLjEtMTEuNiIvPjxwYXRoIGQ9Im01MS4xIDEzLjVjLTQuNCAzLjktNS4xIDguNy01LjEgOC43bDYgNS4zYy0yLjQtNS44LS45LTE0LS45LTE0Ii8+PHBhdGggZD0ibTEwLjYgMTguNWM0IC43IDQuOSA2LjMgNC45IDYuM2wtNiA1LjNjMi4zLTUuOSAxLjEtMTEuNiAxLjEtMTEuNiIvPjxwYXRoIGQ9Im0xMi45IDEzLjVjNC40IDMuOSA1LjEgOC43IDUuMSA4LjdsLTYgNS4zYzIuNC01LjguOS0xNCAuOS0xNCIvPjwvZz48cGF0aCBkPSJtNTIuOCAzMS4xYy01LjctMS44LTEwLjktMy40LTEzLjguOS0yLjQgMy43LjcgOS40LjcgOS40IDExLjIgMS4yIDEzLjEtMTAuMyAxMy4xLTEwLjMiIGZpbGw9IiMzZTQzNDciLz48ZWxsaXBzZSBjeD0iNDMiIGN5PSIzNi4zIiByeD0iNC4yIiByeT0iNC4xIiBmaWxsPSIjZDVmZjgzIi8+PGcgZmlsbD0iIzNlNDM0NyI+PGVsbGlwc2UgY3g9IjQzIiBjeT0iMzYuMyIgcng9IjIuNyIgcnk9IjIuNyIvPjxwYXRoIGQ9Im0xMS4yIDMxLjFjNS43LTEuOCAxMC45LTMuNCAxMy43LjkgMi40IDMuNy0uNyA5LjQtLjcgOS40LTExLjEgMS4yLTEzLTEwLjMtMTMtMTAuMyIvPjwvZz48ZWxsaXBzZSBjeD0iMjEiIGN5PSIzNi4zIiByeD0iNC4yIiByeT0iNC4xIiBmaWxsPSIjZDVmZjgzIi8+PGcgZmlsbD0iIzNlNDM0NyI+PGVsbGlwc2UgY3g9IjIxIiBjeT0iMzYuMyIgcng9IjIuNyIgcnk9IjIuNyIvPjxwYXRoIGQ9Im00MS4yIDQ3LjljLS43LTIuMy0xLjgtNC40LTMtNi41IDEuMSAyLjEgMiA0LjMgMi41IDYuNi41IDIuMy43IDQuNyAwIDYuOC0uNCAxLTEgMi0xLjggMi42LS44LjYtMS44IDEtMi43IDEtLjkgMC0xLjktLjMtMi41LTEtLjYtLjctLjktMS42LS44LTIuNmwtLjkuMmgtLjljMCAxLS4yIDEuOS0uOCAyLjYtLjYuNy0xLjUgMS0yLjUgMS0uOSAwLTEuOS0uNC0yLjctMS0uOC0uNi0xLjQtMS42LTEuOC0yLjYtLjgtMi4xLS42LTQuNiAwLTYuOC41LTIuMyAxLjUtNC41IDIuNS02LjYtMS4yIDItMi4zIDQuMS0zIDYuNS0uNyAyLjMtMS4xIDQuOC0uNCA3LjMuMyAxLjIgMSAyLjQgMS45IDMuMy45LjkgMi4xIDEuNCAzLjQgMS41IDEuMi4xIDIuNi0uMiAzLjctMS4yLjMtLjIuNS0uNS43LS44LjIuMy40LjYuNy44IDEgMSAyLjQgMS4zIDMuNyAxLjIgMS4zLS4xIDIuNC0uNyAzLjQtMS41LjktLjkgMS42LTIgMS45LTMuMy41LTIuNi4xLTUuMi0uNi03LjUiLz48cGF0aCBkPSJtMzcuNiA1MC4zYy0xLjEtMS4xLTQuNS0xLjItNS42LTEuMi0xIDAtNC41LjEtNS42IDEuMi0uOC44LS4yIDIuOCAxLjkgNC41IDEuMyAxLjEgMi42IDEuNCAzLjYgMS40IDEgMCAyLjMtLjMgMy42LTEuNCAyLjMtMS43IDIuOS0zLjcgMi4xLTQuNSIvPjwvZz48L3N2Zz4="; + +/** + * Verifies that the button uses the expected icon. + * + * @param {string} selector The CSS selector used to find the button + * within the DOM. + * @param {boolean} shouldHaveCustomStyling True if the button should + * have custom styling, False otherwise. + * @param {string} message The message that is printed to the console + * by the verifyFn. + */ +function verifyButtonProperties(selector, shouldHaveCustomStyling, message) { + try { + let element = document.querySelector(selector); + let listStyleImage = getComputedStyle(element).listStyleImage; + info(`listStyleImage for fox.svg is ${listStyleImage}`); + is(listStyleImage.includes("moz-extension:"), shouldHaveCustomStyling, message); + } catch (ex) { + ok(false, `Unable to verify ${selector}: ${ex}`); + } +} + +/** + * Verifies that the button uses default styling. + * + * @param {string} selector The CSS selector used to find the button + * within the DOM. + * @param {string} message The message that is printed to the console + * by the verifyFn. + */ +function verifyButtonWithoutCustomStyling(selector, message) { + verifyButtonProperties(selector, false, message); +} + +/** + * Verifies that the button uses non-default styling. + * + * @param {string} selector The CSS selector used to find the button + * within the DOM. + * @param {string} message The message that is printed to the console + * by the verifyFn. + */ +function verifyButtonWithCustomStyling(selector, message) { + verifyButtonProperties(selector, true, message); +} + +/** + * Loops through all of the buttons to confirm that they are styled + * as expected (either with or without custom styling). + * + * @param {object} icons Array of an array that specifies which buttons should + * have custom icons. + * @param {object} iconInfo An array of arrays that maps API names to + * CSS selectors. + * @param {string} area The name of the area that the button resides in. + */ +function checkButtons(icons, iconInfo, area) { + for (let button of iconInfo) { + let iconInfo = icons.find(arr => arr[0] == button[0]); + if (iconInfo[1]) { + verifyButtonWithCustomStyling( + button[1], + `The ${button[1]} should have its icon customized in the ${area}`); + } else { + verifyButtonWithoutCustomStyling( + button[1], + `The ${button[1]} should not have its icon customized in the ${area}`); + } + } +} + +async function runTestWithIcons(icons) { + const FRAME_COLOR = [71, 105, 91]; + const TAB_BACKGROUND_TEXT_COLOR = [207, 221, 192, .9]; + let manifest = { + "theme": { + "images": { + "theme_frame": "fox.svg", + }, + "colors": { + "frame": FRAME_COLOR, + "tab_background_text": TAB_BACKGROUND_TEXT_COLOR, + }, + "icons": {}, + }, + }; + let files = { + "fox.svg": imageBufferFromDataURI(ENCODED_IMAGE_DATA), + }; + + // Each item in this array has the following setup: + // At position 0: The name that is used in the theme manifest. + // At position 1: The CSS selector for the button in the DOM. + // At position 2: The CustomizableUI name for the widget, only defined + // if customizable. + const ICON_INFO = [ + ["back", "#back-button"], + ["forward", "#forward-button"], + ["reload", "#reload-button"], + ["stop", "#stop-button"], + ["downloads", "#downloads-button", "downloads-button"], + ["home", "#home-button", "home-button"], + ["app_menu", "#PanelUI-menu-button"], + ["cut", "#cut-button", "edit-controls"], + ["copy", "#copy-button"], + ["paste", "#paste-button"], + ["new_window", "#new-window-button", "new-window-button"], + ["new_private_window", "#privatebrowsing-button", "privatebrowsing-button"], + ["save_page", "#save-page-button", "save-page-button"], + ["print", "#print-button", "print-button"], + ["history", "#history-panelmenu", "history-panelmenu"], + ["full_screen", "#fullscreen-button", "fullscreen-button"], + ["find", "#find-button", "find-button"], + ["options", "#preferences-button", "preferences-button"], + ["addons", "#add-ons-button", "add-ons-button"], + ["developer", "#developer-button", "developer-button"], + ["synced_tabs", "#sync-button", "sync-button"], + ["open_file", "#open-file-button", "open-file-button"], + ["sidebars", "#sidebar-button", "sidebar-button"], + ["subscribe", "#feed-button", "feed-button"], + ["text_encoding", "#characterencoding-button", "characterencoding-button"], + ["email_link", "#email-link-button", "email-link-button"], + ["forget", "#panic-button", "panic-button"], + ]; + // We add these at the beginning because adding them at the end can end up + // putting them in the overflow panel, where they aren't displayed the same way. + ICON_INFO.unshift(["bookmark_star", "#star-button"]); + ICON_INFO.unshift(["bookmark_menu", "#bookmarks-menu-button", "bookmarks-menu-button"]); + + window.maximize(); + + for (let button of ICON_INFO) { + if (button[2]) { + CustomizableUI.addWidgetToArea(button[2], CustomizableUI.AREA_NAVBAR); + } + + verifyButtonWithoutCustomStyling( + button[1], + `The ${button[1]} should not have its icon customized when the test starts`); + + let iconInfo = icons.find(arr => arr[0] == button[0]); + manifest.theme.icons[button[0]] = iconInfo[1]; + } + + let extension = ExtensionTestUtils.loadExtension({manifest, files}); + + await extension.startup(); + + checkButtons(icons, ICON_INFO, "toolbar"); + + await extension.unload(); + + for (let button of ICON_INFO) { + verifyButtonWithoutCustomStyling( + button[1], + `The ${button[1]} should not have its icon customized when the theme is unloaded`); + } +} + +add_task(async function setup() { + await SpecialPowers.pushPrefEnv({ + set: [["extensions.webextensions.themes.enabled", true], + ["extensions.webextensions.themes.icons.enabled", true]], + }); +}); + +add_task(async function test_all_icons() { + let icons = [ + ["back", "fox.svg"], + ["forward", "fox.svg"], + ["reload", "fox.svg"], + ["stop", "fox.svg"], + ["bookmark_star", "fox.svg"], + ["bookmark_menu", "fox.svg"], + ["downloads", "fox.svg"], + ["home", "fox.svg"], + ["app_menu", "fox.svg"], + ["cut", "fox.svg"], + ["copy", "fox.svg"], + ["paste", "fox.svg"], + ["new_window", "fox.svg"], + ["new_private_window", "fox.svg"], + ["save_page", "fox.svg"], + ["print", "fox.svg"], + ["history", "fox.svg"], + ["full_screen", "fox.svg"], + ["find", "fox.svg"], + ["options", "fox.svg"], + ["addons", "fox.svg"], + ["developer", "fox.svg"], + ["synced_tabs", "fox.svg"], + ["open_file", "fox.svg"], + ["sidebars", "fox.svg"], + ["subscribe", "fox.svg"], + ["text_encoding", "fox.svg"], + ["email_link", "fox.svg"], + ["forget", "fox.svg"], + ]; + await runTestWithIcons(icons); +}); + +add_task(async function teardown() { + CustomizableUI.reset(); + window.restore(); +}); + +add_task(async function test_some_icons() { + let icons = [ + ["back", ""], + ["forward", ""], + ["reload", "fox.svg"], + ["stop", ""], + ["bookmark_star", ""], + ["bookmark_menu", ""], + ["downloads", ""], + ["home", "fox.svg"], + ["app_menu", "fox.svg"], + ["cut", ""], + ["copy", ""], + ["paste", ""], + ["new_window", ""], + ["new_private_window", ""], + ["save_page", ""], + ["print", ""], + ["history", ""], + ["full_screen", ""], + ["find", ""], + ["options", ""], + ["addons", ""], + ["developer", ""], + ["synced_tabs", ""], + ["open_file", ""], + ["sidebars", ""], + ["subscribe", ""], + ["text_encoding", ""], + ["email_link", ""], + ["forget", ""], + ]; + await runTestWithIcons(icons); +}); + +add_task(async function teardown() { + CustomizableUI.reset(); + window.restore(); +}); diff -pruN 1:60.2.1-1/browser/components/migration/tests/unit/test_IE7_passwords.js 1:60.2.1+build1-0ubuntu1/browser/components/migration/tests/unit/test_IE7_passwords.js --- 1:60.2.1-1/browser/components/migration/tests/unit/test_IE7_passwords.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/components/migration/tests/unit/test_IE7_passwords.js 2018-10-02 14:08:34.000000000 +0000 @@ -0,0 +1,408 @@ +"use strict"; + +ChromeUtils.import("resource://gre/modules/AppConstants.jsm"); +ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); + +ChromeUtils.defineModuleGetter(this, "WindowsRegistry", + "resource://gre/modules/WindowsRegistry.jsm"); +ChromeUtils.defineModuleGetter(this, "OSCrypto", + "resource://gre/modules/OSCrypto.jsm"); + +const IE7_FORM_PASSWORDS_MIGRATOR_NAME = "IE7FormPasswords"; +const LOGINS_KEY = "Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2"; +const EXTENSION = "-backup"; +const TESTED_WEBSITES = { + twitter: { + uri: makeURI("https://twitter.com"), + hash: "A89D42BC6406E27265B1AD0782B6F376375764A301", + data: [12, 0, 0, 0, 56, 0, 0, 0, 38, 0, 0, 0, 87, 73, 67, 75, 24, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 36, 67, 124, 118, 212, 208, 1, 8, 0, 0, 0, 18, 0, 0, 0, 68, 36, 67, 124, 118, 212, 208, 1, 9, 0, 0, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0, 0, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0, 57, 0, 0, 0], + logins: [ + { + username: "abcdefgh", + password: "123456789", + hostname: "https://twitter.com", + formSubmitURL: "", + httpRealm: null, + usernameField: "", + passwordField: "", + timeCreated: 1439325854000, + timeLastUsed: 1439325854000, + timePasswordChanged: 1439325854000, + timesUsed: 1, + }, + ], + }, + facebook: { + uri: makeURI("https://www.facebook.com/"), + hash: "EF44D3E034009CB0FD1B1D81A1FF3F3335213BD796", + data: [12, 0, 0, 0, 152, 0, 0, 0, 160, 0, 0, 0, 87, 73, 67, 75, 24, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 182, 125, 18, 121, 212, 208, 1, 9, 0, 0, 0, 20, 0, 0, 0, 88, 182, 125, 18, 121, 212, 208, 1, 9, 0, 0, 0, 40, 0, 0, 0, 134, 65, 33, 37, 121, 212, 208, 1, 9, 0, 0, 0, 60, 0, 0, 0, 134, 65, 33, 37, 121, 212, 208, 1, 9, 0, 0, 0, 80, 0, 0, 0, 45, 242, 246, 62, 121, 212, 208, 1, 9, 0, 0, 0, 100, 0, 0, 0, 45, 242, 246, 62, 121, 212, 208, 1, 9, 0, 0, 0, 120, 0, 0, 0, 28, 10, 193, 80, 121, 212, 208, 1, 9, 0, 0, 0, 140, 0, 0, 0, 28, 10, 193, 80, 121, 212, 208, 1, 9, 0, 0, 0, 117, 0, 115, 0, 101, 0, 114, 0, 110, 0, 97, 0, 109, 0, 101, 0, 48, 0, 0, 0, 112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 48, 0, 0, 0, 117, 0, 115, 0, 101, 0, 114, 0, 110, 0, 97, 0, 109, 0, 101, 0, 49, 0, 0, 0, 112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 49, 0, 0, 0, 117, 0, 115, 0, 101, 0, 114, 0, 110, 0, 97, 0, 109, 0, 101, 0, 50, 0, 0, 0, 112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 50, 0, 0, 0, 117, 0, 115, 0, 101, 0, 114, 0, 110, 0, 97, 0, 109, 0, 101, 0, 51, 0, 0, 0, 112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 51, 0, 0, 0], + logins: [ + { + username: "username0", + password: "password0", + hostname: "https://www.facebook.com", + formSubmitURL: "", + httpRealm: null, + usernameField: "", + passwordField: "", + timeCreated: 1439326966000, + timeLastUsed: 1439326966000, + timePasswordChanged: 1439326966000, + timesUsed: 1, + }, + { + username: "username1", + password: "password1", + hostname: "https://www.facebook.com", + formSubmitURL: "", + httpRealm: null, + usernameField: "", + passwordField: "", + timeCreated: 1439326997000, + timeLastUsed: 1439326997000, + timePasswordChanged: 1439326997000, + timesUsed: 1, + }, + { + username: "username2", + password: "password2", + hostname: "https://www.facebook.com", + formSubmitURL: "", + httpRealm: null, + usernameField: "", + passwordField: "", + timeCreated: 1439327040000, + timeLastUsed: 1439327040000, + timePasswordChanged: 1439327040000, + timesUsed: 1, + }, + { + username: "username3", + password: "password3", + hostname: "https://www.facebook.com", + formSubmitURL: "", + httpRealm: null, + usernameField: "", + passwordField: "", + timeCreated: 1439327070000, + timeLastUsed: 1439327070000, + timePasswordChanged: 1439327070000, + timesUsed: 1, + }, + ], + }, + live: { + uri: makeURI("https://login.live.com/"), + hash: "7B506F2D6B81D939A8E0456F036EE8970856FF705E", + data: [12, 0, 0, 0, 56, 0, 0, 0, 44, 0, 0, 0, 87, 73, 67, 75, 24, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 17, 219, 140, 148, 212, 208, 1, 9, 0, 0, 0, 20, 0, 0, 0, 212, 17, 219, 140, 148, 212, 208, 1, 11, 0, 0, 0, 114, 0, 105, 0, 97, 0, 100, 0, 104, 0, 49, 6, 74, 6, 39, 6, 54, 6, 0, 0, 39, 6, 66, 6, 49, 6, 35, 6, 80, 0, 192, 0, 223, 0, 119, 0, 246, 0, 114, 0, 100, 0, 0, 0], + logins: [ + { + username: "riadhرياض", + password: "اقرأPÀßwörd", + hostname: "https://login.live.com", + formSubmitURL: "", + httpRealm: null, + usernameField: "", + passwordField: "", + timeCreated: 1439338767000, + timeLastUsed: 1439338767000, + timePasswordChanged: 1439338767000, + timesUsed: 1, + }, + ], + }, + reddit: { + uri: makeURI("http://www.reddit.com/"), + hash: "B644028D1C109A91EC2C4B9D1F145E55A1FAE42065", + data: [12, 0, 0, 0, 152, 0, 0, 0, 212, 0, 0, 0, 87, 73, 67, 75, 24, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 8, 234, 114, 153, 212, 208, 1, 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 93, 131, 116, 153, 212, 208, 1, 3, 0, 0, 0, 14, 0, 0, 0, 97, 93, 131, 116, 153, 212, 208, 1, 16, 0, 0, 0, 48, 0, 0, 0, 88, 150, 78, 174, 153, 212, 208, 1, 4, 0, 0, 0, 58, 0, 0, 0, 88, 150, 78, 174, 153, 212, 208, 1, 29, 0, 0, 0, 118, 0, 0, 0, 79, 102, 137, 34, 154, 212, 208, 1, 15, 0, 0, 0, 150, 0, 0, 0, 79, 102, 137, 34, 154, 212, 208, 1, 30, 0, 0, 0, 97, 0, 0, 0, 0, 0, 252, 140, 173, 138, 146, 48, 0, 0, 66, 0, 105, 0, 116, 0, 116, 0, 101, 0, 32, 0, 98, 0, 101, 0, 115, 0, 116, 0, 228, 0, 116, 0, 105, 0, 103, 0, 101, 0, 110, 0, 0, 0, 205, 145, 110, 127, 198, 91, 1, 120, 0, 0, 31, 4, 48, 4, 64, 4, 62, 4, 59, 4, 76, 4, 32, 0, 67, 4, 65, 4, 63, 4, 53, 4, 72, 4, 61, 4, 62, 4, 32, 0, 65, 4, 49, 4, 64, 4, 62, 4, 72, 4, 53, 4, 61, 4, 46, 0, 32, 0, 18, 4, 62, 4, 57, 4, 66, 4, 56, 4, 0, 0, 40, 6, 51, 6, 69, 6, 32, 0, 39, 6, 68, 6, 68, 6, 71, 6, 32, 0, 39, 6, 68, 6, 49, 6, 45, 6, 69, 6, 70, 6, 0, 0, 118, 0, 101, 0, 117, 0, 105, 0, 108, 0, 108, 0, 101, 0, 122, 0, 32, 0, 108, 0, 101, 0, 32, 0, 118, 0, 233, 0, 114, 0, 105, 0, 102, 0, 105, 0, 101, 0, 114, 0, 32, 0, 224, 0, 32, 0, 110, 0, 111, 0, 117, 0, 118, 0, 101, 0, 97, 0, 117, 0, 0, 0], + logins: [ + // This login is present in the data, but should be stripped out + // by the validation rules of the importer: + // { + // "username": "a", + // "password": "", + // "hostname": "http://www.reddit.com", + // "formSubmitURL": "", + // "httpRealm": null, + // "usernameField": "", + // "passwordField": "" + // }, + { + username: "購読を", + password: "Bitte bestätigen", + hostname: "http://www.reddit.com", + formSubmitURL: "", + httpRealm: null, + usernameField: "", + passwordField: "", + timeCreated: 1439340874000, + timeLastUsed: 1439340874000, + timePasswordChanged: 1439340874000, + timesUsed: 1, + }, + { + username: "重置密码", + password: "Пароль успешно сброшен. Войти", + hostname: "http://www.reddit.com", + formSubmitURL: "", + httpRealm: null, + usernameField: "", + passwordField: "", + timeCreated: 1439340971000, + timeLastUsed: 1439340971000, + timePasswordChanged: 1439340971000, + timesUsed: 1, + }, + { + username: "بسم الله الرحمن", + password: "veuillez le vérifier à nouveau", + hostname: "http://www.reddit.com", + formSubmitURL: "", + httpRealm: null, + usernameField: "", + passwordField: "", + timeCreated: 1439341166000, + timeLastUsed: 1439341166000, + timePasswordChanged: 1439341166000, + timesUsed: 1, + }, + ], + }, +}; + +const TESTED_URLS = [ + "http://a.foo.com", + "http://b.foo.com", + "http://c.foo.com", + "http://www.test.net", + "http://www.test.net/home", + "http://www.test.net/index", + "https://a.bar.com", + "https://b.bar.com", + "https://c.bar.com", +]; + +var nsIWindowsRegKey = Ci.nsIWindowsRegKey; +var Storage2Key; + +/* + * If the key value exists, it's going to be backed up and replaced, so the value could be restored. + * Otherwise a new value is going to be created. + */ +function backupAndStore(key, name, value) { + if (key.hasValue(name)) { + // backup the the current value + let type = key.getValueType(name); + // create a new value using use the current value name followed by EXTENSION as its new name + switch (type) { + case nsIWindowsRegKey.TYPE_STRING: + key.writeStringValue(name + EXTENSION, key.readStringValue(name)); + break; + case nsIWindowsRegKey.TYPE_BINARY: + key.writeBinaryValue(name + EXTENSION, key.readBinaryValue(name)); + break; + case nsIWindowsRegKey.TYPE_INT: + key.writeIntValue(name + EXTENSION, key.readIntValue(name)); + break; + case nsIWindowsRegKey.TYPE_INT64: + key.writeInt64Value(name + EXTENSION, key.readInt64Value(name)); + break; + } + } + key.writeBinaryValue(name, value); +} + +// Remove all values where their names are members of the names array from the key of registry +function removeAllValues(key, names) { + for (let name of names) { + key.removeValue(name); + } +} + +// Restore all the backed up values +function restore(key) { + let count = key.valueCount; + let names = []; // the names of the key values + for (let i = 0; i < count; ++i) { + names.push(key.getValueName(i)); + } + + for (let name of names) { + // backed up values have EXTENSION at the end of their names + if (name.lastIndexOf(EXTENSION) == name.length - EXTENSION.length) { + let valueName = name.substr(0, name.length - EXTENSION.length); + let type = key.getValueType(name); + // create a new value using the name before the backup and removed the backed up one + switch (type) { + case nsIWindowsRegKey.TYPE_STRING: + key.writeStringValue(valueName, key.readStringValue(name)); + key.removeValue(name); + break; + case nsIWindowsRegKey.TYPE_BINARY: + key.writeBinaryValue(valueName, key.readBinaryValue(name)); + key.removeValue(name); + break; + case nsIWindowsRegKey.TYPE_INT: + key.writeIntValue(valueName, key.readIntValue(name)); + key.removeValue(name); + break; + case nsIWindowsRegKey.TYPE_INT64: + key.writeInt64Value(valueName, key.readInt64Value(name)); + key.removeValue(name); + break; + } + } + } +} + +function checkLoginsAreEqual(passwordManagerLogin, IELogin, id) { + passwordManagerLogin.QueryInterface(Ci.nsILoginMetaInfo); + for (let attribute in IELogin) { + Assert.equal(passwordManagerLogin[attribute], IELogin[attribute], + "The two logins ID " + id + " have the same " + attribute); + } +} + +function createRegistryPath(path) { + let loginPath = path.split("\\"); + let parentKey = Cc["@mozilla.org/windows-registry-key;1"]. + createInstance(nsIWindowsRegKey); + let currentPath = []; + for (let currentKey of loginPath) { + parentKey.open(nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, currentPath.join("\\"), + nsIWindowsRegKey.ACCESS_ALL); + + if (!parentKey.hasChild(currentKey)) { + parentKey.createChild(currentKey, 0); + } + currentPath.push(currentKey); + parentKey.close(); + } +} + +function getFirstResourceOfType(type) { + let migrator = Cc["@mozilla.org/profile/migrator;1?app=browser&type=ie"] + .createInstance(Ci.nsISupports) + .wrappedJSObject; + let migrators = migrator.getResources(); + for (let m of migrators) { + if (m.name == IE7_FORM_PASSWORDS_MIGRATOR_NAME && m.type == type) { + return m; + } + } + throw new Error("failed to find the " + type + " migrator"); +} + +function makeURI(aURL) { + return Services.io.newURI(aURL); +} + +add_task(async function setup() { + if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) { + Assert.throws(() => getFirstResourceOfType(MigrationUtils.resourceTypes.PASSWORDS), + "The migrator doesn't exist for win8+"); + return; + } + // create the path to Storage2 in the registry if it doest exist. + createRegistryPath(LOGINS_KEY); + Storage2Key = Cc["@mozilla.org/windows-registry-key;1"]. + createInstance(nsIWindowsRegKey); + Storage2Key.open(nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, LOGINS_KEY, + nsIWindowsRegKey.ACCESS_ALL); + + // create a dummy value otherwise the migrator doesn't exist + if (!Storage2Key.hasValue("dummy")) { + Storage2Key.writeBinaryValue("dummy", "dummy"); + } +}); + +add_task(async function test_passwordsNotAvailable() { + if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) { + return; + } + + let migrator = getFirstResourceOfType(MigrationUtils.resourceTypes.PASSWORDS); + Assert.ok(migrator.exists, "The migrator has to exist"); + let logins = Services.logins.getAllLogins({}); + Assert.equal(logins.length, 0, "There are no logins at the beginning of the test"); + + let uris = []; // the uris of the migrated logins + for (let url of TESTED_URLS) { + uris.push(makeURI(url)); + // in this test, there is no IE login data in the registry, so after the migration, the number + // of logins in the store should be 0 + await migrator._migrateURIs(uris); + logins = Services.logins.getAllLogins({}); + Assert.equal(logins.length, 0, + "There are no logins after doing the migration without adding values to the registry"); + } +}); + +add_task(async function test_passwordsAvailable() { + if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) { + return; + } + + let crypto = new OSCrypto(); + let hashes = []; // the hashes of all migrator websites, this is going to be used for the clean up + + registerCleanupFunction(() => { + Services.logins.removeAllLogins(); + logins = Services.logins.getAllLogins({}); + Assert.equal(logins.length, 0, "There are no logins after the cleanup"); + // remove all the values created in this test from the registry + removeAllValues(Storage2Key, hashes); + // restore all backed up values + restore(Storage2Key); + + // clean the dummy value + if (Storage2Key.hasValue("dummy")) { + Storage2Key.removeValue("dummy"); + } + Storage2Key.close(); + crypto.finalize(); + }); + + let migrator = getFirstResourceOfType(MigrationUtils.resourceTypes.PASSWORDS); + Assert.ok(migrator.exists, "The migrator has to exist"); + let logins = Services.logins.getAllLogins({}); + Assert.equal(logins.length, 0, "There are no logins at the beginning of the test"); + + let uris = []; // the uris of the migrated logins + + let loginCount = 0; + for (let current in TESTED_WEBSITES) { + let website = TESTED_WEBSITES[current]; + // backup the current the registry value if it exists and replace the existing value/create a + // new value with the encrypted data + backupAndStore(Storage2Key, website.hash, + crypto.encryptData(crypto.arrayToString(website.data), + website.uri.spec, true)); + Assert.ok(migrator.exists, "The migrator has to exist"); + uris.push(website.uri); + hashes.push(website.hash); + + await migrator._migrateURIs(uris); + logins = Services.logins.getAllLogins({}); + // check that the number of logins in the password manager has increased as expected which means + // that all the values for the current website were imported + loginCount += website.logins.length; + Assert.equal(logins.length, loginCount, + "The number of logins has increased after the migration"); + // NB: because telemetry records any login data passed to the login manager, it + // also gets told about logins that are duplicates or invalid (for one reason + // or another) and so its counts might exceed those of the login manager itself. + Assert.greaterOrEqual(MigrationUtils._importQuantities.logins, loginCount, + "Telemetry quantities equal or exceed the actual import."); + // Reset - this normally happens at the start of a new migration, but we're calling + // the migrator directly so can't rely on that: + MigrationUtils._importQuantities.logins = 0; + + let startIndex = loginCount - website.logins.length; + // compares the imported password manager logins with their expected logins + for (let i = 0; i < website.logins.length; i++) { + checkLoginsAreEqual(logins[startIndex + i], website.logins[i], + " " + current + " - " + i + " "); + } + } +}); diff -pruN 1:60.2.1-1/browser/components/search/test/browser_bing.js 1:60.2.1+build1-0ubuntu1/browser/components/search/test/browser_bing.js --- 1:60.2.1-1/browser/components/search/test/browser_bing.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/components/search/test/browser_bing.js 2018-10-02 14:08:34.000000000 +0000 @@ -0,0 +1,118 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * Test Bing search plugin URLs + */ + +"use strict"; + +const BROWSER_SEARCH_PREF = "browser.search."; + +function test() { + let engine = Services.search.getEngineByName("Bing"); + ok(engine, "Bing"); + + let base = "https://www.bing.com/search?q=foo&pc=MOZI"; + let url; + + // Test search URLs (including purposes). + url = engine.getSubmission("foo").uri.spec; + is(url, base + "&form=MOZSBR", "Check search URL for 'foo'"); + url = engine.getSubmission("foo", null, "contextmenu").uri.spec; + is(url, base + "&form=MOZCON", "Check context menu search URL for 'foo'"); + url = engine.getSubmission("foo", null, "keyword").uri.spec; + is(url, base + "&form=MOZLBR", "Check keyword search URL for 'foo'"); + url = engine.getSubmission("foo", null, "searchbar").uri.spec; + is(url, base + "&form=MOZSBR", "Check search bar search URL for 'foo'"); + url = engine.getSubmission("foo", null, "homepage").uri.spec; + is(url, base + "&form=MOZSPG", "Check homepage search URL for 'foo'"); + url = engine.getSubmission("foo", null, "newtab").uri.spec; + is(url, base + "&form=MOZTSB", "Check newtab search URL for 'foo'"); + + // Check search suggestion URL. + url = engine.getSubmission("foo", "application/x-suggestions+json").uri.spec; + is(url, "https://www.bing.com/osjson.aspx?query=foo&form=OSDJAS&language=" + getLocale(), "Check search suggestion URL for 'foo'"); + + // Check all other engine properties. + const EXPECTED_ENGINE = { + name: "Bing", + alias: null, + description: "Bing. Search by Microsoft.", + searchForm: "https://www.bing.com/search?q=&pc=MOZI&form=MOZSBR", + hidden: false, + wrappedJSObject: { + queryCharset: "UTF-8", + "_iconURL": "data:image/x-icon;base64,AAABAAIAICAAAAEACACoCAAAJgAAABAQAAABAAgAaAUAAM4IAAAoAAAAIAAAAEAAAAABAAgAAAAAAIAEAAAAAAAAAAAAAAABAAAAAAAAhIQMAI+PIwCXlzEAn59BAKioUwCurl8AtbVuAL6+fwDJyZMA0tKlANjYsgDe3r4A5eXMAOzs2QDy8uUA+fnzAP///wAAGi8AAC1QAAA/cAAAUZAAAGOwAAB2zwAAiPAAEZj/ADGm/wBRs/8AccH/AJHP/wCx3f8A0ev/AP///wAAAAAAACwvAABLUAAAaHAAAIaQAAClsAAAw88AAOHwABHv/wAx8f8AUfP/AHH1/wCR9/8Asfn/ANH7/wD///8AAAAAAAAvIQAAUDcAAHBMAACQYwAAsHkAAM+PAADwpgAR/7QAMf++AFH/yABx/9MAkf/cALH/5QDR//AA////AAAAAAAALw4AAFAYAABwIgAAkCwAALA2AADPQAAA8EoAEf9bADH/cQBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAGcAAACJAAAAqwAAALzwAADvAAACD/EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAiUAAAMHAAAD2QAABMsAAAWc8AAGfwAAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAmLwAAQFAAAFpwAAB0kAAAjrAAAKnPAADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAAAAAALyYAAFBBAABwWwAAkHQAALCOAADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD///8AAAAAAC8UAABQIgAAcDAAAJA+AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/5dEA////AAAAAAAvAwAAUAQAAHAGAACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/trEA/9TRAP///wAAAAAALwAOAFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/kbIA/7HIAP/R3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/cdEA/5HcAP+x5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0Uf8A9nH/APeR/wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCmMf8AtFH/AMJx/wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+Ef8AWDH/AHFR/wCMcf8AppH/AL+x/wDa0f8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBggCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAsQEA0HAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwkPEBAQEBALBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEMEBAQEBAQEBAPCQMAAAAAAAAAAAAAAAAAAAAAAAAAAQ0QEBAQEBAQEBAQDQgBAAAAAAAAAAAAAAAAAAAAAAABDRAQEBAQEBAQEBAQEA0GAQAAAAAAAAAAAAAAAAAAAAENEBAQDgcLEBAQEBAQEBALBAAAAAAAAAAAAAAAAAAAAQ0QEBANAQEHDRAQEBAQEBAOCAAAAAAAAAAAAAAAAAABDRAQEA4BAAACCA4QEBAQEBANAQAAAAAAAAAAAAAAAAENEBAQDgEAAAAABAsQEBAQEA0BAAAAAAAAAAAAAAAAAQ0QEBAOAQAAAAABBw4QEBAQDQEAAAAAAAAAAAAAAAABDRAQEA4BAAABBw0QEBAQEBANAQAAAAAAAAAAAAAAAAENEBAQDgEAAAcQEBAQEBAQEA0BAAAAAAAAAAAAAAAAAQ0QEBAOAQABCxAQEBAQEBANBwAAAAAAAAAAAAAAAAABDRAQEA4BAAQPEBAQEA0IBAEAAAAAAAAAAAAAAAAAAAENEBAQDgEACRAQDQkGAQAAAAAAAAAAAAAAAAAAAAAAAQ0QEBAOAQILCgYCAAAAAAAAAAAAAAAAAAAAAAAAAAABDRAQEA4BAQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENEBAQDgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ0QEBAOAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRAQEA4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENEBAQDgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ0QEBAOAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRAQEA0BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENEA0IBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAEAAAAAAACEhAAAjIwAAJKSFgCZmSgAqqpRALKyYgC+vnsAxsaKAM3NmQDU1KgA4ODBAOjozwDw8OEA+fnyAP///wD///8AAAAAAAAaLwAALVAAAD9wAABRkAAAY7AAAHbPAACI8AARmP8AMab/AFGz/wBxwf8Akc//ALHd/wDR6/8A////AAAAAAAALC8AAEtQAABocAAAhpAAAKWwAADDzwAA4fAAEe//ADHx/wBR8/8AcfX/AJH3/wCx+f8A0fv/AP///wAAAAAAAC8hAABQNwAAcEwAAJBjAACweQAAz48AAPCmABH/tAAx/74AUf/IAHH/0wCR/9wAsf/lANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAAsDYAAM9AAADwSgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQAACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBbAACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAiAABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMAAAAAAAAAAAAAAAACBgwMBwIAAAAAAAAAAAAABg4ODg4MBgIAAAAAAAAAAAYODQoODg4KBAAAAAAAAAAGDgwDBQsODg4FAAAAAAAABg4MAgADCg4OBgAAAAAAAAYODAICCg4ODgYAAAAAAAAGDgwCBg4OCwcCAAAAAAAABg4MAwkIBAIAAAAAAAAAAAYODAICAAAAAAAAAAAAAAAGDgwCAAAAAAAAAAAAAAAABg4MAgAAAAAAAAAAAAAAAAYMCAEAAAAAAAAAAAAAAAACAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + _urls: [ + { + type: "application/x-suggestions+json", + method: "GET", + template: "https://www.bing.com/osjson.aspx", + params: [ + { + name: "query", + value: "{searchTerms}", + purpose: undefined, + }, + { + name: "form", + value: "OSDJAS", + purpose: undefined, + }, + { + name: "language", + value: "{moz:locale}", + purpose: undefined, + }, + ], + }, + { + type: "text/html", + method: "GET", + template: "https://www.bing.com/search", + params: [ + { + name: "q", + value: "{searchTerms}", + purpose: undefined, + }, + { + name: "pc", + value: "MOZI", + purpose: undefined, + }, + { + name: "form", + value: "MOZCON", + purpose: "contextmenu", + }, + { + name: "form", + value: "MOZSBR", + purpose: "searchbar", + }, + { + name: "form", + value: "MOZSPG", + purpose: "homepage", + }, + { + name: "form", + value: "MOZLBR", + purpose: "keyword", + }, + { + name: "form", + value: "MOZTSB", + purpose: "newtab", + }, + ], + mozparams: {}, + }, + ], + }, + }; + + isSubObjectOf(EXPECTED_ENGINE, engine, "Bing"); +} diff -pruN 1:60.2.1-1/browser/components/search/test/browser_ddg.js 1:60.2.1+build1-0ubuntu1/browser/components/search/test/browser_ddg.js --- 1:60.2.1-1/browser/components/search/test/browser_ddg.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/components/search/test/browser_ddg.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,108 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * Test DuckDuckGo search plugin URLs + */ + +"use strict"; + +const BROWSER_SEARCH_PREF = "browser.search."; + +function test() { + let engine = Services.search.getEngineByName("DuckDuckGo"); + ok(engine, "DuckDuckGo"); + + let base = "https://duckduckgo.com/?q=foo"; + let url; + + // Test search URLs (including purposes). + url = engine.getSubmission("foo").uri.spec; + is(url, base + "&t=ffsb", "Check search URL for 'foo'"); + url = engine.getSubmission("foo", null, "contextmenu").uri.spec; + is(url, base + "&t=ffcm", "Check context menu search URL for 'foo'"); + url = engine.getSubmission("foo", null, "keyword").uri.spec; + is(url, base + "&t=ffab", "Check keyword search URL for 'foo'"); + url = engine.getSubmission("foo", null, "searchbar").uri.spec; + is(url, base + "&t=ffsb", "Check search bar search URL for 'foo'"); + url = engine.getSubmission("foo", null, "homepage").uri.spec; + is(url, base + "&t=ffhp", "Check homepage search URL for 'foo'"); + url = engine.getSubmission("foo", null, "newtab").uri.spec; + is(url, base + "&t=ffnt", "Check newtab search URL for 'foo'"); + + // Check search suggestion URL. + url = engine.getSubmission("foo", "application/x-suggestions+json").uri.spec; + is(url, "https://ac.duckduckgo.com/ac/?q=foo&type=list", "Check search suggestion URL for 'foo'"); + + // Check all other engine properties. + const EXPECTED_ENGINE = { + name: "DuckDuckGo", + alias: null, + description: "Search DuckDuckGo", + searchForm: "https://duckduckgo.com/?q=&t=ffsb", + hidden: false, + wrappedJSObject: { + queryCharset: "UTF-8", + "_iconURL": "data:image/icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAATCwAAEwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA11RgALs6oACbQ9wAj0v8AI9L/ACfQ9wAu0agANdUYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzzN4CNdL/oK/z//////////////////////+jsPv/BDXX/wAz0t4AAAAAAAAAAAAAAAAAAAAAAAAAAAAyzvNSduD//////8jK/v+P+Lf/IbQL/17RPP+J3Y//wOKX//////9YeuX/ADLO8wAAAAAAAAAAAAAAAAAw091piOX/8/X9/1Fx5P9xhu//WOWZ/0W9Lv9Lwjn/J8BB/xyDAP9bdfL/9fP//2mI5v8AMNPdAAAAAAc610YRQ9f//////0Zr4P8AGdD/sb32////////////wrv//wAh1/8MPab/ACPc/05r4///////EkPX/wc610YANtWkrr/y/6S48P8AJ9L/AB3R/+/w/v///////////3+D7f8AQeL/AYTw/wFr5/8AMNb/p7Tv/6698v8AM9WkADLW//////8yXt//AC3V/wAw1/////////////z///8A0P7/AKb1/wWI7P8AuPf/AJ3w/zZW3P//////ADHV/wAx2P//////AzrZ/wAu1/84ZOL////////////e////AND//wC1+f8Atff/AZbv/wY62f8ELNf//////wAw1/8AMtn//////wAw2f8ALNn/kKrz////+//cwbH////////////R////Rcb8/wDO/f8A/P//AHzo//////8AMNj/ADXa//////8vXuL/ACna/4yq9///79T/jUkg/9i+r///////r2Q0/7Cozv8BKdr/AirY/zdZ4P//////ADTa/wI72tOuv/T/prr0/wAl2v+JqPb//7yW/+bUxv/9+/n////u//W+n/+Op/L/ADPd/wAv2v+ru/T/r7/0/wI72tMLQd1DEEjg//////9Cbef/ADng///////////////////////R3///AC3g/wAy3v9SeOn//////xFI4P8LQd1DAAAAAAM64PNmiuz/9/j//2mN7f/m7P3///////////9Cb+n/ACXd/wAt3v9rju3//////2iL7P8DOuDzAAAAAAAAAAAAAAAAAT3g/0p16f//////3OT8/3OS7v8AKt3/ACPc/zhn5/+xw/b//////0956v8CPeD/AAAAAAAAAAAAAAAAAAAAAAAAAAAEPODzBUDh/5uz8//7/f7/////////////////prz0/wtF4v8FQeDzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtF5kYDQOOkADrj/wA44v8AOeP/ADzk/wVB46QPReZGAAAAAAAAAAAAAAAAAAAAAPAPAADgBwAAwAMAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAADAAwAA4AcAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAATCwAAEwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChIzyAnRNFwJ0TQryND0d8nRNH/J0TR/ydE0f8nRNH/I0PR3ydE0K8nRNFwKEjPIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChE00AlRdK/J0XS/ydF0v8nRdL/XXPd/11z3f94i+P/k6Lp/5Oi6f9rf+D/NVDV/ydF0v8nRdL/JUXSvyhE00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBAzxAnRNOvJ0XT/ydF0/8lRdK/KEXSYOvu+6/+/v6//v7+v/39/c////////////7+/r/J0fOAKEXSYCVF0r8nRdP/J0XT/ydE068gQM8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlRdUwJ0bT7ydG0/8nRtHPKETTQAAAAADHx8dA2vHhn5TYpN/o9+z/////////////////8PL83ydG0o8lRdUwAAAAAChE00AnRtHPJ0bT/ydG0+8lRdUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKEXVYCdG1P8nRtT/KEbTgAAAAAAmRtZQI0PU38jIyP/F6s//Rrtk/0a7ZP9/yIr/c796/4vLkv+JpNf/M3Kq/zyWh/8zeKTfJkbWUAAAAAAoRtOAJ0bU/ydG1P8oRdVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVF1TAnR9X/J0fV/yhF1WAgQM8QJ0fTrydH1f9CW8//2tra/6Pdsv9Gu2T/Rrtk/0WzWv9Gu2T/Rrtk/0a7ZP9Gu2T/Rrtk/z6egP8nR9X/J0fTryBAzxAoRdVgJ0fV/ydH1f8lRdUwAAAAAAAAAAAAAAAAAAAAAAAAAAAgQM8QJ0fV7ydH1f8oSNVgIEDPECdH1c8nR9X/J0fV/1xwyf/t7e3/o92y/0a7ZP9Gu2T/Ra5U/0a7ZP9Gu2T/Rrtk/0a7ZP9Gu2T/Pp6A/ydH1f8nR9X/J0fVzyBAzxAoSNVgJ0fV/ydH1e8gQM8QAAAAAAAAAAAAAAAAAAAAACdH1q8nR9b/KEjVgCBQzxAnR9bPJ0fW/ydH1v8nR9b/gIzB//r6+v+j3bL/Rrtk/13Ed/+i26//ruG7/z6egf8+noH/Rrtk/0a7ZP86kI//J0fW/ydH1v8nR9b/J0fWzyBQzxAoSNWAJ0fW/ydH1q8AAAAAAAAAAAAAAAAoSNdAJkjW/yZH1s8AAAAAJEfWryZI1v8mSNb/JkjW/yZI1v+jqsT//////+j37P/R7tj////////////W3ff/JkjW/yZI1v8uZbr/PJeI/zJzrP8mSNb/JkjW/yZI1v8mSNb/JEfWrwAAAAAmR9bPJkjW/yhI10AAAAAAAAAAACVI1r8mSNf/KEjXQCZJ1lAmSNf/JkjX/yZI1/8mSNf/JkjX/9HR0f///////////////////////////5Ok6/8mSNf/JkjX/yZI1/8mSNf/JkjX/yZI1/8mSNf/JkjX/yZI1/8mSNf/JknWUChI10AmSNf/JUjWvwAAAAAoSNcgJknY/yZH2M8AAAAAI0nY3yZJ2P8mSdj/JknY/yZJ2P9KZM//39/f////////////////////////////XHfi/yZJ2P8mSdj/JknY/yZJ2P8mSdj/JknY/yZJ2P8mSdj/JknY/yZJ2P8jSdjfAAAAACZH2M8mSdj/KEjXICdJ2HAmSdj/JUjXYCVK2jAmSdj/JknY/yZJ2P8mSdj/JknY/2V4yf/t7e3///////////////////////////9cd+L/HXTj/xSf7/8Nwfj/CdL8/wnS/P8J0vz/ELDz/xt85v8mSdj/JknY/yZJ2P8lStowJUjXYCZJ2P8nSdhwJErZryZK2f8oSNcgJUnajyZK2f8mStn/JkrZ/yZK2f8mStn/iJPA////////////////////////////0ff+/xjV/P8J0vz/Drn1/xiO6/8Yjuv/GI7r/xCw8/8Lyvr/CdL8/xmF6P8mStn/JkrZ/yVJ2o8oSNcgJkrZ/yRK2a8jStrfI0rZ3wAAAAAlSdq/Jkra/yZK2v8mStr/Jkra/yZK2v+xtsf///////////////////////////8o2Pz/CdL8/wvK+v8mStr/Jkra/yZK2v8mStr/Jkra/yZK2v8iW97/Jkra/yZK2v8mStr/JUnavwAAAAAjStnfI0ra3yZK2v8lSdq/AAAAACZH2O8mStr/Jkra/yZK2v8mStr/L1HY/9HR0f///////////////////////////yjY/P8J0vz/CdL8/xCw9P8QsPT/ELD0/xSf7/8ddeX/Jkra/yZK2v8mStr/Jkra/yZK2v8mR9jvAAAAACVJ2r8mStr/Jkvb/yVJ2r8AAAAAJkvb/yZL2/8mS9v/Jkvb/yZL2/9KZtL/4+Pj////////////////////////////4Pn//0fd/f8J0vz/CdL8/wnS/P8J0vz/CdL8/wnS/P8Lyvr/Fpfu/yJc3/8mS9v/Jkvb/yZL2/8AAAAAJUnavyZL2/8mS9z/JUncvwAAAAAmS9z/Jkvc/yZL3P8mS9z/Jkvc/26AyP/x8fH//////////////////////////////////////9H3/v/C9P7/o+7+/2fa+/8Oufb/CdL8/wnS/P8J0vz/CdL8/xiP7P8mS9z/Jkvc/wAAAAAlSdy/Jkvc/yZM3P8lTNy/AAAAACZJ2e8mTNz/Jkzc/yZM3P8mTNz/iJTB////////////qnth/5VaOf/x6eX///////////////////////Hp5f/x6eX/ydL2/yZM3P8kVN7/G37o/xKo8v8QsfT/HXbm/yZM3P8mSdnvAAAAACVM3L8mTNz/I0vc3yZJ2u8AAAAAJUzevyZM3f8mTN3/Jkzd/yZM3f+fqc3///////////+VWjn/v5yI/+re1///////////////////////jk8s/7iRe//J0vb/Jkzd/yZM3f8mTN3/Jkzd/yZM3f8mTN3/Jkzd/yVM3r8AAAAAI0vc3yNL3N8kTd2vJk3d/yhQ3yAlTd2PJk3d/yZN3f8mTd3/Jk3d/6St0v////////////Hp5f/q3tf///////////////////////////+xhm7/49PK/6Cx8P8mTd3/Jk3d/yZN3f8mTd3/Jk3d/yZN3f8mTd3/JU3djyhQ3yAmTd3/JE3drydN33AmTd7/J03fcCVK3zAmTd7/Jk3e/yZN3v8mTd7/pK7S///////Sp5r/////////////////////////////////////////////////T27k/yZN3v8mTd7/Jk3e/yZN3v8mTd7/Jk3e/yZN3v8lSt8wJ03fcCZN3v8nTd9wKFDfICZO3/8mTt3PAAAAACVN3r8mTt//Jk7f/yZO3/+EltX//////+fRyv/SqaD/59LO///////////////////////at63/vIBy/7Glxf8mTt//Jk7f/yZO3/8mTt//Jk7f/yZO3/8mTt//JU3evwAAAAAmTt3PJk7f/yhQ3yAAAAAAJE/dryZO3/8oUN9AKFDfQCZO3/8mTt//Jk7f/zhb2v/o6/T/////////////////////////////////////////////////XHrn/yZO3/8mTt//Jk7f/yZO3/8mTt//Jk7f/yZO3/8oUN9AKFDfQCZO3/8kT92vAAAAAAAAAAAoUN9AJk7g/yZO4M8AAAAAJk/hnyZO4P8mTuD/Jk7g/05v5v/k6fv//////////////////////////////////////3eR7P8mTuD/Jk7g/yZO4P8mTuD/Jk7g/yZO4P8mTuD/Jk/hnwAAAAAmTuDPJk7g/yhQ30AAAAAAAAAAAAAAAAAjT+GfJU/h/yVO4Y8gUN8QIk7gzyVP4f8lT+H/SWnW/0lp1v+bq+H/8fHx/////////////////6Cy8v9OcOb/JU/h/yVP4f8lT+H/JU/h/yVP4f8lT+H/JU/h/yJO4M8gUN8QJU7hjyVP4f8jT+GfAAAAAAAAAAAAAAAAAAAAACBQ3xAlTOHvJU/h/yVQ4mAgUN8QIk7hzyVP4f+ktOv///////////////////////H0/f9phur/JU/h/yVP4f8lT+H/JU/h/yVP4f8lT+H/JU/h/yVP4f8iTuHPIFDfECVQ4mAlT+H/JUzh7yBQ3xAAAAAAAAAAAAAAAAAAAAAAAAAAACVQ3zAlUOLvJVDi/yVQ4mAgUN8QI1Din4mb2//J0/j/ydP4/6299P93ku3/M1vk/yVQ4v8lUOL/JVDi/yVQ4v8lUOL/JVDi/yVQ4v8lUOL/I1DinyBQ3xAlUOJgJVDi/yVQ4u8lUN8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVQ5DAlUOLvJVDi/yVQ4o8AAAAAJFDjQCVQ4r8lUOL/JVDi/yVQ4v8lUOL/JVDi/yVQ4v8lUOL/JVDi/yVQ4v8lUOL/JVDivyRQ40AAAAAAJVDijyVQ4v8lUOLvJVDkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVQ5DAjUeTfJVHj/yNR5N8kUONAAAAAACVQ5DAmUuOAJVHivyNR5N8lUeP/JVHj/yNR5N8lUeK/JlLjgCVQ5DAAAAAAJFDjQCNR5N8lUeP/I1Hk3yVQ5DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBQ3xAjUuSfJVHk/yVR5P8jUeTfJFLkcChQ5yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoUOcgJFLkcCNR5N8lUeT/JVHk/yNS5J8gUN8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkUONAI1LknyVS5P8lUuT/JVLk/yVS5O8lUeS/JVHkvyVR5L8lUeS/JVLk7yVS5P8lUuT/JVLk/yRS468kUONAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFDfECVS5GAjUuWfIlPlzyVS5f8lUuX/JVLl/yVS5f8iU+XPI1LlnyVS5GAgUN8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/AA///AAD//AAAP/ggBB/wgAEP4AAAB8AAAAPAAAADiAAAEYAAAAEQAAAIAAAAAAAAAAAgAAAEIAAABCAAAAQgAAAEIAAABCAAAAQAAAAAAAAAABAAAAiAAAABiAAAEcAAAAPAAAAD4AAAB/CAAQ/4IAQf/AfgP/8AAP//wAP/", + _urls: [ + { + type: "text/html", + method: "GET", + template: "https://duckduckgo.com/", + params: [ + { + name: "q", + value: "{searchTerms}", + purpose: undefined, + }, + { + name: "t", + value: "ffcm", + purpose: "contextmenu", + }, + { + name: "t", + value: "ffab", + purpose: "keyword", + }, + { + name: "t", + value: "ffsb", + purpose: "searchbar", + }, + { + name: "t", + value: "ffhp", + purpose: "homepage", + }, + { + name: "t", + value: "ffnt", + purpose: "newtab", + }, + ], + mozparams: {}, + }, + { + type: "application/x-suggestions+json", + method: "GET", + template: "https://ac.duckduckgo.com/ac/", + params: [ + { + name: "q", + value: "{searchTerms}", + purpose: undefined, + }, + { + name: "type", + value: "list", + purpose: undefined, + }, + ], + }, + ], + }, + }; + + isSubObjectOf(EXPECTED_ENGINE, engine, "DuckDuckGo"); +} diff -pruN 1:60.2.1-1/browser/components/search/test/browser_google.js 1:60.2.1+build1-0ubuntu1/browser/components/search/test/browser_google.js --- 1:60.2.1-1/browser/components/search/test/browser_google.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/components/search/test/browser_google.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,117 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * Test Google search plugin URLs + */ + +"use strict"; + +let expectedEngine = { + name: "Google", + alias: null, + description: "Google Search", + searchForm: "https://www.google.com/search?q=&ie=utf-8&oe=utf-8", + hidden: false, + wrappedJSObject: { + queryCharset: "UTF-8", + "_iconURL": "data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///zD9/f2W/f392P39/fn9/f35/f391/39/ZT+/v4uAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7+Cf39/Zn///////////////////////////////////////////39/ZX///8IAAAAAAAAAAAAAAAA/v7+Cf39/cH/////+v35/7TZp/92ul3/WKs6/1iqOv9yuFn/rNWd//j79v///////f39v////wgAAAAAAAAAAP39/Zn/////7PXp/3G3WP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP+Or1j//vDo///////9/f2VAAAAAP///zD/////+vz5/3G3V/9TqDT/WKo6/6LQkf/U6cz/1urO/6rUm/+Zo0r/8IZB//adZ////v7///////7+/i79/f2Y/////4nWzf9Lqkj/Vqo4/9Xqzv///////////////////////ebY//SHRv/0hUL//NjD///////9/f2U/f392v////8sxPH/Ebzt/43RsP/////////////////////////////////4roL/9IVC//i1jf///////f391/39/fr/////Cr37/wW8+/+16/7/////////////////9IVC//SFQv/0hUL/9IVC//SFQv/3pnX///////39/fn9/f36/////wu++/8FvPv/tuz+//////////////////SFQv/0hUL/9IVC//SFQv/0hUL/96p7///////9/f35/f392/////81yfz/CrL5/2uk9v///////////////////////////////////////////////////////f392P39/Zn/////ks/7/zdS7P84Rur/0NT6///////////////////////9/f////////////////////////39/Zb+/v4y//////n5/v9WYu3/NUPq/ztJ6/+VnPT/z9L6/9HU+v+WnfT/Ul7t/+Hj/P////////////////////8wAAAAAP39/Z3/////6Or9/1hj7v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v9sdvD////////////9/f2YAAAAAAAAAAD///8K/f39w//////5+f7/paz2/11p7v88Suv/Okfq/1pm7v+iqfX/+fn+///////9/f3B/v7+CQAAAAAAAAAAAAAAAP///wr9/f2d///////////////////////////////////////////9/f2Z/v7+CQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/jL9/f2Z/f392/39/fr9/f36/f392v39/Zj///8wAAAAAAAAAAAAAAAAAAAAAPAPAADAAwAAgAEAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/g3+/v5X/f39mf39/cj9/f3q/f39+f39/fn9/f3q/f39yP39/Zn+/v5W////DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/iT9/f2c/f399f/////////////////////////////////////////////////////9/f31/f39mv7+/iMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/gn9/f2K/f39+////////////////////////////////////////////////////////////////////////////f39+v39/Yf///8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+/v4k/f390v////////////////////////////////////////////////////////////////////////////////////////////////39/dD///8iAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////MP39/er//////////////////////////+r05v+v16H/gsBs/2WxSf9Wqjj/Vqk3/2OwRv99vWX/pdKV/97u2P////////////////////////////39/ej+/v4vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/iT9/f3q/////////////////////+v15/+Pxnv/VKk2/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/36+Z//d7tf///////////////////////39/ej///8iAAAAAAAAAAAAAAAAAAAAAAAAAAD///8K/f390//////////////////////E4bn/XKw+/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1apN/+x0pv///////////////////////39/dD///8IAAAAAAAAAAAAAAAAAAAAAP39/Yv/////////////////////sdij/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/YKU1/8qOPv/5wZ////////////////////////39/YcAAAAAAAAAAAAAAAD+/v4l/f39+////////////////8Lgt/9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9utlT/n86N/7faqv+426v/pdKV/3u8ZP9UqDX/U6g0/3egN//jiUH/9IVC//SFQv/82MP//////////////////f39+v7+/iMAAAAAAAAAAP39/Z3////////////////q9Ob/W6w+/1OoNP9TqDT/U6g0/1OoNP9nskz/zOXC/////////////////////////////////+Dv2v+osWP/8YVC//SFQv/0hUL/9IVC//WQVP/++fb//////////////////f39mgAAAAD+/v4O/f399v///////////////4LHj/9TqDT/U6g0/1OoNP9TqDT/dblc//L58P/////////////////////////////////////////////8+v/3p3f/9IVC//SFQv/0hUL/9IVC//rIqf/////////////////9/f31////DP7+/ln////////////////f9v7/Cbz2/zOwhv9TqDT/U6g0/2KwRv/v9+z///////////////////////////////////////////////////////738//1kFT/9IVC//SFQv/0hUL/9plg///////////////////////+/v5W/f39nP///////////////4jf/f8FvPv/Bbz7/yG1s/9QqDz/vN2w//////////////////////////////////////////////////////////////////rHqP/0hUL/9IVC//SFQv/0hUL//vDn//////////////////39/Zn9/f3L////////////////R878/wW8+/8FvPv/Bbz7/y7C5P/7/fr//////////////////////////////////////////////////////////////////ere//SFQv/0hUL/9IVC//SFQv/718H//////////////////f39yP39/ez///////////////8cwvv/Bbz7/wW8+/8FvPv/WNL8///////////////////////////////////////0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//rIqv/////////////////9/f3q/f39+v///////////////we9+/8FvPv/Bbz7/wW8+/993P3///////////////////////////////////////SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/+cGf//////////////////39/fn9/f36////////////////B737/wW8+/8FvPv/Bbz7/33c/f//////////////////////////////////////9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/6xaX//////////////////f39+f39/e3///////////////8cwvv/Bbz7/wW8+/8FvPv/WdP8///////////////////////////////////////0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//vVv//////////////////9/f3q/f39y////////////////0bN/P8FvPv/Bbz7/wW8+/8hrvn/+/v///////////////////////////////////////////////////////////////////////////////////////////////////////////////////39/cj9/f2c////////////////ht/9/wW8+/8FvPv/FZP1/zRJ6/+zuPf//////////////////////////////////////////////////////////////////////////////////////////////////////////////////f39mf7+/lr////////////////d9v7/B7n7/yB38f81Q+r/NUPq/0hV7P/u8P3////////////////////////////////////////////////////////////////////////////////////////////////////////////+/v5X////D/39/ff///////////////9tkPT/NUPq/zVD6v81Q+r/NUPq/2Fs7//y8v7////////////////////////////////////////////09f7//////////////////////////////////////////////////f399f7+/g0AAAAA/f39n////////////////+Tm/P89Suv/NUPq/zVD6v81Q+r/NUPq/1Bc7f/IzPn/////////////////////////////////x8v5/0xY7P+MlPP////////////////////////////////////////////9/f2cAAAAAAAAAAD+/v4n/f39/P///////////////7W69/81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v9ZZe7/k5v0/6609/+vtff/lJv0/1pm7v81Q+r/NUPq/zVD6v+GjvL//v7//////////////////////////////f39+/7+/iQAAAAAAAAAAAAAAAD9/f2N/////////////////////6Cn9f81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v+BivL////////////////////////////9/f2KAAAAAAAAAAAAAAAAAAAAAP7+/gv9/f3V/////////////////////7W69/8+S+v/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/P0zr/7q/+P///////////////////////f390v7+/gkAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/ib9/f3r/////////////////////+Xn/P94gfH/NkTq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NkTq/3Z/8f/l5/z///////////////////////39/er+/v4kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/jL9/f3r///////////////////////////k5vz/nqX1/2p08P9IVez/OEbq/zdF6v9GU+z/aHLv/5qh9f/i5Pz////////////////////////////9/f3q////MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/ib9/f3V/////////////////////////////////////////////////////////////////////////////////////////////////f390v7+/iQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wr9/f2N/f39/P///////////////////////////////////////////////////////////////////////////f39+/39/Yv+/v4JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+/v4n/f39n/39/ff//////////////////////////////////////////////////////f399v39/Z3+/v4lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7+Dv7+/lr9/f2c/f39y/39/e39/f36/f39+v39/ez9/f3L/f39nP7+/ln+/v4OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/AA///AAD//AAAP/gAAB/wAAAP4AAAB8AAAAPAAAADgAAAAYAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAAAAcAAAAPAAAAD4AAAB/AAAA/4AAAf/AAAP/8AAP//wAP/", + _urls: [ + { + type: "application/x-suggestions+json", + method: "GET", + template: "https://www.google.com/complete/search?client=firefox&q={searchTerms}", + params: "", + }, + { + type: "text/html", + method: "GET", + template: "https://www.google.com/search", + params: [ + { + "name": "q", + "value": "{searchTerms}", + "purpose": undefined, + }, + { + "name": "ie", + "value": "utf-8", + "purpose": undefined, + }, + { + "name": "oe", + "value": "utf-8", + "purpose": undefined, + }, + ], + mozparams: { + }, + }, + ], + }, +}; + +function test() { + let engine = Services.search.getEngineByName("Google"); + ok(engine, "Found Google search engine"); + + let countryCode = Services.prefs.getCharPref("browser.search.countryCode"); + let code = ""; + switch (countryCode) { + case "US": + code = "firefox-b-1"; + break; + case "DE": + code = "firefox-b"; + break; + case "RU": + // Covered by test but doesn't use a code + break; + } + + let base = "https://www.google.com/search?q=foo&ie=utf-8&oe=utf-8"; + // Keyword uses a slightly different code + let keywordBase = base; + if (code) { + let suffix = `&client=${code}`; + base += suffix; + keywordBase += `${suffix}-ab`; + expectedEngine.searchForm += suffix; + let urlParams = expectedEngine.wrappedJSObject._urls[1].params; + urlParams.push({ + name: "client", + value: `${code}-ab`, + purpose: "keyword", + }); + urlParams.push({ + name: "client", + value: code, + purpose: "searchbar", + }); + } + + let url; + + // Test search URLs (including purposes). + let purposes = ["", "contextmenu", "searchbar", "homepage", "newtab"]; + for (let purpose of purposes) { + url = engine.getSubmission("foo", null, purpose).uri.spec; + is(url, base, `Check ${purpose} search URL for 'foo'`); + } + url = engine.getSubmission("foo", null, "keyword").uri.spec; + is(url, keywordBase, "Check keyword search URL for 'foo'"); + + // Check search suggestion URL. + url = engine.getSubmission("foo", "application/x-suggestions+json").uri.spec; + is(url, "https://www.google.com/complete/search?client=firefox&q=foo", "Check search suggestion URL for 'foo'"); + + // Check result parsing and alternate domains. + let alternateBase = base.replace("www.google.com", "www.google.fr"); + is(Services.search.parseSubmissionURL(base).terms, "foo", + "Check result parsing"); + is(Services.search.parseSubmissionURL(alternateBase).terms, "foo", + "Check alternate domain"); + + // Check all other engine properties. + isSubObjectOf(expectedEngine, engine, "Google"); +} diff -pruN 1:60.2.1-1/browser/components/translation/cld2/cld-worker.js 1:60.2.1+build1-0ubuntu1/browser/components/translation/cld2/cld-worker.js --- 1:60.2.1-1/browser/components/translation/cld2/cld-worker.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/components/translation/cld2/cld-worker.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,86 @@ +'use strict';var c;c||(c=eval("(function() { try { return Module || {} } catch(e) { return {} } })()"));var aa={},g;for(g in c)c.hasOwnProperty(g)&&(aa[g]=c[g]);var ba=!1,k=!1,m=!1,ca=!1; +if(c.ENVIRONMENT)if("WEB"===c.ENVIRONMENT)ba=!0;else if("WORKER"===c.ENVIRONMENT)k=!0;else if("NODE"===c.ENVIRONMENT)m=!0;else if("SHELL"===c.ENVIRONMENT)ca=!0;else throw Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");else ba="object"===typeof window,k="function"===typeof importScripts,m="object"===typeof process&&"function"===typeof require&&!ba&&!k,ca=!ba&&!m&&!k; +if(m){c.print||(c.print=console.log);c.printErr||(c.printErr=console.warn);var da,ea;c.read=function(a,b){da||(da=require("fs"));ea||(ea=require("path"));a=ea.normalize(a);var d=da.readFileSync(a);d||a==ea.resolve(a)||(a=path.join(__dirname,"..","src",a),d=da.readFileSync(a));d&&!b&&(d=d.toString());return d};c.readBinary=function(a){a=c.read(a,!0);a.buffer||(a=new Uint8Array(a));assert(a.buffer);return a};c.load=function(a){fa(read(a))};c.thisProgram||(c.thisProgram=1 0) var gc = undefined");else if(ba||k)c.read=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},c.readAsync=function(a,b,d){var e=new XMLHttpRequest;e.open("GET",a,!0);e.responseType="arraybuffer";e.onload=function(){200== +e.status||0==e.status&&e.response?b(e.response):d()};e.onerror=d;e.send(null)},"undefined"!=typeof arguments&&(c.arguments=arguments),"undefined"!==typeof console?(c.print||(c.print=function(a){console.log(a)}),c.printErr||(c.printErr=function(a){console.warn(a)})):c.print||(c.print=function(){}),k&&(c.load=importScripts),"undefined"===typeof c.setWindowTitle&&(c.setWindowTitle=function(a){document.title=a});else throw"Unknown runtime environment. Where are we?";function fa(a){eval.call(null,a)} +!c.load&&c.read&&(c.load=function(a){fa(c.read(a))});c.print||(c.print=function(){});c.printErr||(c.printErr=c.print);c.arguments||(c.arguments=[]);c.thisProgram||(c.thisProgram="./this.program");c.print=c.print;c.u=c.printErr;c.preRun=[];c.postRun=[];for(g in aa)aa.hasOwnProperty(g)&&(c[g]=aa[g]); +var aa=void 0,t={V:function(a){tempRet0=a},R:function(){return tempRet0},w:function(){return p},o:function(a){p=a},H:function(a){switch(a){case "i1":case "i8":return 1;case "i16":return 2;case "i32":return 4;case "i64":return 8;case "float":return 4;case "double":return 8;default:return"*"===a[a.length-1]?t.q:"i"===a[0]?(a=parseInt(a.substr(1)),assert(0===a%8),a/8):0}},O:function(a){return Math.max(t.H(a),t.q)},W:16,la:function(a,b){"double"===b||"i64"===b?a&7&&(assert(4===(a&7)),a+=4):assert(0=== +(a&3));return a},ea:function(a,b,d){return d||"i64"!=a&&"double"!=a?a?Math.min(b||(a?t.O(a):0),t.q):Math.min(b,8):8},h:function(a,b,d){return d&&d.length?(d.splice||(d=Array.prototype.slice.call(d)),d.splice(0,0,b),c["dynCall_"+a].apply(null,d)):c["dynCall_"+a].call(null,b)},l:[],K:function(a){for(var b=0;b=w&&!ga()?(v=b,0):b},F:function(a, +b){return Math.ceil(a/(b?b:16))*(b?b:16)},ka:function(a,b,d){return d?+(a>>>0)+4294967296*+(b>>>0):+(a>>>0)+4294967296*+(b|0)},C:8,q:4,X:0};c.Runtime=t;t.addFunction=t.K;t.removeFunction=t.U;var ia=!1;function assert(a,b){a||y("Assertion failed: "+b)}function ja(a){var b=c["_"+a];if(!b)try{b=eval("_"+a)}catch(d){}assert(b,"Cannot call unknown function "+a+" (perhaps LLVM optimizations or closure removed it?)");return b}var ka,la; +(function(){function a(a){a=a.toString().match(f).slice(1);return{arguments:a[0],body:a[1],returnValue:a[2]}}function b(){if(!l){l={};for(var b in d)d.hasOwnProperty(b)&&(l[b]=a(d[b]))}}var d={stackSave:function(){t.w()},stackRestore:function(){t.o()},arrayToC:function(a){var b=t.n(a.length);ma(a,b);return b},stringToC:function(a){var b=0;null!==a&&void 0!==a&&0!==a&&(b=t.n((a.length<<2)+1),na(a,b));return b}},e={string:d.stringToC,array:d.arrayToC};la=function(a,b,d,f,l){a=ja(a);var O=[],P=0;if(f)for(var x= +0;x>0]=b;break;case "i8":B[a>>0]=b;break;case "i16":pa[a>>1]=b;break;case "i32":C[a>>2]=b;break;case "i64":tempI64=[b>>>0,(tempDouble=b,1<=+qa(tempDouble)?0>>0:~~+ta((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)];C[a>>2]=tempI64[0];C[a+4>>2]=tempI64[1];break;case "float":ua[a>>2]=b;break;case "double":va[a>>3]=b;break;default:y("invalid type for setValue: "+ +d)}}c.setValue=oa;function wa(a,b){b=b||"i8";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":return B[a>>0];case "i8":return B[a>>0];case "i16":return pa[a>>1];case "i32":return C[a>>2];case "i64":return C[a>>2];case "float":return ua[a>>2];case "double":return va[a>>3];default:y("invalid type for setValue: "+b)}return null}c.getValue=wa;c.ALLOC_NORMAL=0;c.ALLOC_STACK=1;c.ALLOC_STATIC=2;c.ALLOC_DYNAMIC=3;c.ALLOC_NONE=4; +function xa(a,b,d,e){var f,l;"number"===typeof a?(f=!0,l=a):(f=!1,l=a.length);var h="string"===typeof b?b:null;d=4==d?e:["function"===typeof D?D:t.A,t.n,t.A,t.d][void 0===d?2:d](Math.max(l,h?1:b.length));if(f){e=d;assert(0==(d&3));for(a=d+(l&-4);e>2]=0;for(a=d+l;e>0]=0;return d}if("i8"===h)return a.subarray||a.slice?E.set(a,d):E.set(new Uint8Array(a),d),d;e=0;for(var q,r;e>0];d|=e;if(0==e&&!b)break;f++;if(b&&f==b)break}b||(b=f);e="";if(128>d){for(;0>0];if(!d)return b;b+=String.fromCharCode(d)}};c.stringToAscii=function(a,b){return Aa(a,b,!1)}; +function Ba(a,b){for(var d,e,f,l,h,q,r="";;){d=a[b++];if(!d)return r;d&128?(e=a[b++]&63,192==(d&224)?r+=String.fromCharCode((d&31)<<6|e):(f=a[b++]&63,224==(d&240)?d=(d&15)<<12|e<<6|f:(l=a[b++]&63,240==(d&248)?d=(d&7)<<18|e<<12|f<<6|l:(h=a[b++]&63,248==(d&252)?d=(d&3)<<24|e<<18|f<<12|l<<6|h:(q=a[b++]&63,d=(d&1)<<30|e<<24|f<<18|l<<12|h<<6|q))),65536>d?r+=String.fromCharCode(d):(d-=65536,r+=String.fromCharCode(55296|d>>10,56320|d&1023)))):r+=String.fromCharCode(d)}}c.UTF8ArrayToString=Ba; +c.UTF8ToString=function(a){return Ba(E,a)}; +function Ca(a,b,d,e){if(!(0=h&&(h=65536+((h&1023)<<10)|a.charCodeAt(++l)&1023);if(127>=h){if(d>=e)break;b[d++]=h}else{if(2047>=h){if(d+1>=e)break;b[d++]=192|h>>6}else{if(65535>=h){if(d+2>=e)break;b[d++]=224|h>>12}else{if(2097151>=h){if(d+3>=e)break;b[d++]=240|h>>18}else{if(67108863>=h){if(d+4>=e)break;b[d++]=248|h>>24}else{if(d+5>=e)break;b[d++]=252|h>>30;b[d++]=128|h>>24&63}b[d++]=128|h>>18&63}b[d++]=128| +h>>12&63}b[d++]=128|h>>6&63}b[d++]=128|h&63}}b[d]=0;return d-f}c.stringToUTF8Array=Ca;c.stringToUTF8=function(a,b,d){return Ca(a,E,b,d)};function Da(a){for(var b=0,d=0;d=e&&(e=65536+((e&1023)<<10)|a.charCodeAt(++d)&1023);127>=e?++b:b=2047>=e?b+2:65535>=e?b+3:2097151>=e?b+4:67108863>=e?b+5:b+6}return b}c.lengthBytesUTF8=Da; +function Ea(){return Fa().replace(/__Z[\w\d_]+/g,function(a){var b;a:{if(c.___cxa_demangle)try{var d=D(a.length);na(a.substr(1),d);var e=D(4),f=c.___cxa_demangle(d,0,0,e);if(0===wa(e,"i32")&&f){b=z(f);break a}}catch(l){b=a;break a}finally{d&&Ga(d),e&&Ga(e),f&&Ga(f)}t.k("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");b=a}return a===b?a:a+" ["+b+"]"})} +function Fa(){var a=Error();if(!a.stack){try{throw Error(0);}catch(b){a=b}if(!a.stack)return"(no stack trace available)"}return a.stack.toString()}c.stackTrace=function(){return Ea()};function Ha(a){0=a)return!1;for(;w<=v;)if(w=a)return!1;a=c.reallocBuffer(w);if(!a)return!1;c.buffer=buffer=a;Ka();return!0}var Pa; +try{Pa=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get),Pa(new ArrayBuffer(4))}catch(Qa){Pa=function(a){return a.byteLength}}for(var Ra=c.TOTAL_STACK||8192,w=c.TOTAL_MEMORY||2097152,G=65536;GG?2*G:G+16777216;G=Math.max(G,16777216);G!==w&&(w=G);c.buffer?buffer=c.buffer:buffer=new ArrayBuffer(w);Ka();C[0]=255;if(255!==E[0]||0!==E[3])throw"Typed arrays 2 must be run on a little-endian system";c.HEAP=void 0;c.buffer=buffer; +c.HEAP8=B;c.HEAP16=pa;c.HEAP32=C;c.HEAPU8=E;c.HEAPU16=Ia;c.HEAPU32=Ja;c.HEAPF32=ua;c.HEAPF64=va;function H(a){for(;0>0]=a[d],d+=1}c.writeStringToMemory=na;function ma(a,b){for(var d=0;d>0]=a[d]}c.writeArrayToMemory=ma; +function Aa(a,b,d){for(var e=0;e>0]=a.charCodeAt(e);d||(B[b>>0]=0)}c.writeAsciiToMemory=Aa;Math.imul&&-5===Math.imul(4294967295,5)||(Math.imul=function(a,b){var d=a&65535,e=b&65535;return d*e+((a>>>16)*e+d*(b>>>16)<<16)|0});Math.ia=Math.imul;Math.clz32||(Math.clz32=function(a){a=a>>>0;for(var b=0;32>b;b++)if(a&1<<31-b)return b;return 32});Math.$=Math.clz32;var qa=Math.abs,ta=Math.ceil,sa=Math.floor,ra=Math.min,J=0,$a=null,ab=null; +function bb(){J++;c.monitorRunDependencies&&c.monitorRunDependencies(J)}c.addRunDependency=bb;function cb(){J--;c.monitorRunDependencies&&c.monitorRunDependencies(J);if(0==J&&(null!==$a&&(clearInterval($a),$a=null),ab)){var a=ab;ab=null;a()}}c.removeRunDependency=cb;c.preloadedImages={};c.preloadedAudios={};var K=null,db=[function(a,b){throw"Array index "+a+" out of bounds: [0,"+b+")";}],La=8,u=La+1097872;Ta.push();var K="cld-worker.js.mem",eb=u,u=u+16;c._i64Add=fb;c._i64Subtract=gb; +function hb(a){c.___errno_location&&(C[c.___errno_location()>>2]=a);return a}function ib(){return!!ib.b}var jb=0,kb=[],L={};function lb(a){if(!a||L[a])return a;for(var b in L)if(L[b].D===a)return b;return a} +function mb(){var a=jb;if(!a)return(M.setTempRet0(0),0)|0;var b=L[a],d=b.type;if(!d)return(M.setTempRet0(0),a)|0;var e=Array.prototype.slice.call(arguments);c.___cxa_is_pointer_type(d);mb.buffer||(mb.buffer=D(4));C[mb.buffer>>2]=a;for(var a=mb.buffer,f=0;f>2],b.D=a,(M.setTempRet0(e[f]),a)|0;a=C[a>>2];return(M.setTempRet0(d),a)|0}c._memset=nb;function ob(a,b){I.push(function(){t.h("vi",a,[b])});ob.level=I.length}c._bitshift64Lshr=pb; +c._bitshift64Shl=qb;function rb(a,b){rb.b||(rb.b={});a in rb.b||(t.h("v",b),rb.b[a]=1)}c._memcpy=sb;var tb=0;function N(){tb+=4;return C[tb-4>>2]}var ub={},vb={};function F(a){F.b||(v=Ha(v),F.b=!0,assert(t.d),F.f=t.d,t.d=function(){y("cannot dynamically allocate, sbrk now has control")});var b=v;return 0==a||F.f(a)?b:4294967295}c._memmove=wb;var xb=1; +function Q(a,b){tb=b;try{var d=N(),e=N(),f=N(),l=0;Q.buffer||(Q.b=[null,[],[]],Q.g=function(a,b){var d=Q.b[a];assert(d);0===b||10===b?((1===a?c.print:c.printErr)(Ba(d,0)),d.length=0):d.push(b)});for(var h=0;h>2],r=C[e+(8*h+4)>>2],A=0;A>2]=xb;vb[xb]=0;xb++;return 0},_emscripten_asm_const_iii:function(a,b,d){return db[a](b,d)},_pthread_setspecific:function(a,b){if(!(a in vb))return 22;vb[a]=b;return 0},___cxa_throw:function(a,b,d){L[a]={a:a,D:a,type:b,aa:d,I:0};jb=a;"uncaught_exception"in ib?ib.b++:ib.b=1;throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch."; +},_abort:function(){c.abort()},_pthread_cleanup_push:ob,_time:function(a){var b=Date.now()/1E3|0;a&&(C[a>>2]=b);return b},___syscall140:function(a,b){tb=b;try{var d=ub.Q(),e=N(),f=N(),l=N(),h=N();assert(0===e);FS.ja(d,f,h);C[l>>2]=d.position;d.T&&0===f&&0===h&&(d.T=null);return 0}catch(q){return"undefined"!==typeof FS&&q instanceof FS.B||y(q),-q.G}},___syscall146:Q,STACKTOP:p,STACK_MAX:Na,tempDoublePtr:eb,ABORT:ia,cttz_i8:yb};// EMSCRIPTEN_START_ASM + +var M=(function(global,env,buffer) { +"almost asm";var a=global.Int8Array;var b=global.Int16Array;var c=global.Int32Array;var d=global.Uint8Array;var e=global.Uint16Array;var f=global.Uint32Array;var g=global.Float32Array;var h=global.Float64Array;var i=new a(buffer);var j=new b(buffer);var k=new c(buffer);var l=new d(buffer);var m=new e(buffer);var n=new f(buffer);var o=new g(buffer);var p=new h(buffer);var q=global.byteLength;var r=env.STACKTOP|0;var s=env.STACK_MAX|0;var t=env.tempDoublePtr|0;var u=env.ABORT|0;var v=env.cttz_i8|0;var w=0;var x=0;var y=0;var z=0;var A=global.NaN,B=global.Infinity;var C=0,D=0,E=0,F=0,G=0.0,H=0,I=0,J=0,K=0.0;var L=0;var M=0;var N=0;var O=0;var P=0;var Q=0;var R=0;var S=0;var T=0;var U=0;var V=global.Math.floor;var W=global.Math.abs;var X=global.Math.sqrt;var Y=global.Math.pow;var Z=global.Math.cos;var _=global.Math.sin;var $=global.Math.tan;var aa=global.Math.acos;var ba=global.Math.asin;var ca=global.Math.atan;var da=global.Math.atan2;var ea=global.Math.exp;var fa=global.Math.log;var ga=global.Math.ceil;var ha=global.Math.imul;var ia=global.Math.min;var ja=global.Math.clz32;var ka=env.abort;var la=env.assert;var ma=env.invoke_iiii;var na=env.invoke_viiiii;var oa=env.invoke_vi;var pa=env.invoke_ii;var qa=env.invoke_v;var ra=env.invoke_viiiiii;var sa=env.invoke_viiii;var ta=env._pthread_cleanup_pop;var ua=env.___syscall6;var va=env.___gxx_personality_v0;var wa=env.___assert_fail;var xa=env.___cxa_allocate_exception;var ya=env.___cxa_find_matching_catch;var za=env.___setErrNo;var Aa=env._sbrk;var Ba=env.___cxa_begin_catch;var Ca=env._emscripten_memcpy_big;var Da=env.___resumeException;var Ea=env.__ZSt18uncaught_exceptionv;var Fa=env._sysconf;var Ga=env._pthread_getspecific;var Ha=env._pthread_self;var Ia=env._pthread_once;var Ja=env._pthread_key_create;var Ka=env._emscripten_asm_const_iii;var La=env._pthread_setspecific;var Ma=env.___cxa_throw;var Na=env._abort;var Oa=env._pthread_cleanup_push;var Pa=env._time;var Qa=env.___syscall140;var Ra=env.___syscall146;var Sa=0.0;function Ta(newBuffer){if(q(newBuffer)&16777215||q(newBuffer)<=16777215||q(newBuffer)>2147483648)return false;i=new a(newBuffer);j=new b(newBuffer);k=new c(newBuffer);l=new d(newBuffer);m=new e(newBuffer);n=new f(newBuffer);o=new g(newBuffer);p=new h(newBuffer);buffer=newBuffer;return true} +// EMSCRIPTEN_START_FUNCS +function $a(a){a=a|0;var b=0;b=r;r=r+a|0;r=r+15&-16;return b|0}function ab(){return r|0}function bb(a){a=a|0;r=a}function cb(a,b){a=a|0;b=b|0;r=a;s=b}function db(a,b){a=a|0;b=b|0;if(!w){w=a;x=b}}function eb(a){a=a|0;i[t>>0]=i[a>>0];i[t+1>>0]=i[a+1>>0];i[t+2>>0]=i[a+2>>0];i[t+3>>0]=i[a+3>>0]}function fb(a){a=a|0;i[t>>0]=i[a>>0];i[t+1>>0]=i[a+1>>0];i[t+2>>0]=i[a+2>>0];i[t+3>>0]=i[a+3>>0];i[t+4>>0]=i[a+4>>0];i[t+5>>0]=i[a+5>>0];i[t+6>>0]=i[a+6>>0];i[t+7>>0]=i[a+7>>0]}function gb(a){a=a|0;L=a}function hb(){return L|0}function ib(a,b){a=a|0;b=b|0;var c=0,d=0;d=980497+(a<<3&2040)|0;c=a>>>8;if(c&255|0)nd(b,c&255,l[d+5>>0]|0);c=a>>>16;if(c&255|0)nd(b,c&255,l[d+6>>0]|0);c=a>>>24;if(c|0)nd(b,c&255,l[d+7>>0]|0);return}function jb(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,m=0,n=0,o=0;o=r;r=r+16|0;n=o+4|0;m=o;f=a+b|0;g=a+c|0;j=e+8|0;h=k[e+4>>2]|0;b=k[j>>2]|0;c=(i[f>>0]|0)==32?f+1|0:f;do{if(c>>>0>=g>>>0)break;k[n>>2]=c;f=l[1009576+(l[c>>0]|0)>>0]|0;k[m>>2]=f;c=c+f|0;f=ud(d,n,m)|0;if(f<<24>>24){k[e+32+(b<<3)>>2]=c-a;k[e+32+(b<<3)+4>>2]=f&255;b=b+1|0}}while((b|0)<(h|0));k[j>>2]=b;n=c-a|0;k[e+32+(b<<3)>>2]=n;k[e+32+(k[j>>2]<<3)+4>>2]=0;r=o;return n|0}function kb(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;q=a+c|0;z=f+12|0;u=k[f+4>>2]|0;A=f+16|0;v=u+-1|0;w=d+16|0;r=d+12|0;y=a;s=e+16|0;t=e+12|0;h=k[z>>2]|0;g=k[A>>2]|0;p=a+b|0;while(1){if(p>>>0>=q>>>0){c=p;break}b=l[1009576+(l[p>>0]|0)>>0]|0;c=p+b|0;b=(l[1009576+(l[c>>0]|0)>>0]|0)+b|0;do if(b>>>0>5){o=qb(p,b)|0;a=k[d>>2]|0;m=k[w>>2]|0;n=(o>>>12)+o|0;i=(k[r>>2]|0)+-1&n;j=m&o;b=k[a+(i<<4)>>2]|0;if((b^j)&m){b=k[a+(i<<4)+4>>2]|0;if((b^j)&m){b=k[a+(i<<4)+8>>2]|0;if((b^j)&m){b=k[a+(i<<4)+12>>2]|0;if(!((b^j)&m))x=8}else x=8}else x=8}else x=8;if((x|0)==8){x=0;if(b){k[f+8040+(h<<3)>>2]=p-y;k[f+8040+(h<<3)+4>>2]=b&~m;h=h+1|0}}j=k[e>>2]|0;m=k[s>>2]|0;a=(k[t>>2]|0)+-1&n;i=m&o;b=k[j+(a<<4)>>2]|0;if((b^i)&m){b=k[j+(a<<4)+4>>2]|0;if((b^i)&m){b=k[j+(a<<4)+8>>2]|0;if((b^i)&m){b=k[j+(a<<4)+12>>2]|0;if((b^i)&m)break}}}if(b){k[f+16048+(g<<3)>>2]=p-y;k[f+16048+(g<<3)+4>>2]=b&~m;g=g+1|0}}while(0);if((g|0)<(v|0)&(h|0)<(u|0))p=c;else break}k[z>>2]=h;k[A>>2]=g;z=c-y|0;k[f+8040+(h<<3)>>2]=z;k[f+8040+(h<<3)+4>>2]=0;k[f+16048+(k[A>>2]<<3)>>2]=z;k[f+16048+(k[A>>2]<<3)+4>>2]=0;return}function lb(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;D=r;r=r+16|0;C=D;t=a+b|0;u=a+c|0;B=f+8|0;b=k[B>>2]|0;A=k[f+4>>2]|0;v=C;k[v>>2]=0;k[v+4>>2]=0;v=C+4|0;w=d+16|0;x=d+12|0;y=e+12|0;z=e+16|0;g=0;c=(i[t>>0]|0)==32?t+1|0:t;do{if(c>>>0>=u>>>0)break;s=c+(l[979972+(l[c>>0]|0)>>0]|0)|0;s=s+(l[979972+(l[s>>0]|0)>>0]|0)|0;t=s+(l[979972+(l[s>>0]|0)>>0]|0)|0;t=t+(l[979972+(l[t>>0]|0)>>0]|0)|0;q=c;p=sb(c,t-q|0)|0;do if(!((p|0)==(k[C>>2]|0)?1:(p|0)==(k[v>>2]|0))){j=k[d>>2]|0;h=k[w>>2]|0;o=(p>>>12)+p|0;m=(k[x>>2]|0)+-1&o;n=h&p;c=k[j+(m<<4)>>2]|0;if((c^n)&h){c=k[j+(m<<4)+4>>2]|0;if((c^n)&h){c=k[j+(m<<4)+8>>2]|0;if((c^n)&h){c=k[j+(m<<4)+12>>2]|0;if(!((c^n)&h))m=8;else m=9}else m=8}else m=8}else m=8;if((m|0)==8){m=0;if(!c)m=9;else j=0}if((m|0)==9){c=k[y>>2]|0;if(!c)break;n=k[e>>2]|0;h=k[z>>2]|0;j=c+-1&o;m=h&p;c=k[n+(j<<4)>>2]|0;if((c^m)&h){c=k[n+(j<<4)+4>>2]|0;if((c^m)&h){c=k[n+(j<<4)+8>>2]|0;if((c^m)&h){c=k[n+(j<<4)+12>>2]|0;if((c^m)&h)break}}}if(!c)break;else j=-2147483648}k[C+(g<<2)>>2]=p;k[f+32+(b<<3)>>2]=q-a;k[f+32+(b<<3)+4>>2]=c&~h|j;b=b+1|0;g=g&1^1}while(0);c=(i[t>>0]|0)==32?t:s;if(c>>>0>>0)c=c+(l[980228+(l[c>>0]|0)>>0]|0)|0;else c=u}while((b|0)<(A|0));k[B>>2]=b;e=c-a|0;k[f+32+(b<<3)>>2]=e;k[f+32+(k[B>>2]<<3)+4>>2]=0;r=D;return e|0}function mb(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;J=r;r=r+16|0;F=J;u=a+b|0;A=a+(c+1)|0;H=f+12|0;g=k[H>>2]|0;B=k[f+4>>2]|0;I=f+16|0;b=k[I>>2]|0;C=B+-1|0;k[F>>2]=0;k[F+4>>2]=0;k[F+8>>2]=0;k[F+12>>2]=0;u=(i[u>>0]|0)==32?u+1|0:u;x=F+8|0;y=e+16|0;z=e+12|0;E=a;v=d+16|0;w=d+12|0;n=0;a=g;g=0;q=u;D=u;j=u;while(1){if(D>>>0>=A>>>0){c=D;break}c=i[D>>0]|0;if(c<<24>>24==32){t=u;p=ub(u,j-t|0)|0;s=L;n=F;o=x;do if(!(((p|0)==(k[n>>2]|0)?(s|0)==(k[n+4>>2]|0):0)|((p|0)==(k[o>>2]|0)?(s|0)==(k[o+4>>2]|0):0))){h=F+(g<<3)|0;k[h>>2]=p;k[h+4>>2]=s;g=1-g|0;h=F+(g<<3)|0;c=k[h>>2]|0;h=k[h+4>>2]|0;do if(!((c|0)==0&(h|0)==0|(c|0)==(p|0)&(h|0)==(s|0))){c=vb(c,h,p,s)|0;j=L;m=k[e>>2]|0;o=k[y>>2]|0;n=k[z>>2]|0;h=rf(c|0,j|0,12)|0;h=of(h|0,L|0,c|0,j|0)|0;h=n+-1&h;j=rf(c|0,j|0,4)|0;j=o&j;c=k[m+(h<<4)>>2]|0;if((c^j)&o){c=k[m+(h<<4)+4>>2]|0;if((c^j)&o){c=k[m+(h<<4)+8>>2]|0;if((c^j)&o){c=k[m+(h<<4)+12>>2]|0;if((c^j)&o){c=n;break}}}}if(!c)c=n;else{k[f+16048+(b<<3)>>2]=q-E;k[f+16048+(b<<3)+4>>2]=c&~o;c=n;b=b+1|0}}else{c=k[z>>2]|0;o=k[y>>2]|0;m=k[e>>2]|0}while(0);q=rf(p|0,s|0,12)|0;q=of(q|0,L|0,p|0,s|0)|0;j=c+-1&q;p=rf(p|0,s|0,4)|0;h=o&p;c=k[m+(j<<4)>>2]|0;if((c^h)&o){c=k[m+(j<<4)+4>>2]|0;if((c^h)&o){c=k[m+(j<<4)+8>>2]|0;if((c^h)&o){c=k[m+(j<<4)+12>>2]|0;if(!((c^h)&o))G=17}else G=17}else G=17}else G=17;if((G|0)==17){G=0;if(c){k[f+16048+(b<<3)>>2]=t-E;k[f+16048+(b<<3)+4>>2]=c&~o;b=b+1|0}}m=k[d>>2]|0;n=k[v>>2]|0;h=(k[w>>2]|0)+-1&q;j=n&p;c=k[m+(h<<4)>>2]|0;if((c^j)&n){c=k[m+(h<<4)+4>>2]|0;if((c^j)&n){c=k[m+(h<<4)+8>>2]|0;if((c^j)&n){c=k[m+(h<<4)+12>>2]|0;if((c^j)&n)break}}}if(c){k[f+8040+(a<<3)>>2]=t-E;k[f+8040+(a<<3)+4>>2]=c&~n;a=a+1|0}}while(0);m=D+1|0;c=i[D>>0]|0;o=0;h=u;j=m}else{o=n+1|0;h=q;m=u}c=D+(l[1009576+(c&255)>>0]|0)|0;if((b|0)<(C|0)&(a|0)<(B|0)){n=o;q=h;D=c;j=(o|0)<9?c:j;u=m}else break}k[H>>2]=a;k[I>>2]=b;H=c-E|0;k[f+8040+(a<<3)>>2]=H;k[f+8040+(a<<3)+4>>2]=0;k[f+16048+(k[I>>2]<<3)>>2]=H;k[f+16048+(k[I>>2]<<3)+4>>2]=0;r=J;return}function nb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=(c|0)<8?c*12|0:100;e=c*5>>3;e=(e|0)<3?3:(e|0)>16?16:e;c=a-b|0;if((c|0)<(e|0))if((c|0)<1)d=0;else{b=(c*100|0)/(e|0)|0;d=(d|0)<(b|0)?d:b}return d|0}function ob(a,b){a=a|0;b=b|0;var c=0.0;if(b)if(a){if((b|0)>(a|0))c=+(b|0)/+(a|0);else c=+(a|0)/+(b|0);if(!(c<=1.5))if(c>4.0)a=0;else a=~~((4.0-c)*100.0/2.5);else a=100}else a=0;else a=100;return a|0}function pb(a,b){a=a|0;b=b|0;a=((Hc(a)|0)&255)<<8;return a|(l[980484+b>>0]|0)|0}function qb(a,b){a=a|0;b=b|0;var c=0;do if(b){c=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;if((b|0)<5){c=k[120+((b&3)<<2)>>2]&c;c=c>>>3^c;break}else{a=a+4|0;a=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=(a<<18^a)+(c>>>3^c)|0;break}}else c=0;while(0);return c|0}function rb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;do if((b|0)>=5){d=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;d=d>>>3^d;e=a+4|0;e=l[e>>0]|l[e+1>>0]<<8|l[e+2>>0]<<16|l[e+3>>0]<<24;if((b|0)<9){a=k[120+((b&3)<<2)>>2]&e;d=(a<<4^a)+(d^c)|0;break}else{a=a+8|0;a=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);d=(d^c)+(e<<4^e)+(a<<2^a)|0;break}}else{d=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);d=d^c^d>>>3}while(0);return d|0}function sb(a,b){a=a|0;b=b|0;var c=0;if(!b)b=0;else{c=(i[a+-1>>0]|0)==32?17476:0;b=rb(a,b,(i[a+b>>0]|0)==32?c|1145307136:c)|0}return b|0}function tb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,m=0;f=(i[a+-1>>0]|0)==32;e=f?c|17476:c;f=f?d:d;d=(i[a+b>>0]|0)==32;e=d?e|1145307136:e;f=d?f:f;switch(b+-1>>2|0){case 0:{b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=b;d=0;b=(rf(b|0,0,3)|0)^b;a=L;break}case 1:{h=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;j=rf(h|0,0,3)|0;g=L;c=a+4|0;b=k[120+((b&3)<<2)>>2]&(l[c>>0]|l[c+1>>0]<<8|l[c+2>>0]<<16|l[c+3>>0]<<24);c=of(b|0,0,h|0,0)|0;d=L;b=of((sf(b|0,0,4)|0)^b|0,L|0,j^h|0,g|0)|0;a=L;break}case 2:{j=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;g=rf(j|0,0,3)|0;h=L;m=a+4|0;m=l[m>>0]|l[m+1>>0]<<8|l[m+2>>0]<<16|l[m+3>>0]<<24;d=of(m|0,0,j|0,0)|0;c=L;h=of((sf(m|0,0,4)|0)^m|0,L|0,g^j|0,h|0)|0;j=L;a=a+8|0;b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=of(d|0,c|0,b|0,0)|0;d=L;b=of(h|0,j|0,(sf(b|0,0,2)|0)^b|0,L|0)|0;a=L;break}case 3:{m=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;j=rf(m|0,0,3)|0;h=L;g=a+4|0;g=l[g>>0]|l[g+1>>0]<<8|l[g+2>>0]<<16|l[g+3>>0]<<24;c=of(g|0,0,m|0,0)|0;d=L;h=of((sf(g|0,0,4)|0)^g|0,L|0,j^m|0,h|0)|0;m=L;j=a+8|0;j=l[j>>0]|l[j+1>>0]<<8|l[j+2>>0]<<16|l[j+3>>0]<<24;d=of(c|0,d|0,j|0,0)|0;c=L;j=of(h|0,m|0,(sf(j|0,0,2)|0)^j|0,L|0)|0;m=L;a=a+12|0;b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=of(d|0,c|0,b|0,0)|0;d=L;b=of(j|0,m|0,(rf(b|0,0,8)|0)^b|0,L|0)|0;a=L;break}case 4:{m=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;h=rf(m|0,0,3)|0;j=L;g=a+4|0;g=l[g>>0]|l[g+1>>0]<<8|l[g+2>>0]<<16|l[g+3>>0]<<24;d=of(g|0,0,m|0,0)|0;c=L;j=of((sf(g|0,0,4)|0)^g|0,L|0,h^m|0,j|0)|0;m=L;h=a+8|0;h=l[h>>0]|l[h+1>>0]<<8|l[h+2>>0]<<16|l[h+3>>0]<<24;c=of(d|0,c|0,h|0,0)|0;d=L;h=of(j|0,m|0,(sf(h|0,0,2)|0)^h|0,L|0)|0;m=L;j=a+12|0;j=l[j>>0]|l[j+1>>0]<<8|l[j+2>>0]<<16|l[j+3>>0]<<24;d=of(c|0,d|0,j|0,0)|0;c=L;j=of(h|0,m|0,(rf(j|0,0,8)|0)^j|0,L|0)|0;m=L;a=a+16|0;b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=of(d|0,c|0,b|0,0)|0;d=L;b=of(j|0,m|0,(rf(b|0,0,4)|0)^b|0,L|0)|0;a=L;break}default:{m=l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24;j=rf(m|0,0,3)|0;h=L;g=a+4|0;g=l[g>>0]|l[g+1>>0]<<8|l[g+2>>0]<<16|l[g+3>>0]<<24;c=of(g|0,0,m|0,0)|0;d=L;h=of((sf(g|0,0,4)|0)^g|0,L|0,j^m|0,h|0)|0;m=L;j=a+8|0;j=l[j>>0]|l[j+1>>0]<<8|l[j+2>>0]<<16|l[j+3>>0]<<24;d=of(c|0,d|0,j|0,0)|0;c=L;j=of(h|0,m|0,(sf(j|0,0,2)|0)^j|0,L|0)|0;m=L;h=a+12|0;h=l[h>>0]|l[h+1>>0]<<8|l[h+2>>0]<<16|l[h+3>>0]<<24;c=of(d|0,c|0,h|0,0)|0;d=L;h=of(j|0,m|0,(rf(h|0,0,8)|0)^h|0,L|0)|0;m=L;j=a+16|0;j=l[j>>0]|l[j+1>>0]<<8|l[j+2>>0]<<16|l[j+3>>0]<<24;d=of(c|0,d|0,j|0,0)|0;c=L;j=of(h|0,m|0,(rf(j|0,0,4)|0)^j|0,L|0)|0;m=L;a=a+20|0;b=k[120+((b&3)<<2)>>2]&(l[a>>0]|l[a+1>>0]<<8|l[a+2>>0]<<16|l[a+3>>0]<<24);c=of(d|0,c|0,b|0,0)|0;d=L;b=of(j|0,m|0,(rf(b|0,0,6)|0)^b|0,L|0)|0;a=L}}j=rf(c|0,d|0,17)|0;j=of(j|0,L|0,c|0,d|0)|0;m=L;h=rf(j|0,m|0,9)|0;m=of(h|0,L|0,j|0,m|0)|0;m=of(0,m&255|0,b^e|0,a^f|0)|0;return m|0}function ub(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;if(!b){b=0;a=0}else{c=(i[a+-1>>0]|0)==32;e=c?17476:0;c=c?0:0;d=(i[a+b>>0]|0)==32;a=tb(a,b,d?e|1145307136:e,d?c:c)|0;b=L}L=b;return a|0}function vb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;f=rf(a|0,b|0,13)|0;e=L;b=sf(a|0,b|0,51)|0;d=of(f|b|0,e|L|0,c|0,d|0)|0;return d|0}function wb(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0;h=r;r=r+48|0;i=h+24|0;k[i>>2]=0;k[i+4>>2]=1097857;k[i+8>>2]=23;k[i+12>>2]=26;f=kc(a,b,c,i,0,d,e,h,f,g)|0;r=h;return ((f|0)==26?0:f)|0}function xb(a,b,c,d,e,f,g,h,i){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;return kc(a,b,c,d,0,e,f,g,h,i)|0}function yb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;a:do if(a<<16>>16){d=a&1023;e=k[b>>2]|0;do if((e|0)>0){c=0;while(1){f=b+4+(c<<1)|0;g=j[f>>1]|0;c=c+1|0;if((g&1023|0)==(d|0)){c=5;break}if((c|0)>=(e|0)){c=6;break}}if((c|0)==5){b=g<<16>>16>>10;a=a<<16>>16>>10;j[f>>1]=((b|0)>=(a|0)?b:a)<<10|d;break a}else if((c|0)==6)if((e|0)>13)break a;else break}while(0);k[b>>2]=e+1;j[b+4+(e<<1)>>1]=a}while(0);return}function zb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;a:do if(a<<16>>16){d=a&1023;e=k[b>>2]|0;do if((e|0)>0){c=0;while(1){f=b+4+(c<<1)|0;g=m[f>>1]|0;c=c+1|0;if((g&1023|0)==(d|0)){c=5;break}if((c|0)>=(e|0)){c=6;break}}if((c|0)==5){j[f>>1]=g+2048&64512|d;break a}else if((c|0)==6)if((e|0)>13)break a;else break}while(0);k[b>>2]=e+1;j[b+4+(e<<1)>>1]=a}while(0);return}function Ab(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0;if((k[a>>2]|0)>4){g=0;do{f=j[a+4+(g<<1)>>1]|0;d=f<<16>>16>>10;d=(d|0)>-1?d:0-d|0;a:do if((g|0)>0){e=g;while(1){b=e+-1|0;c=j[a+4+(b<<1)>>1]|0;h=c<<16>>16>>10;if((((h|0)>-1?h:0-h|0)|0)>=(d|0)){b=e;break a}j[a+4+(e<<1)>>1]=c;if((e|0)>1)e=b;else break}}else b=g;while(0);j[a+4+(b<<1)>>1]=f;g=g+1|0}while((g|0)<(k[a>>2]|0));k[a>>2]=4}return}function Bb(a){a=a|0;var b=0,c=0,d=0;d=i[a>>0]|0;b=(d&1)==0;d=b?(d&255)>>>1:k[a+4>>2]|0;if((d|0)>0){a=b?a+1|0:k[a+8>>2]|0;b=0;c=0;do{b=((i[a+c>>0]|0)==44&1)+b|0;c=c+1|0}while((c|0)!=(d|0))}else b=0;return b|0}function Cb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;g=c;c=0;a:while(1){if((c|0)<(g|0))f=c;else{c=0;break}while(1){d=f+g>>1;c=b+(d*12|0)|0;e=_d(k[c>>2]|0,a)|0;if((e|0)>=0)break;c=d+1|0;if((c|0)<(g|0))f=c;else{c=0;break a}}if((e|0)>0){g=d;c=f}else break}return c|0}function Db(a){a=a|0;var b=0,c=0,d=0,e=0,f=0;f=181;b=0;a:while(1){if((b|0)<(f|0))e=b;else{b=0;break}while(1){c=e+f>>1;b=5776+(c<<3)|0;d=_d(k[b>>2]|0,a)|0;if((d|0)>=0)break;b=c+1|0;if((b|0)<(f|0))e=b;else{b=0;break a}}if((d|0)>0){f=c;b=e}else break}return b|0}function Eb(a){a=a|0;Ba(a|0)|0;cf()}function Fb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=c+-3|0;a:do if((d|0)>(b|0))do{e=a+b|0;e=l[e>>0]|l[e+1>>0]<<8|l[e+2>>0]<<16|l[e+3>>0]<<24;if((e^1010580540)+-16843009&(e&-2139062144^-2139062144)|0)break a;b=b+4|0}while((b|0)<(d|0));while(0);b:do if((b|0)<(c|0))while(1){if((i[a+b>>0]|0)==60)break b;b=b+1|0;if((b|0)>=(c|0)){b=-1;break}}else b=-1;while(0);return b|0}function Gb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;a:do if((b|0)<(c|0))while(1){b:do switch(i[a+b>>0]|0){case 61:break a;case 34:{e=b+1|0;if((e|0)<(c|0)){d=b;b=e;while(1){switch(i[a+b>>0]|0){case 34:break b;case 92:{d=d+2|0;break}default:d=b}b=d+1|0;if((b|0)>=(c|0))break b}}else b=e;break}case 39:{e=b+1|0;if((e|0)<(c|0)){d=b;b=e;while(1){switch(i[a+b>>0]|0){case 39:break b;case 92:{d=d+2|0;break}default:d=b}b=d+1|0;if((b|0)>=(c|0))break b}}else b=e;break}default:{}}while(0);b=b+1|0;if((b|0)>=(c|0)){b=-1;break a}}else b=-1;while(0);return b|0}function Hb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;g=Vd(d)|0;a:do if((c-b|0)>=(g|0)){f=g+b|0;while(1){if((c|0)<=(f|0))break;e=c+-1|0;if((i[a+e>>0]|0)==32)c=e;else break}c=c-g|0;if((c|0)>=(b|0)){c=a+c|0;if((g|0)>0){e=0;while(1){if((i[c+e>>0]|32|0)!=(i[d+e>>0]|0)){c=0;break a}e=e+1|0;if((e|0)>=(g|0)){c=1;break}}}else c=1}else c=0}else c=0;while(0);return c|0}function Ib(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=Vd(d)|0;a:do if((c-b|0)>=(e|0)){c=c-e|0;b:do if((c|0)>(b|0))while(1){switch(i[a+b>>0]|0){case 39:case 34:case 32:break;default:break b}b=b+1|0;if((b|0)>=(c|0))break b}while(0);b=a+b|0;if((e|0)>0){c=0;while(1){if((i[b+c>>0]|32|0)!=(i[d+c>>0]|0)){b=0;break a}c=c+1|0;if((c|0)>=(e|0)){b=1;break}}}else b=1}else b=0;while(0);return b|0}function Jb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;if((c|0)<(d|0)){f=1;do{e=l[b+c>>0]|0;g=(l[984554+e>>0]|0)>>>(f*3|0);f=g&3;do if(g&4|0)if(!f){Ce(a,1,i[984810+e>>0]|0);break}else{Ce(a,1,44);break}while(0);c=c+1|0}while((c|0)!=(d|0));if(!f)Ce(a,1,44)}return}function Kb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;a:do if((c|0)<(d|0)){b:while(1){switch(i[b+c>>0]|0){case 39:case 34:break b;case 32:break;default:{f=5;break a}}c=c+1|0;if((c|0)>=(d|0)){f=5;break a}}if((c|0)>=0){e=c+1|0;c:do if((e|0)<(d|0)){c=e;d:while(1){switch(i[b+c>>0]|0){case 39:case 34:break d;case 62:{f=8;break d}case 61:{f=9;break d}case 60:{f=10;break d}case 38:{f=11;break d}default:{}}c=c+1|0;if((c|0)>=(d|0))break c}if((f|0)==8)c=c+-1|0;else if((f|0)==9)c=c+-1|0;else if((f|0)==10)c=c+-1|0;else if((f|0)==11)c=c+-1|0;if((c|0)>=0){Jb(a,b,e,c);break a}}while(0);ze(a,1097857,0)}else f=5}else f=5;while(0);if((f|0)==5)ze(a,1097857,0);return}function Lb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,l=0,m=0,n=0,o=0;o=r;r=r+32|0;n=o;d=i[a>>0]|0;l=a+4|0;e=k[l>>2]|0;c=(d&1)==0?(d&255)>>>1:e;if((c|0?(Bb(a)|0)<=4:0)?(c|0)>0:0){g=a+8|0;h=a+1|0;f=0;do{c=Ie(a,f)|0;if((c|0)==-1){if(!(d&1))e=(d&255)>>>1}else e=c;c=e-f|0;do if((c|0)<17){tf(n|0,((d&1)==0?h:k[g>>2]|0)+f|0,c|0)|0;i[n+c>>0]=0;c=Cb(n,136,213)|0;if(c|0){yb(j[c+8>>1]|0,b);yb(j[c+10>>1]|0,b);break}c=me(n,45)|0;if(c|0)i[c>>0]=0;if((Vd(n)|0)<4?(m=Cb(n,2692,257)|0,m|0):0){yb(j[m+8>>1]|0,b);yb(j[m+10>>1]|0,b)}}while(0);f=e+1|0;d=i[a>>0]|0;e=k[l>>2]|0}while((f|0)<(((d&1)==0?(d&255)>>>1:e)|0))}r=o;return}function Mb(a,b){a=a|0;b=b|0;var c=0,d=0;c=r;r=r+16|0;d=c;Jb(d,a,0,Vd(a)|0);Lb(d,b);Ae(d);r=c;return}function Nb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;e=r;r=r+16|0;d=e;c=Vd(a)|0;if((c|0)<=3){ne(d,a);i[d+3>>0]=0;if((c|0)>0){a=0;do{f=d+a|0;i[f>>0]=l[f>>0]|0|32;a=a+1|0}while((a|0)!=(c|0))}a=Db(d)|0;if(a|0){zb(j[a+4>>1]|0,b);zb(j[a+6>>1]|0,b)}}r=e;return}function Ob(a,b){a=a|0;b=b|0;switch(a|0){case 62:case 48:case 46:case 45:case 14:{zb(4112,b);break}case 47:case 20:case 13:{zb(4165,b);break}case 12:case 21:case 11:case 10:{zb(4104,b);break}case 44:case 16:{zb(4105,b);break}default:{}}return}function Pb(a,b){a=a|0;b=b|0;zb(a+8192&65535,b);return}function Qb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0;f=r;r=r+80|0;e=f;d=f+8|0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;if((k[b>>2]|0)>0){c=0;do{g=j[b+4+(c<<1)>>1]|0;h=Ec(g&1023)|0;k[e>>2]=h;k[e+4>>2]=g<<16>>16>>10;ue(d,985273,e);Fe(a,d);c=c+1|0}while((c|0)<(k[b>>2]|0))}r=f;return}function Rb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;D=r;r=r+16|0;C=D;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;y=(c|0)<8192?c:8192;a:do if((y|0)>0){s=C+4|0;t=a+1|0;u=C+8|0;v=C+1|0;w=a+8|0;x=a+4|0;c=0;do{c=Fb(b,c,y)|0;if((c|0)<0)break a;d=c+1|0;if((d|0)<(y|0))c=d;else break a;b:while(1){switch(i[b+c>>0]|0){case 62:break b;case 60:{z=6;break b}case 38:{z=7;break b}default:{}}c=c+1|0;if((c|0)>=(y|0))break a}if((z|0)==6){z=0;c=c+-1|0}else if((z|0)==7){z=0;c=c+-1|0}if((c|0)<0)break a;if((((((!(Ib(b,d,c,985280)|0)?!(Ib(b,d,c,985284)|0):0)?!(Ib(b,d,c,985290)|0):0)?!(Ib(b,d,c,985298)|0):0)?!(Ib(b,d,c,985304)|0):0)?!(Ib(b,d,c,985309)|0):0)?(A=Ib(b,d,c,985312)|0,B=Gb(b,d,c)|0,(B|0)>-1):0){g=B;f=0;e=d;while(1){do if(A){if(Hb(b,e,g,985318)|0?Ib(b,g+1|0,c,985330)|0:0){z=25;break}if(Hb(b,e,g,985348)|0){d=g+1|0;if(!(Ib(b,d,c,985354)|0)?!(f|(Ib(b,d,c,985367)|0)):0){d=0;z=26}else z=25}else z=24}else z=24;while(0);if((z|0)==24)if(f)z=25;else{d=0;z=26}if((z|0)==25)if(Hb(b,e,g,985377)|0){d=1;z=29}else{d=1;z=26}if((z|0)==26){z=0;if(!(Hb(b,e,g,985386)|0)?!(Hb(b,e,g,985392)|0):0)e=g+1|0;else z=29}if((z|0)==29){z=0;p=g+1|0;Kb(C,b,p,c);q=i[C>>0]|0;f=(q&1)==0;q=f?(q&255)>>>1:k[s>>2]|0;c:do if(q|0){e=i[a>>0]|0;if(!(e&1)){e=(e&255)>>>1;g=t}else{e=k[x>>2]|0;g=k[w>>2]|0}l=f?v:k[u>>2]|0;d:do if(e>>>0>=q>>>0){m=g+e|0;n=l+q|0;o=g;if((e|0)<(q|0))break;h=m+(1-q)|0;if((h|0)==(g|0))break;j=i[l>>0]|0;e=g;e:while(1){if((i[e>>0]|0)==j<<24>>24){f=e;g=l;do{g=g+1|0;if((g|0)==(n|0))break e;f=f+1|0}while((i[f>>0]|0)==(i[g>>0]|0))}e=e+1|0;if((e|0)==(h|0))break d}if(!((e|0)==(m|0)|(e-o|0)==-1))break c}while(0);Ee(a,l,q)}while(0);Ae(C);e=p}g=Gb(b,e,c)|0;if((g|0)<=-1)break;else f=d}}c=c+1|0}while((c|0)<(y|0))}while(0);c=i[a>>0]|0;d=(c&1)==0;if(d)e=(c&255)>>>1;else e=k[a+4>>2]|0;if(e>>>0>1){if(d)c=(c&255)>>>1;else c=k[a+4>>2]|0;He(a,c+-1|0)}r=D;return}function Sb(a,b){a=a|0;b=b|0;var c=0;c=(b|0)<32?b:32;a:do if((c|0)>0){b=0;while(1){if((i[a+~b>>0]|0)==32)break a;b=b+1|0;if((b|0)>=(c|0)){b=0;break}}while(1){if((i[a+(0-b)>>0]&-64)<<24>>24!=-128)break a;b=b+1|0;if((b|0)>=(c|0)){b=0;break}}}else b=0;while(0);return b|0}function Tb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;d=(b|0)<32?b:32;c=0;while(1){if((c|0)>=(d|0)){e=3;break}b=c+1|0;if((i[a+c>>0]|0)==32)break;else c=b}a:do if((e|0)==3)if((d|0)>0){b=0;while(1){if((i[a+b>>0]&-64)<<24>>24!=-128)break a;b=b+1|0;if((b|0)>=(d|0)){b=0;break}}}else b=0;while(0);return b|0}function Ub(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,m=0;j=a+b|0;e=k[c>>2]|0;if((b|0)>0){b=0;h=a;do{f=i[h>>0]|0;g=f&255;do if((f&255)>=192){if((g&224|0)==192){g=l[h+1>>0]|0|g<<8;a=2;break}a=i[h+1>>0]|0;f=i[h+2>>0]|0;if((g&240|0)==224){g=(a&255)<<8|g<<16|f&255;a=3;break}else{g=(a&255)<<16|g<<24|(f&255)<<8|(l[h+3>>0]|0);a=4;break}}else a=1;while(0);h=h+a|0;m=d+(e<<2)|0;f=k[m>>2]|0;k[m>>2]=g;b=((g|0)==(f|0)?a:0)+b|0;e=(g^e<<4)&4095}while(h>>>0>>0)}else b=0;k[c>>2]=e;return b|0}function Vb(a,b){a=a|0;b=b|0;var c=0,d=0;c=b&-4;if((c|0)>0){d=0;b=0;do{b=((i[a+d>>0]|0)==32&1)+b+((i[a+(d|1)>>0]|0)==32&1)+((i[a+(d|2)>>0]|0)==32&1)+((i[a+(d|3)>>0]|0)==32&1)|0;d=d+4|0}while((d|0)<(c|0))}else b=0;return b|0}function Wb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;s=a+b|0;e=k[c>>2]|0;if((b|0)>0){q=a;p=0;r=a;m=a;n=0;while(1){g=i[r>>0]|0;j=g&255;f=q+1|0;i[q>>0]=g;do if(g<<24>>24!=32)if((g&255)>=192){if((j&224|0)==192){h=r+1|0;i[f>>0]=i[h>>0]|0;j=l[h>>0]|0|j<<8;f=q+2|0;h=p;o=2;break}h=r+1|0;i[f>>0]=i[h>>0]|0;g=r+2|0;f=q+3|0;i[q+2>>0]=i[g>>0]|0;if((j&240|0)==224){j=(l[h>>0]|0)<<8|j<<16|(l[g>>0]|0);h=p;o=3;break}else{o=r+3|0;i[f>>0]=i[o>>0]|0;j=(l[h>>0]|0)<<16|j<<24|(l[g>>0]|0)<<8|(l[o>>0]|0);f=q+4|0;h=p;o=4;break}}else{h=p;o=1}else{m=(p<<1|0)>(n|0)?m:f;f=m;h=0;o=1;n=0}while(0);r=r+o|0;q=d+(e<<2)|0;g=k[q>>2]|0;k[q>>2]=j;e=(j^e<<4)&4095;if(r>>>0>=s>>>0)break;else{q=f;p=((j|0)==(g|0)?o:0)+h|0;n=o+n|0}}}else f=a;k[c>>2]=e;e=f-a|0;if((e|0)>=(b+-3|0)){if((e|0)<(b|0))i[f>>0]=32}else{i[f>>0]=32;i[f+1>>0]=32;i[f+2>>0]=32;i[f+3>>0]=0}return e|0}function Xb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0;o=r;r=r+16|0;m=o;h=a+b|0;k[m>>2]=0;n=jf(16384)|0;qf(n|0,0,16384)|0;if((b|0)>0){j=h;c=a;l=a+1|0;d=a;e=0;f=a;do{g=j-f|0;g=(g|0)>48?48:g;while(1)if((i[f+g>>0]&-64)<<24>>24==-128)g=g+1|0;else break;p=Vb(f,g)|0;if((p|0)<12&(Ub(f,g,m,n)|0)<19){if(e){p=Tb(f,g)|0;e=g-p|0;f=f+p|0}else e=g;if((e|0)>0){uf(d|0,f|0,e|0)|0;d=d+e|0;g=e;e=0}else{g=e;e=0}}else if(!e){d=d+(0-(Sb(d,d-c|0)|0))|0;if((d|0)==(a|0)){i[a>>0]=32;d=l;e=1}else e=1}else e=1;f=f+g|0}while(f>>>0>>0)}else{c=a;d=a}c=d-c|0;if((c|0)>=(b+-3|0)){if((c|0)<(b|0))i[d>>0]=32}else{i[d>>0]=32;i[d+1>>0]=32;i[d+2>>0]=32;i[d+3>>0]=0}kf(n);r=o;return c|0}function Yb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=r;r=r+16|0;d=e;if((b|0)<256)b=0;else{k[d>>2]=0;c=jf(16384)|0;qf(c|0,0,16384)|0;if((Vb(a,256)|0)<64?(Ub(a,256,d,c)|0)<171:0)b=0;else b=1;kf(c)}r=e;return b|0}function Zb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;y=r;r=r+48|0;x=y+32|0;t=y+16|0;s=y;q=0;do{d=j[a+568+(q<<1)>>1]|0;n=d&65535;do if(((((d<<16>>16!=-1?(o=k[a+616+(q<<2)>>2]|0,o|0):0)?(p=(k[a+808+(q<<2)>>2]|0)/(o|0)|0,(d&65535)<165&(p|0)<41):0)?(i=k[7224+(n<<2)>>2]|0,(i|0)!=26):0)?(l=rd(a,i&65535)|0,(l|0)>=0):0)?(m=k[a+616+(l<<2)>>2]|0,m|0):0){d=(k[a+808+(l<<2)>>2]|0)/(m|0)|0;e=(d|0)<(p|0);if(!e?!((n|0)<(i|0)&(d|0)==(p|0)):0){f=q;g=0;h=l}else{f=l;g=1;h=q}z=e?p:d;e=m+o|0;z=ha((z|0)>41?z:41,e)|0;j[a+568+(f<<1)>>1]=-1;k[a+712+(f<<2)>>2]=0;k[a+808+(f<<2)>>2]=0;k[a+712+(h<<2)>>2]=e;k[a+808+(h<<2)>>2]=z;if(!(c|(e|0)>9&b^1))if(g){h=Ec(i)|0;z=Ec(n)|0;k[s>>2]=h;k[s+4>>2]=d;k[s+8>>2]=m;k[s+12>>2]=z;pe(941016,985398,s);break}else{n=Ec(n)|0;z=Ec(i)|0;k[t>>2]=n;k[t+4>>2]=p;k[t+8>>2]=o;k[t+12>>2]=z;pe(941016,985398,t);break}}while(0);q=q+1|0}while((q|0)!=24);f=0;do{d=a+568+(f<<1)|0;z=j[d>>1]|0;e=z&65535;if(((z<<16>>16!=-1?(u=k[a+616+(f<<2)>>2]|0,v=a+808+(f<<2)|0,u|0):0)?(w=(k[v>>2]|0)/(u|0)|0,(w|0)<=40):0)?(j[d>>1]=-1,k[a+712+(f<<2)>>2]=0,k[v>>2]=0,!(c|(u|0)>9&b^1)):0){z=Ec(e)|0;k[x>>2]=z;k[x+4>>2]=w;k[x+8>>2]=u;pe(941016,985425,x)}f=f+1|0}while((f|0)!=24);r=y;return}function _b(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;e=c+616+(b<<2)|0;k[e>>2]=(k[c+616+(a<<2)>>2]|0)+(k[e>>2]|0);e=c+712+(b<<2)|0;d=c+712+(a<<2)|0;k[e>>2]=(k[d>>2]|0)+(k[e>>2]|0);e=c+808+(b<<2)|0;b=c+808+(a<<2)|0;k[e>>2]=(k[b>>2]|0)+(k[e>>2]|0);j[c+568+(a<<1)>>1]=-1;k[d>>2]=0;k[b>>2]=0;return}function $b(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,n=0,o=0;j=r;r=r+16|0;i=j;f=b^1|c;g=0;do{d=m[a+568+(g<<1)>>1]|0;b=Fc(d)|0;a:do if(b|0){h=g;do{h=h+1|0;if((h|0)>=24)break a;e=m[a+568+(h<<1)>>1]|0}while((Fc(e)|0)!=(b|0));b=(k[a+616+(g<<2)>>2]|0)<(k[a+616+(h<<2)>>2]|0);c=b?g:h;if(!f){l=k[a+616+(c<<2)>>2]|0;n=(k[a+808+(c<<2)>>2]|0)/((l|0?l:1)|0)|0;o=Ec(b?d:e)|0;e=Ec(b?e:d)|0;k[i>>2]=o;k[i+4>>2]=n;k[i+8>>2]=l;k[i+12>>2]=e;pe(941016,985446,i)}_b(c,b?h:g,a)}while(0);g=g+1|0}while((g|0)!=24);r=j;return}function ac(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,l=0,m=0;l=r;r=r+48|0;h=l+32|0;j=l+24|0;g=l+16|0;f=l;se(985487,34,1,941016);e=k[a>>2]|0;if((e|0)!=26){m=Dc(e)|0;e=i[d>>0]|0?1097857:985485;d=k[b>>2]|0;k[f>>2]=m;k[f+4>>2]=e;k[f+8>>2]=d;pe(941016,985522,f)}e=k[a+4>>2]|0;if((e|0)!=26){f=Dc(e)|0;m=k[b+4>>2]|0;k[g>>2]=f;k[g+4>>2]=m;pe(941016,985535,g)}e=k[a+8>>2]|0;if((e|0)!=26){g=Dc(e)|0;m=k[b+8>>2]|0;k[j>>2]=g;k[j+4>>2]=m;pe(941016,985535,j)}k[h>>2]=k[c>>2];pe(941016,985546,h);se(1017206,5,1,941016);r=l;return}function bc(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var l=0.0,m=0,n=0,o=0,q=0,r=0,s=0,t=0,u=0,v=0;k[c>>2]=0;n=c+4|0;k[n>>2]=0;r=c+8|0;k[r>>2]=0;k[d>>2]=26;m=d+4|0;k[m>>2]=26;q=d+8|0;k[q>>2]=26;k[e>>2]=0;u=e+4|0;k[u>>2]=0;v=e+8|0;k[v>>2]=0;o=f+8|0;s=f+16|0;k[f>>2]=0;k[f+4>>2]=0;k[f+8>>2]=0;k[f+12>>2]=0;k[f+16>>2]=0;k[f+20>>2]=0;k[g>>2]=b;i[h>>0]=0;t=j[a+568>>1]|0;switch(t<<16>>16){case 26:case -1:{f=0;break}default:{k[d>>2]=t&65535;d=k[a+616>>2]|0;k[c>>2]=(k[a+808>>2]|0)/((d|0?d:1)|0)|0;if((d|0)<1)l=0.0;else l=+((k[a+712>>2]<<10|0)/(d|0)|0|0);p[f>>3]=l;f=d}}d=j[a+570>>1]|0;switch(d<<16>>16){case 26:case -1:{c=0;break}default:{k[m>>2]=d&65535;d=k[a+620>>2]|0;k[n>>2]=(k[a+812>>2]|0)/((d|0?d:1)|0)|0;if((d|0)<1)l=0.0;else l=+((k[a+716>>2]<<10|0)/(d|0)|0|0);p[o>>3]=l;c=d}}d=j[a+572>>1]|0;switch(d<<16>>16){case 26:case -1:{d=0;break}default:{k[q>>2]=d&65535;d=k[a+624>>2]|0;k[r>>2]=(k[a+816>>2]|0)/((d|0?d:1)|0)|0;if((d|0)<1)l=0.0;else l=+((k[a+720>>2]<<10|0)/(d|0)|0|0);p[s>>3]=l}}c=c+f|0;d=d+c|0;if((d|0)>(b|0)){k[g>>2]=d;b=d}r=(b|0)<1?1:b;f=(f*100|0)/(r|0)|0;k[e>>2]=f;s=(c*100|0)/(r|0)|0;c=((d*100|0)/(r|0)|0)-s|0;k[v>>2]=c;d=s-f|0;k[u>>2]=d;if((d|0)<(c|0)){d=d+1|0;k[u>>2]=d;k[v>>2]=c+-1}if((f|0)<(d|0)){k[e>>2]=f+1;k[u>>2]=d+-1}k[g>>2]=b;switch(t<<16>>16){case 26:case -1:{d=0;break}default:{d=k[a+616>>2]|0;d=((k[a+808>>2]|0)/((d|0?d:1)|0)|0|0)>40&1}}i[h>>0]=d;i[h>>0]=(100-(k[e>>2]|0)-(k[u>>2]|0)-(k[v>>2]|0)|0)>20?0:d;return}function cc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;y=r;r=r+32|0;w=y+8|0;v=y;q=y+12|0;k[q>>2]=k[1971];k[q+4>>2]=k[1972];k[q+8>>2]=k[1973];h=k[c>>2]|0;k[d>>2]=k[b>>2];i[e>>0]=(h|0)>1&1;j=0;m=0;l=0;p=3;while(1){if((k[b+(m<<2)>>2]|0)==25){o=(k[c+(m<<2)>>2]|0)+l|0;n=m+1|0;if((n|0)<3){h=m;j=n;while(1){k[q+(h<<2)>>2]=k[q+(j<<2)>>2];h=j+1|0;if((h|0)==3)break;else{u=j;j=h;h=u}}j=k[q>>2]|0}l=p+-1|0;h=((k[c>>2]|0)*100|0)/(101-o|0)|0;k[d>>2]=k[b+(j<<2)>>2];if((k[c+(j<<2)>>2]|0)<2){i[e>>0]=0;m=n;s=j;t=o;u=l}else{m=n;s=j;t=o;u=l}}else{m=m+1|0;s=j;t=l;u=p}if((m|0)==3)break;else{j=s;l=t;p=u}}o=k[q+4>>2]|0;p=k[c+(o<<2)>>2]|0;n=ha(p,a)|0;o=b+(o<<2)|0;l=k[b+(s<<2)>>2]|0;m=(l|0)==0;a:do if(m){j=k[o>>2]|0;switch(j|0){case 26:case 0:{x=24;break a}default:{}}if((n|0)>1499&(p|0)>16){h=(p*100|0)/(101-t-(k[c+(s<<2)>>2]|0)|0)|0;k[d>>2]=j;if((p|0)<2)i[e>>0]=0}else x=23}else{b=l+-4|0;if(b>>>0<11?(1035>>>(b&2047)&1)!=0:0){j=k[o>>2]|0;if(j>>>0<15){if(16561>>>(j&32767)&1){x=23;break}}else if((j|0)==26){x=23;break}if((n|0)>1499&(p|0)>19){h=(p*100|0)/(101-t-(k[c+(s<<2)>>2]|0)|0)|0;k[d>>2]=j;if((p|0)<2)i[e>>0]=0}else x=23}else x=23}while(0);if((x|0)==23){j=k[o>>2]|0;x=24}do if((x|0)==24){if(!j){if(m)break;h=((k[c+(s<<2)>>2]|0)*100|0)/(101-t-p|0)|0;break}x=j+-4|0;if(x>>>0<11?(1035>>>(x&2047)&1)!=0:0){if(l>>>0<15?16561>>>(l&32767)&1:0)break;h=((k[c+(s<<2)>>2]|0)*100|0)/(101-t-p|0)|0}}while(0);if((h|0)<26){if(!(f^1|g)){x=Ec(k[d>>2]|0)|0;k[v>>2]=x;k[v+4>>2]=h;pe(941016,985557,v)}k[d>>2]=26;i[e>>0]=0}if((h|0)<51)i[e>>0]=0;if((100-(k[c>>2]|0)-(k[c+4>>2]|0)-(k[c+8>>2]|0)|0)>20)i[e>>0]=0;if(!u){if(!(f^1|g)){x=Ec(k[d>>2]|0)|0;k[w>>2]=x;pe(941016,985593,w)}k[d>>2]=26;i[e>>0]=0}r=y;return}function dc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;if(Jc(a)|0){d=c+16|0;e=k[d>>2]|0;k[c+20+(e<<2)>>2]=b;k[d>>2]=e+1&3}if(Kc(a)|0){e=c+36|0;d=k[e>>2]|0;k[c+40+(d<<2)>>2]=b;k[e>>2]=d+1&3}return}function ec(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;d=pb(b,1)|0;if(Jc(a)|0?Jc(b)|0:0){e=c+56|0;f=k[e>>2]|0;k[c+60+(f<<2)>>2]=d;k[e>>2]=f+1&3}if(Kc(a)|0?Kc(b)|0:0){f=c+76|0;e=k[f>>2]|0;k[c+80+(e<<2)>>2]=d;k[f>>2]=e+1&3}return}function fc(a,b){a=a|0;b=b|0;var c=0,d=0;switch(a|0){case 16:{ec(16,69,b);break}case 69:{ec(69,16,b);break}default:{c=Fc(a)|0;if(c|0){d=0;do{if(!((d|0)==(a|0)|(c|0)!=(Fc(d)|0)))ec(a,d,b);d=d+1|0}while((d|0)!=512)}}}return}function gc(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,l=0,n=0,o=0,p=0;p=r;r=r+64|0;h=p+8|0;g=p;n=p+32|0;o=p+16|0;l=p+12|0;k[n>>2]=0;if(!c){Rb(o,a,b);Lb(o,n);if(i[e+5>>0]|0?(c=i[o>>0]|0,f=(c&1)==0,(f?(c&255)>>>1:k[o+4>>2]|0)|0):0){c=k[e>>2]|0;k[g>>2]=f?o+1|0:k[o+8>>2]|0;pe(c,985624,g)}Ae(o)}if(d|0){f=k[d>>2]|0;if(f|0?i[f>>0]|0:0)Mb(f,n);f=k[d+4>>2]|0;if(f|0?i[f>>0]|0:0)Nb(f,n);f=k[d+8>>2]|0;if((f|0)!=23)Ob(f,n);f=k[d+12>>2]|0;if((f|0)!=26)Pb(f,n)}Ab(n);if(i[e+5>>0]|0){Qb(o,n);d=i[o>>0]|0;f=(d&1)==0;if((f?(d&255)>>>1:k[o+4>>2]|0)|0){d=k[e>>2]|0;k[h>>2]=f?o+1|0:k[o+8>>2]|0;pe(d,985648,h)}Ae(o)}d=k[n>>2]|0;c=(d|0)>0;if(c){b=0;do{a=j[n+4+(b<<1)>>1]|0;f=a&1023;a=a<<16>>16>>10;if((a|0)>0)dc(f,pb(f,a)|0,e);b=b+1|0}while((b|0)<(d|0))}k[l>>2]=0;hc(o,l);g=k[o>>2]|0;if(c){b=g+40|0;f=0;while(1){l=m[n+4+(f<<1)>>1]&1023;h=g+((Fc(l)|0)<<2)|0;k[h>>2]=(k[h>>2]|0)+1;switch(l|0){case 16:{k[b>>2]=(k[b>>2]|0)+1;break}case 69:{k[b>>2]=(k[b>>2]|0)+1;break}default:{}}f=f+1|0;if((f|0)==(d|0)){a=0;break}}do{l=j[n+4+(a<<1)>>1]|0;f=l&1023;a:do if((l<<16>>16>>10|0)>0){l=Fc(f)|0;if((l|0)>0?(k[g+(l<<2)>>2]|0)==1:0)fc(f,e);switch(f|0){case 16:case 69:break;default:break a}if((k[b>>2]|0)==1)fc(f,e)}while(0);a=a+1|0}while((a|0)!=(d|0))}b=g;if(g|0){f=o+4|0;a=k[f>>2]|0;if((a|0)!=(g|0))k[f>>2]=a+(~((a+-4-b|0)>>>2)<<2);Qe(g)}r=p;return}function hc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;k[a>>2]=0;e=a+4|0;k[e>>2]=0;k[a+8>>2]=0;ic(a);c=k[e>>2]|0;a=11;d=c;while(1){k[d>>2]=k[b>>2];a=a+-1|0;if(!a)break;else d=d+4|0}k[e>>2]=c+44;return}function ic(a){a=a|0;var b=0;b=gf(44)|0;k[a+4>>2]=b;k[a>>2]=b;k[a+8>>2]=b+44;return}function jc(a){a=a|0;var b=0,c=0,d=0;c=k[a>>2]|0;d=c;if(c|0){a=a+4|0;b=k[a>>2]|0;if((b|0)!=(c|0))k[a>>2]=b+(~((b+-4-d|0)>>>2)<<2);Qe(c)}return}function kc(a,b,c,d,e,f,g,h,j,l){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0;U=r;r=r+3488|0;S=U+3112|0;O=U+3104|0;F=U+3096|0;E=U+3088|0;R=U+3080|0;L=U+3072|0;I=U+3064|0;H=U+3056|0;J=U+3040|0;C=U+3032|0;p=U+3024|0;o=U+3016|0;D=U+2112|0;m=U+3468|0;n=U+3308|0;z=U+3320|0;q=U;T=U+3168|0;A=U+3144|0;y=U+3136|0;G=U+3124|0;Q=U+3120|0;k[f>>2]=26;K=f+4|0;k[K>>2]=26;M=f+8|0;k[M>>2]=26;k[g>>2]=0;N=g+4|0;k[N>>2]=0;P=g+8|0;k[P>>2]=0;k[h>>2]=0;k[h+4>>2]=0;k[h+8>>2]=0;k[h+12>>2]=0;k[h+16>>2]=0;k[h+20>>2]=0;k[j>>2]=0;i[l>>0]=0;if(e&8192|0){ze(D,a,b);if(!(e&512)){lc(n);B=(i[n>>0]&1)==0?n+1|0:k[n+8>>2]|0;k[p>>2]=b;k[p+4>>2]=B;pe(941016,985693,p);Ae(n)}else{mc(m);B=(i[m>>0]&1)==0?m+1|0:k[m+8>>2]|0;k[o>>2]=b;k[o+4>>2]=B;pe(941016,985674,o);Ae(m)}Ae(D)}if(!b)m=26;else{pd(D);k[z>>2]=941016;i[z+4>>0]=e>>>8&1;w=e>>>9&1;i[z+5>>0]=w;x=z+6|0;i[x>>0]=e>>>10&1;i[z+7>>0]=e>>>11&1;k[z+12>>2]=26;t=z+8|0;k[t>>2]=0;k[z+140>>2]=7896;o=z+144|0;k[o>>2]=0;m=z+16|0;n=m+120|0;do{k[m>>2]=0;m=m+4|0}while((m|0)<(n|0));u=e>>>12;gc(a,b,c,d,z);kd(q);kd(q+528|0);kd(q+1056|0);kd(q+1584|0);uc(T,a,b,c);k[o>>2]=T;n=A+4|0;o=A+12|0;k[A>>2]=0;k[A+4>>2]=0;k[A+8>>2]=0;k[A+12>>2]=0;k[A+16>>2]=26;k[y>>2]=0;s=jf(16384)|0;p=(e&4|0)!=0;if(p)qf(s|0,0,16384)|0;q=(e&2|0)==0;v=(e&1|0)!=0;B=0;while(1){if(!(Ac(T,A)|0)){o=21;break}m=k[n>>2]|0;if(q){if(!(v|(m|0)<2049)?Yb(k[A>>2]|0,m)|0:0){o=15;break}}else{m=Xb(k[A>>2]|0,m)|0;k[n>>2]=m}if(p){m=Wb(k[A>>2]|0,m,y,s)|0;k[n>>2]=m}k[t>>2]=k[o>>2];jd(A,z,D);B=m+B|0}if((o|0)==15){if(w|0){k[C>>2]=B;pe(941016,985708,C)}kf(s);m=kc(a,b,c,d,e|2,f,g,h,j,l)|0}else if((o|0)==21){kf(s);n=(w|0)!=0;m=u&1;if(n&(m|0)==0){if(!(i[x>>0]|0))se(1017206,5,1,941016);td(D)}p=(m|0)!=0;$b(D,n,p);sd(D);bc(D,B,G,f,g,h,j,l);do if(!(v|(B|0)<257)){if(i[l>>0]|0){m=k[g>>2]|0;if((m|0)>69){o=29;break}if(((k[N>>2]|0)+m|0)>92){o=29;break}}if(!(p|n^1))ac(f,g,j,l);if((B|0)<256){if(n){k[E>>2]=B;pe(941016,985862,E)}m=kc(a,b,c,d,e|93,f,g,h,j,l)|0;break}else{if(n){k[F>>2]=B;pe(941016,985937,F)}m=kc(a,b,c,d,e|13,f,g,h,j,l)|0;break}}else o=29;while(0);if((o|0)==29){Zb(D,n,p);sd(D);bc(D,B,G,f,g,h,j,l);cc(B,f,g,Q,l,n,p);m=n^1;if(!(p|m)){o=0;do{n=k[f+(o<<2)>>2]|0;if((n|0)!=26){j=Ec(n)|0;E=k[G+(o<<2)>>2]|0;F=k[g+(o<<2)>>2]|0;k[J>>2]=j;k[J+4>>2]=E;k[J+8>>2]=F;pe(941016,985771,J)}o=o+1|0}while((o|0)!=3);k[H>>2]=B;pe(941016,985761,H);H=Dc(k[Q>>2]|0)|0;J=i[l>>0]|0?32:42;k[I>>2]=H;k[I+4>>2]=J;pe(941016,985785,I);se(985793,9,1,941016)}if(m|p^1)m=k[Q>>2]|0;else{se(985803,37,1,941016);m=k[f>>2]|0;if((m|0)!=26){J=Ec(m)|0;g=k[g>>2]|0;k[L>>2]=J;k[L+4>>2]=g;pe(941016,985841,L)}m=k[K>>2]|0;if((m|0)!=26){L=Ec(m)|0;N=k[N>>2]|0;k[O>>2]=L;k[O+4>>2]=N;pe(941016,985841,O)}m=k[M>>2]|0;if((m|0)!=26){O=Ec(m)|0;P=k[P>>2]|0;k[S>>2]=O;k[S+4>>2]=P;pe(941016,985841,S)}m=k[Q>>2]|0;Q=Dc(m)|0;S=i[l>>0]|0?32:42;k[R>>2]=Q;k[R+4>>2]=S;pe(941016,985785,R);se(1017206,5,1,941016)}}}vc(T)}r=U;return m|0}function lc(a){a=a|0;ze(a,1097857,0);return}function mc(a){a=a|0;ze(a,1097857,0);return}function nc(a){a=a|0;a:do if(a>>>0>=256){if(a>>>0>=55296){switch(a&-16|0){case 64992:case 64976:{a=65533;break a}default:{}}if((a&65534|0)==65534)a=65533;else a=(a+-57344|0)>>>0<1056768?a:65533}}else a=k[7932+(a<<2)>>2]|0;while(0);return a|0}function oc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;a:do if((b|0)>0){g=0;c=0;d=0;while(1){f=i[a+g>>0]|0;if((f&-64)<<24>>24!=-128){e=(d|0)>7|((c|0)>24?1:((l[993817+((f&255)>>>4)>>0]|0)+g|0)>(b|0));if(e)break a;else d=(e&1^1)+d|0}switch(f<<24>>24){case 60:{f=1097824+c|0;i[f>>0]=38;i[f+1>>0]=108;i[f+2>>0]=116;i[f+3>>0]=59;c=c+4|0;break}case 62:{f=1097824+c|0;i[f>>0]=38;i[f+1>>0]=103;i[f+2>>0]=116;i[f+3>>0]=59;c=c+4|0;break}case 38:{f=1097824+c|0;i[f>>0]=i[993833]|0;i[f+1>>0]=i[993834]|0;i[f+2>>0]=i[993835]|0;i[f+3>>0]=i[993836]|0;i[f+4>>0]=i[993837]|0;c=c+5|0;break}case 39:{f=1097824+c|0;i[f>>0]=i[993839]|0;i[f+1>>0]=i[993840]|0;i[f+2>>0]=i[993841]|0;i[f+3>>0]=i[993842]|0;i[f+4>>0]=i[993843]|0;i[f+5>>0]=i[993844]|0;c=c+6|0;break}case 34:{f=1097824+c|0;i[f>>0]=i[993846]|0;i[f+1>>0]=i[993847]|0;i[f+2>>0]=i[993848]|0;i[f+3>>0]=i[993849]|0;i[f+4>>0]=i[993850]|0;i[f+5>>0]=i[993851]|0;c=c+6|0;break}default:{i[1097824+c>>0]=f;c=c+1|0}}g=g+1|0;if((g|0)>=(b|0))break a}}else c=0;while(0);i[1097824+c>>0]=0;return}function pc(a,b){a=a|0;b=b|0;do if(b>>>0>=128){if(b>>>0<2048){i[a>>0]=b>>>6|192;i[a+1>>0]=b&63|128;b=2;break}b=b>>>0>1114111?65533:b;if(b>>>0<65536){i[a>>0]=b>>>12|224;i[a+1>>0]=b>>>6&63|128;i[a+2>>0]=b&63|128;b=3;break}else{i[a>>0]=b>>>18|240;i[a+1>>0]=b>>>12&63|128;i[a+2>>0]=b>>>6&63|128;i[a+3>>0]=b&63|128;b=4;break}}else{i[a>>0]=b;b=1}while(0);return b|0}function qc(a,b){a=a|0;b=b|0;var c=0,d=0;d=r;r=r+16|0;c=d;if((b|0)>15)b=-1;else{tf(c|0,a|0,b|0)|0;i[c+b>>0]=0;b=Lc(c)|0;if((b|0)>-1)b=k[8956+(b<<3)+4>>2]|0;else b=-1}r=d;return b|0}function rc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0;j=a+b|0;a:do if((b|0)!=0?(i[a>>0]|0)==38:0){k[c>>2]=1;f=a+1|0;d=i[f>>0]|0;if(d<<24>>24==35){if((b|0)<4){d=-1;break}d=a+2|0;b:do switch(i[d>>0]|0){case 88:case 120:{d=a+3|0;do{if((i[d>>0]|0)!=48)break;d=d+1|0}while(d>>>0>>0);if((d|0)==(j|0)){d=-1;break a}f=i[d>>0]|0;if((f+-48&255)>=10)switch(f<<24>>24){case 65:case 66:case 67:case 68:case 69:case 70:case 97:case 98:case 99:case 100:case 101:case 102:break;default:{d=-1;break a}}c:do if(d>>>0>>0){e=f;b=d;while(1){if((e+-48&255)>=10)switch(e<<24>>24){case 65:case 66:case 67:case 68:case 69:case 70:case 97:case 98:case 99:case 100:case 101:case 102:break;default:{h=b;break c}}b=b+1|0;if(b>>>0>=j>>>0){h=b;break c}e=i[b>>0]|0}}else h=d;while(0);b=h;g=b-d|0;if((g|0)>=8?!((g|0)==8&f<<24>>24<56):0){d=65533;break b}d:do if(d>>>0>>0){g=f;e=0;while(1){f=e<<4;e=g<<24>>24;do if((g+-48&255)>=10)if((g+-97&255)<6){e=e+-87|0;break}else{e=(g+-65&255)<6?e+-55|0:0;break}else e=e+-48|0;while(0);f=e+f|0;e=d+1|0;if((e|0)==(h|0)){d=f;break d}d=e;g=i[e>>0]|0;e=f}}else d=0;while(0);d=nc(d)|0;break}case 48:{while(1){d=d+1|0;if(d>>>0>=j>>>0){l=32;break b}if((i[d>>0]|0)!=48){l=32;break}}break}default:l=32}while(0);do if((l|0)==32){if((d|0)==(j|0)){d=-1;break a}f=i[d>>0]|0;if((f+-48&255)>=10){d=-1;break a}e:do if(d>>>0>>0){b=d;while(1){b=b+1|0;if(b>>>0>=j>>>0){g=b;break e}if(((i[b>>0]|0)+-48&255)>=10){g=b;break}}}else g=d;while(0);b=g;e=b-d|0;if((e|0)>=9){if((e|0)!=10){d=65533;break}if((Yd(d,993853,10)|0)>=1){d=65533;break}}if(d>>>0>>0){e=(f<<24>>24)+-48|0;d=d+1|0;if((d|0)==(g|0))d=e;else{f=d;d=e;do{d=(d*10|0)+-48+(i[f>>0]|0)|0;f=f+1|0}while((f|0)!=(g|0))}}else d=0;d=nc(d)|0}while(0);if((d|0)==-1|b>>>0>j>>>0){d=-1;break}}else{g=f;if((b|0)>1?(d+-48&255)<10|((d&-33)+-65&255)<26:0){d=f;do{d=d+1|0;if(d>>>0>=j>>>0)break;h=i[d>>0]|0}while((h+-48&255)<10|((h&-33)+-65&255)<26);b=d;e=d}else{b=g;e=f}d=qc(f,b-g|0)|0;if((d|0)<0){d=-1;break}if((d|0)>255){if(e>>>0>=j>>>0){d=-1;break}if((i[e>>0]|0)!=59){d=-1;break}}}e=b;if(e>>>0>>0?(i[e>>0]|0)==59:0)b=e+1|0;k[c>>2]=b-a}else l=3;while(0);if((l|0)==3){k[c>>2]=0;d=-1}return d|0}function sc(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;b=rc(a,b,d)|0;if((b|0)>0)b=pc(c,b)|0;else{k[d>>2]=1;b=0}k[e>>2]=b;return}function tc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;f=a+b|0;a:do if((b|0)>0){d=a;e=1008264;while(1){e=l[e+(l[1009064+(l[d>>0]|0)>>0]|0)>>0]|0;if((e|0)<=(c|0))break;d=d+1|0;if(d>>>0>>0)e=1008264+(e*20|0)|0;else break a}switch(e|0){case 0:case 2:{b=d-a|0;break a}default:{}}b=d-a|0;while(1){d=b+-1|0;if((b|0)<=1)break a;if((i[a+d>>0]|0)==60)break;else b=d}}while(0);return b|0}function uc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;k[a>>2]=b;k[a+4>>2]=b;k[a+8>>2]=b+c;k[a+12>>2]=c;i[a+16>>0]=d&1;i[a+28>>0]=1;i[a+29>>0]=1;k[a+32>>2]=1;c=a+36|0;Nc(c);d=a+88|0;Nc(d);b=jf(40960)|0;k[a+20>>2]=b;b=jf(61440)|0;k[a+24>>2]=b;Oc(c);Oc(d);return}function vc(a){a=a|0;var b=0;b=k[a+20>>2]|0;if(b|0)kf(b);b=k[a+24>>2]|0;if(b|0)kf(b);Pc(a+88|0);Pc(a+36|0);return}function wc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0;u=r;r=r+32|0;o=u+12|0;s=u+8|0;q=u+4|0;n=u;p=u+16|0;k[q>>2]=0;a:do if((c|0)>0){m=a+16|0;j=a+32|0;a=0;e=0;while(1){wd(b+e|0,c-e|0,o);e=(k[o>>2]|0)+e|0;if((e|0)>=(c|0)){e=c;a=0;break a}g=b+e|0;h=i[g>>0]|0;f=h&255;b:do if(((h&-32)<<24>>24==32?(i[1009320+f>>0]|0)!=0:0)?(i[m>>0]|0)==0:0)switch(h<<24>>24){case 60:{a=tc(g,c-e|0,k[j>>2]|0)|0;k[q>>2]=a;break b}case 62:{k[q>>2]=1;a=1;break b}case 38:{sc(g,c-e|0,p,q,n);k[o>>2]=l[1009576+(l[p>>0]|0)>>0];k[s>>2]=p;a=(vd(s,o)|0)&255;t=12;break b}default:break b}else t=11;while(0);if((t|0)==11){a=l[1009576+f>>0]|0;k[q>>2]=a;k[o>>2]=a;k[s>>2]=g;a=(vd(s,o)|0)&255;t=12}if((t|0)==12){t=0;if(a|0)break a;a=k[q>>2]|0}e=a+e|0;if((e|0)>=(c|0)){a=0;break}}}else{e=0;a=0}while(0);k[d>>2]=a;r=u;return e|0}function xc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0;w=r;r=r+16|0;p=w+4|0;o=w;t=a+20|0;m=k[t>>2]|0;k[b>>2]=m;u=b+4|0;k[u>>2]=0;v=a+4|0;k[b+8>>2]=(k[v>>2]|0)-(k[a>>2]|0);k[b+12>>2]=0;k[b+16>>2]=26;l=b+20|0;i[l>>0]=0;s=a+12|0;n=k[s>>2]|0;n=(n+-40928|0)>>>0<40928?(n|0)/2|0:40896;i[m>>0]=32;i[(k[t>>2]|0)+1>>0]=0;b=k[s>>2]|0;if((b|0)<1)b=0;else{m=a+16|0;j=a+32|0;c=0;g=b;h=0;a=1;b=0;while(1){d=k[v>>2]|0;e=d+b|0;f=i[e>>0]|0;f=f<<24>>24==13?10:f;if(((f&-32)<<24>>24==32?(i[1009320+(f&255)>>0]|0)!=0:0)?(i[m>>0]|0)==0:0){a:do switch(f<<24>>24){case 60:{b:do if((b|0)<(g+-3|0))switch(i[d+(b+1)>>0]|32|0){case 112:{d=(i[d+(b+2)>>0]|0)<64?10:32;break b}case 98:{if((i[d+(b+2)>>0]|32|0)!=114){d=32;break b}d=(i[d+(b+3)>>0]|0)<64?10:32;break b}case 116:{if((i[d+(b+2)>>0]|32|0)!=114){d=32;break b}d=(i[d+(b+3)>>0]|0)<64?10:32;break b}default:{d=32;break b}}else d=32;while(0);c=(tc(e,g-b|0,k[j>>2]|0)|0)+1|0;k[p>>2]=c;if(h)switch(d<<24>>24){case 10:case 32:{e=d;d=1;break a}default:{}}i[(k[t>>2]|0)+a>>0]=d;e=d;d=d<<24>>24==32|d<<24>>24==10;a=a+1|0;break}case 62:{k[p>>2]=1;i[(k[t>>2]|0)+a>>0]=62;c=1;e=62;d=h;a=a+1|0;break}case 38:{sc(e,g-b|0,(k[t>>2]|0)+a|0,p,o);c=k[p>>2]|0;e=38;d=h;a=(k[o>>2]|0)+a|0;break}default:{e=f;d=h}}while(0);h=c;b=c+b|0}else{if(h)switch(f<<24>>24){case 10:case 32:{d=1;break}default:q=22}else q=22;if((q|0)==22){q=0;i[(k[t>>2]|0)+a>>0]=f;d=f<<24>>24==32|f<<24>>24==10;a=a+1|0}h=c;e=f;b=b+1|0}if(!((a|0)<(n|0)|e<<24>>24!=10&e<<24>>24!=32)){q=25;break}if((a|0)>40927){q=28;break}g=k[s>>2]|0;if((g|0)<=(b|0))break;else{c=h;h=d}}if((q|0)==25)i[l>>0]=1;else if((q|0)==28)i[l>>0]=1;d=k[v>>2]|0;c:do if((b|0)>0){c=b;while(1){if((i[d+c>>0]&-64)<<24>>24!=-128){b=c;break c}b=c+-1|0;a=a+-1|0;if((c|0)>1)c=b;else break}}while(0);k[v>>2]=d+b;k[s>>2]=(k[s>>2]|0)-b;i[(k[t>>2]|0)+a>>0]=32;i[(k[t>>2]|0)+(a+1)>>0]=32;i[(k[t>>2]|0)+(a+2)>>0]=32;i[(k[t>>2]|0)+(a+3)>>0]=0;k[u>>2]=a;b=1}r=w;return b|0}function yc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;C=r;r=r+32|0;s=C+16|0;v=C+12|0;c=C+8|0;u=C+4|0;t=C;if(!(i[a+28>>0]|0))b=xc(a,b)|0;else{z=a+20|0;y=k[z>>2]|0;k[b>>2]=y;A=b+4|0;k[A>>2]=0;B=a+4|0;o=b+8|0;k[o>>2]=(k[B>>2]|0)-(k[a>>2]|0);d=b+12|0;k[d>>2]=0;k[b+16>>2]=26;p=b+20|0;i[p>>0]=0;x=a+12|0;q=k[x>>2]|0;q=(q+-40928|0)>>>0<40928?(q|0)/2|0:40896;k[u>>2]=0;k[t>>2]=0;i[y>>0]=32;i[(k[z>>2]|0)+1>>0]=0;y=a+36|0;Oc(y);Vc(y,k[o>>2]|0);b=wc(a,k[B>>2]|0,k[x>>2]|0,c)|0;k[B>>2]=(k[B>>2]|0)+b;k[x>>2]=(k[x>>2]|0)-b;if((b|0)==1)Tc(y,1);else{Vc(y,b);Uc(y,1)}b=k[x>>2]|0;if((b|0)<1){Rc(y);b=0}else{o=k[c>>2]|0;k[d>>2]=o;m=a+16|0;n=a+29|0;j=a+32|0;d=b;c=1;a=0;b=0;do{a:do if((d|0)>(b|0)){g=a;while(1){f=(k[B>>2]|0)+b|0;a=i[f>>0]|0;e=a&255;b:do if(((a&-32)<<24>>24==32?(i[1009320+e>>0]|0)!=0:0)?(i[m>>0]|0)==0:0){switch(a<<24>>24){case 62:case 60:{h=c;c=0;break a}case 38:break;default:break b}sc(f,d-b|0,(k[z>>2]|0)+c|0,u,t);g=(k[z>>2]|0)+c|0;k[s>>2]=l[1009576+(l[g>>0]|0)>>0];k[v>>2]=g;g=(vd(v,s)|0)&255}else w=15;while(0);if((w|0)==15){w=0;a=l[1009576+e>>0]|0;k[t>>2]=a;k[u>>2]=a;e=(k[z>>2]|0)+c|0;if((b|0)<(d+-3|0)){h=l[f>>0]|l[f+1>>0]<<8|l[f+2>>0]<<16|l[f+3>>0]<<24;i[e>>0]=h;i[e+1>>0]=h>>8;i[e+2>>0]=h>>16;i[e+3>>0]=h>>24}else tf(e|0,f|0,a|0)|0;g=(k[B>>2]|0)+b|0;k[s>>2]=l[1009576+(l[g>>0]|0)>>0];k[v>>2]=g;g=(vd(v,s)|0)&255}if((g|0)!=40&(g|0)!=(o|0)){if(!g){h=c;c=0;break a}d=k[u>>2]|0;h=(k[B>>2]|0)+b+d|0;k[s>>2]=l[1009576+(l[h>>0]|0)>>0];k[v>>2]=h;h=vd(v,s)|0;if(!(h<<24>>24==0|(h&255|0)==(o|0))?(i[n>>0]|0)!=0:0){h=c;c=g;break a}}else d=k[u>>2]|0;b=d+b|0;a=k[t>>2]|0;c=a+c|0;do if((d|0)!=(a|0))if((d|0)<(a|0)){Tc(y,d);Uc(y,a-d|0);break}else{Tc(y,a);Vc(y,d-a|0);break}else Tc(y,d);while(0);if((c|0)>40927)break;d=k[x>>2]|0;if((d|0)<=(b|0)){h=c;c=g;break a}}i[p>>0]=1;h=c;c=g}else{h=c;c=a}while(0);d=k[x>>2]|0;c:do if((d|0)>(b|0))while(1){wd((k[B>>2]|0)+b|0,d-b|0,s);d=k[s>>2]|0;k[u>>2]=d;b=d+b|0;Vc(y,d);d=k[x>>2]|0;if((d|0)<=(b|0)){a=c;break c}a=(k[B>>2]|0)+b|0;e=i[a>>0]|0;f=e&255;d:do if(((e&-32)<<24>>24==32?(i[1009320+f>>0]|0)!=0:0)?(i[m>>0]|0)==0:0)switch(e<<24>>24){case 60:{c=tc(a,d-b|0,k[j>>2]|0)|0;k[u>>2]=c;break d}case 62:{k[u>>2]=1;c=1;break d}case 38:{sc(a,d-b|0,(k[z>>2]|0)+h|0,u,t);c=(k[z>>2]|0)+h|0;k[s>>2]=l[1009576+(l[c>>0]|0)>>0];k[v>>2]=c;c=(vd(v,s)|0)&255;w=42;break d}default:{w=42;break d}}else w=41;while(0);if((w|0)==41){c=l[1009576+f>>0]|0;k[u>>2]=c;k[s>>2]=c;k[v>>2]=a;c=(vd(v,s)|0)&255;w=42}if((w|0)==42){w=0;if(c|0){a=c;break c}c=k[u>>2]|0}b=c+b|0;Vc(y,c);d=k[x>>2]|0;if((d|0)<=(b|0)){a=0;break}else c=0}else a=c;while(0);c=h+1|0;i[(k[z>>2]|0)+h>>0]=32;Uc(y,1);if((a|0)!=40&(a|0)!=(o|0))break;if((c|0)>=(q|0)){w=48;break}d=k[x>>2]|0}while((b|0)<(d|0));if((w|0)==48)i[p>>0]=1;e=k[x>>2]|0;e:do if((b|0)>0){a=(b|0)<(e|0);d=b;while(1){if(!a){b=d;break e}if((i[(k[B>>2]|0)+d>>0]&-64)<<24>>24!=-128){b=d;break e}b=d+-1|0;c=c+-1|0;if((d|0)>1)d=b;else break}}while(0);k[B>>2]=(k[B>>2]|0)+b;k[x>>2]=e-b;i[(k[z>>2]|0)+c>>0]=32;i[(k[z>>2]|0)+(c+1)>>0]=32;i[(k[z>>2]|0)+(c+2)>>0]=32;i[(k[z>>2]|0)+(c+3)>>0]=0;Uc(y,4);Rc(y);k[A>>2]=c;b=1}}r=C;return b|0}function zc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0;c=r;r=r+16|0;g=c+4|0;d=a+88|0;Oc(d);e=b+4|0;f=a+24|0;xd(k[b>>2]|0,(k[e>>2]|0)+3|0,k[f>>2]|0,61440,(i[a+16>>0]|0)!=0,c+8|0,g,c,d);a=k[g>>2]|0;i[(k[f>>2]|0)+a>>0]=0;k[b>>2]=k[f>>2];k[e>>2]=a+-3;Rc(d);r=c;return}function Ac(a,b){a=a|0;b=b|0;var c=0;c=yc(a,b)|0;zc(a,b);return c|0}function Bc(a){a=a|0;a=(a|0)<0?0:a;return k[15988+(((a|0)>101?0:a)<<2)>>2]|0}function Cc(a){a=a|0;a=(a|0)<0?0:a;return k[16396+(((a|0)>101?0:a)<<2)>>2]|0}function Dc(a){a=a|0;a=(a|0)<0?26:a;return k[11076+(((a|0)>613?26:a)<<2)>>2]|0}function Ec(a){a=a|0;a=(a|0)<0?26:a;return k[13532+(((a|0)>613?26:a)<<2)>>2]|0}function Fc(a){a=a|0;do switch(a|0){case 40:case 38:{a=1;break}case 105:{a=2;break}case 135:{a=2;break}case 17:{a=3;break}case 68:{a=3;break}case 84:{a=4;break}case 83:{a=4;break}case 78:{a=5;break}case 28:{a=5;break}case 29:{a=5;break}case 160:{a=5;break}case 35:{a=6;break}case 64:{a=6;break}case 51:{a=6;break}case 43:{a=6;break}case 10:{a=7;break}case 80:{a=7;break}case 1:{a=7;break}case 31:{a=8;break}case 14:{a=8;break}case 12:{a=8;break}case 143:{a=9;break}case 147:{a=9;break}default:a=0}while(0);return a|0}function Gc(a){a=a|0;if(a>>>0>101)a=26;else a=k[16804+(a<<2)>>2]|0;return a|0}function Hc(a){a=a|0;if((a|0)<512)a=i[992810+a>>0]|0;else a=0;return a|0}function Ic(a,b){a=a|0;b=b|0;do if(a>>>0<=101){if((k[16396+(a<<2)>>2]|0)>>>0<2){b=k[16804+(a<<2)>>2]|0;break}b=b&255;if((a|0)==1){b=m[941344+(b<<1)>>1]|0;break}else{b=m[941856+(b<<1)>>1]|0;break}}else b=26;while(0);return b|0}function Jc(a){a=a|0;if((a|0)<512)a=(m[941344+((l[992810+a>>0]|0)<<1)>>1]|0|0)==(a|0);else a=0;return a|0}function Kc(a){a=a|0;if((a|0)<512)a=(m[941856+((l[992810+a>>0]|0)<<1)>>1]|0|0)==(a|0);else a=0;return a|0}function Lc(a){a=a|0;var b=0,c=0,d=0,e=0;c=0;e=265;a:while(1)while(1){if((c|0)>=(e|0)){b=-1;break a}b=c+e>>1;d=_d(a,k[8956+(b<<3)>>2]|0)|0;if((d|0)<0){e=b;continue a}if((d|0)>0)c=b+1|0;else break a}return b|0}function Mc(a){a=a|0;switch(a|0){case 1:{a=0;break}case 3:{a=1;break}case 6:{a=2;break}default:a=3}return a|0}function Nc(a){a=a|0;var b=0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=1;a=a+16|0;b=a+36|0;do{k[a>>2]=0;a=a+4|0}while((a|0)<(b|0));return}function Oc(a){a=a|0;var b=0;if(!(i[a>>0]&1)){i[a+1>>0]=0;i[a>>0]=0}else{i[k[a+8>>2]>>0]=0;k[a+4>>2]=0}k[a+12>>2]=1;a=a+16|0;b=a+36|0;do{k[a>>2]=0;a=a+4|0}while((a|0)<(b|0));return}function Pc(a){a=a|0;Ae(a);return}function Qc(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0,j=0;j=a+16|0;g=k[j>>2]|0;do if(g|0){h=a+12|0;b=k[h>>2]|0;if((b|0)==1){e=i[a>>0]|0;f=(e&1)==0;if(f)c=(e&255)>>>1;else c=k[a+4>>2]|0;if(c|0){if(f){c=(e&255)>>>1;d=a+1|0}else{c=k[a+4>>2]|0;d=k[a+8>>2]|0}d=i[d+(c+-1)>>0]|0;if((d&-64)<<24>>24==64?(g+(d&63)|0)>>>0<64:0){if(f){c=(e&255)>>>1;b=a+1|0}else{c=k[a+4>>2]|0;b=k[a+8>>2]|0}a=b+(c+-1)|0;i[a>>0]=(l[a>>0]|0)+g;k[j>>2]=0;break}}}if(g>>>0>63){c=g;d=0;e=30;while(1){b=c>>>e&63;if(d|(b|0)!=0){Ge(a,b&255);b=1}else b=0;if((e|0)<=6)break;c=k[j>>2]|0;d=b;e=e+-6|0}c=k[j>>2]|0;b=k[h>>2]|0}else c=g;Ge(a,(c&63|b<<6)&255);k[j>>2]=0}while(0);return}function Rc(a){a=a|0;Sc(a);a=a+20|0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=0;k[a+16>>2]=0;k[a+20>>2]=0;return}function Sc(a){a=a|0;var b=0,c=0;if(!(k[a+16>>2]|0)){b=i[a>>0]|0;if(!(b&1))b=(b&255)>>>1;else b=k[a+4>>2]|0;if(!b)c=6}else c=6;if((c|0)==6){Tc(a,1);Qc(a)}return}function Tc(a,b){a=a|0;b=b|0;var c=0;do if(b|0){c=a+44|0;k[c>>2]=(k[c>>2]|0)+b;c=a+48|0;k[c>>2]=(k[c>>2]|0)+b;c=a+12|0;if((k[c>>2]|0)==1){a=a+16|0;k[a>>2]=(k[a>>2]|0)+b;break}else{Qc(a);k[c>>2]=1;k[a+16>>2]=b;break}}while(0);return}function Uc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;do if(b|0){d=a+48|0;k[d>>2]=(k[d>>2]|0)+b;d=a+12|0;e=k[d>>2]|0;if((e|0)==2){a=a+16|0;k[a>>2]=(k[a>>2]|0)+b;break}c=a+16|0;if((b|0)==1&(e|0)==3?(k[c>>2]|0)==1:0){k[d>>2]=1;break}Qc(a);k[d>>2]=2;k[c>>2]=b}while(0);return}function Vc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;do if(b|0){d=a+44|0;k[d>>2]=(k[d>>2]|0)+b;d=a+12|0;e=k[d>>2]|0;if((e|0)==3){a=a+16|0;k[a>>2]=(k[a>>2]|0)+b;break}c=a+16|0;if((b|0)==1&(e|0)==2?(k[c>>2]|0)==1:0){k[d>>2]=1;break}Qc(a);k[d>>2]=3;k[c>>2]=b}while(0);return}function Wc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,l=0,n=0,o=0,p=0,q=0,s=0,t=0;t=r;r=r+16|0;l=t;od(f,l);h=k[l>>2]|0;o=Ic(a,h&255)|0;l=k[l+4>>2]|0;q=Ic(a,l&255)|0;n=f+16|0;if((d|0)>0)s=(m[n+(h<<1)>>1]<<10|0)/(d|0)|0;else s=0;p=(Mc(a)|0)+(o<<2)|0;p=j[(k[(k[e+140>>2]|0)+32>>2]|0)+(p<<1)>>1]|0;j[g>>1]=c;j[g+2>>1]=b;j[g+4>>1]=o;j[g+6>>1]=q;c=j[n+(h<<1)>>1]|0;j[g+8>>1]=c;h=j[n+(l<<1)>>1]|0;j[g+10>>1]=h;j[g+12>>1]=d;e=k[f+12>>2]|0;j[g+14>>1]=e;j[g+16>>1]=a;e=(nb(c&65535,h&65535,e&65535)|0)&255;h=g+18|0;i[h>>0]=e;e=Fc(o)|0;if(e|0?(e|0)==(Fc(q)|0):0)i[h>>0]=100;s=(ob(s,p)|0)&255;i[g+19>>0]=s;r=t;return}function Xc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;e=(k[a+8>>2]|0)==1;f=e?a+96|0:a+116|0;d=e?a+16|0:a+36|0;c=k[d+4>>2]|0;if(c|0)ib(c,b);c=k[d+8>>2]|0;if(c|0)ib(c,b);c=k[d+12>>2]|0;if(c|0)ib(c,b);c=k[d+16>>2]|0;if(c|0)ib(c,b);e=e?a+56|0:a+76|0;c=k[f+4>>2]|0;if(c|0)ib(c,b);c=k[f+8>>2]|0;if(c|0)ib(c,b);c=k[f+12>>2]|0;if(c|0)ib(c,b);c=k[f+16>>2]|0;if(c|0)ib(c,b);d=b+16|0;c=k[e+4>>2]|0;if(c|0)j[d+((c>>>8&255)<<1)>>1]=0;c=k[e+8>>2]|0;if(c|0)j[d+((c>>>8&255)<<1)>>1]=0;c=k[e+12>>2]|0;if(c|0)j[d+((c>>>8&255)<<1)>>1]=0;c=k[e+16>>2]|0;if(c|0)j[d+((c>>>8&255)<<1)>>1]=0;return}function Yc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,l=0,n=0,o=0,p=0,q=0,s=0,t=0;t=r;r=r+16|0;h=t;s=k[b+56064+(c<<2)>>2]|0;q=k[b+56064+(c+1<<2)>>2]|0;ld(f);k[e+16>>2]=0;k[e+20>>2]=0;if(i[d+7>>0]|0){p=k[d>>2]|0;k[h>>2]=s;k[h+4>>2]=q;pe(p,1017069,h)}k[e>>2]=s;k[e+12>>2]=q-s;if((q|0)>(s|0)){h=d+96|0;l=d+8|0;n=d+116|0;p=s;do{o=k[b+24056+(p<<3)+4>>2]|0;ib(o,f);e=b+24056+(p<<3)+2|0;c=j[e>>1]|0;if((c&65535)<2){md(f);c=j[e>>1]|0}if(c<<16>>16==3){e=(k[l>>2]|0)==1?h:n;c=k[e>>2]|0;k[e+4+(c<<2)>>2]=o;k[e>>2]=c+1&3}p=p+1|0}while((p|0)!=(q|0))}Xc(d,f);p=m[b+24056+(s<<3)>>1]|0;Wc(a,s,p,(m[b+24056+(q<<3)>>1]|0)-p|0,d,f,g);k[d+12>>2]=m[g+4>>1];r=t;return}function Zc(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0;x=r;r=r+608|0;w=x+552|0;s=x+528|0;p=x;q=x+576|0;k[w>>2]=0;k[w+4>>2]=0;k[w+8>>2]=0;k[w+12>>2]=0;k[w+16>>2]=0;k[w+20>>2]=0;k[s>>2]=0;k[s+4>>2]=0;k[s+8>>2]=0;k[s+12>>2]=0;k[s+16>>2]=0;k[s+20>>2]=0;g=b+24|0;if((k[g>>2]|0)>0){i=s+12|0;l=s+16|0;m=s+4|0;n=s+20|0;o=s+8|0;t=0;do{kd(p);Yc(a,b,t,c,s,p,q);h=k[d>>2]|0;if((h|0)<50){u=d+4+(h*20|0)|0;f=q;v=u+20|0;do{j[u>>1]=j[f>>1]|0;u=u+2|0;f=f+2|0}while((u|0)<(v|0));h=(k[d>>2]|0)+1|0;k[d>>2]=h};k[w>>2]=k[s>>2];k[w+4>>2]=k[s+4>>2];k[w+8>>2]=k[s+8>>2];k[w+12>>2]=k[s+12>>2];k[w+16>>2]=k[s+16>>2];k[w+20>>2]=k[s+20>>2];k[s>>2]=(k[s>>2]|0)+(k[i>>2]|0);k[m>>2]=(k[m>>2]|0)+(k[l>>2]|0);k[o>>2]=(k[o>>2]|0)+(k[n>>2]|0);t=t+1|0}while((t|0)<(k[g>>2]|0))}else h=k[d>>2]|0;i=k[b+20>>2]|0;f=j[b+24056+(i<<3)>>1]|0;g=d+4+(h*20|0)|0;u=g;v=u+20|0;do{j[u>>1]=0;u=u+2|0}while((u|0)<(v|0));j[g>>1]=f;j[d+4+(h*20|0)+2>>1]=i;k[e>>2]=k[w>>2];k[e+4>>2]=k[w+4>>2];k[e+8>>2]=k[w+8>>2];k[e+12>>2]=k[w+12>>2];k[e+16>>2]=k[w+16>>2];k[e+20>>2]=k[w+20>>2];r=x;return}function _c(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;if((k[a>>2]|0)>0){c=0;do{e=l[a+4+(c*20|0)+18>>0]|0;d=l[a+4+(c*20|0)+19>>0]|0;qd(b,j[a+4+(c*20|0)+4>>1]|0,m[a+4+(c*20|0)+12>>1]|0,m[a+4+(c*20|0)+8>>1]|0,e>>>0>>0?e:d);c=c+1|0}while((c|0)<(k[a>>2]|0))}return}function $c(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0;p=r;r=r+112|0;o=p+96|0;n=p+80|0;l=p+64|0;h=p+48|0;g=p+32|0;i=p+16|0;e=p;t=Bc(k[c>>2]|0)|0;d=c+8|0;s=k[d>>2]|0;j=c+12|0;q=k[j>>2]|0;m=c+16|0;f=k[m>>2]|0;k[e>>2]=t;k[e+4>>2]=s;k[e+8>>2]=q;k[e+12>>2]=f;pe(a,1017096,e);e=c+4|0;a:do if((k[e>>2]|0)>0){f=0;do{if((f|0)<(k[d>>2]|0)){s=k[c+32+(f<<3)>>2]|0;t=k[c+32+(f<<3)+4>>2]|0;oc(b+s|0,6);k[i>>2]=f;k[i+4>>2]=s;k[i+8>>2]=(t|0)<0?(t&2147483647)+2e9|0:t;k[i+12>>2]=1097824;pe(a,1017160,i)}if((f|0)<(k[j>>2]|0)){s=k[c+8040+(f<<3)>>2]|0;t=k[c+8040+(f<<3)+4>>2]|0;oc(b+s|0,12);k[g>>2]=f;k[g+4>>2]=s;k[g+8>>2]=t;k[g+12>>2]=1097824;pe(a,1017175,g)}if((f|0)<(k[m>>2]|0)){s=k[c+16048+(f<<3)>>2]|0;t=k[c+16048+(f<<3)+4>>2]|0;oc(b+s|0,12);k[h>>2]=f;k[h+4>>2]=s;k[h+8>>2]=t;k[h+12>>2]=1097824;pe(a,1017191,h)}if((f|0)<(k[d>>2]|0))se(1017206,5,1,a);if((f|0)>50)break a;f=f+1|0}while((f|0)<(k[e>>2]|0))}while(0);d=k[d>>2]|0;if((d|0)>50){s=k[c+32+(d<<3)>>2]|0;t=k[c+32+(d<<3)+4>>2]|0;oc(b+s|0,6);k[l>>2]=d;k[l+4>>2]=s;k[l+8>>2]=(t|0)<0?(t&2147483647)+2e9|0:t;k[l+12>>2]=1097824;pe(a,1017160,l)}d=k[j>>2]|0;if((d|0)>50){s=k[c+8040+(d<<3)>>2]|0;t=k[c+8040+(d<<3)+4>>2]|0;oc(b+s|0,12);k[n>>2]=d;k[n+4>>2]=s;k[n+8>>2]=t;k[n+12>>2]=1097824;pe(a,1017175,n)}d=k[m>>2]|0;if((d|0)>50){s=k[c+16048+(d<<3)>>2]|0;t=k[c+16048+(d<<3)+4>>2]|0;oc(b+s|0,12);k[o>>2]=d;k[o+4>>2]=s;k[o+8>>2]=t;k[o+12>>2]=1097824;pe(a,1017191,o)}se(1017206,5,1,a);r=p;return}function ad(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0,n=0,o=0;l=r;r=r+48|0;j=l+40|0;g=l+16|0;h=l+8|0;d=l;f=c+20|0;k[d>>2]=k[f>>2];pe(a,1017212,d);d=k[f>>2]|0;if((d|0)>=0){e=0;while(1){if(!((e|0)>50&(e|0)<(d+-1|0))){o=m[c+24056+(e<<3)>>1]|0;n=i[1017266+(m[c+24056+(e<<3)+2>>1]|0)>>0]|0;d=k[c+24056+(e<<3)+4>>2]|0;oc(b+o|0,6);k[g>>2]=e;k[g+4>>2]=o;k[g+8>>2]=n;k[g+12>>2]=d;k[g+16>>2]=1097824;pe(a,1017271,g);d=k[f>>2]|0}if((e|0)<(d|0))e=e+1|0;else break}}se(1017206,5,1,a);e=c+24|0;k[h>>2]=k[e>>2];pe(a,1017242,h);if((k[e>>2]|0)>=0){d=0;while(1){o=k[c+56064+(d<<2)>>2]|0;k[j>>2]=d;k[j+4>>2]=o;pe(a,1017294,j);if((d|0)<(k[e>>2]|0))d=d+1|0;else break}}se(1017206,5,1,a);r=l;return}function bd(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,l=0,n=0,o=0,p=0;c=r;r=r+48|0;d=c;p=m[b>>1]|0;o=m[b+2>>1]|0;n=Ec(m[b+4>>1]|0)|0;l=m[b+8>>1]|0;i=Ec(m[b+6>>1]|0)|0;h=m[b+10>>1]|0;g=m[b+12>>1]|0;f=m[b+14>>1]|0;e=Bc(m[b+16>>1]|0)|0;b=j[b+18>>1]|0;k[d>>2]=p;k[d+4>>2]=o;k[d+8>>2]=n;k[d+12>>2]=l;k[d+16>>2]=i;k[d+20>>2]=h;k[d+24>>2]=g;k[d+28>>2]=f;k[d+32>>2]=e;k[d+36>>2]=b&255;k[d+40>>2]=(b&65535)>>>8&65535;pe(a,1017302,d);r=c;return}function cd(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;e=r;r=r+16|0;d=e+8|0;c=e;k[c>>2]=k[b>>2];pe(a,1017351,c);se(1017382,101,1,a);if((k[b>>2]|0)>=0){c=0;while(1){k[d>>2]=c;pe(a,1017484,d);bd(a,b+4+(c*20|0)|0);if((c|0)<(k[b>>2]|0))c=c+1|0;else break}}se(1017206,5,1,a);r=e;return}function dd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;d=k[a+140>>2]|0;if(b){t=k[d+4>>2]|0;r=0;s=t;b=d+8|0;d=d+12|0}else{r=1;s=k[d+16>>2]|0;t=k[d+20>>2]|0;b=d+24|0;d=d+28|0}e=k[b>>2]|0;b=k[d>>2]|0;o=c+8|0;d=k[o>>2]|0;p=k[c+12>>2]|0;q=k[c+16>>2]|0;j[c+24056>>1]=k[c+28>>2];j[c+24058>>1]=r;n=pb(Gc(k[a+8>>2]|0)|0,1)|0;k[c+24060>>2]=n;if((q|0)>0|((p|0)>0|(d|0)>0)){n=b+4|0;m=e+4|0;g=0;i=0;l=0;b=1;while(1){h=k[c+32+(g<<3)>>2]|0;f=k[c+8040+(i<<3)>>2]|0;a=k[c+16048+(l<<3)>>2]|0;do if((i|0)>=(p|0)|(f|0)>(h|0)|(f|0)>(a|0)){if(!((a|0)>(f|0)|((l|0)>=(q|0)|(a|0)>(h|0)))){f=l+1|0;e=k[(k[n>>2]|0)+(k[c+16048+(l<<3)+4>>2]<<2)>>2]|0;if(!e){a=i;e=f;break}j[c+24056+(b<<3)>>1]=a;j[c+24056+(b<<3)+2>>1]=3;k[c+24056+(b<<3)+4>>2]=e;a=i;e=f;b=b+1|0;break}f=k[c+32+(g<<3)+4>>2]|0;a=f&2147483647;f=(f|0)<0?t:s;g=g+1|0;e=k[f+8>>2]|0;if((a|0)<(e|0)){e=k[(k[f+4>>2]|0)+(a<<2)>>2]|0;if(!e){a=i;e=l;break}j[c+24056+(b<<3)>>1]=h;j[c+24056+(b<<3)+2>>1]=r;k[c+24056+(b<<3)+4>>2]=e;a=i;e=l;b=b+1|0;break}a=a-e+a|0;f=k[f+4>>2]|0;e=k[f+(a<<2)>>2]|0;a=k[f+(a+1<<2)>>2]|0;if(e){j[c+24056+(b<<3)>>1]=h;j[c+24056+(b<<3)+2>>1]=r;k[c+24056+(b<<3)+4>>2]=e;b=b+1|0}if(!a){a=i;e=l}else{j[c+24056+(b<<3)>>1]=h;j[c+24056+(b<<3)+2>>1]=r;k[c+24056+(b<<3)+4>>2]=a;a=i;e=l;b=b+1|0}}else{a=i+1|0;e=k[(k[m>>2]|0)+(k[c+8040+(i<<3)+4>>2]<<2)>>2]|0;if(!e)e=l;else{j[c+24056+(b<<3)>>1]=f;j[c+24056+(b<<3)+2>>1]=2;k[c+24056+(b<<3)+4>>2]=e;e=l;b=b+1|0}}while(0);if((e|0)<(q|0)|((a|0)<(p|0)|(g|0)<(d|0))){i=a;l=e}else break}d=k[o>>2]|0}else b=1;k[c+20>>2]=b;j[c+24056+(b<<3)>>1]=k[c+32+(d<<3)>>2];k[c+24056+(b<<3)+4>>2]=0;return}function ed(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,n=0,o=0;o=b&1^1;i=b?50:20;j=c+20|0;e=k[j>>2]|0;b=k[c+8>>2]|0;if((b|0)>0){l=(i>>>1)+i|0;n=i<<1;h=b;f=0;d=0;b=a;do{if((h|0)>=(l|0))if((h|0)<(n|0))g=h+1>>1;else g=i;else g=h;k[c+56064+(d<<2)>>2]=f;k[c+56268+(d<<2)>>2]=b;d=d+1|0;if((f|0)<(e|0)&(g|0)>0){a=0;b=f;do{a=((m[c+24056+(b<<3)+2>>1]|0|0)==(o|0)&1)+a|0;b=b+1|0}while((b|0)<(e|0)&(a|0)<(g|0));f=b}b=m[c+24056+(f<<3)>>1]|0;h=h-g|0}while((h|0)>0);e=k[j>>2]|0}else{k[c+56064>>2]=0;k[c+56268>>2]=m[c+24056>>1];d=1;b=a}k[c+24>>2]=d;k[c+56064+(d<<2)>>2]=e;k[c+56268+(d<<2)>>2]=b;return}function fd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0;j=r;r=r+1056|0;h=j+24|0;g=c+7|0;if(i[g>>0]|0){se(1017490,12,1,k[c>>2]|0);$c(k[c>>2]|0,k[a>>2]|0,f)}dd(c,e,f);ed(b,e,f);if(i[g>>0]|0){se(1017503,9,1,k[c>>2]|0);ad(k[c>>2]|0,k[a>>2]|0,f)}k[h>>2]=0;Zc(k[a+12>>2]|0,f,c,h,j);if(i[g>>0]|0)cd(k[c>>2]|0,h);_c(h,d);r=j;return}function gd(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;qd(d,(Gc(b)|0)&65535,a,a,100);k[c+12>>2]=26;return}function hd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0;p=r;r=r+16|0;o=p;d=gf(56472)|0;k[d+4>>2]=1e3;l=d+8|0;k[d+8040>>2]=0;k[d+8044>>2]=0;k[d+16048>>2]=0;k[d+16052>>2]=0;j[d+24056>>1]=0;k[d+24060>>2]=0;k[d+56064>>2]=0;k[d+56268>>2]=0;k[l>>2]=0;k[l+4>>2]=0;k[l+8>>2]=0;k[l+12>>2]=0;k[l+16>>2]=0;k[l+20>>2]=0;k[l+24>>2]=0;k[l+28>>2]=0;k[d>>2]=k[a+12>>2];e=b+12|0;k[e>>2]=26;k[b+136>>2]=0;f=d+28|0;k[f>>2]=1;g=k[a+4>>2]|0;if((g|0)>1){h=b+7|0;n=b+140|0;m=1;do{if(i[h>>0]|0){q=k[b>>2]|0;k[o>>2]=m;k[o+4>>2]=g;pe(q,1017513,o)}q=m;m=jb(k[a>>2]|0,m,g,k[k[n>>2]>>2]|0,d)|0;s=k[n>>2]|0;kb(k[a>>2]|0,q,m,k[s+8>>2]|0,k[s+12>>2]|0,d);fd(a,q,b,c,1,d);k[l>>2]=0;k[l+4>>2]=0;k[l+8>>2]=0;k[l+12>>2]=0;k[l+16>>2]=0;k[f>>2]=m}while((m|0)<(g|0))}Qe(d);k[e>>2]=26;r=p;return}function id(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,l=0,m=0;d=gf(56472)|0;k[d+4>>2]=1e3;g=d+8|0;k[d+8040>>2]=0;k[d+8044>>2]=0;k[d+16048>>2]=0;k[d+16052>>2]=0;j[d+24056>>1]=0;k[d+24060>>2]=0;k[d+56064>>2]=0;k[d+56268>>2]=0;k[g>>2]=0;k[g+4>>2]=0;k[g+8>>2]=0;k[g+12>>2]=0;k[g+16>>2]=0;k[g+20>>2]=0;k[g+24>>2]=0;k[g+28>>2]=0;k[d>>2]=k[a+12>>2];k[b+12>>2]=26;k[b+136>>2]=0;e=d+28|0;k[e>>2]=1;f=k[a+4>>2]|0;if((f|0)>1){i=b+140|0;h=1;do{m=k[i>>2]|0;l=h;h=lb(k[a>>2]|0,h,f,k[m+16>>2]|0,k[m+20>>2]|0,d)|0;m=k[i>>2]|0;mb(k[a>>2]|0,l,h,k[m+24>>2]|0,k[m+28>>2]|0,d);fd(a,l,b,c,0,d);k[g>>2]=0;k[g+4>>2]=0;k[g+8>>2]=0;k[g+12>>2]=0;k[g+16>>2]=0;k[e>>2]=h}while((h|0)<(f|0))}Qe(d);return}function jd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0;g=r;r=r+32|0;f=g+16|0;e=g;d=g+20|0;if(!(i[b+7>>0]|0))d=a+12|0;else{l=k[b>>2]|0;h=a+12|0;n=Bc(k[h>>2]|0)|0;j=a+4|0;m=k[j>>2]|0;k[e>>2]=n;k[e+4>>2]=m;pe(l,1017545,e);ze(e,k[a>>2]|0,k[j>>2]|0);j=k[b>>2]|0;mc(d);k[f>>2]=(i[d>>0]&1)==0?d+1|0:k[d+8>>2]|0;pe(j,1017576,f);Ae(d);se(1017206,5,1,k[b>>2]|0);Ae(e);d=h}k[b+12>>2]=26;k[b+136>>2]=0;n=Cc(k[d>>2]|0)|0;switch(((n|0)!=3&(i[b+4>>0]|0)!=0?2:n)|0){case 1:case 0:{gd(k[a+4>>2]|0,k[a+12>>2]|0,b,c);break}case 3:{hd(a,b,c);break}case 2:{id(a,b,c);break}default:{}}r=g;return}function kd(a){a=a|0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=0;return}function ld(a){a=a|0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=0;return}function md(a){a=a|0;a=a+12|0;k[a>>2]=(k[a>>2]|0)+1;return}function nd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0;b=b&255;d=b>>>2;e=sf(1,0,d|0)|0;f=L;h=a;g=k[h>>2]|0;h=k[h+4>>2]|0;if((g&e|0)==0&(h&f|0)==0){d=a+16+(d<<3)|0;k[d>>2]=0;k[d+4>>2]=0;d=a;k[d>>2]=g|e;k[d+4>>2]=h|f}a=a+16+(b<<1)|0;j[a>>1]=(m[a>>1]|0)+c;return}function od(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,n=0,o=0,p=0,q=0;q=r;r=r+16|0;p=q;k[b>>2]=-1;n=b+4|0;k[n>>2]=-1;o=b+8|0;k[o>>2]=-1;k[p>>2]=-1;k[p+4>>2]=-1;k[p+8>>2]=-1;d=a;c=k[d>>2]|0;d=k[d+4>>2]|0;if(!((c|0)==0&(d|0)==0)){i=a+16|0;j=p+8|0;l=p+4|0;g=0;while(1){if(!((c&1|0)==0&0==0)){h=0;do{e=h+g|0;f=m[i+(e<<1)>>1]|0;if((f|0)>(k[j>>2]|0)){a=k[l>>2]|0;if((f|0)>(a|0)){k[j>>2]=a;k[o>>2]=k[n>>2];a=k[p>>2]|0;if((f|0)>(a|0)){k[l>>2]=a;k[n>>2]=k[b>>2];a=0}else a=1}else a=2;k[p+(a<<2)>>2]=f;k[b+(a<<2)>>2]=e}h=h+1|0}while((h|0)!=4)}c=rf(c|0,d|0,1)|0;d=L;if((c|0)==0&(d|0)==0)break;else g=g+4|0}}r=q;return}function pd(a){a=a|0;var b=0;b=a+536|0;k[b>>2]=0;k[b+4>>2]=0;k[b+8>>2]=0;k[b+12>>2]=0;k[b+16>>2]=0;k[b+20>>2]=0;k[b+24>>2]=0;k[b+28>>2]=0;k[a>>2]=0;k[a+4>>2]=0;k[a+8>>2]=0;k[a+12>>2]=0;k[a+16>>2]=0;k[a+20>>2]=0;a=a+568|0;b=a+48|0;do{k[a>>2]=-1;a=a+4|0}while((a|0)<(b|0));return}function qd(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,l=0,m=0;k[a>>2]=(k[a>>2]|0)+1;g=b&65535;l=g&15;m=j[a+568+(l<<1)>>1]|0;do if(m<<16>>16==b<<16>>16){b=a+616+(l<<2)|0;k[b>>2]=(k[b>>2]|0)+c;b=a+712+(l<<2)|0;k[b>>2]=(k[b>>2]|0)+d;d=ha(e,c)|0;a=a+808+(l<<2)|0;k[a>>2]=(k[a>>2]|0)+d}else{f=l^8;i=j[a+568+(f<<1)>>1]|0;if(i<<16>>16==b<<16>>16){b=a+616+(f<<2)|0;k[b>>2]=(k[b>>2]|0)+c;b=a+712+(f<<2)|0;k[b>>2]=(k[b>>2]|0)+d;d=ha(e,c)|0;a=a+808+(f<<2)|0;k[a>>2]=(k[a>>2]|0)+d;break}g=g&7|16;h=j[a+568+(g<<1)>>1]|0;if(h<<16>>16==b<<16>>16){b=a+616+(g<<2)|0;k[b>>2]=(k[b>>2]|0)+c;b=a+712+(g<<2)|0;k[b>>2]=(k[b>>2]|0)+d;d=ha(e,c)|0;a=a+808+(g<<2)|0;k[a>>2]=(k[a>>2]|0)+d;break}if(m<<16>>16!=-1){if(i<<16>>16!=-1)if(h<<16>>16==-1)f=g;else{f=(k[a+616+(f<<2)>>2]|0)<(k[a+616+(l<<2)>>2]|0)?f:l;f=(k[a+616+(g<<2)>>2]|0)<(k[a+616+(f<<2)>>2]|0)?g:f}}else f=l;j[a+568+(f<<1)>>1]=b;k[a+616+(f<<2)>>2]=c;k[a+712+(f<<2)>>2]=d;d=ha(e,c)|0;k[a+808+(f<<2)>>2]=d}while(0);return}function rd(a,b){a=a|0;b=b|0;var c=0,d=0;a:do if(!(k[a+4>>2]|0)){d=b&65535;c=d&15;if((j[a+568+(c<<1)>>1]|0)!=b<<16>>16){c=c^8;if((j[a+568+(c<<1)>>1]|0)!=b<<16>>16){c=d&7|16;c=(j[a+568+(c<<1)>>1]|0)==b<<16>>16?c:-1}}}else{c=0;while(1){if((j[a+568+(c<<1)>>1]|0)==b<<16>>16)break a;c=c+1|0;if((c|0)>=24){c=-1;break}}}while(0);return c|0}function sd(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0,l=0;l=0;while(1){g=a+568+(l<<1)|0;if((j[g>>1]|0)==-1)k[a+616+(l<<2)>>2]=-1;b=l;l=l+1|0;if((l|0)>=24)continue;h=a+616+(b<<2)|0;i=a+712+(b<<2)|0;e=a+808+(b<<2)|0;f=l;do{b=a+568+(f<<1)|0;c=a+616+(f<<2)|0;if((j[b>>1]|0)==-1){k[c>>2]=-1;d=-1}else d=k[c>>2]|0;if((k[h>>2]|0)<(d|0)){d=j[g>>1]|0;j[g>>1]=j[b>>1]|0;j[b>>1]=d;d=k[h>>2]|0;k[h>>2]=k[c>>2];k[c>>2]=d;d=k[i>>2]|0;c=a+712+(f<<2)|0;k[i>>2]=k[c>>2];k[c>>2]=d;c=k[e>>2]|0;d=a+808+(f<<2)|0;k[e>>2]=k[d>>2];k[d>>2]=c}f=f+1|0}while((f|0)!=24);if((l|0)==3)break}k[a+4>>2]=1;return}function td(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0;f=r;r=r+32|0;e=f+8|0;d=f;se(1017581,14,1,941016);c=0;do{b=j[a+568+(c<<1)>>1]|0;if(b<<16>>16!=-1){i=Ec(b&65535)|0;h=k[a+616+(c<<2)>>2]|0;g=k[a+712+(c<<2)>>2]|0;b=k[a+808+(c<<2)>>2]|0;k[e>>2]=c;k[e+4>>2]=i;k[e+8>>2]=h;k[e+12>>2]=g;k[e+16>>2]=b;pe(941016,1017620,e)}c=c+1|0}while((c|0)!=24);k[d>>2]=k[a>>2];pe(941016,1017596,d);r=f;return}function ud(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0;e=k[c>>2]|0;do if((e|0)>=1){f=k[b>>2]|0;g=(k[a+32>>2]|0)+(k[a>>2]|0)|0;d=k[a+16>>2]|0;h=i[f>>0]|0;a=h&255;if(h<<24>>24>-1){a=i[g+a>>0]|0;k[b>>2]=f+1;k[c>>2]=e+-1;break}if((e|0)>1&(a&224|0)==192){a=i[g+(l[g+a>>0]<>0]|0)>>0]|0;k[b>>2]=f+2;k[c>>2]=e+-2;break}if((e|0)>2&(a&240|0)==224){a=g+(l[g+a>>0]<>0]|0)>>0]<>0]|0)>>0]|0;k[b>>2]=f+3;k[c>>2]=e+-3;break}if((a&248|0)==240&(e|0)>3){a=g+(l[g+(l[g+a>>0]<>0]|0)>>0]<>0]|0)>>0]<>0]|0)>>0]|0;k[b>>2]=f+4;k[c>>2]=e+-4;break}else{k[b>>2]=f+1;k[c>>2]=e+-1;a=0;break}}else a=0;while(0);return a|0}function vd(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=k[b>>2]|0;do if((c|0)>=1){d=k[a>>2]|0;f=i[d>>0]|0;e=f&255;if(f<<24>>24>-1){f=j[942368+(e<<1)>>1]|0;k[a>>2]=d+1;k[b>>2]=c+-1;c=f&255;break}if((c|0)>1&(e&224|0)==192){f=j[942368+((m[942368+(e<<1)>>1]|0)<<6<<1)+((l[d+1>>0]|0)<<1)>>1]|0;k[a>>2]=d+2;k[b>>2]=c+-2;c=f&255;break}if((c|0)>2&(e&240|0)==224){f=j[942368+((m[942368+((m[942368+(e<<1)>>1]|0)<<6<<1)+((l[d+1>>0]|0)<<1)>>1]|0)<<6<<1)+((l[d+2>>0]|0)<<1)>>1]|0;k[a>>2]=d+3;k[b>>2]=c+-3;c=f&255;break}if((e&248|0)==240&(c|0)>3){f=j[942368+((m[942368+((m[942368+((m[942368+(e<<1)>>1]|0)<<6<<1)+((l[d+1>>0]|0)<<1)>>1]|0)<<6<<1)+((l[d+2>>0]|0)<<1)>>1]|0)<<6<<1)+((l[d+3>>0]|0)<<1)>>1]|0;k[a>>2]=d+4;k[b>>2]=c+-4;c=f&255;break}else{k[a>>2]=d+1;k[b>>2]=c+-1;c=0;break}}else c=0;while(0);return c|0}function wd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,m=0;h=a+b|0;j=h+-7|0;k[c>>2]=0;if(b|0){b=a;a:do{b:do if(b>>>0>>0){g=b;while(1){d=k[g>>2]|0;b=g+4|0;e=k[b>>2]|0;f=g+8|0;if((d+-656877351|d+1145324612|e+-656877351|e+1145324612)&-2139062144|0){if((i[1008008+(l[g+1>>0]|0)>>0]|i[1008008+(d&255)>>0]|i[1008008+(l[g+2>>0]|0)>>0]|i[1008008+(l[g+3>>0]|0)>>0])<<24>>24){b=g;break b}if((i[1008008+(l[g+5>>0]|0)>>0]|i[1008008+(e&255)>>0]|i[1008008+(l[g+6>>0]|0)>>0]|i[1008008+(l[g+7>>0]|0)>>0])<<24>>24)break b}if(f>>>0>>0)g=f;else{b=f;break}}}while(0);if(b>>>0>>0)d=993864;else{d=993864;m=13;break}while(1){f=i[d+(l[b>>0]|0)>>0]|0;e=b+1|0;if((f&255)>239)break;b=993864+((f&255)<<6)|0;if(e>>>0>>0){d=b;b=e}else{d=b;b=e;m=13;break a}}c:do if((d-993864|0)>>>0>=64)do{b=b+-1|0;if(b>>>0<=a>>>0)break c}while((i[b>>0]&-64)<<24>>24==-128);while(0)}while(f<<24>>24==-3);d:do if((m|0)==13)if((d-993864|0)>>>0>=64)do{b=b+-1|0;if(b>>>0<=a>>>0)break d}while((i[b>>0]&-64)<<24>>24==-128);while(0);k[c>>2]=b-a}return}function xd(a,b,c,d,e,f,g,h,j){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;H=(j|0)==0;I=(j|0)!=0;E=0;F=0;G=0;while(1){C=a;x=a+b|0;D=c;y=c+d|0;z=x;if((d|0)<(b|0))if(H){r=239;q=0;o=0;n=0}else{Tc(j,0);r=239;q=0;o=0;n=0}else{A=1009832;u=0;B=a;p=D;r=0;o=C;n=0;a:while(1){s=o;if(s>>>0>>0){q=i[s>>0]|0;w=i[A+(q&255)>>0]|0;r=w&255;i[p>>0]=q;o=s+1|0;p=p+1|0;if((w&255)>239)w=q;else{w=B;A=1009832+(r<<6)|0;u=q;B=w;continue}}else w=u;if((r|0)<=239){J=43;break}b:do switch(r|0){case 247:{if(H)q=B;else{Tc(j,-2-B+o|0);Vc(j,2);q=o}i[p+-3>>0]=i[A+((w&255)+64)>>0]|0;A=1009832;u=0;B=q;p=p+-2|0;r=0;n=n+1|0;continue a}case 248:{if(H)q=B;else{Tc(j,o+~B|0);Vc(j,1);q=o}u=w&255;i[p+-3>>0]=i[A+(u+128)>>0]|0;i[p+-2>>0]=i[A+(u+64)>>0]|0;A=1009832;u=0;B=q;p=p+-1|0;r=0;n=n+1|0;continue a}case 246:{if(H)q=B;else{Tc(j,o+~B|0);Vc(j,1);q=o}i[p+-2>>0]=i[A+((w&255)+64)>>0]|0;A=1009832;u=0;B=q;p=p+-1|0;r=0;n=n+1|0;continue a}case 245:{q=w&255;r=p;i[r+-3>>0]=i[A+(q+192)>>0]|0;J=23;break}case 244:{q=w&255;r=p;J=23;break}case 243:{q=w&255;r=p;J=24;break}case 251:{i[p+-1>>0]=i[A+(w&255|256)>>0]|0;w=B;A=1009832;u=0;r=0;n=n+1|0;B=w;continue a}case 250:{q=A;r=w&255;if((q-1009832|0)>>>0<320){r=l[A+(r|512)>>0]<<8;break b}else{r=l[A+(r+128)>>0]<<8;J=29;break b}}case 249:case 252:{r=0;J=29;break}default:{J=10;break a}}while(0);if((J|0)==23){i[r+-2>>0]=i[A+(q+128)>>0]|0;J=24}else if((J|0)==29){J=0;q=A}if((J|0)==24){J=0;i[r+-1>>0]=i[A+(q+64)>>0]|0;w=B;A=1009832;u=0;r=0;n=n+1|0;B=w;continue}s=w&255;r=l[A+((q-1009832|0)>>>0<320?s|256:s+64|0)>>0]|r;s=974880+(r<<2)|0;v=l[s>>0]&127;q=l[974880+(r<<2)+1>>0]|0;if(!((q&128|0)==0|e)){s=r+1|0;q=l[974880+(s<<2)+1>>0]|0;s=974880+(s<<2)|0}u=q&127;r=m[s+2>>1]|0;q=p+(0-v)|0;t=q+u|0;if((y-t|0)<(z-o|0)){r=239;J=39;break}tf(q|0,1016936+r|0,u|0)|0;n=n+1|0;do if(!H){if(u>>>0>v>>>0){Tc(j,o-B|0);Uc(j,u-v|0);p=o;break}if(u>>>0>>0){Tc(j,o-B-v+u|0);Vc(j,v-u|0);p=o}else p=B}else p=B;while(0);if((i[s>>0]|0)>=0){A=1009832;u=0;B=p;p=t;r=0;continue}r=l[1016936+(r+u)>>0]|0;A=1009832+(r<<6)|0;u=w;B=p;p=t}c:do if((J|0)==10)J=39;else if((J|0)==43){J=0;if((A-1009832|0)>>>0<320)r=241;else while(1){q=o+-1|0;o=q;p=p+-1|0;if(q>>>0<=a>>>0){r=240;break c}if((i[q>>0]&-64)<<24>>24!=-128){r=240;break}}}while(0);d:do if((J|0)==39){J=0;o=o+-1|0;p=p+-1|0;if((A-1009832|0)>>>0>=320)do{q=o+-1|0;o=q;p=p+-1|0;if(q>>>0<=a>>>0)break d}while((i[q>>0]&-64)<<24>>24==-128)}while(0);if(I&o>>>0>B>>>0)Tc(j,o-B|0);q=o-C|0;o=p-D|0}F=q+F|0;G=o+G|0;E=n+E|0;if((r|0)!=253)break;else{a=a+q|0;b=b-q|0;c=c+o|0;d=d-o|0}}k[f>>2]=F;k[g>>2]=G;k[h>>2]=E;return}function yd(a){a=a|0;if(a|0)Qe(a);return}function zd(a){a=a|0;return Ec(k[a>>2]|0)|0}function Ad(a){a=a|0;return i[a+4>>0]|0}function Bd(a){a=a|0;if(a|0){Cd(a);Qe(a)}return}function Cd(a){a=a|0;var b=0;b=k[a+4>>2]|0;if(b|0)Qe(b);b=k[a+8>>2]|0;if(b|0)Qe(b);b=k[a+12>>2]|0;if(b|0)Qe(b);return}function Dd(a,b,c){a=a|0;b=b|0;c=c|0;return Ed(b,c)|0}function Ed(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=r;r=r+32|0;e=c+16|0;d=c+4|0;f=c+28|0;k[e>>2]=0;k[e+4>>2]=0;k[e+8>>2]=0;k[d>>2]=0;k[d+4>>2]=0;k[d+8>>2]=0;i[f>>0]=0;a=wb(a,Vd(a)|0,b,e,d,c,f)|0;b=gf(20)|0;Fd(b,(i[f>>0]|0)!=0,a,e,d);r=c;return b|0}function Fd(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;k[a>>2]=c;i[a+16>>0]=b&1;b=gf(8)|0;c=k[e>>2]&255;k[b>>2]=k[d>>2];i[b+4>>0]=c;k[a+4>>2]=b;b=gf(8)|0;c=k[e+4>>2]&255;k[b>>2]=k[d+4>>2];i[b+4>>0]=c;k[a+8>>2]=b;b=gf(8)|0;e=k[e+8>>2]&255;k[b>>2]=k[d+8>>2];i[b+4>>0]=e;k[a+12>>2]=b;return}function Gd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Hd(b,c,d,e,f)|0}function Hd(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,l=0;f=r;r=r+80|0;l=f+56|0;h=f+40|0;g=f+28|0;j=f+72|0;k[l>>2]=e;k[l+4>>2]=c;k[l+8>>2]=d;k[l+12>>2]=26;k[h>>2]=0;k[h+4>>2]=0;k[h+8>>2]=0;k[g>>2]=0;k[g+4>>2]=0;k[g+8>>2]=0;i[j>>0]=0;e=xb(a,Vd(a)|0,b,l,h,g,f,f+24|0,j)|0;c=gf(20)|0;Fd(c,(i[j>>0]|0)!=0,e,h,g);r=f;return c|0}function Id(a){a=a|0;return (i[a+16>>0]|0)!=0|0}function Jd(a){a=a|0;return Ec(k[a>>2]|0)|0}function Kd(a,b){a=a|0;b=b|0;if(b>>>0>=3)Ka(0,b|0,3)|0;return k[a+4+(b<<2)>>2]|0}function Ld(a){a=a|0;if(a|0)Qe(a);return}function Md(a){a=a|0;return Ec(k[a>>2]|0)|0}function Nd(a){a=a|0;if(a|0)Qe(a);return}function Od(a){a=a|0;var b=0,c=0;b=r;r=r+16|0;c=b;k[c>>2]=k[a+60>>2];a=Pd(ua(6,c|0)|0)|0;r=b;return a|0}function Pd(a){a=a|0;var b=0;if(a>>>0>4294963200){b=Qd()|0;k[b>>2]=0-a;a=-1}return a|0}function Qd(){var a=0;if(!0)a=1097308;else{a=(Ha()|0)+64|0;a=k[a>>2]|0}return a|0}function Rd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,m=0,n=0,o=0,p=0;p=r;r=r+48|0;m=p+16|0;l=p;i=p+32|0;n=a+28|0;g=k[n>>2]|0;k[i>>2]=g;o=a+20|0;g=(k[o>>2]|0)-g|0;k[i+4>>2]=g;k[i+8>>2]=b;k[i+12>>2]=c;h=a+60|0;j=a+44|0;e=2;b=g+c|0;while(1){if(!0){k[m>>2]=k[h>>2];k[m+4>>2]=i;k[m+8>>2]=e;f=Pd(Ra(146,m|0)|0)|0}else{Oa(8,a|0);k[l>>2]=k[h>>2];k[l+4>>2]=i;k[l+8>>2]=e;f=Pd(Ra(146,l|0)|0)|0;ta(0)}if((b|0)==(f|0)){b=6;break}if((f|0)<0){b=8;break}b=b-f|0;d=k[i+4>>2]|0;if(f>>>0<=d>>>0)if((e|0)==2){k[n>>2]=(k[n>>2]|0)+f;g=d;d=i;e=2}else{g=d;d=i}else{g=k[j>>2]|0;k[n>>2]=g;k[o>>2]=g;g=k[i+12>>2]|0;f=f-d|0;d=i+8|0;e=e+-1|0}k[d>>2]=(k[d>>2]|0)+f;k[d+4>>2]=g-f;i=d}if((b|0)==6){m=k[j>>2]|0;k[a+16>>2]=m+(k[a+48>>2]|0);a=m;k[n>>2]=a;k[o>>2]=a}else if((b|0)==8){k[a+16>>2]=0;k[n>>2]=0;k[o>>2]=0;k[a>>2]=k[a>>2]|32;if((e|0)==2)c=0;else c=c-(k[i+4>>2]|0)|0}r=p;return c|0}function Sd(a){a=a|0;return}function Td(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;e=r;r=r+32|0;f=e;d=e+20|0;k[f>>2]=k[a+60>>2];k[f+4>>2]=0;k[f+8>>2]=b;k[f+12>>2]=d;k[f+16>>2]=c;if((Pd(Qa(140,f|0)|0)|0)<0){k[d>>2]=-1;a=-1}else a=k[d>>2]|0;r=e;return a|0}function Ud(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;d=b&255;a:do if(!d)a=a+(Vd(a)|0)|0;else{if(a&3){c=b&255;do{e=i[a>>0]|0;if(e<<24>>24==0?1:e<<24>>24==c<<24>>24)break a;a=a+1|0}while((a&3|0)!=0)}d=ha(d,16843009)|0;c=k[a>>2]|0;b:do if(!((c&-2139062144^-2139062144)&c+-16843009))do{e=c^d;if((e&-2139062144^-2139062144)&e+-16843009|0)break b;a=a+4|0;c=k[a>>2]|0}while(!((c&-2139062144^-2139062144)&c+-16843009|0));while(0);c=b&255;while(1){e=i[a>>0]|0;if(e<<24>>24==0?1:e<<24>>24==c<<24>>24)break;else a=a+1|0}}while(0);return a|0}function Vd(a){a=a|0;var b=0,c=0,d=0;d=a;a:do if(!(d&3))c=4;else{b=a;a=d;while(1){if(!(i[b>>0]|0))break a;b=b+1|0;a=b;if(!(a&3)){a=b;c=4;break}}}while(0);if((c|0)==4){while(1){b=k[a>>2]|0;if(!((b&-2139062144^-2139062144)&b+-16843009))a=a+4|0;else break}if((b&255)<<24>>24)do a=a+1|0;while((i[a>>0]|0)!=0)}return a-d|0}function Wd(a,b){a=+a;b=b|0;var c=0,d=0,e=0;p[t>>3]=a;c=k[t>>2]|0;d=k[t+4>>2]|0;e=rf(c|0,d|0,52)|0;e=e&2047;switch(e|0){case 0:{if(a!=0.0){a=+Wd(a*18446744073709551616.0,b);c=(k[b>>2]|0)+-64|0}else c=0;k[b>>2]=c;break}case 2047:break;default:{k[b>>2]=e+-1022;k[t>>2]=c;k[t+4>>2]=d&-2146435073|1071644672;a=+p[t>>3]}}return +a}function Xd(a,b){a=+a;b=b|0;return +(+Wd(a,b))}function Yd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;a:do if(!c)c=0;else{while(1){d=i[a>>0]|0;e=i[b>>0]|0;if(d<<24>>24!=e<<24>>24)break;c=c+-1|0;if(!c){c=0;break a}else{a=a+1|0;b=b+1|0}}c=(d&255)-(e&255)|0}while(0);return c|0}function Zd(a){a=a|0;var b=0,c=0;b=0;while(1){if((l[1094098+b>>0]|0)==(a|0)){c=2;break}b=b+1|0;if((b|0)==87){b=87;a=1094186;c=5;break}}if((c|0)==2)if(!b)b=1094186;else{a=1094186;c=5}if((c|0)==5)while(1){do{c=a;a=a+1|0}while((i[c>>0]|0)!=0);b=b+-1|0;if(!b){b=a;break}else c=5}return b|0}function _d(a,b){a=a|0;b=b|0;var c=0,d=0;d=i[a>>0]|0;c=i[b>>0]|0;if(d<<24>>24==0?1:d<<24>>24!=c<<24>>24)b=d;else{do{a=a+1|0;b=b+1|0;d=i[a>>0]|0;c=i[b>>0]|0}while(!(d<<24>>24==0?1:d<<24>>24!=c<<24>>24));b=d}return (b&255)-(c&255)|0}function $d(a,b){a=a|0;b=b|0;if(!a)a=0;else a=ae(a,b)|0;return a|0}function ae(a,b){a=a|0;b=b|0;do if(a){if(b>>>0<128){i[a>>0]=b;a=1;break}if(b>>>0<2048){i[a>>0]=b>>>6|192;i[a+1>>0]=b&63|128;a=2;break}if(b>>>0<55296|(b&-8192|0)==57344){i[a>>0]=b>>>12|224;i[a+1>>0]=b>>>6&63|128;i[a+2>>0]=b&63|128;a=3;break}if((b+-65536|0)>>>0<1048576){i[a>>0]=b>>>18|240;i[a+1>>0]=b>>>12&63|128;i[a+2>>0]=b>>>6&63|128;i[a+3>>0]=b&63|128;a=4;break}else{a=Qd()|0;k[a>>2]=84;a=-1;break}}else a=1;while(0);return a|0}function be(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0;o=r;r=r+128|0;j=o+112|0;l=o;m=l;p=941128;q=m+112|0;do{k[m>>2]=k[p>>2];m=m+4|0;p=p+4|0}while((m|0)<(q|0));if((b+-1|0)>>>0>2147483646)if(!b){e=j;f=1;n=4}else{q=Qd()|0;k[q>>2]=75}else{e=a;f=b;n=4}if((n|0)==4?(q=-2-e|0,q=f>>>0>q>>>0?q:f,k[l+48>>2]=q,h=l+20|0,k[h>>2]=e,k[l+44>>2]=e,p=e+q|0,g=l+16|0,k[g>>2]=p,k[l+28>>2]=p,de(l,c,d)|0,q|0):0){q=k[h>>2]|0;i[q+(((q|0)==(k[g>>2]|0))<<31>>31)>>0]=0}r=o;return}function ce(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=a+20|0;e=k[d>>2]|0;a=(k[a+16>>2]|0)-e|0;a=a>>>0>c>>>0?c:a;tf(e|0,b|0,a|0)|0;k[d>>2]=(k[d>>2]|0)+a;return c|0}function de(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0;q=r;r=r+224|0;m=q+120|0;p=q+80|0;o=q;n=q+136|0;d=p;e=d+40|0;do{k[d>>2]=0;d=d+4|0}while((d|0)<(e|0));k[m>>2]=k[c>>2];if((ee(0,b,m,o,p)|0)<0)c=-1;else{c=k[a>>2]|0;l=c&32;if((i[a+74>>0]|0)<1)k[a>>2]=c&-33;j=a+48|0;if(!(k[j>>2]|0)){d=a+44|0;e=k[d>>2]|0;k[d>>2]=n;f=a+28|0;k[f>>2]=n;g=a+20|0;k[g>>2]=n;k[j>>2]=80;h=a+16|0;k[h>>2]=n+80;c=ee(a,b,m,o,p)|0;if(e){Ua[k[a+36>>2]&7](a,0,0)|0;c=(k[g>>2]|0)==0?-1:c;k[d>>2]=e;k[j>>2]=0;k[h>>2]=0;k[f>>2]=0;k[g>>2]=0}}else c=ee(a,b,m,o,p)|0;p=k[a>>2]|0;k[a>>2]=p|l;c=(p&32|0)==0?c:-1}r=q;return c|0}function ee(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,m=0.0,n=0,o=0,q=0,s=0,u=0,v=0,w=0.0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ia=0;ia=r;r=r+624|0;ca=ia+24|0;ea=ia+16|0;da=ia+588|0;$=ia+576|0;ba=ia;W=ia+536|0;ga=ia+8|0;fa=ia+528|0;M=(a|0)!=0;N=W+40|0;V=N;W=W+39|0;X=ga+4|0;Y=da;Z=0-Y|0;_=$+12|0;$=$+11|0;aa=_;O=aa-Y|0;P=-2-Y|0;Q=aa+2|0;R=ca+288|0;S=da+9|0;T=S;U=da+8|0;f=0;g=0;o=0;x=b;a:while(1){do if((f|0)>-1)if((g|0)>(2147483647-f|0)){f=Qd()|0;k[f>>2]=75;f=-1;break}else{f=g+f|0;break}while(0);b=i[x>>0]|0;if(!(b<<24>>24)){K=244;break}else g=x;b:while(1){switch(b<<24>>24){case 37:{b=g;K=9;break b}case 0:{b=g;break b}default:{}}J=g+1|0;b=i[J>>0]|0;g=J}c:do if((K|0)==9)while(1){K=0;if((i[b+1>>0]|0)!=37)break c;g=g+1|0;b=b+2|0;if((i[b>>0]|0)==37)K=9;else break}while(0);v=g-x|0;if(M?(k[a>>2]&32|0)==0:0)fe(x,v,a)|0;if((g|0)!=(x|0)){g=v;x=b;continue}n=b+1|0;g=i[n>>0]|0;h=(g<<24>>24)+-48|0;if(h>>>0<10){J=(i[b+2>>0]|0)==36;n=J?b+3|0:n;g=i[n>>0]|0;s=J?h:-1;o=J?1:o}else s=-1;b=g<<24>>24;d:do if((b&-32|0)==32){h=0;do{if(!(1<>24)+-32|h;n=n+1|0;g=i[n>>0]|0;b=g<<24>>24}while((b&-32|0)==32)}else h=0;while(0);do if(g<<24>>24==42){g=n+1|0;b=(i[g>>0]|0)+-48|0;if(b>>>0<10?(i[n+2>>0]|0)==36:0){k[e+(b<<2)>>2]=10;b=1;n=n+3|0;g=k[d+((i[g>>0]|0)+-48<<3)>>2]|0}else{if(o|0){f=-1;break a}if(!M){u=h;J=0;n=g;I=0;break}b=(k[c>>2]|0)+(4-1)&~(4-1);J=k[b>>2]|0;k[c>>2]=b+4;b=0;n=g;g=J}if((g|0)<0){u=h|8192;J=b;I=0-g|0}else{u=h;J=b;I=g}}else{b=(g<<24>>24)+-48|0;if(b>>>0<10){g=0;do{g=(g*10|0)+b|0;n=n+1|0;b=(i[n>>0]|0)+-48|0}while(b>>>0<10);if((g|0)<0){f=-1;break a}else{u=h;J=o;I=g}}else{u=h;J=o;I=0}}while(0);e:do if((i[n>>0]|0)==46){b=n+1|0;g=i[b>>0]|0;if(g<<24>>24!=42){h=(g<<24>>24)+-48|0;if(h>>>0<10)g=0;else{o=0;break}while(1){g=(g*10|0)+h|0;b=b+1|0;h=(i[b>>0]|0)+-48|0;if(h>>>0>=10){o=g;break e}}}b=n+2|0;g=(i[b>>0]|0)+-48|0;if(g>>>0<10?(i[n+3>>0]|0)==36:0){k[e+(g<<2)>>2]=10;o=k[d+((i[b>>0]|0)+-48<<3)>>2]|0;b=n+4|0;break}if(J|0){f=-1;break a}if(M){H=(k[c>>2]|0)+(4-1)&~(4-1);o=k[H>>2]|0;k[c>>2]=H+4}else o=0}else{o=-1;b=n}while(0);q=0;while(1){g=(i[b>>0]|0)+-65|0;if(g>>>0>57){f=-1;break a}H=b+1|0;g=i[1095990+(q*58|0)+g>>0]|0;h=g&255;if((h+-1|0)>>>0<8){b=H;q=h}else break}if(!(g<<24>>24)){f=-1;break}n=(s|0)>-1;do if(g<<24>>24==19)if(n){f=-1;break a}else K=52;else{if(n){k[e+(s<<2)>>2]=h;F=d+(s<<3)|0;G=k[F+4>>2]|0;K=ba;k[K>>2]=k[F>>2];k[K+4>>2]=G;K=52;break}if(!M){f=0;break a}he(ba,h,c)}while(0);if((K|0)==52?(K=0,!M):0){g=v;o=J;x=H;continue}s=i[b>>0]|0;s=(q|0)!=0&(s&15|0)==3?s&-33:s;h=u&-65537;G=(u&8192|0)==0?u:h;f:do switch(s|0){case 110:switch(q|0){case 0:{k[k[ba>>2]>>2]=f;g=v;o=J;x=H;continue a}case 1:{k[k[ba>>2]>>2]=f;g=v;o=J;x=H;continue a}case 2:{g=k[ba>>2]|0;k[g>>2]=f;k[g+4>>2]=((f|0)<0)<<31>>31;g=v;o=J;x=H;continue a}case 3:{j[k[ba>>2]>>1]=f;g=v;o=J;x=H;continue a}case 4:{i[k[ba>>2]>>0]=f;g=v;o=J;x=H;continue a}case 6:{k[k[ba>>2]>>2]=f;g=v;o=J;x=H;continue a}case 7:{g=k[ba>>2]|0;k[g>>2]=f;k[g+4>>2]=((f|0)<0)<<31>>31;g=v;o=J;x=H;continue a}default:{g=v;o=J;x=H;continue a}}case 112:{q=G|8;o=o>>>0>8?o:8;s=120;K=64;break}case 88:case 120:{q=G;K=64;break}case 111:{h=ba;g=k[h>>2]|0;h=k[h+4>>2]|0;if((g|0)==0&(h|0)==0)b=N;else{b=N;do{b=b+-1|0;i[b>>0]=g&7|48;g=rf(g|0,h|0,3)|0;h=L}while(!((g|0)==0&(h|0)==0))}if(!(G&8)){g=G;q=0;n=1096470;K=77}else{q=V-b|0;g=G;o=(o|0)>(q|0)?o:q+1|0;q=0;n=1096470;K=77}break}case 105:case 100:{g=ba;b=k[g>>2]|0;g=k[g+4>>2]|0;if((g|0)<0){b=pf(0,0,b|0,g|0)|0;g=L;h=ba;k[h>>2]=b;k[h+4>>2]=g;h=1;n=1096470;K=76;break f}if(!(G&2048)){n=G&1;h=n;n=(n|0)==0?1096470:1096472;K=76}else{h=1;n=1096471;K=76}break}case 117:{g=ba;b=k[g>>2]|0;g=k[g+4>>2]|0;h=0;n=1096470;K=76;break}case 99:{i[W>>0]=k[ba>>2];b=W;s=1;v=0;u=1096470;g=N;break}case 109:{g=Qd()|0;g=Zd(k[g>>2]|0)|0;K=82;break}case 115:{g=k[ba>>2]|0;g=g|0?g:1096480;K=82;break}case 67:{k[ga>>2]=k[ba>>2];k[X>>2]=0;k[ba>>2]=ga;b=ga;o=-1;K=86;break}case 83:{b=k[ba>>2]|0;if(!o){ke(a,32,I,0,G);b=0;K=97}else K=86;break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{m=+p[ba>>3];k[ea>>2]=0;p[t>>3]=m;if((k[t+4>>2]|0)>=0)if(!(G&2048)){F=G&1;E=F;F=(F|0)==0?1096488:1096493}else{E=1;F=1096490}else{m=-m;E=1;F=1096487}p[t>>3]=m;D=k[t+4>>2]&2146435072;do if(D>>>0<2146435072|(D|0)==2146435072&0<0){w=+Xd(m,ea)*2.0;g=w!=0.0;if(g)k[ea>>2]=(k[ea>>2]|0)+-1;B=s|32;if((B|0)==97){u=s&32;x=(u|0)==0?F:F+9|0;v=E|2;b=12-o|0;do if(!(o>>>0>11|(b|0)==0)){m=8.0;do{b=b+-1|0;m=m*16.0}while((b|0)!=0);if((i[x>>0]|0)==45){m=-(m+(-w-m));break}else{m=w+m-m;break}}else m=w;while(0);g=k[ea>>2]|0;b=(g|0)<0?0-g|0:g;b=ie(b,((b|0)<0)<<31>>31,_)|0;if((b|0)==(_|0)){i[$>>0]=48;b=$}i[b+-1>>0]=(g>>31&2)+43;q=b+-2|0;i[q>>0]=s+15;n=(o|0)<1;h=(G&8|0)==0;g=da;while(1){F=~~m;b=g+1|0;i[g>>0]=l[1096454+F>>0]|u;m=(m-+(F|0))*16.0;do if((b-Y|0)==1){if(h&(n&m==0.0))break;i[b>>0]=46;b=g+2|0}while(0);if(!(m!=0.0))break;else g=b}h=q;o=(o|0)!=0&(P+b|0)<(o|0)?Q+o-h|0:O-h+b|0;n=o+v|0;ke(a,32,I,n,G);if(!(k[a>>2]&32))fe(x,v,a)|0;ke(a,48,I,n,G^65536);g=b-Y|0;if(!(k[a>>2]&32))fe(da,g,a)|0;b=aa-h|0;ke(a,48,o-(g+b)|0,0,0);if(!(k[a>>2]&32))fe(q,b,a)|0;ke(a,32,I,n,G^8192);b=(n|0)<(I|0)?I:n;break}b=(o|0)<0?6:o;if(g){g=(k[ea>>2]|0)+-28|0;k[ea>>2]=g;m=w*268435456.0}else{m=w;g=k[ea>>2]|0}D=(g|0)<0?ca:R;C=D;h=D;do{A=~~m>>>0;k[h>>2]=A;h=h+4|0;m=(m-+(A>>>0))*1.0e9}while(m!=0.0);g=k[ea>>2]|0;if((g|0)>0){n=D;o=h;while(1){q=(g|0)>29?29:g;g=o+-4|0;do if(g>>>0>=n>>>0){h=0;do{z=sf(k[g>>2]|0,0,q|0)|0;z=of(z|0,L|0,h|0,0)|0;A=L;y=Cf(z|0,A|0,1e9,0)|0;k[g>>2]=y;h=Bf(z|0,A|0,1e9,0)|0;g=g+-4|0}while(g>>>0>=n>>>0);if(!h)break;n=n+-4|0;k[n>>2]=h}while(0);h=o;while(1){if(h>>>0<=n>>>0)break;g=h+-4|0;if(!(k[g>>2]|0))h=g;else break}g=(k[ea>>2]|0)-q|0;k[ea>>2]=g;if((g|0)>0)o=h;else break}}else n=D;if((g|0)<0){x=((b+25|0)/9|0)+1|0;y=(B|0)==102;do{v=0-g|0;v=(v|0)>9?9:v;do if(n>>>0>>0){g=(1<>>v;u=0;q=n;do{A=k[q>>2]|0;k[q>>2]=(A>>>v)+u;u=ha(A&g,o)|0;q=q+4|0}while(q>>>0>>0);g=(k[n>>2]|0)==0?n+4|0:n;if(!u){n=g;g=h;break}k[h>>2]=u;n=g;g=h+4|0}else{n=(k[n>>2]|0)==0?n+4|0:n;g=h}while(0);h=y?D:n;h=(g-h>>2|0)>(x|0)?h+(x<<2)|0:g;g=(k[ea>>2]|0)+v|0;k[ea>>2]=g}while((g|0)<0);x=n;y=h}else{x=n;y=h}do if(x>>>0>>0){g=(C-x>>2)*9|0;n=k[x>>2]|0;if(n>>>0<10)break;else h=10;do{h=h*10|0;g=g+1|0}while(n>>>0>=h>>>0)}else g=0;while(0);z=(B|0)==103;A=(b|0)!=0;h=b-((B|0)!=102?g:0)+((A&z)<<31>>31)|0;if((h|0)<(((y-C>>2)*9|0)+-9|0)){o=h+9216|0;h=D+4+(((o|0)/9|0)+-1024<<2)|0;o=((o|0)%9|0)+1|0;if((o|0)<9){n=10;do{n=n*10|0;o=o+1|0}while((o|0)!=9)}else n=10;u=k[h>>2]|0;v=(u>>>0)%(n>>>0)|0;o=(h+4|0)==(y|0);do if(o&(v|0)==0)n=x;else{w=(((u>>>0)/(n>>>0)|0)&1|0)==0?9007199254740992.0:9007199254740994.0;q=(n|0)/2|0;if(v>>>0>>0)m=.5;else m=o&(v|0)==(q|0)?1.0:1.5;do if(E){if((i[F>>0]|0)!=45)break;w=-w;m=-m}while(0);o=u-v|0;k[h>>2]=o;if(!(w+m!=w)){n=x;break}B=o+n|0;k[h>>2]=B;if(B>>>0>999999999){g=x;while(1){n=h+-4|0;k[h>>2]=0;if(n>>>0>>0){g=g+-4|0;k[g>>2]=0}B=(k[n>>2]|0)+1|0;k[n>>2]=B;if(B>>>0>999999999)h=n;else{q=g;h=n;break}}}else q=x;g=(C-q>>2)*9|0;o=k[q>>2]|0;if(o>>>0<10){n=q;break}else n=10;do{n=n*10|0;g=g+1|0}while(o>>>0>=n>>>0);n=q}while(0);h=h+4|0;x=n;h=y>>>0>h>>>0?h:y}else h=y;v=0-g|0;B=h;while(1){if(B>>>0<=x>>>0){y=0;break}h=B+-4|0;if(!(k[h>>2]|0))B=h;else{y=1;break}}do if(z){b=(A&1^1)+b|0;if((b|0)>(g|0)&(g|0)>-5){s=s+-1|0;b=b+-1-g|0}else{s=s+-2|0;b=b+-1|0}h=G&8;if(h|0)break;do if(y){h=k[B+-4>>2]|0;if(!h){n=9;break}if(!((h>>>0)%10|0)){o=10;n=0}else{n=0;break}do{o=o*10|0;n=n+1|0}while(!((h>>>0)%(o>>>0)|0|0))}else n=9;while(0);h=((B-C>>2)*9|0)+-9|0;if((s|32|0)==102){h=h-n|0;h=(h|0)<0?0:h;b=(b|0)<(h|0)?b:h;h=0;break}else{h=h+g-n|0;h=(h|0)<0?0:h;b=(b|0)<(h|0)?b:h;h=0;break}}else h=G&8;while(0);u=b|h;o=(u|0)!=0&1;q=(s|32|0)==102;if(q){g=(g|0)>0?g:0;s=0}else{n=(g|0)<0?v:g;n=ie(n,((n|0)<0)<<31>>31,_)|0;if((aa-n|0)<2)do{n=n+-1|0;i[n>>0]=48}while((aa-n|0)<2);i[n+-1>>0]=(g>>31&2)+43;C=n+-2|0;i[C>>0]=s;g=aa-C|0;s=C}v=E+1+b+o+g|0;ke(a,32,I,v,G);if(!(k[a>>2]&32))fe(F,E,a)|0;ke(a,48,I,v,G^65536);do if(q){n=x>>>0>D>>>0?D:x;h=n;do{g=ie(k[h>>2]|0,0,S)|0;do if((h|0)==(n|0)){if((g|0)!=(S|0))break;i[U>>0]=48;g=U}else{if(g>>>0<=da>>>0)break;qf(da|0,48,g-Y|0)|0;do g=g+-1|0;while(g>>>0>da>>>0)}while(0);if(!(k[a>>2]&32))fe(g,T-g|0,a)|0;h=h+4|0}while(h>>>0<=D>>>0);do if(u|0){if(k[a>>2]&32|0)break;fe(1096522,1,a)|0}while(0);if((b|0)>0&h>>>0>>0)while(1){g=ie(k[h>>2]|0,0,S)|0;if(g>>>0>da>>>0){qf(da|0,48,g-Y|0)|0;do g=g+-1|0;while(g>>>0>da>>>0)}if(!(k[a>>2]&32))fe(g,(b|0)>9?9:b,a)|0;h=h+4|0;g=b+-9|0;if(!((b|0)>9&h>>>0>>0)){b=g;break}else b=g}ke(a,48,b+9|0,9,0)}else{q=y?B:x+4|0;if((b|0)>-1){o=(h|0)==0;n=x;do{g=ie(k[n>>2]|0,0,S)|0;if((g|0)==(S|0)){i[U>>0]=48;g=U}do if((n|0)==(x|0)){h=g+1|0;if(!(k[a>>2]&32))fe(g,1,a)|0;if(o&(b|0)<1){g=h;break}if(k[a>>2]&32|0){g=h;break}fe(1096522,1,a)|0;g=h}else{if(g>>>0<=da>>>0)break;qf(da|0,48,g+Z|0)|0;do g=g+-1|0;while(g>>>0>da>>>0)}while(0);h=T-g|0;if(!(k[a>>2]&32))fe(g,(b|0)>(h|0)?h:b,a)|0;b=b-h|0;n=n+4|0}while(n>>>0>>0&(b|0)>-1)}ke(a,48,b+18|0,18,0);if(k[a>>2]&32|0)break;fe(s,aa-s|0,a)|0}while(0);ke(a,32,I,v,G^8192);b=(v|0)<(I|0)?I:v}else{q=(s&32|0)!=0;o=m!=m|0.0!=0.0;g=o?0:E;n=g+3|0;ke(a,32,I,n,h);b=k[a>>2]|0;if(!(b&32)){fe(F,g,a)|0;b=k[a>>2]|0}if(!(b&32))fe(o?(q?1096514:1096518):q?1096506:1096510,3,a)|0;ke(a,32,I,n,G^8192);b=(n|0)<(I|0)?I:n}while(0);g=b;o=J;x=H;continue a}default:{b=x;h=G;s=o;v=0;u=1096470;g=N}}while(0);g:do if((K|0)==64){h=ba;g=k[h>>2]|0;h=k[h+4>>2]|0;n=s&32;if(!((g|0)==0&(h|0)==0)){b=N;do{b=b+-1|0;i[b>>0]=l[1096454+(g&15)>>0]|n;g=rf(g|0,h|0,4)|0;h=L}while(!((g|0)==0&(h|0)==0));K=ba;if((q&8|0)==0|(k[K>>2]|0)==0&(k[K+4>>2]|0)==0){g=q;q=0;n=1096470;K=77}else{g=q;q=2;n=1096470+(s>>4)|0;K=77}}else{b=N;g=q;q=0;n=1096470;K=77}}else if((K|0)==76){b=ie(b,g,N)|0;g=G;q=h;K=77}else if((K|0)==82){K=0;G=je(g,0,o)|0;F=(G|0)==0;b=g;s=F?o:G-g|0;v=0;u=1096470;g=F?g+o|0:G}else if((K|0)==86){K=0;h=0;g=0;q=b;while(1){n=k[q>>2]|0;if(!n)break;g=$d(fa,n)|0;if((g|0)<0|g>>>0>(o-h|0)>>>0)break;h=g+h|0;if(o>>>0>h>>>0)q=q+4|0;else break}if((g|0)<0){f=-1;break a}ke(a,32,I,h,G);if(!h){b=0;K=97}else{n=0;while(1){g=k[b>>2]|0;if(!g){b=h;K=97;break g}g=$d(fa,g)|0;n=g+n|0;if((n|0)>(h|0)){b=h;K=97;break g}if(!(k[a>>2]&32))fe(fa,g,a)|0;if(n>>>0>=h>>>0){b=h;K=97;break}else b=b+4|0}}}while(0);if((K|0)==97){K=0;ke(a,32,I,b,G^8192);g=(I|0)>(b|0)?I:b;o=J;x=H;continue}if((K|0)==77){K=0;h=(o|0)>-1?g&-65537:g;g=ba;g=(k[g>>2]|0)!=0|(k[g+4>>2]|0)!=0;if((o|0)!=0|g){s=(g&1^1)+(V-b)|0;s=(o|0)>(s|0)?o:s;v=q;u=n;g=N}else{b=N;s=0;v=q;u=n;g=N}}q=g-b|0;n=(s|0)<(q|0)?q:s;o=v+n|0;g=(I|0)<(o|0)?o:I;ke(a,32,g,o,h);if(!(k[a>>2]&32))fe(u,v,a)|0;ke(a,48,g,o,h^65536);ke(a,48,n,q,0);if(!(k[a>>2]&32))fe(b,q,a)|0;ke(a,32,g,o,h^8192);o=J;x=H}h:do if((K|0)==244)if(!a)if(!o)f=0;else{f=1;while(1){b=k[e+(f<<2)>>2]|0;if(!b){b=0;break}he(d+(f<<3)|0,b,c);f=f+1|0;if((f|0)>=10){f=1;break h}}while(1){f=f+1|0;if(b|0){f=-1;break h}if((f|0)>=10){f=1;break h}b=k[e+(f<<2)>>2]|0}}while(0);r=ia;return f|0}function fe(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=c+16|0;e=k[d>>2]|0;if(!e)if(!(ge(c)|0)){e=k[d>>2]|0;f=5}else d=0;else f=5;a:do if((f|0)==5){g=c+20|0;d=k[g>>2]|0;f=d;if((e-d|0)>>>0>>0){d=Ua[k[c+36>>2]&7](c,a,b)|0;break}b:do if((i[c+75>>0]|0)>-1){d=b;while(1){if(!d){e=f;d=0;break b}e=d+-1|0;if((i[a+e>>0]|0)==10)break;else d=e}if((Ua[k[c+36>>2]&7](c,a,d)|0)>>>0>>0)break a;b=b-d|0;a=a+d|0;e=k[g>>2]|0}else{e=f;d=0}while(0);tf(e|0,a|0,b|0)|0;k[g>>2]=(k[g>>2]|0)+b;d=d+b|0}while(0);return d|0}function ge(a){a=a|0;var b=0,c=0;b=a+74|0;c=i[b>>0]|0;i[b>>0]=c+255|c;b=k[a>>2]|0;if(!(b&8)){k[a+8>>2]=0;k[a+4>>2]=0;b=k[a+44>>2]|0;k[a+28>>2]=b;k[a+20>>2]=b;k[a+16>>2]=b+(k[a+48>>2]|0);b=0}else{k[a>>2]=b|32;b=-1}return b|0}function he(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0.0;a:do if(b>>>0<=20)do switch(b|0){case 9:{d=(k[c>>2]|0)+(4-1)&~(4-1);b=k[d>>2]|0;k[c>>2]=d+4;k[a>>2]=b;break a}case 10:{d=(k[c>>2]|0)+(4-1)&~(4-1);b=k[d>>2]|0;k[c>>2]=d+4;d=a;k[d>>2]=b;k[d+4>>2]=((b|0)<0)<<31>>31;break a}case 11:{d=(k[c>>2]|0)+(4-1)&~(4-1);b=k[d>>2]|0;k[c>>2]=d+4;d=a;k[d>>2]=b;k[d+4>>2]=0;break a}case 12:{d=(k[c>>2]|0)+(8-1)&~(8-1);b=d;e=k[b>>2]|0;b=k[b+4>>2]|0;k[c>>2]=d+8;d=a;k[d>>2]=e;k[d+4>>2]=b;break a}case 13:{e=(k[c>>2]|0)+(4-1)&~(4-1);d=k[e>>2]|0;k[c>>2]=e+4;d=(d&65535)<<16>>16;e=a;k[e>>2]=d;k[e+4>>2]=((d|0)<0)<<31>>31;break a}case 14:{e=(k[c>>2]|0)+(4-1)&~(4-1);d=k[e>>2]|0;k[c>>2]=e+4;e=a;k[e>>2]=d&65535;k[e+4>>2]=0;break a}case 15:{e=(k[c>>2]|0)+(4-1)&~(4-1);d=k[e>>2]|0;k[c>>2]=e+4;d=(d&255)<<24>>24;e=a;k[e>>2]=d;k[e+4>>2]=((d|0)<0)<<31>>31;break a}case 16:{e=(k[c>>2]|0)+(4-1)&~(4-1);d=k[e>>2]|0;k[c>>2]=e+4;e=a;k[e>>2]=d&255;k[e+4>>2]=0;break a}case 17:{e=(k[c>>2]|0)+(8-1)&~(8-1);f=+p[e>>3];k[c>>2]=e+8;p[a>>3]=f;break a}case 18:{e=(k[c>>2]|0)+(8-1)&~(8-1);f=+p[e>>3];k[c>>2]=e+8;p[a>>3]=f;break a}default:break a}while(0);while(0);return}function ie(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;if(b>>>0>0|(b|0)==0&a>>>0>4294967295)while(1){d=Cf(a|0,b|0,10,0)|0;c=c+-1|0;i[c>>0]=d|48;d=a;a=Bf(a|0,b|0,10,0)|0;if(!(b>>>0>9|(b|0)==9&d>>>0>4294967295))break;else b=L}if(a)while(1){c=c+-1|0;i[c>>0]=(a>>>0)%10|0|48;if(a>>>0<10)break;else a=(a>>>0)/10|0}return c|0}function je(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;f=b&255;d=(c|0)!=0;a:do if(d&(a&3|0)!=0){e=b&255;while(1){if((i[a>>0]|0)==e<<24>>24)break a;a=a+1|0;c=c+-1|0;d=(c|0)!=0;if(!(d&(a&3|0)!=0)){g=5;break}}}else g=5;while(0);b:do if((g|0)==5)if(d){e=b&255;if((i[a>>0]|0)!=e<<24>>24){d=ha(f,16843009)|0;c:do if(c>>>0>3)while(1){f=k[a>>2]^d;if((f&-2139062144^-2139062144)&f+-16843009|0)break;a=a+4|0;c=c+-4|0;if(c>>>0<=3){g=11;break c}}else g=11;while(0);if((g|0)==11)if(!c){c=0;break}while(1){if((i[a>>0]|0)==e<<24>>24)break b;a=a+1|0;c=c+-1|0;if(!c){c=0;break}}}}else c=0;while(0);return (c|0?a:0)|0}function ke(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;g=r;r=r+256|0;f=g;do if((c|0)>(d|0)&(e&73728|0)==0){e=c-d|0;qf(f|0,b|0,(e>>>0>256?256:e)|0)|0;d=k[a>>2]|0;c=(d&32|0)==0;if(e>>>0>255){b=e;do{if(c){fe(f,256,a)|0;d=k[a>>2]|0}b=b+-256|0;c=(d&32|0)==0}while(b>>>0>255);if(c)e=e&255;else break}else if(!c)break;fe(f,e,a)|0}while(0);r=g;return}function le(){return 0}function me(a,b){a=a|0;b=b|0;a=Ud(a,b)|0;return ((i[a>>0]|0)==(b&255)<<24>>24?a:0)|0}function ne(a,b){a=a|0;b=b|0;oe(a,b,4);return}function oe(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;e=b;a:do if(!((e^a)&3)){d=(c|0)!=0;if(d&(e&3|0)!=0)do{e=i[b>>0]|0;i[a>>0]=e;if(!(e<<24>>24))break a;c=c+-1|0;b=b+1|0;a=a+1|0;d=(c|0)!=0}while(d&(b&3|0)!=0);if(d){if(i[b>>0]|0){b:do if(c>>>0>3)do{d=k[b>>2]|0;if((d&-2139062144^-2139062144)&d+-16843009|0)break b;k[a>>2]=d;c=c+-4|0;b=b+4|0;a=a+4|0}while(c>>>0>3);while(0);f=11}}else c=0}else f=11;while(0);c:do if((f|0)==11)if(!c)c=0;else while(1){f=i[b>>0]|0;i[a>>0]=f;if(!(f<<24>>24))break c;c=c+-1|0;a=a+1|0;if(!c){c=0;break}else b=b+1|0}while(0);qf(a|0,0,c|0)|0;return}function pe(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=r;r=r+16|0;e=d;k[e>>2]=c;de(a,b,e)|0;r=d;return}function qe(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,j=0;j=r;r=r+16|0;h=j;g=b&255;i[h>>0]=g;d=a+16|0;e=k[d>>2]|0;if(!e)if(!(ge(a)|0)){e=k[d>>2]|0;f=4}else c=-1;else f=4;do if((f|0)==4){d=a+20|0;f=k[d>>2]|0;if(f>>>0>>0?(c=b&255,(c|0)!=(i[a+75>>0]|0)):0){k[d>>2]=f+1;i[f>>0]=g;break}if((Ua[k[a+36>>2]&7](a,h,1)|0)==1)c=l[h>>0]|0;else c=-1}while(0);r=j;return c|0}function re(){var a=0,b=0,c=0;do if((k[235273]|0)>=0?(le()|0)!=0:0){if((i[941091]|0)!=10?(a=k[235259]|0,a>>>0<(k[235258]|0)>>>0):0){k[235259]=a+1;i[a>>0]=10;break}qe(941016,10)|0}else c=3;while(0);do if((c|0)==3){if((i[941091]|0)!=10?(b=k[235259]|0,b>>>0<(k[235258]|0)>>>0):0){k[235259]=b+1;i[b>>0]=10;break}qe(941016,10)|0}while(0);return}function se(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;fe(a,ha(c,b)|0,d)|0;return}function te(a,b,c){a=a|0;b=b|0;c=c|0;be(a,2147483647,b,c);return}function ue(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=r;r=r+16|0;e=d;k[e>>2]=c;te(a,b,e);r=d;return}function ve(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;do if(a>>>0<245){o=a>>>0<11?16:a+11&-8;a=o>>>3;i=k[274328]|0;b=i>>>a;if(b&3|0){b=(b&1^1)+a|0;c=1097352+(b<<1<<2)|0;d=c+8|0;e=k[d>>2]|0;f=e+8|0;g=k[f>>2]|0;do if((c|0)!=(g|0)){if(g>>>0<(k[274332]|0)>>>0)Na();a=g+12|0;if((k[a>>2]|0)==(e|0)){k[a>>2]=c;k[d>>2]=g;break}else Na()}else k[274328]=i&~(1<>2]=G|3;G=e+G+4|0;k[G>>2]=k[G>>2]|1;G=f;return G|0}g=k[274330]|0;if(o>>>0>g>>>0){if(b|0){c=2<>>12&16;c=c>>>h;e=c>>>5&8;c=c>>>e;f=c>>>2&4;c=c>>>f;d=c>>>1&2;c=c>>>d;b=c>>>1&1;b=(e|h|f|d|b)+(c>>>b)|0;c=1097352+(b<<1<<2)|0;d=c+8|0;f=k[d>>2]|0;h=f+8|0;e=k[h>>2]|0;do if((c|0)!=(e|0)){if(e>>>0<(k[274332]|0)>>>0)Na();a=e+12|0;if((k[a>>2]|0)==(f|0)){k[a>>2]=c;k[d>>2]=e;j=k[274330]|0;break}else Na()}else{k[274328]=i&~(1<>2]=o|3;d=f+o|0;k[d+4>>2]=g|1;k[d+g>>2]=g;if(j|0){e=k[274333]|0;b=j>>>3;c=1097352+(b<<1<<2)|0;a=k[274328]|0;b=1<>2]|0;if(b>>>0<(k[274332]|0)>>>0)Na();else{l=a;m=b}}else{k[274328]=a|b;l=c+8|0;m=c}k[l>>2]=e;k[m+12>>2]=e;k[e+8>>2]=m;k[e+12>>2]=c}k[274330]=g;k[274333]=d;G=h;return G|0}a=k[274329]|0;if(a){h=(a&0-a)+-1|0;F=h>>>12&16;h=h>>>F;E=h>>>5&8;h=h>>>E;G=h>>>2&4;h=h>>>G;b=h>>>1&2;h=h>>>b;i=h>>>1&1;i=k[1097616+((E|F|G|b|i)+(h>>>i)<<2)>>2]|0;h=(k[i+4>>2]&-8)-o|0;b=i;while(1){a=k[b+16>>2]|0;if(!a){a=k[b+20>>2]|0;if(!a)break}b=(k[a+4>>2]&-8)-o|0;G=b>>>0>>0;h=G?b:h;b=a;i=G?a:i}e=k[274332]|0;if(i>>>0>>0)Na();g=i+o|0;if(i>>>0>=g>>>0)Na();f=k[i+24>>2]|0;c=k[i+12>>2]|0;do if((c|0)==(i|0)){b=i+20|0;a=k[b>>2]|0;if(!a){b=i+16|0;a=k[b>>2]|0;if(!a){n=0;break}}while(1){c=a+20|0;d=k[c>>2]|0;if(d|0){a=d;b=c;continue}c=a+16|0;d=k[c>>2]|0;if(!d)break;else{a=d;b=c}}if(b>>>0>>0)Na();else{k[b>>2]=0;n=a;break}}else{d=k[i+8>>2]|0;if(d>>>0>>0)Na();a=d+12|0;if((k[a>>2]|0)!=(i|0))Na();b=c+8|0;if((k[b>>2]|0)==(i|0)){k[a>>2]=c;k[b>>2]=d;n=c;break}else Na()}while(0);do if(f|0){a=k[i+28>>2]|0;b=1097616+(a<<2)|0;if((i|0)==(k[b>>2]|0)){k[b>>2]=n;if(!n){k[274329]=k[274329]&~(1<>>0<(k[274332]|0)>>>0)Na();a=f+16|0;if((k[a>>2]|0)==(i|0))k[a>>2]=n;else k[f+20>>2]=n;if(!n)break}b=k[274332]|0;if(n>>>0>>0)Na();k[n+24>>2]=f;a=k[i+16>>2]|0;do if(a|0)if(a>>>0>>0)Na();else{k[n+16>>2]=a;k[a+24>>2]=n;break}while(0);a=k[i+20>>2]|0;if(a|0)if(a>>>0<(k[274332]|0)>>>0)Na();else{k[n+20>>2]=a;k[a+24>>2]=n;break}}while(0);if(h>>>0<16){G=h+o|0;k[i+4>>2]=G|3;G=i+G+4|0;k[G>>2]=k[G>>2]|1}else{k[i+4>>2]=o|3;k[g+4>>2]=h|1;k[g+h>>2]=h;a=k[274330]|0;if(a|0){d=k[274333]|0;b=a>>>3;c=1097352+(b<<1<<2)|0;a=k[274328]|0;b=1<>2]|0;if(b>>>0<(k[274332]|0)>>>0)Na();else{p=a;q=b}}else{k[274328]=a|b;p=c+8|0;q=c}k[p>>2]=d;k[q+12>>2]=d;k[d+8>>2]=q;k[d+12>>2]=c}k[274330]=h;k[274333]=g}G=i+8|0;return G|0}}}else if(a>>>0<=4294967231){a=a+11|0;o=a&-8;j=k[274329]|0;if(j){c=0-o|0;a=a>>>8;if(a)if(o>>>0>16777215)i=31;else{q=(a+1048320|0)>>>16&8;z=a<>>16&4;z=z<>>16&2;i=14-(p|q|i)+(z<>>15)|0;i=o>>>(i+7|0)&1|i<<1}else i=0;b=k[1097616+(i<<2)>>2]|0;a:do if(!b){a=0;b=0;z=86}else{e=c;a=0;g=o<<((i|0)==31?0:25-(i>>>1)|0);h=b;b=0;while(1){d=k[h+4>>2]&-8;c=d-o|0;if(c>>>0>>0)if((d|0)==(o|0)){a=h;b=h;z=90;break a}else b=h;else c=e;d=k[h+20>>2]|0;h=k[h+16+(g>>>31<<2)>>2]|0;a=(d|0)==0|(d|0)==(h|0)?a:d;d=(h|0)==0;if(d){z=86;break}else{e=c;g=g<<(d&1^1)}}}while(0);if((z|0)==86){if((a|0)==0&(b|0)==0){a=2<>>12&16;q=q>>>m;l=q>>>5&8;q=q>>>l;n=q>>>2&4;q=q>>>n;p=q>>>1&2;q=q>>>p;a=q>>>1&1;a=k[1097616+((l|m|n|p|a)+(q>>>a)<<2)>>2]|0}if(!a){h=c;i=b}else z=90}if((z|0)==90)while(1){z=0;q=(k[a+4>>2]&-8)-o|0;d=q>>>0>>0;c=d?q:c;b=d?a:b;d=k[a+16>>2]|0;if(d|0){a=d;z=90;continue}a=k[a+20>>2]|0;if(!a){h=c;i=b;break}else z=90}if((i|0)!=0?h>>>0<((k[274330]|0)-o|0)>>>0:0){e=k[274332]|0;if(i>>>0>>0)Na();g=i+o|0;if(i>>>0>=g>>>0)Na();f=k[i+24>>2]|0;c=k[i+12>>2]|0;do if((c|0)==(i|0)){b=i+20|0;a=k[b>>2]|0;if(!a){b=i+16|0;a=k[b>>2]|0;if(!a){s=0;break}}while(1){c=a+20|0;d=k[c>>2]|0;if(d|0){a=d;b=c;continue}c=a+16|0;d=k[c>>2]|0;if(!d)break;else{a=d;b=c}}if(b>>>0>>0)Na();else{k[b>>2]=0;s=a;break}}else{d=k[i+8>>2]|0;if(d>>>0>>0)Na();a=d+12|0;if((k[a>>2]|0)!=(i|0))Na();b=c+8|0;if((k[b>>2]|0)==(i|0)){k[a>>2]=c;k[b>>2]=d;s=c;break}else Na()}while(0);do if(f|0){a=k[i+28>>2]|0;b=1097616+(a<<2)|0;if((i|0)==(k[b>>2]|0)){k[b>>2]=s;if(!s){k[274329]=k[274329]&~(1<>>0<(k[274332]|0)>>>0)Na();a=f+16|0;if((k[a>>2]|0)==(i|0))k[a>>2]=s;else k[f+20>>2]=s;if(!s)break}b=k[274332]|0;if(s>>>0>>0)Na();k[s+24>>2]=f;a=k[i+16>>2]|0;do if(a|0)if(a>>>0>>0)Na();else{k[s+16>>2]=a;k[a+24>>2]=s;break}while(0);a=k[i+20>>2]|0;if(a|0)if(a>>>0<(k[274332]|0)>>>0)Na();else{k[s+20>>2]=a;k[a+24>>2]=s;break}}while(0);do if(h>>>0>=16){k[i+4>>2]=o|3;k[g+4>>2]=h|1;k[g+h>>2]=h;a=h>>>3;if(h>>>0<256){c=1097352+(a<<1<<2)|0;b=k[274328]|0;a=1<>2]|0;if(b>>>0<(k[274332]|0)>>>0)Na();else{t=a;v=b}}else{k[274328]=b|a;t=c+8|0;v=c}k[t>>2]=g;k[v+12>>2]=g;k[g+8>>2]=v;k[g+12>>2]=c;break}a=h>>>8;if(a)if(h>>>0>16777215)c=31;else{F=(a+1048320|0)>>>16&8;G=a<>>16&4;G=G<>>16&2;c=14-(E|F|c)+(G<>>15)|0;c=h>>>(c+7|0)&1|c<<1}else c=0;d=1097616+(c<<2)|0;k[g+28>>2]=c;a=g+16|0;k[a+4>>2]=0;k[a>>2]=0;a=k[274329]|0;b=1<>2]=g;k[g+24>>2]=d;k[g+12>>2]=g;k[g+8>>2]=g;break}c=h<<((c|0)==31?0:25-(c>>>1)|0);d=k[d>>2]|0;while(1){if((k[d+4>>2]&-8|0)==(h|0)){z=148;break}b=d+16+(c>>>31<<2)|0;a=k[b>>2]|0;if(!a){z=145;break}else{c=c<<1;d=a}}if((z|0)==145)if(b>>>0<(k[274332]|0)>>>0)Na();else{k[b>>2]=g;k[g+24>>2]=d;k[g+12>>2]=g;k[g+8>>2]=g;break}else if((z|0)==148){a=d+8|0;b=k[a>>2]|0;G=k[274332]|0;if(b>>>0>=G>>>0&d>>>0>=G>>>0){k[b+12>>2]=g;k[a>>2]=g;k[g+8>>2]=b;k[g+12>>2]=d;k[g+24>>2]=0;break}else Na()}}else{G=h+o|0;k[i+4>>2]=G|3;G=i+G+4|0;k[G>>2]=k[G>>2]|1}while(0);G=i+8|0;return G|0}}}else o=-1;while(0);c=k[274330]|0;if(c>>>0>=o>>>0){a=c-o|0;b=k[274333]|0;if(a>>>0>15){G=b+o|0;k[274333]=G;k[274330]=a;k[G+4>>2]=a|1;k[G+a>>2]=a;k[b+4>>2]=o|3}else{k[274330]=0;k[274333]=0;k[b+4>>2]=c|3;G=b+c+4|0;k[G>>2]=k[G>>2]|1}G=b+8|0;return G|0}a=k[274331]|0;if(a>>>0>o>>>0){E=a-o|0;k[274331]=E;G=k[274334]|0;F=G+o|0;k[274334]=F;k[F+4>>2]=E|1;k[G+4>>2]=o|3;G=G+8|0;return G|0}do if(!(k[274446]|0)){a=Fa(30)|0;if(!(a+-1&a)){k[274448]=a;k[274447]=a;k[274449]=-1;k[274450]=-1;k[274451]=0;k[274439]=0;v=(Pa(0)|0)&-16^1431655768;k[274446]=v;break}else Na()}while(0);g=o+48|0;d=k[274448]|0;h=o+47|0;c=d+h|0;d=0-d|0;i=c&d;if(i>>>0<=o>>>0){G=0;return G|0}a=k[274438]|0;if(a|0?(t=k[274436]|0,v=t+i|0,v>>>0<=t>>>0|v>>>0>a>>>0):0){G=0;return G|0}b:do if(!(k[274439]&4)){b=k[274334]|0;c:do if(b){e=1097760;while(1){a=k[e>>2]|0;if(a>>>0<=b>>>0?(r=e+4|0,(a+(k[r>>2]|0)|0)>>>0>b>>>0):0)break;a=k[e+8>>2]|0;if(!a){z=173;break c}else e=a}a=c-(k[274331]|0)&d;if(a>>>0<2147483647){b=Aa(a|0)|0;if((b|0)==((k[e>>2]|0)+(k[r>>2]|0)|0)){if((b|0)!=(-1|0)){g=b;f=a;z=193;break b}}else z=183}}else z=173;while(0);do if((z|0)==173?(u=Aa(0)|0,(u|0)!=(-1|0)):0){a=u;b=k[274447]|0;c=b+-1|0;if(!(c&a))a=i;else a=i-a+(c+a&0-b)|0;b=k[274436]|0;c=b+a|0;if(a>>>0>o>>>0&a>>>0<2147483647){v=k[274438]|0;if(v|0?c>>>0<=b>>>0|c>>>0>v>>>0:0)break;b=Aa(a|0)|0;if((b|0)==(u|0)){g=u;f=a;z=193;break b}else z=183}}while(0);d:do if((z|0)==183){c=0-a|0;do if(g>>>0>a>>>0&(a>>>0<2147483647&(b|0)!=(-1|0))?(w=k[274448]|0,w=h-a+w&0-w,w>>>0<2147483647):0)if((Aa(w|0)|0)==(-1|0)){Aa(c|0)|0;break d}else{a=w+a|0;break}while(0);if((b|0)!=(-1|0)){g=b;f=a;z=193;break b}}while(0);k[274439]=k[274439]|4;z=190}else z=190;while(0);if((((z|0)==190?i>>>0<2147483647:0)?(x=Aa(i|0)|0,y=Aa(0)|0,x>>>0>>0&((x|0)!=(-1|0)&(y|0)!=(-1|0))):0)?(f=y-x|0,f>>>0>(o+40|0)>>>0):0){g=x;z=193}if((z|0)==193){a=(k[274436]|0)+f|0;k[274436]=a;if(a>>>0>(k[274437]|0)>>>0)k[274437]=a;j=k[274334]|0;do if(j){e=1097760;while(1){a=k[e>>2]|0;b=e+4|0;c=k[b>>2]|0;if((g|0)==(a+c|0)){z=203;break}d=k[e+8>>2]|0;if(!d)break;else e=d}if(((z|0)==203?(k[e+12>>2]&8|0)==0:0)?j>>>0>>0&j>>>0>=a>>>0:0){k[b>>2]=c+f;G=j+8|0;G=(G&7|0)==0?0:0-G&7;F=j+G|0;G=f-G+(k[274331]|0)|0;k[274334]=F;k[274331]=G;k[F+4>>2]=G|1;k[F+G+4>>2]=40;k[274335]=k[274450];break}a=k[274332]|0;if(g>>>0>>0){k[274332]=g;h=g}else h=a;b=g+f|0;a=1097760;while(1){if((k[a>>2]|0)==(b|0)){z=211;break}a=k[a+8>>2]|0;if(!a){b=1097760;break}}if((z|0)==211)if(!(k[a+12>>2]&8)){k[a>>2]=g;m=a+4|0;k[m>>2]=(k[m>>2]|0)+f;m=g+8|0;m=g+((m&7|0)==0?0:0-m&7)|0;a=b+8|0;a=b+((a&7|0)==0?0:0-a&7)|0;l=m+o|0;i=a-m-o|0;k[m+4>>2]=o|3;do if((a|0)!=(j|0)){if((a|0)==(k[274333]|0)){G=(k[274330]|0)+i|0;k[274330]=G;k[274333]=l;k[l+4>>2]=G|1;k[l+G>>2]=G;break}b=k[a+4>>2]|0;if((b&3|0)==1){g=b&-8;e=b>>>3;e:do if(b>>>0>=256){f=k[a+24>>2]|0;d=k[a+12>>2]|0;do if((d|0)==(a|0)){d=a+16|0;c=d+4|0;b=k[c>>2]|0;if(!b){b=k[d>>2]|0;if(!b){E=0;break}else c=d}while(1){d=b+20|0;e=k[d>>2]|0;if(e|0){b=e;c=d;continue}d=b+16|0;e=k[d>>2]|0;if(!e)break;else{b=e;c=d}}if(c>>>0>>0)Na();else{k[c>>2]=0;E=b;break}}else{e=k[a+8>>2]|0;if(e>>>0>>0)Na();b=e+12|0;if((k[b>>2]|0)!=(a|0))Na();c=d+8|0;if((k[c>>2]|0)==(a|0)){k[b>>2]=d;k[c>>2]=e;E=d;break}else Na()}while(0);if(!f)break;b=k[a+28>>2]|0;c=1097616+(b<<2)|0;do if((a|0)!=(k[c>>2]|0)){if(f>>>0<(k[274332]|0)>>>0)Na();b=f+16|0;if((k[b>>2]|0)==(a|0))k[b>>2]=E;else k[f+20>>2]=E;if(!E)break e}else{k[c>>2]=E;if(E|0)break;k[274329]=k[274329]&~(1<>>0>>0)Na();k[E+24>>2]=f;b=a+16|0;c=k[b>>2]|0;do if(c|0)if(c>>>0>>0)Na();else{k[E+16>>2]=c;k[c+24>>2]=E;break}while(0);b=k[b+4>>2]|0;if(!b)break;if(b>>>0<(k[274332]|0)>>>0)Na();else{k[E+20>>2]=b;k[b+24>>2]=E;break}}else{c=k[a+8>>2]|0;d=k[a+12>>2]|0;b=1097352+(e<<1<<2)|0;do if((c|0)!=(b|0)){if(c>>>0>>0)Na();if((k[c+12>>2]|0)==(a|0))break;Na()}while(0);if((d|0)==(c|0)){k[274328]=k[274328]&~(1<>>0>>0)Na();b=d+8|0;if((k[b>>2]|0)==(a|0)){B=b;break}Na()}while(0);k[c+12>>2]=d;k[B>>2]=c}while(0);a=a+g|0;e=g+i|0}else e=i;a=a+4|0;k[a>>2]=k[a>>2]&-2;k[l+4>>2]=e|1;k[l+e>>2]=e;a=e>>>3;if(e>>>0<256){c=1097352+(a<<1<<2)|0;b=k[274328]|0;a=1<>2]|0;if(b>>>0>=(k[274332]|0)>>>0){F=a;G=b;break}Na()}while(0);k[F>>2]=l;k[G+12>>2]=l;k[l+8>>2]=G;k[l+12>>2]=c;break}a=e>>>8;do if(!a)c=0;else{if(e>>>0>16777215){c=31;break}F=(a+1048320|0)>>>16&8;G=a<>>16&4;G=G<>>16&2;c=14-(E|F|c)+(G<>>15)|0;c=e>>>(c+7|0)&1|c<<1}while(0);d=1097616+(c<<2)|0;k[l+28>>2]=c;a=l+16|0;k[a+4>>2]=0;k[a>>2]=0;a=k[274329]|0;b=1<>2]=l;k[l+24>>2]=d;k[l+12>>2]=l;k[l+8>>2]=l;break}c=e<<((c|0)==31?0:25-(c>>>1)|0);d=k[d>>2]|0;while(1){if((k[d+4>>2]&-8|0)==(e|0)){z=281;break}b=d+16+(c>>>31<<2)|0;a=k[b>>2]|0;if(!a){z=278;break}else{c=c<<1;d=a}}if((z|0)==278)if(b>>>0<(k[274332]|0)>>>0)Na();else{k[b>>2]=l;k[l+24>>2]=d;k[l+12>>2]=l;k[l+8>>2]=l;break}else if((z|0)==281){a=d+8|0;b=k[a>>2]|0;G=k[274332]|0;if(b>>>0>=G>>>0&d>>>0>=G>>>0){k[b+12>>2]=l;k[a>>2]=l;k[l+8>>2]=b;k[l+12>>2]=d;k[l+24>>2]=0;break}else Na()}}else{G=(k[274331]|0)+i|0;k[274331]=G;k[274334]=l;k[l+4>>2]=G|1}while(0);G=m+8|0;return G|0}else b=1097760;while(1){a=k[b>>2]|0;if(a>>>0<=j>>>0?(A=a+(k[b+4>>2]|0)|0,A>>>0>j>>>0):0)break;b=k[b+8>>2]|0}e=A+-47|0;b=e+8|0;b=e+((b&7|0)==0?0:0-b&7)|0;e=j+16|0;b=b>>>0>>0?j:b;a=b+8|0;c=g+8|0;c=(c&7|0)==0?0:0-c&7;G=g+c|0;c=f+-40-c|0;k[274334]=G;k[274331]=c;k[G+4>>2]=c|1;k[G+c+4>>2]=40;k[274335]=k[274450];c=b+4|0;k[c>>2]=27;k[a>>2]=k[274440];k[a+4>>2]=k[274441];k[a+8>>2]=k[274442];k[a+12>>2]=k[274443];k[274440]=g;k[274441]=f;k[274443]=0;k[274442]=a;a=b+24|0;do{a=a+4|0;k[a>>2]=7}while((a+4|0)>>>0>>0);if((b|0)!=(j|0)){f=b-j|0;k[c>>2]=k[c>>2]&-2;k[j+4>>2]=f|1;k[b>>2]=f;a=f>>>3;if(f>>>0<256){c=1097352+(a<<1<<2)|0;b=k[274328]|0;a=1<>2]|0;if(b>>>0<(k[274332]|0)>>>0)Na();else{C=a;D=b}}else{k[274328]=b|a;C=c+8|0;D=c}k[C>>2]=j;k[D+12>>2]=j;k[j+8>>2]=D;k[j+12>>2]=c;break}a=f>>>8;if(a)if(f>>>0>16777215)c=31;else{F=(a+1048320|0)>>>16&8;G=a<>>16&4;G=G<>>16&2;c=14-(E|F|c)+(G<>>15)|0;c=f>>>(c+7|0)&1|c<<1}else c=0;d=1097616+(c<<2)|0;k[j+28>>2]=c;k[j+20>>2]=0;k[e>>2]=0;a=k[274329]|0;b=1<>2]=j;k[j+24>>2]=d;k[j+12>>2]=j;k[j+8>>2]=j;break}c=f<<((c|0)==31?0:25-(c>>>1)|0);d=k[d>>2]|0;while(1){if((k[d+4>>2]&-8|0)==(f|0)){z=307;break}b=d+16+(c>>>31<<2)|0;a=k[b>>2]|0;if(!a){z=304;break}else{c=c<<1;d=a}}if((z|0)==304)if(b>>>0<(k[274332]|0)>>>0)Na();else{k[b>>2]=j;k[j+24>>2]=d;k[j+12>>2]=j;k[j+8>>2]=j;break}else if((z|0)==307){a=d+8|0;b=k[a>>2]|0;G=k[274332]|0;if(b>>>0>=G>>>0&d>>>0>=G>>>0){k[b+12>>2]=j;k[a>>2]=j;k[j+8>>2]=b;k[j+12>>2]=d;k[j+24>>2]=0;break}else Na()}}}else{G=k[274332]|0;if((G|0)==0|g>>>0>>0)k[274332]=g;k[274440]=g;k[274441]=f;k[274443]=0;k[274337]=k[274446];k[274336]=-1;a=0;do{G=1097352+(a<<1<<2)|0;k[G+12>>2]=G;k[G+8>>2]=G;a=a+1|0}while((a|0)!=32);G=g+8|0;G=(G&7|0)==0?0:0-G&7;F=g+G|0;G=f+-40-G|0;k[274334]=F;k[274331]=G;k[F+4>>2]=G|1;k[F+G+4>>2]=40;k[274335]=k[274450]}while(0);a=k[274331]|0;if(a>>>0>o>>>0){E=a-o|0;k[274331]=E;G=k[274334]|0;F=G+o|0;k[274334]=F;k[F+4>>2]=E|1;k[G+4>>2]=o|3;G=G+8|0;return G|0}}G=Qd()|0;k[G>>2]=12;G=0;return G|0} +function we(a){a=a|0;var b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0;if(!a)return;c=a+-8|0;g=k[274332]|0;if(c>>>0>>0)Na();a=k[a+-4>>2]|0;b=a&3;if((b|0)==1)Na();d=a&-8;m=c+d|0;do if(!(a&1)){a=k[c>>2]|0;if(!b)return;j=c+(0-a)|0;i=a+d|0;if(j>>>0>>0)Na();if((j|0)==(k[274333]|0)){a=m+4|0;b=k[a>>2]|0;if((b&3|0)!=3){q=j;e=i;break}k[274330]=i;k[a>>2]=b&-2;k[j+4>>2]=i|1;k[j+i>>2]=i;return}d=a>>>3;if(a>>>0<256){b=k[j+8>>2]|0;c=k[j+12>>2]|0;a=1097352+(d<<1<<2)|0;if((b|0)!=(a|0)){if(b>>>0>>0)Na();if((k[b+12>>2]|0)!=(j|0))Na()}if((c|0)==(b|0)){k[274328]=k[274328]&~(1<>>0>>0)Na();a=c+8|0;if((k[a>>2]|0)==(j|0))f=a;else Na()}else f=c+8|0;k[b+12>>2]=c;k[f>>2]=b;q=j;e=i;break}f=k[j+24>>2]|0;c=k[j+12>>2]|0;do if((c|0)==(j|0)){c=j+16|0;b=c+4|0;a=k[b>>2]|0;if(!a){a=k[c>>2]|0;if(!a){h=0;break}else b=c}while(1){c=a+20|0;d=k[c>>2]|0;if(d|0){a=d;b=c;continue}c=a+16|0;d=k[c>>2]|0;if(!d)break;else{a=d;b=c}}if(b>>>0>>0)Na();else{k[b>>2]=0;h=a;break}}else{d=k[j+8>>2]|0;if(d>>>0>>0)Na();a=d+12|0;if((k[a>>2]|0)!=(j|0))Na();b=c+8|0;if((k[b>>2]|0)==(j|0)){k[a>>2]=c;k[b>>2]=d;h=c;break}else Na()}while(0);if(f){a=k[j+28>>2]|0;b=1097616+(a<<2)|0;if((j|0)==(k[b>>2]|0)){k[b>>2]=h;if(!h){k[274329]=k[274329]&~(1<>>0<(k[274332]|0)>>>0)Na();a=f+16|0;if((k[a>>2]|0)==(j|0))k[a>>2]=h;else k[f+20>>2]=h;if(!h){q=j;e=i;break}}c=k[274332]|0;if(h>>>0>>0)Na();k[h+24>>2]=f;a=j+16|0;b=k[a>>2]|0;do if(b|0)if(b>>>0>>0)Na();else{k[h+16>>2]=b;k[b+24>>2]=h;break}while(0);a=k[a+4>>2]|0;if(a)if(a>>>0<(k[274332]|0)>>>0)Na();else{k[h+20>>2]=a;k[a+24>>2]=h;q=j;e=i;break}else{q=j;e=i}}else{q=j;e=i}}else{q=c;e=d}while(0);if(q>>>0>=m>>>0)Na();a=m+4|0;b=k[a>>2]|0;if(!(b&1))Na();if(!(b&2)){if((m|0)==(k[274334]|0)){p=(k[274331]|0)+e|0;k[274331]=p;k[274334]=q;k[q+4>>2]=p|1;if((q|0)!=(k[274333]|0))return;k[274333]=0;k[274330]=0;return}if((m|0)==(k[274333]|0)){p=(k[274330]|0)+e|0;k[274330]=p;k[274333]=q;k[q+4>>2]=p|1;k[q+p>>2]=p;return}e=(b&-8)+e|0;d=b>>>3;do if(b>>>0>=256){f=k[m+24>>2]|0;a=k[m+12>>2]|0;do if((a|0)==(m|0)){c=m+16|0;b=c+4|0;a=k[b>>2]|0;if(!a){a=k[c>>2]|0;if(!a){n=0;break}else b=c}while(1){c=a+20|0;d=k[c>>2]|0;if(d|0){a=d;b=c;continue}c=a+16|0;d=k[c>>2]|0;if(!d)break;else{a=d;b=c}}if(b>>>0<(k[274332]|0)>>>0)Na();else{k[b>>2]=0;n=a;break}}else{b=k[m+8>>2]|0;if(b>>>0<(k[274332]|0)>>>0)Na();c=b+12|0;if((k[c>>2]|0)!=(m|0))Na();d=a+8|0;if((k[d>>2]|0)==(m|0)){k[c>>2]=a;k[d>>2]=b;n=a;break}else Na()}while(0);if(f|0){a=k[m+28>>2]|0;b=1097616+(a<<2)|0;if((m|0)==(k[b>>2]|0)){k[b>>2]=n;if(!n){k[274329]=k[274329]&~(1<>>0<(k[274332]|0)>>>0)Na();a=f+16|0;if((k[a>>2]|0)==(m|0))k[a>>2]=n;else k[f+20>>2]=n;if(!n)break}c=k[274332]|0;if(n>>>0>>0)Na();k[n+24>>2]=f;a=m+16|0;b=k[a>>2]|0;do if(b|0)if(b>>>0>>0)Na();else{k[n+16>>2]=b;k[b+24>>2]=n;break}while(0);a=k[a+4>>2]|0;if(a|0)if(a>>>0<(k[274332]|0)>>>0)Na();else{k[n+20>>2]=a;k[a+24>>2]=n;break}}}else{b=k[m+8>>2]|0;c=k[m+12>>2]|0;a=1097352+(d<<1<<2)|0;if((b|0)!=(a|0)){if(b>>>0<(k[274332]|0)>>>0)Na();if((k[b+12>>2]|0)!=(m|0))Na()}if((c|0)==(b|0)){k[274328]=k[274328]&~(1<>>0<(k[274332]|0)>>>0)Na();a=c+8|0;if((k[a>>2]|0)==(m|0))l=a;else Na()}else l=c+8|0;k[b+12>>2]=c;k[l>>2]=b}while(0);k[q+4>>2]=e|1;k[q+e>>2]=e;if((q|0)==(k[274333]|0)){k[274330]=e;return}}else{k[a>>2]=b&-2;k[q+4>>2]=e|1;k[q+e>>2]=e}a=e>>>3;if(e>>>0<256){c=1097352+(a<<1<<2)|0;b=k[274328]|0;a=1<>2]|0;if(b>>>0<(k[274332]|0)>>>0)Na();else{o=a;p=b}}else{k[274328]=b|a;o=c+8|0;p=c}k[o>>2]=q;k[p+12>>2]=q;k[q+8>>2]=p;k[q+12>>2]=c;return}a=e>>>8;if(a)if(e>>>0>16777215)c=31;else{o=(a+1048320|0)>>>16&8;p=a<>>16&4;p=p<>>16&2;c=14-(n|o|c)+(p<>>15)|0;c=e>>>(c+7|0)&1|c<<1}else c=0;d=1097616+(c<<2)|0;k[q+28>>2]=c;k[q+20>>2]=0;k[q+16>>2]=0;a=k[274329]|0;b=1<>>1)|0);d=k[d>>2]|0;while(1){if((k[d+4>>2]&-8|0)==(e|0)){a=130;break}b=d+16+(c>>>31<<2)|0;a=k[b>>2]|0;if(!a){a=127;break}else{c=c<<1;d=a}}if((a|0)==127)if(b>>>0<(k[274332]|0)>>>0)Na();else{k[b>>2]=q;k[q+24>>2]=d;k[q+12>>2]=q;k[q+8>>2]=q;break}else if((a|0)==130){a=d+8|0;b=k[a>>2]|0;p=k[274332]|0;if(b>>>0>=p>>>0&d>>>0>=p>>>0){k[b+12>>2]=q;k[a>>2]=q;k[q+8>>2]=b;k[q+12>>2]=d;k[q+24>>2]=0;break}else Na()}}else{k[274329]=a|b;k[d>>2]=q;k[q+24>>2]=d;k[q+12>>2]=q;k[q+8>>2]=q}while(0);q=(k[274336]|0)+-1|0;k[274336]=q;if(!q)a=1097768;else return;while(1){a=k[a>>2]|0;if(!a)break;else a=a+8|0}k[274336]=-1;return}function xe(){wa(1096524,1096553,1164,1096636)}function ye(){wa(1096657,1096553,1175,1096686)}function ze(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;if(c>>>0>4294967279)xe();if(c>>>0<11){i[a>>0]=c<<1;a=a+1|0}else{e=c+16&-16;d=gf(e)|0;k[a+8>>2]=d;k[a>>2]=e|1;k[a+4>>2]=c;a=d}tf(a|0,b|0,c|0)|0;i[a+c>>0]=0;return}function Ae(a){a=a|0;if(i[a>>0]&1)Qe(k[a+8>>2]|0);return}function Be(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,l=0,m=0;if((-18-b|0)>>>0>>0)xe();if(!(i[a>>0]&1))m=a+1|0;else m=k[a+8>>2]|0;if(b>>>0<2147483623){j=c+b|0;l=b<<1;j=j>>>0>>0?l:j;j=j>>>0<11?11:j+16&-16}else j=-17;l=gf(j)|0;if(e|0)tf(l|0,m|0,e|0)|0;if(g|0)tf(l+e|0,h|0,g|0)|0;c=d-f|0;if((c|0)!=(e|0))tf(l+e+g|0,m+e+f|0,c-e|0)|0;if((b|0)!=10)Qe(m);k[a+8>>2]=l;k[a>>2]=j|1;b=c+g|0;k[a+4>>2]=b;i[l+b>>0]=0;return}function Ce(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;if(b|0){d=i[a>>0]|0;if(!(d&1))e=10;else{d=k[a>>2]|0;e=(d&-2)+-1|0;d=d&255}if(!(d&1))f=(d&255)>>>1;else f=k[a+4>>2]|0;if((e-f|0)>>>0>>0){De(a,e,b-e+f|0,f,f);d=i[a>>0]|0}if(!(d&1))e=a+1|0;else e=k[a+8>>2]|0;qf(e+f|0,c|0,b|0)|0;d=f+b|0;if(!(i[a>>0]&1))i[a>>0]=d<<1;else k[a+4>>2]=d;i[e+d>>0]=0}return}function De(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;if((-17-b|0)>>>0>>0)xe();if(!(i[a>>0]&1))g=a+1|0;else g=k[a+8>>2]|0;if(b>>>0<2147483623){c=c+b|0;f=b<<1;c=c>>>0>>0?f:c;c=c>>>0<11?11:c+16&-16}else c=-17;f=gf(c)|0;if(e|0)tf(f|0,g|0,e|0)|0;if((d|0)!=(e|0))tf(f+e|0,g+e|0,d-e|0)|0;if((b|0)!=10)Qe(g);k[a+8>>2]=f;k[a>>2]=c|1;return}function Ee(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0;d=i[a>>0]|0;if(!(d&1))f=10;else{d=k[a>>2]|0;f=(d&-2)+-1|0;d=d&255}e=(d&1)==0;if(e)d=(d&255)>>>1;else d=k[a+4>>2]|0;if((f-d|0)>>>0>=c>>>0){if(c|0){if(e)e=a+1|0;else e=k[a+8>>2]|0;tf(e+d|0,b|0,c|0)|0;d=d+c|0;if(!(i[a>>0]&1))i[a>>0]=d<<1;else k[a+4>>2]=d;i[e+d>>0]=0}}else Be(a,f,c-f+d|0,d,d,0,c,b);return}function Fe(a,b){a=a|0;b=b|0;Ee(a,b,Vd(b)|0);return}function Ge(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=i[a>>0]|0;d=(c&1)!=0;if(d){e=(k[a>>2]&-2)+-1|0;f=k[a+4>>2]|0}else{e=10;f=(c&255)>>>1}if((f|0)==(e|0)){De(a,e,1,e,e);if(!(i[a>>0]&1))d=7;else d=8}else if(d)d=8;else d=7;if((d|0)==7){i[a>>0]=(f<<1)+2;c=a+1|0}else if((d|0)==8){c=k[a+8>>2]|0;k[a+4>>2]=f+1}a=c+f|0;i[a>>0]=b;i[a+1>>0]=0;return}function He(a,b){a=a|0;b=b|0;var c=0,d=0;c=i[a>>0]|0;d=(c&1)==0;if(d)c=(c&255)>>>1;else c=k[a+4>>2]|0;if(c>>>0>>0)ye();if(d){i[a>>0]=b<<1;c=a+1|0}else{c=k[a+8>>2]|0;k[a+4>>2]=b}i[c+b>>0]=0;return}function Ie(a,b){a=a|0;b=b|0;var c=0,d=0;c=i[a>>0]|0;if(!(c&1)){d=(c&255)>>>1;c=a+1|0}else{d=k[a+4>>2]|0;c=k[a+8>>2]|0}if(d>>>0>b>>>0){b=je(c+b|0,44,d-b|0)|0;c=(b|0)==0?-1:b-c|0}else c=-1;return c|0}function Je(){var a=0,b=0,c=0,d=0,e=0,f=0,g=0,h=0;e=r;r=r+48|0;g=e+32|0;c=e+24|0;h=e+16|0;f=e;e=e+36|0;a=Ke()|0;if(a|0?(d=k[a>>2]|0,d|0):0){a=d+48|0;b=k[a>>2]|0;a=k[a+4>>2]|0;if(!((b&-256|0)==1126902528&(a|0)==1129074247)){k[c>>2]=1096989;Ne(1097084,c)}if((b|0)==1126902529&(a|0)==1129074247)a=k[d+44>>2]|0;else a=d+80|0;k[e>>2]=a;d=k[d>>2]|0;a=k[d+4>>2]|0;if(Te(8,d,e)|0){h=k[e>>2]|0;h=Xa[k[(k[h>>2]|0)+8>>2]&3](h)|0;k[f>>2]=1096989;k[f+4>>2]=a;k[f+8>>2]=h;Ne(1096998,f)}else{k[h>>2]=1096989;k[h+4>>2]=a;Ne(1097043,h)}}Ne(1097122,g)}function Ke(){var a=0,b=0;a=r;r=r+16|0;if(!(Ia(1097808,2)|0)){b=Ga(k[274453]|0)|0;r=a;return b|0}else Ne(1096810,a);return 0}function Le(){var a=0;a=r;r=r+16|0;if(!(Ja(1097812,9)|0)){r=a;return}else Ne(1096760,a)}function Me(a){a=a|0;var b=0;b=r;r=r+16|0;we(a);if(!(La(k[274453]|0,0)|0)){r=b;return}else Ne(1096707,b)}function Ne(a,b){a=a|0;b=b|0;var c=0;c=r;r=r+16|0;k[c>>2]=b;de(941016,a,c)|0;re();Na()}function Oe(a){a=a|0;return}function Pe(a){a=a|0;Qe(a);return}function Qe(a){a=a|0;we(a);return}function Re(a){a=a|0;return}function Se(a){a=a|0;return}function Te(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;g=r;r=r+64|0;f=g;if((a|0)!=(b|0))if((b|0)!=0?(e=Ue(b,16)|0,(e|0)!=0):0){b=f;d=b+56|0;do{k[b>>2]=0;b=b+4|0}while((b|0)<(d|0));k[f>>2]=e;k[f+8>>2]=a;k[f+12>>2]=-1;k[f+48>>2]=1;_a[k[(k[e>>2]|0)+28>>2]&3](e,f,k[c>>2]|0,1);if((k[f+24>>2]|0)==1){k[c>>2]=k[f+16>>2];b=1}else b=0}else b=0;else b=1;r=g;return b|0}function Ue(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0,g=0,h=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0;s=r;r=r+64|0;q=s;p=k[a>>2]|0;o=a+(k[p+-8>>2]|0)|0;p=k[p+-4>>2]|0;k[q>>2]=b;k[q+4>>2]=a;k[q+8>>2]=48;h=q+12|0;l=q+16|0;a=q+20|0;c=q+24|0;d=q+28|0;e=q+32|0;f=q+40|0;g=(p|0)==(b|0);m=h;n=m+40|0;do{k[m>>2]=0;m=m+4|0}while((m|0)<(n|0));j[h+40>>1]=0;i[h+42>>0]=0;a:do if(g){k[q+48>>2]=1;Za[k[(k[b>>2]|0)+20>>2]&3](b,q,o,o,1,0);a=(k[c>>2]|0)==1?o:0}else{Va[k[(k[p>>2]|0)+24>>2]&3](p,q,o,1,0);switch(k[q+36>>2]|0){case 0:{a=(k[f>>2]|0)==1&(k[d>>2]|0)==1&(k[e>>2]|0)==1?k[a>>2]|0:0;break a}case 1:break;default:{a=0;break a}}if((k[c>>2]|0)!=1?!((k[f>>2]|0)==0&(k[d>>2]|0)==1&(k[e>>2]|0)==1):0){a=0;break}a=k[l>>2]|0}while(0);r=s;return a|0}function Ve(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;if((a|0)==(k[b+8>>2]|0))We(b,c,d,e);else{a=k[a+8>>2]|0;Za[k[(k[a>>2]|0)+20>>2]&3](a,b,c,d,e,f)}return}function We(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;i[a+53>>0]=1;do if((k[a+4>>2]|0)==(c|0)){i[a+52>>0]=1;c=a+16|0;e=k[c>>2]|0;if(!e){k[c>>2]=b;k[a+24>>2]=d;k[a+36>>2]=1;if(!((d|0)==1?(k[a+48>>2]|0)==1:0))break;i[a+54>>0]=1;break}if((e|0)!=(b|0)){d=a+36|0;k[d>>2]=(k[d>>2]|0)+1;i[a+54>>0]=1;break}e=a+24|0;c=k[e>>2]|0;if((c|0)==2){k[e>>2]=d;c=d}if((c|0)==1?(k[a+48>>2]|0)==1:0)i[a+54>>0]=1}while(0);return}function Xe(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;do if((a|0)==(k[b+8>>2]|0)){if((k[b+4>>2]|0)==(c|0)?(f=b+28|0,(k[f>>2]|0)!=1):0)k[f>>2]=d}else{if((a|0)!=(k[b>>2]|0)){h=k[a+8>>2]|0;Va[k[(k[h>>2]|0)+24>>2]&3](h,b,c,d,e);break}if((k[b+16>>2]|0)!=(c|0)?(h=b+20|0,(k[h>>2]|0)!=(c|0)):0){k[b+32>>2]=d;g=b+44|0;if((k[g>>2]|0)==4)break;f=b+52|0;i[f>>0]=0;d=b+53|0;i[d>>0]=0;a=k[a+8>>2]|0;Za[k[(k[a>>2]|0)+20>>2]&3](a,b,c,c,1,e);if(i[d>>0]|0)if(!(i[f>>0]|0)){f=1;d=13}else d=17;else{f=0;d=13}do if((d|0)==13){k[h>>2]=c;c=b+40|0;k[c>>2]=(k[c>>2]|0)+1;if((k[b+36>>2]|0)==1?(k[b+24>>2]|0)==2:0){i[b+54>>0]=1;if(f){d=17;break}else{f=4;break}}if(f)d=17;else f=4}while(0);if((d|0)==17)f=3;k[g>>2]=f;break}if((d|0)==1)k[b+32>>2]=1}while(0);return}function Ye(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;if((a|0)==(k[b+8>>2]|0))Ze(b,c,d);else{a=k[a+8>>2]|0;_a[k[(k[a>>2]|0)+28>>2]&3](a,b,c,d)}return}function Ze(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=a+16|0;e=k[d>>2]|0;do if(e){if((e|0)!=(b|0)){c=a+36|0;k[c>>2]=(k[c>>2]|0)+1;k[a+24>>2]=2;i[a+54>>0]=1;break}d=a+24|0;if((k[d>>2]|0)==2)k[d>>2]=c}else{k[d>>2]=b;k[a+24>>2]=c;k[a+36>>2]=1}while(0);return}function _e(a){a=a|0;Qe(a);return}function $e(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;if((a|0)==(k[b+8>>2]|0))We(b,c,d,e);return}function af(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;do if((a|0)==(k[b+8>>2]|0)){if((k[b+4>>2]|0)==(c|0)?(g=b+28|0,(k[g>>2]|0)!=1):0)k[g>>2]=d}else if((a|0)==(k[b>>2]|0)){if((k[b+16>>2]|0)!=(c|0)?(f=b+20|0,(k[f>>2]|0)!=(c|0)):0){k[b+32>>2]=d;k[f>>2]=c;e=b+40|0;k[e>>2]=(k[e>>2]|0)+1;if((k[b+36>>2]|0)==1?(k[b+24>>2]|0)==2:0)i[b+54>>0]=1;k[b+44>>2]=4;break}if((d|0)==1)k[b+32>>2]=1}while(0);return}function bf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;if((a|0)==(k[b+8>>2]|0))Ze(b,c,d);return}function cf(){var a=0,b=0,c=0,d=0;c=r;r=r+16|0;d=c+8|0;a=Ke()|0;if((a|0?(b=k[a>>2]|0,b|0):0)?(a=b+48|0,(k[a>>2]&-256|0)==1126902528?(k[a+4>>2]|0)==1129074247:0):0){Ya[k[b+12>>2]&3]();Ne(1097134,c)}c=k[235310]|0;k[235310]=c+0;Ya[c&3]();Ne(1097134,d)}function df(a){a=a|0;return}function ef(a){a=a|0;Qe(a);return}function ff(a){a=a|0;return 1097187}function gf(a){a=a|0;var b=0,c=0;b=(a|0)==0?1:a;while(1){c=ve(b)|0;if(c|0){a=6;break}a=hf()|0;if(!a){a=5;break}Ya[a&3]()}if((a|0)==5){c=xa(4)|0;k[c>>2]=941332;Ma(c|0,72,6)}else if((a|0)==6)return c|0;return 0}function hf(){var a=0;a=k[274454]|0;k[274454]=a+0;return a|0}function jf(a){a=a|0;return gf(a)|0}function kf(a){a=a|0;Qe(a);return}function lf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;e=r;r=r+16|0;d=e;k[d>>2]=k[c>>2];a=Ua[k[(k[a>>2]|0)+16>>2]&7](a,b,d)|0;if(a)k[c>>2]=k[d>>2];r=e;return a&1|0}function mf(a){a=a|0;if(!a)a=0;else a=(Ue(a,104)|0)!=0;return a&1|0}function nf(){}function of(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;c=a+c>>>0;return (L=b+d+(c>>>0>>0|0)>>>0,c|0)|0}function pf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;d=b-d-(c>>>0>a>>>0|0)>>>0;return (L=d,a-c>>>0|0)|0}function qf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=a+c|0;if((c|0)>=20){b=b&255;f=a&3;g=b|b<<8|b<<16|b<<24;e=d&~3;if(f){f=a+4-f|0;while((a|0)<(f|0)){i[a>>0]=b;a=a+1|0}}while((a|0)<(e|0)){k[a>>2]=g;a=a+4|0}}while((a|0)<(d|0)){i[a>>0]=b;a=a+1|0}return a-c|0}function rf(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){L=b>>>c;return a>>>c|(b&(1<>>c-32|0}function sf(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){L=b<>>32-c;return a<=4096)return Ca(a|0,b|0,c|0)|0;d=a|0;if((a&3)==(b&3)){while(a&3){if(!c)return d|0;i[a>>0]=i[b>>0]|0;a=a+1|0;b=b+1|0;c=c-1|0}while((c|0)>=4){k[a>>2]=k[b>>2];a=a+4|0;b=b+4|0;c=c-4|0}}while((c|0)>0){i[a>>0]=i[b>>0]|0;a=a+1|0;b=b+1|0;c=c-1|0}return d|0}function uf(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;if((b|0)<(a|0)&(a|0)<(b+c|0)){d=a;b=b+c|0;a=a+c|0;while((c|0)>0){a=a-1|0;b=b-1|0;c=c-1|0;i[a>>0]=i[b>>0]|0}a=d}else tf(a,b,c)|0;return a|0}function vf(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){L=b>>c;return a>>>c|(b&(1<>c-32|0}function wf(a){a=a|0;var b=0;b=i[v+(a&255)>>0]|0;if((b|0)<8)return b|0;b=i[v+(a>>8&255)>>0]|0;if((b|0)<8)return b+8|0;b=i[v+(a>>16&255)>>0]|0;if((b|0)<8)return b+16|0;return (i[v+(a>>>24)>>0]|0)+24|0}function xf(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;f=a&65535;e=b&65535;c=ha(e,f)|0;d=a>>>16;a=(c>>>16)+(ha(e,d)|0)|0;e=b>>>16;b=ha(e,f)|0;return (L=(a>>>16)+(ha(e,d)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|c&65535|0)|0}function yf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=b>>31|((b|0)<0?-1:0)<<1;i=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;f=d>>31|((d|0)<0?-1:0)<<1;e=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;h=pf(j^a|0,i^b|0,j|0,i|0)|0;g=L;a=f^j;b=e^i;return pf((Df(h,g,pf(f^c|0,e^d|0,f|0,e|0)|0,L,0)|0)^a|0,L^b|0,a|0,b|0)|0}function zf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;e=r;r=r+16|0;h=e|0;g=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;j=d>>31|((d|0)<0?-1:0)<<1;i=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;a=pf(g^a|0,f^b|0,g|0,f|0)|0;b=L;Df(a,b,pf(j^c|0,i^d|0,j|0,i|0)|0,L,h)|0;d=pf(k[h>>2]^g|0,k[h+4>>2]^f|0,g|0,f|0)|0;c=L;r=e;return (L=c,d)|0}function Af(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;f=c;c=xf(e,f)|0;a=L;return (L=(ha(b,f)|0)+(ha(d,e)|0)+a|a&0,c|0|0)|0}function Bf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Df(a,b,c,d,0)|0}function Cf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;f=r;r=r+16|0;e=f|0;Df(a,b,c,d,e)|0;r=f;return (L=k[e+4>>2]|0,k[e>>2]|0)|0}function Df(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,l=0,m=0,n=0,o=0,p=0;l=a;i=b;j=i;g=c;n=d;h=n;if(!j){f=(e|0)!=0;if(!h){if(f){k[e>>2]=(l>>>0)%(g>>>0);k[e+4>>2]=0}n=0;e=(l>>>0)/(g>>>0)>>>0;return (L=n,e)|0}else{if(!f){n=0;e=0;return (L=n,e)|0}k[e>>2]=a|0;k[e+4>>2]=b&0;n=0;e=0;return (L=n,e)|0}}f=(h|0)==0;do if(g){if(!f){f=(ja(h|0)|0)-(ja(j|0)|0)|0;if(f>>>0<=31){m=f+1|0;h=31-f|0;b=f-31>>31;g=m;a=l>>>(m>>>0)&b|j<>>(m>>>0)&b;f=0;h=l<>2]=a|0;k[e+4>>2]=i|b&0;n=0;e=0;return (L=n,e)|0}f=g-1|0;if(f&g|0){h=(ja(g|0)|0)+33-(ja(j|0)|0)|0;p=64-h|0;m=32-h|0;i=m>>31;o=h-32|0;b=o>>31;g=h;a=m-1>>31&j>>>(o>>>0)|(j<>>(h>>>0))&b;b=b&j>>>(h>>>0);f=l<>>(o>>>0))&i|l<>31;break}if(e|0){k[e>>2]=f&l;k[e+4>>2]=0}if((g|0)==1){o=i|b&0;p=a|0|0;return (L=o,p)|0}else{p=wf(g|0)|0;o=j>>>(p>>>0)|0;p=j<<32-p|l>>>(p>>>0)|0;return (L=o,p)|0}}else{if(f){if(e|0){k[e>>2]=(j>>>0)%(g>>>0);k[e+4>>2]=0}o=0;p=(j>>>0)/(g>>>0)>>>0;return (L=o,p)|0}if(!l){if(e|0){k[e>>2]=0;k[e+4>>2]=(j>>>0)%(h>>>0)}o=0;p=(j>>>0)/(h>>>0)>>>0;return (L=o,p)|0}f=h-1|0;if(!(f&h)){if(e|0){k[e>>2]=a|0;k[e+4>>2]=f&j|b&0}o=0;p=j>>>((wf(h|0)|0)>>>0);return (L=o,p)|0}f=(ja(h|0)|0)-(ja(j|0)|0)|0;if(f>>>0<=30){b=f+1|0;h=31-f|0;g=b;a=j<>>(b>>>0);b=j>>>(b>>>0);f=0;h=l<>2]=a|0;k[e+4>>2]=i|b&0;o=0;p=0;return (L=o,p)|0}while(0);if(!g){j=h;i=0;h=0}else{m=c|0|0;l=n|d&0;j=of(m|0,l|0,-1,-1)|0;c=L;i=h;h=0;do{d=i;i=f>>>31|i<<1;f=h|f<<1;d=a<<1|d>>>31|0;n=a>>>31|b<<1|0;pf(j|0,c|0,d|0,n|0)|0;p=L;o=p>>31|((p|0)<0?-1:0)<<1;h=o&1;a=pf(d|0,n|0,o&m|0,(((p|0)<0?-1:0)>>31|((p|0)<0?-1:0)<<1)&l|0)|0;b=L;g=g-1|0}while((g|0)!=0);j=i;i=0}g=0;if(e|0){k[e>>2]=a;k[e+4>>2]=b}o=(f|0)>>>31|(j|g)<<1|(g<<1|f>>>31)&0|i;p=(f<<1|0>>>31)&-2|h;return (L=o,p)|0}function Ef(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Ua[a&7](b|0,c|0,d|0)|0}function Ff(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;Va[a&3](b|0,c|0,d|0,e|0,f|0)}function Gf(a,b){a=a|0;b=b|0;Wa[a&15](b|0)}function Hf(a,b){a=a|0;b=b|0;return Xa[a&3](b|0)|0}function If(a){a=a|0;Ya[a&3]()}function Jf(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;Za[a&3](b|0,c|0,d|0,e|0,f|0,g|0)}function Kf(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;_a[a&3](b|0,c|0,d|0,e|0)}function Lf(a,b,c){a=a|0;b=b|0;c=c|0;ka(0);return 0}function Mf(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;ka(1)}function Nf(a){a=a|0;ka(2)}function Of(a){a=a|0;ka(3);return 0}function Pf(){ka(4)}function Qf(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;ka(5)}function Rf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ka(6)} + +// EMSCRIPTEN_END_FUNCS +var Ua=[Lf,Rd,Td,ce,Te,Lf,Lf,Lf];var Va=[Mf,af,Xe,Mf];var Wa=[Nf,Oe,_e,Re,Se,Pe,df,ef,Sd,Me,Nf,Nf,Nf,Nf,Nf,Nf];var Xa=[Of,Od,ff,Of];var Ya=[Pf,Je,Le,Pf];var Za=[Qf,$e,Ve,Qf];var _a=[Rf,bf,Ye,Rf];return{_emscripten_bind_LanguageInfo_getLanguageCode_0:Jd,_bitshift64Lshr:rf,_bitshift64Shl:sf,_malloc:ve,___cxa_is_pointer_type:mf,_emscripten_bind_LanguageGuess_getPercent_0:Ad,_emscripten_bind_VoidPtr___destroy___0:Nd,_memset:qf,_memcpy:tf,_emscripten_bind_LanguageInfo_getIsReliable_0:Id,_i64Subtract:pf,_emscripten_bind_LanguageInfo___destroy___0:Bd,_i64Add:of,_emscripten_bind_LanguageInfo_get_languages_1:Kd,_emscripten_bind_Language_getLanguageCode_0:Md,_emscripten_bind_LanguageGuess___destroy___0:yd,_emscripten_bind_Language___destroy___0:Ld,___cxa_can_catch:lf,_free:we,_emscripten_bind_LanguageInfo_detectLanguage_5:Gd,_memmove:uf,_emscripten_bind_LanguageInfo_detectLanguage_2:Dd,_emscripten_bind_LanguageGuess_getLanguageCode_0:zd,runPostSets:nf,_emscripten_replace_memory:Ta,stackAlloc:$a,stackSave:ab,stackRestore:bb,establishStackSpace:cb,setThrew:db,setTempRet0:gb,getTempRet0:hb,dynCall_iiii:Ef,dynCall_viiiii:Ff,dynCall_vi:Gf,dynCall_ii:Hf,dynCall_v:If,dynCall_viiiiii:Jf,dynCall_viiii:Kf}}) + + +// EMSCRIPTEN_END_ASM +(c.L,c.M,buffer),zb=c._emscripten_bind_LanguageInfo_getLanguageCode_0=M._emscripten_bind_LanguageInfo_getLanguageCode_0,pb=c._bitshift64Lshr=M._bitshift64Lshr,qb=c._bitshift64Shl=M._bitshift64Shl,Ab=c._emscripten_bind_LanguageGuess_getLanguageCode_0=M._emscripten_bind_LanguageGuess_getLanguageCode_0;c.___cxa_is_pointer_type=M.___cxa_is_pointer_type; +var Bb=c._emscripten_bind_LanguageGuess_getPercent_0=M._emscripten_bind_LanguageGuess_getPercent_0,Cb=c._emscripten_bind_VoidPtr___destroy___0=M._emscripten_bind_VoidPtr___destroy___0,nb=c._memset=M._memset,sb=c._memcpy=M._memcpy,Db=c._emscripten_bind_LanguageInfo_getIsReliable_0=M._emscripten_bind_LanguageInfo_getIsReliable_0,gb=c._i64Subtract=M._i64Subtract,Eb=c._emscripten_bind_LanguageInfo___destroy___0=M._emscripten_bind_LanguageInfo___destroy___0,fb=c._i64Add=M._i64Add,Fb=c._emscripten_bind_LanguageInfo_get_languages_1= +M._emscripten_bind_LanguageInfo_get_languages_1,Gb=c._emscripten_bind_Language_getLanguageCode_0=M._emscripten_bind_Language_getLanguageCode_0,Hb=c._emscripten_bind_LanguageGuess___destroy___0=M._emscripten_bind_LanguageGuess___destroy___0,Ib=c._emscripten_bind_Language___destroy___0=M._emscripten_bind_Language___destroy___0;c.___cxa_can_catch=M.___cxa_can_catch;var Ga=c._free=M._free;c.runPostSets=M.runPostSets; +var Jb=c._emscripten_bind_LanguageInfo_detectLanguage_5=M._emscripten_bind_LanguageInfo_detectLanguage_5,wb=c._memmove=M._memmove,Kb=c._emscripten_bind_LanguageInfo_detectLanguage_2=M._emscripten_bind_LanguageInfo_detectLanguage_2,D=c._malloc=M._malloc,Oa=c._emscripten_replace_memory=M._emscripten_replace_memory;c.dynCall_iiii=M.dynCall_iiii;c.dynCall_viiiii=M.dynCall_viiiii;c.dynCall_vi=M.dynCall_vi;c.dynCall_ii=M.dynCall_ii;c.dynCall_v=M.dynCall_v;c.dynCall_viiiiii=M.dynCall_viiiiii; +c.dynCall_viiii=M.dynCall_viiii;t.n=M.stackAlloc;t.w=M.stackSave;t.o=M.stackRestore;t.ba=M.establishStackSpace;t.V=M.setTempRet0;t.R=M.getTempRet0; +if(K)if("function"===typeof c.locateFile?K=c.locateFile(K):c.memoryInitializerPrefixURL&&(K=c.memoryInitializerPrefixURL+K),m||ca){var Lb=c.readBinary(K);E.set(Lb,t.C)}else{var Nb=function(){c.readAsync(K,Mb,function(){throw"could not load memory initializer "+K;})};bb();var Mb=function(a){a.byteLength&&(a=new Uint8Array(a));E.set(a,t.C);c.memoryInitializerRequest&&delete c.memoryInitializerRequest.response;cb()};if(c.memoryInitializerRequest){var Ob=function(){var a=c.memoryInitializerRequest;200!== +a.status&&0!==a.status?(console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+a.status+", retrying "+K),Nb()):Mb(a.response)};c.memoryInitializerRequest.response?setTimeout(Ob,0):c.memoryInitializerRequest.addEventListener("load",Ob)}else Nb()}function n(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}n.prototype=Error();n.prototype.constructor=n;var Pb=null,ab=function Qb(){c.calledRun||Rb();c.calledRun||(ab=Qb)}; +c.callMain=c.Z=function(a){function b(){for(var a=0;3>a;a++)e.push(0)}a=a||[];za||(za=!0,H(Ta));var d=a.length+1,e=[xa(Za(c.thisProgram),"i8",0)];b();for(var f=0;f=this.size?(assert(0>=1; +break;case 4:e>>=2;break;case 8:e>>=3}for(d=0;d item[2] == test_string); + + // Set shorter timeouts and lower string lengths to make things easier + // on the test infrastructure. + detectorModule.LARGE_STRING = test_string.length - 1; + detectorModule.IDLE_TIMEOUT = 1000; + + equal(detectorModule.workerManager._idleTimeout, null, + "Should have no idle timeout to start with"); + + let result = await LanguageDetector.detectLanguage(test_string); + + // Make sure the results are still correct. + check_result(result, test_item[0], test_item[3]); + + // We should have an idle timeout after processing the string. + ok(detectorModule.workerManager._idleTimeout != null, + "Should have an idle timeout"); + ok(detectorModule.workerManager._worker != null, + "Should have a worker instance"); + ok(detectorModule.workerManager._workerReadyPromise != null, + "Should have a worker promise"); + + // Wait for the idle timeout to elapse. + await new Promise(resolve => setTimeout(resolve, detectorModule.IDLE_TIMEOUT)); + + equal(detectorModule.workerManager._idleTimeout, null, + "Should have no idle timeout after it has elapsed"); + equal(detectorModule.workerManager._worker, null, + "Should have no worker instance after idle timeout"); + equal(detectorModule.workerManager._workerReadyPromise, null, + "Should have no worker promise after idle timeout"); + + // We should still be able to use the language detector after its + // worker has been flushed. + result = await LanguageDetector.detectLanguage(test_string); + + // Make sure the results are still correct. + check_result(result, test_item[0], test_item[3]); +}); diff -pruN 1:60.2.1-1/browser/extensions/activity-stream/data/content/activity-stream.bundle.js 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/data/content/activity-stream.bundle.js --- 1:60.2.1-1/browser/extensions/activity-stream/data/content/activity-stream.bundle.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/data/content/activity-stream.bundle.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,4803 @@ +/******/ (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, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // 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 = 14); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export MAIN_MESSAGE_TYPE */ +/* unused harmony export CONTENT_MESSAGE_TYPE */ +/* unused harmony export PRELOAD_MESSAGE_TYPE */ +/* unused harmony export UI_CODE */ +/* unused harmony export BACKGROUND_PROCESS */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return actionCreators; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return actionUtils; }); +/* 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/. */ + + +var MAIN_MESSAGE_TYPE = "ActivityStream:Main"; +var CONTENT_MESSAGE_TYPE = "ActivityStream:Content"; +var PRELOAD_MESSAGE_TYPE = "ActivityStream:PreloadedBrowser"; +var UI_CODE = 1; +var BACKGROUND_PROCESS = 2; + +/** + * globalImportContext - Are we in UI code (i.e. react, a dom) or some kind of background process? + * Use this in action creators if you need different logic + * for ui/background processes. + */ + +const globalImportContext = typeof Window === "undefined" ? BACKGROUND_PROCESS : UI_CODE; +/* unused harmony export globalImportContext */ + +// Export for tests + +// Create an object that avoids accidental differing key/value pairs: +// { +// INIT: "INIT", +// UNINIT: "UNINIT" +// } +const actionTypes = {}; +/* harmony export (immutable) */ __webpack_exports__["b"] = actionTypes; + + +for (const type of ["ARCHIVE_FROM_POCKET", "BLOCK_URL", "BOOKMARK_URL", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DELETE_HISTORY_URL_CONFIRM", "DIALOG_CANCEL", "DIALOG_OPEN", "DISABLE_ONBOARDING", "INIT", "MIGRATION_CANCEL", "MIGRATION_COMPLETED", "MIGRATION_START", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "PAGE_PRERENDERED", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_CHANGED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINKS_DELETED", "PLACES_LINK_BLOCKED", "PLACES_SAVED_TO_POCKET", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "RICH_ICON_MISSING", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_MOVE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SETTINGS_CLOSE", "SETTINGS_OPEN", "SET_PREF", "SHOW_FIREFOX_ACCOUNTS", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_PERFORMANCE_EVENT", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_EDIT", "TOP_SITES_INSERT", "TOP_SITES_PIN", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "TOTAL_BOOKMARKS_REQUEST", "TOTAL_BOOKMARKS_RESPONSE", "UNINIT", "WEBEXT_CLICK", "WEBEXT_DISMISS"]) { + actionTypes[type] = type; +} + +// Helper function for creating routed actions between content and main +// Not intended to be used by consumers +function _RouteMessage(action, options) { + const meta = action.meta ? Object.assign({}, action.meta) : {}; + if (!options || !options.from || !options.to) { + throw new Error("Routed Messages must have options as the second parameter, and must at least include a .from and .to property."); + } + // For each of these fields, if they are passed as an option, + // add them to the action. If they are not defined, remove them. + ["from", "to", "toTarget", "fromTarget", "skipMain", "skipLocal"].forEach(o => { + if (typeof options[o] !== "undefined") { + meta[o] = options[o]; + } else if (meta[o]) { + delete meta[o]; + } + }); + return Object.assign({}, action, { meta }); +} + +/** + * AlsoToMain - Creates a message that will be dispatched locally and also sent to the Main process. + * + * @param {object} action Any redux action (required) + * @param {object} options + * @param {bool} skipLocal Used by OnlyToMain to skip the main reducer + * @param {string} fromTarget The id of the content port from which the action originated. (optional) + * @return {object} An action with added .meta properties + */ +function AlsoToMain(action, fromTarget, skipLocal) { + return _RouteMessage(action, { + from: CONTENT_MESSAGE_TYPE, + to: MAIN_MESSAGE_TYPE, + fromTarget, + skipLocal + }); +} + +/** + * OnlyToMain - Creates a message that will be sent to the Main process and skip the local reducer. + * + * @param {object} action Any redux action (required) + * @param {object} options + * @param {string} fromTarget The id of the content port from which the action originated. (optional) + * @return {object} An action with added .meta properties + */ +function OnlyToMain(action, fromTarget) { + return AlsoToMain(action, fromTarget, true); +} + +/** + * BroadcastToContent - Creates a message that will be dispatched to main and sent to ALL content processes. + * + * @param {object} action Any redux action (required) + * @return {object} An action with added .meta properties + */ +function BroadcastToContent(action) { + return _RouteMessage(action, { + from: MAIN_MESSAGE_TYPE, + to: CONTENT_MESSAGE_TYPE + }); +} + +/** + * AlsoToOneContent - Creates a message that will be will be dispatched to the main store + * and also sent to a particular Content process. + * + * @param {object} action Any redux action (required) + * @param {string} target The id of a content port + * @param {bool} skipMain Used by OnlyToOneContent to skip the main process + * @return {object} An action with added .meta properties + */ +function AlsoToOneContent(action, target, skipMain) { + if (!target) { + throw new Error("You must provide a target ID as the second parameter of AlsoToOneContent. If you want to send to all content processes, use BroadcastToContent"); + } + return _RouteMessage(action, { + from: MAIN_MESSAGE_TYPE, + to: CONTENT_MESSAGE_TYPE, + toTarget: target, + skipMain + }); +} + +/** + * OnlyToOneContent - Creates a message that will be sent to a particular Content process + * and skip the main reducer. + * + * @param {object} action Any redux action (required) + * @param {string} target The id of a content port + * @return {object} An action with added .meta properties + */ +function OnlyToOneContent(action, target) { + return AlsoToOneContent(action, target, true); +} + +/** + * AlsoToPreloaded - Creates a message that dispatched to the main reducer and also sent to the preloaded tab. + * + * @param {object} action Any redux action (required) + * @return {object} An action with added .meta properties + */ +function AlsoToPreloaded(action) { + return _RouteMessage(action, { + from: MAIN_MESSAGE_TYPE, + to: PRELOAD_MESSAGE_TYPE + }); +} + +/** + * UserEvent - A telemetry ping indicating a user action. This should only + * be sent from the UI during a user session. + * + * @param {object} data Fields to include in the ping (source, etc.) + * @return {object} An AlsoToMain action + */ +function UserEvent(data) { + return AlsoToMain({ + type: actionTypes.TELEMETRY_USER_EVENT, + data + }); +} + +/** + * UndesiredEvent - A telemetry ping indicating an undesired state. + * + * @param {object} data Fields to include in the ping (value, etc.) + * @param {int} importContext (For testing) Override the import context for testing. + * @return {object} An action. For UI code, a AlsoToMain action. + */ +function UndesiredEvent(data, importContext = globalImportContext) { + const action = { + type: actionTypes.TELEMETRY_UNDESIRED_EVENT, + data + }; + return importContext === UI_CODE ? AlsoToMain(action) : action; +} + +/** + * PerfEvent - A telemetry ping indicating a performance-related event. + * + * @param {object} data Fields to include in the ping (value, etc.) + * @param {int} importContext (For testing) Override the import context for testing. + * @return {object} An action. For UI code, a AlsoToMain action. + */ +function PerfEvent(data, importContext = globalImportContext) { + const action = { + type: actionTypes.TELEMETRY_PERFORMANCE_EVENT, + data + }; + return importContext === UI_CODE ? AlsoToMain(action) : action; +} + +/** + * ImpressionStats - A telemetry ping indicating an impression stats. + * + * @param {object} data Fields to include in the ping + * @param {int} importContext (For testing) Override the import context for testing. + * #return {object} An action. For UI code, a AlsoToMain action. + */ +function ImpressionStats(data, importContext = globalImportContext) { + const action = { + type: actionTypes.TELEMETRY_IMPRESSION_STATS, + data + }; + return importContext === UI_CODE ? AlsoToMain(action) : action; +} + +function SetPref(name, value, importContext = globalImportContext) { + const action = { type: actionTypes.SET_PREF, data: { name, value } }; + return importContext === UI_CODE ? AlsoToMain(action) : action; +} + +function WebExtEvent(type, data, importContext = globalImportContext) { + if (!data || !data.source) { + throw new Error("WebExtEvent actions should include a property \"source\", the id of the webextension that should receive the event."); + } + const action = { type, data }; + return importContext === UI_CODE ? AlsoToMain(action) : action; +} + +var actionCreators = { + BroadcastToContent, + UserEvent, + UndesiredEvent, + PerfEvent, + ImpressionStats, + AlsoToOneContent, + OnlyToOneContent, + AlsoToMain, + OnlyToMain, + AlsoToPreloaded, + SetPref, + WebExtEvent +}; + +// These are helpers to test for certain kinds of actions + +var actionUtils = { + isSendToMain(action) { + if (!action.meta) { + return false; + } + return action.meta.to === MAIN_MESSAGE_TYPE && action.meta.from === CONTENT_MESSAGE_TYPE; + }, + isBroadcastToContent(action) { + if (!action.meta) { + return false; + } + if (action.meta.to === CONTENT_MESSAGE_TYPE && !action.meta.toTarget) { + return true; + } + return false; + }, + isSendToOneContent(action) { + if (!action.meta) { + return false; + } + if (action.meta.to === CONTENT_MESSAGE_TYPE && action.meta.toTarget) { + return true; + } + return false; + }, + isSendToPreloaded(action) { + if (!action.meta) { + return false; + } + return action.meta.to === PRELOAD_MESSAGE_TYPE && action.meta.from === MAIN_MESSAGE_TYPE; + }, + isFromMain(action) { + if (!action.meta) { + return false; + } + return action.meta.from === MAIN_MESSAGE_TYPE && action.meta.to === CONTENT_MESSAGE_TYPE; + }, + getPortIdOfSender(action) { + return action.meta && action.meta.fromTarget || null; + }, + _RouteMessage +}; + +/***/ }), +/* 1 */ +/***/ (function(module, exports) { + +module.exports = React; + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + +module.exports = ReactIntl; + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); +} catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + +module.exports = ReactRedux; + +/***/ }), +/* 5 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +const TOP_SITES_SOURCE = "TOP_SITES"; +/* harmony export (immutable) */ __webpack_exports__["d"] = TOP_SITES_SOURCE; + +const TOP_SITES_CONTEXT_MENU_OPTIONS = ["CheckPinTopSite", "EditTopSite", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl", "DeleteUrl"]; +/* harmony export (immutable) */ __webpack_exports__["c"] = TOP_SITES_CONTEXT_MENU_OPTIONS; + +// minimum size necessary to show a rich icon instead of a screenshot +const MIN_RICH_FAVICON_SIZE = 96; +/* harmony export (immutable) */ __webpack_exports__["b"] = MIN_RICH_FAVICON_SIZE; + +// minimum size necessary to show any icon in the top left corner with a screenshot +const MIN_CORNER_FAVICON_SIZE = 16; +/* harmony export (immutable) */ __webpack_exports__["a"] = MIN_CORNER_FAVICON_SIZE; + + +/***/ }), +/* 6 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./system-addon/common/Actions.jsm +var Actions = __webpack_require__(0); + +// CONCATENATED MODULE: ./system-addon/common/Dedupe.jsm +class Dedupe { + constructor(createKey) { + this.createKey = createKey || this.defaultCreateKey; + } + + defaultCreateKey(item) { + return item; + } + + /** + * Dedupe any number of grouped elements favoring those from earlier groups. + * + * @param {Array} groups Contains an arbitrary number of arrays of elements. + * @returns {Array} A matching array of each provided group deduped. + */ + group(...groups) { + const globalKeys = new Set(); + const result = []; + for (const values of groups) { + const valueMap = new Map(); + for (const value of values) { + const key = this.createKey(value); + if (!globalKeys.has(key) && !valueMap.has(key)) { + valueMap.set(key, value); + } + } + result.push(valueMap); + valueMap.forEach((value, key) => globalKeys.add(key)); + } + return result.map(m => Array.from(m.values())); + } +} +// CONCATENATED MODULE: ./system-addon/common/Reducers.jsm +/* unused harmony export insertPinned */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return reducers; }); +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + + + +const TOP_SITES_DEFAULT_ROWS = 1; +/* unused harmony export TOP_SITES_DEFAULT_ROWS */ + +const TOP_SITES_MAX_SITES_PER_ROW = 8; +/* harmony export (immutable) */ __webpack_exports__["a"] = TOP_SITES_MAX_SITES_PER_ROW; + + + +const dedupe = new Dedupe(site => site && site.url); + +const INITIAL_STATE = { + App: { + // Have we received real data from the app yet? + initialized: false, + // The version of the system-addon + version: null + }, + Snippets: { initialized: false }, + TopSites: { + // Have we received real data from history yet? + initialized: false, + // The history (and possibly default) links + rows: [], + // Used in content only to dispatch action to TopSiteForm. + editForm: null + }, + Prefs: { + initialized: false, + values: {} + }, + Dialog: { + visible: false, + data: {} + }, + Sections: [], + PreferencesPane: { visible: false } +}; +/* unused harmony export INITIAL_STATE */ + + + +function App(prevState = INITIAL_STATE.App, action) { + switch (action.type) { + case Actions["b" /* actionTypes */].INIT: + return Object.assign({}, prevState, action.data || {}, { initialized: true }); + default: + return prevState; + } +} + +/** + * insertPinned - Inserts pinned links in their specified slots + * + * @param {array} a list of links + * @param {array} a list of pinned links + * @return {array} resulting list of links with pinned links inserted + */ +function insertPinned(links, pinned) { + // Remove any pinned links + const pinnedUrls = pinned.map(link => link && link.url); + let newLinks = links.filter(link => link ? !pinnedUrls.includes(link.url) : false); + newLinks = newLinks.map(link => { + if (link && link.isPinned) { + delete link.isPinned; + delete link.pinIndex; + } + return link; + }); + + // Then insert them in their specified location + pinned.forEach((val, index) => { + if (!val) { + return; + } + let link = Object.assign({}, val, { isPinned: true, pinIndex: index }); + if (index > newLinks.length) { + newLinks[index] = link; + } else { + newLinks.splice(index, 0, link); + } + }); + + return newLinks; +} + + +function TopSites(prevState = INITIAL_STATE.TopSites, action) { + let hasMatch; + let newRows; + switch (action.type) { + case Actions["b" /* actionTypes */].TOP_SITES_UPDATED: + if (!action.data) { + return prevState; + } + return Object.assign({}, prevState, { initialized: true, rows: action.data }); + case Actions["b" /* actionTypes */].TOP_SITES_EDIT: + return Object.assign({}, prevState, { editForm: { index: action.data.index } }); + case Actions["b" /* actionTypes */].TOP_SITES_CANCEL_EDIT: + return Object.assign({}, prevState, { editForm: null }); + case Actions["b" /* actionTypes */].SCREENSHOT_UPDATED: + newRows = prevState.rows.map(row => { + if (row && row.url === action.data.url) { + hasMatch = true; + return Object.assign({}, row, { screenshot: action.data.screenshot }); + } + return row; + }); + return hasMatch ? Object.assign({}, prevState, { rows: newRows }) : prevState; + case Actions["b" /* actionTypes */].PLACES_BOOKMARK_ADDED: + if (!action.data) { + return prevState; + } + newRows = prevState.rows.map(site => { + if (site && site.url === action.data.url) { + const { bookmarkGuid, bookmarkTitle, dateAdded } = action.data; + return Object.assign({}, site, { bookmarkGuid, bookmarkTitle, bookmarkDateCreated: dateAdded }); + } + return site; + }); + return Object.assign({}, prevState, { rows: newRows }); + case Actions["b" /* actionTypes */].PLACES_BOOKMARK_REMOVED: + if (!action.data) { + return prevState; + } + newRows = prevState.rows.map(site => { + if (site && site.url === action.data.url) { + const newSite = Object.assign({}, site); + delete newSite.bookmarkGuid; + delete newSite.bookmarkTitle; + delete newSite.bookmarkDateCreated; + return newSite; + } + return site; + }); + return Object.assign({}, prevState, { rows: newRows }); + default: + return prevState; + } +} + +function Dialog(prevState = INITIAL_STATE.Dialog, action) { + switch (action.type) { + case Actions["b" /* actionTypes */].DIALOG_OPEN: + return Object.assign({}, prevState, { visible: true, data: action.data }); + case Actions["b" /* actionTypes */].DIALOG_CANCEL: + return Object.assign({}, prevState, { visible: false }); + case Actions["b" /* actionTypes */].DELETE_HISTORY_URL: + return Object.assign({}, INITIAL_STATE.Dialog); + default: + return prevState; + } +} + +function Prefs(prevState = INITIAL_STATE.Prefs, action) { + let newValues; + switch (action.type) { + case Actions["b" /* actionTypes */].PREFS_INITIAL_VALUES: + return Object.assign({}, prevState, { initialized: true, values: action.data }); + case Actions["b" /* actionTypes */].PREF_CHANGED: + newValues = Object.assign({}, prevState.values); + newValues[action.data.name] = action.data.value; + return Object.assign({}, prevState, { values: newValues }); + default: + return prevState; + } +} + +function Sections(prevState = INITIAL_STATE.Sections, action) { + let hasMatch; + let newState; + switch (action.type) { + case Actions["b" /* actionTypes */].SECTION_DEREGISTER: + return prevState.filter(section => section.id !== action.data); + case Actions["b" /* actionTypes */].SECTION_REGISTER: + // If section exists in prevState, update it + newState = prevState.map(section => { + if (section && section.id === action.data.id) { + hasMatch = true; + return Object.assign({}, section, action.data); + } + return section; + }); + // Otherwise, append it + if (!hasMatch) { + const initialized = !!(action.data.rows && action.data.rows.length > 0); + const section = Object.assign({ title: "", rows: [], enabled: false }, action.data, { initialized }); + newState.push(section); + } + return newState; + case Actions["b" /* actionTypes */].SECTION_UPDATE: + newState = prevState.map(section => { + if (section && section.id === action.data.id) { + // If the action is updating rows, we should consider initialized to be true. + // This can be overridden if initialized is defined in the action.data + const initialized = action.data.rows ? { initialized: true } : {}; + + // Make sure pinned cards stay at their current position when rows are updated. + // Disabling a section (SECTION_UPDATE with empty rows) does not retain pinned cards. + if (action.data.rows && action.data.rows.length > 0 && section.rows.find(card => card.pinned)) { + const rows = Array.from(action.data.rows); + section.rows.forEach((card, index) => { + if (card.pinned) { + rows.splice(index, 0, card); + } + }); + return Object.assign({}, section, initialized, Object.assign({}, action.data, { rows })); + } + + return Object.assign({}, section, initialized, action.data); + } + return section; + }); + + if (!action.data.dedupeConfigurations) { + return newState; + } + + action.data.dedupeConfigurations.forEach(dedupeConf => { + newState = newState.map(section => { + if (section.id === dedupeConf.id) { + const dedupedRows = dedupeConf.dedupeFrom.reduce((rows, dedupeSectionId) => { + const dedupeSection = newState.find(s => s.id === dedupeSectionId); + const [, newRows] = dedupe.group(dedupeSection.rows, rows); + return newRows; + }, section.rows); + + return Object.assign({}, section, { rows: dedupedRows }); + } + + return section; + }); + }); + + return newState; + case Actions["b" /* actionTypes */].SECTION_UPDATE_CARD: + return prevState.map(section => { + if (section && section.id === action.data.id && section.rows) { + const newRows = section.rows.map(card => { + if (card.url === action.data.url) { + return Object.assign({}, card, action.data.options); + } + return card; + }); + return Object.assign({}, section, { rows: newRows }); + } + return section; + }); + case Actions["b" /* actionTypes */].PLACES_BOOKMARK_ADDED: + if (!action.data) { + return prevState; + } + return prevState.map(section => Object.assign({}, section, { + rows: section.rows.map(item => { + // find the item within the rows that is attempted to be bookmarked + if (item.url === action.data.url) { + const { bookmarkGuid, bookmarkTitle, dateAdded } = action.data; + return Object.assign({}, item, { + bookmarkGuid, + bookmarkTitle, + bookmarkDateCreated: dateAdded, + type: "bookmark" + }); + } + return item; + }) + })); + case Actions["b" /* actionTypes */].PLACES_SAVED_TO_POCKET: + if (!action.data) { + return prevState; + } + return prevState.map(section => Object.assign({}, section, { + rows: section.rows.map(item => { + if (item.url === action.data.url) { + return Object.assign({}, item, { + open_url: action.data.open_url, + pocket_id: action.data.pocket_id, + title: action.data.title, + type: "pocket" + }); + } + return item; + }) + })); + case Actions["b" /* actionTypes */].PLACES_BOOKMARK_REMOVED: + if (!action.data) { + return prevState; + } + return prevState.map(section => Object.assign({}, section, { + rows: section.rows.map(item => { + // find the bookmark within the rows that is attempted to be removed + if (item.url === action.data.url) { + const newSite = Object.assign({}, item); + delete newSite.bookmarkGuid; + delete newSite.bookmarkTitle; + delete newSite.bookmarkDateCreated; + if (!newSite.type || newSite.type === "bookmark") { + newSite.type = "history"; + } + return newSite; + } + return item; + }) + })); + case Actions["b" /* actionTypes */].PLACES_LINKS_DELETED: + return prevState.map(section => Object.assign({}, section, { rows: section.rows.filter(site => !action.data.includes(site.url)) })); + case Actions["b" /* actionTypes */].PLACES_LINK_BLOCKED: + return prevState.map(section => Object.assign({}, section, { rows: section.rows.filter(site => site.url !== action.data.url) })); + case Actions["b" /* actionTypes */].DELETE_FROM_POCKET: + case Actions["b" /* actionTypes */].ARCHIVE_FROM_POCKET: + return prevState.map(section => Object.assign({}, section, { rows: section.rows.filter(site => site.pocket_id !== action.data.pocket_id) })); + default: + return prevState; + } +} + +function Snippets(prevState = INITIAL_STATE.Snippets, action) { + switch (action.type) { + case Actions["b" /* actionTypes */].SNIPPETS_DATA: + return Object.assign({}, prevState, { initialized: true }, action.data); + case Actions["b" /* actionTypes */].SNIPPET_BLOCKED: + return Object.assign({}, prevState, { blockList: prevState.blockList.concat(action.data) }); + case Actions["b" /* actionTypes */].SNIPPETS_BLOCKLIST_CLEARED: + return Object.assign({}, prevState, { blockList: [] }); + case Actions["b" /* actionTypes */].SNIPPETS_RESET: + return INITIAL_STATE.Snippets; + default: + return prevState; + } +} + +function PreferencesPane(prevState = INITIAL_STATE.PreferencesPane, action) { + switch (action.type) { + case Actions["b" /* actionTypes */].SETTINGS_OPEN: + return Object.assign({}, prevState, { visible: true }); + case Actions["b" /* actionTypes */].SETTINGS_CLOSE: + return Object.assign({}, prevState, { visible: false }); + default: + return prevState; + } +} + +var reducers = { TopSites, App, Snippets, Prefs, Dialog, Sections, PreferencesPane }; + +/***/ }), +/* 7 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react_intl__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react_intl___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react_intl__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__); + + + +class ErrorBoundaryFallback extends __WEBPACK_IMPORTED_MODULE_1_react___default.a.PureComponent { + constructor(props) { + super(props); + this.windowObj = this.props.windowObj || window; + this.onClick = this.onClick.bind(this); + } + + /** + * Since we only get here if part of the page has crashed, do a + * forced reload to give us the best chance at recovering. + */ + onClick() { + this.windowObj.location.reload(true); + } + + render() { + const defaultClass = "as-error-fallback"; + let className; + if ("className" in this.props) { + className = `${this.props.className} ${defaultClass}`; + } else { + className = defaultClass; + } + + // href="#" to force normal link styling stuff (eg cursor on hover) + return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "div", + { className: className }, + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "div", + null, + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_0_react_intl__["FormattedMessage"], { + defaultMessage: "Oops, something went wrong loading this content.", + id: "error_fallback_default_info" }) + ), + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "span", + null, + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "a", + { href: "#", className: "reload-button", onClick: this.onClick }, + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_0_react_intl__["FormattedMessage"], { + defaultMessage: "Refresh page to try again.", + id: "error_fallback_default_refresh_suggestion" }) + ) + ) + ); + } +} +/* unused harmony export ErrorBoundaryFallback */ + +ErrorBoundaryFallback.defaultProps = { className: "as-error-fallback" }; + +class ErrorBoundary extends __WEBPACK_IMPORTED_MODULE_1_react___default.a.PureComponent { + constructor(props) { + super(props); + this.state = { hasError: false }; + } + + componentDidCatch(error, info) { + this.setState({ hasError: true }); + } + + render() { + if (!this.state.hasError) { + return this.props.children; + } + + return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement(this.props.FallbackComponent, { className: this.props.className }); + } +} +/* harmony export (immutable) */ __webpack_exports__["a"] = ErrorBoundary; + + +ErrorBoundary.defaultProps = { FallbackComponent: ErrorBoundaryFallback }; + +/***/ }), +/* 8 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./system-addon/common/Actions.jsm +var Actions = __webpack_require__(0); + +// EXTERNAL MODULE: external "ReactRedux" +var external__ReactRedux_ = __webpack_require__(4); +var external__ReactRedux__default = /*#__PURE__*/__webpack_require__.n(external__ReactRedux_); + +// EXTERNAL MODULE: ./system-addon/content-src/components/ContextMenu/ContextMenu.jsx +var ContextMenu = __webpack_require__(9); + +// EXTERNAL MODULE: external "ReactIntl" +var external__ReactIntl_ = __webpack_require__(2); +var external__ReactIntl__default = /*#__PURE__*/__webpack_require__.n(external__ReactIntl_); + +// CONCATENATED MODULE: ./system-addon/content-src/lib/link-menu-options.js + + +const _OpenInPrivateWindow = site => ({ + id: "menu_action_open_private_window", + icon: "new-window-private", + action: Actions["a" /* actionCreators */].OnlyToMain({ + type: Actions["b" /* actionTypes */].OPEN_PRIVATE_WINDOW, + data: { url: site.url, referrer: site.referrer } + }), + userEvent: "OPEN_PRIVATE_WINDOW" +}); + +/** + * List of functions that return items that can be included as menu options in a + * LinkMenu. All functions take the site as the first parameter, and optionally + * the index of the site. + */ +const LinkMenuOptions = { + Separator: () => ({ type: "separator" }), + EmptyItem: () => ({ type: "empty" }), + RemoveBookmark: site => ({ + id: "menu_action_remove_bookmark", + icon: "bookmark-added", + action: Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].DELETE_BOOKMARK_BY_ID, + data: site.bookmarkGuid + }), + userEvent: "BOOKMARK_DELETE" + }), + AddBookmark: site => ({ + id: "menu_action_bookmark", + icon: "bookmark-hollow", + action: Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].BOOKMARK_URL, + data: { url: site.url, title: site.title, type: site.type } + }), + userEvent: "BOOKMARK_ADD" + }), + OpenInNewWindow: site => ({ + id: "menu_action_open_new_window", + icon: "new-window", + action: Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].OPEN_NEW_WINDOW, + data: { url: site.url, referrer: site.referrer } + }), + userEvent: "OPEN_NEW_WINDOW" + }), + BlockUrl: (site, index, eventSource) => ({ + id: "menu_action_dismiss", + icon: "dismiss", + action: Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].BLOCK_URL, + data: { url: site.url, pocket_id: site.pocket_id } + }), + impression: Actions["a" /* actionCreators */].ImpressionStats({ + source: eventSource, + block: 0, + tiles: [{ id: site.guid, pos: index }] + }), + userEvent: "BLOCK" + }), + + // This is an option for web extentions which will result in remove items from + // memory and notify the web extenion, rather than using the built-in block list. + WebExtDismiss: (site, index, eventSource) => ({ + id: "menu_action_webext_dismiss", + string_id: "menu_action_dismiss", + icon: "dismiss", + action: Actions["a" /* actionCreators */].WebExtEvent(Actions["b" /* actionTypes */].WEBEXT_DISMISS, { + source: eventSource, + url: site.url, + action_position: index + }) + }), + DeleteUrl: (site, index, eventSource, isEnabled, siteInfo) => ({ + id: "menu_action_delete", + icon: "delete", + action: { + type: Actions["b" /* actionTypes */].DIALOG_OPEN, + data: { + onConfirm: [Actions["a" /* actionCreators */].AlsoToMain({ type: Actions["b" /* actionTypes */].DELETE_HISTORY_URL, data: { url: site.url, pocket_id: site.pocket_id, forceBlock: site.bookmarkGuid } }), Actions["a" /* actionCreators */].UserEvent(Object.assign({ event: "DELETE", source: eventSource, action_position: index }, siteInfo))], + eventSource, + body_string_id: ["confirm_history_delete_p1", "confirm_history_delete_notice_p2"], + confirm_button_string_id: "menu_action_delete", + cancel_button_string_id: "topsites_form_cancel_button", + icon: "modal-delete" + } + }, + userEvent: "DIALOG_OPEN" + }), + PinTopSite: (site, index) => ({ + id: "menu_action_pin", + icon: "pin", + action: Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].TOP_SITES_PIN, + data: { site: { url: site.url }, index } + }), + userEvent: "PIN" + }), + UnpinTopSite: site => ({ + id: "menu_action_unpin", + icon: "unpin", + action: Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].TOP_SITES_UNPIN, + data: { site: { url: site.url } } + }), + userEvent: "UNPIN" + }), + SaveToPocket: (site, index, eventSource) => ({ + id: "menu_action_save_to_pocket", + icon: "pocket", + action: Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].SAVE_TO_POCKET, + data: { site: { url: site.url, title: site.title } } + }), + impression: Actions["a" /* actionCreators */].ImpressionStats({ + source: eventSource, + pocket: 0, + tiles: [{ id: site.guid, pos: index }] + }), + userEvent: "SAVE_TO_POCKET" + }), + DeleteFromPocket: site => ({ + id: "menu_action_delete_pocket", + icon: "delete", + action: Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].DELETE_FROM_POCKET, + data: { pocket_id: site.pocket_id } + }), + userEvent: "DELETE_FROM_POCKET" + }), + ArchiveFromPocket: site => ({ + id: "menu_action_archive_pocket", + icon: "check", + action: Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].ARCHIVE_FROM_POCKET, + data: { pocket_id: site.pocket_id } + }), + userEvent: "ARCHIVE_FROM_POCKET" + }), + EditTopSite: (site, index) => ({ + id: "edit_topsites_button_text", + icon: "edit", + action: { + type: Actions["b" /* actionTypes */].TOP_SITES_EDIT, + data: { index } + } + }), + CheckBookmark: site => site.bookmarkGuid ? LinkMenuOptions.RemoveBookmark(site) : LinkMenuOptions.AddBookmark(site), + CheckPinTopSite: (site, index) => site.isPinned ? LinkMenuOptions.UnpinTopSite(site) : LinkMenuOptions.PinTopSite(site, index), + CheckSavedToPocket: (site, index) => site.pocket_id ? LinkMenuOptions.DeleteFromPocket(site) : LinkMenuOptions.SaveToPocket(site, index), + CheckBookmarkOrArchive: site => site.pocket_id ? LinkMenuOptions.ArchiveFromPocket(site) : LinkMenuOptions.CheckBookmark(site), + CheckDeleteHistoryOrEmpty: (site, index, eventSource, isEnabled, siteInfo) => site.pocket_id ? LinkMenuOptions.EmptyItem() : LinkMenuOptions.DeleteUrl(site, index, eventSource, isEnabled, siteInfo), + OpenInPrivateWindow: (site, index, eventSource, isEnabled) => isEnabled ? _OpenInPrivateWindow(site) : LinkMenuOptions.EmptyItem() +}; +// EXTERNAL MODULE: external "React" +var external__React_ = __webpack_require__(1); +var external__React__default = /*#__PURE__*/__webpack_require__.n(external__React_); + +// CONCATENATED MODULE: ./system-addon/content-src/components/LinkMenu/LinkMenu.jsx + + + + + + + +const DEFAULT_SITE_MENU_OPTIONS = ["CheckPinTopSite", "EditTopSite", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl"]; + +class LinkMenu__LinkMenu extends external__React__default.a.PureComponent { + getOptions() { + const { props } = this; + const { site, index, source, isPrivateBrowsingEnabled, siteInfo } = props; + + // Handle special case of default site + const propOptions = !site.isDefault ? props.options : DEFAULT_SITE_MENU_OPTIONS; + + const options = propOptions.map(o => LinkMenuOptions[o](site, index, source, isPrivateBrowsingEnabled, siteInfo)).map(option => { + const { action, impression, id, string_id, type, userEvent } = option; + if (!type && id) { + option.label = props.intl.formatMessage({ id: string_id || id }); + option.onClick = () => { + props.dispatch(action); + if (userEvent) { + const userEventData = Object.assign({ + event: userEvent, + source, + action_position: index + }, siteInfo); + props.dispatch(Actions["a" /* actionCreators */].UserEvent(userEventData)); + } + if (impression && props.shouldSendImpressionStats) { + props.dispatch(impression); + } + }; + } + return option; + }); + + // This is for accessibility to support making each item tabbable. + // We want to know which item is the first and which item + // is the last, so we can close the context menu accordingly. + options[0].first = true; + options[options.length - 1].last = true; + return options; + } + + render() { + return external__React__default.a.createElement(ContextMenu["a" /* ContextMenu */], { + onUpdate: this.props.onUpdate, + options: this.getOptions() }); + } +} +/* unused harmony export _LinkMenu */ + + +const getState = state => ({ isPrivateBrowsingEnabled: state.Prefs.values.isPrivateBrowsingEnabled }); +const LinkMenu = Object(external__ReactRedux_["connect"])(getState)(Object(external__ReactIntl_["injectIntl"])(LinkMenu__LinkMenu)); +/* harmony export (immutable) */ __webpack_exports__["a"] = LinkMenu; + + +/***/ }), +/* 9 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__); + + +class ContextMenu extends __WEBPACK_IMPORTED_MODULE_0_react___default.a.PureComponent { + constructor(props) { + super(props); + this.hideContext = this.hideContext.bind(this); + this.onClick = this.onClick.bind(this); + } + + hideContext() { + this.props.onUpdate(false); + } + + componentDidMount() { + setTimeout(() => { + global.addEventListener("click", this.hideContext); + }, 0); + } + + componentWillUnmount() { + global.removeEventListener("click", this.hideContext); + } + + onClick(event) { + // Eat all clicks on the context menu so they don't bubble up to window. + // This prevents the context menu from closing when clicking disabled items + // or the separators. + event.stopPropagation(); + } + + render() { + return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement( + "span", + { className: "context-menu", onClick: this.onClick }, + __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement( + "ul", + { role: "menu", className: "context-menu-list" }, + this.props.options.map((option, i) => option.type === "separator" ? __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement("li", { key: i, className: "separator" }) : option.type !== "empty" && __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement(ContextMenuItem, { key: i, option: option, hideContext: this.hideContext })) + ) + ); + } +} +/* harmony export (immutable) */ __webpack_exports__["a"] = ContextMenu; + + +class ContextMenuItem extends __WEBPACK_IMPORTED_MODULE_0_react___default.a.PureComponent { + constructor(props) { + super(props); + this.onClick = this.onClick.bind(this); + this.onKeyDown = this.onKeyDown.bind(this); + } + + onClick() { + this.props.hideContext(); + this.props.option.onClick(); + } + + onKeyDown(event) { + const { option } = this.props; + switch (event.key) { + case "Tab": + // tab goes down in context menu, shift + tab goes up in context menu + // if we're on the last item, one more tab will close the context menu + // similarly, if we're on the first item, one more shift + tab will close it + if (event.shiftKey && option.first || !event.shiftKey && option.last) { + this.props.hideContext(); + } + break; + case "Enter": + this.props.hideContext(); + option.onClick(); + break; + } + } + + render() { + const { option } = this.props; + return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement( + "li", + { role: "menuitem", className: "context-menu-item" }, + __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement( + "a", + { onClick: this.onClick, onKeyDown: this.onKeyDown, tabIndex: "0", className: option.disabled ? "disabled" : "" }, + option.icon && __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement("span", { className: `icon icon-spacer icon-${option.icon}` }), + option.label + ) + ); + } +} +/* unused harmony export ContextMenuItem */ + +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3))) + +/***/ }), +/* 10 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react_intl__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react_intl___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react_intl__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_common_Actions_jsm__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_content_src_components_ErrorBoundary_ErrorBoundary__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_content_src_components_SectionMenu_SectionMenu__ = __webpack_require__(20); + + + + + + +const VISIBLE = "visible"; +const VISIBILITY_CHANGE_EVENT = "visibilitychange"; + +function getFormattedMessage(message) { + return typeof message === "string" ? __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "span", + null, + message + ) : __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_0_react_intl__["FormattedMessage"], message); +} +function getCollapsed(props) { + return props.prefName in props.Prefs.values ? props.Prefs.values[props.prefName] : false; +} + +class Disclaimer extends __WEBPACK_IMPORTED_MODULE_3_react___default.a.PureComponent { + constructor(props) { + super(props); + this.onAcknowledge = this.onAcknowledge.bind(this); + } + + onAcknowledge() { + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_1_common_Actions_jsm__["a" /* actionCreators */].SetPref(this.props.disclaimerPref, false)); + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_1_common_Actions_jsm__["a" /* actionCreators */].UserEvent({ event: "SECTION_DISCLAIMER_ACKNOWLEDGED", source: this.props.eventSource })); + } + + render() { + const { disclaimer } = this.props; + return __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "div", + { className: "section-disclaimer" }, + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "div", + { className: "section-disclaimer-text" }, + getFormattedMessage(disclaimer.text), + disclaimer.link && __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "a", + { href: disclaimer.link.href, target: "_blank", rel: "noopener noreferrer" }, + getFormattedMessage(disclaimer.link.title || disclaimer.link) + ) + ), + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "button", + { onClick: this.onAcknowledge }, + getFormattedMessage(disclaimer.button) + ) + ); + } +} +/* unused harmony export Disclaimer */ + + +const DisclaimerIntl = Object(__WEBPACK_IMPORTED_MODULE_0_react_intl__["injectIntl"])(Disclaimer); +/* unused harmony export DisclaimerIntl */ + + +class _CollapsibleSection extends __WEBPACK_IMPORTED_MODULE_3_react___default.a.PureComponent { + constructor(props) { + super(props); + this.onBodyMount = this.onBodyMount.bind(this); + this.onHeaderClick = this.onHeaderClick.bind(this); + this.onTransitionEnd = this.onTransitionEnd.bind(this); + this.enableOrDisableAnimation = this.enableOrDisableAnimation.bind(this); + this.onMenuButtonClick = this.onMenuButtonClick.bind(this); + this.onMenuButtonMouseEnter = this.onMenuButtonMouseEnter.bind(this); + this.onMenuButtonMouseLeave = this.onMenuButtonMouseLeave.bind(this); + this.onMenuUpdate = this.onMenuUpdate.bind(this); + this.state = { enableAnimation: true, isAnimating: false, menuButtonHover: false, showContextMenu: false }; + } + + componentWillMount() { + this.props.document.addEventListener(VISIBILITY_CHANGE_EVENT, this.enableOrDisableAnimation); + } + + componentWillUpdate(nextProps) { + // Check if we're about to go from expanded to collapsed + if (!getCollapsed(this.props) && getCollapsed(nextProps)) { + // This next line forces a layout flush of the section body, which has a + // max-height style set, so that the upcoming collapse animation can + // animate from that height to the collapsed height. Without this, the + // update is coalesced and there's no animation from no-max-height to 0. + this.sectionBody.scrollHeight; // eslint-disable-line no-unused-expressions + } + } + + componentWillUnmount() { + this.props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this.enableOrDisableAnimation); + } + + enableOrDisableAnimation() { + // Only animate the collapse/expand for visible tabs. + const visible = this.props.document.visibilityState === VISIBLE; + if (this.state.enableAnimation !== visible) { + this.setState({ enableAnimation: visible }); + } + } + + onBodyMount(node) { + this.sectionBody = node; + } + + onHeaderClick() { + // If this.sectionBody is unset, it means that we're in some sort of error + // state, probably displaying the error fallback, so we won't be able to + // compute the height, and we don't want to persist the preference. + if (!this.sectionBody) { + return; + } + + // Get the current height of the body so max-height transitions can work + this.setState({ + isAnimating: true, + maxHeight: `${this.sectionBody.scrollHeight}px` + }); + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_1_common_Actions_jsm__["a" /* actionCreators */].SetPref(this.props.prefName, !getCollapsed(this.props))); + } + + onTransitionEnd(event) { + // Only update the animating state for our own transition (not a child's) + if (event.target === event.currentTarget) { + this.setState({ isAnimating: false }); + } + } + + renderIcon() { + const { icon } = this.props; + if (icon && icon.startsWith("moz-extension://")) { + return __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement("span", { className: "icon icon-small-spacer", style: { backgroundImage: `url('${icon}')` } }); + } + return __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement("span", { className: `icon icon-small-spacer icon-${icon || "webextension"}` }); + } + + onMenuButtonClick(event) { + event.preventDefault(); + this.setState({ showContextMenu: true }); + } + + onMenuButtonMouseEnter() { + this.setState({ menuButtonHover: true }); + } + + onMenuButtonMouseLeave() { + this.setState({ menuButtonHover: false }); + } + + onMenuUpdate(showContextMenu) { + this.setState({ showContextMenu }); + } + + render() { + const isCollapsible = this.props.prefName in this.props.Prefs.values; + const isCollapsed = getCollapsed(this.props); + const { enableAnimation, isAnimating, maxHeight, menuButtonHover, showContextMenu } = this.state; + const { id, eventSource, disclaimer, title, extraMenuOptions, prefName, showPrefName, privacyNoticeURL, dispatch, isFirst, isLast } = this.props; + const disclaimerPref = `section.${id}.showDisclaimer`; + const needsDisclaimer = disclaimer && this.props.Prefs.values[disclaimerPref]; + const active = menuButtonHover || showContextMenu; + + return __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "section", + { className: `collapsible-section ${this.props.className}${enableAnimation ? " animation-enabled" : ""}${isCollapsed ? " collapsed" : ""}${active ? " active" : ""}` }, + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "div", + { className: "section-top-bar" }, + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "h3", + { className: "section-title" }, + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "span", + { className: "click-target", onClick: isCollapsible && this.onHeaderClick }, + this.renderIcon(), + title, + isCollapsible && __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement("span", { className: `collapsible-arrow icon ${isCollapsed ? "icon-arrowhead-forward-small" : "icon-arrowhead-down-small"}` }) + ) + ), + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "div", + null, + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "button", + { + className: "context-menu-button icon", + onClick: this.onMenuButtonClick, + onMouseEnter: this.onMenuButtonMouseEnter, + onMouseLeave: this.onMenuButtonMouseLeave }, + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "span", + { className: "sr-only" }, + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_0_react_intl__["FormattedMessage"], { id: "section_context_menu_button_sr" }) + ) + ), + showContextMenu && __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_4_content_src_components_SectionMenu_SectionMenu__["a" /* SectionMenu */], { + id: id, + extraOptions: extraMenuOptions, + eventSource: eventSource, + showPrefName: showPrefName, + collapsePrefName: prefName, + privacyNoticeURL: privacyNoticeURL, + isCollapsed: isCollapsed, + onUpdate: this.onMenuUpdate, + isFirst: isFirst, + isLast: isLast, + dispatch: dispatch }) + ) + ), + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + __WEBPACK_IMPORTED_MODULE_2_content_src_components_ErrorBoundary_ErrorBoundary__["a" /* ErrorBoundary */], + { className: "section-body-fallback" }, + __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement( + "div", + { + className: `section-body${isAnimating ? " animating" : ""}`, + onTransitionEnd: this.onTransitionEnd, + ref: this.onBodyMount, + style: isAnimating && !isCollapsed ? { maxHeight } : null }, + needsDisclaimer && __WEBPACK_IMPORTED_MODULE_3_react___default.a.createElement(DisclaimerIntl, { disclaimerPref: disclaimerPref, disclaimer: disclaimer, eventSource: eventSource, dispatch: this.props.dispatch }), + this.props.children + ) + ) + ); + } +} +/* unused harmony export _CollapsibleSection */ + + +_CollapsibleSection.defaultProps = { + document: global.document || { + addEventListener: () => {}, + removeEventListener: () => {}, + visibilityState: "hidden" + }, + Prefs: { values: {} } +}; + +const CollapsibleSection = Object(__WEBPACK_IMPORTED_MODULE_0_react_intl__["injectIntl"])(_CollapsibleSection); +/* harmony export (immutable) */ __webpack_exports__["a"] = CollapsibleSection; + +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3))) + +/***/ }), +/* 11 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_common_PerfService_jsm__ = __webpack_require__(12); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__); + + + + +// Currently record only a fixed set of sections. This will prevent data +// from custom sections from showing up or from topstories. +const RECORDED_SECTIONS = ["highlights", "topsites"]; + +class ComponentPerfTimer extends __WEBPACK_IMPORTED_MODULE_2_react___default.a.Component { + constructor(props) { + super(props); + // Just for test dependency injection: + this.perfSvc = this.props.perfSvc || __WEBPACK_IMPORTED_MODULE_1_common_PerfService_jsm__["a" /* perfService */]; + + this._sendBadStateEvent = this._sendBadStateEvent.bind(this); + this._sendPaintedEvent = this._sendPaintedEvent.bind(this); + this._reportMissingData = false; + this._timestampHandled = false; + this._recordedFirstRender = false; + } + + componentDidMount() { + if (!RECORDED_SECTIONS.includes(this.props.id)) { + return; + } + + this._maybeSendPaintedEvent(); + } + + componentDidUpdate() { + if (!RECORDED_SECTIONS.includes(this.props.id)) { + return; + } + + this._maybeSendPaintedEvent(); + } + + /** + * Call the given callback after the upcoming frame paints. + * + * @note Both setTimeout and requestAnimationFrame are throttled when the page + * is hidden, so this callback may get called up to a second or so after the + * requestAnimationFrame "paint" for hidden tabs. + * + * Newtabs hidden while loading will presumably be fairly rare (other than + * preloaded tabs, which we will be filtering out on the server side), so such + * cases should get lost in the noise. + * + * If we decide that it's important to find out when something that's hidden + * has "painted", however, another option is to post a message to this window. + * That should happen even faster than setTimeout, and, at least as of this + * writing, it's not throttled in hidden windows in Firefox. + * + * @param {Function} callback + * + * @returns void + */ + _afterFramePaint(callback) { + requestAnimationFrame(() => setTimeout(callback, 0)); + } + + _maybeSendBadStateEvent() { + // Follow up bugs: + // https://github.com/mozilla/activity-stream/issues/3691 + if (!this.props.initialized) { + // Remember to report back when data is available. + this._reportMissingData = true; + } else if (this._reportMissingData) { + this._reportMissingData = false; + // Report how long it took for component to become initialized. + this._sendBadStateEvent(); + } + } + + _maybeSendPaintedEvent() { + // If we've already handled a timestamp, don't do it again. + if (this._timestampHandled || !this.props.initialized) { + return; + } + + // And if we haven't, we're doing so now, so remember that. Even if + // something goes wrong in the callback, we can't try again, as we'd be + // sending back the wrong data, and we have to do it here, so that other + // calls to this method while waiting for the next frame won't also try to + // handle it. + this._timestampHandled = true; + this._afterFramePaint(this._sendPaintedEvent); + } + + /** + * Triggered by call to render. Only first call goes through due to + * `_recordedFirstRender`. + */ + _ensureFirstRenderTsRecorded() { + // Used as t0 for recording how long component took to initialize. + if (!this._recordedFirstRender) { + this._recordedFirstRender = true; + // topsites_first_render_ts, highlights_first_render_ts. + const key = `${this.props.id}_first_render_ts`; + this.perfSvc.mark(key); + } + } + + /** + * Creates `TELEMETRY_UNDESIRED_EVENT` with timestamp in ms + * of how much longer the data took to be ready for display than it would + * have been the ideal case. + * https://github.com/mozilla/ping-centre/issues/98 + */ + _sendBadStateEvent() { + // highlights_data_ready_ts, topsites_data_ready_ts. + const dataReadyKey = `${this.props.id}_data_ready_ts`; + this.perfSvc.mark(dataReadyKey); + + try { + const firstRenderKey = `${this.props.id}_first_render_ts`; + // value has to be Int32. + const value = parseInt(this.perfSvc.getMostRecentAbsMarkStartByName(dataReadyKey) - this.perfSvc.getMostRecentAbsMarkStartByName(firstRenderKey), 10); + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].OnlyToMain({ + type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].SAVE_SESSION_PERF_DATA, + // highlights_data_late_by_ms, topsites_data_late_by_ms. + data: { [`${this.props.id}_data_late_by_ms`]: value } + })); + } catch (ex) { + // If this failed, it's likely because the `privacy.resistFingerprinting` + // pref is true. + } + } + + _sendPaintedEvent() { + // Record first_painted event but only send if topsites. + if (this.props.id !== "topsites") { + return; + } + + // topsites_first_painted_ts. + const key = `${this.props.id}_first_painted_ts`; + this.perfSvc.mark(key); + + try { + const data = {}; + data[key] = this.perfSvc.getMostRecentAbsMarkStartByName(key); + + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].OnlyToMain({ + type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].SAVE_SESSION_PERF_DATA, + data + })); + } catch (ex) { + // If this failed, it's likely because the `privacy.resistFingerprinting` + // pref is true. We should at least not blow up, and should continue + // to set this._timestampHandled to avoid going through this again. + } + } + + render() { + if (RECORDED_SECTIONS.includes(this.props.id)) { + this._ensureFirstRenderTsRecorded(); + this._maybeSendBadStateEvent(); + } + return this.props.children; + } +} +/* harmony export (immutable) */ __webpack_exports__["a"] = ComponentPerfTimer; + + +/***/ }), +/* 12 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export _PerfService */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return perfService; }); +/* globals Services */ + + +/* istanbul ignore if */ + +if (typeof ChromeUtils !== "undefined") { + ChromeUtils.import("resource://gre/modules/Services.jsm"); +} + +let usablePerfObj; + +/* istanbul ignore if */ +/* istanbul ignore else */ +if (typeof Services !== "undefined") { + // Borrow the high-resolution timer from the hidden window.... + usablePerfObj = Services.appShell.hiddenDOMWindow.performance; +} else if (typeof performance !== "undefined") { + // we must be running in content space + // eslint-disable-next-line no-undef + usablePerfObj = performance; +} else { + // This is a dummy object so this file doesn't crash in the node prerendering + // task. + usablePerfObj = { + now() {}, + mark() {} + }; +} + +function _PerfService(options) { + // For testing, so that we can use a fake Window.performance object with + // known state. + if (options && options.performanceObj) { + this._perf = options.performanceObj; + } else { + this._perf = usablePerfObj; + } +} + + +_PerfService.prototype = { + /** + * Calls the underlying mark() method on the appropriate Window.performance + * object to add a mark with the given name to the appropriate performance + * timeline. + * + * @param {String} name the name to give the current mark + * @return {void} + */ + mark: function mark(str) { + this._perf.mark(str); + }, + + /** + * Calls the underlying getEntriesByName on the appropriate Window.performance + * object. + * + * @param {String} name + * @param {String} type eg "mark" + * @return {Array} Performance* objects + */ + getEntriesByName: function getEntriesByName(name, type) { + return this._perf.getEntriesByName(name, type); + }, + + /** + * The timeOrigin property from the appropriate performance object. + * Used to ensure that timestamps from the add-on code and the content code + * are comparable. + * + * @note If this is called from a context without a window + * (eg a JSM in chrome), it will return the timeOrigin of the XUL hidden + * window, which appears to be the first created window (and thus + * timeOrigin) in the browser. Note also, however, there is also a private + * hidden window, presumably for private browsing, which appears to be + * created dynamically later. Exactly how/when that shows up needs to be + * investigated. + * + * @return {Number} A double of milliseconds with a precision of 0.5us. + */ + get timeOrigin() { + return this._perf.timeOrigin; + }, + + /** + * Returns the "absolute" version of performance.now(), i.e. one that + * should ([bug 1401406](https://bugzilla.mozilla.org/show_bug.cgi?id=1401406) + * be comparable across both chrome and content. + * + * @return {Number} + */ + absNow: function absNow() { + return this.timeOrigin + this._perf.now(); + }, + + /** + * This returns the absolute startTime from the most recent performance.mark() + * with the given name. + * + * @param {String} name the name to lookup the start time for + * + * @return {Number} the returned start time, as a DOMHighResTimeStamp + * + * @throws {Error} "No Marks with the name ..." if none are available + * + * @note Always surround calls to this by try/catch. Otherwise your code + * may fail when the `privacy.resistFingerprinting` pref is true. When + * this pref is set, all attempts to get marks will likely fail, which will + * cause this method to throw. + * + * See [bug 1369303](https://bugzilla.mozilla.org/show_bug.cgi?id=1369303) + * for more info. + */ + getMostRecentAbsMarkStartByName(name) { + let entries = this.getEntriesByName(name, "mark"); + + if (!entries.length) { + throw new Error(`No marks with the name ${name}`); + } + + let mostRecentEntry = entries[entries.length - 1]; + return this._perf.timeOrigin + mostRecentEntry.startTime; + } +}; + +var perfService = new _PerfService(); + +/***/ }), +/* 13 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_react_intl__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_react_intl___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react_intl__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__TopSitesConstants__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_content_src_components_LinkMenu_LinkMenu__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_react__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_common_Reducers_jsm__ = __webpack_require__(6); +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + + + + + + + + +class TopSiteLink extends __WEBPACK_IMPORTED_MODULE_4_react___default.a.PureComponent { + constructor(props) { + super(props); + this.onDragEvent = this.onDragEvent.bind(this); + } + + /* + * Helper to determine whether the drop zone should allow a drop. We only allow + * dropping top sites for now. + */ + _allowDrop(e) { + return e.dataTransfer.types.includes("text/topsite-index"); + } + + onDragEvent(event) { + switch (event.type) { + case "click": + // Stop any link clicks if we started any dragging + if (this.dragged) { + event.preventDefault(); + } + break; + case "dragstart": + this.dragged = true; + event.dataTransfer.effectAllowed = "move"; + event.dataTransfer.setData("text/topsite-index", this.props.index); + event.target.blur(); + this.props.onDragEvent(event, this.props.index, this.props.link, this.props.title); + break; + case "dragend": + this.props.onDragEvent(event); + break; + case "dragenter": + case "dragover": + case "drop": + if (this._allowDrop(event)) { + event.preventDefault(); + this.props.onDragEvent(event, this.props.index); + } + break; + case "mousedown": + // Reset at the first mouse event of a potential drag + this.dragged = false; + break; + } + } + + render() { + const { children, className, isDraggable, link, onClick, title } = this.props; + const topSiteOuterClassName = `top-site-outer${className ? ` ${className}` : ""}${link.isDragged ? " dragged" : ""}`; + const { tippyTopIcon, faviconSize } = link; + const [letterFallback] = title; + let imageClassName; + let imageStyle; + let showSmallFavicon = false; + let smallFaviconStyle; + let smallFaviconFallback; + if (tippyTopIcon || faviconSize >= __WEBPACK_IMPORTED_MODULE_2__TopSitesConstants__["b" /* MIN_RICH_FAVICON_SIZE */]) { + // styles and class names for top sites with rich icons + imageClassName = "top-site-icon rich-icon"; + imageStyle = { + backgroundColor: link.backgroundColor, + backgroundImage: `url(${tippyTopIcon || link.favicon})` + }; + } else { + // styles and class names for top sites with screenshot + small icon in top left corner + imageClassName = `screenshot${link.screenshot ? " active" : ""}`; + imageStyle = { backgroundImage: link.screenshot ? `url(${link.screenshot})` : "none" }; + + // only show a favicon in top left if it's greater than 16x16 + if (faviconSize >= __WEBPACK_IMPORTED_MODULE_2__TopSitesConstants__["a" /* MIN_CORNER_FAVICON_SIZE */]) { + showSmallFavicon = true; + smallFaviconStyle = { backgroundImage: `url(${link.favicon})` }; + } else if (link.screenshot) { + // Don't show a small favicon if there is no screenshot, because that + // would result in two fallback icons + showSmallFavicon = true; + smallFaviconFallback = true; + } + } + let draggableProps = {}; + if (isDraggable) { + draggableProps = { + onClick: this.onDragEvent, + onDragEnd: this.onDragEvent, + onDragStart: this.onDragEvent, + onMouseDown: this.onDragEvent + }; + } + return __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "li", + _extends({ className: topSiteOuterClassName, onDrop: this.onDragEvent, onDragOver: this.onDragEvent, onDragEnter: this.onDragEvent, onDragLeave: this.onDragEvent }, draggableProps), + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "div", + { className: "top-site-inner" }, + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "a", + { href: link.url, onClick: onClick }, + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "div", + { className: "tile", "aria-hidden": true, "data-fallback": letterFallback }, + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement("div", { className: imageClassName, style: imageStyle }), + showSmallFavicon && __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement("div", { + className: "top-site-icon default-icon", + "data-fallback": smallFaviconFallback && letterFallback, + style: smallFaviconStyle }) + ), + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "div", + { className: `title ${link.isPinned ? "pinned" : ""}` }, + link.isPinned && __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement("div", { className: "icon icon-pin-small" }), + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "span", + { dir: "auto" }, + title + ) + ) + ), + children + ) + ); + } +} +/* harmony export (immutable) */ __webpack_exports__["a"] = TopSiteLink; + +TopSiteLink.defaultProps = { + title: "", + link: {}, + isDraggable: true +}; + +class TopSite extends __WEBPACK_IMPORTED_MODULE_4_react___default.a.PureComponent { + constructor(props) { + super(props); + this.state = { showContextMenu: false }; + this.onLinkClick = this.onLinkClick.bind(this); + this.onMenuButtonClick = this.onMenuButtonClick.bind(this); + this.onMenuUpdate = this.onMenuUpdate.bind(this); + } + + /** + * Report to telemetry additional information about the item. + */ + _getTelemetryInfo() { + const value = { icon_type: this.props.link.iconType }; + // Filter out "not_pinned" type for being the default + if (this.props.link.isPinned) { + value.card_type = "pinned"; + } + return { value }; + } + + userEvent(event) { + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].UserEvent(Object.assign({ + event, + source: __WEBPACK_IMPORTED_MODULE_2__TopSitesConstants__["d" /* TOP_SITES_SOURCE */], + action_position: this.props.index + }, this._getTelemetryInfo()))); + } + + onLinkClick(ev) { + this.userEvent("CLICK"); + } + + onMenuButtonClick(event) { + event.preventDefault(); + this.props.onActivate(this.props.index); + this.setState({ showContextMenu: true }); + } + + onMenuUpdate(showContextMenu) { + this.setState({ showContextMenu }); + } + + render() { + const { props } = this; + const { link } = props; + const isContextMenuOpen = this.state.showContextMenu && props.activeIndex === props.index; + const title = link.label || link.hostname; + return __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + TopSiteLink, + _extends({}, props, { onClick: this.onLinkClick, onDragEvent: this.props.onDragEvent, className: `${props.className || ""}${isContextMenuOpen ? " active" : ""}`, title: title }), + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "div", + null, + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "button", + { className: "context-menu-button icon", onClick: this.onMenuButtonClick }, + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "span", + { className: "sr-only" }, + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_1_react_intl__["FormattedMessage"], { id: "context_menu_button_sr", values: { title } }) + ) + ), + isContextMenuOpen && __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_3_content_src_components_LinkMenu_LinkMenu__["a" /* LinkMenu */], { + dispatch: props.dispatch, + index: props.index, + onUpdate: this.onMenuUpdate, + options: __WEBPACK_IMPORTED_MODULE_2__TopSitesConstants__["c" /* TOP_SITES_CONTEXT_MENU_OPTIONS */], + site: link, + siteInfo: this._getTelemetryInfo(), + source: __WEBPACK_IMPORTED_MODULE_2__TopSitesConstants__["d" /* TOP_SITES_SOURCE */] }) + ) + ); + } +} +/* unused harmony export TopSite */ + +TopSite.defaultProps = { + link: {}, + onActivate() {} +}; + +class TopSitePlaceholder extends __WEBPACK_IMPORTED_MODULE_4_react___default.a.PureComponent { + constructor(props) { + super(props); + this.onEditButtonClick = this.onEditButtonClick.bind(this); + } + + onEditButtonClick() { + this.props.dispatch({ type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].TOP_SITES_EDIT, data: { index: this.props.index } }); + } + + render() { + return __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + TopSiteLink, + _extends({}, this.props, { className: `placeholder ${this.props.className || ""}`, isDraggable: false }), + __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement("button", { className: "context-menu-button edit-button icon", + title: this.props.intl.formatMessage({ id: "edit_topsites_edit_button" }), + onClick: this.onEditButtonClick }) + ); + } +} +/* unused harmony export TopSitePlaceholder */ + + +class _TopSiteList extends __WEBPACK_IMPORTED_MODULE_4_react___default.a.PureComponent { + static get DEFAULT_STATE() { + return { + activeIndex: null, + draggedIndex: null, + draggedSite: null, + draggedTitle: null, + topSitesPreview: null + }; + } + + constructor(props) { + super(props); + this.state = _TopSiteList.DEFAULT_STATE; + this.onDragEvent = this.onDragEvent.bind(this); + this.onActivate = this.onActivate.bind(this); + } + + componentWillReceiveProps(nextProps) { + if (this.state.draggedSite) { + const prevTopSites = this.props.TopSites && this.props.TopSites.rows; + const newTopSites = nextProps.TopSites && nextProps.TopSites.rows; + if (prevTopSites && prevTopSites[this.state.draggedIndex] && prevTopSites[this.state.draggedIndex].url === this.state.draggedSite.url && (!newTopSites[this.state.draggedIndex] || newTopSites[this.state.draggedIndex].url !== this.state.draggedSite.url)) { + // We got the new order from the redux store via props. We can clear state now. + this.setState(_TopSiteList.DEFAULT_STATE); + } + } + } + + userEvent(event, index) { + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].UserEvent({ + event, + source: __WEBPACK_IMPORTED_MODULE_2__TopSitesConstants__["d" /* TOP_SITES_SOURCE */], + action_position: index + })); + } + + onDragEvent(event, index, link, title) { + switch (event.type) { + case "dragstart": + this.dropped = false; + this.setState({ + draggedIndex: index, + draggedSite: link, + draggedTitle: title, + activeIndex: null + }); + this.userEvent("DRAG", index); + break; + case "dragend": + if (!this.dropped) { + // If there was no drop event, reset the state to the default. + this.setState(_TopSiteList.DEFAULT_STATE); + } + break; + case "dragenter": + if (index === this.state.draggedIndex) { + this.setState({ topSitesPreview: null }); + } else { + this.setState({ topSitesPreview: this._makeTopSitesPreview(index) }); + } + break; + case "drop": + if (index !== this.state.draggedIndex) { + this.dropped = true; + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].AlsoToMain({ + type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].TOP_SITES_INSERT, + data: { site: { url: this.state.draggedSite.url, label: this.state.draggedTitle }, index, draggedFromIndex: this.state.draggedIndex } + })); + this.userEvent("DROP", index); + } + break; + } + } + + _getTopSites() { + // Make a copy of the sites to truncate or extend to desired length + let topSites = this.props.TopSites.rows.slice(); + topSites.length = this.props.TopSitesRows * __WEBPACK_IMPORTED_MODULE_5_common_Reducers_jsm__["a" /* TOP_SITES_MAX_SITES_PER_ROW */]; + return topSites; + } + + /** + * Make a preview of the topsites that will be the result of dropping the currently + * dragged site at the specified index. + */ + _makeTopSitesPreview(index) { + const topSites = this._getTopSites(); + topSites[this.state.draggedIndex] = null; + const pinnedOnly = topSites.map(site => site && site.isPinned ? site : null); + const unpinned = topSites.filter(site => site && !site.isPinned); + const siteToInsert = Object.assign({}, this.state.draggedSite, { isPinned: true, isDragged: true }); + if (!pinnedOnly[index]) { + pinnedOnly[index] = siteToInsert; + } else { + // Find the hole to shift the pinned site(s) towards. We shift towards the + // hole left by the site being dragged. + let holeIndex = index; + const indexStep = index > this.state.draggedIndex ? -1 : 1; + while (pinnedOnly[holeIndex]) { + holeIndex += indexStep; + } + + // Shift towards the hole. + const shiftingStep = index > this.state.draggedIndex ? 1 : -1; + while (holeIndex !== index) { + const nextIndex = holeIndex + shiftingStep; + pinnedOnly[holeIndex] = pinnedOnly[nextIndex]; + holeIndex = nextIndex; + } + pinnedOnly[index] = siteToInsert; + } + + // Fill in the remaining holes with unpinned sites. + const preview = pinnedOnly; + for (let i = 0; i < preview.length; i++) { + if (!preview[i]) { + preview[i] = unpinned.shift() || null; + } + } + + return preview; + } + + onActivate(index) { + this.setState({ activeIndex: index }); + } + + render() { + const { props } = this; + const topSites = this.state.topSitesPreview || this._getTopSites(); + const topSitesUI = []; + const commonProps = { + onDragEvent: this.onDragEvent, + dispatch: props.dispatch, + intl: props.intl + }; + // We assign a key to each placeholder slot. We need it to be independent + // of the slot index (i below) so that the keys used stay the same during + // drag and drop reordering and the underlying DOM nodes are reused. + // This mostly (only?) affects linux so be sure to test on linux before changing. + let holeIndex = 0; + + // On narrow viewports, we only show 6 sites per row. We'll mark the rest as + // .hide-for-narrow to hide in CSS via @media query. + const maxNarrowVisibleIndex = props.TopSitesRows * 6; + + for (let i = 0, l = topSites.length; i < l; i++) { + const link = topSites[i] && Object.assign({}, topSites[i], { iconType: this.props.topSiteIconType(topSites[i]) }); + const slotProps = { + key: link ? link.url : holeIndex++, + index: i + }; + if (i >= maxNarrowVisibleIndex) { + slotProps.className = "hide-for-narrow"; + } + topSitesUI.push(!link ? __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement(TopSitePlaceholder, _extends({}, slotProps, commonProps)) : __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement(TopSite, _extends({ + link: link, + activeIndex: this.state.activeIndex, + onActivate: this.onActivate + }, slotProps, commonProps))); + } + return __WEBPACK_IMPORTED_MODULE_4_react___default.a.createElement( + "ul", + { className: `top-sites-list${this.state.draggedSite ? " dnd-active" : ""}` }, + topSitesUI + ); + } +} +/* unused harmony export _TopSiteList */ + + +const TopSiteList = Object(__WEBPACK_IMPORTED_MODULE_1_react_intl__["injectIntl"])(_TopSiteList); +/* harmony export (immutable) */ __webpack_exports__["b"] = TopSiteList; + + +/***/ }), +/* 14 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_content_src_lib_snippets__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_content_src_components_Base_Base__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_content_src_lib_detect_user_session_start__ = __webpack_require__(24); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_content_src_lib_init_store__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_react_redux__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_react_redux___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react_redux__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_react__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_react__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_react_dom__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_react_dom___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_react_dom__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_common_Reducers_jsm__ = __webpack_require__(6); + + + + + + + + + + +const store = Object(__WEBPACK_IMPORTED_MODULE_4_content_src_lib_init_store__["a" /* initStore */])(__WEBPACK_IMPORTED_MODULE_8_common_Reducers_jsm__["b" /* reducers */], global.gActivityStreamPrerenderedState); + +new __WEBPACK_IMPORTED_MODULE_3_content_src_lib_detect_user_session_start__["a" /* DetectUserSessionStart */](store).sendEventOrAddListener(); + +// If we are starting in a prerendered state, we must wait until the first render +// to request state rehydration (see Base.jsx). If we are NOT in a prerendered state, +// we can request it immedately. +if (!global.gActivityStreamPrerenderedState) { + store.dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].AlsoToMain({ type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].NEW_TAB_STATE_REQUEST })); +} + +__WEBPACK_IMPORTED_MODULE_7_react_dom___default.a.hydrate(__WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + __WEBPACK_IMPORTED_MODULE_5_react_redux__["Provider"], + { store: store }, + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_2_content_src_components_Base_Base__["a" /* Base */], { + isPrerendered: !!global.gActivityStreamPrerenderedState, + locale: global.document.documentElement.lang, + strings: global.gActivityStreamStrings }) +), document.getElementById("root")); + +Object(__WEBPACK_IMPORTED_MODULE_1_content_src_lib_snippets__["a" /* addSnippetsSubscriber */])(store); +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3))) + +/***/ }), +/* 15 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* harmony export (immutable) */ __webpack_exports__["a"] = addSnippetsSubscriber; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__ = __webpack_require__(0); +const DATABASE_NAME = "snippets_db"; +const DATABASE_VERSION = 1; +const SNIPPETS_OBJECTSTORE_NAME = "snippets"; +const SNIPPETS_UPDATE_INTERVAL_MS = 14400000; +/* unused harmony export SNIPPETS_UPDATE_INTERVAL_MS */ + // 4 hours. + +const SNIPPETS_ENABLED_EVENT = "Snippets:Enabled"; +const SNIPPETS_DISABLED_EVENT = "Snippets:Disabled"; + + + +/** + * SnippetsMap - A utility for cacheing values related to the snippet. It has + * the same interface as a Map, but is optionally backed by + * indexedDB for persistent storage. + * Call .connect() to open a database connection and restore any + * previously cached data, if necessary. + * + */ +class SnippetsMap extends Map { + constructor(dispatch) { + super(); + this._db = null; + this._dispatch = dispatch; + } + + set(key, value) { + super.set(key, value); + return this._dbTransaction(db => db.put(value, key)); + } + + delete(key) { + super.delete(key); + return this._dbTransaction(db => db.delete(key)); + } + + clear() { + super.clear(); + this._dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].OnlyToMain({ type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].SNIPPETS_BLOCKLIST_CLEARED })); + return this._dbTransaction(db => db.clear()); + } + + get blockList() { + return this.get("blockList") || []; + } + + /** + * blockSnippetById - Blocks a snippet given an id + * + * @param {str|int} id The id of the snippet + * @return {Promise} Resolves when the id has been written to indexedDB, + * or immediately if the snippetMap is not connected + */ + async blockSnippetById(id) { + if (!id) { + return; + } + const { blockList } = this; + if (!blockList.includes(id)) { + blockList.push(id); + this._dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].AlsoToMain({ type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].SNIPPETS_BLOCKLIST_UPDATED, data: id })); + await this.set("blockList", blockList); + } + } + + disableOnboarding() { + this._dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].AlsoToMain({ type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].DISABLE_ONBOARDING })); + } + + showFirefoxAccounts() { + this._dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].AlsoToMain({ type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].SHOW_FIREFOX_ACCOUNTS })); + } + + getTotalBookmarksCount() { + return new Promise(resolve => { + this._dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].OnlyToMain({ type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].TOTAL_BOOKMARKS_REQUEST })); + global.addMessageListener("ActivityStream:MainToContent", function onMessage({ data: action }) { + if (action.type === __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].TOTAL_BOOKMARKS_RESPONSE) { + resolve(action.data); + global.removeMessageListener("ActivityStream:MainToContent", onMessage); + } + }); + }); + } + + /** + * connect - Attaches an indexedDB back-end to the Map so that any set values + * are also cached in a store. It also restores any existing values + * that are already stored in the indexedDB store. + * + * @return {type} description + */ + async connect() { + // Open the connection + const db = await this._openDB(); + + // Restore any existing values + await this._restoreFromDb(db); + + // Attach a reference to the db + this._db = db; + } + + /** + * _dbTransaction - Returns a db transaction wrapped with the given modifier + * function as a Promise. If the db has not been connected, + * it resolves immediately. + * + * @param {func} modifier A function to call with the transaction + * @return {obj} A Promise that resolves when the transaction has + * completed or errored + */ + _dbTransaction(modifier) { + if (!this._db) { + return Promise.resolve(); + } + return new Promise((resolve, reject) => { + const transaction = modifier(this._db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite").objectStore(SNIPPETS_OBJECTSTORE_NAME)); + transaction.onsuccess = event => resolve(); + + /* istanbul ignore next */ + transaction.onerror = event => reject(transaction.error); + }); + } + + _openDB() { + return new Promise((resolve, reject) => { + const openRequest = indexedDB.open(DATABASE_NAME, DATABASE_VERSION); + + /* istanbul ignore next */ + openRequest.onerror = event => { + // Try to delete the old database so that we can start this process over + // next time. + indexedDB.deleteDatabase(DATABASE_NAME); + reject(event); + }; + + openRequest.onupgradeneeded = event => { + const db = event.target.result; + if (!db.objectStoreNames.contains(SNIPPETS_OBJECTSTORE_NAME)) { + db.createObjectStore(SNIPPETS_OBJECTSTORE_NAME); + } + }; + + openRequest.onsuccess = event => { + let db = event.target.result; + + /* istanbul ignore next */ + db.onerror = err => console.error(err); // eslint-disable-line no-console + /* istanbul ignore next */ + db.onversionchange = versionChangeEvent => versionChangeEvent.target.close(); + + resolve(db); + }; + }); + } + + _restoreFromDb(db) { + return new Promise((resolve, reject) => { + let cursorRequest; + try { + cursorRequest = db.transaction(SNIPPETS_OBJECTSTORE_NAME).objectStore(SNIPPETS_OBJECTSTORE_NAME).openCursor(); + } catch (err) { + // istanbul ignore next + reject(err); + // istanbul ignore next + return; + } + + /* istanbul ignore next */ + cursorRequest.onerror = event => reject(event); + + cursorRequest.onsuccess = event => { + let cursor = event.target.result; + // Populate the cache from the persistent storage. + if (cursor) { + if (cursor.value !== "blockList") { + this.set(cursor.key, cursor.value); + } + cursor.continue(); + } else { + // We are done. + resolve(); + } + }; + }); + } +} +/* unused harmony export SnippetsMap */ + + +/** + * SnippetsProvider - Initializes a SnippetsMap and loads snippets from a + * remote location, or else default snippets if the remote + * snippets cannot be retrieved. + */ +class SnippetsProvider { + constructor(dispatch) { + // Initialize the Snippets Map and attaches it to a global so that + // the snippet payload can interact with it. + global.gSnippetsMap = new SnippetsMap(dispatch); + this._onAction = this._onAction.bind(this); + } + + get snippetsMap() { + return global.gSnippetsMap; + } + + async _refreshSnippets() { + // Check if the cached version of of the snippets in snippetsMap. If it's too + // old, blow away the entire snippetsMap. + const cachedVersion = this.snippetsMap.get("snippets-cached-version"); + + if (cachedVersion !== this.appData.version) { + this.snippetsMap.clear(); + } + + // Has enough time passed for us to require an update? + const lastUpdate = this.snippetsMap.get("snippets-last-update"); + const needsUpdate = !(lastUpdate >= 0) || Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS; + + if (needsUpdate && this.appData.snippetsURL) { + this.snippetsMap.set("snippets-last-update", Date.now()); + try { + const response = await fetch(this.appData.snippetsURL); + if (response.status === 200) { + const payload = await response.text(); + + this.snippetsMap.set("snippets", payload); + this.snippetsMap.set("snippets-cached-version", this.appData.version); + } + } catch (e) { + console.error(e); // eslint-disable-line no-console + } + } + } + + _noSnippetFallback() { + // TODO + } + + _forceOnboardingVisibility(shouldBeVisible) { + const onboardingEl = document.getElementById("onboarding-notification-bar"); + + if (onboardingEl) { + onboardingEl.style.display = shouldBeVisible ? "" : "none"; + } + } + + _showRemoteSnippets() { + const snippetsEl = document.getElementById(this.elementId); + const payload = this.snippetsMap.get("snippets"); + + if (!snippetsEl) { + throw new Error(`No element was found with id '${this.elementId}'.`); + } + + // This could happen if fetching failed + if (!payload) { + throw new Error("No remote snippets were found in gSnippetsMap."); + } + + if (typeof payload !== "string") { + throw new Error("Snippet payload was incorrectly formatted"); + } + + // Note that injecting snippets can throw if they're invalid XML. + // eslint-disable-next-line no-unsanitized/property + snippetsEl.innerHTML = payload; + + // Scripts injected by innerHTML are inactive, so we have to relocate them + // through DOM manipulation to activate their contents. + for (const scriptEl of snippetsEl.getElementsByTagName("script")) { + const relocatedScript = document.createElement("script"); + relocatedScript.text = scriptEl.text; + scriptEl.parentNode.replaceChild(relocatedScript, scriptEl); + } + } + + _onAction(msg) { + if (msg.data.type === __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].SNIPPET_BLOCKED) { + if (!this.snippetsMap.blockList.includes(msg.data.data)) { + this.snippetsMap.set("blockList", this.snippetsMap.blockList.concat(msg.data.data)); + document.getElementById("snippets-container").style.display = "none"; + } + } + } + + /** + * init - Fetch the snippet payload and show snippets + * + * @param {obj} options + * @param {str} options.appData.snippetsURL The URL from which we fetch snippets + * @param {int} options.appData.version The current snippets version + * @param {str} options.elementId The id of the element in which to inject snippets + * @param {bool} options.connect Should gSnippetsMap connect to indexedDB? + */ + async init(options) { + Object.assign(this, { + appData: {}, + elementId: "snippets", + connect: true + }, options); + + // Add listener so we know when snippets are blocked on other pages + if (global.addMessageListener) { + global.addMessageListener("ActivityStream:MainToContent", this._onAction); + } + + // TODO: Requires enabling indexedDB on newtab + // Restore the snippets map from indexedDB + if (this.connect) { + try { + await this.snippetsMap.connect(); + } catch (e) { + console.error(e); // eslint-disable-line no-console + } + } + + // Cache app data values so they can be accessible from gSnippetsMap + for (const key of Object.keys(this.appData)) { + if (key === "blockList") { + this.snippetsMap.set("blockList", this.appData[key]); + } else { + this.snippetsMap.set(`appData.${key}`, this.appData[key]); + } + } + + // Refresh snippets, if enough time has passed. + await this._refreshSnippets(); + + // Try showing remote snippets, falling back to defaults if necessary. + try { + this._showRemoteSnippets(); + } catch (e) { + this._noSnippetFallback(e); + } + + window.dispatchEvent(new Event(SNIPPETS_ENABLED_EVENT)); + + this._forceOnboardingVisibility(true); + this.initialized = true; + } + + uninit() { + window.dispatchEvent(new Event(SNIPPETS_DISABLED_EVENT)); + this._forceOnboardingVisibility(false); + if (global.removeMessageListener) { + global.removeMessageListener("ActivityStream:MainToContent", this._onAction); + } + this.initialized = false; + } +} +/* unused harmony export SnippetsProvider */ + + +/** + * addSnippetsSubscriber - Creates a SnippetsProvider that Initializes + * when the store has received the appropriate + * Snippet data. + * + * @param {obj} store The redux store + * @return {obj} Returns the snippets instance and unsubscribe function + */ +function addSnippetsSubscriber(store) { + const snippets = new SnippetsProvider(store.dispatch); + + let initializing = false; + + store.subscribe(async () => { + const state = store.getState(); + // state.Prefs.values["feeds.snippets"]: Should snippets be shown? + // state.Snippets.initialized Is the snippets data initialized? + // snippets.initialized: Is SnippetsProvider currently initialised? + if (state.Prefs.values["feeds.snippets"] && !state.Prefs.values.disableSnippets && state.Snippets.initialized && !snippets.initialized && + // Don't call init multiple times + !initializing) { + initializing = true; + await snippets.init({ appData: state.Snippets }); + initializing = false; + } else if ((state.Prefs.values["feeds.snippets"] === false || state.Prefs.values.disableSnippets === true) && snippets.initialized) { + snippets.uninit(); + } + }); + + // These values are returned for testing purposes + return snippets; +} +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3))) + +/***/ }), +/* 16 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./system-addon/common/Actions.jsm +var Actions = __webpack_require__(0); + +// EXTERNAL MODULE: external "ReactIntl" +var external__ReactIntl_ = __webpack_require__(2); +var external__ReactIntl__default = /*#__PURE__*/__webpack_require__.n(external__ReactIntl_); + +// EXTERNAL MODULE: external "ReactRedux" +var external__ReactRedux_ = __webpack_require__(4); +var external__ReactRedux__default = /*#__PURE__*/__webpack_require__.n(external__ReactRedux_); + +// EXTERNAL MODULE: external "React" +var external__React_ = __webpack_require__(1); +var external__React__default = /*#__PURE__*/__webpack_require__.n(external__React_); + +// CONCATENATED MODULE: ./system-addon/content-src/components/ConfirmDialog/ConfirmDialog.jsx + + + + + +/** + * ConfirmDialog component. + * One primary action button, one cancel button. + * + * Content displayed is controlled by `data` prop the component receives. + * Example: + * data: { + * // Any sort of data needed to be passed around by actions. + * payload: site.url, + * // Primary button AlsoToMain action. + * action: "DELETE_HISTORY_URL", + * // Primary button USerEvent action. + * userEvent: "DELETE", + * // Array of locale ids to display. + * message_body: ["confirm_history_delete_p1", "confirm_history_delete_notice_p2"], + * // Text for primary button. + * confirm_button_string_id: "menu_action_delete" + * }, + */ +class ConfirmDialog__ConfirmDialog extends external__React__default.a.PureComponent { + constructor(props) { + super(props); + this._handleCancelBtn = this._handleCancelBtn.bind(this); + this._handleConfirmBtn = this._handleConfirmBtn.bind(this); + } + + _handleCancelBtn() { + this.props.dispatch({ type: Actions["b" /* actionTypes */].DIALOG_CANCEL }); + this.props.dispatch(Actions["a" /* actionCreators */].UserEvent({ event: Actions["b" /* actionTypes */].DIALOG_CANCEL, source: this.props.data.eventSource })); + } + + _handleConfirmBtn() { + this.props.data.onConfirm.forEach(this.props.dispatch); + } + + _renderModalMessage() { + const message_body = this.props.data.body_string_id; + + if (!message_body) { + return null; + } + + return external__React__default.a.createElement( + "span", + null, + message_body.map(msg => external__React__default.a.createElement( + "p", + { key: msg }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: msg }) + )) + ); + } + + render() { + if (!this.props.visible) { + return null; + } + + return external__React__default.a.createElement( + "div", + { className: "confirmation-dialog" }, + external__React__default.a.createElement("div", { className: "modal-overlay", onClick: this._handleCancelBtn }), + external__React__default.a.createElement( + "div", + { className: "modal" }, + external__React__default.a.createElement( + "section", + { className: "modal-message" }, + this.props.data.icon && external__React__default.a.createElement("span", { className: `icon icon-spacer icon-${this.props.data.icon}` }), + this._renderModalMessage() + ), + external__React__default.a.createElement( + "section", + { className: "actions" }, + external__React__default.a.createElement( + "button", + { onClick: this._handleCancelBtn }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: this.props.data.cancel_button_string_id }) + ), + external__React__default.a.createElement( + "button", + { className: "done", onClick: this._handleConfirmBtn }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: this.props.data.confirm_button_string_id }) + ) + ) + ) + ); + } +} + +const ConfirmDialog = Object(external__ReactRedux_["connect"])(state => state.Dialog)(ConfirmDialog__ConfirmDialog); +// EXTERNAL MODULE: ./system-addon/content-src/components/ErrorBoundary/ErrorBoundary.jsx +var ErrorBoundary = __webpack_require__(7); + +// CONCATENATED MODULE: ./system-addon/content-src/components/ManualMigration/ManualMigration.jsx + + + + + +/** + * Manual migration component used to start the profile import wizard. + * Message is presented temporarily and will go away if: + * 1. User clicks "No Thanks" + * 2. User completed the data import + * 3. After 3 active days + * 4. User clicks "Cancel" on the import wizard (currently not implemented). + */ +class ManualMigration__ManualMigration extends external__React__default.a.PureComponent { + constructor(props) { + super(props); + this.onLaunchTour = this.onLaunchTour.bind(this); + this.onCancelTour = this.onCancelTour.bind(this); + } + + onLaunchTour() { + this.props.dispatch(Actions["a" /* actionCreators */].AlsoToMain({ type: Actions["b" /* actionTypes */].MIGRATION_START })); + this.props.dispatch(Actions["a" /* actionCreators */].UserEvent({ event: Actions["b" /* actionTypes */].MIGRATION_START })); + } + + onCancelTour() { + this.props.dispatch(Actions["a" /* actionCreators */].AlsoToMain({ type: Actions["b" /* actionTypes */].MIGRATION_CANCEL })); + this.props.dispatch(Actions["a" /* actionCreators */].UserEvent({ event: Actions["b" /* actionTypes */].MIGRATION_CANCEL })); + } + + render() { + return external__React__default.a.createElement( + "div", + { className: "manual-migration-container" }, + external__React__default.a.createElement( + "p", + null, + external__React__default.a.createElement("span", { className: "icon icon-import" }), + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: "manual_migration_explanation2" }) + ), + external__React__default.a.createElement( + "div", + { className: "manual-migration-actions actions" }, + external__React__default.a.createElement( + "button", + { className: "dismiss", onClick: this.onCancelTour }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: "manual_migration_cancel_button" }) + ), + external__React__default.a.createElement( + "button", + { onClick: this.onLaunchTour }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: "manual_migration_import_button" }) + ) + ) + ); + } +} + +const ManualMigration = Object(external__ReactRedux_["connect"])()(ManualMigration__ManualMigration); +// CONCATENATED MODULE: ./system-addon/content-src/components/PreferencesPane/PreferencesPane.jsx + + + + + +const getFormattedMessage = message => typeof message === "string" ? external__React__default.a.createElement( + "span", + null, + message +) : external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], message); + +const PreferencesInput = props => external__React__default.a.createElement( + "section", + null, + external__React__default.a.createElement("input", { type: "checkbox", id: props.prefName, name: props.prefName, checked: props.value, disabled: props.disabled, onChange: props.onChange, className: props.className }), + external__React__default.a.createElement( + "label", + { htmlFor: props.prefName, className: props.labelClassName }, + getFormattedMessage(props.titleString) + ), + props.descString && external__React__default.a.createElement( + "p", + { className: "prefs-input-description" }, + getFormattedMessage(props.descString) + ), + external__React__default.a.Children.map(props.children, child => external__React__default.a.createElement( + "div", + { className: `options${child.props.disabled ? " disabled" : ""}` }, + child + )) +); + +class PreferencesPane__PreferencesPane extends external__React__default.a.PureComponent { + constructor(props) { + super(props); + this.handleClickOutside = this.handleClickOutside.bind(this); + this.handlePrefChange = this.handlePrefChange.bind(this); + this.handleSectionChange = this.handleSectionChange.bind(this); + this.togglePane = this.togglePane.bind(this); + this.onWrapperMount = this.onWrapperMount.bind(this); + } + + componentDidUpdate(prevProps, prevState) { + if (prevProps.PreferencesPane.visible !== this.props.PreferencesPane.visible) { + // While the sidebar is open, listen for all document clicks. + if (this.isSidebarOpen()) { + document.addEventListener("click", this.handleClickOutside); + } else { + document.removeEventListener("click", this.handleClickOutside); + } + } + } + + isSidebarOpen() { + return this.props.PreferencesPane.visible; + } + + handleClickOutside(event) { + // if we are showing the sidebar and there is a click outside, close it. + if (this.isSidebarOpen() && !this.wrapper.contains(event.target)) { + this.togglePane(); + } + } + + handlePrefChange({ target: { name, checked } }) { + let value = checked; + if (name === "topSitesRows") { + value = checked ? 2 : 1; + } + this.props.dispatch(Actions["a" /* actionCreators */].SetPref(name, value)); + } + + handleSectionChange({ target }) { + const id = target.name; + const type = target.checked ? Actions["b" /* actionTypes */].SECTION_ENABLE : Actions["b" /* actionTypes */].SECTION_DISABLE; + this.props.dispatch(Actions["a" /* actionCreators */].AlsoToMain({ type, data: id })); + } + + togglePane() { + if (this.isSidebarOpen()) { + this.props.dispatch({ type: Actions["b" /* actionTypes */].SETTINGS_CLOSE }); + this.props.dispatch(Actions["a" /* actionCreators */].UserEvent({ event: "CLOSE_NEWTAB_PREFS" })); + } else { + this.props.dispatch({ type: Actions["b" /* actionTypes */].SETTINGS_OPEN }); + this.props.dispatch(Actions["a" /* actionCreators */].UserEvent({ event: "OPEN_NEWTAB_PREFS" })); + } + } + + onWrapperMount(wrapper) { + this.wrapper = wrapper; + } + + render() { + const { props } = this; + const prefs = props.Prefs.values; + const sections = props.Sections; + const isVisible = this.isSidebarOpen(); + return external__React__default.a.createElement( + "div", + { className: "prefs-pane-wrapper", ref: this.onWrapperMount }, + external__React__default.a.createElement( + "div", + { className: "prefs-pane-button" }, + external__React__default.a.createElement("button", { + className: `prefs-button icon ${isVisible ? "icon-dismiss" : "icon-settings"}`, + title: props.intl.formatMessage({ id: isVisible ? "settings_pane_done_button" : "settings_pane_button_label" }), + onClick: this.togglePane }) + ), + external__React__default.a.createElement( + "div", + { className: "prefs-pane" }, + external__React__default.a.createElement( + "div", + { className: `sidebar ${isVisible ? "" : "hidden"}` }, + external__React__default.a.createElement( + "div", + { className: "prefs-modal-inner-wrapper" }, + external__React__default.a.createElement( + "h1", + null, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: "settings_pane_header" }) + ), + external__React__default.a.createElement( + "p", + null, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: "settings_pane_body2" }) + ), + external__React__default.a.createElement(PreferencesInput, { + className: "showSearch", + prefName: "showSearch", + value: prefs.showSearch, + onChange: this.handlePrefChange, + titleString: { id: "settings_pane_search_header" }, + descString: { id: "settings_pane_search_body" } }), + external__React__default.a.createElement("hr", null), + external__React__default.a.createElement( + PreferencesInput, + { + className: "showTopSites", + prefName: "showTopSites", + value: prefs.showTopSites, + onChange: this.handlePrefChange, + titleString: { id: "settings_pane_topsites_header" }, + descString: { id: "settings_pane_topsites_body" } }, + external__React__default.a.createElement(PreferencesInput, { + className: "showMoreTopSites", + prefName: "topSitesRows", + disabled: !prefs.showTopSites, + value: prefs.topSitesRows === 2, + onChange: this.handlePrefChange, + titleString: { id: "settings_pane_topsites_options_showmore" }, + labelClassName: "icon icon-topsites" }) + ), + sections.filter(section => !section.shouldHidePref).map(({ id, title, enabled, pref }) => external__React__default.a.createElement( + PreferencesInput, + { + key: id, + className: "showSection", + prefName: pref && pref.feed || id, + value: enabled, + onChange: pref && pref.feed ? this.handlePrefChange : this.handleSectionChange, + titleString: pref && pref.titleString || title, + descString: pref && pref.descString }, + pref && pref.nestedPrefs && pref.nestedPrefs.map(nestedPref => external__React__default.a.createElement(PreferencesInput, { + key: nestedPref.name, + prefName: nestedPref.name, + disabled: !enabled, + value: prefs[nestedPref.name], + onChange: this.handlePrefChange, + titleString: nestedPref.titleString, + labelClassName: `icon ${nestedPref.icon}` })) + )), + !prefs.disableSnippets && external__React__default.a.createElement("hr", null), + !prefs.disableSnippets && external__React__default.a.createElement(PreferencesInput, { className: "showSnippets", prefName: "feeds.snippets", + value: prefs["feeds.snippets"], onChange: this.handlePrefChange, + titleString: { id: "settings_pane_snippets_header" }, + descString: { id: "settings_pane_snippets_body" } }) + ), + external__React__default.a.createElement( + "section", + { className: "actions" }, + external__React__default.a.createElement( + "button", + { className: "done", onClick: this.togglePane }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: "settings_pane_done_button" }) + ) + ) + ) + ) + ); + } +} + +const PreferencesPane = Object(external__ReactRedux_["connect"])(state => ({ + Prefs: state.Prefs, + PreferencesPane: state.PreferencesPane, + Sections: state.Sections +}))(Object(external__ReactIntl_["injectIntl"])(PreferencesPane__PreferencesPane)); +// CONCATENATED MODULE: ./system-addon/common/PrerenderData.jsm +class _PrerenderData { + constructor(options) { + this.initialPrefs = options.initialPrefs; + this.initialSections = options.initialSections; + this._setValidation(options.validation); + } + + get validation() { + return this._validation; + } + + set validation(value) { + this._setValidation(value); + } + + get invalidatingPrefs() { + return this._invalidatingPrefs; + } + + // This is needed so we can use it in the constructor + _setValidation(value = []) { + this._validation = value; + this._invalidatingPrefs = value.reduce((result, next) => { + if (typeof next === "string") { + result.push(next); + return result; + } else if (next && next.oneOf) { + return result.concat(next.oneOf); + } + throw new Error("Your validation configuration is not properly configured"); + }, []); + } + + arePrefsValid(getPref) { + for (const prefs of this.validation) { + // {oneOf: ["foo", "bar"]} + if (prefs && prefs.oneOf && !prefs.oneOf.some(name => getPref(name) === this.initialPrefs[name])) { + return false; + + // "foo" + } else if (getPref(prefs) !== this.initialPrefs[prefs]) { + return false; + } + } + return true; + } +} +var PrerenderData = new _PrerenderData({ + initialPrefs: { + "migrationExpired": true, + "showTopSites": true, + "showSearch": true, + "topSitesRows": 1, + "collapseTopSites": false, + "section.highlights.collapsed": false, + "section.topstories.collapsed": false, + "feeds.section.topstories": true, + "feeds.section.highlights": true, + "enableWideLayout": true, + "sectionOrder": "topsites,topstories,highlights" + }, + // Prefs listed as invalidating will prevent the prerendered version + // of AS from being used if their value is something other than what is listed + // here. This is required because some preferences cause the page layout to be + // too different for the prerendered version to be used. Unfortunately, this + // will result in users who have modified some of their preferences not being + // able to get the benefits of prerendering. + validation: ["showTopSites", "showSearch", "topSitesRows", "collapseTopSites", "section.highlights.collapsed", "section.topstories.collapsed", "enableWideLayout", "sectionOrder", + // This means if either of these are set to their default values, + // prerendering can be used. + { oneOf: ["feeds.section.topstories", "feeds.section.highlights"] }], + initialSections: [{ + enabled: true, + icon: "pocket", + id: "topstories", + order: 1, + title: { id: "header_recommended_by", values: { provider: "Pocket" } } + }, { + enabled: true, + id: "highlights", + icon: "highlights", + order: 2, + title: { id: "header_highlights" } + }] +}); +// EXTERNAL MODULE: ./system-addon/content-src/lib/constants.js +var constants = __webpack_require__(17); + +// CONCATENATED MODULE: ./system-addon/content-src/components/Search/Search.jsx +/* globals ContentSearchUIController */ + + + + + + + + +class Search__Search extends external__React__default.a.PureComponent { + constructor(props) { + super(props); + this.onClick = this.onClick.bind(this); + this.onInputMount = this.onInputMount.bind(this); + } + + handleEvent(event) { + // Also track search events with our own telemetry + if (event.detail.type === "Search") { + this.props.dispatch(Actions["a" /* actionCreators */].UserEvent({ event: "SEARCH" })); + } + } + + onClick(event) { + window.gContentSearchController.search(event); + } + + componentWillUnmount() { + delete window.gContentSearchController; + } + + onInputMount(input) { + if (input) { + // The "healthReportKey" and needs to be "newtab" or "abouthome" so that + // BrowserUsageTelemetry.jsm knows to handle events with this name, and + // can add the appropriate telemetry probes for search. Without the correct + // name, certain tests like browser_UsageTelemetry_content.js will fail + // (See github ticket #2348 for more details) + const healthReportKey = constants["a" /* IS_NEWTAB */] ? "newtab" : "abouthome"; + + // The "searchSource" needs to be "newtab" or "homepage" and is sent with + // the search data and acts as context for the search request (See + // nsISearchEngine.getSubmission). It is necessary so that search engine + // plugins can correctly atribute referrals. (See github ticket #3321 for + // more details) + const searchSource = constants["a" /* IS_NEWTAB */] ? "newtab" : "homepage"; + + // gContentSearchController needs to exist as a global so that tests for + // the existing about:home can find it; and so it allows these tests to pass. + // In the future, when activity stream is default about:home, this can be renamed + window.gContentSearchController = new ContentSearchUIController(input, input.parentNode, healthReportKey, searchSource); + addEventListener("ContentSearchClient", this); + } else { + window.gContentSearchController = null; + removeEventListener("ContentSearchClient", this); + } + } + + /* + * Do not change the ID on the input field, as legacy newtab code + * specifically looks for the id 'newtab-search-text' on input fields + * in order to execute searches in various tests + */ + render() { + return external__React__default.a.createElement( + "div", + { className: "search-wrapper" }, + external__React__default.a.createElement( + "label", + { htmlFor: "newtab-search-text", className: "search-label" }, + external__React__default.a.createElement( + "span", + { className: "sr-only" }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: "search_web_placeholder" }) + ) + ), + external__React__default.a.createElement("input", { + id: "newtab-search-text", + maxLength: "256", + placeholder: this.props.intl.formatMessage({ id: "search_web_placeholder" }), + ref: this.onInputMount, + title: this.props.intl.formatMessage({ id: "search_web_placeholder" }), + type: "search" }), + external__React__default.a.createElement( + "button", + { + id: "searchSubmit", + className: "search-button", + onClick: this.onClick, + title: this.props.intl.formatMessage({ id: "search_button" }) }, + external__React__default.a.createElement( + "span", + { className: "sr-only" }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: "search_button" }) + ) + ) + ); + } +} + +const Search = Object(external__ReactRedux_["connect"])()(Object(external__ReactIntl_["injectIntl"])(Search__Search)); +// EXTERNAL MODULE: ./system-addon/content-src/components/Sections/Sections.jsx +var Sections = __webpack_require__(18); + +// CONCATENATED MODULE: ./system-addon/content-src/components/Base/Base.jsx + + + + + + + + + + + + +// Add the locale data for pluralization and relative-time formatting for now, +// this just uses english locale data. We can make this more sophisticated if +// more features are needed. +function addLocaleDataForReactIntl(locale) { + Object(external__ReactIntl_["addLocaleData"])([{ locale, parentLocale: "en" }]); +} + +class Base__Base extends external__React__default.a.PureComponent { + componentWillMount() { + const { App, locale } = this.props; + this.sendNewTabRehydrated(App); + addLocaleDataForReactIntl(locale); + } + + componentDidMount() { + // Request state AFTER the first render to ensure we don't cause the + // prerendered DOM to be unmounted. Otherwise, NEW_TAB_STATE_REQUEST is + // dispatched right after the store is ready. + if (this.props.isPrerendered) { + this.props.dispatch(Actions["a" /* actionCreators */].AlsoToMain({ type: Actions["b" /* actionTypes */].NEW_TAB_STATE_REQUEST })); + this.props.dispatch(Actions["a" /* actionCreators */].AlsoToMain({ type: Actions["b" /* actionTypes */].PAGE_PRERENDERED })); + } + } + + componentWillUpdate({ App }) { + this.sendNewTabRehydrated(App); + } + + // The NEW_TAB_REHYDRATED event is used to inform feeds that their + // data has been consumed e.g. for counting the number of tabs that + // have rendered that data. + sendNewTabRehydrated(App) { + if (App && App.initialized && !this.renderNotified) { + this.props.dispatch(Actions["a" /* actionCreators */].AlsoToMain({ type: Actions["b" /* actionTypes */].NEW_TAB_REHYDRATED, data: {} })); + this.renderNotified = true; + } + } + + render() { + const { props } = this; + const { App, locale, strings } = props; + const { initialized } = App; + + if (!props.isPrerendered && !initialized) { + return null; + } + + return external__React__default.a.createElement( + external__ReactIntl_["IntlProvider"], + { locale: locale, messages: strings }, + external__React__default.a.createElement( + ErrorBoundary["a" /* ErrorBoundary */], + { className: "base-content-fallback" }, + external__React__default.a.createElement(Base_BaseContent, this.props) + ) + ); + } +} +/* unused harmony export _Base */ + + +class Base_BaseContent extends external__React__default.a.PureComponent { + render() { + const { props } = this; + const { App } = props; + const { initialized } = App; + const prefs = props.Prefs.values; + + const shouldBeFixedToTop = PrerenderData.arePrefsValid(name => prefs[name]); + + const outerClassName = `outer-wrapper${shouldBeFixedToTop ? " fixed-to-top" : ""} ${prefs.enableWideLayout ? "wide-layout-enabled" : "wide-layout-disabled"}`; + + return external__React__default.a.createElement( + "div", + { className: outerClassName }, + external__React__default.a.createElement( + "main", + null, + prefs.showSearch && external__React__default.a.createElement( + "div", + { className: "non-collapsible-section" }, + external__React__default.a.createElement( + ErrorBoundary["a" /* ErrorBoundary */], + null, + external__React__default.a.createElement(Search, null) + ) + ), + external__React__default.a.createElement( + "div", + { className: `body-wrapper${initialized ? " on" : ""}` }, + !prefs.migrationExpired && external__React__default.a.createElement( + "div", + { className: "non-collapsible-section" }, + external__React__default.a.createElement(ManualMigration, null) + ), + external__React__default.a.createElement(Sections["a" /* Sections */], null) + ), + external__React__default.a.createElement(ConfirmDialog, null) + ), + initialized && external__React__default.a.createElement( + "div", + { className: "prefs-pane" }, + external__React__default.a.createElement( + ErrorBoundary["a" /* ErrorBoundary */], + { className: "sidebar" }, + " ", + external__React__default.a.createElement(PreferencesPane, null), + " " + ) + ) + ); + } +} +/* unused harmony export BaseContent */ + + +const Base = Object(external__ReactRedux_["connect"])(state => ({ App: state.App, Prefs: state.Prefs }))(Base__Base); +/* harmony export (immutable) */ __webpack_exports__["a"] = Base; + + +/***/ }), +/* 17 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {const IS_NEWTAB = global.document && global.document.documentURI === "about:newtab"; +/* harmony export (immutable) */ __webpack_exports__["a"] = IS_NEWTAB; + +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3))) + +/***/ }), +/* 18 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_content_src_components_Card_Card__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_react_intl__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_react_intl___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react_intl__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_common_Actions_jsm__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_content_src_components_CollapsibleSection_CollapsibleSection__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_content_src_components_ComponentPerfTimer_ComponentPerfTimer__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_react_redux__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_react_redux___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react_redux__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_react__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_react__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_content_src_components_Topics_Topics__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_content_src_components_TopSites_TopSites__ = __webpack_require__(22); +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + + + + + + + + + + + +const VISIBLE = "visible"; +const VISIBILITY_CHANGE_EVENT = "visibilitychange"; +const CARDS_PER_ROW = 3; + +function getFormattedMessage(message) { + return typeof message === "string" ? __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + "span", + null, + message + ) : __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_1_react_intl__["FormattedMessage"], message); +} + +class Section extends __WEBPACK_IMPORTED_MODULE_6_react___default.a.PureComponent { + _dispatchImpressionStats() { + const { props } = this; + const maxCards = 3 * props.maxRows; + const cards = props.rows.slice(0, maxCards); + + if (this.needsImpressionStats(cards)) { + props.dispatch(__WEBPACK_IMPORTED_MODULE_2_common_Actions_jsm__["a" /* actionCreators */].ImpressionStats({ + source: props.eventSource, + tiles: cards.map(link => ({ id: link.guid })) + })); + this.impressionCardGuids = cards.map(link => link.guid); + } + } + + // This sends an event when a user sees a set of new content. If content + // changes while the page is hidden (i.e. preloaded or on a hidden tab), + // only send the event if the page becomes visible again. + sendImpressionStatsOrAddListener() { + const { props } = this; + + if (!props.shouldSendImpressionStats || !props.dispatch) { + return; + } + + if (props.document.visibilityState === VISIBLE) { + this._dispatchImpressionStats(); + } else { + // We should only ever send the latest impression stats ping, so remove any + // older listeners. + if (this._onVisibilityChange) { + props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange); + } + + // When the page becomes visible, send the impression stats ping if the section isn't collapsed. + this._onVisibilityChange = () => { + if (props.document.visibilityState === VISIBLE) { + const { id, Prefs } = this.props; + const isCollapsed = Prefs.values[`section.${id}.collapsed`]; + if (!isCollapsed) { + this._dispatchImpressionStats(); + } + props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange); + } + }; + props.document.addEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange); + } + } + + componentDidMount() { + const { id, rows, Prefs } = this.props; + const isCollapsed = Prefs.values[`section.${id}.collapsed`]; + if (rows.length && !isCollapsed) { + this.sendImpressionStatsOrAddListener(); + } + } + + componentDidUpdate(prevProps) { + const { props } = this; + const { id, Prefs } = props; + const isCollapsedPref = `section.${id}.collapsed`; + const isCollapsed = Prefs.values[isCollapsedPref]; + const wasCollapsed = prevProps.Prefs.values[isCollapsedPref]; + if ( + // Don't send impression stats for the empty state + props.rows.length && ( + // We only want to send impression stats if the content of the cards has changed + // and the section is not collapsed... + props.rows !== prevProps.rows && !isCollapsed || + // or if we are expanding a section that was collapsed. + wasCollapsed && !isCollapsed)) { + this.sendImpressionStatsOrAddListener(); + } + } + + componentWillUnmount() { + if (this._onVisibilityChange) { + this.props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange); + } + } + + needsImpressionStats(cards) { + if (!this.impressionCardGuids || this.impressionCardGuids.length !== cards.length) { + return true; + } + + for (let i = 0; i < cards.length; i++) { + if (cards[i].guid !== this.impressionCardGuids[i]) { + return true; + } + } + + return false; + } + + numberOfPlaceholders(items) { + if (items === 0) { + return CARDS_PER_ROW; + } + const remainder = items % CARDS_PER_ROW; + if (remainder === 0) { + return 0; + } + return CARDS_PER_ROW - remainder; + } + + render() { + const { + id, eventSource, title, icon, rows, + emptyState, dispatch, maxRows, + contextMenuOptions, initialized, disclaimer, + pref, privacyNoticeURL, isFirst, isLast + } = this.props; + const maxCards = CARDS_PER_ROW * maxRows; + + // Show topics only for top stories and if it's not initialized yet (so + // content doesn't shift when it is loaded) or has loaded with topics + const shouldShowTopics = id === "topstories" && (!this.props.topics || this.props.topics.length > 0); + + const realRows = rows.slice(0, maxCards); + const placeholders = this.numberOfPlaceholders(realRows.length); + + // The empty state should only be shown after we have initialized and there is no content. + // Otherwise, we should show placeholders. + const shouldShowEmptyState = initialized && !rows.length; + + //
<-- React component + //
<-- HTML5 element + return __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + __WEBPACK_IMPORTED_MODULE_4_content_src_components_ComponentPerfTimer_ComponentPerfTimer__["a" /* ComponentPerfTimer */], + this.props, + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + __WEBPACK_IMPORTED_MODULE_3_content_src_components_CollapsibleSection_CollapsibleSection__["a" /* CollapsibleSection */], + { className: "section", icon: icon, + title: getFormattedMessage(title), + id: id, + eventSource: eventSource, + disclaimer: disclaimer, + prefName: `section.${id}.collapsed`, + showPrefName: pref && pref.feed || id, + privacyNoticeURL: privacyNoticeURL, + Prefs: this.props.Prefs, + isFirst: isFirst, + isLast: isLast, + dispatch: this.props.dispatch }, + !shouldShowEmptyState && __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + "ul", + { className: "section-list", style: { padding: 0 } }, + realRows.map((link, index) => link && __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_0_content_src_components_Card_Card__["a" /* Card */], { key: index, index: index, dispatch: dispatch, link: link, contextMenuOptions: contextMenuOptions, + eventSource: eventSource, shouldSendImpressionStats: this.props.shouldSendImpressionStats, isWebExtension: this.props.isWebExtension })), + placeholders > 0 && [...new Array(placeholders)].map((_, i) => __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_0_content_src_components_Card_Card__["b" /* PlaceholderCard */], { key: i })) + ), + shouldShowEmptyState && __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + "div", + { className: "section-empty-state" }, + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + "div", + { className: "empty-state" }, + emptyState.icon && emptyState.icon.startsWith("moz-extension://") ? __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement("img", { className: "empty-state-icon icon", style: { "background-image": `url('${emptyState.icon}')` } }) : __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement("img", { className: `empty-state-icon icon icon-${emptyState.icon}` }), + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + "p", + { className: "empty-state-message" }, + getFormattedMessage(emptyState.message) + ) + ) + ), + shouldShowTopics && __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_7_content_src_components_Topics_Topics__["a" /* Topics */], { topics: this.props.topics, read_more_endpoint: this.props.read_more_endpoint }) + ) + ); + } +} +/* unused harmony export Section */ + + +Section.defaultProps = { + document: global.document, + rows: [], + emptyState: {}, + title: "" +}; + +const SectionIntl = Object(__WEBPACK_IMPORTED_MODULE_5_react_redux__["connect"])(state => ({ Prefs: state.Prefs }))(Object(__WEBPACK_IMPORTED_MODULE_1_react_intl__["injectIntl"])(Section)); +/* unused harmony export SectionIntl */ + + +class _Sections extends __WEBPACK_IMPORTED_MODULE_6_react___default.a.PureComponent { + renderSections() { + const sections = []; + const enabledSections = this.props.Sections.filter(section => section.enabled); + const { sectionOrder, showTopSites } = this.props.Prefs.values; + // Enabled sections doesn't include Top Sites, so we add it if enabled. + const expectedCount = enabledSections.length + ~~showTopSites; + + for (const sectionId of sectionOrder.split(",")) { + const commonProps = { + key: sectionId, + isFirst: sections.length === 0, + isLast: sections.length === expectedCount - 1 + }; + if (sectionId === "topsites" && showTopSites) { + sections.push(__WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_8_content_src_components_TopSites_TopSites__["a" /* TopSites */], commonProps)); + } else { + const section = enabledSections.find(s => s.id === sectionId); + if (section) { + sections.push(__WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(SectionIntl, _extends({}, section, commonProps))); + } + } + } + return sections; + } + + render() { + return __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + "div", + { className: "sections-list" }, + this.renderSections() + ); + } +} +/* unused harmony export _Sections */ + + +const Sections = Object(__WEBPACK_IMPORTED_MODULE_5_react_redux__["connect"])(state => ({ Sections: state.Sections, Prefs: state.Prefs }))(_Sections); +/* harmony export (immutable) */ __webpack_exports__["a"] = Sections; + +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3))) + +/***/ }), +/* 19 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./system-addon/common/Actions.jsm +var Actions = __webpack_require__(0); + +// CONCATENATED MODULE: ./system-addon/content-src/components/Card/types.js +const cardContextTypes = { + history: { + intlID: "type_label_visited", + icon: "historyItem" + }, + bookmark: { + intlID: "type_label_bookmarked", + icon: "bookmark-added" + }, + trending: { + intlID: "type_label_recommended", + icon: "trending" + }, + now: { + intlID: "type_label_now", + icon: "now" + }, + pocket: { + intlID: "type_label_pocket", + icon: "pocket-small" + } +}; +// EXTERNAL MODULE: external "ReactIntl" +var external__ReactIntl_ = __webpack_require__(2); +var external__ReactIntl__default = /*#__PURE__*/__webpack_require__.n(external__ReactIntl_); + +// EXTERNAL MODULE: ./system-addon/content-src/components/LinkMenu/LinkMenu.jsx + 1 modules +var LinkMenu = __webpack_require__(8); + +// EXTERNAL MODULE: external "React" +var external__React_ = __webpack_require__(1); +var external__React__default = /*#__PURE__*/__webpack_require__.n(external__React_); + +// CONCATENATED MODULE: ./system-addon/content-src/components/Card/Card.jsx + + + + + + +// Keep track of pending image loads to only request once +const gImageLoading = new Map(); + +/** + * Card component. + * Cards are found within a Section component and contain information about a link such + * as preview image, page title, page description, and some context about if the page + * was visited, bookmarked, trending etc... + * Each Section can make an unordered list of Cards which will create one instane of + * this class. Each card will then get a context menu which reflects the actions that + * can be done on this Card. + */ +class Card_Card extends external__React__default.a.PureComponent { + constructor(props) { + super(props); + this.state = { + activeCard: null, + imageLoaded: false, + showContextMenu: false + }; + this.onMenuButtonClick = this.onMenuButtonClick.bind(this); + this.onMenuUpdate = this.onMenuUpdate.bind(this); + this.onLinkClick = this.onLinkClick.bind(this); + } + + /** + * Helper to conditionally load an image and update state when it loads. + */ + async maybeLoadImage() { + // No need to load if it's already loaded or no image + const { image } = this.props.link; + if (!this.state.imageLoaded && image) { + // Initialize a promise to share a load across multiple card updates + if (!gImageLoading.has(image)) { + const loaderPromise = new Promise((resolve, reject) => { + const loader = new Image(); + loader.addEventListener("load", resolve); + loader.addEventListener("error", reject); + loader.src = image; + }); + + // Save and remove the promise only while it's pending + gImageLoading.set(image, loaderPromise); + loaderPromise.catch(ex => ex).then(() => gImageLoading.delete(image)).catch(); + } + + // Wait for the image whether just started loading or reused promise + await gImageLoading.get(image); + + // Only update state if we're still waiting to load the original image + if (this.props.link.image === image && !this.state.imageLoaded) { + this.setState({ imageLoaded: true }); + } + } + } + + onMenuButtonClick(event) { + event.preventDefault(); + this.setState({ + activeCard: this.props.index, + showContextMenu: true + }); + } + + /** + * Report to telemetry additional information about the item. + */ + _getTelemetryInfo() { + // Filter out "history" type for being the default + if (this.props.link.type !== "history") { + return { value: { card_type: this.props.link.type } }; + } + + return null; + } + + onLinkClick(event) { + event.preventDefault(); + const { altKey, button, ctrlKey, metaKey, shiftKey } = event; + this.props.dispatch(Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].OPEN_LINK, + data: Object.assign(this.props.link, { event: { altKey, button, ctrlKey, metaKey, shiftKey } }) + })); + + if (this.props.isWebExtension) { + this.props.dispatch(Actions["a" /* actionCreators */].WebExtEvent(Actions["b" /* actionTypes */].WEBEXT_CLICK, { + source: this.props.eventSource, + url: this.props.link.url, + action_position: this.props.index + })); + } else { + this.props.dispatch(Actions["a" /* actionCreators */].UserEvent(Object.assign({ + event: "CLICK", + source: this.props.eventSource, + action_position: this.props.index + }, this._getTelemetryInfo()))); + + if (this.props.shouldSendImpressionStats) { + this.props.dispatch(Actions["a" /* actionCreators */].ImpressionStats({ + source: this.props.eventSource, + click: 0, + tiles: [{ id: this.props.link.guid, pos: this.props.index }] + })); + } + } + } + + onMenuUpdate(showContextMenu) { + this.setState({ showContextMenu }); + } + + componentDidMount() { + this.maybeLoadImage(); + } + + componentDidUpdate() { + this.maybeLoadImage(); + } + + componentWillReceiveProps(nextProps) { + // Clear the image state if changing images + if (nextProps.link.image !== this.props.link.image) { + this.setState({ imageLoaded: false }); + } + } + + render() { + const { index, link, dispatch, contextMenuOptions, eventSource, shouldSendImpressionStats } = this.props; + const { props } = this; + const isContextMenuOpen = this.state.showContextMenu && this.state.activeCard === index; + // Display "now" as "trending" until we have new strings #3402 + const { icon, intlID } = cardContextTypes[link.type === "now" ? "trending" : link.type] || {}; + const hasImage = link.image || link.hasImage; + const imageStyle = { backgroundImage: link.image ? `url(${link.image})` : "none" }; + + return external__React__default.a.createElement( + "li", + { className: `card-outer${isContextMenuOpen ? " active" : ""}${props.placeholder ? " placeholder" : ""}` }, + external__React__default.a.createElement( + "a", + { href: link.type === "pocket" ? link.open_url : link.url, onClick: !props.placeholder ? this.onLinkClick : undefined }, + external__React__default.a.createElement( + "div", + { className: "card" }, + hasImage && external__React__default.a.createElement( + "div", + { className: "card-preview-image-outer" }, + external__React__default.a.createElement("div", { className: `card-preview-image${this.state.imageLoaded ? " loaded" : ""}`, style: imageStyle }) + ), + external__React__default.a.createElement( + "div", + { className: `card-details${hasImage ? "" : " no-image"}` }, + link.hostname && external__React__default.a.createElement( + "div", + { className: "card-host-name" }, + link.hostname + ), + external__React__default.a.createElement( + "div", + { className: ["card-text", icon ? "" : "no-context", link.description ? "" : "no-description", link.hostname ? "" : "no-host-name", hasImage ? "" : "no-image"].join(" ") }, + external__React__default.a.createElement( + "h4", + { className: "card-title", dir: "auto" }, + link.title + ), + external__React__default.a.createElement( + "p", + { className: "card-description", dir: "auto" }, + link.description + ) + ), + external__React__default.a.createElement( + "div", + { className: "card-context" }, + icon && !link.context && external__React__default.a.createElement("span", { className: `card-context-icon icon icon-${icon}` }), + link.icon && link.context && external__React__default.a.createElement("span", { className: "card-context-icon icon", style: { backgroundImage: `url('${link.icon}')` } }), + intlID && !link.context && external__React__default.a.createElement( + "div", + { className: "card-context-label" }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: intlID, defaultMessage: "Visited" }) + ), + link.context && external__React__default.a.createElement( + "div", + { className: "card-context-label" }, + link.context + ) + ) + ) + ) + ), + !props.placeholder && external__React__default.a.createElement( + "button", + { className: "context-menu-button icon", + onClick: this.onMenuButtonClick }, + external__React__default.a.createElement( + "span", + { className: "sr-only" }, + `Open context menu for ${link.title}` + ) + ), + isContextMenuOpen && external__React__default.a.createElement(LinkMenu["a" /* LinkMenu */], { + dispatch: dispatch, + index: index, + source: eventSource, + onUpdate: this.onMenuUpdate, + options: link.contextMenuOptions || contextMenuOptions, + site: link, + siteInfo: this._getTelemetryInfo(), + shouldSendImpressionStats: shouldSendImpressionStats }) + ); + } +} +/* harmony export (immutable) */ __webpack_exports__["a"] = Card_Card; + +Card_Card.defaultProps = { link: {} }; + +const PlaceholderCard = () => external__React__default.a.createElement(Card_Card, { placeholder: true }); +/* harmony export (immutable) */ __webpack_exports__["b"] = PlaceholderCard; + + +/***/ }), +/* 20 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./system-addon/common/Actions.jsm +var Actions = __webpack_require__(0); + +// EXTERNAL MODULE: ./system-addon/content-src/components/ContextMenu/ContextMenu.jsx +var ContextMenu = __webpack_require__(9); + +// EXTERNAL MODULE: external "ReactIntl" +var external__ReactIntl_ = __webpack_require__(2); +var external__ReactIntl__default = /*#__PURE__*/__webpack_require__.n(external__ReactIntl_); + +// EXTERNAL MODULE: external "React" +var external__React_ = __webpack_require__(1); +var external__React__default = /*#__PURE__*/__webpack_require__.n(external__React_); + +// CONCATENATED MODULE: ./system-addon/content-src/lib/section-menu-options.js + + +/** + * List of functions that return items that can be included as menu options in a + * SectionMenu. All functions take the section as the only parameter. + */ +const SectionMenuOptions = { + Separator: () => ({ type: "separator" }), + MoveUp: section => ({ + id: "section_menu_action_move_up", + icon: "arrowhead-up", + action: Actions["a" /* actionCreators */].OnlyToMain({ + type: Actions["b" /* actionTypes */].SECTION_MOVE, + data: { id: section.id, direction: -1 } + }), + userEvent: "SECTION_MENU_MOVE_UP", + disabled: !!section.isFirst + }), + MoveDown: section => ({ + id: "section_menu_action_move_down", + icon: "arrowhead-down", + action: Actions["a" /* actionCreators */].OnlyToMain({ + type: Actions["b" /* actionTypes */].SECTION_MOVE, + data: { id: section.id, direction: +1 } + }), + userEvent: "SECTION_MENU_MOVE_DOWN", + disabled: !!section.isLast + }), + RemoveSection: section => ({ + id: "section_menu_action_remove_section", + icon: "dismiss", + action: Actions["a" /* actionCreators */].SetPref(section.showPrefName, false), + userEvent: "SECTION_MENU_REMOVE" + }), + CollapseSection: section => ({ + id: "section_menu_action_collapse_section", + icon: "minimize", + action: Actions["a" /* actionCreators */].SetPref(section.collapsePrefName, true), + userEvent: "SECTION_MENU_COLLAPSE" + }), + ExpandSection: section => ({ + id: "section_menu_action_expand_section", + icon: "maximize", + action: Actions["a" /* actionCreators */].SetPref(section.collapsePrefName, false), + userEvent: "SECTION_MENU_EXPAND" + }), + ManageSection: section => ({ + id: "section_menu_action_manage_section", + icon: "settings", + action: { type: Actions["b" /* actionTypes */].SETTINGS_OPEN }, + userEvent: "SECTION_MENU_MANAGE" + }), + AddTopSite: section => ({ + id: "section_menu_action_add_topsite", + icon: "add", + action: { type: Actions["b" /* actionTypes */].TOP_SITES_EDIT, data: { index: -1 } }, + userEvent: "SECTION_MENU_ADD_TOPSITE" + }), + PrivacyNotice: section => ({ + id: "section_menu_action_privacy_notice", + icon: "info", + action: Actions["a" /* actionCreators */].OnlyToMain({ + type: Actions["b" /* actionTypes */].OPEN_LINK, + data: { url: section.privacyNoticeURL } + }), + userEvent: "SECTION_MENU_PRIVACY_NOTICE" + }), + CheckCollapsed: section => section.isCollapsed ? SectionMenuOptions.ExpandSection(section) : SectionMenuOptions.CollapseSection(section) +}; +// CONCATENATED MODULE: ./system-addon/content-src/components/SectionMenu/SectionMenu.jsx + + + + + + +const DEFAULT_SECTION_MENU_OPTIONS = ["MoveUp", "MoveDown", "Separator", "RemoveSection", "CheckCollapsed", "Separator", "ManageSection"]; + +class SectionMenu__SectionMenu extends external__React__default.a.PureComponent { + getOptions() { + const { props } = this; + + const propOptions = Array.from(DEFAULT_SECTION_MENU_OPTIONS); + // Prepend custom options and a separator + if (props.extraOptions) { + propOptions.splice(0, 0, ...props.extraOptions, "Separator"); + } + // Insert privacy notice before the last option ("ManageSection") + if (props.privacyNoticeURL) { + propOptions.splice(-1, 0, "PrivacyNotice"); + } + + const options = propOptions.map(o => SectionMenuOptions[o](props)).map(option => { + const { action, id, type, userEvent } = option; + if (!type && id) { + option.label = props.intl.formatMessage({ id }); + option.onClick = () => { + props.dispatch(action); + if (userEvent) { + props.dispatch(Actions["a" /* actionCreators */].UserEvent({ + event: userEvent, + source: props.source + })); + } + }; + } + return option; + }); + + // This is for accessibility to support making each item tabbable. + // We want to know which item is the first and which item + // is the last, so we can close the context menu accordingly. + options[0].first = true; + options[options.length - 1].last = true; + return options; + } + + render() { + return external__React__default.a.createElement(ContextMenu["a" /* ContextMenu */], { + onUpdate: this.props.onUpdate, + options: this.getOptions() }); + } +} +/* unused harmony export _SectionMenu */ + + +const SectionMenu = Object(external__ReactIntl_["injectIntl"])(SectionMenu__SectionMenu); +/* harmony export (immutable) */ __webpack_exports__["a"] = SectionMenu; + + +/***/ }), +/* 21 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react_intl__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react_intl___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react_intl__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__); + + + +class Topic extends __WEBPACK_IMPORTED_MODULE_1_react___default.a.PureComponent { + render() { + const { url, name } = this.props; + return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "li", + null, + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "a", + { key: name, className: "topic-link", href: url }, + name + ) + ); + } +} +/* unused harmony export Topic */ + + +class Topics extends __WEBPACK_IMPORTED_MODULE_1_react___default.a.PureComponent { + render() { + const { topics, read_more_endpoint } = this.props; + return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "div", + { className: "topic" }, + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "span", + null, + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_0_react_intl__["FormattedMessage"], { id: "pocket_read_more" }) + ), + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "ul", + null, + topics && topics.map(t => __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement(Topic, { key: t.name, url: t.url, name: t.name })) + ), + read_more_endpoint && __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement( + "a", + { className: "topic-read-more", href: read_more_endpoint }, + __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_0_react_intl__["FormattedMessage"], { id: "pocket_read_even_more" }) + ) + ); + } +} +/* harmony export (immutable) */ __webpack_exports__["a"] = Topics; + + +/***/ }), +/* 22 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__TopSitesConstants__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_content_src_components_CollapsibleSection_CollapsibleSection__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_content_src_components_ComponentPerfTimer_ComponentPerfTimer__ = __webpack_require__(11); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_react_redux__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_react_redux___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react_redux__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_react_intl__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_react_intl___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react_intl__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_react__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_react__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_common_Reducers_jsm__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__TopSiteForm__ = __webpack_require__(23); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__TopSite__ = __webpack_require__(13); + + + + + + + + + + + +function topSiteIconType(link) { + if (link.tippyTopIcon || link.faviconRef === "tippytop") { + return "tippytop"; + } + if (link.faviconSize >= __WEBPACK_IMPORTED_MODULE_1__TopSitesConstants__["b" /* MIN_RICH_FAVICON_SIZE */]) { + return "rich_icon"; + } + if (link.screenshot && link.faviconSize >= __WEBPACK_IMPORTED_MODULE_1__TopSitesConstants__["a" /* MIN_CORNER_FAVICON_SIZE */]) { + return "screenshot_with_icon"; + } + if (link.screenshot) { + return "screenshot"; + } + return "no_image"; +} + +/** + * Iterates through TopSites and counts types of images. + * @param acc Accumulator for reducer. + * @param topsite Entry in TopSites. + */ +function countTopSitesIconsTypes(topSites) { + const countTopSitesTypes = (acc, link) => { + acc[topSiteIconType(link)]++; + return acc; + }; + + return topSites.reduce(countTopSitesTypes, { + "screenshot_with_icon": 0, + "screenshot": 0, + "tippytop": 0, + "rich_icon": 0, + "no_image": 0 + }); +} + +class _TopSites extends __WEBPACK_IMPORTED_MODULE_6_react___default.a.PureComponent { + constructor(props) { + super(props); + this.onFormClose = this.onFormClose.bind(this); + } + + /** + * Dispatch session statistics about the quality of TopSites icons and pinned count. + */ + _dispatchTopSitesStats() { + const topSites = this._getVisibleTopSites(); + const topSitesIconsStats = countTopSitesIconsTypes(topSites); + const topSitesPinned = topSites.filter(site => !!site.isPinned).length; + // Dispatch telemetry event with the count of TopSites images types. + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].AlsoToMain({ + type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].SAVE_SESSION_PERF_DATA, + data: { topsites_icon_stats: topSitesIconsStats, topsites_pinned: topSitesPinned } + })); + } + + /** + * Return the TopSites that are visible based on prefs and window width. + */ + _getVisibleTopSites() { + // We hide 2 sites per row when not in the wide layout. + let sitesPerRow = __WEBPACK_IMPORTED_MODULE_7_common_Reducers_jsm__["a" /* TOP_SITES_MAX_SITES_PER_ROW */]; + // $break-point-widest = 1072px (from _variables.scss) + if (!global.matchMedia(`(min-width: 1072px)`).matches) { + sitesPerRow -= 2; + } + return this.props.TopSites.rows.slice(0, this.props.TopSitesRows * sitesPerRow); + } + + componentDidUpdate() { + this._dispatchTopSitesStats(); + } + + componentDidMount() { + this._dispatchTopSitesStats(); + } + + onFormClose() { + this.props.dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].UserEvent({ + source: __WEBPACK_IMPORTED_MODULE_1__TopSitesConstants__["d" /* TOP_SITES_SOURCE */], + event: "TOP_SITES_EDIT_CLOSE" + })); + this.props.dispatch({ type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].TOP_SITES_CANCEL_EDIT }); + } + + render() { + const { props } = this; + const { editForm } = props.TopSites; + + return __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + __WEBPACK_IMPORTED_MODULE_3_content_src_components_ComponentPerfTimer_ComponentPerfTimer__["a" /* ComponentPerfTimer */], + { id: "topsites", initialized: props.TopSites.initialized, dispatch: props.dispatch }, + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + __WEBPACK_IMPORTED_MODULE_2_content_src_components_CollapsibleSection_CollapsibleSection__["a" /* CollapsibleSection */], + { + className: "top-sites", + icon: "topsites", + id: "topsites", + title: props.intl.formatMessage({ id: "header_top_sites" }), + extraMenuOptions: ["AddTopSite"], + prefName: "collapseTopSites", + showPrefName: "showTopSites", + eventSource: __WEBPACK_IMPORTED_MODULE_1__TopSitesConstants__["d" /* TOP_SITES_SOURCE */], + Prefs: props.Prefs, + isFirst: props.isFirst, + isLast: props.isLast, + dispatch: props.dispatch }, + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_9__TopSite__["b" /* TopSiteList */], { TopSites: props.TopSites, TopSitesRows: props.TopSitesRows, dispatch: props.dispatch, intl: props.intl, topSiteIconType: topSiteIconType }), + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + "div", + { className: "edit-topsites-wrapper" }, + editForm && __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + "div", + { className: "edit-topsites" }, + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement("div", { className: "modal-overlay", onClick: this.onFormClose }), + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement( + "div", + { className: "modal" }, + __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_8__TopSiteForm__["a" /* TopSiteForm */], { + site: props.TopSites.rows[editForm.index], + index: editForm.index, + onClose: this.onFormClose, + dispatch: this.props.dispatch, + intl: this.props.intl }) + ) + ) + ) + ) + ); + } +} +/* unused harmony export _TopSites */ + + +const TopSites = Object(__WEBPACK_IMPORTED_MODULE_4_react_redux__["connect"])(state => ({ + TopSites: state.TopSites, + Prefs: state.Prefs, + TopSitesRows: state.Prefs.values.topSitesRows +}))(Object(__WEBPACK_IMPORTED_MODULE_5_react_intl__["injectIntl"])(_TopSites)); +/* harmony export (immutable) */ __webpack_exports__["a"] = TopSites; + +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3))) + +/***/ }), +/* 23 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./system-addon/common/Actions.jsm +var Actions = __webpack_require__(0); + +// EXTERNAL MODULE: external "ReactIntl" +var external__ReactIntl_ = __webpack_require__(2); +var external__ReactIntl__default = /*#__PURE__*/__webpack_require__.n(external__ReactIntl_); + +// EXTERNAL MODULE: external "React" +var external__React_ = __webpack_require__(1); +var external__React__default = /*#__PURE__*/__webpack_require__.n(external__React_); + +// EXTERNAL MODULE: ./system-addon/content-src/components/TopSites/TopSitesConstants.js +var TopSitesConstants = __webpack_require__(5); + +// CONCATENATED MODULE: ./system-addon/content-src/components/TopSites/TopSiteFormInput.jsx + + + +class TopSiteFormInput_TopSiteFormInput extends external__React__default.a.PureComponent { + constructor(props) { + super(props); + this.onMount = this.onMount.bind(this); + } + + componentWillReceiveProps(nextProps) { + if (nextProps.validationError && !this.props.validationError) { + this.input.focus(); + } + } + + onMount(input) { + this.input = input; + } + + render() { + const showClearButton = this.props.value && this.props.onClear; + const { validationError, typeUrl } = this.props; + + return external__React__default.a.createElement( + "label", + null, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: this.props.titleId }), + external__React__default.a.createElement( + "div", + { className: `field ${typeUrl ? "url" : ""}${validationError ? " invalid" : ""}` }, + showClearButton && external__React__default.a.createElement("div", { className: "icon icon-clear-input", onClick: this.props.onClear }), + external__React__default.a.createElement("input", { type: "text", + value: this.props.value, + ref: this.onMount, + onChange: this.props.onChange, + placeholder: this.props.intl.formatMessage({ id: this.props.placeholderId }) }), + validationError && external__React__default.a.createElement( + "aside", + { className: "error-tooltip" }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: this.props.errorMessageId }) + ) + ) + ); + } +} + +TopSiteFormInput_TopSiteFormInput.defaultProps = { + showClearButton: false, + value: "", + validationError: false +}; +// EXTERNAL MODULE: ./system-addon/content-src/components/TopSites/TopSite.jsx +var TopSite = __webpack_require__(13); + +// CONCATENATED MODULE: ./system-addon/content-src/components/TopSites/TopSiteForm.jsx + + + + + + + +class TopSiteForm_TopSiteForm extends external__React__default.a.PureComponent { + constructor(props) { + super(props); + const { site } = props; + this.state = { + label: site ? site.label || site.hostname : "", + url: site ? site.url : "", + validationError: false + }; + this.onLabelChange = this.onLabelChange.bind(this); + this.onUrlChange = this.onUrlChange.bind(this); + this.onCancelButtonClick = this.onCancelButtonClick.bind(this); + this.onClearUrlClick = this.onClearUrlClick.bind(this); + this.onDoneButtonClick = this.onDoneButtonClick.bind(this); + } + + onLabelChange(event) { + this.setState({ "label": event.target.value }); + } + + onUrlChange(event) { + this.setState({ + url: event.target.value, + validationError: false + }); + } + + onClearUrlClick() { + this.setState({ + url: "", + validationError: false + }); + } + + onCancelButtonClick(ev) { + ev.preventDefault(); + this.props.onClose(); + } + + onDoneButtonClick(ev) { + ev.preventDefault(); + + if (this.validateForm()) { + const site = { url: this.cleanUrl(this.state.url) }; + const { index } = this.props; + if (this.state.label !== "") { + site.label = this.state.label; + } + + this.props.dispatch(Actions["a" /* actionCreators */].AlsoToMain({ + type: Actions["b" /* actionTypes */].TOP_SITES_PIN, + data: { site, index } + })); + this.props.dispatch(Actions["a" /* actionCreators */].UserEvent({ + source: TopSitesConstants["d" /* TOP_SITES_SOURCE */], + event: "TOP_SITES_EDIT", + action_position: index + })); + + this.props.onClose(); + } + } + + cleanUrl(url) { + // If we are missing a protocol, prepend http:// + if (!url.startsWith("http:") && !url.startsWith("https:")) { + return `http://${url}`; + } + return url; + } + + validateUrl(url) { + try { + return !!new URL(this.cleanUrl(url)); + } catch (e) { + return false; + } + } + + validateForm() { + const validate = this.validateUrl(this.state.url); + this.setState({ validationError: !validate }); + return validate; + } + + render() { + // For UI purposes, editing without an existing link is "add" + const showAsAdd = !this.props.site; + + return external__React__default.a.createElement( + "form", + { className: "topsite-form" }, + external__React__default.a.createElement( + "div", + { className: "form-input-container" }, + external__React__default.a.createElement( + "h3", + { className: "section-title" }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: showAsAdd ? "topsites_form_add_header" : "topsites_form_edit_header" }) + ), + external__React__default.a.createElement( + "div", + { className: "fields-and-preview" }, + external__React__default.a.createElement( + "div", + { className: "form-wrapper" }, + external__React__default.a.createElement(TopSiteFormInput_TopSiteFormInput, { onChange: this.onLabelChange, + value: this.state.label, + titleId: "topsites_form_title_label", + placeholderId: "topsites_form_title_placeholder", + intl: this.props.intl }), + external__React__default.a.createElement(TopSiteFormInput_TopSiteFormInput, { onChange: this.onUrlChange, + value: this.state.url, + onClear: this.onClearUrlClick, + validationError: this.state.validationError, + titleId: "topsites_form_url_label", + typeUrl: true, + placeholderId: "topsites_form_url_placeholder", + errorMessageId: "topsites_form_url_validation", + intl: this.props.intl }) + ), + external__React__default.a.createElement(TopSite["a" /* TopSiteLink */], { link: this.props.site || {}, title: this.state.label }) + ) + ), + external__React__default.a.createElement( + "section", + { className: "actions" }, + external__React__default.a.createElement( + "button", + { className: "cancel", type: "button", onClick: this.onCancelButtonClick }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: "topsites_form_cancel_button" }) + ), + external__React__default.a.createElement( + "button", + { className: "done", type: "submit", onClick: this.onDoneButtonClick }, + external__React__default.a.createElement(external__ReactIntl_["FormattedMessage"], { id: showAsAdd ? "topsites_form_add_button" : "topsites_form_save_button" }) + ) + ) + ); + } +} +/* harmony export (immutable) */ __webpack_exports__["a"] = TopSiteForm_TopSiteForm; + + +TopSiteForm_TopSiteForm.defaultProps = { + TopSite: null, + index: -1 +}; + +/***/ }), +/* 24 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_common_PerfService_jsm__ = __webpack_require__(12); + + + +const VISIBLE = "visible"; +const VISIBILITY_CHANGE_EVENT = "visibilitychange"; + +class DetectUserSessionStart { + constructor(store, options = {}) { + this._store = store; + // Overrides for testing + this.document = options.document || global.document; + this._perfService = options.perfService || __WEBPACK_IMPORTED_MODULE_1_common_PerfService_jsm__["a" /* perfService */]; + this._onVisibilityChange = this._onVisibilityChange.bind(this); + } + + /** + * sendEventOrAddListener - Notify immediately if the page is already visible, + * or else set up a listener for when visibility changes. + * This is needed for accurate session tracking for telemetry, + * because tabs are pre-loaded. + */ + sendEventOrAddListener() { + if (this.document.visibilityState === VISIBLE) { + // If the document is already visible, to the user, send a notification + // immediately that a session has started. + this._sendEvent(); + } else { + // If the document is not visible, listen for when it does become visible. + this.document.addEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange); + } + } + + /** + * _sendEvent - Sends a message to the main process to indicate the current + * tab is now visible to the user, includes the + * visibility_event_rcvd_ts time in ms from the UNIX epoch. + */ + _sendEvent() { + this._perfService.mark("visibility_event_rcvd_ts"); + + try { + let visibility_event_rcvd_ts = this._perfService.getMostRecentAbsMarkStartByName("visibility_event_rcvd_ts"); + + this._store.dispatch(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].AlsoToMain({ + type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].SAVE_SESSION_PERF_DATA, + data: { visibility_event_rcvd_ts } + })); + } catch (ex) { + // If this failed, it's likely because the `privacy.resistFingerprinting` + // pref is true. We should at least not blow up. + } + } + + /** + * _onVisibilityChange - If the visibility has changed to visible, sends a notification + * and removes the event listener. This should only be called once per tab. + */ + _onVisibilityChange() { + if (this.document.visibilityState === VISIBLE) { + this._sendEvent(); + this.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange); + } + } +} +/* harmony export (immutable) */ __webpack_exports__["a"] = DetectUserSessionStart; + +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3))) + +/***/ }), +/* 25 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* harmony export (immutable) */ __webpack_exports__["a"] = initStore; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_redux__ = __webpack_require__(26); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_redux___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_redux__); +/* eslint-env mozilla/frame-script */ + + + + +const MERGE_STORE_ACTION = "NEW_TAB_INITIAL_STATE"; +/* unused harmony export MERGE_STORE_ACTION */ + +const OUTGOING_MESSAGE_NAME = "ActivityStream:ContentToMain"; +/* unused harmony export OUTGOING_MESSAGE_NAME */ + +const INCOMING_MESSAGE_NAME = "ActivityStream:MainToContent"; +/* unused harmony export INCOMING_MESSAGE_NAME */ + +const EARLY_QUEUED_ACTIONS = [__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].SAVE_SESSION_PERF_DATA, __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].PAGE_PRERENDERED]; +/* unused harmony export EARLY_QUEUED_ACTIONS */ + + +/** + * A higher-order function which returns a reducer that, on MERGE_STORE action, + * will return the action.data object merged into the previous state. + * + * For all other actions, it merely calls mainReducer. + * + * Because we want this to merge the entire state object, it's written as a + * higher order function which takes the main reducer (itself often a call to + * combineReducers) as a parameter. + * + * @param {function} mainReducer reducer to call if action != MERGE_STORE_ACTION + * @return {function} a reducer that, on MERGE_STORE_ACTION action, + * will return the action.data object merged + * into the previous state, and the result + * of calling mainReducer otherwise. + */ +function mergeStateReducer(mainReducer) { + return (prevState, action) => { + if (action.type === MERGE_STORE_ACTION) { + return Object.assign({}, prevState, action.data); + } + + return mainReducer(prevState, action); + }; +} + +/** + * messageMiddleware - Middleware that looks for SentToMain type actions, and sends them if necessary + */ +const messageMiddleware = store => next => action => { + const skipLocal = action.meta && action.meta.skipLocal; + if (__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["c" /* actionUtils */].isSendToMain(action)) { + sendAsyncMessage(OUTGOING_MESSAGE_NAME, action); + } + if (!skipLocal) { + next(action); + } +}; + +const rehydrationMiddleware = store => next => action => { + if (store._didRehydrate) { + return next(action); + } + + const isMergeStoreAction = action.type === MERGE_STORE_ACTION; + const isRehydrationRequest = action.type === __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].NEW_TAB_STATE_REQUEST; + + if (isRehydrationRequest) { + store._didRequestInitialState = true; + return next(action); + } + + if (isMergeStoreAction) { + store._didRehydrate = true; + return next(action); + } + + // If init happened after our request was made, we need to re-request + if (store._didRequestInitialState && action.type === __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].INIT) { + return next(__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["a" /* actionCreators */].AlsoToMain({ type: __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["b" /* actionTypes */].NEW_TAB_STATE_REQUEST })); + } + + if (__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["c" /* actionUtils */].isBroadcastToContent(action) || __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["c" /* actionUtils */].isSendToOneContent(action) || __WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["c" /* actionUtils */].isSendToPreloaded(action)) { + // Note that actions received before didRehydrate will not be dispatched + // because this could negatively affect preloading and the the state + // will be replaced by rehydration anyway. + return null; + } + + return next(action); +}; +/* unused harmony export rehydrationMiddleware */ + + +/** + * This middleware queues up all the EARLY_QUEUED_ACTIONS until it receives + * the first action from main. This is useful for those actions for main which + * require higher reliability, i.e. the action will not be lost in the case + * that it gets sent before the main is ready to receive it. Conversely, any + * actions allowed early are accepted to be ignorable or re-sendable. + */ +const queueEarlyMessageMiddleware = store => next => action => { + if (store._receivedFromMain) { + next(action); + } else if (__WEBPACK_IMPORTED_MODULE_0_common_Actions_jsm__["c" /* actionUtils */].isFromMain(action)) { + next(action); + store._receivedFromMain = true; + // Sending out all the early actions as main is ready now + if (store._earlyActionQueue) { + store._earlyActionQueue.forEach(next); + store._earlyActionQueue = []; + } + } else if (EARLY_QUEUED_ACTIONS.includes(action.type)) { + store._earlyActionQueue = store._earlyActionQueue || []; + store._earlyActionQueue.push(action); + } else { + // Let any other type of action go through + next(action); + } +}; +/* unused harmony export queueEarlyMessageMiddleware */ + + +/** + * initStore - Create a store and listen for incoming actions + * + * @param {object} reducers An object containing Redux reducers + * @param {object} intialState (optional) The initial state of the store, if desired + * @return {object} A redux store + */ +function initStore(reducers, initialState) { + const store = Object(__WEBPACK_IMPORTED_MODULE_1_redux__["createStore"])(mergeStateReducer(Object(__WEBPACK_IMPORTED_MODULE_1_redux__["combineReducers"])(reducers)), initialState, global.addMessageListener && Object(__WEBPACK_IMPORTED_MODULE_1_redux__["applyMiddleware"])(rehydrationMiddleware, queueEarlyMessageMiddleware, messageMiddleware)); + + store._didRehydrate = false; + store._didRequestInitialState = false; + + if (global.addMessageListener) { + global.addMessageListener(INCOMING_MESSAGE_NAME, msg => { + try { + store.dispatch(msg.data); + } catch (ex) { + console.error("Content msg:", msg, "Dispatch error: ", ex); // eslint-disable-line no-console + dump(`Content msg: ${JSON.stringify(msg)}\nDispatch error: ${ex}\n${ex.stack}`); + } + }); + } + + return store; +} +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3))) + +/***/ }), +/* 26 */ +/***/ (function(module, exports) { + +module.exports = Redux; + +/***/ }), +/* 27 */ +/***/ (function(module, exports) { + +module.exports = ReactDOM; + +/***/ }) +/******/ ]); +//# sourceMappingURL=activity-stream.bundle.js.map \ No newline at end of file diff -pruN 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/ka/activity-stream-strings.js 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/ka/activity-stream-strings.js --- 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/ka/activity-stream-strings.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/ka/activity-stream-strings.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,94 @@ +// Note - this is a generated file. +window.gActivityStreamStrings = { + "newtab_page_title": "ახალი ჩანართი", + "header_top_sites": "რჩეული საიტები", + "header_highlights": "მნიშვნელოვანი საიტები", + "header_recommended_by": "რეკომენდებულია {provider}-ის მიერ", + "context_menu_button_sr": "კონტექსტური მენიუს გახსნა {title}", + "section_context_menu_button_sr": "გვერდის ნაწილების პარამეტრები", + "type_label_visited": "მონახულებული", + "type_label_bookmarked": "ჩანიშნული", + "type_label_recommended": "პოპულარული", + "type_label_pocket": "შენახულია Pocket-ში", + "menu_action_bookmark": "ჩანიშვნა", + "menu_action_remove_bookmark": "სანიშნებიდან ამოშლა", + "menu_action_open_new_window": "ახალ ფანჯარაში გახსნა", + "menu_action_open_private_window": "ახალ პირად ფანჯარაში გახსნა", + "menu_action_dismiss": "დამალვა", + "menu_action_delete": "ისტორიიდან ამოშლა", + "menu_action_pin": "მიმაგრება", + "menu_action_unpin": "მოხსნა", + "confirm_history_delete_p1": "ნამდვილად გსურთ, ამ გვერდის ყველა ჩანაწერის ისტორიიდან ამოშლა?", + "confirm_history_delete_notice_p2": "ეს ქმედება შეუქცევადია.", + "menu_action_save_to_pocket": "Pocket-ში შენახვა", + "menu_action_delete_pocket": "წაშლა Pocket-იდან", + "menu_action_archive_pocket": "დაარქივება Pocket-ში", + "search_button": "ძიება", + "search_header": "{search_engine_name} საძიებოთი ძიება", + "search_web_placeholder": "ინტერნეტში ძიება", + "section_disclaimer_topstories": "საუკეთესო და საინტერესო სიახლეები ინტერნეტიდან, შერჩეული თქვენ მიერ მონახულებული გვერდების საფუძველზე. Pocket-იდან, რომელიც უკვე Mozilla-ს ნაწილია.", + "section_disclaimer_topstories_linktext": "ნახეთ, როგორ მუშაობს.", + "section_disclaimer_topstories_buttontext": "კარგი, გასაგებია", + "prefs_home_header": "Firefox საწყისი გვერდი", + "prefs_home_description": "აირჩიეთ, თუ რისი გამოჩენა გსურთ Firefox-ის საწყის გვერდზე.", + "prefs_restore_defaults_button": "ნაგულისხმევის აღდგენა", + "prefs_section_rows_option": "{num} რიგად;{num} რიგად", + "prefs_search_header": "საძიებო ველი", + "prefs_topsites_description": "ხშირად მონახულებული საიტები", + "prefs_topstories_description": "High-quality content you might otherwise miss", + "prefs_topstories_show_sponsored_label": "მასალის მომწოდებელი {provider}", + "prefs_topstories_sponsored_learn_more": "იხილეთ ვრცლად", + "prefs_highlights_description": "თქვენ მიერ შენახული ან ბოლოს მონახულებული საიტები", + "prefs_snippets_description": "სიახლეები Mozilla-სა და Firefox-ისგან", + "settings_pane_button_label": "მოირგეთ ახალი ჩანართის გვერდი", + "settings_pane_header": "ახალი ჩანართის პარამეტრები", + "settings_pane_body2": "მიუთითეთ, რისი ხილვა გსურთ ამ გვერდზე.", + "settings_pane_search_header": "ძიება", + "settings_pane_search_body": "ძიება ინტერნეტში ახალი ჩანართიდან.", + "settings_pane_topsites_header": "რჩეული საიტები", + "settings_pane_topsites_body": "წვდომა ხშირად მონახულებულ საიტებთან.", + "settings_pane_topsites_options_showmore": "ორ რიგად ჩვენება", + "settings_pane_highlights_header": "მნიშვნელოვანი საიტები", + "settings_pane_highlights_body2": "მარტივად დაუბრუნდით ბოლოს მონახულებულ, ან ჩანიშნულ გვერდებს.", + "settings_pane_highlights_options_bookmarks": "სანიშნები", + "settings_pane_highlights_options_visited": "მონახულებული საიტები", + "settings_pane_snippets_header": "ცნობები", + "settings_pane_snippets_body": "გაეცანით მოკლე, საინტერესო სიახლეებს Mozilla-სგან, Firefox-ის, ინტერნეტსამყაროს მიღწევებისა და სხვა დასამახსოვრებელი ფაქტების შესახებ.", + "settings_pane_done_button": "მზადაა", + "settings_pane_topstories_options_sponsored": "დარეკლამებული სტატიების ჩვენება", + "edit_topsites_button_text": "ჩასწორება", + "edit_topsites_edit_button": "საიტის ჩასწორება", + "topsites_form_add_header": "ახალი საიტი რჩეულებში", + "topsites_form_edit_header": "რჩეული საიტის ჩასწორება", + "topsites_form_title_label": "დასახელება", + "topsites_form_title_placeholder": "სათაურის შეყვანა", + "topsites_form_url_label": "URL ბმული", + "topsites_form_image_url_label": "სასურველი სურათის URL ბმული", + "topsites_form_url_placeholder": "აკრიფეთ ან ჩასვით URL ბმული", + "topsites_form_use_image_link": "სასურველი სურათის გამოყენება…", + "topsites_form_preview_button": "შეთვალიერება", + "topsites_form_add_button": "დამატება", + "topsites_form_save_button": "შენახვა", + "topsites_form_cancel_button": "გაუქმება", + "topsites_form_url_validation": "საჭიროა მართებული URL", + "topsites_form_image_validation": "სურათი ვერ ჩაიტვირთა. სცადეთ სხვა URL ბმული.", + "pocket_read_more": "პოპულარული თემები:", + "pocket_read_even_more": "მეტი სიახლის ნახვა", + "pocket_description": "გაეცანით ინტერნეტში არსებულ მაღალი ხარისხის მასალას Pocket-ის საშუალებით, რომელიც ახლა უკვე Mozilla-ს ნაწილს წარმოადგენს.", + "highlights_empty_state": "დაიწყეთ გვერდების დათვალიერება და აქ გამოჩნდება თქვენი რჩეული სტატიები, ვიდეოები და ბოლოს მონახულებული, ან ჩანიშნული საიტები.", + "topstories_empty_state": "უკვე ყველაფერი წაკითხული გაქვთ. {provider}-იდან ახალი რჩეული სტატიების მისაღებად, მოგვიანებით შემოიარეთ. თუ ვერ ითმენთ, აირჩიეთ რომელიმე მოთხოვნადი თემა, ახალი საინტერესო სტატიების მოსაძიებლად.", + "manual_migration_explanation2": "გადმოიტანეთ სხვა ბრაუზერებიდან თქვენი სანიშნები, ისტორია და პაროლები Firefox-ში.", + "manual_migration_cancel_button": "არა, გმადლობთ", + "manual_migration_import_button": "ახლავე გადმოტანა", + "error_fallback_default_info": "სამწუხაროდ, შიგთავსის ჩატვირთვისას რაღაც ხარვეზი წარმოიქმნა.", + "error_fallback_default_refresh_suggestion": "განაახლეთ გვერდი და სცადეთ ხელახლა.", + "section_menu_action_remove_section": "ამ ნაწილის მოცილება", + "section_menu_action_collapse_section": "ამ ნაწილის აკეცვა", + "section_menu_action_expand_section": "ამ ნაწილის გაშლა", + "section_menu_action_manage_section": "გვერდის ნაწილების მართვა", + "section_menu_action_add_topsite": "რჩეული საიტის დამატება", + "section_menu_action_move_up": "აწევა", + "section_menu_action_move_down": "ჩამოწევა", + "section_menu_action_privacy_notice": "პირადი მონაცემების დაცვის განაცხადი", + "prefs_topstories_description2": "მნიშვნელოვანი ამბები ინტერნეტ-სამყაროდან, შერჩეული თქვენი ინტერესების მიხედვით" +}; diff -pruN 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/km/activity-stream-strings.js 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/km/activity-stream-strings.js --- 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/km/activity-stream-strings.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/km/activity-stream-strings.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,128 @@ +// Note - this is a generated file. +window.gActivityStreamStrings = { + "newtab_page_title": "ផ្ទាំង​ថ្មី", + "header_top_sites": "វិបសាយ​លើ​គេ", + "header_highlights": "រឿងសំខាន់ៗ", + "header_recommended_by": "បានណែនាំដោយ {provider}", + "context_menu_button_sr": "Open context menu for {title}", + "section_context_menu_button_sr": "Open the section context menu", + "type_label_visited": "បាន​ចូល​មើល", + "type_label_bookmarked": "បាន​ចំណាំ", + "type_label_recommended": "និន្នាការ", + "type_label_pocket": "Saved to Pocket", + "menu_action_bookmark": "ចំណាំ", + "menu_action_remove_bookmark": "លុប​ចំណាំ​ចេញ", + "menu_action_open_new_window": "បើក​នៅ​ក្នុង​បង្អួច​ថ្មី", + "menu_action_open_private_window": "បើក​នៅ​ក្នុង​បង្អួច​ឯកជន​ថ្មី", + "menu_action_dismiss": "បោះបង់ចោល", + "menu_action_delete": "លុប​ពី​ប្រវត្តិ", + "menu_action_pin": "ខ្ទាស់", + "menu_action_unpin": "ដកខ្ទាស់", + "confirm_history_delete_p1": "តើអ្នកប្រាកដថាអ្នកចង់លុបគ្រប់វត្ថុនៃទំព័រនេះពីប្រវត្តិរបស់អ្នកឬ?", + "confirm_history_delete_notice_p2": "សកម្មភាពនេះមិនអាចមិនធ្វើឡើង​វិញបានទេ។", + "menu_action_save_to_pocket": "រក្សាទុកទៅ Pocket", + "menu_action_delete_pocket": "Delete from Pocket", + "menu_action_archive_pocket": "Archive in Pocket", + "search_button": "ស្វែងរក", + "search_header": "{search_engine_name} ស្វែងរក", + "search_web_placeholder": "ស្វែងរក​បណ្ដាញ", + "section_disclaimer_topstories": "The most interesting stories on the web, selected based on what you read. From Pocket, now part of Mozilla.", + "section_disclaimer_topstories_linktext": "Learn how it works.", + "section_disclaimer_topstories_buttontext": "យល់​ហើយ", + "prefs_home_header": "Firefox Home Content", + "prefs_home_description": "Choose what content you want on your Firefox Home screen.", + "prefs_restore_defaults_button": "Restore Defaults", + "prefs_section_rows_option": "{num} row;{num} rows", + "prefs_search_header": "Web Search", + "prefs_topsites_description": "The sites you visit most", + "prefs_topstories_description": "High-quality content you might otherwise miss", + "prefs_topstories_show_sponsored_label": "{provider} Sponsored Stories", + "prefs_topstories_sponsored_learn_more": "Learn more", + "prefs_highlights_description": "A selection of sites that you’ve saved or visited", + "prefs_snippets_description": "Updates from Mozilla and Firefox", + "settings_pane_button_label": "Customize your New Tab page", + "settings_pane_header": "ចំណង់ចំណូលចិត្ត ផ្ទាំងថ្មី", + "settings_pane_body2": "ជ្រើសរើសអ្វីដែលអ្នកឃើញនៅលើទំព័រនេះ។", + "settings_pane_search_header": "ស្វែងរក", + "settings_pane_search_body": "ស្វែងរកបណ្តាញពីផ្ទាំងថ្មីរបស់អ្នក។", + "settings_pane_topsites_header": "សាយកំពូល", + "settings_pane_topsites_body": "ចូលវេបសាយដែលអ្នកទស្សនាច្រើនបំផុត។", + "settings_pane_topsites_options_showmore": "បង្ហាញជួរដេកពីរ", + "settings_pane_highlights_header": "រឿងសំខាន់ៗ", + "settings_pane_highlights_body2": "Find your way back to interesting things you’ve recently visited or bookmarked.", + "settings_pane_highlights_options_bookmarks": "ចំណាំ", + "settings_pane_highlights_options_visited": "សាយដែលបានទស្សនា", + "settings_pane_snippets_header": "អត្ថបទសង្ខេប", + "settings_pane_snippets_body": "Read short and sweet updates from Mozilla about Firefox, internet culture, and the occasional random meme.", + "settings_pane_done_button": "ធ្វើរួច", + "settings_pane_topstories_options_sponsored": "Show Sponsored Stories", + "edit_topsites_button_text": "កែសម្រួល", + "edit_topsites_edit_button": "កែសម្រួលសាយនេះ", + "topsites_form_add_header": "សាយកំពូលថ្មី", + "topsites_form_edit_header": "កែសម្រួលសាយកំពូល", + "topsites_form_title_label": "Title", + "topsites_form_title_placeholder": "បញ្ចូលចំណងជើង", + "topsites_form_url_label": "URL", + "topsites_form_image_url_label": "Custom Image URL", + "topsites_form_url_placeholder": "វាយបញ្ចូល ឬបិទភ្ជាប់ URL", + "topsites_form_use_image_link": "Use a custom image…", + "topsites_form_preview_button": "Preview", + "topsites_form_add_button": "បន្ថែម", + "topsites_form_save_button": "រក្សាទុក", + "topsites_form_cancel_button": "បោះបង់", + "topsites_form_url_validation": "ត្រូវការ URL ដែលត្រឹមត្រូវ", + "topsites_form_image_validation": "Image failed to load. Try a different URL.", + "pocket_read_more": "ប្រធានបទកំពុងពេញនិយម៖", + "pocket_read_even_more": "មើលរឿងរ៉ាវច្រើនទៀត", + "pocket_description": "Discover high-quality content you might otherwise miss, with help from Pocket, now part of Mozilla.", + "highlights_empty_state": "Start browsing, and we’ll show some of the great articles, videos, and other pages you’ve recently visited or bookmarked here.", + "topstories_empty_state": "You’ve caught up. Check back later for more top stories from {provider}. Can’t wait? Select a popular topic to find more great stories from around the web.", + "manual_migration_explanation2": "សាកល្បងប្រើ Firefox ជាមួយចំណាំ ប្រវត្តិ និងពាក្យសម្ងាត់ពីកម្មវិធីរុករកផ្សេងទៀត។", + "manual_migration_cancel_button": "ទេ អរគុណ", + "manual_migration_import_button": "នាំចូលឥឡូវនេះ", + "error_fallback_default_info": "Oops, something went wrong loading this content.", + "error_fallback_default_refresh_suggestion": "Refresh page to try again.", + "section_menu_action_remove_section": "Remove Section", + "section_menu_action_collapse_section": "Collapse Section", + "section_menu_action_expand_section": "Expand Section", + "section_menu_action_manage_section": "Manage Section", + "section_menu_action_add_topsite": "Add Top Site", + "section_menu_action_move_up": "Move Up", + "section_menu_action_move_down": "Move Down", + "section_menu_action_privacy_notice": "Privacy Notice", + "default_label_loading": "កំពុង​ផ្ទុក...", + "header_stories": "រឿងរ៉ាវកំពូល", + "header_visit_again": "ទស្សនាម្តងទៀត", + "header_bookmarks": "ចំណាំថ្មីៗ", + "header_bookmarks_placeholder": "អ្នកមិនមានចំណាំណាមួយនៅឡើយទេ ។", + "header_stories_from": "មកពី", + "type_label_synced": "បាន​ធ្វើ​សមកាលកម្ម​ពី​ឧបករណ៍​ផ្សេង​ទៀត", + "type_label_open": "បើក", + "type_label_topic": "ប្រធានបទ", + "type_label_now": "ឥឡូវនេះ", + "menu_action_copy_address": "ចម្លង​អាសយដ្ឋាន", + "menu_action_email_link": "តំណ​អ៊ីមែល...", + "search_for_something_with": "ស្វែងរក {search_term} ជាមួយ៖", + "search_settings": "ផ្លាស់ប្ដូរ​ការ​កំណត់​ស្វែងរក", + "section_info_option": "ព័ត៌មាន", + "section_info_send_feedback": "ផ្ញើមតិត្រឡប់", + "section_info_privacy_notice": "សេចក្តីជូនដំណឹងអំពីភាពឯកជន", + "welcome_title": "ស្វាគមន៍​មក​កាន់​ផ្ទាំង​ថ្មី", + "welcome_body": "Firefox នឹង​ប្រើប្រាស់​កន្លែង​ទំនេរ​នេះ ដើម្បី​បង្ហាញ​ចំណាំ អត្ថបទ វីដេអូ និង​ទំព័រ​ដែល​ទាក់ទង​អ្នក​បំផុត ដែល​អ្នក​បាន​ចូល​មើល​ថ្មីៗ​នេះ ដូច្នេះ​អ្នក​អាច​ត្រឡប់​ទៅ​​កាន់​​វា​​វិញ​បាន​យ៉ាងងាយស្រួល។", + "welcome_label": "កំពុង​បញ្ជាក់​ការ​រំលេច​របស់​អ្នក", + "time_label_less_than_minute": "<1 នាទី", + "time_label_minute": "{number} នាទី", + "time_label_hour": "{number} ម៉ោង", + "time_label_day": "{number} ថ្ងៃ", + "settings_pane_bookmarks_header": "ចំណាំថ្មីៗ", + "settings_pane_bookmarks_body": "ចំណាំថ្មីៗ ដែលបានបង្កើតរបស់អ្នកនៅក្នុងទីតាំងដែលងាយស្រួល។", + "settings_pane_visit_again_header": "ទស្សនាម្ដងទៀត", + "edit_topsites_showmore_button": "បង្ហាញច្រើនទៀត", + "edit_topsites_showless_button": "បង្ហាញតិចជាង​នេះ", + "edit_topsites_done_button": "ធ្វើរួច", + "edit_topsites_pin_button": "ខ្ទាស់សាយនេះ", + "edit_topsites_unpin_button": "ដកខ្ទាស់សាយនេះ", + "edit_topsites_dismiss_button": "ច្រានចោលសាយនេះ", + "edit_topsites_add_button": "បន្ថែម", + "pocket_feedback_header": "បណ្តាញល្អបំផុត ដែលបានវាយតម្លៃដោយមនុស្សជាង 25 លាននាក់។" +}; diff -pruN 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/ml/activity-stream-strings.js 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/ml/activity-stream-strings.js --- 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/ml/activity-stream-strings.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/ml/activity-stream-strings.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,130 @@ +// Note - this is a generated file. +window.gActivityStreamStrings = { + "newtab_page_title": "പുതിയ ടാബ്", + "header_top_sites": "മികച്ച സൈറ്റുകൾ", + "header_highlights": "ഹൈലൈറ്റുകൾ", + "header_recommended_by": "{provider} ശുപാർശ ചെയ്തത്", + "context_menu_button_sr": "Open context menu for {title}", + "section_context_menu_button_sr": "Open the section context menu", + "type_label_visited": "സന്ദർശിച്ചത്‌", + "type_label_bookmarked": "അടയാളപ്പെടുത്തിയത്", + "type_label_recommended": "ട്രെൻഡിംഗ്", + "type_label_pocket": "Saved to Pocket", + "menu_action_bookmark": "അടയാളം", + "menu_action_remove_bookmark": "അടയാളം മാറ്റുക", + "menu_action_open_new_window": "പുതിയ ജാലകത്തിൽ തുറക്കുക", + "menu_action_open_private_window": "പുതിയ രസഹ്യജാലകത്തിൽ തുറക്കുക", + "menu_action_dismiss": "പുറത്താക്കുക", + "menu_action_delete": "ചരിത്രത്തിൽ നിന്ന് ഒഴിവാക്കുക", + "menu_action_pin": "പിൻ ചെയ്യുക", + "menu_action_unpin": "അൺപിൻ ചെയ്യുക", + "confirm_history_delete_p1": "നിങ്ങളുടെ ചരിത്രത്തിൽ നിന്ന് ഈ പേജിന്റെ എല്ലാ ഉദാഹരണങ്ങളും ഇല്ലാതാക്കാൻ നിങ്ങൾ താൽപ്പര്യപ്പെടുന്നുവെന്ന് തീർച്ചയാണോ?", + "confirm_history_delete_notice_p2": "ഈ പ്രവർത്തനം പഴയപടിയാക്കാനാവില്ല.", + "menu_action_save_to_pocket": "പോക്കറ്റിലേയ്ക്ക് സംരക്ഷിയ്ക്കുക", + "menu_action_delete_pocket": "Delete from Pocket", + "menu_action_archive_pocket": "Archive in Pocket", + "search_button": "തിരയുക", + "search_header": "{search_engine_name} തിരയുക", + "search_web_placeholder": "ഇൻറർനെറ്റിൽ തിരയുക", + "section_disclaimer_topstories": "വെബിലെ ഏറ്റവും രസകരമായ അറിവുകൾ, നിങ്ങൾ വായിച്ചവ അടിസ്ഥാനമാക്കി തിരഞ്ഞെടുത്തത്. ഇപ്പോൾ മോസില്ലയുടെ ഭാഗമായ പോക്കറ്റിൽ നിന്നും.", + "section_disclaimer_topstories_linktext": "എങ്ങനെ പ്രവര്‍ത്തിക്കുന്നു എന്ന് കാണുക.", + "section_disclaimer_topstories_buttontext": "ശരി, മനസ്സിലായി", + "prefs_home_header": "Firefox Home Content", + "prefs_home_description": "Choose what content you want on your Firefox Home screen.", + "prefs_restore_defaults_button": "Restore Defaults", + "prefs_section_rows_option": "{num} row;{num} rows", + "prefs_search_header": "Web Search", + "prefs_topsites_description": "The sites you visit most", + "prefs_topstories_description": "High-quality content you might otherwise miss", + "prefs_topstories_show_sponsored_label": "{provider} Sponsored Stories", + "prefs_topstories_sponsored_learn_more": "Learn more", + "prefs_highlights_description": "A selection of sites that you’ve saved or visited", + "prefs_snippets_description": "Updates from Mozilla and Firefox", + "settings_pane_button_label": "നിങ്ങളുടെ പുതിയ ടാബ് താള് ഇഷ്ടാനുസൃതമാക്കുക", + "settings_pane_header": "പുതിയ ടാബിന്റെ മുൻഗണനകൾ", + "settings_pane_body2": "നിങ്ങൾ ഈ താളിൽ കാണുന്നത് തിരഞ്ഞെടുക്കുക.", + "settings_pane_search_header": "തിരയുക", + "settings_pane_search_body": "പുതിയ ടാബിൽ നിന്ന് ഇന്റർനെറ്റിൽ തിരയുക.", + "settings_pane_topsites_header": "മുന്നേറിയ സൈറ്റുകൾ", + "settings_pane_topsites_body": "നിങ്ങൾ കൂടുതൽ സന്ദർശിക്കുന്ന വെബ്‌സൈറ്റുകളിൽ പ്രവേശിക്കുക.", + "settings_pane_topsites_options_showmore": "രണ്ടു വരികൾ കാണിയ്ക്കുക", + "settings_pane_highlights_header": "ഹൈലൈറ്റുകൾ", + "settings_pane_highlights_body2": "നിങ്ങൾ സമീപകാലത്ത് സന്ദർശിച്ചതോ അല്ലെങ്കിൽ ബുക്ക്മാർക്ക് ചെയ്തതോ ആയ രസകരമായ കാര്യങ്ങളിലേക്ക് വഴി കണ്ടെത്തുക.", + "settings_pane_highlights_options_bookmarks": "ബുക്ക്മാർക്കുകൾ", + "settings_pane_highlights_options_visited": "സന്ദർശിച്ച സൈറ്റുകൾ", + "settings_pane_snippets_header": "ലഘു കുറിപ്പുകൾ", + "settings_pane_snippets_body": "മോസില്ലയിൽ നിന്നും ഫയർഫോക്സ്, ഇന്റർനെറ്റ് സംസ്കാരം, വല്ലപ്പോഴുമുള്ള ക്രമമില്ലാത്ത മെമെ, എന്നിവയിൽ ചെറുതും മധുരവുമായ പരിഷ്കരണങ്ങൾ വായിക്കുക.", + "settings_pane_done_button": "തീർന്നു", + "settings_pane_topstories_options_sponsored": "സ്പോൺസർ ചെയ്തവ കാണിക്കുക", + "edit_topsites_button_text": "തിരുത്തുക", + "edit_topsites_edit_button": "ഈ സൈറ്റ് തിരുത്തുക", + "topsites_form_add_header": "പുതിയ മികച്ച സൈറ്റുകൾ", + "topsites_form_edit_header": "മികച്ച സൈറ്റ് ലിസ്റ്റ് തിരുത്തൂ", + "topsites_form_title_label": "Title", + "topsites_form_title_placeholder": "തലക്കെട്ട് നൽകൂ", + "topsites_form_url_label": "URL", + "topsites_form_image_url_label": "Custom Image URL", + "topsites_form_url_placeholder": "വെബ്URLനൽകൂ", + "topsites_form_use_image_link": "Use a custom image…", + "topsites_form_preview_button": "Preview", + "topsites_form_add_button": "ചേർക്കൂ", + "topsites_form_save_button": "സംരക്ഷിയ്ക്കൂ", + "topsites_form_cancel_button": "ഒഴിവാക്കൂ", + "topsites_form_url_validation": "പ്രവർത്തിയ്ക്കുന്ന URL ആവശ്യമാണ്", + "topsites_form_image_validation": "Image failed to load. Try a different URL.", + "pocket_read_more": "ജനപ്രിയ വിഷയങ്ങൾ:", + "pocket_read_even_more": "കൂടുതൽ ലേഖനങ്ങൾ കാണുക", + "pocket_description": "മോസില്ലയുടെ ഭാഗമായ, പോക്കറ്റിന്റെ സഹായം കൊണ്ട്, നിങ്ങൾക്ക് കണ്ടെത്താനാവാത്ത ഉയർന്ന നിലവാരമുള്ള ഉള്ളടക്കം കണ്ടെത്തുക.", + "highlights_empty_state": "ബ്രൗസിംഗ് ആരംഭിക്കുക, നിങ്ങൾ സമീപകാലത്ത് സന്ദർശിച്ചതോ ബുക്ക്മാർക്ക് ചെയ്തതോ ആയ മികച്ച ലേഖനങ്ങളിൽ നിന്നോ, വീഡിയോകളിൽ നിന്നോ, മറ്റു പേജുകളിൽ നിന്നോ ചിലത് ഞങ്ങൾ ഇവിടെ കാണിക്കും.", + "topstories_empty_state": "നിങ്ങൾ ഇവിടെ വരെ എത്തി. {Provider}ൽ നിന്നുള്ള കൂടുതൽ പ്രധാന വാർത്തകൾക്കായി പിന്നീട് വീണ്ടും പരിശോധിക്കുക. കാത്തിരിക്കാൻ പറ്റില്ലേ? വെബിൽ നിന്ന് കൂടുതൽ മികച്ച കഥകൾ കണ്ടെത്തുന്നതിന് ഒരു ജനപ്രിയ വിഷയം തിരഞ്ഞെടുക്കുക.", + "manual_migration_explanation2": "മറ്റൊരു ബ്രൗസറിൽ നിന്നുള്ള ബുക്ക്മാർക്കുകൾ, ചരിത്രം, പാസ്വേഡുകൾ എന്നിവ ഉപയോഗിച്ച് ഫയർഫോക്സ് പരീക്ഷിക്കുക.", + "manual_migration_cancel_button": "വേണ്ട, നന്ദി", + "manual_migration_import_button": "ഇപ്പോൾ ഇറക്കുമതി ചെയ്യുക", + "error_fallback_default_info": "Oops, something went wrong loading this content.", + "error_fallback_default_refresh_suggestion": "Refresh page to try again.", + "section_menu_action_remove_section": "Remove Section", + "section_menu_action_collapse_section": "Collapse Section", + "section_menu_action_expand_section": "Expand Section", + "section_menu_action_manage_section": "Manage Section", + "section_menu_action_add_topsite": "Add Top Site", + "section_menu_action_move_up": "Move Up", + "section_menu_action_move_down": "Move Down", + "section_menu_action_privacy_notice": "Privacy Notice", + "default_label_loading": "ലോഡ്ചെയ്യുന്നു…", + "header_stories": "മികച്ച ലേഖനങ്ങൾ", + "header_visit_again": "വീണ്ടും സന്ദർശിക്കുക", + "header_bookmarks": "അടുത്തിടെയുള്ള ബുക്ക്മാർക്കുകൾ", + "header_bookmarks_placeholder": "നിങ്ങൾക്ക് ഇതുവരെ ബുക്ക്മാർക്കുകൾ ഇല്ല.", + "header_stories_from": "എവിടെ നിന്നും", + "type_label_synced": "മറ്റു ഉപകരണങ്ങളുമായി സാമ്യപ്പെടുക", + "type_label_open": "തുറക്കുക", + "type_label_topic": "വിഷയം", + "type_label_now": "ഇപ്പോൾ", + "menu_action_copy_address": "വിലാസം പകർത്തുക", + "menu_action_email_link": "ഇമെയിൽ വിലാസം…", + "search_for_something_with": "തിരയാൻ {search_term} : എന്നത് ഉപയോഗിയ്ക്കുക", + "search_settings": "തിരയാനുള്ള രീതികൾ മാറ്റുക", + "section_info_option": "വിവരം", + "section_info_send_feedback": "ഫീഡ്ബാക്ക് അയയ്ക്കുക", + "section_info_privacy_notice": "സ്വകാര്യതാ അറിയിപ്പ്", + "welcome_title": "പുതിയ ജാലകത്തിലേക്കു സ്വാഗതം", + "welcome_body": "നിങ്ങളുടെ ഏറ്റവും ശ്രദ്ധേയമായ അടയാളങ്ങൾ, ലേഖനങ്ങൾ, വീഡിയോകൾ, കൂടാതെ നിങ്ങൾ സമീപകാലത്ത് സന്ദർശിച്ച താളുകൾ എന്നിവ കാണിക്കുന്നതിനായി ഫയർഫോക്സ് ഈ ഇടം ഉപയോഗിക്കും, അതിനാൽ നിങ്ങൾക്ക് എളുപ്പത്തിൽ അവയിലേക്ക് തിരിച്ചു പോകാം.", + "welcome_label": "താങ്കളുടെ ഹൈലൈറ്റ്സ് തിരിച്ചറിയുന്നു", + "time_label_less_than_minute": "<1 മിനിറ്റ്", + "time_label_minute": "{number} മിനിറ്റ്", + "time_label_hour": "{number} മിനിറ്റ്", + "time_label_day": "{number} മിനിറ്റ്", + "settings_pane_bookmarks_header": "അടുത്തിടെയുള്ള ബുക്ക്മാർക്കുകൾ", + "settings_pane_bookmarks_body": "നിങ്ങളുടെ പുതിയതായി സൃഷ്ടിച്ച ബുക്ക്മാർക്കുകൾ ഒരു സ്ഥലത്ത്.", + "settings_pane_visit_again_header": "വീണ്ടും സന്ദർശിക്കുക", + "settings_pane_visit_again_body": "നിങ്ങൾ ഓർത്തുവയ്ക്കാനോ അല്ലെങ്കിൽ തിരികെ ചെല്ലാനോ ആഗ്രഹിക്കുന്ന ബ്രൌസിംഗ് ചരിത്രത്തിന്റെ ഭാഗങ്ങൾ നിങ്ങൾക്ക് ഫയർഫോക്സ് കാണിച്ച് തരും.", + "edit_topsites_button_label": "നിങ്ങളുടെ മുന്നേറിയ സൈറ്റുകളുടെ വിഭാഗം ഇഷ്ടാനുസൃതമാക്കുക", + "edit_topsites_showmore_button": "കൂടുതൽ കാണിക്കുക", + "edit_topsites_showless_button": "കുറച്ച് കാണിക്കുക", + "edit_topsites_done_button": "തീർന്നു", + "edit_topsites_pin_button": "ഈ സൈറ്റ് പിൻ ചെയ്യുക", + "edit_topsites_unpin_button": "ഈ സൈറ്റ് അണ്‍പിന്‍ ചെയ്യുക", + "edit_topsites_dismiss_button": "ഈ സൈറ്റ് പുറത്താക്കുക", + "edit_topsites_add_button": "ചേര്‍ക്കുക", + "pocket_feedback_header": "250 ലക്ഷം പേരാൽ തെരഞ്ഞെടുക്കപ്പെട്ട വെബിലെ ഏറ്റവും മികച്ചവയാണിവ." +}; diff -pruN 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/ne-NP/activity-stream-strings.js 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/ne-NP/activity-stream-strings.js --- 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/ne-NP/activity-stream-strings.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/ne-NP/activity-stream-strings.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,129 @@ +// Note - this is a generated file. +window.gActivityStreamStrings = { + "newtab_page_title": "नयाँ ट्याब", + "header_top_sites": "शीर्ष साइटहरु", + "header_highlights": "विशेषताहरू", + "header_recommended_by": "{provider} द्वारा सिफारिस गरिएको", + "context_menu_button_sr": "Open context menu for {title}", + "section_context_menu_button_sr": "Open the section context menu", + "type_label_visited": "भ्रमण गरिएको", + "type_label_bookmarked": "पुस्तकचिनो लागाइएको", + "type_label_recommended": "प्रचलनमा", + "type_label_pocket": "Saved to Pocket", + "menu_action_bookmark": "पुस्तकचिनो", + "menu_action_remove_bookmark": "पुस्तकचिनो हटाउनुहोस्", + "menu_action_open_new_window": "नयाँ सञ्झ्यालमा खोल्नुहोस्", + "menu_action_open_private_window": "नयाँ निजी सञ्झ्यालमा खोल्नुहोस्", + "menu_action_dismiss": "खारेज गर्नुहोस्", + "menu_action_delete": "इतिहासबाट मेट्नुहोस्", + "menu_action_pin": "पिन गर्नुहोस्", + "menu_action_unpin": "अन पिन गर्नुहोस्", + "confirm_history_delete_p1": "के तपाईं पक्का हुनुहुन्छ कि तपाइँ यस पृष्ठको हरेक उदाहरण तपाइँको इतिहासबाट हटाउन चाहनुहुन्छ ?", + "confirm_history_delete_notice_p2": "यो कार्य पूर्ववत गर्न सकिँदैन ।", + "menu_action_save_to_pocket": "Pocketमा बचत गर्नुहोस्", + "menu_action_delete_pocket": "Delete from Pocket", + "menu_action_archive_pocket": "Archive in Pocket", + "search_button": "खोजी गर्नुहोस्", + "search_header": "{search_engine_name} खोजी", + "search_web_placeholder": "वेबमा खोज्नुहोस्", + "section_disclaimer_topstories": "वेबमा सबैभन्दा रोचक कथाहरू, तपाईंले पढ्नु भएको आधारमा Pocket बाट चयन गर्नुभएको छ।", + "section_disclaimer_topstories_linktext": "कसरी काम गर्छ हेर्नुहोस्।", + "section_disclaimer_topstories_buttontext": "बुझेँ", + "prefs_home_header": "Firefox Home Content", + "prefs_home_description": "Choose what content you want on your Firefox Home screen.", + "prefs_restore_defaults_button": "Restore Defaults", + "prefs_section_rows_option": "{num} row;{num} rows", + "prefs_search_header": "Web Search", + "prefs_topsites_description": "The sites you visit most", + "prefs_topstories_description": "High-quality content you might otherwise miss", + "prefs_topstories_show_sponsored_label": "{provider} Sponsored Stories", + "prefs_topstories_sponsored_learn_more": "Learn more", + "prefs_highlights_description": "A selection of sites that you’ve saved or visited", + "prefs_snippets_description": "Updates from Mozilla and Firefox", + "settings_pane_button_label": "तपाईंको नयाँ ट्याब पृष्ठ अनुकूलन गर्नुहोस्", + "settings_pane_header": "नयाँ ट्याब प्राथमिकताहरू", + "settings_pane_body2": "तपाईँले यो पृष्ठमा के देख्नुभयो छनौट गर्नुहोस् ।", + "settings_pane_search_header": "खोजी गर्नुहोस्", + "settings_pane_search_body": "तपाईंको नयाँ ट्याबबाट वेबमा खोज्नुहोस् ।", + "settings_pane_topsites_header": "शीर्ष साइटहरू", + "settings_pane_topsites_body": "तपाईले धेरै भ्रमण गर्नुभएका वेबसाइटहरूमा पहुँच गर्नुहोस् ।", + "settings_pane_topsites_options_showmore": "दुई पङ्क्तिहरू देखाउनुहोस्", + "settings_pane_highlights_header": "विशेषताहरू", + "settings_pane_highlights_body2": "Find your way back to interesting things you’ve recently visited or bookmarked.", + "settings_pane_highlights_options_bookmarks": "पुस्तकचिनोहरू", + "settings_pane_highlights_options_visited": "भ्रमण गरिएका साईटहरु", + "settings_pane_snippets_header": "स्निप्पेटस्", + "settings_pane_snippets_body": "Read short and sweet updates from Mozilla about Firefox, internet culture, and the occasional random meme.", + "settings_pane_done_button": "सम्पन्न भयो", + "settings_pane_topstories_options_sponsored": "प्रायोजित गरिएको कथाहरू देखाउनुहोस्", + "edit_topsites_button_text": "सम्पादन गर्नुहोस्", + "edit_topsites_edit_button": "यस साइटलाई सम्पादन गर्नुहोस्", + "topsites_form_add_header": "नयाँ शीर्ष साइट", + "topsites_form_edit_header": "शीर्ष साइट सम्पादन गर्नुहोस्", + "topsites_form_title_label": "Title", + "topsites_form_title_placeholder": "शीर्षक प्रविष्ट गर्नुहोस्", + "topsites_form_url_label": "URL", + "topsites_form_image_url_label": "Custom Image URL", + "topsites_form_url_placeholder": "URL लेख्नुहोस् ", + "topsites_form_use_image_link": "Use a custom image…", + "topsites_form_preview_button": "Preview", + "topsites_form_add_button": "थप्नुहोस्", + "topsites_form_save_button": "सङ्ग्रह गर्नुहोस्", + "topsites_form_cancel_button": "रद्द गर्नुहोस्", + "topsites_form_url_validation": "मान्य URL चाहिन्छ", + "topsites_form_image_validation": "Image failed to load. Try a different URL.", + "pocket_read_more": "लोकप्रिय शीर्षकहरू:", + "pocket_read_even_more": "अरू कथा देखाउनुहोस्", + "pocket_description": "Discover high-quality content you might otherwise miss, with help from Pocket, now part of Mozilla.", + "highlights_empty_state": "Start browsing, and we’ll show some of the great articles, videos, and other pages you’ve recently visited or bookmarked here.", + "topstories_empty_state": "You’ve caught up. Check back later for more top stories from {provider}. Can’t wait? Select a popular topic to find more great stories from around the web.", + "manual_migration_explanation2": "Try Firefox with the bookmarks, history and passwords from another browser.", + "manual_migration_cancel_button": "पर्दैन, धन्यबाद", + "manual_migration_import_button": "अहिले आयात गर्नुहोस्", + "error_fallback_default_info": "Oops, something went wrong loading this content.", + "error_fallback_default_refresh_suggestion": "Refresh page to try again.", + "section_menu_action_remove_section": "Remove Section", + "section_menu_action_collapse_section": "Collapse Section", + "section_menu_action_expand_section": "Expand Section", + "section_menu_action_manage_section": "Manage Section", + "section_menu_action_add_topsite": "Add Top Site", + "section_menu_action_move_up": "Move Up", + "section_menu_action_move_down": "Move Down", + "section_menu_action_privacy_notice": "Privacy Notice", + "default_label_loading": "लोड हुदैँछ...", + "header_stories": "शीर्ष साइटहरु", + "header_visit_again": "फेरि भ्रमण गर्नुहोस्", + "header_bookmarks": "भर्खरैका पुस्तकचिनोहरु", + "header_bookmarks_placeholder": "तपाइँसँग अहिले सम्म कुनै पुस्तकचिनोहरु छैन ।", + "header_stories_from": "बाट", + "type_label_synced": "अर्को यण्त्रबाट समक्रमण गरिएको", + "type_label_open": "खोल्नुहोस्", + "type_label_topic": "शीर्षक", + "type_label_now": "अहिले", + "menu_action_copy_address": "ठेगाना प्रतिलिपि गर्नुहोस्", + "menu_action_email_link": "लिङ्कलाई इमेल गर्नुहोस्...", + "search_for_something_with": "{search_term} खोज्न प्रयोग गर्नुहोस्:", + "search_settings": "खोजी सेटिङ परिवर्तन गर्नुहोस्", + "section_info_option": "जानकारी", + "section_info_send_feedback": "प्रतिक्रिया पठाउनुहोस्", + "section_info_privacy_notice": "गोपनीयता नीति", + "welcome_title": "नयाँ ट्याबमा स्वागत छ", + "welcome_body": "Firefoxले यस ठाउँको प्रयोग तपाईंको सबैभन्दा सान्दर्भिक पुस्तकचिनो, लेखहरू, भिडियोहरू, र तपाईंले हालै भ्रमण गर्नु भएको पृष्ठहरूलाई राख्न प्रयोग गर्दछ, जसले गर्दा तपाइँ तिनीहरूलाई सजिलै भेटाउन सक्नुहुनेछ ।", + "welcome_label": "तपाईँका विशेषताहरु पत्ता लगाउँदै", + "time_label_less_than_minute": "< १ मिनेट", + "time_label_minute": "{number} मिनेट", + "time_label_hour": "{number} घण्टा", + "time_label_day": "{number} दिन", + "settings_pane_bookmarks_header": "भर्खरैका पुस्तकचिनोहरु", + "settings_pane_bookmarks_body": "तपाईंको नयाँ सिर्जना गरिएको पुस्तकचिनोहरुहरू एउटा सजिलो स्थानमा ।", + "settings_pane_visit_again_header": "फेरि भ्रमण गर्नुहोस्", + "edit_topsites_button_label": "तपाईंको शीर्ष साइट खण्ड अनुकूलन गर्नुहोस्", + "edit_topsites_showmore_button": "थप देखाउनुहोस्", + "edit_topsites_showless_button": "थोरै देखाउनुहोस्", + "edit_topsites_done_button": "सम्पन्न भयो", + "edit_topsites_pin_button": "यस साइटलाई पिन गर्नुहोस्", + "edit_topsites_unpin_button": "यस साइटलाई अनपिन गर्नुहोस्", + "edit_topsites_dismiss_button": "यस साइटलाई खारेज गर्नुहोस्", + "edit_topsites_add_button": "थप्नुहोस्", + "pocket_feedback_header": "वेबको सर्वोत्तम, 25 मिलियन भन्दा बढी व्यक्तिहरू द्वारा लिपिबद्ध।" +}; diff -pruN 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/ta/activity-stream-strings.js 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/ta/activity-stream-strings.js --- 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/ta/activity-stream-strings.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/ta/activity-stream-strings.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,93 @@ +// Note - this is a generated file. +window.gActivityStreamStrings = { + "newtab_page_title": "புதிய கீற்று", + "header_top_sites": "சிறந்த தளங்கள்", + "header_highlights": "மிளிர்ப்புகள்", + "header_recommended_by": "{provider} என்பவரால் பரிந்துரைக்கப்பட்டது", + "context_menu_button_sr": "Open context menu for {title}", + "section_context_menu_button_sr": "Open the section context menu", + "type_label_visited": "பார்த்தவை", + "type_label_bookmarked": "புத்தகக்குறியிடப்பட்டது", + "type_label_recommended": "பிரபலமான", + "type_label_pocket": "Saved to Pocket", + "menu_action_bookmark": "புத்தகக்குறி", + "menu_action_remove_bookmark": "புத்தகக்குறியை நீக்கு", + "menu_action_open_new_window": "ஒரு புதிய சாளரத்தில் திற", + "menu_action_open_private_window": "ஒரு புதிய அந்தரங்க சாளரத்தில் திற", + "menu_action_dismiss": "வெளியேற்று", + "menu_action_delete": "வரலாற்றிலருந்து அழி", + "menu_action_pin": "பொருத்து", + "menu_action_unpin": "விடுவி", + "confirm_history_delete_p1": "இப்பக்கத்தை உங்களின் வரலாற்றிலிருந்து முழுமையாக நீக்க விரும்புகிறீர்களா?", + "confirm_history_delete_notice_p2": "இச்செயலை மீட்க முடியாது.", + "menu_action_save_to_pocket": "பாக்கட்டில் சேமி", + "menu_action_delete_pocket": "பாக்கெட்டிலிருந்து நீக்கு", + "menu_action_archive_pocket": "பாக்கெட்டில் காப்பெடு", + "search_button": "தேடு", + "search_header": "{search_engine_name} தேடுபொறியில் தேடு", + "search_web_placeholder": "இணையத்தில் தேடு", + "section_disclaimer_topstories": "The most interesting stories on the web, selected based on what you read. From Pocket, now part of Mozilla.", + "section_disclaimer_topstories_linktext": "இது எப்படி வேலை செய்கிறது என்று தெரிந்துகொள்ளவும்.", + "section_disclaimer_topstories_buttontext": "சரி, புரிந்தது", + "prefs_home_header": "Firefox முகப்பு உள்ளடக்கம்", + "prefs_home_description": "Choose what content you want on your Firefox Home screen.", + "prefs_restore_defaults_button": "Restore Defaults", + "prefs_section_rows_option": "{num} row;{num} rows", + "prefs_search_header": "வலைதள தேடல்", + "prefs_topsites_description": "நீங்கள் மிகவும் பார்வையிடும் தளங்கள்", + "prefs_topstories_description": "High-quality content you might otherwise miss", + "prefs_topstories_show_sponsored_label": "{provider} விளம்பரதாரர் செய்திகள்", + "prefs_topstories_sponsored_learn_more": "மேலும் அறிய", + "prefs_highlights_description": "நீங்கள் சேமித்த அல்லது பார்வையிட்ட தளங்களின் தேர்வு", + "prefs_snippets_description": "மொசில்லா மற்றும் பயர்பாக்சிலிருந்து புதுப்பிப்புகள்", + "settings_pane_button_label": "உங்கள் புதிய கீற்றுப் பக்கத்தை விருப்பமை", + "settings_pane_header": "புதிய கீற்றின் முன்னுரிமைகள்", + "settings_pane_body2": "இந்த பக்கத்தில் நீங்கள் பார்ப்பதை தேர்வு செய்யவும்.", + "settings_pane_search_header": "தேடல்", + "settings_pane_search_body": "புதிய கீற்றிலீருந்து இணையத்தை தேடு.", + "settings_pane_topsites_header": "சிறந்த தளங்கள்", + "settings_pane_topsites_body": "நீங்கள் அடிக்கடி பார்க்கும் தளங்களை அணுகவும்.", + "settings_pane_topsites_options_showmore": "இரு வரிசைகளைக் காண்பி", + "settings_pane_highlights_header": "மிளிர்ப்புகள்", + "settings_pane_highlights_body2": "நீங்கள் சமீபத்தில் பார்வையிட்ட புத்தகக்குறியிட்ட சுவாரசியமான விடயங்களை மீண்டும் காணுங்கள்.", + "settings_pane_highlights_options_bookmarks": "புத்தகக்குறிகள்", + "settings_pane_highlights_options_visited": "பார்வையிடப்பட்ட தளம்", + "settings_pane_snippets_header": "துணுக்குகள்", + "settings_pane_snippets_body": "பயர்பாக்ஸ், இணைய கலாச்சாரம், அவ்வப்போது மீம்கள் போன்ற சுருக்கமான இனிய புதுப்பிப்புகளை மொசில்லாவிடமிருந்து படியுங்கள்.", + "settings_pane_done_button": "முடிந்தது", + "settings_pane_topstories_options_sponsored": "விளம்பரங்களைக் காட்டு", + "edit_topsites_button_text": "தொகு", + "edit_topsites_edit_button": "இத்தளத்தை தொகு", + "topsites_form_add_header": "புதிய முக்கிய தளம்", + "topsites_form_edit_header": "முக்கிய தளத்தை தொகு", + "topsites_form_title_label": "தலைப்பு", + "topsites_form_title_placeholder": "தலைப்பை இடு", + "topsites_form_url_label": "URL", + "topsites_form_image_url_label": "Custom Image URL", + "topsites_form_url_placeholder": "உள்ளிடு (அ) ஒரு URL ஒட்டு", + "topsites_form_use_image_link": "தனிப்பயன் படத்தை பயன்படுத்தவும்…", + "topsites_form_preview_button": "முன்தோற்றம்", + "topsites_form_add_button": "சேர்", + "topsites_form_save_button": "சேமி", + "topsites_form_cancel_button": "தவிர்", + "topsites_form_url_validation": "சரியான URL தேவை", + "topsites_form_image_validation": "படத்தை ஏற்றுவதில் தோல்வி. வேறு URL ஐ முயற்சிக்கவும்.", + "pocket_read_more": "பிரபலமான தலைப்புகள்:", + "pocket_read_even_more": "இன்னும் கதைகளைப் பார்க்கவும்", + "pocket_description": "Discover high-quality content you might otherwise miss, with help from Pocket, now part of Mozilla.", + "highlights_empty_state": "உலாவலைத் தொடங்கவும், மேலும் நாங்கள் சில சிறந்த கட்டுரைகள், காணொளிகள், மற்றும் நீங்கள் சமீபத்தில் பார்த்த பிற பக்கங்கள் அல்லது இங்கே புத்தகக்குறியிட்டவற்றைக் காட்டுவோம்.", + "topstories_empty_state": "You’ve caught up. Check back later for more top stories from {provider}. Can’t wait? Select a popular topic to find more great stories from around the web.", + "manual_migration_explanation2": "Try Firefox with the bookmarks, history and passwords from another browser.", + "manual_migration_cancel_button": "பரவாயில்லை", + "manual_migration_import_button": "இப்போது இறக்கு", + "error_fallback_default_info": "அச்சச்சோ, இந்த உள்ளடக்கத்தை ஏற்றுவதில் ஏதோ தவறு ஏற்பட்டது.", + "error_fallback_default_refresh_suggestion": "மீண்டும் முயற்சிக்க பக்கத்தை புதுப்பி.", + "section_menu_action_remove_section": "பகுதியை நீக்கவும்", + "section_menu_action_collapse_section": "பகுதியைச் சுருக்கு", + "section_menu_action_expand_section": "பகுதியை விரி", + "section_menu_action_manage_section": "பகுதியை நிர்வகி", + "section_menu_action_add_topsite": "முதன்மை தளத்தைச் சேர்", + "section_menu_action_move_up": "மேலே நகர்த்து", + "section_menu_action_move_down": "கீழே நகர்த்து", + "section_menu_action_privacy_notice": "தனியுரிமை அறிவிப்பு" +}; diff -pruN 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/th/activity-stream-strings.js 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/th/activity-stream-strings.js --- 1:60.2.1-1/browser/extensions/activity-stream/prerendered/locales/th/activity-stream-strings.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/prerendered/locales/th/activity-stream-strings.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,94 @@ +// Note - this is a generated file. +window.gActivityStreamStrings = { + "newtab_page_title": "แท็บใหม่", + "header_top_sites": "ไซต์เด่น", + "header_highlights": "รายการเด่น", + "header_recommended_by": "แนะนำโดย {provider}", + "context_menu_button_sr": "เปิดเมนูบริบทสำหรับ {title}", + "section_context_menu_button_sr": "เปิดเมนูบริบทของส่วน", + "type_label_visited": "เยี่ยมชมแล้ว", + "type_label_bookmarked": "เพิ่มที่คั่นหน้าแล้ว", + "type_label_recommended": "กำลังนิยม", + "type_label_pocket": "บันทึกไปยัง Pocket แล้ว", + "menu_action_bookmark": "เพิ่มที่คั่นหน้า", + "menu_action_remove_bookmark": "เอาที่คั่นหน้าออก", + "menu_action_open_new_window": "เปิดในหน้าต่างใหม่", + "menu_action_open_private_window": "เปิดในหน้าต่างส่วนตัวใหม่", + "menu_action_dismiss": "ยกเลิก", + "menu_action_delete": "ลบออกจากประวัติ", + "menu_action_pin": "ปักหมุด", + "menu_action_unpin": "ถอนหมุด", + "confirm_history_delete_p1": "คุณแน่ใจหรือไม่ว่าต้องการลบทุกอินสแตนซ์ของหน้านี้ออกจากประวัติของคุณ?", + "confirm_history_delete_notice_p2": "การกระทำนี้ไม่สามารถเลิกทำได้", + "menu_action_save_to_pocket": "บันทึกไปยัง Pocket", + "menu_action_delete_pocket": "ลบจาก Pocket", + "menu_action_archive_pocket": "เก็บถาวรใน Pocket", + "search_button": "ค้นหา", + "search_header": "ค้นหา {search_engine_name}", + "search_web_placeholder": "ค้นหาเว็บ", + "section_disclaimer_topstories": "เรื่องราวที่น่าสนใจที่สุดบนเว็บ เลือกตามสิ่งที่คุณอ่าน จาก Pocket ซึ่งขณะนี้เป็นส่วนหนึ่งของ Mozilla", + "section_disclaimer_topstories_linktext": "เรียนรู้วิธีการทำงาน", + "section_disclaimer_topstories_buttontext": "ตกลง เข้าใจแล้ว", + "prefs_home_header": "เนื้อหาหน้าแรก Firefox", + "prefs_home_description": "เลือกเนื้อหาที่คุณต้องการในหน้าจอหน้าแรก Firefox ของคุณ", + "prefs_restore_defaults_button": "เรียกคืนค่าเริ่มต้น", + "prefs_section_rows_option": "{num} แถว", + "prefs_search_header": "การค้นหาเว็บ", + "prefs_topsites_description": "ไซต์ที่คุณเยี่ยมชมมากที่สุด", + "prefs_topstories_description": "High-quality content you might otherwise miss", + "prefs_topstories_show_sponsored_label": "เรื่องราวที่สนับสนุนโดย {provider}", + "prefs_topstories_sponsored_learn_more": "เรียนรู้เพิ่มเติม", + "prefs_highlights_description": "การคัดเลือกไซต์ที่คุณได้บันทึกไว้หรือเยี่ยมชม", + "prefs_snippets_description": "ข้อมูลอัปเดตจาก Mozilla และ Firefox", + "settings_pane_button_label": "ปรับแต่งหน้าแท็บใหม่ของคุณ", + "settings_pane_header": "ค่ากำหนดแท็บใหม่", + "settings_pane_body2": "เลือกสิ่งที่คุณเห็นในหน้านี้", + "settings_pane_search_header": "ค้นหา", + "settings_pane_search_body": "ค้นหาเว็บจากแท็บใหม่ของคุณ", + "settings_pane_topsites_header": "ไซต์เด่น", + "settings_pane_topsites_body": "เข้าถึงเว็บไซต์ที่คุณเยี่ยมชมมากที่สุด", + "settings_pane_topsites_options_showmore": "แสดงสองแถว", + "settings_pane_highlights_header": "รายการเด่น", + "settings_pane_highlights_body2": "ค้นหาทางของคุณกลับไปยังสิ่งที่น่าสนใจที่คุณได้เยี่ยมชมหรือเพิ่มที่คั่นหน้าไว้ล่าสุด", + "settings_pane_highlights_options_bookmarks": "ที่คั่นหน้า", + "settings_pane_highlights_options_visited": "ไซต์ที่เยี่ยมชมแล้ว", + "settings_pane_snippets_header": "ส่วนย่อย", + "settings_pane_snippets_body": "อ่านข้อมูลอัปเดตที่สั้นและไพเราะจาก Mozilla เกี่ยวกับ Firefox, วัฒนธรรมอินเทอร์เน็ต และมีมแบบสุ่มเป็นครั้งคราว", + "settings_pane_done_button": "เสร็จสิ้น", + "settings_pane_topstories_options_sponsored": "แสดงเรื่องราวที่ได้รับการสนับสนุน", + "edit_topsites_button_text": "แก้ไข", + "edit_topsites_edit_button": "แก้ไขไซต์นี้", + "topsites_form_add_header": "ไซต์เด่นใหม่", + "topsites_form_edit_header": "แก้ไขไซต์เด่น", + "topsites_form_title_label": "ชื่อเรื่อง", + "topsites_form_title_placeholder": "ป้อนชื่อเรื่อง", + "topsites_form_url_label": "URL", + "topsites_form_image_url_label": "URL ภาพที่กำหนดเอง", + "topsites_form_url_placeholder": "พิมพ์หรือวาง URL", + "topsites_form_use_image_link": "ใช้ภาพที่กำหนดเอง…", + "topsites_form_preview_button": "แสดงตัวอย่าง", + "topsites_form_add_button": "เพิ่ม", + "topsites_form_save_button": "บันทึก", + "topsites_form_cancel_button": "ยกเลิก", + "topsites_form_url_validation": "ต้องการ URL ที่ถูกต้อง", + "topsites_form_image_validation": "ไม่สามารถโหลดภาพ ลอง URL อื่น", + "pocket_read_more": "หัวข้อยอดนิยม:", + "pocket_read_even_more": "ดูเรื่องราวเพิ่มเติม", + "pocket_description": "ค้นพบเนื้อหาคุณภาพสูงที่คุณอาจพลาดไปด้วยความช่วยเหลือจาก Pocket ที่ตอนนี้เป็นส่วนหนึ่งของ Mozilla", + "highlights_empty_state": "เริ่มการท่องเว็บและเราจะแสดงบทความ, วิดีโอ และหน้าอื่น ๆ บางส่วนที่ยอดเยี่ยมที่คุณได้เยี่ยมชมหรือเพิ่มที่คั่นหน้าไว้ล่าสุดที่นี่", + "topstories_empty_state": "คุณได้อ่านเรื่องราวครบทั้งหมดแล้ว คุณสามารถกลับมาตรวจดูเรื่องราวเด่นจาก {provider} ได้ภายหลัง อดใจรอไม่ได้งั้นหรือ? เลือกหัวข้อยอดนิยมเพื่อค้นหาเรื่องราวที่ยอดเยี่ยมจากเว็บต่าง ๆ", + "manual_migration_explanation2": "ลอง Firefox ด้วยที่คั่นหน้า, ประวัติ และรหัสผ่านจากเบราว์เซอร์อื่น", + "manual_migration_cancel_button": "ไม่ ขอบคุณ", + "manual_migration_import_button": "นำเข้าตอนนี้", + "error_fallback_default_info": "อุปส์ มีบางอย่างผิดพลาดในการโหลดเนื้อหานี้", + "error_fallback_default_refresh_suggestion": "เรียกหน้าใหม่เพื่อลองอีกครั้ง", + "section_menu_action_remove_section": "เอาส่วนออก", + "section_menu_action_collapse_section": "ยุบส่วน", + "section_menu_action_expand_section": "ขยายส่วน", + "section_menu_action_manage_section": "จัดการส่วน", + "section_menu_action_add_topsite": "เพิ่มไซต์เด่น", + "section_menu_action_move_up": "ย้ายขึ้น", + "section_menu_action_move_down": "ย้ายลง", + "section_menu_action_privacy_notice": "ประกาศความเป็นส่วนตัว", + "prefs_topstories_description2": "เนื้อหาที่ยอดเยี่ยมจากเว็บต่าง ๆ ปรับแต่งให้เป็นส่วนบุคคลเพื่อคุณ" +}; diff -pruN 1:60.2.1-1/browser/extensions/activity-stream/vendor/prop-types.js 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/vendor/prop-types.js --- 1:60.2.1-1/browser/extensions/activity-stream/vendor/prop-types.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/vendor/prop-types.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1 @@ +!function(f){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=f();else if("function"==typeof define&&define.amd)define([],f);else{var g;g="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,g.PropTypes=f()}}(function(){return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var argIndex = 0; + var message = 'Warning: ' + format.replace(/%s/g, function () { + return args[argIndex++]; + }); + if (typeof console !== 'undefined') { + console.warn(message); + } + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch (x) {} + }; + + lowPriorityWarning = function (condition, format) { + if (format === undefined) { + throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); + } + if (!condition) { + for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { + args[_key2 - 2] = arguments[_key2]; + } + + printWarning.apply(undefined, [format].concat(args)); + } + }; +} + +var lowPriorityWarning$1 = lowPriorityWarning; + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * + */ + +function makeEmptyFunction(arg) { + return function () { + return arg; + }; +} + +/** + * This function accepts and discards inputs; it has no side effects. This is + * primarily useful idiomatically for overridable function endpoints which + * always need to be callable, since JS lacks a null-call idiom ala Cocoa. + */ +var emptyFunction = function emptyFunction() {}; + +emptyFunction.thatReturns = makeEmptyFunction; +emptyFunction.thatReturnsFalse = makeEmptyFunction(false); +emptyFunction.thatReturnsTrue = makeEmptyFunction(true); +emptyFunction.thatReturnsNull = makeEmptyFunction(null); +emptyFunction.thatReturnsThis = function () { + return this; +}; +emptyFunction.thatReturnsArgument = function (arg) { + return arg; +}; + +var emptyFunction_1 = emptyFunction; + +/** + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + + + + + +/** + * Similar to invariant but only logs a warning if the condition is not met. + * This can be used to log issues in development environments in critical + * paths. Removing the logging code for production environments will keep the + * same logic and follow the same code paths. + */ + +var warning = emptyFunction_1; + +{ + var printWarning$1 = function printWarning(format) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var argIndex = 0; + var message = 'Warning: ' + format.replace(/%s/g, function () { + return args[argIndex++]; + }); + if (typeof console !== 'undefined') { + console.error(message); + } + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch (x) {} + }; + + warning = function warning(condition, format) { + if (format === undefined) { + throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); + } + + if (format.indexOf('Failed Composite propType: ') === 0) { + return; // Ignore CompositeComponent proptype check. + } + + if (!condition) { + for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { + args[_key2 - 2] = arguments[_key2]; + } + + printWarning$1.apply(undefined, [format].concat(args)); + } + }; +} + +var warning_1 = warning; + +var didWarnStateUpdateForUnmountedComponent = {}; + +function warnNoop(publicInstance, callerName) { + { + var constructor = publicInstance.constructor; + var componentName = constructor && (constructor.displayName || constructor.name) || 'ReactClass'; + var warningKey = componentName + '.' + callerName; + if (didWarnStateUpdateForUnmountedComponent[warningKey]) { + return; + } + warning_1(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op.\n\nPlease check the code for the %s component.', callerName, callerName, componentName); + didWarnStateUpdateForUnmountedComponent[warningKey] = true; + } +} + +/** + * This is the abstract API for an update queue. + */ +var ReactNoopUpdateQueue = { + /** + * Checks whether or not this composite component is mounted. + * @param {ReactClass} publicInstance The instance we want to test. + * @return {boolean} True if mounted, false otherwise. + * @protected + * @final + */ + isMounted: function (publicInstance) { + return false; + }, + + /** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {?function} callback Called after component is updated. + * @param {?string} callerName name of the calling function in the public API. + * @internal + */ + enqueueForceUpdate: function (publicInstance, callback, callerName) { + warnNoop(publicInstance, 'forceUpdate'); + }, + + /** + * Replaces all of the state. Always use this or `setState` to mutate state. + * You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} completeState Next state. + * @param {?function} callback Called after component is updated. + * @param {?string} callerName name of the calling function in the public API. + * @internal + */ + enqueueReplaceState: function (publicInstance, completeState, callback, callerName) { + warnNoop(publicInstance, 'replaceState'); + }, + + /** + * Sets a subset of the state. This only exists because _pendingState is + * internal. This provides a merging strategy that is not available to deep + * properties which is confusing. TODO: Expose pendingState or don't use it + * during the merge. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} partialState Next partial state to be merged with state. + * @param {?function} callback Called after component is updated. + * @param {?string} Name of the calling function in the public API. + * @internal + */ + enqueueSetState: function (publicInstance, partialState, callback, callerName) { + warnNoop(publicInstance, 'setState'); + } +}; + +/** + * Base class helpers for the updating state of a component. + */ +function Component(props, context, updater) { + this.props = props; + this.context = context; + this.refs = emptyObject_1; + // We initialize the default updater but the real one gets injected by the + // renderer. + this.updater = updater || ReactNoopUpdateQueue; +} + +Component.prototype.isReactComponent = {}; + +/** + * Sets a subset of the state. Always use this to mutate + * state. You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * There is no guarantee that calls to `setState` will run synchronously, + * as they may eventually be batched together. You can provide an optional + * callback that will be executed when the call to setState is actually + * completed. + * + * When a function is provided to setState, it will be called at some point in + * the future (not synchronously). It will be called with the up to date + * component arguments (state, props, context). These values can be different + * from this.* because your function may be called after receiveProps but before + * shouldComponentUpdate, and this new state, props, and context will not yet be + * assigned to this. + * + * @param {object|function} partialState Next partial state or function to + * produce next partial state to be merged with current state. + * @param {?function} callback Called after state is updated. + * @final + * @protected + */ +Component.prototype.setState = function (partialState, callback) { + !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? invariant_1(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : void 0; + this.updater.enqueueSetState(this, partialState, callback, 'setState'); +}; + +/** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {?function} callback Called after update is complete. + * @final + * @protected + */ +Component.prototype.forceUpdate = function (callback) { + this.updater.enqueueForceUpdate(this, callback, 'forceUpdate'); +}; + +/** + * Deprecated APIs. These APIs used to exist on classic React classes but since + * we would like to deprecate them, we're not going to move them over to this + * modern base class. Instead, we define a getter that warns if it's accessed. + */ +{ + var deprecatedAPIs = { + isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'], + replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).'] + }; + var defineDeprecationWarning = function (methodName, info) { + Object.defineProperty(Component.prototype, methodName, { + get: function () { + lowPriorityWarning$1(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]); + return undefined; + } + }); + }; + for (var fnName in deprecatedAPIs) { + if (deprecatedAPIs.hasOwnProperty(fnName)) { + defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); + } + } +} + +/** + * Base class helpers for the updating state of a component. + */ +function PureComponent(props, context, updater) { + // Duplicated from Component. + this.props = props; + this.context = context; + this.refs = emptyObject_1; + // We initialize the default updater but the real one gets injected by the + // renderer. + this.updater = updater || ReactNoopUpdateQueue; +} + +function ComponentDummy() {} +ComponentDummy.prototype = Component.prototype; +var pureComponentPrototype = PureComponent.prototype = new ComponentDummy(); +pureComponentPrototype.constructor = PureComponent; +// Avoid an extra prototype jump for these methods. +objectAssign(pureComponentPrototype, Component.prototype); +pureComponentPrototype.isPureReactComponent = true; + +function AsyncComponent(props, context, updater) { + // Duplicated from Component. + this.props = props; + this.context = context; + this.refs = emptyObject_1; + // We initialize the default updater but the real one gets injected by the + // renderer. + this.updater = updater || ReactNoopUpdateQueue; +} + +var asyncComponentPrototype = AsyncComponent.prototype = new ComponentDummy(); +asyncComponentPrototype.constructor = AsyncComponent; +// Avoid an extra prototype jump for these methods. +objectAssign(asyncComponentPrototype, Component.prototype); +asyncComponentPrototype.unstable_isAsyncReactComponent = true; +asyncComponentPrototype.render = function () { + return this.props.children; +}; + +/** + * Keeps track of the current owner. + * + * The current owner is the component who should own any components that are + * currently being constructed. + */ +var ReactCurrentOwner = { + /** + * @internal + * @type {ReactComponent} + */ + current: null +}; + +var hasOwnProperty$1 = Object.prototype.hasOwnProperty; + +var RESERVED_PROPS = { + key: true, + ref: true, + __self: true, + __source: true +}; + +var specialPropKeyWarningShown; +var specialPropRefWarningShown; + +function hasValidRef(config) { + { + if (hasOwnProperty$1.call(config, 'ref')) { + var getter = Object.getOwnPropertyDescriptor(config, 'ref').get; + if (getter && getter.isReactWarning) { + return false; + } + } + } + return config.ref !== undefined; +} + +function hasValidKey(config) { + { + if (hasOwnProperty$1.call(config, 'key')) { + var getter = Object.getOwnPropertyDescriptor(config, 'key').get; + if (getter && getter.isReactWarning) { + return false; + } + } + } + return config.key !== undefined; +} + +function defineKeyPropWarningGetter(props, displayName) { + var warnAboutAccessingKey = function () { + if (!specialPropKeyWarningShown) { + specialPropKeyWarningShown = true; + warning_1(false, '%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName); + } + }; + warnAboutAccessingKey.isReactWarning = true; + Object.defineProperty(props, 'key', { + get: warnAboutAccessingKey, + configurable: true + }); +} + +function defineRefPropWarningGetter(props, displayName) { + var warnAboutAccessingRef = function () { + if (!specialPropRefWarningShown) { + specialPropRefWarningShown = true; + warning_1(false, '%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName); + } + }; + warnAboutAccessingRef.isReactWarning = true; + Object.defineProperty(props, 'ref', { + get: warnAboutAccessingRef, + configurable: true + }); +} + +/** + * Factory method to create a new React element. This no longer adheres to + * the class pattern, so do not use new to call it. Also, no instanceof check + * will work. Instead test $$typeof field against Symbol.for('react.element') to check + * if something is a React Element. + * + * @param {*} type + * @param {*} key + * @param {string|object} ref + * @param {*} self A *temporary* helper to detect places where `this` is + * different from the `owner` when React.createElement is called, so that we + * can warn. We want to get rid of owner and replace string `ref`s with arrow + * functions, and as long as `this` and owner are the same, there will be no + * change in behavior. + * @param {*} source An annotation object (added by a transpiler or otherwise) + * indicating filename, line number, and/or other information. + * @param {*} owner + * @param {*} props + * @internal + */ +var ReactElement = function (type, key, ref, self, source, owner, props) { + var element = { + // This tag allow us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + + // Built-in properties that belong on the element + type: type, + key: key, + ref: ref, + props: props, + + // Record the component responsible for creating this element. + _owner: owner + }; + + { + // The validation flag is currently mutative. We put it on + // an external backing store so that we can freeze the whole object. + // This can be replaced with a WeakMap once they are implemented in + // commonly used development environments. + element._store = {}; + + // To make comparing ReactElements easier for testing purposes, we make + // the validation flag non-enumerable (where possible, which should + // include every environment we run tests in), so the test framework + // ignores it. + Object.defineProperty(element._store, 'validated', { + configurable: false, + enumerable: false, + writable: true, + value: false + }); + // self and source are DEV only properties. + Object.defineProperty(element, '_self', { + configurable: false, + enumerable: false, + writable: false, + value: self + }); + // Two elements created in two different places should be considered + // equal for testing purposes and therefore we hide it from enumeration. + Object.defineProperty(element, '_source', { + configurable: false, + enumerable: false, + writable: false, + value: source + }); + if (Object.freeze) { + Object.freeze(element.props); + Object.freeze(element); + } + } + + return element; +}; + +/** + * Create and return a new ReactElement of the given type. + * See https://reactjs.org/docs/react-api.html#createelement + */ +function createElement(type, config, children) { + var propName; + + // Reserved names are extracted + var props = {}; + + var key = null; + var ref = null; + var self = null; + var source = null; + + if (config != null) { + if (hasValidRef(config)) { + ref = config.ref; + } + if (hasValidKey(config)) { + key = '' + config.key; + } + + self = config.__self === undefined ? null : config.__self; + source = config.__source === undefined ? null : config.__source; + // Remaining properties are added to a new props object + for (propName in config) { + if (hasOwnProperty$1.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) { + props[propName] = config[propName]; + } + } + } + + // Children can be more than one argument, and those are transferred onto + // the newly allocated props object. + var childrenLength = arguments.length - 2; + if (childrenLength === 1) { + props.children = children; + } else if (childrenLength > 1) { + var childArray = Array(childrenLength); + for (var i = 0; i < childrenLength; i++) { + childArray[i] = arguments[i + 2]; + } + { + if (Object.freeze) { + Object.freeze(childArray); + } + } + props.children = childArray; + } + + // Resolve default props + if (type && type.defaultProps) { + var defaultProps = type.defaultProps; + for (propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } + } + { + if (key || ref) { + if (typeof props.$$typeof === 'undefined' || props.$$typeof !== REACT_ELEMENT_TYPE) { + var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type; + if (key) { + defineKeyPropWarningGetter(props, displayName); + } + if (ref) { + defineRefPropWarningGetter(props, displayName); + } + } + } + } + return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props); +} + +/** + * Return a function that produces ReactElements of a given type. + * See https://reactjs.org/docs/react-api.html#createfactory + */ + + +function cloneAndReplaceKey(oldElement, newKey) { + var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props); + + return newElement; +} + +/** + * Clone and return a new ReactElement using element as the starting point. + * See https://reactjs.org/docs/react-api.html#cloneelement + */ +function cloneElement(element, config, children) { + var propName; + + // Original props are copied + var props = objectAssign({}, element.props); + + // Reserved names are extracted + var key = element.key; + var ref = element.ref; + // Self is preserved since the owner is preserved. + var self = element._self; + // Source is preserved since cloneElement is unlikely to be targeted by a + // transpiler, and the original source is probably a better indicator of the + // true owner. + var source = element._source; + + // Owner will be preserved, unless ref is overridden + var owner = element._owner; + + if (config != null) { + if (hasValidRef(config)) { + // Silently steal the ref from the parent. + ref = config.ref; + owner = ReactCurrentOwner.current; + } + if (hasValidKey(config)) { + key = '' + config.key; + } + + // Remaining properties override existing props + var defaultProps; + if (element.type && element.type.defaultProps) { + defaultProps = element.type.defaultProps; + } + for (propName in config) { + if (hasOwnProperty$1.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) { + if (config[propName] === undefined && defaultProps !== undefined) { + // Resolve default props + props[propName] = defaultProps[propName]; + } else { + props[propName] = config[propName]; + } + } + } + } + + // Children can be more than one argument, and those are transferred onto + // the newly allocated props object. + var childrenLength = arguments.length - 2; + if (childrenLength === 1) { + props.children = children; + } else if (childrenLength > 1) { + var childArray = Array(childrenLength); + for (var i = 0; i < childrenLength; i++) { + childArray[i] = arguments[i + 2]; + } + props.children = childArray; + } + + return ReactElement(element.type, key, ref, self, source, owner, props); +} + +/** + * Verifies the object is a ReactElement. + * See https://reactjs.org/docs/react-api.html#isvalidelement + * @param {?object} object + * @return {boolean} True if `object` is a valid component. + * @final + */ +function isValidElement(object) { + return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; +} + +var ReactDebugCurrentFrame = {}; + +{ + // Component that is being worked on + ReactDebugCurrentFrame.getCurrentStack = null; + + ReactDebugCurrentFrame.getStackAddendum = function () { + var impl = ReactDebugCurrentFrame.getCurrentStack; + if (impl) { + return impl(); + } + return null; + }; +} + +var SEPARATOR = '.'; +var SUBSEPARATOR = ':'; + +/** + * Escape and wrap key so it is safe to use as a reactid + * + * @param {string} key to be escaped. + * @return {string} the escaped key. + */ +function escape(key) { + var escapeRegex = /[=:]/g; + var escaperLookup = { + '=': '=0', + ':': '=2' + }; + var escapedString = ('' + key).replace(escapeRegex, function (match) { + return escaperLookup[match]; + }); + + return '$' + escapedString; +} + +/** + * TODO: Test that a single child and an array with one item have the same key + * pattern. + */ + +var didWarnAboutMaps = false; + +var userProvidedKeyEscapeRegex = /\/+/g; +function escapeUserProvidedKey(text) { + return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/'); +} + +var POOL_SIZE = 10; +var traverseContextPool = []; +function getPooledTraverseContext(mapResult, keyPrefix, mapFunction, mapContext) { + if (traverseContextPool.length) { + var traverseContext = traverseContextPool.pop(); + traverseContext.result = mapResult; + traverseContext.keyPrefix = keyPrefix; + traverseContext.func = mapFunction; + traverseContext.context = mapContext; + traverseContext.count = 0; + return traverseContext; + } else { + return { + result: mapResult, + keyPrefix: keyPrefix, + func: mapFunction, + context: mapContext, + count: 0 + }; + } +} + +function releaseTraverseContext(traverseContext) { + traverseContext.result = null; + traverseContext.keyPrefix = null; + traverseContext.func = null; + traverseContext.context = null; + traverseContext.count = 0; + if (traverseContextPool.length < POOL_SIZE) { + traverseContextPool.push(traverseContext); + } +} + +/** + * @param {?*} children Children tree container. + * @param {!string} nameSoFar Name of the key path so far. + * @param {!function} callback Callback to invoke with each child found. + * @param {?*} traverseContext Used to pass information throughout the traversal + * process. + * @return {!number} The number of children in this subtree. + */ +function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) { + var type = typeof children; + + if (type === 'undefined' || type === 'boolean') { + // All of the above are perceived as null. + children = null; + } + + var invokeCallback = false; + + if (children === null) { + invokeCallback = true; + } else { + switch (type) { + case 'string': + case 'number': + invokeCallback = true; + break; + case 'object': + switch (children.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_CALL_TYPE: + case REACT_RETURN_TYPE: + case REACT_PORTAL_TYPE: + invokeCallback = true; + } + } + } + + if (invokeCallback) { + callback(traverseContext, children, + // If it's the only child, treat the name as if it was wrapped in an array + // so that it's consistent if the number of children grows. + nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar); + return 1; + } + + var child; + var nextName; + var subtreeCount = 0; // Count of children found in the current subtree. + var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR; + + if (Array.isArray(children)) { + for (var i = 0; i < children.length; i++) { + child = children[i]; + nextName = nextNamePrefix + getComponentKey(child, i); + subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext); + } + } else { + var iteratorFn = getIteratorFn(children); + if (typeof iteratorFn === 'function') { + { + // Warn about using Maps as children + if (iteratorFn === children.entries) { + warning_1(didWarnAboutMaps, 'Using Maps as children is unsupported and will likely yield ' + 'unexpected results. Convert it to a sequence/iterable of keyed ' + 'ReactElements instead.%s', ReactDebugCurrentFrame.getStackAddendum()); + didWarnAboutMaps = true; + } + } + + var iterator = iteratorFn.call(children); + var step; + var ii = 0; + while (!(step = iterator.next()).done) { + child = step.value; + nextName = nextNamePrefix + getComponentKey(child, ii++); + subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext); + } + } else if (type === 'object') { + var addendum = ''; + { + addendum = ' If you meant to render a collection of children, use an array ' + 'instead.' + ReactDebugCurrentFrame.getStackAddendum(); + } + var childrenString = '' + children; + invariant_1(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum); + } + } + + return subtreeCount; +} + +/** + * Traverses children that are typically specified as `props.children`, but + * might also be specified through attributes: + * + * - `traverseAllChildren(this.props.children, ...)` + * - `traverseAllChildren(this.props.leftPanelChildren, ...)` + * + * The `traverseContext` is an optional argument that is passed through the + * entire traversal. It can be used to store accumulations or anything else that + * the callback might find relevant. + * + * @param {?*} children Children tree object. + * @param {!function} callback To invoke upon traversing each child. + * @param {?*} traverseContext Context for traversal. + * @return {!number} The number of children in this subtree. + */ +function traverseAllChildren(children, callback, traverseContext) { + if (children == null) { + return 0; + } + + return traverseAllChildrenImpl(children, '', callback, traverseContext); +} + +/** + * Generate a key string that identifies a component within a set. + * + * @param {*} component A component that could contain a manual key. + * @param {number} index Index that is used if a manual key is not provided. + * @return {string} + */ +function getComponentKey(component, index) { + // Do some typechecking here since we call this blindly. We want to ensure + // that we don't block potential future ES APIs. + if (typeof component === 'object' && component !== null && component.key != null) { + // Explicit key + return escape(component.key); + } + // Implicit key determined by the index in the set + return index.toString(36); +} + +function forEachSingleChild(bookKeeping, child, name) { + var func = bookKeeping.func, + context = bookKeeping.context; + + func.call(context, child, bookKeeping.count++); +} + +/** + * Iterates through children that are typically specified as `props.children`. + * + * See https://reactjs.org/docs/react-api.html#react.children.foreach + * + * The provided forEachFunc(child, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} forEachFunc + * @param {*} forEachContext Context for forEachContext. + */ +function forEachChildren(children, forEachFunc, forEachContext) { + if (children == null) { + return children; + } + var traverseContext = getPooledTraverseContext(null, null, forEachFunc, forEachContext); + traverseAllChildren(children, forEachSingleChild, traverseContext); + releaseTraverseContext(traverseContext); +} + +function mapSingleChildIntoContext(bookKeeping, child, childKey) { + var result = bookKeeping.result, + keyPrefix = bookKeeping.keyPrefix, + func = bookKeeping.func, + context = bookKeeping.context; + + + var mappedChild = func.call(context, child, bookKeeping.count++); + if (Array.isArray(mappedChild)) { + mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction_1.thatReturnsArgument); + } else if (mappedChild != null) { + if (isValidElement(mappedChild)) { + mappedChild = cloneAndReplaceKey(mappedChild, + // Keep both the (mapped) and old keys if they differ, just as + // traverseAllChildren used to do for objects as children + keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey); + } + result.push(mappedChild); + } +} + +function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) { + var escapedPrefix = ''; + if (prefix != null) { + escapedPrefix = escapeUserProvidedKey(prefix) + '/'; + } + var traverseContext = getPooledTraverseContext(array, escapedPrefix, func, context); + traverseAllChildren(children, mapSingleChildIntoContext, traverseContext); + releaseTraverseContext(traverseContext); +} + +/** + * Maps children that are typically specified as `props.children`. + * + * See https://reactjs.org/docs/react-api.html#react.children.map + * + * The provided mapFunction(child, key, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} func The map function. + * @param {*} context Context for mapFunction. + * @return {object} Object containing the ordered map of results. + */ +function mapChildren(children, func, context) { + if (children == null) { + return children; + } + var result = []; + mapIntoWithKeyPrefixInternal(children, result, null, func, context); + return result; +} + +/** + * Count the number of children that are typically specified as + * `props.children`. + * + * See https://reactjs.org/docs/react-api.html#react.children.count + * + * @param {?*} children Children tree container. + * @return {number} The number of children. + */ +function countChildren(children, context) { + return traverseAllChildren(children, emptyFunction_1.thatReturnsNull, null); +} + +/** + * Flatten a children object (typically specified as `props.children`) and + * return an array with appropriately re-keyed children. + * + * See https://reactjs.org/docs/react-api.html#react.children.toarray + */ +function toArray(children) { + var result = []; + mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction_1.thatReturnsArgument); + return result; +} + +/** + * Returns the first child in a collection of children and verifies that there + * is only one child in the collection. + * + * See https://reactjs.org/docs/react-api.html#react.children.only + * + * The current implementation of this function assumes that a single child gets + * passed without a wrapper, but the purpose of this helper function is to + * abstract away the particular structure of children. + * + * @param {?object} children Child collection structure. + * @return {ReactElement} The first and only `ReactElement` contained in the + * structure. + */ +function onlyChild(children) { + !isValidElement(children) ? invariant_1(false, 'React.Children.only expected to receive a single React element child.') : void 0; + return children; +} + +var describeComponentFrame = function (name, source, ownerName) { + return '\n in ' + (name || 'Unknown') + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : ''); +}; + +function getComponentName(fiber) { + var type = fiber.type; + + if (typeof type === 'string') { + return type; + } + if (typeof type === 'function') { + return type.displayName || type.name; + } + return null; +} + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + + +var ReactPropTypesSecret$1 = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; + +var ReactPropTypesSecret_1 = ReactPropTypesSecret$1; + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + + +{ + var invariant$2 = invariant_1; + var warning$2 = warning_1; + var ReactPropTypesSecret = ReactPropTypesSecret_1; + var loggedTypeFailures = {}; +} + +/** + * Assert that the values match with the type specs. + * Error messages are memorized and will only be shown once. + * + * @param {object} typeSpecs Map of name to a ReactPropType + * @param {object} values Runtime values that need to be type-checked + * @param {string} location e.g. "prop", "context", "child context" + * @param {string} componentName Name of the component for error messages. + * @param {?Function} getStack Returns the component stack. + * @private + */ +function checkPropTypes(typeSpecs, values, location, componentName, getStack) { + { + for (var typeSpecName in typeSpecs) { + if (typeSpecs.hasOwnProperty(typeSpecName)) { + var error; + // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + invariant$2(typeof typeSpecs[typeSpecName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'the `prop-types` package, but received `%s`.', componentName || 'React class', location, typeSpecName, typeof typeSpecs[typeSpecName]); + error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret); + } catch (ex) { + error = ex; + } + warning$2(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error); + if (error instanceof Error && !(error.message in loggedTypeFailures)) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error.message] = true; + + var stack = getStack ? getStack() : ''; + + warning$2(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : ''); + } + } + } + } +} + +var checkPropTypes_1 = checkPropTypes; + +/** + * ReactElementValidator provides a wrapper around a element factory + * which validates the props passed to the element. This is intended to be + * used only in DEV and could be replaced by a static type checker for languages + * that support it. + */ + +{ + var currentlyValidatingElement = null; + + var propTypesMisspellWarningShown = false; + + var getDisplayName = function (element) { + if (element == null) { + return '#empty'; + } else if (typeof element === 'string' || typeof element === 'number') { + return '#text'; + } else if (typeof element.type === 'string') { + return element.type; + } else if (element.type === REACT_FRAGMENT_TYPE) { + return 'React.Fragment'; + } else { + return element.type.displayName || element.type.name || 'Unknown'; + } + }; + + var getStackAddendum = function () { + var stack = ''; + if (currentlyValidatingElement) { + var name = getDisplayName(currentlyValidatingElement); + var owner = currentlyValidatingElement._owner; + stack += describeComponentFrame(name, currentlyValidatingElement._source, owner && getComponentName(owner)); + } + stack += ReactDebugCurrentFrame.getStackAddendum() || ''; + return stack; + }; + + var VALID_FRAGMENT_PROPS = new Map([['children', true], ['key', true]]); +} + +function getDeclarationErrorAddendum() { + if (ReactCurrentOwner.current) { + var name = getComponentName(ReactCurrentOwner.current); + if (name) { + return '\n\nCheck the render method of `' + name + '`.'; + } + } + return ''; +} + +function getSourceInfoErrorAddendum(elementProps) { + if (elementProps !== null && elementProps !== undefined && elementProps.__source !== undefined) { + var source = elementProps.__source; + var fileName = source.fileName.replace(/^.*[\\\/]/, ''); + var lineNumber = source.lineNumber; + return '\n\nCheck your code at ' + fileName + ':' + lineNumber + '.'; + } + return ''; +} + +/** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ +var ownerHasKeyUseWarning = {}; + +function getCurrentComponentErrorInfo(parentType) { + var info = getDeclarationErrorAddendum(); + + if (!info) { + var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name; + if (parentName) { + info = '\n\nCheck the top-level render call using <' + parentName + '>.'; + } + } + return info; +} + +/** + * Warn if the element doesn't have an explicit key assigned to it. + * This element is in an array. The array could grow and shrink or be + * reordered. All children that haven't already been validated are required to + * have a "key" property assigned to it. Error statuses are cached so a warning + * will only be shown once. + * + * @internal + * @param {ReactElement} element Element that requires a key. + * @param {*} parentType element's parent's type. + */ +function validateExplicitKey(element, parentType) { + if (!element._store || element._store.validated || element.key != null) { + return; + } + element._store.validated = true; + + var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType); + if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + return; + } + ownerHasKeyUseWarning[currentComponentErrorInfo] = true; + + // Usually the current owner is the offender, but if it accepts children as a + // property, it may be the creator of the child that's responsible for + // assigning it a key. + var childOwner = ''; + if (element && element._owner && element._owner !== ReactCurrentOwner.current) { + // Give the component that originally created this child. + childOwner = ' It was passed a child from ' + getComponentName(element._owner) + '.'; + } + + currentlyValidatingElement = element; + { + warning_1(false, 'Each child in an array or iterator should have a unique "key" prop.' + '%s%s See https://fb.me/react-warning-keys for more information.%s', currentComponentErrorInfo, childOwner, getStackAddendum()); + } + currentlyValidatingElement = null; +} + +/** + * Ensure that every element either is passed in a static location, in an + * array with an explicit keys property defined, or in an object literal + * with valid key property. + * + * @internal + * @param {ReactNode} node Statically passed child of any type. + * @param {*} parentType node's parent's type. + */ +function validateChildKeys(node, parentType) { + if (typeof node !== 'object') { + return; + } + if (Array.isArray(node)) { + for (var i = 0; i < node.length; i++) { + var child = node[i]; + if (isValidElement(child)) { + validateExplicitKey(child, parentType); + } + } + } else if (isValidElement(node)) { + // This element was passed in a valid location. + if (node._store) { + node._store.validated = true; + } + } else if (node) { + var iteratorFn = getIteratorFn(node); + if (typeof iteratorFn === 'function') { + // Entry iterators used to provide implicit keys, + // but now we print a separate warning for them later. + if (iteratorFn !== node.entries) { + var iterator = iteratorFn.call(node); + var step; + while (!(step = iterator.next()).done) { + if (isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } + } + } + } + } +} + +/** + * Given an element, validate that its props follow the propTypes definition, + * provided by the type. + * + * @param {ReactElement} element + */ +function validatePropTypes(element) { + var componentClass = element.type; + if (typeof componentClass !== 'function') { + return; + } + var name = componentClass.displayName || componentClass.name; + var propTypes = componentClass.propTypes; + if (propTypes) { + currentlyValidatingElement = element; + checkPropTypes_1(propTypes, element.props, 'prop', name, getStackAddendum); + currentlyValidatingElement = null; + } else if (componentClass.PropTypes !== undefined && !propTypesMisspellWarningShown) { + propTypesMisspellWarningShown = true; + warning_1(false, 'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', name || 'Unknown'); + } + if (typeof componentClass.getDefaultProps === 'function') { + warning_1(componentClass.getDefaultProps.isReactClassApproved, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.'); + } +} + +/** + * Given a fragment, validate that it can only be provided with fragment props + * @param {ReactElement} fragment + */ +function validateFragmentProps(fragment) { + currentlyValidatingElement = fragment; + + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = Object.keys(fragment.props)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var key = _step.value; + + if (!VALID_FRAGMENT_PROPS.has(key)) { + warning_1(false, 'Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.%s', key, getStackAddendum()); + break; + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator['return']) { + _iterator['return'](); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + if (fragment.ref !== null) { + warning_1(false, 'Invalid attribute `ref` supplied to `React.Fragment`.%s', getStackAddendum()); + } + + currentlyValidatingElement = null; +} + +function createElementWithValidation(type, props, children) { + var validType = typeof type === 'string' || typeof type === 'function' || typeof type === 'symbol' || typeof type === 'number'; + // We warn in this case but don't throw. We expect the element creation to + // succeed and there will likely be errors in render. + if (!validType) { + var info = ''; + if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) { + info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and named imports."; + } + + var sourceInfo = getSourceInfoErrorAddendum(props); + if (sourceInfo) { + info += sourceInfo; + } else { + info += getDeclarationErrorAddendum(); + } + + info += getStackAddendum() || ''; + + warning_1(false, 'React.createElement: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', type == null ? type : typeof type, info); + } + + var element = createElement.apply(this, arguments); + + // The result can be nullish if a mock or a custom function is used. + // TODO: Drop this when these are no longer allowed as the type argument. + if (element == null) { + return element; + } + + // Skip key warning if the type isn't valid since our key validation logic + // doesn't expect a non-string/function type and can throw confusing errors. + // We don't want exception behavior to differ between dev and prod. + // (Rendering will throw with a helpful message and as soon as the type is + // fixed, the key warnings will appear.) + if (validType) { + for (var i = 2; i < arguments.length; i++) { + validateChildKeys(arguments[i], type); + } + } + + if (typeof type === 'symbol' && type === REACT_FRAGMENT_TYPE) { + validateFragmentProps(element); + } else { + validatePropTypes(element); + } + + return element; +} + +function createFactoryWithValidation(type) { + var validatedFactory = createElementWithValidation.bind(null, type); + // Legacy hook TODO: Warn if this is accessed + validatedFactory.type = type; + + { + Object.defineProperty(validatedFactory, 'type', { + enumerable: false, + get: function () { + lowPriorityWarning$1(false, 'Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.'); + Object.defineProperty(this, 'type', { + value: type + }); + return type; + } + }); + } + + return validatedFactory; +} + +function cloneElementWithValidation(element, props, children) { + var newElement = cloneElement.apply(this, arguments); + for (var i = 2; i < arguments.length; i++) { + validateChildKeys(arguments[i], newElement.type); + } + validatePropTypes(newElement); + return newElement; +} + +var React = { + Children: { + map: mapChildren, + forEach: forEachChildren, + count: countChildren, + toArray: toArray, + only: onlyChild + }, + + Component: Component, + PureComponent: PureComponent, + unstable_AsyncComponent: AsyncComponent, + + Fragment: REACT_FRAGMENT_TYPE, + + createElement: createElementWithValidation, + cloneElement: cloneElementWithValidation, + createFactory: createFactoryWithValidation, + isValidElement: isValidElement, + + version: ReactVersion, + + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: { + ReactCurrentOwner: ReactCurrentOwner, + // Used by renderers to avoid bundling object-assign twice in UMD bundles: + assign: objectAssign + } +}; + +{ + objectAssign(React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, { + // These should not be included in production. + ReactDebugCurrentFrame: ReactDebugCurrentFrame, + // Shim for React DOM 16.0.0 which still destructured (but not used) this. + // TODO: remove in React 17.0. + ReactComponentTreeHook: {} + }); +} + + + +var React$2 = Object.freeze({ + default: React +}); + +var React$3 = ( React$2 && React ) || React$2; + +// TODO: decide on the top-level export form. +// This is hacky but makes it work with both Rollup and Jest. +var react = React$3['default'] ? React$3['default'] : React$3; + +return react; + +}))); diff -pruN 1:60.2.1-1/browser/extensions/activity-stream/vendor/react-dom-dev.js 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/vendor/react-dom-dev.js --- 1:60.2.1-1/browser/extensions/activity-stream/vendor/react-dom-dev.js 1970-01-01 00:00:00.000000000 +0000 +++ 1:60.2.1+build1-0ubuntu1/browser/extensions/activity-stream/vendor/react-dom-dev.js 2018-10-02 14:08:35.000000000 +0000 @@ -0,0 +1,16068 @@ +/** @license React v16.2.0 + * react-dom.development.js + * + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) : + typeof define === 'function' && define.amd ? define(['react'], factory) : + (global.ReactDOM = factory(global.React)); +}(this, (function (React) { 'use strict'; + +/** + * WARNING: DO NOT manually require this module. + * This is a replacement for `invariant(...)` used by the error code system + * and will _only_ be required by the corresponding babel pass. + * It always throws. + */ + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + + + +/** + * Use invariant() to assert state which your program assumes to be true. + * + * Provide sprintf-style format (only %s is supported) and arguments + * to provide information about what broke and what you were + * expecting. + * + * The invariant message will be stripped in production, but the invariant + * will remain to ensure logic does not differ in production. + */ + +var validateFormat = function validateFormat(format) {}; + +{ + validateFormat = function validateFormat(format) { + if (format === undefined) { + throw new Error('invariant requires an error message argument'); + } + }; +} + +function invariant(condition, format, a, b, c, d, e, f) { + validateFormat(format); + + if (!condition) { + var error; + if (format === undefined) { + error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); + } else { + var args = [a, b, c, d, e, f]; + var argIndex = 0; + error = new Error(format.replace(/%s/g, function () { + return args[argIndex++]; + })); + error.name = 'Invariant Violation'; + } + + error.framesToPop = 1; // we don't care about invariant's own frame + throw error; + } +} + +var invariant_1 = invariant; + +!React ? invariant_1(false, 'ReactDOM was loaded before React. Make sure you load the React package before loading ReactDOM.') : void 0; + +// These attributes should be all lowercase to allow for +// case insensitive checks +var RESERVED_PROPS = { + children: true, + dangerouslySetInnerHTML: true, + defaultValue: true, + defaultChecked: true, + innerHTML: true, + suppressContentEditableWarning: true, + suppressHydrationWarning: true, + style: true +}; + +function checkMask(value, bitmask) { + return (value & bitmask) === bitmask; +} + +var DOMPropertyInjection = { + /** + * Mapping from normalized, camelcased property names to a configuration that + * specifies how the associated DOM property should be accessed or rendered. + */ + MUST_USE_PROPERTY: 0x1, + HAS_BOOLEAN_VALUE: 0x4, + HAS_NUMERIC_VALUE: 0x8, + HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8, + HAS_OVERLOADED_BOOLEAN_VALUE: 0x20, + HAS_STRING_BOOLEAN_VALUE: 0x40, + + /** + * Inject some specialized knowledge about the DOM. This takes a config object + * with the following properties: + * + * Properties: object mapping DOM property name to one of the + * DOMPropertyInjection constants or null. If your attribute isn't in here, + * it won't get written to the DOM. + * + * DOMAttributeNames: object mapping React attribute name to the DOM + * attribute name. Attribute names not specified use the **lowercase** + * normalized name. + * + * DOMAttributeNamespaces: object mapping React attribute name to the DOM + * attribute namespace URL. (Attribute names not specified use no namespace.) + * + * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties. + * Property names not specified use the normalized name. + * + * DOMMutationMethods: Properties that require special mutation methods. If + * `value` is undefined, the mutation method should unset the property. + * + * @param {object} domPropertyConfig the config as described above. + */ + injectDOMPropertyConfig: function (domPropertyConfig) { + var Injection = DOMPropertyInjection; + var Properties = domPropertyConfig.Properties || {}; + var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {}; + var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {}; + var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {}; + + for (var propName in Properties) { + !!properties.hasOwnProperty(propName) ? invariant_1(false, "injectDOMPropertyConfig(...): You're trying to inject DOM property '%s' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.", propName) : void 0; + + var lowerCased = propName.toLowerCase(); + var propConfig = Properties[propName]; + + var propertyInfo = { + attributeName: lowerCased, + attributeNamespace: null, + propertyName: propName, + mutationMethod: null, + + mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY), + hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE), + hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE), + hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE), + hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE), + hasStringBooleanValue: checkMask(propConfig, Injection.HAS_STRING_BOOLEAN_VALUE) + }; + !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? invariant_1(false, "DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s", propName) : void 0; + + if (DOMAttributeNames.hasOwnProperty(propName)) { + var attributeName = DOMAttributeNames[propName]; + + propertyInfo.attributeName = attributeName; + } + + if (DOMAttributeNamespaces.hasOwnProperty(propName)) { + propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName]; + } + + if (DOMMutationMethods.hasOwnProperty(propName)) { + propertyInfo.mutationMethod = DOMMutationMethods[propName]; + } + + // Downcase references to whitelist properties to check for membership + // without case-sensitivity. This allows the whitelist to pick up + // `allowfullscreen`, which should be written using the property configuration + // for `allowFullscreen` + properties[propName] = propertyInfo; + } + } +}; + +/* eslint-disable max-len */ +var ATTRIBUTE_NAME_START_CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; +/* eslint-enable max-len */ +var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; + + +var ROOT_ATTRIBUTE_NAME = 'data-reactroot'; + +/** + * Map from property "standard name" to an object with info about how to set + * the property in the DOM. Each object contains: + * + * attributeName: + * Used when rendering markup or with `*Attribute()`. + * attributeNamespace + * propertyName: + * Used on DOM node instances. (This includes properties that mutate due to + * external factors.) + * mutationMethod: + * If non-null, used instead of the property or `setAttribute()` after + * initial render. + * mustUseProperty: + * Whether the property must be accessed and mutated as an object property. + * hasBooleanValue: + * Whether the property should be removed when set to a falsey value. + * hasNumericValue: + * Whether the property must be numeric or parse as a numeric and should be + * removed when set to a falsey value. + * hasPositiveNumericValue: + * Whether the property must be positive numeric or parse as a positive + * numeric and should be removed when set to a falsey value. + * hasOverloadedBooleanValue: + * Whether the property can be used as a flag as well as with a value. + * Removed when strictly equal to false; present without a value when + * strictly equal to true; present with a value otherwise. + */ +var properties = {}; + +/** + * Checks whether a property name is a writeable attribute. + * @method + */ +function shouldSetAttribute(name, value) { + if (isReservedProp(name)) { + return false; + } + if (name.length > 2 && (name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) { + return false; + } + if (value === null) { + return true; + } + switch (typeof value) { + case 'boolean': + return shouldAttributeAcceptBooleanValue(name); + case 'undefined': + case 'number': + case 'string': + case 'object': + return true; + default: + // function, symbol + return false; + } +} + +function getPropertyInfo(name) { + return properties.hasOwnProperty(name) ? properties[name] : null; +} + +function shouldAttributeAcceptBooleanValue(name) { + if (isReservedProp(name)) { + return true; + } + var propertyInfo = getPropertyInfo(name); + if (propertyInfo) { + return propertyInfo.hasBooleanValue || propertyInfo.hasStringBooleanValue || propertyInfo.hasOverloadedBooleanValue; + } + var prefix = name.toLowerCase().slice(0, 5); + return prefix === 'data-' || prefix === 'aria-'; +} + +/** + * Checks to see if a property name is within the list of properties + * reserved for internal React operations. These properties should + * not be set on an HTML element. + * + * @private + * @param {string} name + * @return {boolean} If the name is within reserved props + */ +function isReservedProp(name) { + return RESERVED_PROPS.hasOwnProperty(name); +} + +var injection = DOMPropertyInjection; + +var MUST_USE_PROPERTY = injection.MUST_USE_PROPERTY; +var HAS_BOOLEAN_VALUE = injection.HAS_BOOLEAN_VALUE; +var HAS_NUMERIC_VALUE = injection.HAS_NUMERIC_VALUE; +var HAS_POSITIVE_NUMERIC_VALUE = injection.HAS_POSITIVE_NUMERIC_VALUE; +var HAS_OVERLOADED_BOOLEAN_VALUE = injection.HAS_OVERLOADED_BOOLEAN_VALUE; +var HAS_STRING_BOOLEAN_VALUE = injection.HAS_STRING_BOOLEAN_VALUE; + +var HTMLDOMPropertyConfig = { + // When adding attributes to this list, be sure to also add them to + // the `possibleStandardNames` module to ensure casing and incorrect + // name warnings. + Properties: { + allowFullScreen: HAS_BOOLEAN_VALUE, + // specifies target context for links with `preload` type + async: HAS_BOOLEAN_VALUE, + // Note: there is a special case that prevents it from being written to the DOM + // on the client side because the browsers are inconsistent. Instead we call focus(). + autoFocus: HAS_BOOLEAN_VALUE, + autoPlay: HAS_BOOLEAN_VALUE, + capture: HAS_OVERLOADED_BOOLEAN_VALUE, + checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + cols: HAS_POSITIVE_NUMERIC_VALUE, + contentEditable: HAS_STRING_BOOLEAN_VALUE, + controls: HAS_BOOLEAN_VALUE, + 'default': HAS_BOOLEAN_VALUE, + defer: HAS_BOOLEAN_VALUE, + disabled: HAS_BOOLEAN_VALUE, + download: HAS_OVERLOADED_BOOLEAN_VALUE, + draggable: HAS_STRING_BOOLEAN_VALUE, + formNoValidate: HAS_BOOLEAN_VALUE, + hidden: HAS_BOOLEAN_VALUE, + loop: HAS_BOOLEAN_VALUE, + // Caution; `option.selected` is not updated if `select.multiple` is + // disabled with `removeAttribute`. + multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + noValidate: HAS_BOOLEAN_VALUE, + open: HAS_BOOLEAN_VALUE, + playsInline: HAS_BOOLEAN_VALUE, + readOnly: HAS_BOOLEAN_VALUE, + required: HAS_BOOLEAN_VALUE, + reversed: HAS_BOOLEAN_VALUE, + rows: HAS_POSITIVE_NUMERIC_VALUE, + rowSpan: HAS_NUMERIC_VALUE, + scoped: HAS_BOOLEAN_VALUE, + seamless: HAS_BOOLEAN_VALUE, + selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + size: HAS_POSITIVE_NUMERIC_VALUE, + start: HAS_NUMERIC_VALUE, + // support for projecting regular DOM Elements via V1 named slots ( shadow dom ) + span: HAS_POSITIVE_NUMERIC_VALUE, + spellCheck: HAS_STRING_BOOLEAN_VALUE, + // Style must be explicitly set in the attribute list. React components + // expect a style object + style: 0, + // Keep it in the whitelist because it is case-sensitive for SVG. + tabIndex: 0, + // itemScope is for for Microdata support. + // See http://schema.org/docs/gs.html + itemScope: HAS_BOOLEAN_VALUE, + // These attributes must stay in the white-list because they have + // different attribute names (see DOMAttributeNames below) + acceptCharset: 0, + className: 0, + htmlFor: 0, + httpEquiv: 0, + // Attributes with mutation methods must be specified in the whitelist + // Set the string boolean flag to allow the behavior + value: HAS_STRING_BOOLEAN_VALUE + }, + DOMAttributeNames: { + acceptCharset: 'accept-charset', + className: 'class', + htmlFor: 'for', + httpEquiv: 'http-equiv' + }, + DOMMutationMethods: { + value: function (node, value) { + if (value == null) { + return node.removeAttribute('value'); + } + + // Number inputs get special treatment due to some edge cases in + // Chrome. Let everything else assign the value attribute as normal. + // https://github.com/facebook/react/issues/7253#issuecomment-236074326 + if (node.type !== 'number' || node.hasAttribute('value') === false) { + node.setAttribute('value', '' + value); + } else if (node.validity && !node.validity.badInput && node.ownerDocument.activeElement !== node) { + // Don't assign an attribute if validation reports bad + // input. Chrome will clear the value. Additionally, don't + // operate on inputs that have focus, otherwise Chrome might + // strip off trailing decimal places and cause the user's + // cursor position to jump to the beginning of the input. + // + // In ReactDOMInput, we have an onBlur event that will trigger + // this function again when focus is lost. + node.setAttribute('value', '' + value); + } + } + } +}; + +var HAS_STRING_BOOLEAN_VALUE$1 = injection.HAS_STRING_BOOLEAN_VALUE; + + +var NS = { + xlink: 'http://www.w3.org/1999/xlink', + xml: 'http://www.w3.org/XML/1998/namespace' +}; + +/** + * This is a list of all SVG attributes that need special casing, + * namespacing, or boolean value assignment. + * + * When adding attributes to this list, be sure to also add them to + * the `possibleStandardNames` module to ensure casing and incorrect + * name warnings. + * + * SVG Attributes List: + * https://www.w3.org/TR/SVG/attindex.html + * SMIL Spec: + * https://www.w3.org/TR/smil + */ +var ATTRS = ['accent-height', 'alignment-baseline', 'arabic-form', 'baseline-shift', 'cap-height', 'clip-path', 'clip-rule', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'dominant-baseline', 'enable-background', 'fill-opacity', 'fill-rule', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-name', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'horiz-adv-x', 'horiz-origin-x', 'image-rendering', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'overline-position', 'overline-thickness', 'paint-order', 'panose-1', 'pointer-events', 'rendering-intent', 'shape-rendering', 'stop-color', 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'underline-position', 'underline-thickness', 'unicode-bidi', 'unicode-range', 'units-per-em', 'v-alphabetic', 'v-hanging', 'v-ideographic', 'v-mathematical', 'vector-effect', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'word-spacing', 'writing-mode', 'x-height', 'xlink:actuate', 'xlink:arcrole', 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type', 'xml:base', 'xmlns:xlink', 'xml:lang', 'xml:space']; + +var SVGDOMPropertyConfig = { + Properties: { + autoReverse: HAS_STRING_BOOLEAN_VALUE$1, + externalResourcesRequired: HAS_STRING_BOOLEAN_VALUE$1, + preserveAlpha: HAS_STRING_BOOLEAN_VALUE$1 + }, + DOMAttributeNames: { + autoReverse: 'autoReverse', + externalResourcesRequired: 'externalResourcesRequired', + preserveAlpha: 'preserveAlpha' + }, + DOMAttributeNamespaces: { + xlinkActuate: NS.xlink, + xlinkArcrole: NS.xlink, + xlinkHref: NS.xlink, + xlinkRole: NS.xlink, + xlinkShow: NS.xlink, + xlinkTitle: NS.xlink, + xlinkType: NS.xlink, + xmlBase: NS.xml, + xmlLang: NS.xml, + xmlSpace: NS.xml + } +}; + +var CAMELIZE = /[\-\:]([a-z])/g; +var capitalize = function (token) { + return token[1].toUpperCase(); +}; + +ATTRS.forEach(function (original) { + var reactName = original.replace(CAMELIZE, capitalize); + + SVGDOMPropertyConfig.Properties[reactName] = 0; + SVGDOMPropertyConfig.DOMAttributeNames[reactName] = original; +}); + +injection.injectDOMPropertyConfig(HTMLDOMPropertyConfig); +injection.injectDOMPropertyConfig(SVGDOMPropertyConfig); + +var ReactErrorUtils = { + // Used by Fiber to simulate a try-catch. + _caughtError: null, + _hasCaughtError: false, + + // Used by event system to capture/rethrow the first error. + _rethrowError: null, + _hasRethrowError: false, + + injection: { + injectErrorUtils: function (injectedErrorUtils) { + !(typeof injectedErrorUtils.invokeGuardedCallback === 'function') ? invariant_1(false, 'Injected invokeGuardedCallback() must be a function.') : void 0; + invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback; + } + }, + + /** + * Call a function while guarding against errors that happens within it. + * Returns an error if it throws, otherwise null. + * + * In production, this is implemented using a try-catch. The reason we don't + * use a try-catch directly is so that we can swap out a different + * implementation in DEV mode. + * + * @param {String} name of the guard to use for logging or debugging + * @param {Function} func The function to invoke + * @param {*} context The context to use when calling the function + * @param {...*} args Arguments for function + */ + invokeGuardedCallback: function (name, func, context, a, b, c, d, e, f) { + invokeGuardedCallback.apply(ReactErrorUtils, arguments); + }, + + /** + * Same as invokeGuardedCallback, but instead of returning an error, it stores + * it in a global so it can be rethrown by `rethrowCaughtError` later. + * TODO: See if _caughtError and _rethrowError can be unified. + * + * @param {String} name of the guard to use for logging or debugging + * @param {Function} func The function to invoke + * @param {*} context The context to use when calling the function + * @param {...*} args Arguments for function + */ + invokeGuardedCallbackAndCatchFirstError: function (name, func, context, a, b, c, d, e, f) { + ReactErrorUtils.invokeGuardedCallback.apply(this, arguments); + if (ReactErrorUtils.hasCaughtError()) { + var error = ReactErrorUtils.clearCaughtError(); + if (!ReactErrorUtils._hasRethrowError) { + ReactErrorUtils._hasRethrowError = true; + ReactErrorUtils._rethrowError = error; + } + } + }, + + /** + * During execution of guarded functions we will capture the first error which + * we will rethrow to be handled by the top level error handler. + */ + rethrowCaughtError: function () { + return rethrowCaughtError.apply(ReactErrorUtils, arguments); + }, + + hasCaughtError: function () { + return ReactErrorUtils._hasCaughtError; + }, + + clearCaughtError: function () { + if (ReactErrorUtils._hasCaughtError) { + var error = ReactErrorUtils._caughtError; + ReactErrorUtils._caughtError = null; + ReactErrorUtils._hasCaughtError = false; + return error; + } else { + invariant_1(false, 'clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue.'); + } + } +}; + +var invokeGuardedCallback = function (name, func, context, a, b, c, d, e, f) { + ReactErrorUtils._hasCaughtError = false; + ReactErrorUtils._caughtError = null; + var funcArgs = Array.prototype.slice.call(arguments, 3); + try { + func.apply(context, funcArgs); + } catch (error) { + ReactErrorUtils._caughtError = error; + ReactErrorUtils._hasCaughtError = true; + } +}; + +{ + // In DEV mode, we swap out invokeGuardedCallback for a special version + // that plays more nicely with the browser's DevTools. The idea is to preserve + // "Pause on exceptions" behavior. Because React wraps all user-provided + // functions in invokeGuardedCallback, and the production version of + // invokeGuardedCallback uses a try-catch, all user exceptions are treated + // like caught exceptions, and the DevTools won't pause unless the developer + // takes the extra step of enabling pause on caught exceptions. This is + // untintuitive, though, because even though React has caught the error, from + // the developer's perspective, the error is uncaught. + // + // To preserve the expected "Pause on exceptions" behavior, we don't use a + // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake + // DOM node, and call the user-provided callback from inside an event handler + // for that fake event. If the callback throws, the error is "captured" using + // a global event handler. But because the error happens in a different + // event loop context, it does not interrupt the normal program flow. + // Effectively, this gives us try-catch behavior without actually using + // try-catch. Neat! + + // Check that the browser supports the APIs we need to implement our special + // DEV version of invokeGuardedCallback + if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') { + var fakeNode = document.createElement('react'); + + var invokeGuardedCallbackDev = function (name, func, context, a, b, c, d, e, f) { + // Keeps track of whether the user-provided callback threw an error. We + // set this to true at the beginning, then set it to false right after + // calling the function. If the function errors, `didError` will never be + // set to false. This strategy works even if the browser is flaky and + // fails to call our global error handler, because it doesn't rely on + // the error event at all. + var didError = true; + + // Create an event handler for our fake event. We will synchronously + // dispatch our fake event using `dispatchEvent`. Inside the handler, we + // call the user-provided callback. + var funcArgs = Array.prototype.slice.call(arguments, 3); + function callCallback() { + // We immediately remove the callback from event listeners so that + // nested `invokeGuardedCallback` calls do not clash. Otherwise, a + // nested call would trigger the fake event handlers of any call higher + // in the stack. + fakeNode.removeEventListener(evtType, callCallback, false); + func.apply(context, funcArgs); + didError = false; + } + + // Create a global error event handler. We use this to capture the value + // that was thrown. It's possible that this error handler will fire more + // than once; for example, if non-React code also calls `dispatchEvent` + // and a handler for that event throws. We should be resilient to most of + // those cases. Even if our error event handler fires more than once, the + // last error event is always used. If the callback actually does error, + // we know that the last error event is the correct one, because it's not + // possible for anything else to have happened in between our callback + // erroring and the code that follows the `dispatchEvent` call below. If + // the callback doesn't error, but the error event was fired, we know to + // ignore it because `didError` will be false, as described above. + var error = void 0; + // Use this to track whether the error event is ever called. + var didSetError = false; + var isCrossOriginError = false; + + function onError(event) { + error = event.error; + didSetError = true; + if (error === null && event.colno === 0 && event.lineno === 0) { + isCrossOriginError = true; + } + } + + // Create a fake event type. + var evtType = 'react-' + (name ? name : 'invokeguardedcallback'); + + // Attach our event handlers + window.addEventListener('error', onError); + fakeNode.addEventListener(evtType, callCallback, false); + + // Synchronously dispatch our fake event. If the user-provided function + // errors, it will trigger our global error handler. + var evt = document.createEvent('Event'); + evt.initEvent(evtType, false, false); + fakeNode.dispatchEvent(evt); + + if (didError) { + if (!didSetError) { + // The callback errored, but the error event never fired. + error = new Error('An error was thrown inside one of your components, but React ' + "doesn't know what it was. This is likely due to browser " + 'flakiness. React does its best to preserve the "Pause on ' + 'exceptions" behavior of the DevTools, which requires some ' + "DEV-mode only tricks. It's possible that these don't work in " + 'your browser. Try triggering the error in production mode, ' + 'or switching to a modern browser. If you suspect that this is ' + 'actually an issue with React, please file an issue.'); + } else if (isCrossOriginError) { + error = new Error("A cross-origin error was thrown. React doesn't have access to " + 'the actual error object in development. ' + 'See https://fb.me/react-crossorigin-error for more information.'); + } + ReactErrorUtils._hasCaughtError = true; + ReactErrorUtils._caughtError = error; + } else { + ReactErrorUtils._hasCaughtError = false; + ReactErrorUtils._caughtError = null; + } + + // Remove our event listeners + window.removeEventListener('error', onError); + }; + + invokeGuardedCallback = invokeGuardedCallbackDev; + } +} + +var rethrowCaughtError = function () { + if (ReactErrorUtils._hasRethrowError) { + var error = ReactErrorUtils._rethrowError; + ReactErrorUtils._rethrowError = null; + ReactErrorUtils._hasRethrowError = false; + throw error; + } +}; + +/** + * Injectable ordering of event plugins. + */ +var eventPluginOrder = null; + +/** + * Injectable mapping from names to event plugin modules. + */ +var namesToPlugins = {}; + +/** + * Recomputes the plugin list using the injected plugins and plugin ordering. + * + * @private + */ +function recomputePluginOrdering() { + if (!eventPluginOrder) { + // Wait until an `eventPluginOrder` is injected. + return; + } + for (var pluginName in namesToPlugins) { + var pluginModule = namesToPlugins[pluginName]; + var pluginIndex = eventPluginOrder.indexOf(pluginName); + !(pluginIndex > -1) ? invariant_1(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : void 0; + if (plugins[pluginIndex]) { + continue; + } + !pluginModule.extractEvents ? invariant_1(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : void 0; + plugins[pluginIndex] = pluginModule; + var publishedEvents = pluginModule.eventTypes; + for (var eventName in publishedEvents) { + !publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) ? invariant_1(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : void 0; + } + } +} + +/** + * Publishes an event so that it can be dispatched by the supplied plugin. + * + * @param {object} dispatchConfig Dispatch configuration for the event. + * @param {object} PluginModule Plugin publishing the event. + * @return {boolean} True if the event was successfully published. + * @private + */ +function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { + !!eventNameDispatchConfigs.hasOwnProperty(eventName) ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : void 0; + eventNameDispatchConfigs[eventName] = dispatchConfig; + + var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + if (phasedRegistrationNames) { + for (var phaseName in phasedRegistrationNames) { + if (phasedRegistrationNames.hasOwnProperty(phaseName)) { + var phasedRegistrationName = phasedRegistrationNames[phaseName]; + publishRegistrationName(phasedRegistrationName, pluginModule, eventName); + } + } + return true; + } else if (dispatchConfig.registrationName) { + publishRegistrationName(dispatchConfig.registrationName, pluginModule, eventName); + return true; + } + return false; +} + +/** + * Publishes a registration name that is used to identify dispatched events. + * + * @param {string} registrationName Registration name to add. + * @param {object} PluginModule Plugin publishing the event. + * @private + */ +function publishRegistrationName(registrationName, pluginModule, eventName) { + !!registrationNameModules[registrationName] ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : void 0; + registrationNameModules[registrationName] = pluginModule; + registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies; + + { + var lowerCasedName = registrationName.toLowerCase(); + possibleRegistrationNames[lowerCasedName] = registrationName; + + if (registrationName === 'onDoubleClick') { + possibleRegistrationNames.ondblclick = registrationName; + } + } +} + +/** + * Registers plugins so that they can extract and dispatch events. + * + * @see {EventPluginHub} + */ + +/** + * Ordered list of injected plugins. + */ +var plugins = []; + +/** + * Mapping from event name to dispatch config + */ +var eventNameDispatchConfigs = {}; + +/** + * Mapping from registration name to plugin module + */ +var registrationNameModules = {}; + +/** + * Mapping from registration name to event name + */ +var registrationNameDependencies = {}; + +/** + * Mapping from lowercase registration names to the properly cased version, + * used to warn in the case of missing event handlers. Available + * only in true. + * @type {Object} + */ +var possibleRegistrationNames = {}; +// Trust the developer to only use possibleRegistrationNames in true + +/** + * Injects an ordering of plugins (by plugin name). This allows the ordering + * to be decoupled from injection of the actual plugins so that ordering is + * always deterministic regardless of packaging, on-the-fly injection, etc. + * + * @param {array} InjectedEventPluginOrder + * @internal + * @see {EventPluginHub.injection.injectEventPluginOrder} + */ +function injectEventPluginOrder(injectedEventPluginOrder) { + !!eventPluginOrder ? invariant_1(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : void 0; + // Clone the ordering so it cannot be dynamically mutated. + eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder); + recomputePluginOrdering(); +} + +/** + * Injects plugins to be used by `EventPluginHub`. The plugin names must be + * in the ordering injected by `injectEventPluginOrder`. + * + * Plugins can be injected as part of page initialization or on-the-fly. + * + * @param {object} injectedNamesToPlugins Map from names to plugin modules. + * @internal + * @see {EventPluginHub.injection.injectEventPluginsByName} + */ +function injectEventPluginsByName(injectedNamesToPlugins) { + var isOrderingDirty = false; + for (var pluginName in injectedNamesToPlugins) { + if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { + continue; + } + var pluginModule = injectedNamesToPlugins[pluginName]; + if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== pluginModule) { + !!namesToPlugins[pluginName] ? invariant_1(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : void 0; + namesToPlugins[pluginName] = pluginModule; + isOrderingDirty = true; + } + } + if (isOrderingDirty) { + recomputePluginOrdering(); + } +} + +var EventPluginRegistry = Object.freeze({ + plugins: plugins, + eventNameDispatchConfigs: eventNameDispatchConfigs, + registrationNameModules: registrationNameModules, + registrationNameDependencies: registrationNameDependencies, + possibleRegistrationNames: possibleRegistrationNames, + injectEventPluginOrder: injectEventPluginOrder, + injectEventPluginsByName: injectEventPluginsByName +}); + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * + */ + +function makeEmptyFunction(arg) { + return function () { + return arg; + }; +} + +/** + * This function accepts and discards inputs; it has no side effects. This is + * primarily useful idiomatically for overridable function endpoints which + * always need to be callable, since JS lacks a null-call idiom ala Cocoa. + */ +var emptyFunction = function emptyFunction() {}; + +emptyFunction.thatReturns = makeEmptyFunction; +emptyFunction.thatReturnsFalse = makeEmptyFunction(false); +emptyFunction.thatReturnsTrue = makeEmptyFunction(true); +emptyFunction.thatReturnsNull = makeEmptyFunction(null); +emptyFunction.thatReturnsThis = function () { + return this; +}; +emptyFunction.thatReturnsArgument = function (arg) { + return arg; +}; + +var emptyFunction_1 = emptyFunction; + +/** + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + + + + + +/** + * Similar to invariant but only logs a warning if the condition is not met. + * This can be used to log issues in development environments in critical + * paths. Removing the logging code for production environments will keep the + * same logic and follow the same code paths. + */ + +var warning = emptyFunction_1; + +{ + var printWarning = function printWarning(format) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var argIndex = 0; + var message = 'Warning: ' + format.replace(/%s/g, function () { + return args[argIndex++]; + }); + if (typeof console !== 'undefined') { + console.error(message); + } + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch (x) {} + }; + + warning = function warning(condition, format) { + if (format === undefined) { + throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); + } + + if (format.indexOf('Failed Composite propType: ') === 0) { + return; // Ignore CompositeComponent proptype check. + } + + if (!condition) { + for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { + args[_key2 - 2] = arguments[_key2]; + } + + printWarning.apply(undefined, [format].concat(args)); + } + }; +} + +var warning_1 = warning; + +var getFiberCurrentPropsFromNode = null; +var getInstanceFromNode = null; +var getNodeFromInstance = null; + +var injection$2 = { + injectComponentTree: function (Injected) { + getFiberCurrentPropsFromNode = Injected.getFiberCurrentPropsFromNode; + getInstanceFromNode = Injected.getInstanceFromNode; + getNodeFromInstance = Injected.getNodeFromInstance; + + { + warning_1(getNodeFromInstance && getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.'); + } + } +}; + + + + + + +var validateEventDispatches; +{ + validateEventDispatches = function (event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + + var listenersIsArr = Array.isArray(dispatchListeners); + var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0; + + var instancesIsArr = Array.isArray(dispatchInstances); + var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0; + + warning_1(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.'); + }; +} + +/** + * Dispatch the event to the listener. + * @param {SyntheticEvent} event SyntheticEvent to handle + * @param {boolean} simulated If the event is simulated (changes exn behavior) + * @param {function} listener Application-level callback + * @param {*} inst Internal component instance + */ +function executeDispatch(event, simulated, listener, inst) { + var type = event.type || 'unknown-event'; + event.currentTarget = getNodeFromInstance(inst); + ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event); + event.currentTarget = null; +} + +/** + * Standard/simple iteration through an event's collected dispatches. + */ +function executeDispatchesInOrder(event, simulated) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + { + validateEventDispatches(event); + } + if (Array.isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } + // Listeners and Instances are two parallel arrays that are always in sync. + executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]); + } + } else if (dispatchListeners) { + executeDispatch(event, simulated, dispatchListeners, dispatchInstances); + } + event._dispatchListeners = null; + event._dispatchInstances = null; +} + +/** + * @see executeDispatchesInOrderStopAtTrueImpl + */ + + +/** + * Execution of a "direct" dispatch - there must be at most one dispatch + * accumulated on the event or it is considered an error. It doesn't really make + * sense for an event with multiple dispatches (bubbled) to keep track of the + * return values at each dispatch execution, but it does tend to make sense when + * dealing with "direct" dispatches. + * + * @return {*} The return value of executing the single dispatch. + */ + + +/** + * @param {SyntheticEvent} event + * @return {boolean} True iff number of dispatches accumulated is greater than 0. + */ + +/** + * Accumulates items that must not be null or undefined into the first one. This + * is used to conserve memory by avoiding array allocations, and thus sacrifices + * API cleanness. Since `current` can be null before being passed in and not + * null after this function, make sure to assign it back to `current`: + * + * `a = accumulateInto(a, b);` + * + * This API should be sparingly used. Try `accumulate` for something cleaner. + * + * @return {*|array<*>} An accumulation of items. + */ + +function accumulateInto(current, next) { + !(next != null) ? invariant_1(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : void 0; + + if (current == null) { + return next; + } + + // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). + if (Array.isArray(current)) { + if (Array.isArray(next)) { + current.push.apply(current, next); + return current; + } + current.push(next); + return current; + } + + if (Array.isArray(next)) { + // A bit too dangerous to mutate `next`. + return [current].concat(next); + } + + return [current, next]; +} + +/** + * @param {array} arr an "accumulation" of items which is either an Array or + * a single item. Useful when paired with the `accumulate` module. This is a + * simple utility that allows us to reason about a collection of items, but + * handling the case when there is exactly one item (and we do not need to + * allocate an array). + * @param {function} cb Callback invoked with each element or a collection. + * @param {?} [scope] Scope used as `this` in a callback. + */ +function forEachAccumulated(arr, cb, scope) { + if (Array.isArray(arr)) { + arr.forEach(cb, scope); + } else if (arr) { + cb.call(scope, arr); + } +} + +/** + * Internal queue of events that have accumulated their dispatches and are + * waiting to have their dispatches executed. + */ +var eventQueue = null; + +/** + * Dispatches an event and releases it back into the pool, unless persistent. + * + * @param {?object} event Synthetic event to be dispatched. + * @param {boolean} simulated If the event is simulated (changes exn behavior) + * @private + */ +var executeDispatchesAndRelease = function (event, simulated) { + if (event) { + executeDispatchesInOrder(event, simulated); + + if (!event.isPersistent()) { + event.constructor.release(event); + } + } +}; +var executeDispatchesAndReleaseSimulated = function (e) { + return executeDispatchesAndRelease(e, true); +}; +var executeDispatchesAndReleaseTopLevel = function (e) { + return executeDispatchesAndRelease(e, false); +}; + +function isInteractive(tag) { + return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea'; +} + +function shouldPreventMouseEvent(name, type, props) { + switch (name) { + case 'onClick': + case 'onClickCapture': + case 'onDoubleClick': + case 'onDoubleClickCapture': + case 'onMouseDown': + case 'onMouseDownCapture': + case 'onMouseMove': + case 'onMouseMoveCapture': + case 'onMouseUp': + case 'onMouseUpCapture': + return !!(props.disabled && isInteractive(type)); + default: + return false; + } +} + +/** + * This is a unified interface for event plugins to be installed and configured. + * + * Event plugins can implement the following properties: + * + * `extractEvents` {function(string, DOMEventTarget, string, object): *} + * Required. When a top-level event is fired, this method is expected to + * extract synthetic events that will in turn be queued and dispatched. + * + * `eventTypes` {object} + * Optional, plugins that fire events must publish a mapping of registration + * names that are used to register listeners. Values of this mapping must + * be objects that contain `registrationName` or `phasedRegistrationNames`. + * + * `executeDispatch` {function(object, function, string)} + * Optional, allows plugins to override how an event gets dispatched. By + * default, the listener is simply invoked. + * + * Each plugin that is injected into `EventsPluginHub` is immediately operable. + * + * @public + */ + +/** + * Methods for injecting dependencies. + */ +var injection$1 = { + /** + * @param {array} InjectedEventPluginOrder + * @public + */ + injectEventPluginOrder: injectEventPluginOrder, + + /** + * @param {object} injectedNamesToPlugins Map from names to plugin modules. + */ + injectEventPluginsByName: injectEventPluginsByName +}; + +/** + * @param {object} inst The instance, which is the source of events. + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @return {?function} The stored callback. + */ +function getListener(inst, registrationName) { + var listener; + + // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not + // live here; needs to be moved to a better place soon + var stateNode = inst.stateNode; + if (!stateNode) { + // Work in progress (ex: onload events in incremental mode). + return null; + } + var props = getFiberCurrentPropsFromNode(stateNode); + if (!props) { + // Work in progress. + return null; + } + listener = props[registrationName]; + if (shouldPreventMouseEvent(registrationName, inst.type, props)) { + return null; + } + !(!listener || typeof listener === 'function') ? invariant_1(false, 'Expected `%s` listener to be a function, instead got a value of `%s` type.', registrationName, typeof listener) : void 0; + return listener; +} + +/** + * Allows registered plugins an opportunity to extract events from top-level + * native browser events. + * + * @return {*} An accumulation of synthetic events. + * @internal + */ +function extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var events; + for (var i = 0; i < plugins.length; i++) { + // Not every plugin in the ordering may be loaded at runtime. + var possiblePlugin = plugins[i]; + if (possiblePlugin) { + var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget); + if (extractedEvents) { + events = accumulateInto(events, extractedEvents); + } + } + } + return events; +} + +/** + * Enqueues a synthetic event that should be dispatched when + * `processEventQueue` is invoked. + * + * @param {*} events An accumulation of synthetic events. + * @internal + */ +function enqueueEvents(events) { + if (events) { + eventQueue = accumulateInto(eventQueue, events); + } +} + +/** + * Dispatches all synthetic events on the event queue. + * + * @internal + */ +function processEventQueue(simulated) { + // Set `eventQueue` to null before processing it so that we can tell if more + // events get enqueued while processing. + var processingEventQueue = eventQueue; + eventQueue = null; + + if (!processingEventQueue) { + return; + } + + if (simulated) { + forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated); + } else { + forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); + } + !!eventQueue ? invariant_1(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : void 0; + // This would be a good time to rethrow if any of the event handlers threw. + ReactErrorUtils.rethrowCaughtError(); +} + +var EventPluginHub = Object.freeze({ + injection: injection$1, + getListener: getListener, + extractEvents: extractEvents, + enqueueEvents: enqueueEvents, + processEventQueue: processEventQueue +}); + +var IndeterminateComponent = 0; // Before we know whether it is functional or class +var FunctionalComponent = 1; +var ClassComponent = 2; +var HostRoot = 3; // Root of a host tree. Could be nested inside another node. +var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. +var HostComponent = 5; +var HostText = 6; +var CallComponent = 7; +var CallHandlerPhase = 8; +var ReturnComponent = 9; +var Fragment = 10; + +var randomKey = Math.random().toString(36).slice(2); +var internalInstanceKey = '__reactInternalInstance$' + randomKey; +var internalEventHandlersKey = '__reactEventHandlers$' + randomKey; + +function precacheFiberNode$1(hostInst, node) { + node[internalInstanceKey] = hostInst; +} + +/** + * Given a DOM node, return the closest ReactDOMComponent or + * ReactDOMTextComponent instance ancestor. + */ +function getClosestInstanceFromNode(node) { + if (node[internalInstanceKey]) { + return node[internalInstanceKey]; + } + + // Walk up the tree until we find an ancestor whose instance we have cached. + var parents = []; + while (!node[internalInstanceKey]) { + parents.push(node); + if (node.parentNode) { + node = node.parentNode; + } else { + // Top of the tree. This node must not be part of a React tree (or is + // unmounted, potentially). + return null; + } + } + + var closest = void 0; + var inst = node[internalInstanceKey]; + if (inst.tag === HostComponent || inst.tag === HostText) { + // In Fiber, this will always be the deepest root. + return inst; + } + for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) { + closest = inst; + } + + return closest; +} + +/** + * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent + * instance, or null if the node was not rendered by this React. + */ +function getInstanceFromNode$1(node) { + var inst = node[internalInstanceKey]; + if (inst) { + if (inst.tag === HostComponent || inst.tag === HostText) { + return inst; + } else { + return null; + } + } + return null; +} + +/** + * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding + * DOM node. + */ +function getNodeFromInstance$1(inst) { + if (inst.tag === HostComponent || inst.tag === HostText) { + // In Fiber this, is just the state node right now. We assume it will be + // a host component or host text. + return inst.stateNode; + } + + // Without this first invariant, passing a non-DOM-component triggers the next + // invariant for a missing parent, which is super confusing. + invariant_1(false, 'getNodeFromInstance: Invalid argument.'); +} + +function getFiberCurrentPropsFromNode$1(node) { + return node[internalEventHandlersKey] || null; +} + +function updateFiberProps$1(node, props) { + node[internalEventHandlersKey] = props; +} + +var ReactDOMComponentTree = Object.freeze({ + precacheFiberNode: precacheFiberNode$1, + getClosestInstanceFromNode: getClosestInstanceFromNode, + getInstanceFromNode: getInstanceFromNode$1, + getNodeFromInstance: getNodeFromInstance$1, + getFiberCurrentPropsFromNode: getFiberCurrentPropsFromNode$1, + updateFiberProps: updateFiberProps$1 +}); + +function getParent(inst) { + do { + inst = inst['return']; + // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); + if (inst) { + return inst; + } + return null; +} + +/** + * Return the lowest common ancestor of A and B, or null if they are in + * different trees. + */ +function getLowestCommonAncestor(instA, instB) { + var depthA = 0; + for (var tempA = instA; tempA; tempA = getParent(tempA)) { + depthA++; + } + var depthB = 0; + for (var tempB = instB; tempB; tempB = getParent(tempB)) { + depthB++; + } + + // If A is deeper, crawl up. + while (depthA - depthB > 0) { + instA = getParent(instA); + depthA--; + } + + // If B is deeper, crawl up. + while (depthB - depthA > 0) { + instB = getParent(instB); + depthB--; + } + + // Walk in lockstep until we find a match. + var depth = depthA; + while (depth--) { + if (instA === instB || instA === instB.alternate) { + return instA; + } + instA = getParent(instA); + instB = getParent(instB); + } + return null; +} + +/** + * Return if A is an ancestor of B. + */ + + +/** + * Return the parent instance of the passed-in instance. + */ +function getParentInstance(inst) { + return getParent(inst); +} + +/** + * Simulates the traversal of a two-phase, capture/bubble event dispatch. + */ +function traverseTwoPhase(inst, fn, arg) { + var path = []; + while (inst) { + path.push(inst); + inst = getParent(inst); + } + var i; + for (i = path.length; i-- > 0;) { + fn(path[i], 'captured', arg); + } + for (i = 0; i < path.length; i++) { + fn(path[i], 'bubbled', arg); + } +} + +/** + * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that + * should would receive a `mouseEnter` or `mouseLeave` event. + * + * Does not invoke the callback on the nearest common ancestor because nothing + * "entered" or "left" that element. + */ +function traverseEnterLeave(from, to, fn, argFrom, argTo) { + var common = from && to ? getLowestCommonAncestor(from, to) : null; + var pathFrom = []; + while (true) { + if (!from) { + break; + } + if (from === common) { + break; + } + var alternate = from.alternate; + if (alternate !== null && alternate === common) { + break; + } + pathFrom.push(from); + from = getParent(from); + } + var pathTo = []; + while (true) { + if (!to) { + break; + } + if (to === common) { + break; + } + var _alternate = to.alternate; + if (_alternate !== null && _alternate === common) { + break; + } + pathTo.push(to); + to = getParent(to); + } + for (var i = 0; i < pathFrom.length; i++) { + fn(pathFrom[i], 'bubbled', argFrom); + } + for (var _i = pathTo.length; _i-- > 0;) { + fn(pathTo[_i], 'captured', argTo); + } +} + +/** + * Some event types have a notion of different registration names for different + * "phases" of propagation. This finds listeners by a given phase. + */ +function listenerAtPhase(inst, event, propagationPhase) { + var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListener(inst, registrationName); +} + +/** + * A small set of propagation patterns, each of which will accept a small amount + * of information, and generate a set of "dispatch ready event objects" - which + * are sets of events that have already been annotated with a set of dispatched + * listener functions/ids. The API is designed this way to discourage these + * propagation strategies from actually executing the dispatches, since we + * always want to collect the entire set of dispatches before executing even a + * single one. + */ + +/** + * Tags a `SyntheticEvent` with dispatched listeners. Creating this function + * here, allows us to not have to bind or create functions for each event. + * Mutating the event's members allows us to not have to create a wrapping + * "dispatch" object that pairs the event with the listener. + */ +function accumulateDirectionalDispatches(inst, phase, event) { + { + warning_1(inst, 'Dispatching inst must not be null'); + } + var listener = listenerAtPhase(inst, event, phase); + if (listener) { + event._dispatchListeners = accumulateInto(event._dispatchListeners, listener); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } +} + +/** + * Collect dispatches (must be entirely collected before dispatching - see unit + * tests). Lazily allocate the array to conserve memory. We must loop through + * each event and perform the traversal for each one. We cannot perform a + * single traversal for the entire collection of events because each event may + * have a different target. + */ +function accumulateTwoPhaseDispatchesSingle(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); + } +} + +/** + * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID. + */ +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + var parentInst = targetInst ? getParentInstance(targetInst) : null; + traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); + } +} + +/** + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. + */ +function accumulateDispatches(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listener = getListener(inst, registrationName); + if (listener) { + event._dispatchListeners = accumulateInto(event._dispatchListeners, listener); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } + } +} + +/** + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event + */ +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches(event._targetInst, null, event); + } +} + +function accumulateTwoPhaseDispatches(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); +} + +function accumulateTwoPhaseDispatchesSkipTarget(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); +} + +function accumulateEnterLeaveDispatches(leave, enter, from, to) { + traverseEnterLeave(from, to, accumulateDispatches, leave, enter); +} + +function accumulateDirectDispatches(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle); +} + +var EventPropagators = Object.freeze({ + accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches, + accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget, + accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches, + accumulateDirectDispatches: accumulateDirectDispatches +}); + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + + + +var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); + +/** + * Simple, lightweight module assisting with the detection and context of + * Worker. Helps avoid circular dependencies and allows code to reason about + * whether or not they are in a Worker, even if they never include the main + * `ReactWorker` dependency. + */ +var ExecutionEnvironment = { + + canUseDOM: canUseDOM, + + canUseWorkers: typeof Worker !== 'undefined', + + canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent), + + canUseViewport: canUseDOM && !!window.screen, + + isInWorker: !canUseDOM // For now, this is true - might change in the future. + +}; + +var ExecutionEnvironment_1 = ExecutionEnvironment; + +var contentKey = null; + +/** + * Gets the key used to access text content on a DOM node. + * + * @return {?string} Key used to access text content. + * @internal + */ +function getTextContentAccessor() { + if (!contentKey && ExecutionEnvironment_1.canUseDOM) { + // Prefer textContent to innerText because many browsers support both but + // SVG elements don't support innerText even when
does. + contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText'; + } + return contentKey; +} + +/** + * This helper object stores information about text content of a target node, + * allowing comparison of content before and after a given event. + * + * Identify the node where selection currently begins, then observe + * both its text content and its current position in the DOM. Since the + * browser may natively replace the target node during composition, we can + * use its position to find its replacement. + * + * + */ +var compositionState = { + _root: null, + _startText: null, + _fallbackText: null +}; + +function initialize(nativeEventTarget) { + compositionState._root = nativeEventTarget; + compositionState._startText = getText(); + return true; +} + +function reset() { + compositionState._root = null; + compositionState._startText = null; + compositionState._fallbackText = null; +} + +function getData() { + if (compositionState._fallbackText) { + return compositionState._fallbackText; + } + + var start; + var startValue = compositionState._startText; + var startLength = startValue.length; + var end; + var endValue = getText(); + var endLength = endValue.length; + + for (start = 0; start < startLength; start++) { + if (startValue[start] !== endValue[start]) { + break; + } + } + + var minEnd = startLength - start; + for (end = 1; end <= minEnd; end++) { + if (startValue[startLength - end] !== endValue[endLength - end]) { + break; + } + } + + var sliceTail = end > 1 ? 1 - end : undefined; + compositionState._fallbackText = endValue.slice(start, sliceTail); + return compositionState._fallbackText; +} + +function getText() { + if ('value' in compositionState._root) { + return compositionState._root.value; + } + return compositionState._root[getTextContentAccessor()]; +} + +var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + +var _assign = ReactInternals.assign; + +/* eslint valid-typeof: 0 */ + +var didWarnForAddedNewProperty = false; +var isProxySupported = typeof Proxy === 'function'; +var EVENT_POOL_SIZE = 10; + +var shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances']; + +/** + * @interface Event + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ +var EventInterface = { + type: null, + target: null, + // currentTarget is set when dispatching; no use in copying it here + currentTarget: emptyFunction_1.thatReturnsNull, + eventPhase: null, + bubbles: null, + cancelable: null, + timeStamp: function (event) { + return event.timeStamp || Date.now(); + }, + defaultPrevented: null, + isTrusted: null +}; + +/** + * Synthetic events are dispatched by event plugins, typically in response to a + * top-level event delegation handler. + * + * These systems should generally use pooling to reduce the frequency of garbage + * collection. The system should check `isPersistent` to determine whether the + * event should be released into the pool after being dispatched. Users that + * need a persisted event should invoke `persist`. + * + * Synthetic events (and subclasses) implement the DOM Level 3 Events API by + * normalizing browser quirks. Subclasses do not necessarily have to implement a + * DOM interface; custom application-specific events can also subclass this. + * + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {*} targetInst Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @param {DOMEventTarget} nativeEventTarget Target node. + */ +function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) { + { + // these have a getter/setter for warnings + delete this.nativeEvent; + delete this.preventDefault; + delete this.stopPropagation; + } + + this.dispatchConfig = dispatchConfig; + this._targetInst = targetInst; + this.nativeEvent = nativeEvent; + + var Interface = this.constructor.Interface; + for (var propName in Interface) { + if (!Interface.hasOwnProperty(propName)) { + continue; + } + { + delete this[propName]; // this has a getter/setter for warnings + } + var normalize = Interface[propName]; + if (normalize) { + this[propName] = normalize(nativeEvent); + } else { + if (propName === 'target') { + this.target = nativeEventTarget; + } else { + this[propName] = nativeEvent[propName]; + } + } + } + + var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false; + if (defaultPrevented) { + this.isDefaultPrevented = emptyFunction_1.thatReturnsTrue; + } else { + this.isDefaultPrevented = emptyFunction_1.thatReturnsFalse; + } + this.isPropagationStopped = emptyFunction_1.thatReturnsFalse; + return this; +} + +_assign(SyntheticEvent.prototype, { + preventDefault: function () { + this.defaultPrevented = true; + var event = this.nativeEvent; + if (!event) { + return; + } + + if (event.preventDefault) { + event.preventDefault(); + } else if (typeof event.returnValue !== 'unknown') { + event.returnValue = false; + } + this.isDefaultPrevented = emptyFunction_1.thatReturnsTrue; + }, + + stopPropagation: function () { + var event = this.nativeEvent; + if (!event) { + return; + } + + if (event.stopPropagation) { + event.stopPropagation(); + } else if (typeof event.cancelBubble !== 'unknown') { + // The ChangeEventPlugin registers a "propertychange" event for + // IE. This event does not support bubbling or cancelling, and + // any references to cancelBubble throw "Member not found". A + // typeof check of "unknown" circumvents this issue (and is also + // IE specific). + event.cancelBubble = true; + } + + this.isPropagationStopped = emptyFunction_1.thatReturnsTrue; + }, + + /** + * We release all dispatched `SyntheticEvent`s after each event loop, adding + * them back into the pool. This allows a way to hold onto a reference that + * won't be added back into the pool. + */ + persist: function () { + this.isPersistent = emptyFunction_1.thatReturnsTrue; + }, + + /** + * Checks if this event should be released back into the pool. + * + * @return {boolean} True if this should not be released, false otherwise. + */ + isPersistent: emptyFunction_1.thatReturnsFalse, + + /** + * `PooledClass` looks for `destructor` on each instance it releases. + */ + destructor: function () { + var Interface = this.constructor.Interface; + for (var propName in Interface) { + { + Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName])); + } + } + for (var i = 0; i < shouldBeReleasedProperties.length; i++) { + this[shouldBeReleasedProperties[i]] = null; + } + { + Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null)); + Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', emptyFunction_1)); + Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction_1)); + } + } +}); + +SyntheticEvent.Interface = EventInterface; + +/** + * Helper to reduce boilerplate when creating subclasses. + * + * @param {function} Class + * @param {?object} Interface + */ +SyntheticEvent.augmentClass = function (Class, Interface) { + var Super = this; + + var E = function () {}; + E.prototype = Super.prototype; + var prototype = new E(); + + _assign(prototype, Class.prototype); + Class.prototype = prototype; + Class.prototype.constructor = Class; + + Class.Interface = _assign({}, Super.Interface, Interface); + Class.augmentClass = Super.augmentClass; + addEventPoolingTo(Class); +}; + +/** Proxying after everything set on SyntheticEvent + * to resolve Proxy issue on some WebKit browsers + * in which some Event properties are set to undefined (GH#10010) + */ +{ + if (isProxySupported) { + /*eslint-disable no-func-assign */ + SyntheticEvent = new Proxy(SyntheticEvent, { + construct: function (target, args) { + return this.apply(target, Object.create(target.prototype), args); + }, + apply: function (constructor, that, args) { + return new Proxy(constructor.apply(that, args), { + set: function (target, prop, value) { + if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) { + warning_1(didWarnForAddedNewProperty || target.isPersistent(), "This synthetic event is reused for performance reasons. If you're " + "seeing this, you're adding a new property in the synthetic event object. " + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.'); + didWarnForAddedNewProperty = true; + } + target[prop] = value; + return true; + } + }); + } + }); + /*eslint-enable no-func-assign */ + } +} + +addEventPoolingTo(SyntheticEvent); + +/** + * Helper to nullify syntheticEvent instance properties when destructing + * + * @param {String} propName + * @param {?object} getVal + * @return {object} defineProperty object + */ +function getPooledWarningPropertyDefinition(propName, getVal) { + var isFunction = typeof getVal === 'function'; + return { + configurable: true, + set: set, + get: get + }; + + function set(val) { + var action = isFunction ? 'setting the method' : 'setting the property'; + warn(action, 'This is effectively a no-op'); + return val; + } + + function get() { + var action = isFunction ? 'accessing the method' : 'accessing the property'; + var result = isFunction ? 'This is a no-op function' : 'This is set to null'; + warn(action, result); + return getVal; + } + + function warn(action, result) { + var warningCondition = false; + warning_1(warningCondition, "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result); + } +} + +function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { + var EventConstructor = this; + if (EventConstructor.eventPool.length) { + var instance = EventConstructor.eventPool.pop(); + EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst); + return instance; + } + return new EventConstructor(dispatchConfig, targetInst, nativeEvent, nativeInst); +} + +function releasePooledEvent(event) { + var EventConstructor = this; + !(event instanceof EventConstructor) ? invariant_1(false, 'Trying to release an event instance into a pool of a different type.') : void 0; + event.destructor(); + if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) { + EventConstructor.eventPool.push(event); + } +} + +function addEventPoolingTo(EventConstructor) { + EventConstructor.eventPool = []; + EventConstructor.getPooled = getPooledEvent; + EventConstructor.release = releasePooledEvent; +} + +var SyntheticEvent$1 = SyntheticEvent; + +/** + * @interface Event + * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents + */ +var CompositionEventInterface = { + data: null +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticEvent} + */ +function SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticEvent$1.augmentClass(SyntheticCompositionEvent, CompositionEventInterface); + +/** + * @interface Event + * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105 + * /#events-inputevents + */ +var InputEventInterface = { + data: null +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticEvent} + */ +function SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticEvent$1.augmentClass(SyntheticInputEvent, InputEventInterface); + +var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space +var START_KEYCODE = 229; + +var canUseCompositionEvent = ExecutionEnvironment_1.canUseDOM && 'CompositionEvent' in window; + +var documentMode = null; +if (ExecutionEnvironment_1.canUseDOM && 'documentMode' in document) { + documentMode = document.documentMode; +} + +// Webkit offers a very useful `textInput` event that can be used to +// directly represent `beforeInput`. The IE `textinput` event is not as +// useful, so we don't use it. +var canUseTextInputEvent = ExecutionEnvironment_1.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto(); + +// In IE9+, we have access to composition events, but the data supplied +// by the native compositionend event may be incorrect. Japanese ideographic +// spaces, for instance (\u3000) are not recorded correctly. +var useFallbackCompositionData = ExecutionEnvironment_1.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11); + +/** + * Opera <= 12 includes TextEvent in window, but does not fire + * text input events. Rely on keypress instead. + */ +function isPresto() { + var opera = window.opera; + return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12; +} + +var SPACEBAR_CODE = 32; +var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE); + +// Events and their corresponding property names. +var eventTypes = { + beforeInput: { + phasedRegistrationNames: { + bubbled: 'onBeforeInput', + captured: 'onBeforeInputCapture' + }, + dependencies: ['topCompositionEnd', 'topKeyPress', 'topTextInput', 'topPaste'] + }, + compositionEnd: { + phasedRegistrationNames: { + bubbled: 'onCompositionEnd', + captured: 'onCompositionEndCapture' + }, + dependencies: ['topBlur', 'topCompositionEnd', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown'] + }, + compositionStart: { + phasedRegistrationNames: { + bubbled: 'onCompositionStart', + captured: 'onCompositionStartCapture' + }, + dependencies: ['topBlur', 'topCompositionStart', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown'] + }, + compositionUpdate: { + phasedRegistrationNames: { + bubbled: 'onCompositionUpdate', + captured: 'onCompositionUpdateCapture' + }, + dependencies: ['topBlur', 'topCompositionUpdate', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown'] + } +}; + +// Track whether we've ever handled a keypress on the space key. +var hasSpaceKeypress = false; + +/** + * Return whether a native keypress event is assumed to be a command. + * This is required because Firefox fires `keypress` events for key commands + * (cut, copy, select-all, etc.) even though no character is inserted. + */ +function isKeypressCommand(nativeEvent) { + return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) && + // ctrlKey && altKey is equivalent to AltGr, and is not a command. + !(nativeEvent.ctrlKey && nativeEvent.altKey); +} + +/** + * Translate native top level events into event types. + * + * @param {string} topLevelType + * @return {object} + */ +function getCompositionEventType(topLevelType) { + switch (topLevelType) { + case 'topCompositionStart': + return eventTypes.compositionStart; + case 'topCompositionEnd': + return eventTypes.compositionEnd; + case 'topCompositionUpdate': + return eventTypes.compositionUpdate; + } +} + +/** + * Does our fallback best-guess model think this event signifies that + * composition has begun? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackCompositionStart(topLevelType, nativeEvent) { + return topLevelType === 'topKeyDown' && nativeEvent.keyCode === START_KEYCODE; +} + +/** + * Does our fallback mode think that this event is the end of composition? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackCompositionEnd(topLevelType, nativeEvent) { + switch (topLevelType) { + case 'topKeyUp': + // Command keys insert or clear IME input. + return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; + case 'topKeyDown': + // Expect IME keyCode on each keydown. If we get any other + // code we must have exited earlier. + return nativeEvent.keyCode !== START_KEYCODE; + case 'topKeyPress': + case 'topMouseDown': + case 'topBlur': + // Events are not possible without cancelling IME. + return true; + default: + return false; + } +} + +/** + * Google Input Tools provides composition data via a CustomEvent, + * with the `data` property populated in the `detail` object. If this + * is available on the event object, use it. If not, this is a plain + * composition event and we have nothing special to extract. + * + * @param {object} nativeEvent + * @return {?string} + */ +function getDataFromCustomEvent(nativeEvent) { + var detail = nativeEvent.detail; + if (typeof detail === 'object' && 'data' in detail) { + return detail.data; + } + return null; +} + +// Track the current IME composition status, if any. +var isComposing = false; + +/** + * @return {?object} A SyntheticCompositionEvent. + */ +function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var eventType; + var fallbackData; + + if (canUseCompositionEvent) { + eventType = getCompositionEventType(topLevelType); + } else if (!isComposing) { + if (isFallbackCompositionStart(topLevelType, nativeEvent)) { + eventType = eventTypes.compositionStart; + } + } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) { + eventType = eventTypes.compositionEnd; + } + + if (!eventType) { + return null; + } + + if (useFallbackCompositionData) { + // The current composition is stored statically and must not be + // overwritten while composition continues. + if (!isComposing && eventType === eventTypes.compositionStart) { + isComposing = initialize(nativeEventTarget); + } else if (eventType === eventTypes.compositionEnd) { + if (isComposing) { + fallbackData = getData(); + } + } + } + + var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget); + + if (fallbackData) { + // Inject data generated from fallback path into the synthetic event. + // This matches the property of native CompositionEventInterface. + event.data = fallbackData; + } else { + var customData = getDataFromCustomEvent(nativeEvent); + if (customData !== null) { + event.data = customData; + } + } + + accumulateTwoPhaseDispatches(event); + return event; +} + +/** + * @param {TopLevelTypes} topLevelType Record from `BrowserEventConstants`. + * @param {object} nativeEvent Native browser event. + * @return {?string} The string corresponding to this `beforeInput` event. + */ +function getNativeBeforeInputChars(topLevelType, nativeEvent) { + switch (topLevelType) { + case 'topCompositionEnd': + return getDataFromCustomEvent(nativeEvent); + case 'topKeyPress': + /** + * If native `textInput` events are available, our goal is to make + * use of them. However, there is a special case: the spacebar key. + * In Webkit, preventing default on a spacebar `textInput` event + * cancels character insertion, but it *also* causes the browser + * to fall back to its default spacebar behavior of scrolling the + * page. + * + * Tracking at: + * https://code.google.com/p/chromium/issues/detail?id=355103 + * + * To avoid this issue, use the keypress event as if no `textInput` + * event is available. + */ + var which = nativeEvent.which; + if (which !== SPACEBAR_CODE) { + return null; + } + + hasSpaceKeypress = true; + return SPACEBAR_CHAR; + + case 'topTextInput': + // Record the characters to be added to the DOM. + var chars = nativeEvent.data; + + // If it's a spacebar character, assume that we have already handled + // it at the keypress level and bail immediately. Android Chrome + // doesn't give us keycodes, so we need to blacklist it. + if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { + return null; + } + + return chars; + + default: + // For other native event types, do nothing. + return null; + } +} + +/** + * For browsers that do not provide the `textInput` event, extract the + * appropriate string to use for SyntheticInputEvent. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @param {object} nativeEvent Native browser event. + * @return {?string} The fallback string for this `beforeInput` event. + */ +function getFallbackBeforeInputChars(topLevelType, nativeEvent) { + // If we are currently composing (IME) and using a fallback to do so, + // try to extract the composed characters from the fallback object. + // If composition event is available, we extract a string only at + // compositionevent, otherwise extract it at fallback events. + if (isComposing) { + if (topLevelType === 'topCompositionEnd' || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) { + var chars = getData(); + reset(); + isComposing = false; + return chars; + } + return null; + } + + switch (topLevelType) { + case 'topPaste': + // If a paste event occurs after a keypress, throw out the input + // chars. Paste events should not lead to BeforeInput events. + return null; + case 'topKeyPress': + /** + * As of v27, Firefox may fire keypress events even when no character + * will be inserted. A few possibilities: + * + * - `which` is `0`. Arrow keys, Esc key, etc. + * + * - `which` is the pressed key code, but no char is available. + * Ex: 'AltGr + d` in Polish. There is no modified character for + * this key combination and no character is inserted into the + * document, but FF fires the keypress for char code `100` anyway. + * No `input` event will occur. + * + * - `which` is the pressed key code, but a command combination is + * being used. Ex: `Cmd+C`. No character is inserted, and no + * `input` event will occur. + */ + if (!isKeypressCommand(nativeEvent)) { + // IE fires the `keypress` event when a user types an emoji via + // Touch keyboard of Windows. In such a case, the `char` property + // holds an emoji character like `\uD83D\uDE0A`. Because its length + // is 2, the property `which` does not represent an emoji correctly. + // In such a case, we directly return the `char` property instead of + // using `which`. + if (nativeEvent.char && nativeEvent.char.length > 1) { + return nativeEvent.char; + } else if (nativeEvent.which) { + return String.fromCharCode(nativeEvent.which); + } + } + return null; + case 'topCompositionEnd': + return useFallbackCompositionData ? null : nativeEvent.data; + default: + return null; + } +} + +/** + * Extract a SyntheticInputEvent for `beforeInput`, based on either native + * `textInput` or fallback behavior. + * + * @return {?object} A SyntheticInputEvent. + */ +function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var chars; + + if (canUseTextInputEvent) { + chars = getNativeBeforeInputChars(topLevelType, nativeEvent); + } else { + chars = getFallbackBeforeInputChars(topLevelType, nativeEvent); + } + + // If no characters are being inserted, no BeforeInput event should + // be fired. + if (!chars) { + return null; + } + + var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget); + + event.data = chars; + accumulateTwoPhaseDispatches(event); + return event; +} + +/** + * Create an `onBeforeInput` event to match + * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. + * + * This event plugin is based on the native `textInput` event + * available in Chrome, Safari, Opera, and IE. This event fires after + * `onKeyPress` and `onCompositionEnd`, but before `onInput`. + * + * `beforeInput` is spec'd but not implemented in any browsers, and + * the `input` event does not provide any useful information about what has + * actually been added, contrary to the spec. Thus, `textInput` is the best + * available event to identify the characters that have actually been inserted + * into the target node. + * + * This plugin is also responsible for emitting `composition` events, thus + * allowing us to share composition fallback code for both `beforeInput` and + * `composition` event types. + */ +var BeforeInputEventPlugin = { + eventTypes: eventTypes, + + extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { + return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)]; + } +}; + +// Use to restore controlled state after a change event has fired. + +var fiberHostComponent = null; + +var ReactControlledComponentInjection = { + injectFiberControlledHostComponent: function (hostComponentImpl) { + // The fiber implementation doesn't use dynamic dispatch so we need to + // inject the implementation. + fiberHostComponent = hostComponentImpl; + } +}; + +var restoreTarget = null; +var restoreQueue = null; + +function restoreStateOfTarget(target) { + // We perform this translation at the end of the event loop so that we + // always receive the correct fiber here + var internalInstance = getInstanceFromNode(target); + if (!internalInstance) { + // Unmounted + return; + } + !(fiberHostComponent && typeof fiberHostComponent.restoreControlledState === 'function') ? invariant_1(false, 'Fiber needs to be injected to handle a fiber target for controlled events. This error is likely caused by a bug in React. Please file an issue.') : void 0; + var props = getFiberCurrentPropsFromNode(internalInstance.stateNode); + fiberHostComponent.restoreControlledState(internalInstance.stateNode, internalInstance.type, props); +} + +var injection$3 = ReactControlledComponentInjection; + +function enqueueStateRestore(target) { + if (restoreTarget) { + if (restoreQueue) { + restoreQueue.push(target); + } else { + restoreQueue = [target]; + } + } else { + restoreTarget = target; + } +} + +function restoreStateIfNeeded() { + if (!restoreTarget) { + return; + } + var target = restoreTarget; + var queuedTargets = restoreQueue; + restoreTarget = null; + restoreQueue = null; + + restoreStateOfTarget(target); + if (queuedTargets) { + for (var i = 0; i < queuedTargets.length; i++) { + restoreStateOfTarget(queuedTargets[i]); + } + } +} + +var ReactControlledComponent = Object.freeze({ + injection: injection$3, + enqueueStateRestore: enqueueStateRestore, + restoreStateIfNeeded: restoreStateIfNeeded +}); + +// Used as a way to call batchedUpdates when we don't have a reference to +// the renderer. Such as when we're dispatching events or if third party +// libraries need to call batchedUpdates. Eventually, this API will go away when +// everything is batched by default. We'll then have a similar API to opt-out of +// scheduled work and instead do synchronous work. + +// Defaults +var fiberBatchedUpdates = function (fn, bookkeeping) { + return fn(bookkeeping); +}; + +var isNestingBatched = false; +function batchedUpdates(fn, bookkeeping) { + if (isNestingBatched) { + // If we are currently inside another batch, we need to wait until it + // fully completes before restoring state. Therefore, we add the target to + // a queue of work. + return fiberBatchedUpdates(fn, bookkeeping); + } + isNestingBatched = true; + try { + return fiberBatchedUpdates(fn, bookkeeping); + } finally { + // Here we wait until all updates have propagated, which is important + // when using controlled components within layers: + // https://github.com/facebook/react/issues/1698 + // Then we restore state of any controlled component. + isNestingBatched = false; + restoreStateIfNeeded(); + } +} + +var ReactGenericBatchingInjection = { + injectFiberBatchedUpdates: function (_batchedUpdates) { + fiberBatchedUpdates = _batchedUpdates; + } +}; + +var injection$4 = ReactGenericBatchingInjection; + +/** + * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary + */ +var supportedInputTypes = { + color: true, + date: true, + datetime: true, + 'datetime-local': true, + email: true, + month: true, + number: true, + password: true, + range: true, + search: true, + tel: true, + text: true, + time: true, + url: true, + week: true +}; + +function isTextInputElement(elem) { + var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); + + if (nodeName === 'input') { + return !!supportedInputTypes[elem.type]; + } + + if (nodeName === 'textarea') { + return true; + } + + return false; +} + +/** + * HTML nodeType values that represent the type of the node + */ + +var ELEMENT_NODE = 1; +var TEXT_NODE = 3; +var COMMENT_NODE = 8; +var DOCUMENT_NODE = 9; +var DOCUMENT_FRAGMENT_NODE = 11; + +/** + * Gets the target node from a native browser event by accounting for + * inconsistencies in browser DOM APIs. + * + * @param {object} nativeEvent Native browser event. + * @return {DOMEventTarget} Target node. + */ +function getEventTarget(nativeEvent) { + var target = nativeEvent.target || nativeEvent.srcElement || window; + + // Normalize SVG element events #4963 + if (target.correspondingUseElement) { + target = target.correspondingUseElement; + } + + // Safari may fire events on text nodes (Node.TEXT_NODE is 3). + // @see http://www.quirksmode.org/js/events_properties.html + return target.nodeType === TEXT_NODE ? target.parentNode : target; +} + +var useHasFeature; +if (ExecutionEnvironment_1.canUseDOM) { + useHasFeature = document.implementation && document.implementation.hasFeature && + // always returns true in newer browsers as per the standard. + // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature + document.implementation.hasFeature('', '') !== true; +} + +/** + * Checks if an event is supported in the current execution environment. + * + * NOTE: This will not work correctly for non-generic events such as `change`, + * `reset`, `load`, `error`, and `select`. + * + * Borrows from Modernizr. + * + * @param {string} eventNameSuffix Event name, e.g. "click". + * @param {?boolean} capture Check if the capture phase is supported. + * @return {boolean} True if the event is supported. + * @internal + * @license Modernizr 3.0.0pre (Custom Build) | MIT + */ +function isEventSupported(eventNameSuffix, capture) { + if (!ExecutionEnvironment_1.canUseDOM || capture && !('addEventListener' in document)) { + return false; + } + + var eventName = 'on' + eventNameSuffix; + var isSupported = eventName in document; + + if (!isSupported) { + var element = document.createElement('div'); + element.setAttribute(eventName, 'return;'); + isSupported = typeof element[eventName] === 'function'; + } + + if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') { + // This is the only way to test support for the `wheel` event in IE9+. + isSupported = document.implementation.hasFeature('Events.wheel', '3.0'); + } + + return isSupported; +} + +function isCheckable(elem) { + var type = elem.type; + var nodeName = elem.nodeName; + return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio'); +} + +function getTracker(node) { + return node._valueTracker; +} + +function detachTracker(node) { + node._valueTracker = null; +} + +function getValueFromNode(node) { + var value = ''; + if (!node) { + return value; + } + + if (isCheckable(node)) { + value = node.checked ? 'true' : 'false'; + } else { + value = node.value; + } + + return value; +} + +function trackValueOnNode(node) { + var valueField = isCheckable(node) ? 'checked' : 'value'; + var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField); + + var currentValue = '' + node[valueField]; + + // if someone has already defined a value or Safari, then bail + // and don't track value will cause over reporting of changes, + // but it's better then a hard failure + // (needed for certain tests that spyOn input values and Safari) + if (node.hasOwnProperty(valueField) || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') { + return; + } + + Object.defineProperty(node, valueField, { + enumerable: descriptor.enumerable, + configurable: true, + get: function () { + return descriptor.get.call(this); + }, + set: function (value) { + currentValue = '' + value; + descriptor.set.call(this, value); + } + }); + + var tracker = { + getValue: function () { + return currentValue; + }, + setValue: function (value) { + currentValue = '' + value; + }, + stopTracking: function () { + detachTracker(node); + delete node[valueField]; + } + }; + return tracker; +} + +function track(node) { + if (getTracker(node)) { + return; + } + + // TODO: Once it's just Fiber we can move this to node._wrapperState + node._valueTracker = trackValueOnNode(node); +} + +function updateValueIfChanged(node) { + if (!node) { + return false; + } + + var tracker = getTracker(node); + // if there is no tracker at this point it's unlikely + // that trying again will succeed + if (!tracker) { + return true; + } + + var lastValue = tracker.getValue(); + var nextValue = getValueFromNode(node); + if (nextValue !== lastValue) { + tracker.setValue(nextValue); + return true; + } + return false; +} + +var eventTypes$1 = { + change: { + phasedRegistrationNames: { + bubbled: 'onChange', + captured: 'onChangeCapture' + }, + dependencies: ['topBlur', 'topChange', 'topClick', 'topFocus', 'topInput', 'topKeyDown', 'topKeyUp', 'topSelectionChange'] + } +}; + +function createAndAccumulateChangeEvent(inst, nativeEvent, target) { + var event = SyntheticEvent$1.getPooled(eventTypes$1.change, inst, nativeEvent, target); + event.type = 'change'; + // Flag this event loop as needing state restore. + enqueueStateRestore(target); + accumulateTwoPhaseDispatches(event); + return event; +} +/** + * For IE shims + */ +var activeElement = null; +var activeElementInst = null; + +/** + * SECTION: handle `change` event + */ +function shouldUseChangeEvent(elem) { + var nodeName = elem.nodeName && elem.nodeName.toLowerCase(); + return nodeName === 'select' || nodeName === 'input' && elem.type === 'file'; +} + +function manualDispatchChangeEvent(nativeEvent) { + var event = createAndAccumulateChangeEvent(activeElementInst, nativeEvent, getEventTarget(nativeEvent)); + + // If change and propertychange bubbled, we'd just bind to it like all the + // other events and have it go through ReactBrowserEventEmitter. Since it + // doesn't, we manually listen for the events and so we have to enqueue and + // process the abstract event manually. + // + // Batching is necessary here in order to ensure that all event handlers run + // before the next rerender (including event handlers attached to ancestor + // elements instead of directly on the input). Without this, controlled + // components don't work properly in conjunction with event bubbling because + // the component is rerendered and the value reverted before all the event + // handlers can run. See https://github.com/facebook/react/issues/708. + batchedUpdates(runEventInBatch, event); +} + +function runEventInBatch(event) { + enqueueEvents(event); + processEventQueue(false); +} + +function getInstIfValueChanged(targetInst) { + var targetNode = getNodeFromInstance$1(targetInst); + if (updateValueIfChanged(targetNode)) { + return targetInst; + } +} + +function getTargetInstForChangeEvent(topLevelType, targetInst) { + if (topLevelType === 'topChange') { + return targetInst; + } +} + +/** + * SECTION: handle `input` event + */ +var isInputEventSupported = false; +if (ExecutionEnvironment_1.canUseDOM) { + // IE9 claims to support the input event but fails to trigger it when + // deleting text, so we ignore its input events. + isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9); +} + +/** + * (For IE <=9) Starts tracking propertychange events on the passed-in element + * and override the value property so that we can distinguish user events from + * value changes in JS. + */ +function startWatchingForValueChange(target, targetInst) { + activeElement = target; + activeElementInst = targetInst; + activeElement.attachEvent('onpropertychange', handlePropertyChange); +} + +/** + * (For IE <=9) Removes the event listeners from the currently-tracked element, + * if any exists. + */ +function stopWatchingForValueChange() { + if (!activeElement) { + return; + } + activeElement.detachEvent('onpropertychange', handlePropertyChange); + activeElement = null; + activeElementInst = null; +} + +/** + * (For IE <=9) Handles a propertychange event, sending a `change` event if + * the value of the active element has changed. + */ +function handlePropertyChange(nativeEvent) { + if (nativeEvent.propertyName !== 'value') { + return; + } + if (getInstIfValueChanged(activeElementInst)) { + manualDispatchChangeEvent(nativeEvent); + } +} + +function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) { + if (topLevelType === 'topFocus') { + // In IE9, propertychange fires for most input events but is buggy and + // doesn't fire when text is deleted, but conveniently, selectionchange + // appears to fire in all of the remaining cases so we catch those and + // forward the event if the value has changed + // In either case, we don't want to call the event handler if the value + // is changed from JS so we redefine a setter for `.value` that updates + // our activeElementValue variable, allowing us to ignore those changes + // + // stopWatching() should be a noop here but we call it just in case we + // missed a blur event somehow. + stopWatchingForValueChange(); + startWatchingForValueChange(target, targetInst); + } else if (topLevelType === 'topBlur') { + stopWatchingForValueChange(); + } +} + +// For IE8 and IE9. +function getTargetInstForInputEventPolyfill(topLevelType, targetInst) { + if (topLevelType === 'topSelectionChange' || topLevelType === 'topKeyUp' || topLevelType === 'topKeyDown') { + // On the selectionchange event, the target is just document which isn't + // helpful for us so just check activeElement instead. + // + // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire + // propertychange on the first input event after setting `value` from a + // script and fires only keydown, keypress, keyup. Catching keyup usually + // gets it and catching keydown lets us fire an event for the first + // keystroke if user does a key repeat (it'll be a little delayed: right + // before the second keystroke). Other input methods (e.g., paste) seem to + // fire selectionchange normally. + return getInstIfValueChanged(activeElementInst); + } +} + +/** + * SECTION: handle `click` event + */ +function shouldUseClickEvent(elem) { + // Use the `click` event to detect changes to checkbox and radio inputs. + // This approach works across all browsers, whereas `change` does not fire + // until `blur` in IE8. + var nodeName = elem.nodeName; + return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio'); +} + +function getTargetInstForClickEvent(topLevelType, targetInst) { + if (topLevelType === 'topClick') { + return getInstIfValueChanged(targetInst); + } +} + +function getTargetInstForInputOrChangeEvent(topLevelType, targetInst) { + if (topLevelType === 'topInput' || topLevelType === 'topChange') { + return getInstIfValueChanged(targetInst); + } +} + +function handleControlledInputBlur(inst, node) { + // TODO: In IE, inst is occasionally null. Why? + if (inst == null) { + return; + } + + // Fiber and ReactDOM keep wrapper state in separate places + var state = inst._wrapperState || node._wrapperState; + + if (!state || !state.controlled || node.type !== 'number') { + return; + } + + // If controlled, assign the value attribute to the current value on blur + var value = '' + node.value; + if (node.getAttribute('value') !== value) { + node.setAttribute('value', value); + } +} + +/** + * This plugin creates an `onChange` event that normalizes change events + * across form elements. This event fires at a time when it's possible to + * change the element's value without seeing a flicker. + * + * Supported elements are: + * - input (see `isTextInputElement`) + * - textarea + * - select + */ +var ChangeEventPlugin = { + eventTypes: eventTypes$1, + + _isInputEventSupported: isInputEventSupported, + + extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window; + + var getTargetInstFunc, handleEventFunc; + if (shouldUseChangeEvent(targetNode)) { + getTargetInstFunc = getTargetInstForChangeEvent; + } else if (isTextInputElement(targetNode)) { + if (isInputEventSupported) { + getTargetInstFunc = getTargetInstForInputOrChangeEvent; + } else { + getTargetInstFunc = getTargetInstForInputEventPolyfill; + handleEventFunc = handleEventsForInputEventPolyfill; + } + } else if (shouldUseClickEvent(targetNode)) { + getTargetInstFunc = getTargetInstForClickEvent; + } + + if (getTargetInstFunc) { + var inst = getTargetInstFunc(topLevelType, targetInst); + if (inst) { + var event = createAndAccumulateChangeEvent(inst, nativeEvent, nativeEventTarget); + return event; + } + } + + if (handleEventFunc) { + handleEventFunc(topLevelType, targetNode, targetInst); + } + + // When blurring, set the value attribute for number inputs + if (topLevelType === 'topBlur') { + handleControlledInputBlur(targetInst, targetNode); + } + } +}; + +/** + * Module that is injectable into `EventPluginHub`, that specifies a + * deterministic ordering of `EventPlugin`s. A convenient way to reason about + * plugins, without having to package every one of them. This is better than + * having plugins be ordered in the same order that they are injected because + * that ordering would be influenced by the packaging order. + * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that + * preventing default on events is convenient in `SimpleEventPlugin` handlers. + */ +var DOMEventPluginOrder = ['ResponderEventPlugin', 'SimpleEventPlugin', 'TapEventPlugin', 'EnterLeaveEventPlugin', 'ChangeEventPlugin', 'SelectEventPlugin', 'BeforeInputEventPlugin']; + +/** + * @interface UIEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ +var UIEventInterface = { + view: null, + detail: null +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticEvent} + */ +function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticEvent$1.augmentClass(SyntheticUIEvent, UIEventInterface); + +/** + * Translation from modifier key to the associated property in the event. + * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers + */ + +var modifierKeyToProp = { + Alt: 'altKey', + Control: 'ctrlKey', + Meta: 'metaKey', + Shift: 'shiftKey' +}; + +// IE8 does not implement getModifierState so we simply map it to the only +// modifier keys exposed by the event itself, does not support Lock-keys. +// Currently, all major browsers except Chrome seems to support Lock-keys. +function modifierStateGetter(keyArg) { + var syntheticEvent = this; + var nativeEvent = syntheticEvent.nativeEvent; + if (nativeEvent.getModifierState) { + return nativeEvent.getModifierState(keyArg); + } + var keyProp = modifierKeyToProp[keyArg]; + return keyProp ? !!nativeEvent[keyProp] : false; +} + +function getEventModifierState(nativeEvent) { + return modifierStateGetter; +} + +/** + * @interface MouseEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ +var MouseEventInterface = { + screenX: null, + screenY: null, + clientX: null, + clientY: null, + pageX: null, + pageY: null, + ctrlKey: null, + shiftKey: null, + altKey: null, + metaKey: null, + getModifierState: getEventModifierState, + button: null, + buttons: null, + relatedTarget: function (event) { + return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement); + } +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticUIEvent} + */ +function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface); + +var eventTypes$2 = { + mouseEnter: { + registrationName: 'onMouseEnter', + dependencies: ['topMouseOut', 'topMouseOver'] + }, + mouseLeave: { + registrationName: 'onMouseLeave', + dependencies: ['topMouseOut', 'topMouseOver'] + } +}; + +var EnterLeaveEventPlugin = { + eventTypes: eventTypes$2, + + /** + * For almost every interaction we care about, there will be both a top-level + * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that + * we do not extract duplicate events. However, moving the mouse into the + * browser from outside will not fire a `mouseout` event. In this case, we use + * the `mouseover` top-level event. + */ + extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { + if (topLevelType === 'topMouseOver' && (nativeEvent.relatedTarget || nativeEvent.fromElement)) { + return null; + } + if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') { + // Must not be a mouse in or mouse out - ignoring. + return null; + } + + var win; + if (nativeEventTarget.window === nativeEventTarget) { + // `nativeEventTarget` is probably a window object. + win = nativeEventTarget; + } else { + // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. + var doc = nativeEventTarget.ownerDocument; + if (doc) { + win = doc.defaultView || doc.parentWindow; + } else { + win = window; + } + } + + var from; + var to; + if (topLevelType === 'topMouseOut') { + from = targetInst; + var related = nativeEvent.relatedTarget || nativeEvent.toElement; + to = related ? getClosestInstanceFromNode(related) : null; + } else { + // Moving to a node from outside the window. + from = null; + to = targetInst; + } + + if (from === to) { + // Nothing pertains to our managed components. + return null; + } + + var fromNode = from == null ? win : getNodeFromInstance$1(from); + var toNode = to == null ? win : getNodeFromInstance$1(to); + + var leave = SyntheticMouseEvent.getPooled(eventTypes$2.mouseLeave, from, nativeEvent, nativeEventTarget); + leave.type = 'mouseleave'; + leave.target = fromNode; + leave.relatedTarget = toNode; + + var enter = SyntheticMouseEvent.getPooled(eventTypes$2.mouseEnter, to, nativeEvent, nativeEventTarget); + enter.type = 'mouseenter'; + enter.target = toNode; + enter.relatedTarget = fromNode; + + accumulateEnterLeaveDispatches(leave, enter, from, to); + + return [leave, enter]; + } +}; + +/** + * `ReactInstanceMap` maintains a mapping from a public facing stateful + * instance (key) and the internal representation (value). This allows public + * methods to accept the user facing instance as an argument and map them back + * to internal methods. + * + * Note that this module is currently shared and assumed to be stateless. + * If this becomes an actual Map, that will break. + */ + +/** + * This API should be called `delete` but we'd have to make sure to always + * transform these to strings for IE support. When this transform is fully + * supported we can rename it. + */ + + +function get(key) { + return key._reactInternalFiber; +} + +function has(key) { + return key._reactInternalFiber !== undefined; +} + +function set(key, value) { + key._reactInternalFiber = value; +} + +var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + +var ReactCurrentOwner = ReactInternals$1.ReactCurrentOwner; +var ReactDebugCurrentFrame = ReactInternals$1.ReactDebugCurrentFrame; + +function getComponentName(fiber) { + var type = fiber.type; + + if (typeof type === 'string') { + return type; + } + if (typeof type === 'function') { + return type.displayName || type.name; + } + return null; +} + +// Don't change these two values: +var NoEffect = 0; // 0b00000000 +var PerformedWork = 1; // 0b00000001 + +// You can change the rest (and add more). +var Placement = 2; // 0b00000010 +var Update = 4; // 0b00000100 +var PlacementAndUpdate = 6; // 0b00000110 +var Deletion = 8; // 0b00001000 +var ContentReset = 16; // 0b00010000 +var Callback = 32; // 0b00100000 +var Err = 64; // 0b01000000 +var Ref = 128; // 0b10000000 + +var MOUNTING = 1; +var MOUNTED = 2; +var UNMOUNTED = 3; + +function isFiberMountedImpl(fiber) { + var node = fiber; + if (!fiber.alternate) { + // If there is no alternate, this might be a new tree that isn't inserted + // yet. If it is, then it will have a pending insertion effect on it. + if ((node.effectTag & Placement) !== NoEffect) { + return MOUNTING; + } + while (node['return']) { + node = node['return']; + if ((node.effectTag & Placement) !== NoEffect) { + return MOUNTING; + } + } + } else { + while (node['return']) { + node = node['return']; + } + } + if (node.tag === HostRoot) { + // TODO: Check if this was a nested HostRoot when used with + // renderContainerIntoSubtree. + return MOUNTED; + } + // If we didn't hit the root, that means that we're in an disconnected tree + // that has been unmounted. + return UNMOUNTED; +} + +function isFiberMounted(fiber) { + return isFiberMountedImpl(fiber) === MOUNTED; +} + +function isMounted(component) { + { + var owner = ReactCurrentOwner.current; + if (owner !== null && owner.tag === ClassComponent) { + var ownerFiber = owner; + var instance = ownerFiber.stateNode; + warning_1(instance._warnedAboutRefsInRender, '%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', getComponentName(ownerFiber) || 'A component'); + instance._warnedAboutRefsInRender = true; + } + } + + var fiber = get(component); + if (!fiber) { + return false; + } + return isFiberMountedImpl(fiber) === MOUNTED; +} + +function assertIsMounted(fiber) { + !(isFiberMountedImpl(fiber) === MOUNTED) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0; +} + +function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; + if (!alternate) { + // If there is no alternate, then we only need to check if it is mounted. + var state = isFiberMountedImpl(fiber); + !(state !== UNMOUNTED) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0; + if (state === MOUNTING) { + return null; + } + return fiber; + } + // If we have two possible branches, we'll walk backwards up to the root + // to see what path the root points to. On the way we may hit one of the + // special cases and we'll deal with them. + var a = fiber; + var b = alternate; + while (true) { + var parentA = a['return']; + var parentB = parentA ? parentA.alternate : null; + if (!parentA || !parentB) { + // We're at the root. + break; + } + + // If both copies of the parent fiber point to the same child, we can + // assume that the child is current. This happens when we bailout on low + // priority: the bailed out fiber's child reuses the current child. + if (parentA.child === parentB.child) { + var child = parentA.child; + while (child) { + if (child === a) { + // We've determined that A is the current branch. + assertIsMounted(parentA); + return fiber; + } + if (child === b) { + // We've determined that B is the current branch. + assertIsMounted(parentA); + return alternate; + } + child = child.sibling; + } + // We should never have an alternate for any mounting node. So the only + // way this could possibly happen is if this was unmounted, if at all. + invariant_1(false, 'Unable to find node on an unmounted component.'); + } + + if (a['return'] !== b['return']) { + // The return pointer of A and the return pointer of B point to different + // fibers. We assume that return pointers never criss-cross, so A must + // belong to the child set of A.return, and B must belong to the child + // set of B.return. + a = parentA; + b = parentB; + } else { + // The return pointers point to the same fiber. We'll have to use the + // default, slow path: scan the child sets of each parent alternate to see + // which child belongs to which set. + // + // Search parent A's child set + var didFindChild = false; + var _child = parentA.child; + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentA; + b = parentB; + break; + } + if (_child === b) { + didFindChild = true; + b = parentA; + a = parentB; + break; + } + _child = _child.sibling; + } + if (!didFindChild) { + // Search parent B's child set + _child = parentB.child; + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentB; + b = parentA; + break; + } + if (_child === b) { + didFindChild = true; + b = parentB; + a = parentA; + break; + } + _child = _child.sibling; + } + !didFindChild ? invariant_1(false, 'Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue.') : void 0; + } + } + + !(a.alternate === b) ? invariant_1(false, 'Return fibers should always be each others\' alternates. This error is likely caused by a bug in React. Please file an issue.') : void 0; + } + // If the root is not a host container, we're in a disconnected tree. I.e. + // unmounted. + !(a.tag === HostRoot) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0; + if (a.stateNode.current === a) { + // We've determined that A is the current branch. + return fiber; + } + // Otherwise B has to be current branch. + return alternate; +} + +function findCurrentHostFiber(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + if (!currentParent) { + return null; + } + + // Next we'll drill down this component to find the first HostComponent/Text. + var node = currentParent; + while (true) { + if (node.tag === HostComponent || node.tag === HostText) { + return node; + } else if (node.child) { + node.child['return'] = node; + node = node.child; + continue; + } + if (node === currentParent) { + return null; + } + while (!node.sibling) { + if (!node['return'] || node['return'] === currentParent) { + return null; + } + node = node['return']; + } + node.sibling['return'] = node['return']; + node = node.sibling; + } + // Flow needs the return null here, but ESLint complains about it. + // eslint-disable-next-line no-unreachable + return null; +} + +function findCurrentHostFiberWithNoPortals(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + if (!currentParent) { + return null; + } + + // Next we'll drill down this component to find the first HostComponent/Text. + var node = currentParent; + while (true) { + if (node.tag === HostComponent || node.tag === HostText) { + return node; + } else if (node.child && node.tag !== HostPortal) { + node.child['return'] = node; + node = node.child; + continue; + } + if (node === currentParent) { + return null; + } + while (!node.sibling) { + if (!node['return'] || node['return'] === currentParent) { + return null; + } + node = node['return']; + } + node.sibling['return'] = node['return']; + node = node.sibling; + } + // Flow needs the return null here, but ESLint complains about it. + // eslint-disable-next-line no-unreachable + return null; +} + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @typechecks + */ + + + +/** + * Upstream version of event listener. Does not take into account specific + * nature of platform. + */ +var EventListener = { + /** + * Listen to DOM events during the bubble phase. + * + * @param {DOMEventTarget} target DOM element to register listener on. + * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. + * @param {function} callback Callback function. + * @return {object} Object with a `remove` method. + */ + listen: function listen(target, eventType, callback) { + if (target.addEventListener) { + target.addEventListener(eventType, callback, false); + return { + remove: function remove() { + target.removeEventListener(eventType, callback, false); + } + }; + } else if (target.attachEvent) { + target.attachEvent('on' + eventType, callback); + return { + remove: function remove() { + target.detachEvent('on' + eventType, callback); + } + }; + } + }, + + /** + * Listen to DOM events during the capture phase. + * + * @param {DOMEventTarget} target DOM element to register listener on. + * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. + * @param {function} callback Callback function. + * @return {object} Object with a `remove` method. + */ + capture: function capture(target, eventType, callback) { + if (target.addEventListener) { + target.addEventListener(eventType, callback, true); + return { + remove: function remove() { + target.removeEventListener(eventType, callback, true); + } + }; + } else { + { + console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.'); + } + return { + remove: emptyFunction_1 + }; + } + }, + + registerDefault: function registerDefault() {} +}; + +var EventListener_1 = EventListener; + +var CALLBACK_BOOKKEEPING_POOL_SIZE = 10; +var callbackBookkeepingPool = []; + +/** + * Find the deepest React component completely containing the root of the + * passed-in instance (for use when entire React trees are nested within each + * other). If React trees are not nested, returns null. + */ +function findRootContainerNode(inst) { + // TODO: It may be a good idea to cache this to prevent unnecessary DOM + // traversal, but caching is difficult to do correctly without using a + // mutation observer to listen for all DOM changes. + while (inst['return']) { + inst = inst['return']; + } + if (inst.tag !== HostRoot) { + // This can happen if we're in a detached tree. + return null; + } + return inst.stateNode.containerInfo; +} + +// Used to store ancestor hierarchy in top level callback +function getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst) { + if (callbackBookkeepingPool.length) { + var instance = callbackBookkeepingPool.pop(); + instance.topLevelType = topLevelType; + instance.nativeEvent = nativeEvent; + instance.targetInst = targetInst; + return instance; + } + return { + topLevelType: topLevelType, + nativeEvent: nativeEvent, + targetInst: targetInst, + ancestors: [] + }; +} + +function releaseTopLevelCallbackBookKeeping(instance) { + instance.topLevelType = null; + instance.nativeEvent = null; + instance.targetInst = null; + instance.ancestors.length = 0; + if (callbackBookkeepingPool.length < CALLBACK_BOOKKEEPING_POOL_SIZE) { + callbackBookkeepingPool.push(instance); + } +} + +function handleTopLevelImpl(bookKeeping) { + var targetInst = bookKeeping.targetInst; + + // Loop through the hierarchy, in case there's any nested components. + // It's important that we build the array of ancestors before calling any + // event handlers, because event handlers can modify the DOM, leading to + // inconsistencies with ReactMount's node cache. See #1105. + var ancestor = targetInst; + do { + if (!ancestor) { + bookKeeping.ancestors.push(ancestor); + break; + } + var root = findRootContainerNode(ancestor); + if (!root) { + break; + } + bookKeeping.ancestors.push(ancestor); + ancestor = getClosestInstanceFromNode(root); + } while (ancestor); + + for (var i = 0; i < bookKeeping.ancestors.length; i++) { + targetInst = bookKeeping.ancestors[i]; + _handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent)); + } +} + +// TODO: can we stop exporting these? +var _enabled = true; +var _handleTopLevel = void 0; + +function setHandleTopLevel(handleTopLevel) { + _handleTopLevel = handleTopLevel; +} + +function setEnabled(enabled) { + _enabled = !!enabled; +} + +function isEnabled() { + return _enabled; +} + +/** + * Traps top-level events by using event bubbling. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @param {string} handlerBaseName Event name (e.g. "click"). + * @param {object} element Element on which to attach listener. + * @return {?object} An object with a remove function which will forcefully + * remove the listener. + * @internal + */ +function trapBubbledEvent(topLevelType, handlerBaseName, element) { + if (!element) { + return null; + } + return EventListener_1.listen(element, handlerBaseName, dispatchEvent.bind(null, topLevelType)); +} + +/** + * Traps a top-level event by using event capturing. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @param {string} handlerBaseName Event name (e.g. "click"). + * @param {object} element Element on which to attach listener. + * @return {?object} An object with a remove function which will forcefully + * remove the listener. + * @internal + */ +function trapCapturedEvent(topLevelType, handlerBaseName, element) { + if (!element) { + return null; + } + return EventListener_1.capture(element, handlerBaseName, dispatchEvent.bind(null, topLevelType)); +} + +function dispatchEvent(topLevelType, nativeEvent) { + if (!_enabled) { + return; + } + + var nativeEventTarget = getEventTarget(nativeEvent); + var targetInst = getClosestInstanceFromNode(nativeEventTarget); + if (targetInst !== null && typeof targetInst.tag === 'number' && !isFiberMounted(targetInst)) { + // If we get an event (ex: img onload) before committing that + // component's mount, ignore it for now (that is, treat it as if it was an + // event on a non-React tree). We might also consider queueing events and + // dispatching them after the mount. + targetInst = null; + } + + var bookKeeping = getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst); + + try { + // Event queue being processed in the same cycle allows + // `preventDefault`. + batchedUpdates(handleTopLevelImpl, bookKeeping); + } finally { + releaseTopLevelCallbackBookKeeping(bookKeeping); + } +} + +var ReactDOMEventListener = Object.freeze({ + get _enabled () { return _enabled; }, + get _handleTopLevel () { return _handleTopLevel; }, + setHandleTopLevel: setHandleTopLevel, + setEnabled: setEnabled, + isEnabled: isEnabled, + trapBubbledEvent: trapBubbledEvent, + trapCapturedEvent: trapCapturedEvent, + dispatchEvent: dispatchEvent +}); + +/** + * Generate a mapping of standard vendor prefixes using the defined style property and event name. + * + * @param {string} styleProp + * @param {string} eventName + * @returns {object} + */ +function makePrefixMap(styleProp, eventName) { + var prefixes = {}; + + prefixes[styleProp.toLowerCase()] = eventName.toLowerCase(); + prefixes['Webkit' + styleProp] = 'webkit' + eventName; + prefixes['Moz' + styleProp] = 'moz' + eventName; + prefixes['ms' + styleProp] = 'MS' + eventName; + prefixes['O' + styleProp] = 'o' + eventName.toLowerCase(); + + return prefixes; +} + +/** + * A list of event names to a configurable list of vendor prefixes. + */ +var vendorPrefixes = { + animationend: makePrefixMap('Animation', 'AnimationEnd'), + animationiteration: makePrefixMap('Animation', 'AnimationIteration'), + animationstart: makePrefixMap('Animation', 'AnimationStart'), + transitionend: makePrefixMap('Transition', 'TransitionEnd') +}; + +/** + * Event names that have already been detected and prefixed (if applicable). + */ +var prefixedEventNames = {}; + +/** + * Element to check for prefixes on. + */ +var style = {}; + +/** + * Bootstrap if a DOM exists. + */ +if (ExecutionEnvironment_1.canUseDOM) { + style = document.createElement('div').style; + + // On some platforms, in particular some releases of Android 4.x, + // the un-prefixed "animation" and "transition" properties are defined on the + // style object but the events that fire will still be prefixed, so we need + // to check if the un-prefixed events are usable, and if not remove them from the map. + if (!('AnimationEvent' in window)) { + delete vendorPrefixes.animationend.animation; + delete vendorPrefixes.animationiteration.animation; + delete vendorPrefixes.animationstart.animation; + } + + // Same as above + if (!('TransitionEvent' in window)) { + delete vendorPrefixes.transitionend.transition; + } +} + +/** + * Attempts to determine the correct vendor prefixed event name. + * + * @param {string} eventName + * @returns {string} + */ +function getVendorPrefixedEventName(eventName) { + if (prefixedEventNames[eventName]) { + return prefixedEventNames[eventName]; + } else if (!vendorPrefixes[eventName]) { + return eventName; + } + + var prefixMap = vendorPrefixes[eventName]; + + for (var styleProp in prefixMap) { + if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) { + return prefixedEventNames[eventName] = prefixMap[styleProp]; + } + } + + return ''; +} + +/** + * Types of raw signals from the browser caught at the top level. + * + * For events like 'submit' which don't consistently bubble (which we + * trap at a lower node than `document`), binding at `document` would + * cause duplicate events so we don't include them here. + */ +var topLevelTypes$1 = { + topAbort: 'abort', + topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend', + topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration', + topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart', + topBlur: 'blur', + topCancel: 'cancel', + topCanPlay: 'canplay', + topCanPlayThrough: 'canplaythrough', + topChange: 'change', + topClick: 'click', + topClose: 'close', + topCompositionEnd: 'compositionend', + topCompositionStart: 'compositionstart', + topCompositionUpdate: 'compositionupdate', + topContextMenu: 'contextmenu', + topCopy: 'copy', + topCut: 'cut', + topDoubleClick: 'dblclick', + topDrag: 'drag', + topDragEnd: 'dragend', + topDragEnter: 'dragenter', + topDragExit: 'dragexit', + topDragLeave: 'dragleave', + topDragOver: 'dragover', + topDragStart: 'dragstart', + topDrop: 'drop', + topDurationChange: 'durationchange', + topEmptied: 'emptied', + topEncrypted: 'encrypted', + topEnded: 'ended', + topError: 'error', + topFocus: 'focus', + topInput: 'input', + topKeyDown: 'keydown', + topKeyPress: 'keypress', + topKeyUp: 'keyup', + topLoadedData: 'loadeddata', + topLoad: 'load', + topLoadedMetadata: 'loadedmetadata', + topLoadStart: 'loadstart', + topMouseDown: 'mousedown', + topMouseMove: 'mousemove', + topMouseOut: 'mouseout', + topMouseOver: 'mouseover', + topMouseUp: 'mouseup', + topPaste: 'paste', + topPause: 'pause', + topPlay: 'play', + topPlaying: 'playing', + topProgress: 'progress', + topRateChange: 'ratechange', + topScroll: 'scroll', + topSeeked: 'seeked', + topSeeking: 'seeking', + topSelectionChange: 'selectionchange', + topStalled: 'stalled', + topSuspend: 'suspend', + topTextInput: 'textInput', + topTimeUpdate: 'timeupdate', + topToggle: 'toggle', + topTouchCancel: 'touchcancel', + topTouchEnd: 'touchend', + topTouchMove: 'touchmove', + topTouchStart: 'touchstart', + topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend', + topVolumeChange: 'volumechange', + topWaiting: 'waiting', + topWheel: 'wheel' +}; + +var BrowserEventConstants = { + topLevelTypes: topLevelTypes$1 +}; + +function runEventQueueInBatch(events) { + enqueueEvents(events); + processEventQueue(false); +} + +/** + * Streams a fired top-level event to `EventPluginHub` where plugins have the + * opportunity to create `ReactEvent`s to be dispatched. + */ +function handleTopLevel(topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var events = extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget); + runEventQueueInBatch(events); +} + +var topLevelTypes = BrowserEventConstants.topLevelTypes; + +/** + * Summary of `ReactBrowserEventEmitter` event handling: + * + * - Top-level delegation is used to trap most native browser events. This + * may only occur in the main thread and is the responsibility of + * ReactDOMEventListener, which is injected and can therefore support + * pluggable event sources. This is the only work that occurs in the main + * thread. + * + * - We normalize and de-duplicate events to account for browser quirks. This + * may be done in the worker thread. + * + * - Forward these native events (with the associated top-level type used to + * trap it) to `EventPluginHub`, which in turn will ask plugins if they want + * to extract any synthetic events. + * + * - The `EventPluginHub` will then process each event by annotating them with + * "dispatches", a sequence of listeners and IDs that care about that event. + * + * - The `EventPluginHub` then dispatches the events. + * + * Overview of React and the event system: + * + * +------------+ . + * | DOM | . + * +------------+ . + * | . + * v . + * +------------+ . + * | ReactEvent | . + * | Listener | . + * +------------+ . +-----------+ + * | . +--------+|SimpleEvent| + * | . | |Plugin | + * +-----|------+ . v +-----------+ + * | | | . +--------------+ +------------+ + * | +-----------.--->|EventPluginHub| | Event | + * | | . | | +-----------+ | Propagators| + * | ReactEvent | . | | |TapEvent | |------------| + * | Emitter | . | |<---+|Plugin | |other plugin| + * | | . | | +-----------+ | utilities | + * | +-----------.--->| | +------------+ + * | | | . +--------------+ + * +-----|------+ . ^ +-----------+ + * | . | |Enter/Leave| + * + . +-------+|Plugin | + * +-------------+ . +-----------+ + * | application | . + * |-------------| . + * | | . + * | | . + * +-------------+ . + * . + * React Core . General Purpose Event Plugin System + */ + +var alreadyListeningTo = {}; +var reactTopListenersCounter = 0; + +/** + * To ensure no conflicts with other potential React instances on the page + */ +var topListenersIDKey = '_reactListenersID' + ('' + Math.random()).slice(2); + +function getListeningForDocument(mountAt) { + // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty` + // directly. + if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) { + mountAt[topListenersIDKey] = reactTopListenersCounter++; + alreadyListeningTo[mountAt[topListenersIDKey]] = {}; + } + return alreadyListeningTo[mountAt[topListenersIDKey]]; +} + +/** + * We listen for bubbled touch events on the document object. + * + * Firefox v8.01 (and possibly others) exhibited strange behavior when + * mounting `onmousemove` events at some node that was not the document + * element. The symptoms were that if your mouse is not moving over something + * contained within that mount point (for example on the background) the + * top-level listeners for `onmousemove` won't be called. However, if you + * register the `mousemove` on the document object, then it will of course + * catch all `mousemove`s. This along with iOS quirks, justifies restricting + * top-level listeners to the document object only, at least for these + * movement types of events and possibly all events. + * + * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html + * + * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but + * they bubble to document. + * + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @param {object} contentDocumentHandle Document which owns the container + */ +function listenTo(registrationName, contentDocumentHandle) { + var mountAt = contentDocumentHandle; + var isListening = getListeningForDocument(mountAt); + var dependencies = registrationNameDependencies[registrationName]; + + for (var i = 0; i < dependencies.length; i++) { + var dependency = dependencies[i]; + if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) { + if (dependency === 'topScroll') { + trapCapturedEvent('topScroll', 'scroll', mountAt); + } else if (dependency === 'topFocus' || dependency === 'topBlur') { + trapCapturedEvent('topFocus', 'focus', mountAt); + trapCapturedEvent('topBlur', 'blur', mountAt); + + // to make sure blur and focus event listeners are only attached once + isListening.topBlur = true; + isListening.topFocus = true; + } else if (dependency === 'topCancel') { + if (isEventSupported('cancel', true)) { + trapCapturedEvent('topCancel', 'cancel', mountAt); + } + isListening.topCancel = true; + } else if (dependency === 'topClose') { + if (isEventSupported('close', true)) { + trapCapturedEvent('topClose', 'close', mountAt); + } + isListening.topClose = true; + } else if (topLevelTypes.hasOwnProperty(dependency)) { + trapBubbledEvent(dependency, topLevelTypes[dependency], mountAt); + } + + isListening[dependency] = true; + } + } +} + +function isListeningToAllDependencies(registrationName, mountAt) { + var isListening = getListeningForDocument(mountAt); + var dependencies = registrationNameDependencies[registrationName]; + for (var i = 0; i < dependencies.length; i++) { + var dependency = dependencies[i]; + if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) { + return false; + } + } + return true; +} + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @typechecks + */ + +/* eslint-disable fb-www/typeof-undefined */ + +/** + * Same as document.activeElement but wraps in a try-catch block. In IE it is + * not safe to call document.activeElement if there is nothing focused. + * + * The activeElement will be null only if the document or document body is not + * yet defined. + * + * @param {?DOMDocument} doc Defaults to current document. + * @return {?DOMElement} + */ +function getActiveElement(doc) /*?DOMElement*/{ + doc = doc || (typeof document !== 'undefined' ? document : undefined); + if (typeof doc === 'undefined') { + return null; + } + try { + return doc.activeElement || doc.body; + } catch (e) { + return doc.body; + } +} + +var getActiveElement_1 = getActiveElement; + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @typechecks + * + */ + +/*eslint-disable no-self-compare */ + + + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ +function is(x, y) { + // SameValue algorithm + if (x === y) { + // Steps 1-5, 7-10 + // Steps 6.b-6.e: +0 != -0 + // Added the nonzero y check to make Flow happy, but it is redundant + return x !== 0 || y !== 0 || 1 / x === 1 / y; + } else { + // Step 6.a: NaN == NaN + return x !== x && y !== y; + } +} + +/** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ +function shallowEqual(objA, objB) { + if (is(objA, objB)) { + return true; + } + + if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { + return false; + } + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } + + // Test for A's keys different from B. + for (var i = 0; i < keysA.length; i++) { + if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { + return false; + } + } + + return true; +} + +var shallowEqual_1 = shallowEqual; + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @typechecks + */ + +/** + * @param {*} object The object to check. + * @return {boolean} Whether or not the object is a DOM node. + */ +function isNode(object) { + var doc = object ? object.ownerDocument || object : document; + var defaultView = doc.defaultView || window; + return !!(object && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string')); +} + +var isNode_1 = isNode; + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @typechecks + */ + + + +/** + * @param {*} object The object to check. + * @return {boolean} Whether or not the object is a DOM text node. + */ +function isTextNode(object) { + return isNode_1(object) && object.nodeType == 3; +} + +var isTextNode_1 = isTextNode; + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * + */ + + + +/*eslint-disable no-bitwise */ + +/** + * Checks if a given DOM node contains or is another DOM node. + */ +function containsNode(outerNode, innerNode) { + if (!outerNode || !innerNode) { + return false; + } else if (outerNode === innerNode) { + return true; + } else if (isTextNode_1(outerNode)) { + return false; + } else if (isTextNode_1(innerNode)) { + return containsNode(outerNode, innerNode.parentNode); + } else if ('contains' in outerNode) { + return outerNode.contains(innerNode); + } else if (outerNode.compareDocumentPosition) { + return !!(outerNode.compareDocumentPosition(innerNode) & 16); + } else { + return false; + } +} + +var containsNode_1 = containsNode; + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + + + +/** + * @param {DOMElement} node input/textarea to focus + */ + +function focusNode(node) { + // IE8 can throw "Can't move focus to the control because it is invisible, + // not enabled, or of a type that does not accept the focus." for all kinds of + // reasons that are too expensive and fragile to test. + try { + node.focus(); + } catch (e) {} +} + +var focusNode_1 = focusNode; + +/** + * Given any node return the first leaf node without children. + * + * @param {DOMElement|DOMTextNode} node + * @return {DOMElement|DOMTextNode} + */ +function getLeafNode(node) { + while (node && node.firstChild) { + node = node.firstChild; + } + return node; +} + +/** + * Get the next sibling within a container. This will walk up the + * DOM if a node's siblings have been exhausted. + * + * @param {DOMElement|DOMTextNode} node + * @return {?DOMElement|DOMTextNode} + */ +function getSiblingNode(node) { + while (node) { + if (node.nextSibling) { + return node.nextSibling; + } + node = node.parentNode; + } +} + +/** + * Get object describing the nodes which contain characters at offset. + * + * @param {DOMElement|DOMTextNode} root + * @param {number} offset + * @return {?object} + */ +function getNodeForCharacterOffset(root, offset) { + var node = getLeafNode(root); + var nodeStart = 0; + var nodeEnd = 0; + + while (node) { + if (node.nodeType === TEXT_NODE) { + nodeEnd = nodeStart + node.textContent.length; + + if (nodeStart <= offset && nodeEnd >= offset) { + return { + node: node, + offset: offset - nodeStart + }; + } + + nodeStart = nodeEnd; + } + + node = getLeafNode(getSiblingNode(node)); + } +} + +/** + * @param {DOMElement} outerNode + * @return {?object} + */ +function getOffsets(outerNode) { + var selection = window.getSelection && window.getSelection(); + + if (!selection || selection.rangeCount === 0) { + return null; + } + + var anchorNode = selection.anchorNode, + anchorOffset = selection.anchorOffset, + focusNode = selection.focusNode, + focusOffset = selection.focusOffset; + + // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the + // up/down buttons on an . Anonymous divs do not seem to + // expose properties, triggering a "Permission denied error" if any of its + // properties are accessed. The only seemingly possible way to avoid erroring + // is to access a property that typically works for non-anonymous divs and + // catch any error that may otherwise arise. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=208427 + + try { + /* eslint-disable no-unused-expressions */ + anchorNode.nodeType; + focusNode.nodeType; + /* eslint-enable no-unused-expressions */ + } catch (e) { + return null; + } + + return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset); +} + +/** + * Returns {start, end} where `start` is the character/codepoint index of + * (anchorNode, anchorOffset) within the textContent of `outerNode`, and + * `end` is the index of (focusNode, focusOffset). + * + * Returns null if you pass in garbage input but we should probably just crash. + * + * Exported only for testing. + */ +function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) { + var length = 0; + var start = -1; + var end = -1; + var indexWithinAnchor = 0; + var indexWithinFocus = 0; + var node = outerNode; + var parentNode = null; + + outer: while (true) { + var next = null; + + while (true) { + if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) { + start = length + anchorOffset; + } + if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) { + end = length + focusOffset; + } + + if (node.nodeType === TEXT_NODE) { + length += node.nodeValue.length; + } + + if ((next = node.firstChild) === null) { + break; + } + // Moving from `node` to its first child `next`. + parentNode = node; + node = next; + } + + while (true) { + if (node === outerNode) { + // If `outerNode` has children, this is always the second time visiting + // it. If it has no children, this is still the first loop, and the only + // valid selection is anchorNode and focusNode both equal to this node + // and both offsets 0, in which case we will have handled above. + break outer; + } + if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) { + start = length; + } + if (parentNode === focusNode && ++indexWithinFocus === focusOffset) { + end = length; + } + if ((next = node.nextSibling) !== null) { + break; + } + node = parentNode; + parentNode = node.parentNode; + } + + // Moving from `node` to its next sibling `next`. + node = next; + } + + if (start === -1 || end === -1) { + // This should never happen. (Would happen if the anchor/focus nodes aren't + // actually inside the passed-in node.) + return null; + } + + return { + start: start, + end: end + }; +} + +/** + * In modern non-IE browsers, we can support both forward and backward + * selections. + * + * Note: IE10+ supports the Selection object, but it does not support + * the `extend` method, which means that even in modern IE, it's not possible + * to programmatically create a backward selection. Thus, for all IE + * versions, we use the old IE API to create our selections. + * + * @param {DOMElement|DOMTextNode} node + * @param {object} offsets + */ +function setOffsets(node, offsets) { + if (!window.getSelection) { + return; + } + + var selection = window.getSelection(); + var length = node[getTextContentAccessor()].length; + var start = Math.min(offsets.start, length); + var end = offsets.end === undefined ? start : Math.min(offsets.end, length); + + // IE 11 uses modern selection, but doesn't support the extend method. + // Flip backward selections, so we can set with a single range. + if (!selection.extend && start > end) { + var temp = end; + end = start; + start = temp; + } + + var startMarker = getNodeForCharacterOffset(node, start); + var endMarker = getNodeForCharacterOffset(node, end); + + if (startMarker && endMarker) { + if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) { + return; + } + var range = document.createRange(); + range.setStart(startMarker.node, startMarker.offset); + selection.removeAllRanges(); + + if (start > end) { + selection.addRange(range); + selection.extend(endMarker.node, endMarker.offset); + } else { + range.setEnd(endMarker.node, endMarker.offset); + selection.addRange(range); + } + } +} + +function isInDocument(node) { + return containsNode_1(document.documentElement, node); +} + +/** + * @ReactInputSelection: React input selection module. Based on Selection.js, + * but modified to be suitable for react and has a couple of bug fixes (doesn't + * assume buttons have range selections allowed). + * Input selection module for React. + */ + +function hasSelectionCapabilities(elem) { + var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); + return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true'); +} + +function getSelectionInformation() { + var focusedElem = getActiveElement_1(); + return { + focusedElem: focusedElem, + selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection$1(focusedElem) : null + }; +} + +/** + * @restoreSelection: If any selection information was potentially lost, + * restore it. This is useful when performing operations that could remove dom + * nodes and place them back in, resulting in focus being lost. + */ +function restoreSelection(priorSelectionInformation) { + var curFocusedElem = getActiveElement_1(); + var priorFocusedElem = priorSelectionInformation.focusedElem; + var priorSelectionRange = priorSelectionInformation.selectionRange; + if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) { + if (hasSelectionCapabilities(priorFocusedElem)) { + setSelection(priorFocusedElem, priorSelectionRange); + } + + // Focusing a node can change the scroll position, which is undesirable + var ancestors = []; + var ancestor = priorFocusedElem; + while (ancestor = ancestor.parentNode) { + if (ancestor.nodeType === ELEMENT_NODE) { + ancestors.push({ + element: ancestor, + left: ancestor.scrollLeft, + top: ancestor.scrollTop + }); + } + } + + focusNode_1(priorFocusedElem); + + for (var i = 0; i < ancestors.length; i++) { + var info = ancestors[i]; + info.element.scrollLeft = info.left; + info.element.scrollTop = info.top; + } + } +} + +/** + * @getSelection: Gets the selection bounds of a focused textarea, input or + * contentEditable node. + * -@input: Look up selection bounds of this input + * -@return {start: selectionStart, end: selectionEnd} + */ +function getSelection$1(input) { + var selection = void 0; + + if ('selectionStart' in input) { + // Modern browser with input or textarea. + selection = { + start: input.selectionStart, + end: input.selectionEnd + }; + } else { + // Content editable or old IE textarea. + selection = getOffsets(input); + } + + return selection || { start: 0, end: 0 }; +} + +/** + * @setSelection: Sets the selection bounds of a textarea or input and focuses + * the input. + * -@input Set selection bounds of this input or textarea + * -@offsets Object of same form that is returned from get* + */ +function setSelection(input, offsets) { + var start = offsets.start, + end = offsets.end; + + if (end === undefined) { + end = start; + } + + if ('selectionStart' in input) { + input.selectionStart = start; + input.selectionEnd = Math.min(end, input.value.length); + } else { + setOffsets(input, offsets); + } +} + +var skipSelectionChangeEvent = ExecutionEnvironment_1.canUseDOM && 'documentMode' in document && document.documentMode <= 11; + +var eventTypes$3 = { + select: { + phasedRegistrationNames: { + bubbled: 'onSelect', + captured: 'onSelectCapture' + }, + dependencies: ['topBlur', 'topContextMenu', 'topFocus', 'topKeyDown', 'topKeyUp', 'topMouseDown', 'topMouseUp', 'topSelectionChange'] + } +}; + +var activeElement$1 = null; +var activeElementInst$1 = null; +var lastSelection = null; +var mouseDown = false; + +/** + * Get an object which is a unique representation of the current selection. + * + * The return value will not be consistent across nodes or browsers, but + * two identical selections on the same node will return identical objects. + * + * @param {DOMElement} node + * @return {object} + */ +function getSelection(node) { + if ('selectionStart' in node && hasSelectionCapabilities(node)) { + return { + start: node.selectionStart, + end: node.selectionEnd + }; + } else if (window.getSelection) { + var selection = window.getSelection(); + return { + anchorNode: selection.anchorNode, + anchorOffset: selection.anchorOffset, + focusNode: selection.focusNode, + focusOffset: selection.focusOffset + }; + } +} + +/** + * Poll selection to see whether it's changed. + * + * @param {object} nativeEvent + * @return {?SyntheticEvent} + */ +function constructSelectEvent(nativeEvent, nativeEventTarget) { + // Ensure we have the right element, and that the user is not dragging a + // selection (this matches native `select` event behavior). In HTML5, select + // fires only on input and textarea thus if there's no focused element we + // won't dispatch. + if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement_1()) { + return null; + } + + // Only fire when selection has actually changed. + var currentSelection = getSelection(activeElement$1); + if (!lastSelection || !shallowEqual_1(lastSelection, currentSelection)) { + lastSelection = currentSelection; + + var syntheticEvent = SyntheticEvent$1.getPooled(eventTypes$3.select, activeElementInst$1, nativeEvent, nativeEventTarget); + + syntheticEvent.type = 'select'; + syntheticEvent.target = activeElement$1; + + accumulateTwoPhaseDispatches(syntheticEvent); + + return syntheticEvent; + } + + return null; +} + +/** + * This plugin creates an `onSelect` event that normalizes select events + * across form elements. + * + * Supported elements are: + * - input (see `isTextInputElement`) + * - textarea + * - contentEditable + * + * This differs from native browser implementations in the following ways: + * - Fires on contentEditable fields as well as inputs. + * - Fires for collapsed selection. + * - Fires after user input. + */ +var SelectEventPlugin = { + eventTypes: eventTypes$3, + + extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var doc = nativeEventTarget.window === nativeEventTarget ? nativeEventTarget.document : nativeEventTarget.nodeType === DOCUMENT_NODE ? nativeEventTarget : nativeEventTarget.ownerDocument; + // Track whether all listeners exists for this plugin. If none exist, we do + // not extract events. See #3639. + if (!doc || !isListeningToAllDependencies('onSelect', doc)) { + return null; + } + + var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window; + + switch (topLevelType) { + // Track the input node that has focus. + case 'topFocus': + if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') { + activeElement$1 = targetNode; + activeElementInst$1 = targetInst; + lastSelection = null; + } + break; + case 'topBlur': + activeElement$1 = null; + activeElementInst$1 = null; + lastSelection = null; + break; + // Don't fire the event while the user is dragging. This matches the + // semantics of the native select event. + case 'topMouseDown': + mouseDown = true; + break; + case 'topContextMenu': + case 'topMouseUp': + mouseDown = false; + return constructSelectEvent(nativeEvent, nativeEventTarget); + // Chrome and IE fire non-standard event when selection is changed (and + // sometimes when it hasn't). IE's event fires out of order with respect + // to key and input events on deletion, so we discard it. + // + // Firefox doesn't support selectionchange, so check selection status + // after each key entry. The selection changes after keydown and before + // keyup, but we check on keydown as well in the case of holding down a + // key, when multiple keydown events are fired but only one keyup is. + // This is also our approach for IE handling, for the reason above. + case 'topSelectionChange': + if (skipSelectionChangeEvent) { + break; + } + // falls through + case 'topKeyDown': + case 'topKeyUp': + return constructSelectEvent(nativeEvent, nativeEventTarget); + } + + return null; + } +}; + +/** + * @interface Event + * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface + * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent + */ +var AnimationEventInterface = { + animationName: null, + elapsedTime: null, + pseudoElement: null +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticEvent} + */ +function SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticEvent$1.augmentClass(SyntheticAnimationEvent, AnimationEventInterface); + +/** + * @interface Event + * @see http://www.w3.org/TR/clipboard-apis/ + */ +var ClipboardEventInterface = { + clipboardData: function (event) { + return 'clipboardData' in event ? event.clipboardData : window.clipboardData; + } +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticEvent} + */ +function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticEvent$1.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface); + +/** + * @interface FocusEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ +var FocusEventInterface = { + relatedTarget: null +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticUIEvent} + */ +function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface); + +/** + * `charCode` represents the actual "character code" and is safe to use with + * `String.fromCharCode`. As such, only keys that correspond to printable + * characters produce a valid `charCode`, the only exception to this is Enter. + * The Tab-key is considered non-printable and does not have a `charCode`, + * presumably because it does not produce a tab-character in browsers. + * + * @param {object} nativeEvent Native browser event. + * @return {number} Normalized `charCode` property. + */ +function getEventCharCode(nativeEvent) { + var charCode; + var keyCode = nativeEvent.keyCode; + + if ('charCode' in nativeEvent) { + charCode = nativeEvent.charCode; + + // FF does not set `charCode` for the Enter-key, check against `keyCode`. + if (charCode === 0 && keyCode === 13) { + charCode = 13; + } + } else { + // IE8 does not implement `charCode`, but `keyCode` has the correct value. + charCode = keyCode; + } + + // Some non-printable keys are reported in `charCode`/`keyCode`, discard them. + // Must not discard the (non-)printable Enter-key. + if (charCode >= 32 || charCode === 13) { + return charCode; + } + + return 0; +} + +/** + * Normalization of deprecated HTML5 `key` values + * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names + */ +var normalizeKey = { + Esc: 'Escape', + Spacebar: ' ', + Left: 'ArrowLeft', + Up: 'ArrowUp', + Right: 'ArrowRight', + Down: 'ArrowDown', + Del: 'Delete', + Win: 'OS', + Menu: 'ContextMenu', + Apps: 'ContextMenu', + Scroll: 'ScrollLock', + MozPrintableKey: 'Unidentified' +}; + +/** + * Translation from legacy `keyCode` to HTML5 `key` + * Only special keys supported, all others depend on keyboard layout or browser + * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names + */ +var translateToKey = { + '8': 'Backspace', + '9': 'Tab', + '12': 'Clear', + '13': 'Enter', + '16': 'Shift', + '17': 'Control', + '18': 'Alt', + '19': 'Pause', + '20': 'CapsLock', + '27': 'Escape', + '32': ' ', + '33': 'PageUp', + '34': 'PageDown', + '35': 'End', + '36': 'Home', + '37': 'ArrowLeft', + '38': 'ArrowUp', + '39': 'ArrowRight', + '40': 'ArrowDown', + '45': 'Insert', + '46': 'Delete', + '112': 'F1', + '113': 'F2', + '114': 'F3', + '115': 'F4', + '116': 'F5', + '117': 'F6', + '118': 'F7', + '119': 'F8', + '120': 'F9', + '121': 'F10', + '122': 'F11', + '123': 'F12', + '144': 'NumLock', + '145': 'ScrollLock', + '224': 'Meta' +}; + +/** + * @param {object} nativeEvent Native browser event. + * @return {string} Normalized `key` property. + */ +function getEventKey(nativeEvent) { + if (nativeEvent.key) { + // Normalize inconsistent values reported by browsers due to + // implementations of a working draft specification. + + // FireFox implements `key` but returns `MozPrintableKey` for all + // printable characters (normalized to `Unidentified`), ignore it. + var key = normalizeKey[nativeEvent.key] || nativeEvent.key; + if (key !== 'Unidentified') { + return key; + } + } + + // Browser does not implement `key`, polyfill as much of it as we can. + if (nativeEvent.type === 'keypress') { + var charCode = getEventCharCode(nativeEvent); + + // The enter-key is technically both printable and non-printable and can + // thus be captured by `keypress`, no other non-printable key should. + return charCode === 13 ? 'Enter' : String.fromCharCode(charCode); + } + if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') { + // While user keyboard layout determines the actual meaning of each + // `keyCode` value, almost all function keys have a universal value. + return translateToKey[nativeEvent.keyCode] || 'Unidentified'; + } + return ''; +} + +/** + * @interface KeyboardEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ +var KeyboardEventInterface = { + key: getEventKey, + location: null, + ctrlKey: null, + shiftKey: null, + altKey: null, + metaKey: null, + repeat: null, + locale: null, + getModifierState: getEventModifierState, + // Legacy Interface + charCode: function (event) { + // `charCode` is the result of a KeyPress event and represents the value of + // the actual printable character. + + // KeyPress is deprecated, but its replacement is not yet final and not + // implemented in any major browser. Only KeyPress has charCode. + if (event.type === 'keypress') { + return getEventCharCode(event); + } + return 0; + }, + keyCode: function (event) { + // `keyCode` is the result of a KeyDown/Up event and represents the value of + // physical keyboard key. + + // The actual meaning of the value depends on the users' keyboard layout + // which cannot be detected. Assuming that it is a US keyboard layout + // provides a surprisingly accurate mapping for US and European users. + // Due to this, it is left to the user to implement at this time. + if (event.type === 'keydown' || event.type === 'keyup') { + return event.keyCode; + } + return 0; + }, + which: function (event) { + // `which` is an alias for either `keyCode` or `charCode` depending on the + // type of the event. + if (event.type === 'keypress') { + return getEventCharCode(event); + } + if (event.type === 'keydown' || event.type === 'keyup') { + return event.keyCode; + } + return 0; + } +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticUIEvent} + */ +function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface); + +/** + * @interface DragEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ +var DragEventInterface = { + dataTransfer: null +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticMouseEvent} + */ +function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface); + +/** + * @interface TouchEvent + * @see http://www.w3.org/TR/touch-events/ + */ +var TouchEventInterface = { + touches: null, + targetTouches: null, + changedTouches: null, + altKey: null, + metaKey: null, + ctrlKey: null, + shiftKey: null, + getModifierState: getEventModifierState +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticUIEvent} + */ +function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface); + +/** + * @interface Event + * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events- + * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent + */ +var TransitionEventInterface = { + propertyName: null, + elapsedTime: null, + pseudoElement: null +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticEvent} + */ +function SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticEvent$1.augmentClass(SyntheticTransitionEvent, TransitionEventInterface); + +/** + * @interface WheelEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ +var WheelEventInterface = { + deltaX: function (event) { + return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive). + 'wheelDeltaX' in event ? -event.wheelDeltaX : 0; + }, + deltaY: function (event) { + return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive). + 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). + 'wheelDelta' in event ? -event.wheelDelta : 0; + }, + deltaZ: null, + + // Browsers without "deltaMode" is reporting in raw wheel delta where one + // notch on the scroll is always +/- 120, roughly equivalent to pixels. + // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or + // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size. + deltaMode: null +}; + +/** + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {string} dispatchMarker Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @extends {SyntheticMouseEvent} + */ +function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) { + return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget); +} + +SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface); + +/** + * Turns + * ['abort', ...] + * into + * eventTypes = { + * 'abort': { + * phasedRegistrationNames: { + * bubbled: 'onAbort', + * captured: 'onAbortCapture', + * }, + * dependencies: ['topAbort'], + * }, + * ... + * }; + * topLevelEventsToDispatchConfig = { + * 'topAbort': { sameConfig } + * }; + */ +var eventTypes$4 = {}; +var topLevelEventsToDispatchConfig = {}; +['abort', 'animationEnd', 'animationIteration', 'animationStart', 'blur', 'cancel', 'canPlay', 'canPlayThrough', 'click', 'close', 'contextMenu', 'copy', 'cut', 'doubleClick', 'drag', 'dragEnd', 'dragEnter', 'dragExit', 'dragLeave', 'dragOver', 'dragStart', 'drop', 'durationChange', 'emptied', 'encrypted', 'ended', 'error', 'focus', 'input', 'invalid', 'keyDown', 'keyPress', 'keyUp', 'load', 'loadedData', 'loadedMetadata', 'loadStart', 'mouseDown', 'mouseMove', 'mouseOut', 'mouseOver', 'mouseUp', 'paste', 'pause', 'play', 'playing', 'progress', 'rateChange', 'reset', 'scroll', 'seeked', 'seeking', 'stalled', 'submit', 'suspend', 'timeUpdate', 'toggle', 'touchCancel', 'touchEnd', 'touchMove', 'touchStart', 'transitionEnd', 'volumeChange', 'waiting', 'wheel'].forEach(function (event) { + var capitalizedEvent = event[0].toUpperCase() + event.slice(1); + var onEvent = 'on' + capitalizedEvent; + var topEvent = 'top' + capitalizedEvent; + + var type = { + phasedRegistrationNames: { + bubbled: onEvent, + captured: onEvent + 'Capture' + }, + dependencies: [topEvent] + }; + eventTypes$4[event] = type; + topLevelEventsToDispatchConfig[topEvent] = type; +}); + +// Only used in DEV for exhaustiveness validation. +var knownHTMLTopLevelTypes = ['topAbort', 'topCancel', 'topCanPlay', 'topCanPlayThrough', 'topClose', 'topDurationChange', 'topEmptied', 'topEncrypted', 'topEnded', 'topError', 'topInput', 'topInvalid', 'topLoad', 'topLoadedData', 'topLoadedMetadata', 'topLoadStart', 'topPause', 'topPlay', 'topPlaying', 'topProgress', 'topRateChange', 'topReset', 'topSeeked', 'topSeeking', 'topStalled', 'topSubmit', 'topSuspend', 'topTimeUpdate', 'topToggle', 'topVolumeChange', 'topWaiting']; + +var SimpleEventPlugin = { + eventTypes: eventTypes$4, + + extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType]; + if (!dispatchConfig) { + return null; + } + var EventConstructor; + switch (topLevelType) { + case 'topKeyPress': + // Firefox creates a keypress event for function keys too. This removes + // the unwanted keypress events. Enter is however both printable and + // non-printable. One would expect Tab to be as well (but it isn't). + if (getEventCharCode(nativeEvent) === 0) { + return null; + } + /* falls through */ + case 'topKeyDown': + case 'topKeyUp': + EventConstructor = SyntheticKeyboardEvent; + break; + case 'topBlur': + case 'topFocus': + EventConstructor = SyntheticFocusEvent; + break; + case 'topClick': + // Firefox creates a click event on right mouse clicks. This removes the + // unwanted click events. + if (nativeEvent.button === 2) { + return null; + } + /* falls through */ + case 'topDoubleClick': + case 'topMouseDown': + case 'topMouseMove': + case 'topMouseUp': + // TODO: Disabled elements should not respond to mouse events + /* falls through */ + case 'topMouseOut': + case 'topMouseOver': + case 'topContextMenu': + EventConstructor = SyntheticMouseEvent; + break; + case 'topDrag': + case 'topDragEnd': + case 'topDragEnter': + case 'topDragExit': + case 'topDragLeave': + case 'topDragOver': + case 'topDragStart': + case 'topDrop': + EventConstructor = SyntheticDragEvent; + break; + case 'topTouchCancel': + case 'topTouchEnd': + case 'topTouchMove': + case 'topTouchStart': + EventConstructor = SyntheticTouchEvent; + break; + case 'topAnimationEnd': + case 'topAnimationIteration': + case 'topAnimationStart': + EventConstructor = SyntheticAnimationEvent; + break; + case 'topTransitionEnd': + EventConstructor = SyntheticTransitionEvent; + break; + case 'topScroll': + EventConstructor = SyntheticUIEvent; + break; + case 'topWheel': + EventConstructor = SyntheticWheelEvent; + break; + case 'topCopy': + case 'topCut': + case 'topPaste': + EventConstructor = SyntheticClipboardEvent; + break; + default: + { + if (knownHTMLTopLevelTypes.indexOf(topLevelType) === -1) { + warning_1(false, 'SimpleEventPlugin: Unhandled event type, `%s`. This warning ' + 'is likely caused by a bug in React. Please file an issue.', topLevelType); + } + } + // HTML Events + // @see http://www.w3.org/TR/html5/index.html#events-0 + EventConstructor = SyntheticEvent$1; + break; + } + var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget); + accumulateTwoPhaseDispatches(event); + return event; + } +}; + +setHandleTopLevel(handleTopLevel); + +/** + * Inject modules for resolving DOM hierarchy and plugin ordering. + */ +injection$1.injectEventPluginOrder(DOMEventPluginOrder); +injection$2.injectComponentTree(ReactDOMComponentTree); + +/** + * Some important event plugins included by default (without having to require + * them). + */ +injection$1.injectEventPluginsByName({ + SimpleEventPlugin: SimpleEventPlugin, + EnterLeaveEventPlugin: EnterLeaveEventPlugin, + ChangeEventPlugin: ChangeEventPlugin, + SelectEventPlugin: SelectEventPlugin, + BeforeInputEventPlugin: BeforeInputEventPlugin +}); + +var enableAsyncSubtreeAPI = true; +var enableAsyncSchedulingByDefaultInReactDOM = false; +// Exports ReactDOM.createRoot +var enableCreateRoot = false; +var enableUserTimingAPI = true; + +// Mutating mode (React DOM, React ART, React Native): +var enableMutatingReconciler = true; +// Experimental noop mode (currently unused): +var enableNoopReconciler = false; +// Experimental persistent mode (CS): +var enablePersistentReconciler = false; + +// Helps identify side effects in begin-phase lifecycle hooks and setState reducers: +var debugRenderPhaseSideEffects = false; + +// Only used in www builds. + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + + + +var emptyObject = {}; + +{ + Object.freeze(emptyObject); +} + +var emptyObject_1 = emptyObject; + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + + +var ReactPropTypesSecret$1 = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; + +var ReactPropTypesSecret_1 = ReactPropTypesSecret$1; + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + + +{ + var invariant$2 = invariant_1; + var warning$2 = warning_1; + var ReactPropTypesSecret = ReactPropTypesSecret_1; + var loggedTypeFailures = {}; +} + +/** + * Assert that the values match with the type specs. + * Error messages are memorized and will only be shown once. + * + * @param {object} typeSpecs Map of name to a ReactPropType + * @param {object} values Runtime values that need to be type-checked + * @param {string} location e.g. "prop", "context", "child context" + * @param {string} componentName Name of the component for error messages. + * @param {?Function} getStack Returns the component stack. + * @private + */ +function checkPropTypes(typeSpecs, values, location, componentName, getStack) { + { + for (var typeSpecName in typeSpecs) { + if (typeSpecs.hasOwnProperty(typeSpecName)) { + var error; + // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + invariant$2(typeof typeSpecs[typeSpecName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'the `prop-types` package, but received `%s`.', componentName || 'React class', location, typeSpecName, typeof typeSpecs[typeSpecName]); + error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret); + } catch (ex) { + error = ex; + } + warning$2(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error); + if (error instanceof Error && !(error.message in loggedTypeFailures)) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error.message] = true; + + var stack = getStack ? getStack() : ''; + + warning$2(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : ''); + } + } + } + } +} + +var checkPropTypes_1 = checkPropTypes; + +var valueStack = []; + +{ + var fiberStack = []; +} + +var index = -1; + +function createCursor(defaultValue) { + return { + current: defaultValue + }; +} + + + +function pop(cursor, fiber) { + if (index < 0) { + { + warning_1(false, 'Unexpected pop.'); + } + return; + } + + { + if (fiber !== fiberStack[index]) { + warning_1(false, 'Unexpected Fiber popped.'); + } + } + + cursor.current = valueStack[index]; + + valueStack[index] = null; + + { + fiberStack[index] = null; + } + + index--; +} + +function push(cursor, value, fiber) { + index++; + + valueStack[index] = cursor.current; + + { + fiberStack[index] = fiber; + } + + cursor.current = value; +} + +function reset$1() { + while (index > -1) { + valueStack[index] = null; + + { + fiberStack[index] = null; + } + + index--; + } +} + +var describeComponentFrame = function (name, source, ownerName) { + return '\n in ' + (name || 'Unknown') + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : ''); +}; + +function describeFiber(fiber) { + switch (fiber.tag) { + case IndeterminateComponent: + case FunctionalComponent: + case ClassComponent: + case HostComponent: + var owner = fiber._debugOwner; + var source = fiber._debugSource; + var name = getComponentName(fiber); + var ownerName = null; + if (owner) { + ownerName = getComponentName(owner); + } + return describeComponentFrame(name, source, ownerName); + default: + return ''; + } +} + +// This function can only be called with a work-in-progress fiber and +// only during begin or complete phase. Do not call it under any other +// circumstances. +function getStackAddendumByWorkInProgressFiber(workInProgress) { + var info = ''; + var node = workInProgress; + do { + info += describeFiber(node); + // Otherwise this return pointer might point to the wrong tree: + node = node['return']; + } while (node); + return info; +} + +function getCurrentFiberOwnerName() { + { + var fiber = ReactDebugCurrentFiber.current; + if (fiber === null) { + return null; + } + var owner = fiber._debugOwner; + if (owner !== null && typeof owner !== 'undefined') { + return getComponentName(owner); + } + } + return null; +} + +function getCurrentFiberStackAddendum() { + { + var fiber = ReactDebugCurrentFiber.current; + if (fiber === null) { + return null; + } + // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. + return getStackAddendumByWorkInProgressFiber(fiber); + } + return null; +} + +function resetCurrentFiber() { + ReactDebugCurrentFrame.getCurrentStack = null; + ReactDebugCurrentFiber.current = null; + ReactDebugCurrentFiber.phase = null; +} + +function setCurrentFiber(fiber) { + ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; + ReactDebugCurrentFiber.current = fiber; + ReactDebugCurrentFiber.phase = null; +} + +function setCurrentPhase(phase) { + ReactDebugCurrentFiber.phase = phase; +} + +var ReactDebugCurrentFiber = { + current: null, + phase: null, + resetCurrentFiber: resetCurrentFiber, + setCurrentFiber: setCurrentFiber, + setCurrentPhase: setCurrentPhase, + getCurrentFiberOwnerName: getCurrentFiberOwnerName, + getCurrentFiberStackAddendum: getCurrentFiberStackAddendum +}; + +// Prefix measurements so that it's possible to filter them. +// Longer prefixes are hard to read in DevTools. +var reactEmoji = '\u269B'; +var warningEmoji = '\u26D4'; +var supportsUserTiming = typeof performance !== 'undefined' && typeof performance.mark === 'function' && typeof performance.clearMarks === 'function' && typeof performance.measure === 'function' && typeof performance.clearMeasures === 'function'; + +// Keep track of current fiber so that we know the path to unwind on pause. +// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? +var currentFiber = null; +// If we're in the middle of user code, which fiber and method is it? +// Reusing `currentFiber` would be confusing for this because user code fiber +// can change during commit phase too, but we don't need to unwind it (since +// lifecycles in the commit phase don't resemble a tree). +var currentPhase = null; +var currentPhaseFiber = null; +// Did lifecycle hook schedule an update? This is often a performance problem, +// so we will keep track of it, and include it in the report. +// Track commits caused by cascading updates. +var isCommitting = false; +var hasScheduledUpdateInCurrentCommit = false; +var hasScheduledUpdateInCurrentPhase = false; +var commitCountInCurrentWorkLoop = 0; +var effectCountInCurrentCommit = 0; +var isWaitingForCallback = false; +// During commits, we only show a measurement once per method name +// to avoid stretch the commit phase with measurement overhead. +var labelsInCurrentCommit = new Set(); + +var formatMarkName = function (markName) { + return reactEmoji + ' ' + markName; +}; + +var formatLabel = function (label, warning) { + var prefix = warning ? warningEmoji + ' ' : reactEmoji + ' '; + var suffix = warning ? ' Warning: ' + warning : ''; + return '' + prefix + label + suffix; +}; + +var beginMark = function (markName) { + performance.mark(formatMarkName(markName)); +}; + +var clearMark = function (markName) { + performance.clearMarks(formatMarkName(markName)); +}; + +var endMark = function (label, markName, warning) { + var formattedMarkName = formatMarkName(markName); + var formattedLabel = formatLabel(label, warning); + try { + performance.measure(formattedLabel, formattedMarkName); + } catch (err) {} + // If previous mark was missing for some reason, this will throw. + // This could only happen if React crashed in an unexpected place earlier. + // Don't pile on with more errors. + + // Clear marks immediately to avoid growing buffer. + performance.clearMarks(formattedMarkName); + performance.clearMeasures(formattedLabel); +}; + +var getFiberMarkName = function (label, debugID) { + return label + ' (#' + debugID + ')'; +}; + +var getFiberLabel = function (componentName, isMounted, phase) { + if (phase === null) { + // These are composite component total time measurements. + return componentName + ' [' + (isMounted ? 'update' : 'mount') + ']'; + } else { + // Composite component methods. + return componentName + '.' + phase; + } +}; + +var beginFiberMark = function (fiber, phase) { + var componentName = getComponentName(fiber) || 'Unknown'; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + + if (isCommitting && labelsInCurrentCommit.has(label)) { + // During the commit phase, we don't show duplicate labels because + // there is a fixed overhead for every measurement, and we don't + // want to stretch the commit phase beyond necessary. + return false; + } + labelsInCurrentCommit.add(label); + + var markName = getFiberMarkName(label, debugID); + beginMark(markName); + return true; +}; + +var clearFiberMark = function (fiber, phase) { + var componentName = getComponentName(fiber) || 'Unknown'; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + var markName = getFiberMarkName(label, debugID); + clearMark(markName); +}; + +var endFiberMark = function (fiber, phase, warning) { + var componentName = getComponentName(fiber) || 'Unknown'; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + var markName = getFiberMarkName(label, debugID); + endMark(label, markName, warning); +}; + +var shouldIgnoreFiber = function (fiber) { + // Host components should be skipped in the timeline. + // We could check typeof fiber.type, but does this work with RN? + switch (fiber.tag) { + case HostRoot: + case HostComponent: + case HostText: + case HostPortal: + case ReturnComponent: + case Fragment: + return true; + default: + return false; + } +}; + +var clearPendingPhaseMeasurement = function () { + if (currentPhase !== null && currentPhaseFiber !== null) { + clearFiberMark(currentPhaseFiber, currentPhase); + } + currentPhaseFiber = null; + currentPhase = null; + hasScheduledUpdateInCurrentPhase = false; +}; + +var pauseTimers = function () { + // Stops all currently active measurements so that they can be resumed + // if we continue in a later deferred loop from the same unit of work. + var fiber = currentFiber; + while (fiber) { + if (fiber._debugIsCurrentlyTiming) { + endFiberMark(fiber, null, null); + } + fiber = fiber['return']; + } +}; + +var resumeTimersRecursively = function (fiber) { + if (fiber['return'] !== null) { + resumeTimersRecursively(fiber['return']); + } + if (fiber._debugIsCurrentlyTiming) { + beginFiberMark(fiber, null); + } +}; + +var resumeTimers = function () { + // Resumes all measurements that were active during the last deferred loop. + if (currentFiber !== null) { + resumeTimersRecursively(currentFiber); + } +}; + +function recordEffect() { + if (enableUserTimingAPI) { + effectCountInCurrentCommit++; + } +} + +function recordScheduleUpdate() { + if (enableUserTimingAPI) { + if (isCommitting) { + hasScheduledUpdateInCurrentCommit = true; + } + if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') { + hasScheduledUpdateInCurrentPhase = true; + } + } +} + +function startRequestCallbackTimer() { + if (enableUserTimingAPI) { + if (supportsUserTiming && !isWaitingForCallback) { + isWaitingForCallback = true; + beginMark('(Waiting for async callback...)'); + } + } +} + +function stopRequestCallbackTimer(didExpire) { + if (enableUserTimingAPI) { + if (supportsUserTiming) { + isWaitingForCallback = false; + var warning = didExpire ? 'React was blocked by main thread' : null; + endMark('(Waiting for async callback...)', '(Waiting for async callback...)', warning); + } + } +} + +function startWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // If we pause, this is the fiber to unwind from. + currentFiber = fiber; + if (!beginFiberMark(fiber, null)) { + return; + } + fiber._debugIsCurrentlyTiming = true; + } +} + +function cancelWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // Remember we shouldn't complete measurement for this fiber. + // Otherwise flamechart will be deep even for small updates. + fiber._debugIsCurrentlyTiming = false; + clearFiberMark(fiber, null); + } +} + +function stopWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber['return']; + if (!fiber._debugIsCurrentlyTiming) { + return; + } + fiber._debugIsCurrentlyTiming = false; + endFiberMark(fiber, null, null); + } +} + +function stopFailedWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber['return']; + if (!fiber._debugIsCurrentlyTiming) { + return; + } + fiber._debugIsCurrentlyTiming = false; + var warning = 'An error was thrown inside this error boundary'; + endFiberMark(fiber, null, warning); + } +} + +function startPhaseTimer(fiber, phase) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + clearPendingPhaseMeasurement(); + if (!beginFiberMark(fiber, phase)) { + return; + } + currentPhaseFiber = fiber; + currentPhase = phase; + } +} + +function stopPhaseTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + if (currentPhase !== null && currentPhaseFiber !== null) { + var warning = hasScheduledUpdateInCurrentPhase ? 'Scheduled a cascading update' : null; + endFiberMark(currentPhaseFiber, currentPhase, warning); + } + currentPhase = null; + currentPhaseFiber = null; + } +} + +function startWorkLoopTimer(nextUnitOfWork) { + if (enableUserTimingAPI) { + currentFiber = nextUnitOfWork; + if (!supportsUserTiming) { + return; + } + commitCountInCurrentWorkLoop = 0; + // This is top level call. + // Any other measurements are performed within. + beginMark('(React Tree Reconciliation)'); + // Resume any measurements that were in progress during the last loop. + resumeTimers(); + } +} + +function stopWorkLoopTimer(interruptedBy) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var warning = null; + if (interruptedBy !== null) { + if (interruptedBy.tag === HostRoot) { + warning = 'A top-level update interrupted the previous render'; + } else { + var componentName = getComponentName(interruptedBy) || 'Unknown'; + warning = 'An update to ' + componentName + ' interrupted the previous render'; + } + } else if (commitCountInCurrentWorkLoop > 1) { + warning = 'There were cascading updates'; + } + commitCountInCurrentWorkLoop = 0; + // Pause any measurements until the next loop. + pauseTimers(); + endMark('(React Tree Reconciliation)', '(React Tree Reconciliation)', warning); + } +} + +function startCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + isCommitting = true; + hasScheduledUpdateInCurrentCommit = false; + labelsInCurrentCommit.clear(); + beginMark('(Committing Changes)'); + } +} + +function stopCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + + var warning = null; + if (hasScheduledUpdateInCurrentCommit) { + warning = 'Lifecycle hook scheduled a cascading update'; + } else if (commitCountInCurrentWorkLoop > 0) { + warning = 'Caused by a cascading update in earlier commit'; + } + hasScheduledUpdateInCurrentCommit = false; + commitCountInCurrentWorkLoop++; + isCommitting = false; + labelsInCurrentCommit.clear(); + + endMark('(Committing Changes)', '(Committing Changes)', warning); + } +} + +function startCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark('(Committing Host Effects)'); + } +} + +function stopCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark('(Committing Host Effects: ' + count + ' Total)', '(Committing Host Effects)', null); + } +} + +function startCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark('(Calling Lifecycle Methods)'); + } +} + +function stopCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark('(Calling Lifecycle Methods: ' + count + ' Total)', '(Calling Lifecycle Methods)', null); + } +} + +{ + var warnedAboutMissingGetChildContext = {}; +} + +// A cursor to the current merged context object on the stack. +var contextStackCursor = createCursor(emptyObject_1); +// A cursor to a boolean indicating whether the context has changed. +var didPerformWorkStackCursor = createCursor(false); +// Keep track of the previous context object that was on the stack. +// We use this to get access to the parent context after we have already +// pushed the next context provider, and now need to merge their contexts. +var previousContext = emptyObject_1; + +function getUnmaskedContext(workInProgress) { + var hasOwnContext = isContextProvider(workInProgress); + if (hasOwnContext) { + // If the fiber is a context provider itself, when we read its context + // we have already pushed its own child context on the stack. A context + // provider should not "see" its own child context. Therefore we read the + // previous (parent) context instead for a context provider. + return previousContext; + } + return contextStackCursor.current; +} + +function cacheContext(workInProgress, unmaskedContext, maskedContext) { + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; +} + +function getMaskedContext(workInProgress, unmaskedContext) { + var type = workInProgress.type; + var contextTypes = type.contextTypes; + if (!contextTypes) { + return emptyObject_1; + } + + // Avoid recreating masked context unless unmasked context has changed. + // Failing to do this will result in unnecessary calls to componentWillReceiveProps. + // This may trigger infinite loops if componentWillReceiveProps calls setState. + var instance = workInProgress.stateNode; + if (instance && instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext) { + return instance.__reactInternalMemoizedMaskedChildContext; + } + + var context = {}; + for (var key in contextTypes) { + context[key] = unmaskedContext[key]; + } + + { + var name = getComponentName(workInProgress) || 'Unknown'; + checkPropTypes_1(contextTypes, context, 'context', name, ReactDebugCurrentFiber.getCurrentFiberStackAddendum); + } + + // Cache unmasked context so we can avoid recreating masked context unless necessary. + // Context is created before the class component is instantiated so check for instance. + if (instance) { + cacheContext(workInProgress, unmaskedContext, context); + } + + return context; +} + +function hasContextChanged() { + return didPerformWorkStackCursor.current; +} + +function isContextConsumer(fiber) { + return fiber.tag === ClassComponent && fiber.type.contextTypes != null; +} + +function isContextProvider(fiber) { + return fiber.tag === ClassComponent && fiber.type.childContextTypes != null; +} + +function popContextProvider(fiber) { + if (!isContextProvider(fiber)) { + return; + } + + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); +} + +function popTopLevelContextObject(fiber) { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); +} + +function pushTopLevelContextObject(fiber, context, didChange) { + !(contextStackCursor.cursor == null) ? invariant_1(false, 'Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue.') : void 0; + + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); +} + +function processChildContext(fiber, parentContext) { + var instance = fiber.stateNode; + var childContextTypes = fiber.type.childContextTypes; + + // TODO (bvaughn) Replace this behavior with an invariant() in the future. + // It has only been added in Fiber to match the (unintentional) behavior in Stack. + if (typeof instance.getChildContext !== 'function') { + { + var componentName = getComponentName(fiber) || 'Unknown'; + + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[componentName] = true; + warning_1(false, '%s.childContextTypes is specified but there is no getChildContext() method ' + 'on the instance. You can either define getChildContext() on %s or remove ' + 'childContextTypes from it.', componentName, componentName); + } + } + return parentContext; + } + + var childContext = void 0; + { + ReactDebugCurrentFiber.setCurrentPhase('getChildContext'); + } + startPhaseTimer(fiber, 'getChildContext'); + childContext = instance.getChildContext(); + stopPhaseTimer(); + { + ReactDebugCurrentFiber.setCurrentPhase(null); + } + for (var contextKey in childContext) { + !(contextKey in childContextTypes) ? invariant_1(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', getComponentName(fiber) || 'Unknown', contextKey) : void 0; + } + { + var name = getComponentName(fiber) || 'Unknown'; + checkPropTypes_1(childContextTypes, childContext, 'child context', name, + // In practice, there is one case in which we won't get a stack. It's when + // somebody calls unstable_renderSubtreeIntoContainer() and we process + // context from the parent component instance. The stack will be missing + // because it's outside of the reconciliation, and so the pointer has not + // been set. This is rare and doesn't matter. We'll also remove that API. + ReactDebugCurrentFiber.getCurrentFiberStackAddendum); + } + + return _assign({}, parentContext, childContext); +} + +function pushContextProvider(workInProgress) { + if (!isContextProvider(workInProgress)) { + return false; + } + + var instance = workInProgress.stateNode; + // We push the context as early as possible to ensure stack integrity. + // If the instance does not exist yet, we will push null at first, + // and replace it on the stack later when invalidating the context. + var memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyObject_1; + + // Remember the parent context so we can merge with it later. + // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. + previousContext = contextStackCursor.current; + push(contextStackCursor, memoizedMergedChildContext, workInProgress); + push(didPerformWorkStackCursor, didPerformWorkStackCursor.current, workInProgress); + + return true; +} + +function invalidateContextProvider(workInProgress, didChange) { + var instance = workInProgress.stateNode; + !instance ? invariant_1(false, 'Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue.') : void 0; + + if (didChange) { + // Merge parent and own context. + // Skip this if we're not updating due to sCU. + // This avoids unnecessarily recomputing memoized values. + var mergedContext = processChildContext(workInProgress, previousContext); + instance.__reactInternalMemoizedMergedChildContext = mergedContext; + + // Replace the old (or empty) context with the new one. + // It is important to unwind the context in the reverse order. + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); + // Now push the new context and mark that it has changed. + push(contextStackCursor, mergedContext, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } else { + pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } +} + +function resetContext() { + previousContext = emptyObject_1; + contextStackCursor.current = emptyObject_1; + didPerformWorkStackCursor.current = false; +} + +function findCurrentUnmaskedContext(fiber) { + // Currently this is only used with renderSubtreeIntoContainer; not sure if it + // makes sense elsewhere + !(isFiberMounted(fiber) && fiber.tag === ClassComponent) ? invariant_1(false, 'Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue.') : void 0; + + var node = fiber; + while (node.tag !== HostRoot) { + if (isContextProvider(node)) { + return node.stateNode.__reactInternalMemoizedMergedChildContext; + } + var parent = node['return']; + !parent ? invariant_1(false, 'Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue.') : void 0; + node = parent; + } + return node.stateNode.context; +} + +var NoWork = 0; // TODO: Use an opaque type once ESLint et al support the syntax + +var Sync = 1; +var Never = 2147483647; // Max int32: Math.pow(2, 31) - 1 + +var UNIT_SIZE = 10; +var MAGIC_NUMBER_OFFSET = 2; + +// 1 unit of expiration time represents 10ms. +function msToExpirationTime(ms) { + // Always add an offset so that we don't clash with the magic number for NoWork. + return (ms / UNIT_SIZE | 0) + MAGIC_NUMBER_OFFSET; +} + +function expirationTimeToMs(expirationTime) { + return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE; +} + +function ceiling(num, precision) { + return ((num / precision | 0) + 1) * precision; +} + +function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) { + return ceiling(currentTime + expirationInMs / UNIT_SIZE, bucketSizeMs / UNIT_SIZE); +} + +var NoContext = 0; +var AsyncUpdates = 1; + +{ + var hasBadMapPolyfill = false; + try { + var nonExtensibleObject = Object.preventExtensions({}); + /* eslint-disable no-new */ + + /* eslint-enable no-new */ + } catch (e) { + // TODO: Consider warning about bad polyfills + hasBadMapPolyfill = true; + } +} + +// A Fiber is work on a Component that needs to be done or was done. There can +// be more than one per component. + + +{ + var debugCounter = 1; +} + +function FiberNode(tag, key, internalContextTag) { + // Instance + this.tag = tag; + this.key = key; + this.type = null; + this.stateNode = null; + + // Fiber + this['return'] = null; + this.child = null; + this.sibling = null; + this.index = 0; + + this.ref = null; + + this.pendingProps = null; + this.memoizedProps = null; + this.updateQueue = null; + this.memoizedState = null; + + this.internalContextTag = internalContextTag; + + // Effects + this.effectTag = NoEffect; + this.nextEffect = null; + + this.firstEffect = null; + this.lastEffect = null; + + this.expirationTime = NoWork; + + this.alternate = null; + + { + this._debugID = debugCounter++; + this._debugSource = null; + this._debugOwner = null; + this._debugIsCurrentlyTiming = false; + if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') { + Object.preventExtensions(this); + } + } +} + +// This is a constructor function, rather than a POJO constructor, still +// please ensure we do the following: +// 1) Nobody should add any instance methods on this. Instance methods can be +// more difficult to predict when they get optimized and they are almost +// never inlined properly in static compilers. +// 2) Nobody should rely on `instanceof Fiber` for type testing. We should +// always know when it is a fiber. +// 3) We might want to experiment with using numeric keys since they are easier +// to optimize in a non-JIT environment. +// 4) We can easily go from a constructor to a createFiber object literal if that +// is faster. +// 5) It should be easy to port this to a C struct and keep a C implementation +// compatible. +var createFiber = function (tag, key, internalContextTag) { + // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors + return new FiberNode(tag, key, internalContextTag); +}; + +function shouldConstruct(Component) { + return !!(Component.prototype && Component.prototype.isReactComponent); +} + +// This is used to create an alternate fiber to do work on. +function createWorkInProgress(current, pendingProps, expirationTime) { + var workInProgress = current.alternate; + if (workInProgress === null) { + // We use a double buffering pooling technique because we know that we'll + // only ever need at most two versions of a tree. We pool the "other" unused + // node that we're free to reuse. This is lazily created to avoid allocating + // extra objects for things that are never updated. It also allow us to + // reclaim the extra memory if needed. + workInProgress = createFiber(current.tag, current.key, current.internalContextTag); + workInProgress.type = current.type; + workInProgress.stateNode = current.stateNode; + + { + // DEV-only fields + workInProgress._debugID = current._debugID; + workInProgress._debugSource = current._debugSource; + workInProgress._debugOwner = current._debugOwner; + } + + workInProgress.alternate = current; + current.alternate = workInProgress; + } else { + // We already have an alternate. + // Reset the effect tag. + workInProgress.effectTag = NoEffect; + + // The effect list is no longer valid. + workInProgress.nextEffect = null; + workInProgress.firstEffect = null; + workInProgress.lastEffect = null; + } + + workInProgress.expirationTime = expirationTime; + workInProgress.pendingProps = pendingProps; + + workInProgress.child = current.child; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; + + // These will be overridden during the parent's reconciliation + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; + + return workInProgress; +} + +function createHostRootFiber() { + var fiber = createFiber(HostRoot, null, NoContext); + return fiber; +} + +function createFiberFromElement(element, internalContextTag, expirationTime) { + var owner = null; + { + owner = element._owner; + } + + var fiber = void 0; + var type = element.type, + key = element.key; + + if (typeof type === 'function') { + fiber = shouldConstruct(type) ? createFiber(ClassComponent, key, internalContextTag) : createFiber(IndeterminateComponent, key, internalContextTag); + fiber.type = type; + fiber.pendingProps = element.props; + } else if (typeof type === 'string') { + fiber = createFiber(HostComponent, key, internalContextTag); + fiber.type = type; + fiber.pendingProps = element.props; + } else if (typeof type === 'object' && type !== null && typeof type.tag === 'number') { + // Currently assumed to be a continuation and therefore is a fiber already. + // TODO: The yield system is currently broken for updates in some cases. + // The reified yield stores a fiber, but we don't know which fiber that is; + // the current or a workInProgress? When the continuation gets rendered here + // we don't know if we can reuse that fiber or if we need to clone it. + // There is probably a clever way to restructure this. + fiber = type; + fiber.pendingProps = element.props; + } else { + var info = ''; + { + if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) { + info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and named imports."; + } + var ownerName = owner ? getComponentName(owner) : null; + if (ownerName) { + info += '\n\nCheck the render method of `' + ownerName + '`.'; + } + } + invariant_1(false, 'Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s', type == null ? type : typeof type, info); + } + + { + fiber._debugSource = element._source; + fiber._debugOwner = element._owner; + } + + fiber.expirationTime = expirationTime; + + return fiber; +} + +function createFiberFromFragment(elements, internalContextTag, expirationTime, key) { + var fiber = createFiber(Fragment, key, internalContextTag); + fiber.pendingProps = elements; + fiber.expirationTime = expirationTime; + return fiber; +} + +function createFiberFromText(content, internalContextTag, expirationTime) { + var fiber = createFiber(HostText, null, internalContextTag); + fiber.pendingProps = content; + fiber.expirationTime = expirationTime; + return fiber; +} + +function createFiberFromHostInstanceForDeletion() { + var fiber = createFiber(HostComponent, null, NoContext); + fiber.type = 'DELETED'; + return fiber; +} + +function createFiberFromCall(call, internalContextTag, expirationTime) { + var fiber = createFiber(CallComponent, call.key, internalContextTag); + fiber.type = call.handler; + fiber.pendingProps = call; + fiber.expirationTime = expirationTime; + return fiber; +} + +function createFiberFromReturn(returnNode, internalContextTag, expirationTime) { + var fiber = createFiber(ReturnComponent, null, internalContextTag); + fiber.expirationTime = expirationTime; + return fiber; +} + +function createFiberFromPortal(portal, internalContextTag, expirationTime) { + var fiber = createFiber(HostPortal, portal.key, internalContextTag); + fiber.pendingProps = portal.children || []; + fiber.expirationTime = expirationTime; + fiber.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, // Used by persistent updates + implementation: portal.implementation + }; + return fiber; +} + +function createFiberRoot(containerInfo, hydrate) { + // Cyclic construction. This cheats the type system right now because + // stateNode is any. + var uninitializedFiber = createHostRootFiber(); + var root = { + current: uninitializedFiber, + containerInfo: containerInfo, + pendingChildren: null, + remainingExpirationTime: NoWork, + isReadyForCommit: false, + finishedWork: null, + context: null, + pendingContext: null, + hydrate: hydrate, + nextScheduledRoot: null + }; + uninitializedFiber.stateNode = root; + return root; +} + +var onCommitFiberRoot = null; +var onCommitFiberUnmount = null; +var hasLoggedError = false; + +function catchErrors(fn) { + return function (arg) { + try { + return fn(arg); + } catch (err) { + if (true && !hasLoggedError) { + hasLoggedError = true; + warning_1(false, 'React DevTools encountered an error: %s', err); + } + } + }; +} + +function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { + // No DevTools + return false; + } + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (hook.isDisabled) { + // This isn't a real property on the hook, but it can be set to opt out + // of DevTools integration and associated warnings and logs. + // https://github.com/facebook/react/issues/3877 + return true; + } + if (!hook.supportsFiber) { + { + warning_1(false, 'The installed version of React DevTools is too old and will not work ' + 'with the current version of React. Please update React DevTools. ' + 'https://fb.me/react-devtools'); + } + // DevTools exists, even though it doesn't support Fiber. + return true; + } + try { + var rendererID = hook.inject(internals); + // We have successfully injected, so now it is safe to set up hooks. + onCommitFiberRoot = catchErrors(function (root) { + return hook.onCommitFiberRoot(rendererID, root); + }); + onCommitFiberUnmount = catchErrors(function (fiber) { + return hook.onCommitFiberUnmount(rendererID, fiber); + }); + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + warning_1(false, 'React DevTools encountered an error: %s.', err); + } + } + // DevTools exists + return true; +} + +function onCommitRoot(root) { + if (typeof onCommitFiberRoot === 'function') { + onCommitFiberRoot(root); + } +} + +function onCommitUnmount(fiber) { + if (typeof onCommitFiberUnmount === 'function') { + onCommitFiberUnmount(fiber); + } +} + +{ + var didWarnUpdateInsideUpdate = false; +} + +// Callbacks are not validated until invocation + + +// Singly linked-list of updates. When an update is scheduled, it is added to +// the queue of the current fiber and the work-in-progress fiber. The two queues +// are separate but they share a persistent structure. +// +// During reconciliation, updates are removed from the work-in-progress fiber, +// but they remain on the current fiber. That ensures that if a work-in-progress +// is aborted, the aborted updates are recovered by cloning from current. +// +// The work-in-progress queue is always a subset of the current queue. +// +// When the tree is committed, the work-in-progress becomes the current. + + +function createUpdateQueue(baseState) { + var queue = { + baseState: baseState, + expirationTime: NoWork, + first: null, + last: null, + callbackList: null, + hasForceUpdate: false, + isInitialized: false + }; + { + queue.isProcessing = false; + } + return queue; +} + +function insertUpdateIntoQueue(queue, update) { + // Append the update to the end of the list. + if (queue.last === null) { + // Queue is empty + queue.first = queue.last = update; + } else { + queue.last.next = update; + queue.last = update; + } + if (queue.expirationTime === NoWork || queue.expirationTime > update.expirationTime) { + queue.expirationTime = update.expirationTime; + } +} + +function insertUpdateIntoFiber(fiber, update) { + // We'll have at least one and at most two distinct update queues. + var alternateFiber = fiber.alternate; + var queue1 = fiber.updateQueue; + if (queue1 === null) { + // TODO: We don't know what the base state will be until we begin work. + // It depends on which fiber is the next current. Initialize with an empty + // base state, then set to the memoizedState when rendering. Not super + // happy with this approach. + queue1 = fiber.updateQueue = createUpdateQueue(null); + } + + var queue2 = void 0; + if (alternateFiber !== null) { + queue2 = alternateFiber.updateQueue; + if (queue2 === null) { + queue2 = alternateFiber.updateQueue = createUpdateQueue(null); + } + } else { + queue2 = null; + } + queue2 = queue2 !== queue1 ? queue2 : null; + + // Warn if an update is scheduled from inside an updater function. + { + if ((queue1.isProcessing || queue2 !== null && queue2.isProcessing) && !didWarnUpdateInsideUpdate) { + warning_1(false, 'An update (setState, replaceState, or forceUpdate) was scheduled ' + 'from inside an update function. Update functions should be pure, ' + 'with zero side-effects. Consider using componentDidUpdate or a ' + 'callback.'); + didWarnUpdateInsideUpdate = true; + } + } + + // If there's only one queue, add the update to that queue and exit. + if (queue2 === null) { + insertUpdateIntoQueue(queue1, update); + return; + } + + // If either queue is empty, we need to add to both queues. + if (queue1.last === null || queue2.last === null) { + insertUpdateIntoQueue(queue1, update); + insertUpdateIntoQueue(queue2, update); + return; + } + + // If both lists are not empty, the last update is the same for both lists + // because of structural sharing. So, we should only append to one of + // the lists. + insertUpdateIntoQueue(queue1, update); + // But we still need to update the `last` pointer of queue2. + queue2.last = update; +} + +function getUpdateExpirationTime(fiber) { + if (fiber.tag !== ClassComponent && fiber.tag !== HostRoot) { + return NoWork; + } + var updateQueue = fiber.updateQueue; + if (updateQueue === null) { + return NoWork; + } + return updateQueue.expirationTime; +} + +function getStateFromUpdate(update, instance, prevState, props) { + var partialState = update.partialState; + if (typeof partialState === 'function') { + var updateFn = partialState; + + // Invoke setState callback an extra time to help detect side-effects. + if (debugRenderPhaseSideEffects) { + updateFn.call(instance, prevState, props); + } + + return updateFn.call(instance, prevState, props); + } else { + return partialState; + } +} + +function processUpdateQueue(current, workInProgress, queue, instance, props, renderExpirationTime) { + if (current !== null && current.updateQueue === queue) { + // We need to create a work-in-progress queue, by cloning the current queue. + var currentQueue = queue; + queue = workInProgress.updateQueue = { + baseState: currentQueue.baseState, + expirationTime: currentQueue.expirationTime, + first: currentQueue.first, + last: currentQueue.last, + isInitialized: currentQueue.isInitialized, + // These fields are no longer valid because they were already committed. + // Reset them. + callbackList: null, + hasForceUpdate: false + }; + } + + { + // Set this flag so we can warn if setState is called inside the update + // function of another setState. + queue.isProcessing = true; + } + + // Reset the remaining expiration time. If we skip over any updates, we'll + // increase this accordingly. + queue.expirationTime = NoWork; + + // TODO: We don't know what the base state will be until we begin work. + // It depends on which fiber is the next current. Initialize with an empty + // base state, then set to the memoizedState when rendering. Not super + // happy with this approach. + var state = void 0; + if (queue.isInitialized) { + state = queue.baseState; + } else { + state = queue.baseState = workInProgress.memoizedState; + queue.isInitialized = true; + } + var dontMutatePrevState = true; + var update = queue.first; + var didSkip = false; + while (update !== null) { + var updateExpirationTime = update.expirationTime; + if (updateExpirationTime > renderExpirationTime) { + // This update does not have sufficient priority. Skip it. + var remainingExpirationTime = queue.expirationTime; + if (remainingExpirationTime === NoWork || remainingExpirationTime > updateExpirationTime) { + // Update the remaining expiration time. + queue.expirationTime = updateExpirationTime; + } + if (!didSkip) { + didSkip = true; + queue.baseState = state; + } + // Continue to the next update. + update = update.next; + continue; + } + + // This update does have sufficient priority. + + // If no previous updates were skipped, drop this update from the queue by + // advancing the head of the list. + if (!didSkip) { + queue.first = update.next; + if (queue.first === null) { + queue.last = null; + } + } + + // Process the update + var _partialState = void 0; + if (update.isReplace) { + state = getStateFromUpdate(update, instance, state, props); + dontMutatePrevState = true; + } else { + _partialState = getStateFromUpdate(update, instance, state, props); + if (_partialState) { + if (dontMutatePrevState) { + // $FlowFixMe: Idk how to type this properly. + state = _assign({}, state, _partialState); + } else { + state = _assign(state, _partialState); + } + dontMutatePrevState = false; + } + } + if (update.isForced) { + queue.hasForceUpdate = true; + } + if (update.callback !== null) { + // Append to list of callbacks. + var _callbackList = queue.callbackList; + if (_callbackList === null) { + _callbackList = queue.callbackList = []; + } + _callbackList.push(update); + } + update = update.next; + } + + if (queue.callbackList !== null) { + workInProgress.effectTag |= Callback; + } else if (queue.first === null && !queue.hasForceUpdate) { + // The queue is empty. We can reset it. + workInProgress.updateQueue = null; + } + + if (!didSkip) { + didSkip = true; + queue.baseState = state; + } + + { + // No longer processing. + queue.isProcessing = false; + } + + return state; +} + +function commitCallbacks(queue, context) { + var callbackList = queue.callbackList; + if (callbackList === null) { + return; + } + // Set the list to null to make sure they don't get called more than once. + queue.callbackList = null; + for (var i = 0; i < callbackList.length; i++) { + var update = callbackList[i]; + var _callback = update.callback; + // This update might be processed again. Clear the callback so it's only + // called once. + update.callback = null; + !(typeof _callback === 'function') ? invariant_1(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback) : void 0; + _callback.call(context); + } +} + +var fakeInternalInstance = {}; +var isArray = Array.isArray; + +{ + var didWarnAboutStateAssignmentForComponent = {}; + + var warnOnInvalidCallback = function (callback, callerName) { + warning_1(callback === null || typeof callback === 'function', '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback); + }; + + // This is so gross but it's at least non-critical and can be removed if + // it causes problems. This is meant to give a nicer error message for + // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, + // ...)) which otherwise throws a "_processChildContext is not a function" + // exception. + Object.defineProperty(fakeInternalInstance, '_processChildContext', { + enumerable: false, + value: function () { + invariant_1(false, '_processChildContext is not available in React 16+. This likely means you have multiple copies of React and are attempting to nest a React 15 tree inside a React 16 tree using unstable_renderSubtreeIntoContainer, which isn\'t supported. Try to make sure you have only one copy of React (and ideally, switch to ReactDOM.createPortal).'); + } + }); + Object.freeze(fakeInternalInstance); +} + +var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState) { + // Class component state updater + var updater = { + isMounted: isMounted, + enqueueSetState: function (instance, partialState, callback) { + var fiber = get(instance); + callback = callback === undefined ? null : callback; + { + warnOnInvalidCallback(callback, 'setState'); + } + var expirationTime = computeExpirationForFiber(fiber); + var update = { + expirationTime: expirationTime, + partialState: partialState, + callback: callback, + isReplace: false, + isForced: false, + nextCallback: null, + next: null + }; + insertUpdateIntoFiber(fiber, update); + scheduleWork(fiber, expirationTime); + }, + enqueueReplaceState: function (instance, state, callback) { + var fiber = get(instance); + callback = callback === undefined ? null : callback; + { + warnOnInvalidCallback(callback, 'replaceState'); + } + var expirationTime = computeExpirationForFiber(fiber); + var update = { + expirationTime: expirationTime, + partialState: state, + callback: callback, + isReplace: true, + isForced: false, + nextCallback: null, + next: null + }; + insertUpdateIntoFiber(fiber, update); + scheduleWork(fiber, expirationTime); + }, + enqueueForceUpdate: function (instance, callback) { + var fiber = get(instance); + callback = callback === undefined ? null : callback; + { + warnOnInvalidCallback(callback, 'forceUpdate'); + } + var expirationTime = computeExpirationForFiber(fiber); + var update = { + expirationTime: expirationTime, + partialState: null, + callback: callback, + isReplace: false, + isForced: true, + nextCallback: null, + next: null + }; + insertUpdateIntoFiber(fiber, update); + scheduleWork(fiber, expirationTime); + } + }; + + function checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext) { + if (oldProps === null || workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate) { + // If the workInProgress already has an Update effect, return true + return true; + } + + var instance = workInProgress.stateNode; + var type = workInProgress.type; + if (typeof instance.shouldComponentUpdate === 'function') { + startPhaseTimer(workInProgress, 'shouldComponentUpdate'); + var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, newContext); + stopPhaseTimer(); + + // Simulate an async bailout/interruption by invoking lifecycle twice. + if (debugRenderPhaseSideEffects) { + instance.shouldComponentUpdate(newProps, newState, newContext); + } + + { + warning_1(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentName(workInProgress) || 'Unknown'); + } + + return shouldUpdate; + } + + if (type.prototype && type.prototype.isPureReactComponent) { + return !shallowEqual_1(oldProps, newProps) || !shallowEqual_1(oldState, newState); + } + + return true; + } + + function checkClassInstance(workInProgress) { + var instance = workInProgress.stateNode; + var type = workInProgress.type; + { + var name = getComponentName(workInProgress); + var renderPresent = instance.render; + + if (!renderPresent) { + if (type.prototype && typeof type.prototype.render === 'function') { + warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name); + } else { + warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name); + } + } + + var noGetInitialStateOnES6 = !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state; + warning_1(noGetInitialStateOnES6, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', name); + var noGetDefaultPropsOnES6 = !instance.getDefaultProps || instance.getDefaultProps.isReactClassApproved; + warning_1(noGetDefaultPropsOnES6, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', name); + var noInstancePropTypes = !instance.propTypes; + warning_1(noInstancePropTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name); + var noInstanceContextTypes = !instance.contextTypes; + warning_1(noInstanceContextTypes, 'contextTypes was defined as an instance property on %s. Use a static ' + 'property to define contextTypes instead.', name); + var noComponentShouldUpdate = typeof instance.componentShouldUpdate !== 'function'; + warning_1(noComponentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', name); + if (type.prototype && type.prototype.isPureReactComponent && typeof instance.shouldComponentUpdate !== 'undefined') { + warning_1(false, '%s has a method called shouldComponentUpdate(). ' + 'shouldComponentUpdate should not be used when extending React.PureComponent. ' + 'Please extend React.Component if shouldComponentUpdate is used.', getComponentName(workInProgress) || 'A pure component'); + } + var noComponentDidUnmount = typeof instance.componentDidUnmount !== 'function'; + warning_1(noComponentDidUnmount, '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name); + var noComponentDidReceiveProps = typeof instance.componentDidReceiveProps !== 'function'; + warning_1(noComponentDidReceiveProps, '%s has a method called ' + 'componentDidReceiveProps(). But there is no such lifecycle method. ' + 'If you meant to update the state in response to changing props, ' + 'use componentWillReceiveProps(). If you meant to fetch data or ' + 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().', name); + var noComponentWillRecieveProps = typeof instance.componentWillRecieveProps !== 'function'; + warning_1(noComponentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name); + var hasMutatedProps = instance.props !== workInProgress.pendingProps; + warning_1(instance.props === undefined || !hasMutatedProps, '%s(...): When calling super() in `%s`, make sure to pass ' + "up the same props that your component's constructor was passed.", name, name); + var noInstanceDefaultProps = !instance.defaultProps; + warning_1(noInstanceDefaultProps, 'Setting defaultProps as an instance property on %s is not supported and will be ignored.' + ' Instead, define defaultProps as a static property on %s.', name, name); + } + + var state = instance.state; + if (state && (typeof state !== 'object' || isArray(state))) { + warning_1(false, '%s.state: must be set to an object or null', getComponentName(workInProgress)); + } + if (typeof instance.getChildContext === 'function') { + warning_1(typeof workInProgress.type.childContextTypes === 'object', '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', getComponentName(workInProgress)); + } + } + + function resetInputPointers(workInProgress, instance) { + instance.props = workInProgress.memoizedProps; + instance.state = workInProgress.memoizedState; + } + + function adoptClassInstance(workInProgress, instance) { + instance.updater = updater; + workInProgress.stateNode = instance; + // The instance needs access to the fiber so that it can schedule updates + set(instance, workInProgress); + { + instance._reactInternalInstance = fakeInternalInstance; + } + } + + function constructClassInstance(workInProgress, props) { + var ctor = workInProgress.type; + var unmaskedContext = getUnmaskedContext(workInProgress); + var needsContext = isContextConsumer(workInProgress); + var context = needsContext ? getMaskedContext(workInProgress, unmaskedContext) : emptyObject_1; + var instance = new ctor(props, context); + adoptClassInstance(workInProgress, instance); + + // Cache unmasked context so we can avoid recreating masked context unless necessary. + // ReactFiberContext usually updates this cache but can't for newly-created instances. + if (needsContext) { + cacheContext(workInProgress, unmaskedContext, context); + } + + return instance; + } + + function callComponentWillMount(workInProgress, instance) { + startPhaseTimer(workInProgress, 'componentWillMount'); + var oldState = instance.state; + instance.componentWillMount(); + stopPhaseTimer(); + + // Simulate an async bailout/interruption by invoking lifecycle twice. + if (debugRenderPhaseSideEffects) { + instance.componentWillMount(); + } + + if (oldState !== instance.state) { + { + warning_1(false, '%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentName(workInProgress)); + } + updater.enqueueReplaceState(instance, instance.state, null); + } + } + + function callComponentWillReceiveProps(workInProgress, instance, newProps, newContext) { + startPhaseTimer(workInProgress, 'componentWillReceiveProps'); + var oldState = instance.state; + instance.componentWillReceiveProps(newProps, newContext); + stopPhaseTimer(); + + // Simulate an async bailout/interruption by invoking lifecycle twice. + if (debugRenderPhaseSideEffects) { + instance.componentWillReceiveProps(newProps, newContext); + } + + if (instance.state !== oldState) { + { + var componentName = getComponentName(workInProgress) || 'Component'; + if (!didWarnAboutStateAssignmentForComponent[componentName]) { + warning_1(false, '%s.componentWillReceiveProps(): Assigning directly to ' + "this.state is deprecated (except inside a component's " + 'constructor). Use setState instead.', componentName); + didWarnAboutStateAssignmentForComponent[componentName] = true; + } + } + updater.enqueueReplaceState(instance, instance.state, null); + } + } + + // Invokes the mount life-cycles on a previously never rendered instance. + function mountClassInstance(workInProgress, renderExpirationTime) { + var current = workInProgress.alternate; + + { + checkClassInstance(workInProgress); + } + + var instance = workInProgress.stateNode; + var state = instance.state || null; + + var props = workInProgress.pendingProps; + !props ? invariant_1(false, 'There must be pending props for an initial mount. This error is likely caused by a bug in React. Please file an issue.') : void 0; + + var unmaskedContext = getUnmaskedContext(workInProgress); + + instance.props = props; + instance.state = workInProgress.memoizedState = state; + instance.refs = emptyObject_1; + instance.context = getMaskedContext(workInProgress, unmaskedContext); + + if (enableAsyncSubtreeAPI && workInProgress.type != null && workInProgress.type.prototype != null && workInProgress.type.prototype.unstable_isAsyncReactComponent === true) { + workInProgress.internalContextTag |= AsyncUpdates; + } + + if (typeof instance.componentWillMount === 'function') { + callComponentWillMount(workInProgress, instance); + // If we had additional state updates during this life-cycle, let's + // process them now. + var updateQueue = workInProgress.updateQueue; + if (updateQueue !== null) { + instance.state = processUpdateQueue(current, workInProgress, updateQueue, instance, props, renderExpirationTime); + } + } + if (typeof instance.componentDidMount === 'function') { + workInProgress.effectTag |= Update; + } + } + + // Called on a preexisting class instance. Returns false if a resumed render + // could be reused. + // function resumeMountClassInstance( + // workInProgress: Fiber, + // priorityLevel: PriorityLevel, + // ): boolean { + // const instance = workInProgress.stateNode; + // resetInputPointers(workInProgress, instance); + + // let newState = workInProgress.memoizedState; + // let newProps = workInProgress.pendingProps; + // if (!newProps) { + // // If there isn't any new props, then we'll reuse the memoized props. + // // This could be from already completed work. + // newProps = workInProgress.memoizedProps; + // invariant( + // newProps != null, + // 'There should always be pending or memoized props. This error is ' + + // 'likely caused by a bug in React. Please file an issue.', + // ); + // } + // const newUnmaskedContext = getUnmaskedContext(workInProgress); + // const newContext = getMaskedContext(workInProgress, newUnmaskedContext); + + // const oldContext = instance.context; + // const oldProps = workInProgress.memoizedProps; + + // if ( + // typeof instance.componentWillReceiveProps === 'function' && + // (oldProps !== newProps || oldContext !== newContext) + // ) { + // callComponentWillReceiveProps( + // workInProgress, + // instance, + // newProps, + // newContext, + // ); + // } + + // // Process the update queue before calling shouldComponentUpdate + // const updateQueue = workInProgress.updateQueue; + // if (updateQueue !== null) { + // newState = processUpdateQueue( + // workInProgress, + // updateQueue, + // instance, + // newState, + // newProps, + // priorityLevel, + // ); + // } + + // // TODO: Should we deal with a setState that happened after the last + // // componentWillMount and before this componentWillMount? Probably + // // unsupported anyway. + + // if ( + // !checkShouldComponentUpdate( + // workInProgress, + // workInProgress.memoizedProps, + // newProps, + // workInProgress.memoizedState, + // newState, + // newContext, + // ) + // ) { + // // Update the existing instance's state, props, and context pointers even + // // though we're bailing out. + // instance.props = newProps; + // instance.state = newState; + // instance.context = newContext; + // return false; + // } + + // // Update the input pointers now so that they are correct when we call + // // componentWillMount + // instance.props = newProps; + // instance.state = newState; + // instance.context = newContext; + + // if (typeof instance.componentWillMount === 'function') { + // callComponentWillMount(workInProgress, instance); + // // componentWillMount may have called setState. Process the update queue. + // const newUpdateQueue = workInProgress.updateQueue; + // if (newUpdateQueue !== null) { + // newState = processUpdateQueue( + // workInProgress, + // newUpdateQueue, + // instance, + // newState, + // newProps, + // priorityLevel, + // ); + // } + // } + + // if (typeof instance.componentDidMount === 'function') { + // workInProgress.effectTag |= Update; + // } + + // instance.state = newState; + + // return true; + // } + + // Invokes the update life-cycles and returns false if it shouldn't rerender. + function updateClassInstance(current, workInProgress, renderExpirationTime) { + var instance = workInProgress.stateNode; + resetInputPointers(workInProgress, instance); + + var oldProps = workInProgress.memoizedProps; + var newProps = workInProgress.pendingProps; + if (!newProps) { + // If there aren't any new props, then we'll reuse the memoized props. + // This could be from already completed work. + newProps = oldProps; + !(newProps != null) ? invariant_1(false, 'There should always be pending or memoized props. This error is likely caused by a bug in React. Please file an issue.') : void 0; + } + var oldContext = instance.context; + var newUnmaskedContext = getUnmaskedContext(workInProgress); + var newContext = getMaskedContext(workInProgress, newUnmaskedContext); + + // Note: During these life-cycles, instance.props/instance.state are what + // ever the previously attempted to render - not the "current". However, + // during componentDidUpdate we pass the "current" props. + + if (typeof instance.componentWillReceiveProps === 'function' && (oldProps !== newProps || oldContext !== newContext)) { + callComponentWillReceiveProps(workInProgress, instance, newProps, newContext); + } + + // Compute the next state using the memoized state and the update queue. + var oldState = workInProgress.memoizedState; + // TODO: Previous state can be null. + var newState = void 0; + if (workInProgress.updateQueue !== null) { + newState = processUpdateQueue(current, workInProgress, workInProgress.updateQueue, instance, newProps, renderExpirationTime); + } else { + newState = oldState; + } + + if (oldProps === newProps && oldState === newState && !hasContextChanged() && !(workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate)) { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === 'function') { + if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) { + workInProgress.effectTag |= Update; + } + } + return false; + } + + var shouldUpdate = checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext); + + if (shouldUpdate) { + if (typeof instance.componentWillUpdate === 'function') { + startPhaseTimer(workInProgress, 'componentWillUpdate'); + instance.componentWillUpdate(newProps, newState, newContext); + stopPhaseTimer(); + + // Simulate an async bailout/interruption by invoking lifecycle twice. + if (debugRenderPhaseSideEffects) { + instance.componentWillUpdate(newProps, newState, newContext); + } + } + if (typeof instance.componentDidUpdate === 'function') { + workInProgress.effectTag |= Update; + } + } else { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === 'function') { + if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) { + workInProgress.effectTag |= Update; + } + } + + // If shouldComponentUpdate returned false, we should still update the + // memoized props/state to indicate that this work can be reused. + memoizeProps(workInProgress, newProps); + memoizeState(workInProgress, newState); + } + + // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. + instance.props = newProps; + instance.state = newState; + instance.context = newContext; + + return shouldUpdate; + } + + return { + adoptClassInstance: adoptClassInstance, + constructClassInstance: constructClassInstance, + mountClassInstance: mountClassInstance, + // resumeMountClassInstance, + updateClassInstance: updateClassInstance + }; +}; + +// The Symbol used to tag the ReactElement-like types. If there is no native Symbol +// nor polyfill, then a plain number is used for performance. +var hasSymbol = typeof Symbol === 'function' && Symbol['for']; + +var REACT_ELEMENT_TYPE = hasSymbol ? Symbol['for']('react.element') : 0xeac7; +var REACT_CALL_TYPE = hasSymbol ? Symbol['for']('react.call') : 0xeac8; +var REACT_RETURN_TYPE = hasSymbol ? Symbol['for']('react.return') : 0xeac9; +var REACT_PORTAL_TYPE = hasSymbol ? Symbol['for']('react.portal') : 0xeaca; +var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol['for']('react.fragment') : 0xeacb; + +var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; +var FAUX_ITERATOR_SYMBOL = '@@iterator'; + +function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable === 'undefined') { + return null; + } + var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; + if (typeof maybeIterator === 'function') { + return maybeIterator; + } + return null; +} + +var getCurrentFiberStackAddendum$1 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum; + + +{ + var didWarnAboutMaps = false; + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ + var ownerHasKeyUseWarning = {}; + var ownerHasFunctionTypeWarning = {}; + + var warnForMissingKey = function (child) { + if (child === null || typeof child !== 'object') { + return; + } + if (!child._store || child._store.validated || child.key != null) { + return; + } + !(typeof child._store === 'object') ? invariant_1(false, 'React Component in warnForMissingKey should have a _store. This error is likely caused by a bug in React. Please file an issue.') : void 0; + child._store.validated = true; + + var currentComponentErrorInfo = 'Each child in an array or iterator should have a unique ' + '"key" prop. See https://fb.me/react-warning-keys for ' + 'more information.' + (getCurrentFiberStackAddendum$1() || ''); + if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + return; + } + ownerHasKeyUseWarning[currentComponentErrorInfo] = true; + + warning_1(false, 'Each child in an array or iterator should have a unique ' + '"key" prop. See https://fb.me/react-warning-keys for ' + 'more information.%s', getCurrentFiberStackAddendum$1()); + }; +} + +var isArray$1 = Array.isArray; + +function coerceRef(current, element) { + var mixedRef = element.ref; + if (mixedRef !== null && typeof mixedRef !== 'function') { + if (element._owner) { + var owner = element._owner; + var inst = void 0; + if (owner) { + var ownerFiber = owner; + !(ownerFiber.tag === ClassComponent) ? invariant_1(false, 'Stateless function components cannot have refs.') : void 0; + inst = ownerFiber.stateNode; + } + !inst ? invariant_1(false, 'Missing owner for string ref %s. This error is likely caused by a bug in React. Please file an issue.', mixedRef) : void 0; + var stringRef = '' + mixedRef; + // Check if previous string ref matches new string ref + if (current !== null && current.ref !== null && current.ref._stringRef === stringRef) { + return current.ref; + } + var ref = function (value) { + var refs = inst.refs === emptyObject_1 ? inst.refs = {} : inst.refs; + if (value === null) { + delete refs[stringRef]; + } else { + refs[stringRef] = value; + } + }; + ref._stringRef = stringRef; + return ref; + } else { + !(typeof mixedRef === 'string') ? invariant_1(false, 'Expected ref to be a function or a string.') : void 0; + !element._owner ? invariant_1(false, 'Element ref was specified as a string (%s) but no owner was set. You may have multiple copies of React loaded. (details: https://fb.me/react-refs-must-have-owner).', mixedRef) : void 0; + } + } + return mixedRef; +} + +function throwOnInvalidObjectType(returnFiber, newChild) { + if (returnFiber.type !== 'textarea') { + var addendum = ''; + { + addendum = ' If you meant to render a collection of children, use an array ' + 'instead.' + (getCurrentFiberStackAddendum$1() || ''); + } + invariant_1(false, 'Objects are not valid as a React child (found: %s).%s', Object.prototype.toString.call(newChild) === '[object Object]' ? 'object with keys {' + Object.keys(newChild).join(', ') + '}' : newChild, addendum); + } +} + +function warnOnFunctionType() { + var currentComponentErrorInfo = 'Functions are not valid as a React child. This may happen if ' + 'you return a Component instead of from render. ' + 'Or maybe you meant to call this function rather than return it.' + (getCurrentFiberStackAddendum$1() || ''); + + if (ownerHasFunctionTypeWarning[currentComponentErrorInfo]) { + return; + } + ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true; + + warning_1(false, 'Functions are not valid as a React child. This may happen if ' + 'you return a Component instead of from render. ' + 'Or maybe you meant to call this function rather than return it.%s', getCurrentFiberStackAddendum$1() || ''); +} + +// This wrapper function exists because I expect to clone the code in each path +// to be able to optimize each path individually by branching early. This needs +// a compiler or we can do it manually. Helpers that don't need this branching +// live outside of this function. +function ChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; + } + // Deletions are added in reversed order so we add it to the front. + // At this point, the return fiber's effect list is empty except for + // deletions, so we can just append the deletion to the list. The remaining + // effects aren't added until the complete phase. Once we implement + // resuming, this may not be true. + var last = returnFiber.lastEffect; + if (last !== null) { + last.nextEffect = childToDelete; + returnFiber.lastEffect = childToDelete; + } else { + returnFiber.firstEffect = returnFiber.lastEffect = childToDelete; + } + childToDelete.nextEffect = null; + childToDelete.effectTag = Deletion; + } + + function deleteRemainingChildren(returnFiber, currentFirstChild) { + if (!shouldTrackSideEffects) { + // Noop. + return null; + } + + // TODO: For the shouldClone case, this could be micro-optimized a bit by + // assuming that after the first child we've already added everything. + var childToDelete = currentFirstChild; + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; + } + return null; + } + + function mapRemainingChildren(returnFiber, currentFirstChild) { + // Add the remaining children to a temporary map so that we can find them by + // keys quickly. Implicit (null) keys get added to this set with their index + var existingChildren = new Map(); + + var existingChild = currentFirstChild; + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); + } else { + existingChildren.set(existingChild.index, existingChild); + } + existingChild = existingChild.sibling; + } + return existingChildren; + } + + function useFiber(fiber, pendingProps, expirationTime) { + // We currently set sibling to null and index to 0 here because it is easy + // to forget to do before returning it. E.g. for the single child case. + var clone = createWorkInProgress(fiber, pendingProps, expirationTime); + clone.index = 0; + clone.sibling = null; + return clone; + } + + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; + if (!shouldTrackSideEffects) { + // Noop. + return lastPlacedIndex; + } + var current = newFiber.alternate; + if (current !== null) { + var oldIndex = current.index; + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.effectTag = Placement; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; + } + } else { + // This is an insertion. + newFiber.effectTag = Placement; + return lastPlacedIndex; + } + } + + function placeSingleChild(newFiber) { + // This is simpler for the single child case. We only need to do a + // placement for inserting new children. + if (shouldTrackSideEffects && newFiber.alternate === null) { + newFiber.effectTag = Placement; + } + return newFiber; + } + + function updateTextNode(returnFiber, current, textContent, expirationTime) { + if (current === null || current.tag !== HostText) { + // Insert + var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime); + created['return'] = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, textContent, expirationTime); + existing['return'] = returnFiber; + return existing; + } + } + + function updateElement(returnFiber, current, element, expirationTime) { + if (current !== null && current.type === element.type) { + // Move based on index + var existing = useFiber(current, element.props, expirationTime); + existing.ref = coerceRef(current, element); + existing['return'] = returnFiber; + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } + return existing; + } else { + // Insert + var created = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime); + created.ref = coerceRef(current, element); + created['return'] = returnFiber; + return created; + } + } + + function updateCall(returnFiber, current, call, expirationTime) { + // TODO: Should this also compare handler to determine whether to reuse? + if (current === null || current.tag !== CallComponent) { + // Insert + var created = createFiberFromCall(call, returnFiber.internalContextTag, expirationTime); + created['return'] = returnFiber; + return created; + } else { + // Move based on index + var existing = useFiber(current, call, expirationTime); + existing['return'] = returnFiber; + return existing; + } + } + + function updateReturn(returnFiber, current, returnNode, expirationTime) { + if (current === null || current.tag !== ReturnComponent) { + // Insert + var created = createFiberFromReturn(returnNode, returnFiber.internalContextTag, expirationTime); + created.type = returnNode.value; + created['return'] = returnFiber; + return created; + } else { + // Move based on index + var existing = useFiber(current, null, expirationTime); + existing.type = returnNode.value; + existing['return'] = returnFiber; + return existing; + } + } + + function updatePortal(returnFiber, current, portal, expirationTime) { + if (current === null || current.tag !== HostPortal || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) { + // Insert + var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime); + created['return'] = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, portal.children || [], expirationTime); + existing['return'] = returnFiber; + return existing; + } + } + + function updateFragment(returnFiber, current, fragment, expirationTime, key) { + if (current === null || current.tag !== Fragment) { + // Insert + var created = createFiberFromFragment(fragment, returnFiber.internalContextTag, expirationTime, key); + created['return'] = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, fragment, expirationTime); + existing['return'] = returnFiber; + return existing; + } + } + + function createChild(returnFiber, newChild, expirationTime) { + if (typeof newChild === 'string' || typeof newChild === 'number') { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + var created = createFiberFromText('' + newChild, returnFiber.internalContextTag, expirationTime); + created['return'] = returnFiber; + return created; + } + + if (typeof newChild === 'object' && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + { + if (newChild.type === REACT_FRAGMENT_TYPE) { + var _created = createFiberFromFragment(newChild.props.children, returnFiber.internalContextTag, expirationTime, newChild.key); + _created['return'] = returnFiber; + return _created; + } else { + var _created2 = createFiberFromElement(newChild, returnFiber.internalContextTag, expirationTime); + _created2.ref = coerceRef(null, newChild); + _created2['return'] = returnFiber; + return _created2; + } + } + + case REACT_CALL_TYPE: + { + var _created3 = createFiberFromCall(newChild, returnFiber.internalContextTag, expirationTime); + _created3['return'] = returnFiber; + return _created3; + } + + case REACT_RETURN_TYPE: + { + var _created4 = createFiberFromReturn(newChild, returnFiber.internalContextTag, expirationTime); + _created4.type = newChild.value; + _created4['return'] = returnFiber; + return _created4; + } + + case REACT_PORTAL_TYPE: + { + var _created5 = createFiberFromPortal(newChild, returnFiber.internalContextTag, expirationTime); + _created5['return'] = returnFiber; + return _created5; + } + } + + if (isArray$1(newChild) || getIteratorFn(newChild)) { + var _created6 = createFiberFromFragment(newChild, returnFiber.internalContextTag, expirationTime, null); + _created6['return'] = returnFiber; + return _created6; + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === 'function') { + warnOnFunctionType(); + } + } + + return null; + } + + function updateSlot(returnFiber, oldFiber, newChild, expirationTime) { + // Update the fiber if the keys match, otherwise return null. + + var key = oldFiber !== null ? oldFiber.key : null; + + if (typeof newChild === 'string' || typeof newChild === 'number') { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + if (key !== null) { + return null; + } + return updateTextNode(returnFiber, oldFiber, '' + newChild, expirationTime); + } + + if (typeof newChild === 'object' && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + { + if (newChild.key === key) { + if (newChild.type === REACT_FRAGMENT_TYPE) { + return updateFragment(returnFiber, oldFiber, newChild.props.children, expirationTime, key); + } + return updateElement(returnFiber, oldFiber, newChild, expirationTime); + } else { + return null; + } + } + + case REACT_CALL_TYPE: + { + if (newChild.key === key) { + return updateCall(returnFiber, oldFiber, newChild, expirationTime); + } else { + return null; + } + } + + case REACT_RETURN_TYPE: + { + // Returns don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a + // yield. + if (key === null) { + return updateReturn(returnFiber, oldFiber, newChild, expirationTime); + } else { + return null; + } + } + + case REACT_PORTAL_TYPE: + { + if (newChild.key === key) { + return updatePortal(returnFiber, oldFiber, newChild, expirationTime); + } else { + return null; + } + } + } + + if (isArray$1(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; + } + + return updateFragment(returnFiber, oldFiber, newChild, expirationTime, null); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === 'function') { + warnOnFunctionType(); + } + } + + return null; + } + + function updateFromMap(existingChildren, returnFiber, newIdx, newChild, expirationTime) { + if (typeof newChild === 'string' || typeof newChild === 'number') { + // Text nodes don't have keys, so we neither have to check the old nor + // new node for the key. If both are text nodes, they match. + var matchedFiber = existingChildren.get(newIdx) || null; + return updateTextNode(returnFiber, matchedFiber, '' + newChild, expirationTime); + } + + if (typeof newChild === 'object' && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + { + var _matchedFiber = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null; + if (newChild.type === REACT_FRAGMENT_TYPE) { + return updateFragment(returnFiber, _matchedFiber, newChild.props.children, expirationTime, newChild.key); + } + return updateElement(returnFiber, _matchedFiber, newChild, expirationTime); + } + + case REACT_CALL_TYPE: + { + var _matchedFiber2 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null; + return updateCall(returnFiber, _matchedFiber2, newChild, expirationTime); + } + + case REACT_RETURN_TYPE: + { + // Returns don't have keys, so we neither have to check the old nor + // new node for the key. If both are returns, they match. + var _matchedFiber3 = existingChildren.get(newIdx) || null; + return updateReturn(returnFiber, _matchedFiber3, newChild, expirationTime); + } + + case REACT_PORTAL_TYPE: + { + var _matchedFiber4 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null; + return updatePortal(returnFiber, _matchedFiber4, newChild, expirationTime); + } + } + + if (isArray$1(newChild) || getIteratorFn(newChild)) { + var _matchedFiber5 = existingChildren.get(newIdx) || null; + return updateFragment(returnFiber, _matchedFiber5, newChild, expirationTime, null); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === 'function') { + warnOnFunctionType(); + } + } + + return null; + } + + /** + * Warns if there is a duplicate or missing key + */ + function warnOnInvalidKey(child, knownKeys) { + { + if (typeof child !== 'object' || child === null) { + return knownKeys; + } + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_CALL_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child); + var key = child.key; + if (typeof key !== 'string') { + break; + } + if (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } + if (!knownKeys.has(key)) { + knownKeys.add(key); + break; + } + warning_1(false, 'Encountered two children with the same key, `%s`. ' + 'Keys should be unique so that components maintain their identity ' + 'across updates. Non-unique keys may cause children to be ' + 'duplicated and/or omitted — the behavior is unsupported and ' + 'could change in a future version.%s', key, getCurrentFiberStackAddendum$1()); + break; + default: + break; + } + } + return knownKeys; + } + + function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, expirationTime) { + // This algorithm can't optimize by searching from boths ends since we + // don't have backpointers on fibers. I'm trying to see how far we can get + // with that model. If it ends up not being worth the tradeoffs, we can + // add it later. + + // Even with a two ended optimization, we'd want to optimize for the case + // where there are few changes and brute force the comparison instead of + // going for the Map. It'd like to explore hitting that path first in + // forward-only mode and only go for the Map once we notice that we need + // lots of look ahead. This doesn't handle reversal as well as two ended + // search but that's unusual. Besides, for the two ended optimization to + // work on Iterables, we'd need to copy the whole set. + + // In this first iteration, we'll just live with hitting the bad case + // (adding everything to a Map) in for every insert/move. + + // If you change this code, also update reconcileChildrenIterator() which + // uses the same algorithm. + + { + // First, validate keys. + var knownKeys = null; + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys); + } + } + + var resultingFirstChild = null; + var previousNewFiber = null; + + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } + var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], expirationTime); + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } + break; + } + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; + } + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber = createChild(returnFiber, newChildren[newIdx], expirationTime); + if (!_newFiber) { + continue; + } + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } + previousNewFiber = _newFiber; + } + return resultingFirstChild; + } + + // Add all children to a key map for quick lookups. + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); + + // Keep scanning and use the map to restore deleted items as moves. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], expirationTime); + if (_newFiber2) { + if (shouldTrackSideEffects) { + if (_newFiber2.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren['delete'](_newFiber2.key === null ? newIdx : _newFiber2.key); + } + } + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } + previousNewFiber = _newFiber2; + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; + } + + function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, expirationTime) { + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + + var iteratorFn = getIteratorFn(newChildrenIterable); + !(typeof iteratorFn === 'function') ? invariant_1(false, 'An object is not an iterable. This error is likely caused by a bug in React. Please file an issue.') : void 0; + + { + // Warn about using Maps as children + if (typeof newChildrenIterable.entries === 'function') { + var possibleMap = newChildrenIterable; + if (possibleMap.entries === iteratorFn) { + warning_1(didWarnAboutMaps, 'Using Maps as children is unsupported and will likely yield ' + 'unexpected results. Convert it to a sequence/iterable of keyed ' + 'ReactElements instead.%s', getCurrentFiberStackAddendum$1()); + didWarnAboutMaps = true; + } + } + + // First, validate keys. + // We'll get a different iterator later for the main pass. + var _newChildren = iteratorFn.call(newChildrenIterable); + if (_newChildren) { + var knownKeys = null; + var _step = _newChildren.next(); + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys); + } + } + } + + var newChildren = iteratorFn.call(newChildrenIterable); + !(newChildren != null) ? invariant_1(false, 'An iterable object provided no iterator.') : void 0; + + var resultingFirstChild = null; + var previousNewFiber = null; + + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + + var step = newChildren.next(); + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } + var newFiber = updateSlot(returnFiber, oldFiber, step.value, expirationTime); + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (!oldFiber) { + oldFiber = nextOldFiber; + } + break; + } + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; + } + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber3 = createChild(returnFiber, step.value, expirationTime); + if (_newFiber3 === null) { + continue; + } + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } + previousNewFiber = _newFiber3; + } + return resultingFirstChild; + } + + // Add all children to a key map for quick lookups. + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); + + // Keep scanning and use the map to restore deleted items as moves. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, expirationTime); + if (_newFiber4 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber4.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren['delete'](_newFiber4.key === null ? newIdx : _newFiber4.key); + } + } + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + if (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; + } + previousNewFiber = _newFiber4; + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; + } + + function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, expirationTime) { + // There's no need to check for keys on text nodes since we don't have a + // way to define them. + if (currentFirstChild !== null && currentFirstChild.tag === HostText) { + // We already have an existing node so let's just update it and delete + // the rest. + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + var existing = useFiber(currentFirstChild, textContent, expirationTime); + existing['return'] = returnFiber; + return existing; + } + // The existing first child is not a text node so we need to create one + // and delete the existing ones. + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime); + created['return'] = returnFiber; + return created; + } + + function reconcileSingleElement(returnFiber, currentFirstChild, element, expirationTime) { + var key = element.key; + var child = currentFirstChild; + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.type === element.type) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, element.type === REACT_FRAGMENT_TYPE ? element.props.children : element.props, expirationTime); + existing.ref = coerceRef(child, element); + existing['return'] = returnFiber; + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; + } + } else { + deleteChild(returnFiber, child); + } + child = child.sibling; + } + + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment(element.props.children, returnFiber.internalContextTag, expirationTime, element.key); + created['return'] = returnFiber; + return created; + } else { + var _created7 = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime); + _created7.ref = coerceRef(currentFirstChild, element); + _created7['return'] = returnFiber; + return _created7; + } + } + + function reconcileSingleCall(returnFiber, currentFirstChild, call, expirationTime) { + var key = call.key; + var child = currentFirstChild; + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if (child.tag === CallComponent) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, call, expirationTime); + existing['return'] = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; + } + } else { + deleteChild(returnFiber, child); + } + child = child.sibling; + } + + var created = createFiberFromCall(call, returnFiber.internalContextTag, expirationTime); + created['return'] = returnFiber; + return created; + } + + function reconcileSingleReturn(returnFiber, currentFirstChild, returnNode, expirationTime) { + // There's no need to check for keys on yields since they're stateless. + var child = currentFirstChild; + if (child !== null) { + if (child.tag === ReturnComponent) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, null, expirationTime); + existing.type = returnNode.value; + existing['return'] = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + } + } + + var created = createFiberFromReturn(returnNode, returnFiber.internalContextTag, expirationTime); + created.type = returnNode.value; + created['return'] = returnFiber; + return created; + } + + function reconcileSinglePortal(returnFiber, currentFirstChild, portal, expirationTime) { + var key = portal.key; + var child = currentFirstChild; + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, portal.children || [], expirationTime); + existing['return'] = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; + } + } else { + deleteChild(returnFiber, child); + } + child = child.sibling; + } + + var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime); + created['return'] = returnFiber; + return created; + } + + // This API will tag the children with the side-effect of the reconciliation + // itself. They will be added to the side-effect list as we pass through the + // children and the parent. + function reconcileChildFibers(returnFiber, currentFirstChild, newChild, expirationTime) { + // This function is not recursive. + // If the top level item is an array, we treat it as a set of children, + // not as a fragment. Nested arrays on the other hand will be treated as + // fragment nodes. Recursion happens at the normal flow. + + // Handle top level unkeyed fragments as if they were arrays. + // This leads to an ambiguity between <>{[...]} and <>.... + // We treat the ambiguous cases above the same. + if (typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && newChild.key === null) { + newChild = newChild.props.children; + } + + // Handle object types + var isObject = typeof newChild === 'object' && newChild !== null; + + if (isObject) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, expirationTime)); + + case REACT_CALL_TYPE: + return placeSingleChild(reconcileSingleCall(returnFiber, currentFirstChild, newChild, expirationTime)); + case REACT_RETURN_TYPE: + return placeSingleChild(reconcileSingleReturn(returnFiber, currentFirstChild, newChild, expirationTime)); + case REACT_PORTAL_TYPE: + return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, expirationTime)); + } + } + + if (typeof newChild === 'string' || typeof newChild === 'number') { + return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, expirationTime)); + } + + if (isArray$1(newChild)) { + return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, expirationTime); + } + + if (getIteratorFn(newChild)) { + return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, expirationTime); + } + + if (isObject) { + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === 'function') { + warnOnFunctionType(); + } + } + if (typeof newChild === 'undefined') { + // If the new child is undefined, and the return fiber is a composite + // component, throw an error. If Fiber return types are disabled, + // we already threw above. + switch (returnFiber.tag) { + case ClassComponent: + { + { + var instance = returnFiber.stateNode; + if (instance.render._isMockFunction) { + // We allow auto-mocks to proceed as if they're returning null. + break; + } + } + } + // Intentionally fall through to the next case, which handles both + // functions and classes + // eslint-disable-next-lined no-fallthrough + case FunctionalComponent: + { + var Component = returnFiber.type; + invariant_1(false, '%s(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.', Component.displayName || Component.name || 'Component'); + } + } + } + + // Remaining cases are all treated as empty. + return deleteRemainingChildren(returnFiber, currentFirstChild); + } + + return reconcileChildFibers; +} + +var reconcileChildFibers = ChildReconciler(true); +var mountChildFibers = ChildReconciler(false); + +function cloneChildFibers(current, workInProgress) { + !(current === null || workInProgress.child === current.child) ? invariant_1(false, 'Resuming work not yet implemented.') : void 0; + + if (workInProgress.child === null) { + return; + } + + var currentChild = workInProgress.child; + var newChild = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime); + workInProgress.child = newChild; + + newChild['return'] = workInProgress; + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime); + newChild['return'] = workInProgress; + } + newChild.sibling = null; +} + +{ + var warnedAboutStatelessRefs = {}; +} + +var ReactFiberBeginWork = function (config, hostContext, hydrationContext, scheduleWork, computeExpirationForFiber) { + var shouldSetTextContent = config.shouldSetTextContent, + useSyncScheduling = config.useSyncScheduling, + shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree; + var pushHostContext = hostContext.pushHostContext, + pushHostContainer = hostContext.pushHostContainer; + var enterHydrationState = hydrationContext.enterHydrationState, + resetHydrationState = hydrationContext.resetHydrationState, +